summaryrefslogtreecommitdiff
path: root/emulators/tme/patches/patch-aq
diff options
context:
space:
mode:
Diffstat (limited to 'emulators/tme/patches/patch-aq')
-rw-r--r--emulators/tme/patches/patch-aq169
1 files changed, 169 insertions, 0 deletions
diff --git a/emulators/tme/patches/patch-aq b/emulators/tme/patches/patch-aq
new file mode 100644
index 00000000000..f180e4d6fb3
--- /dev/null
+++ b/emulators/tme/patches/patch-aq
@@ -0,0 +1,169 @@
+$NetBSD: patch-aq,v 1.1 2007/03/17 13:44:19 tsutsui Exp $
+
+--- ic/m68k/m68k-insns.c.orig 2005-03-23 20:53:02.000000000 +0900
++++ ic/m68k/m68k-insns.c 2007-03-14 20:28:31.000000000 +0900
+@@ -485,9 +485,8 @@
+ TME_M68K_INSN(tme_m68k_cmp2_chk2)
+ {
+ tme_uint32_t ireg;
+- unsigned int size_bytes, size_name, size_ireg;
++ unsigned int size_bytes, size_ireg;
+ tme_uint32_t uvalue, ulower, uupper;
+- tme_int32_t value, lower, upper;
+
+ TME_M68K_INSN_CANFAULT;
+
+@@ -495,60 +494,109 @@
+ ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);
+ size_bytes = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 2);
+ size_ireg = 2 - size_bytes;
+- size_name = TME_M68K_SIZE_8 + size_bytes;
++
++ /* size comes back from cp2 instruction as:
++ 0 : byte
++ 1 : word
++ 2 : long
++ we convert to
++ 0 : byte
++ 1 : word
++ 4 : long
++ */
+ size_bytes = 1 << size_bytes;
+
+ /* read in the two bounds: */
+- (*_tme_m68k_read_mem[size_name])(ic, TME_M68K_IREG_MEMX32 << size_ireg);
++ (*_tme_m68k_read_mem[size_bytes])(ic, TME_M68K_IREG_MEMX32 << size_ireg);
+ if (!TME_M68K_SEQUENCE_RESTARTING) {
+ ic->_tme_m68k_ea_address += size_bytes;
+ }
+- (*_tme_m68k_read_mem[size_name])(ic, TME_M68K_IREG_MEMY32 << size_ireg);
++ (*_tme_m68k_read_mem[size_bytes])(ic, TME_M68K_IREG_MEMY32 << size_ireg);
+
+- /* if we have an address register, sign-extend the bounds to 32
+- bits: */
++ /* if value is an address register, sign-extend the bounds to 32 bits,
++ then set size of bounds and value to 32 bits (so we check entire
++ longword value)
++ */
+ if (ireg >= TME_M68K_IREG_A0) {
+- if (size_name == TME_M68K_SIZE_8) {
++ if (size_bytes == TME_M68K_SIZE_8) {
+ ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = TME_EXT_S8_S32(ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMX8));
+ ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32) = TME_EXT_S8_S32(ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMY8));
+ }
+- else if (size_name == TME_M68K_SIZE_16) {
++ else if (size_bytes == TME_M68K_SIZE_16) {
+ ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = TME_EXT_S16_S32(ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMX16));
+ ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32) = TME_EXT_S16_S32(ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMY16));
+ }
+- size_bytes = sizeof(tme_uint32_t);
+- size_name = TME_M68K_SIZE_32;
++ size_bytes = TME_M68K_SIZE_32;
+ }
+
+- /* get the values to check: */
+- switch (size_name) {
++ /* get the bounds and value */
++ switch (size_bytes) {
+ case TME_M68K_SIZE_8:
+- uvalue = ic->tme_m68k_ireg_uint8(ireg);
+ ulower = ic->tme_m68k_ireg_uint8(TME_M68K_IREG_MEMX8);
+ uupper = ic->tme_m68k_ireg_uint8(TME_M68K_IREG_MEMY8);
+- value = ic->tme_m68k_ireg_int8(ireg);
+- lower = ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMX8);
+- upper = ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMY8);
++
++ /* if value is a data register, read the entire register, extract
++ the appropriate number of bytes, and sign extend to our own
++ longword size for comparison.
++ if value is an address register, just use the entire register as is
++ */
++ if (ireg < TME_M68K_IREG_A0)
++ uvalue = (tme_uint32_t)TME_EXT_S8_S32
++ ((tme_int32_t)(ic->tme_m68k_ireg_uint32(ireg) & 0xFF));
++ else
++ uvalue = ic->tme_m68k_ireg_uint32(ireg);
++
+ break;
+ case TME_M68K_SIZE_16:
+- uvalue = ic->tme_m68k_ireg_uint16(ireg);
+ ulower = ic->tme_m68k_ireg_uint16(TME_M68K_IREG_MEMX16);
+ uupper = ic->tme_m68k_ireg_uint16(TME_M68K_IREG_MEMY16);
+- value = ic->tme_m68k_ireg_int16(ireg);
+- lower = ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMX16);
+- upper = ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMY16);
++
++ /* if value is a data register, read the entire register, extract
++ the appropriate number of bytes, and sign extend to our own
++ longword size for comparison.
++ if value is an address register, just use the entire register as is
++ */
++ if (ireg < TME_M68K_IREG_A0)
++ uvalue = (tme_uint32_t)TME_EXT_S16_S32
++ ((tme_int32_t)(ic->tme_m68k_ireg_uint32(ireg) & 0xFFFF));
++ else
++ uvalue = ic->tme_m68k_ireg_uint32(ireg);
++
+ break;
+ case TME_M68K_SIZE_32:
+- uvalue = ic->tme_m68k_ireg_uint32(ireg);
+ ulower = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_MEMX32);
+ uupper = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_MEMY32);
+- value = ic->tme_m68k_ireg_int32(ireg);
+- lower = ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32);
+- upper = ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32);
++
++ uvalue = ic->tme_m68k_ireg_uint32(ireg);
++
+ break;
+ default: abort();
+ }
+
++ /* cmp2 / chk2 can be used for unsigned, or signed.
++ for either type, the lower bound "should be" <= upper bound
++ (per m68000 family programmer's reference manual)
++
++ cmp2 instruction doesn't know if signed or unsigned
++ if bound 250 250 then bound is the one value, check unsigned or signed
++
++ if bound 253 255 could be unsigned 253 255
++ or signed -3 -1
++ either way, ok to check.
++
++ if bound 255 5 then only makes sense to check signed -1 5
++
++ if bound 255 253 then doesn't make sense either way!
++ its either 255 253 unsigned or -1 -3 signed.
++
++ reverse engineering the code, by running many test cases shows that
++ the motorola 68020 microcode does the following.
++
++ Always check unsigned.
++ if low <= high, then out of bounds if either < low or > high.
++ if high > low, then out of bounds if BOTH < low AND > high.
++ */
++
+ /* do the comparison. if the value is out-of-bounds and this is
+ a chk2 instruction, trap: */
+ ic->tme_m68k_ireg_ccr = (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
+@@ -556,13 +604,14 @@
+ || uvalue == uupper) {
+ ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
+ }
+- else if ((ulower > uupper)
+- /* signed comparison: */
+- ? (value < lower || value > upper)
+- /* unsigned comparison: */
+- : (uvalue < ulower || uvalue > uupper)) {
++ else if (((ulower <= uupper) && (uvalue < ulower || uvalue > uupper)) ||
++ ((ulower > uupper) && (uvalue < ulower && uvalue > uupper))) {
+ ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_C;
+- if (TME_M68K_INSN_OPCODE & TME_BIT(11)) {
++
++ /* if chk2 instruction,
++ also cause a CHK instruction exception (vector number 6)
++ */
++ if (TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 11, 1)) {
+ ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
+ ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
+ TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));