68k cores: fix bcd instructions
[picodrive.git] / cpu / musashi / m68k_in.c
index bcc5612..d1756a5 100644 (file)
@@ -8,10 +8,10 @@ must fix:
 /* ======================================================================== */\r
 /*\r
  *                                  MUSASHI\r
- *                                Version 3.3\r
+ *                                Version 3.31\r
  *\r
  * A portable Motorola M680x0 processor emulation engine.\r
- * Copyright 1998-2001 Karl Stenerud.  All rights reserved.\r
+ * Copyright 1998-2007 Karl Stenerud.  All rights reserved.\r
  *\r
  * This code may be freely used for non-commercial purposes as long as this\r
  * copyright notice remains unaltered in the source code and any binary files\r
@@ -259,6 +259,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 M68KMAKE_OPCODE_HANDLER_HEADER\r
 \r
 #include "m68kcpu.h"\r
+extern void m68040_fpu_op0(void);\r
+extern void m68040_fpu_op1(void);\r
 \r
 /* ======================================================================== */\r
 /* ========================= INSTRUCTION HANDLERS ========================= */\r
@@ -354,6 +356,8 @@ name    size  proc   ea   bit pattern       A+-DXWLdxI  0 1 2 4  000 010 020 040
 M68KMAKE_TABLE_START\r
 1010       0  .     .     1010............  ..........  U U U U   4   4   4   4\r
 1111       0  .     .     1111............  ..........  U U U U   4   4   4   4\r
+040fpu0   32  .     .     11110010........  ..........  . . . U   .   .   .   0\r
+040fpu1   32  .     .     11110011........  ..........  . . . U   .   .   .   0\r
 abcd       8  rr    .     1100...100000...  ..........  U U U U   6   6   4   4\r
 abcd       8  mm    ax7   1100111100001...  ..........  U U U U  18  18  16  16\r
 abcd       8  mm    ay7   1100...100001111  ..........  U U U U  18  18  16  16\r
@@ -492,9 +496,9 @@ chk2cmp2  32  .     pcdi  0000010011111010  ..........  . . U U   .   .  23  23
 chk2cmp2  32  .     pcix  0000010011111011  ..........  . . U U   .   .  23  23\r
 chk2cmp2  32  .     .     0000010011......  A..DXWL...  . . U U   .   .  18  18\r
 clr        8  .     d     0100001000000...  ..........  U U U U   4   4   2   2\r
-clr        8  .     .     0100001000......  A+-DXWL...  U U U U   6   4   4   4  notaz hack: changed 000 cycles 8 -> 6 like in starscream for Fatal Rewind\r
+clr        8  .     .     0100001000......  A+-DXWL...  U U U U   8   4   4   4\r
 clr       16  .     d     0100001001000...  ..........  U U U U   4   4   2   2\r
-clr       16  .     .     0100001001......  A+-DXWL...  U U U U   6   4   4   4  ditto\r
+clr       16  .     .     0100001001......  A+-DXWL...  U U U U   8   4   4   4\r
 clr       32  .     d     0100001010000...  ..........  U U U U   6   6   2   2\r
 clr       32  .     .     0100001010......  A+-DXWL...  U U U U  12   6   4   4\r
 cmp        8  .     d     1011...000000...  ..........  U U U U   4   4   2   2\r
@@ -885,19 +889,44 @@ M68KMAKE_OP(1111, 0, ., .)
 }\r
 \r
 \r
+M68KMAKE_OP(040fpu0, 32, ., .)\r
+{\r
+       if(CPU_TYPE_IS_040_PLUS(CPU_TYPE))\r
+       {\r
+               m68040_fpu_op0();\r
+               return;\r
+       }\r
+       m68ki_exception_1111();\r
+}\r
+\r
+\r
+M68KMAKE_OP(040fpu1, 32, ., .)\r
+{\r
+       if(CPU_TYPE_IS_040_PLUS(CPU_TYPE))\r
+       {\r
+               m68040_fpu_op1();\r
+               return;\r
+       }\r
+       m68ki_exception_1111();\r
+}\r
+\r
+\r
+\r
 M68KMAKE_OP(abcd, 8, rr, .)\r
 {\r
        uint* r_dst = &DX;\r
        uint src = DY;\r
        uint dst = *r_dst;\r
        uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();\r
-\r
-       FLAG_V = ~res; /* Undefined V behavior */\r
+       uint corf = 0;\r
 \r
        if(res > 9)\r
-               res += 6;\r
+               corf = 6;\r
        res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);\r
-       FLAG_X = FLAG_C = (res > 0x99) << 8;\r
+       FLAG_V = ~res; /* Undefined V behavior */\r
+\r
+       res += corf;\r
+       FLAG_X = FLAG_C = (res > 0x9f) << 8;\r
        if(FLAG_C)\r
                res -= 0xa0;\r
 \r
@@ -917,13 +946,15 @@ M68KMAKE_OP(abcd, 8, mm, ax7)
        uint ea  = EA_A7_PD_8();\r
        uint dst = m68ki_read_8(ea);\r
        uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();\r
-\r
-       FLAG_V = ~res; /* Undefined V behavior */\r
+       uint corf = 0;\r
 \r
        if(res > 9)\r
-               res += 6;\r
+               corf = 6;\r
        res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);\r
-       FLAG_X = FLAG_C = (res > 0x99) << 8;\r
+       FLAG_V = ~res; /* Undefined V behavior */\r
+\r
+       res += corf;\r
+       FLAG_X = FLAG_C = (res > 0x9f) << 8;\r
        if(FLAG_C)\r
                res -= 0xa0;\r
 \r
@@ -943,13 +974,15 @@ M68KMAKE_OP(abcd, 8, mm, ay7)
        uint ea  = EA_AX_PD_8();\r
        uint dst = m68ki_read_8(ea);\r
        uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();\r
-\r
-       FLAG_V = ~res; /* Undefined V behavior */\r
+       uint corf = 0;\r
 \r
        if(res > 9)\r
-               res += 6;\r
+               corf = 6;\r
        res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);\r
-       FLAG_X = FLAG_C = (res > 0x99) << 8;\r
+       FLAG_V = ~res; /* Undefined V behavior */\r
+\r
+       res += corf;\r
+       FLAG_X = FLAG_C = (res > 0x9f) << 8;\r
        if(FLAG_C)\r
                res -= 0xa0;\r
 \r
@@ -969,13 +1002,15 @@ M68KMAKE_OP(abcd, 8, mm, axy7)
        uint ea  = EA_A7_PD_8();\r
        uint dst = m68ki_read_8(ea);\r
        uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();\r
-\r
-       FLAG_V = ~res; /* Undefined V behavior */\r
+       uint corf = 0;\r
 \r
        if(res > 9)\r
-               res += 6;\r
+               corf = 6;\r
        res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);\r
-       FLAG_X = FLAG_C = (res > 0x99) << 8;\r
+       FLAG_V = ~res; /* Undefined V behavior */\r
+\r
+       res += corf;\r
+       FLAG_X = FLAG_C = (res > 0x9f) << 8;\r
        if(FLAG_C)\r
                res -= 0xa0;\r
 \r
@@ -995,13 +1030,15 @@ M68KMAKE_OP(abcd, 8, mm, .)
        uint ea  = EA_AX_PD_8();\r
        uint dst = m68ki_read_8(ea);\r
        uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();\r
-\r
-       FLAG_V = ~res; /* Undefined V behavior */\r
+       uint corf = 0;\r
 \r
        if(res > 9)\r
-               res += 6;\r
+               corf = 6;\r
        res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);\r
-       FLAG_X = FLAG_C = (res > 0x99) << 8;\r
+       FLAG_V = ~res; /* Undefined V behavior */\r
+\r
+       res += corf;\r
+       FLAG_X = FLAG_C = (res > 0x9f) << 8;\r
        if(FLAG_C)\r
                res -= 0xa0;\r
 \r
@@ -1210,8 +1247,9 @@ M68KMAKE_OP(adda, 16, ., a)
 M68KMAKE_OP(adda, 16, ., .)\r
 {\r
        uint* r_dst = &AX;\r
+       uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16);\r
 \r
-       *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(M68KMAKE_GET_OPER_AY_16));\r
+       *r_dst = MASK_OUT_ABOVE_32(*r_dst + src);\r
 }\r
 \r
 \r
@@ -1234,8 +1272,9 @@ M68KMAKE_OP(adda, 32, ., a)
 M68KMAKE_OP(adda, 32, ., .)\r
 {\r
        uint* r_dst = &AX;\r
+       uint src = M68KMAKE_GET_OPER_AY_32; // notaz\r
 \r
-       *r_dst = MASK_OUT_ABOVE_32(*r_dst + M68KMAKE_GET_OPER_AY_32);\r
+       *r_dst = MASK_OUT_ABOVE_32(*r_dst + src);\r
 }\r
 \r
 \r
@@ -3100,8 +3139,8 @@ M68KMAKE_OP(bra, 8, ., .)
 {\r
        m68ki_trace_t0();                                  /* auto-disable (see m68kcpu.h) */\r
        m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR));\r
-//     if(REG_PC == REG_PPC)\r
-//             USE_ALL_CYCLES();\r
+       if(REG_PC == REG_PPC)\r
+               USE_ALL_CYCLES();\r
 }\r
 \r
 \r
@@ -3111,8 +3150,8 @@ M68KMAKE_OP(bra, 16, ., .)
        REG_PC -= 2;\r
        m68ki_trace_t0();                          /* auto-disable (see m68kcpu.h) */\r
        m68ki_branch_16(offset);\r
-//     if(REG_PC == REG_PPC)\r
-//             USE_ALL_CYCLES();\r
+       if(REG_PC == REG_PPC)\r
+               USE_ALL_CYCLES();\r
 }\r
 \r
 \r
@@ -3132,8 +3171,8 @@ M68KMAKE_OP(bra, 32, ., .)
        {\r
                m68ki_trace_t0();                                  /* auto-disable (see m68kcpu.h) */\r
                m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR));\r
-//             if(REG_PC == REG_PPC)\r
-//                     USE_ALL_CYCLES();\r
+               if(REG_PC == REG_PPC)\r
+                       USE_ALL_CYCLES();\r
        }\r
 }\r
 \r
@@ -5258,7 +5297,7 @@ M68KMAKE_OP(jsr, 32, ., .)
 {\r
        uint ea = M68KMAKE_GET_EA_AY_32;\r
        m68ki_trace_t0();                                  /* auto-disable (see m68kcpu.h) */\r
-       m68ki_push_32(MAKE_INT_24(REG_PC)); // notaz: Cyclone can't handle 32bit PC and I neet to debug it\r
+       m68ki_push_32(REG_PC);\r
        m68ki_jump(ea);\r
 }\r
 \r
@@ -6426,7 +6465,8 @@ M68KMAKE_OP(move, 32, pd, d)
        uint res = DY;\r
        uint ea = EA_AX_PD_32();\r
 \r
-       m68ki_write_32(ea, res);\r
+       m68ki_write_16(ea+2, res & 0xFFFF );\r
+       m68ki_write_16(ea, (res >> 16) & 0xFFFF );\r
 \r
        FLAG_N = NFLAG_32(res);\r
        FLAG_Z = res;\r
@@ -6440,7 +6480,8 @@ M68KMAKE_OP(move, 32, pd, a)
        uint res = AY;\r
        uint ea = EA_AX_PD_32();\r
 \r
-       m68ki_write_32(ea, res);\r
+       m68ki_write_16(ea+2, res & 0xFFFF );\r
+       m68ki_write_16(ea, (res >> 16) & 0xFFFF );\r
 \r
        FLAG_N = NFLAG_32(res);\r
        FLAG_Z = res;\r
@@ -6454,7 +6495,8 @@ M68KMAKE_OP(move, 32, pd, .)
        uint res = M68KMAKE_GET_OPER_AY_32;\r
        uint ea = EA_AX_PD_32();\r
 \r
-       m68ki_write_32(ea, res);\r
+       m68ki_write_16(ea+2, res & 0xFFFF );\r
+       m68ki_write_16(ea, (res >> 16) & 0xFFFF );\r
 \r
        FLAG_N = NFLAG_32(res);\r
        FLAG_Z = res;\r
@@ -6921,7 +6963,15 @@ M68KMAKE_OP(movec, 32, rc, .)
                        case 0x002:                        /* CACR */\r
                                if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE))\r
                                {\r
-                                       REG_CACR = REG_DA[(word2 >> 12) & 15];\r
+                                       if (CPU_TYPE_IS_040_PLUS(CPU_TYPE))\r
+                                       {\r
+                                               REG_CACR = REG_DA[(word2 >> 12) & 15];\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* non 68040 can only set the lower 4 bits (C,CE,F,E) */\r
+                                               REG_CACR = REG_DA[(word2 >> 12) & 15] & 0x0f;\r
+                                       }\r
                                        return;\r
                                }\r
                                m68ki_exception_illegal();\r
@@ -7093,7 +7143,12 @@ M68KMAKE_OP(movem, 32, re, pd)
                if(register_list & (1 << i))\r
                {\r
                        ea -= 4;\r
-                       m68ki_write_32(ea, REG_DA[15-i]);\r
+#if 0\r
+                       m68ki_write_32(ea, REG_DA[15-i] ); // notaz Cyclone hack\r
+#else\r
+                       m68ki_write_16(ea+2, REG_DA[15-i] & 0xFFFF );\r
+                       m68ki_write_16(ea, (REG_DA[15-i] >> 16) & 0xFFFF );\r
+#endif\r
                        count++;\r
                }\r
        AY = ea;\r
@@ -7749,19 +7804,19 @@ M68KMAKE_OP(mull, 32, ., .)
 M68KMAKE_OP(nbcd, 8, ., d)\r
 {\r
        uint* r_dst = &DY;\r
-       uint dst = *r_dst;\r
-       uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());\r
+       uint dst = MASK_OUT_ABOVE_8(*r_dst);\r
+       uint res = -dst - XFLAG_AS_1();\r
 \r
-       if(res != 0x9a)\r
+       if(res != 0)\r
        {\r
-               FLAG_V = ~res; /* Undefined V behavior */\r
+               FLAG_V = res; /* Undefined V behavior */\r
 \r
-               if((res & 0x0f) == 0xa)\r
-                       res = (res & 0xf0) + 0x10;\r
+               if(((res|dst) & 0x0f) == 0)\r
+                       res = (res & 0xf0) + 6;\r
 \r
-               res = MASK_OUT_ABOVE_8(res);\r
+               res = MASK_OUT_ABOVE_8(res + 0x9a);\r
 \r
-               FLAG_V &= res; /* Undefined V behavior part II */\r
+               FLAG_V &= ~res; /* Undefined V behavior part II */\r
 \r
                *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;\r
 \r
@@ -7783,18 +7838,18 @@ M68KMAKE_OP(nbcd, 8, ., .)
 {\r
        uint ea = M68KMAKE_GET_EA_AY_8;\r
        uint dst = m68ki_read_8(ea);\r
-       uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());\r
+       uint res = -dst - XFLAG_AS_1();\r
 \r
-       if(res != 0x9a)\r
+       if(res != 0)\r
        {\r
-               FLAG_V = ~res; /* Undefined V behavior */\r
+               FLAG_V = res; /* Undefined V behavior */\r
 \r
-               if((res & 0x0f) == 0xa)\r
-                       res = (res & 0xf0) + 0x10;\r
+               if(((res|dst) & 0x0f) == 0)\r
+                       res = (res & 0xf0) + 6;\r
 \r
-               res = MASK_OUT_ABOVE_8(res);\r
+               res = MASK_OUT_ABOVE_8(res + 0x9a);\r
 \r
-               FLAG_V &= res; /* Undefined V behavior part II */\r
+               FLAG_V &= ~res; /* Undefined V behavior part II */\r
 \r
                m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));\r
 \r
@@ -8700,8 +8755,7 @@ M68KMAKE_OP(rol, 32, r, .)
 \r
                *r_dst = res;\r
 \r
-               FLAG_C = (src >> (32 - shift)) << 8;\r
-               if (shift == 0) FLAG_C = src << 8; // notaz\r
+               FLAG_C = (src >> ((32 - shift) & 0x1f)) << 8;\r
                FLAG_N = NFLAG_32(res);\r
                FLAG_Z = res;\r
                FLAG_V = VFLAG_CLEAR;\r
@@ -9315,26 +9369,26 @@ M68KMAKE_OP(sbcd, 8, rr, .)
        uint src = DY;\r
        uint dst = *r_dst;\r
        uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();\r
+       uint corf = 0;\r
 \r
-//  FLAG_V = ~res; /* Undefined V behavior */\r
-       FLAG_V = VFLAG_CLEAR;   /* Undefined in Motorola's M68000PM/AD rev.1 and safer to assume cleared. */\r
-\r
-       if(res > 9)\r
-               res -= 6;\r
+       if(res > 0xf)\r
+               corf = 6;\r
        res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);\r
-       if(res > 0x99)\r
+       FLAG_V = res; /* Undefined V behavior */\r
+       if(res > 0xff)\r
        {\r
                res += 0xa0;\r
                FLAG_X = FLAG_C = CFLAG_SET;\r
-               FLAG_N = NFLAG_SET;     /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */\r
        }\r
+       else if(res < corf)\r
+               FLAG_X = FLAG_C = CFLAG_SET;\r
        else\r
-               FLAG_N = FLAG_X = FLAG_C = 0;\r
+               FLAG_X = FLAG_C = 0;\r
 \r
-       res = MASK_OUT_ABOVE_8(res);\r
+       res = MASK_OUT_ABOVE_8(res - corf);\r
 \r
-//  FLAG_V &= res; /* Undefined V behavior part II */\r
-//  FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
+       FLAG_V &= ~res; /* Undefined V behavior part II */\r
+       FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
        FLAG_Z |= res;\r
 \r
        *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;\r
@@ -9347,26 +9401,26 @@ M68KMAKE_OP(sbcd, 8, mm, ax7)
        uint ea  = EA_A7_PD_8();\r
        uint dst = m68ki_read_8(ea);\r
        uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();\r
+       uint corf = 0;\r
 \r
-//  FLAG_V = ~res; /* Undefined V behavior */\r
-       FLAG_V = VFLAG_CLEAR;   /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */\r
-\r
-       if(res > 9)\r
-               res -= 6;\r
+       if(res > 0xf)\r
+               corf = 6;\r
        res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);\r
-       if(res > 0x99)\r
+       FLAG_V = res; /* Undefined V behavior */\r
+       if(res > 0xff)\r
        {\r
                res += 0xa0;\r
                FLAG_X = FLAG_C = CFLAG_SET;\r
-               FLAG_N = NFLAG_SET;     /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */\r
        }\r
+       else if(res < corf)\r
+               FLAG_X = FLAG_C = CFLAG_SET;\r
        else\r
-               FLAG_N = FLAG_X = FLAG_C = 0;\r
+               FLAG_X = FLAG_C = 0;\r
 \r
-       res = MASK_OUT_ABOVE_8(res);\r
+       res = MASK_OUT_ABOVE_8(res - corf);\r
 \r
-//  FLAG_V &= res; /* Undefined V behavior part II */\r
-//  FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
+       FLAG_V &= ~res; /* Undefined V behavior part II */\r
+       FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
        FLAG_Z |= res;\r
 \r
        m68ki_write_8(ea, res);\r
@@ -9379,26 +9433,26 @@ M68KMAKE_OP(sbcd, 8, mm, ay7)
        uint ea  = EA_AX_PD_8();\r
        uint dst = m68ki_read_8(ea);\r
        uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();\r
+       uint corf = 0;\r
 \r
-//  FLAG_V = ~res; /* Undefined V behavior */\r
-       FLAG_V = VFLAG_CLEAR;   /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */\r
-\r
-       if(res > 9)\r
-               res -= 6;\r
+       if(res > 0xf)\r
+               corf = 6;\r
        res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);\r
-       if(res > 0x99)\r
+       FLAG_V = res; /* Undefined V behavior */\r
+       if(res > 0xff)\r
        {\r
                res += 0xa0;\r
                FLAG_X = FLAG_C = CFLAG_SET;\r
-               FLAG_N = NFLAG_SET;     /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */\r
        }\r
+       else if(res < corf)\r
+               FLAG_X = FLAG_C = CFLAG_SET;\r
        else\r
-               FLAG_N = FLAG_X = FLAG_C = 0;\r
+               FLAG_X = FLAG_C = 0;\r
 \r
-       res = MASK_OUT_ABOVE_8(res);\r
+       res = MASK_OUT_ABOVE_8(res - corf);\r
 \r
-//  FLAG_V &= res; /* Undefined V behavior part II */\r
-//  FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
+       FLAG_V &= ~res; /* Undefined V behavior part II */\r
+       FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
        FLAG_Z |= res;\r
 \r
        m68ki_write_8(ea, res);\r
@@ -9411,26 +9465,26 @@ M68KMAKE_OP(sbcd, 8, mm, axy7)
        uint ea  = EA_A7_PD_8();\r
        uint dst = m68ki_read_8(ea);\r
        uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();\r
+       uint corf = 0;\r
 \r
-//  FLAG_V = ~res; /* Undefined V behavior */\r
-       FLAG_V = VFLAG_CLEAR;   /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */\r
-\r
-       if(res > 9)\r
-               res -= 6;\r
+       if(res > 0xf)\r
+               corf = 6;\r
        res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);\r
-       if(res > 0x99)\r
+       FLAG_V = res; /* Undefined V behavior */\r
+       if(res > 0xff)\r
        {\r
                res += 0xa0;\r
                FLAG_X = FLAG_C = CFLAG_SET;\r
-               FLAG_N = NFLAG_SET;     /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */\r
        }\r
+       else if(res < corf)\r
+               FLAG_X = FLAG_C = CFLAG_SET;\r
        else\r
-               FLAG_N = FLAG_X = FLAG_C = 0;\r
+               FLAG_X = FLAG_C = 0;\r
 \r
-       res = MASK_OUT_ABOVE_8(res);\r
+       res = MASK_OUT_ABOVE_8(res - corf);\r
 \r
-//  FLAG_V &= res; /* Undefined V behavior part II */\r
-//  FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
+       FLAG_V &= ~res; /* Undefined V behavior part II */\r
+       FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
        FLAG_Z |= res;\r
 \r
        m68ki_write_8(ea, res);\r
@@ -9443,26 +9497,26 @@ M68KMAKE_OP(sbcd, 8, mm, .)
        uint ea  = EA_AX_PD_8();\r
        uint dst = m68ki_read_8(ea);\r
        uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();\r
+       uint corf = 0;\r
 \r
-//  FLAG_V = ~res; /* Undefined V behavior */\r
-       FLAG_V = VFLAG_CLEAR;   /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */\r
-\r
-       if(res > 9)\r
-               res -= 6;\r
+       if(res > 0xf)\r
+               corf = 6;\r
        res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);\r
-       if(res > 0x99)\r
+       FLAG_V = res; /* Undefined V behavior */\r
+       if(res > 0xff)\r
        {\r
                res += 0xa0;\r
                FLAG_X = FLAG_C = CFLAG_SET;\r
-               FLAG_N = NFLAG_SET;     /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */\r
        }\r
+       else if(res < corf)\r
+               FLAG_X = FLAG_C = CFLAG_SET;\r
        else\r
-               FLAG_N = FLAG_X = FLAG_C = 0;\r
+               FLAG_X = FLAG_C = 0;\r
 \r
-       res = MASK_OUT_ABOVE_8(res);\r
+       res = MASK_OUT_ABOVE_8(res - corf);\r
 \r
-//  FLAG_V &= res; /* Undefined V behavior part II */\r
-//  FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
+       FLAG_V &= ~res; /* Undefined V behavior part II */\r
+       FLAG_N = NFLAG_8(res); /* Undefined N behavior */\r
        FLAG_Z |= res;\r
 \r
        m68ki_write_8(ea, res);\r
@@ -9721,8 +9775,9 @@ M68KMAKE_OP(suba, 16, ., a)
 M68KMAKE_OP(suba, 16, ., .)\r
 {\r
        uint* r_dst = &AX;\r
+       uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16);\r
 \r
-       *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(M68KMAKE_GET_OPER_AY_16));\r
+       *r_dst = MASK_OUT_ABOVE_32(*r_dst - src);\r
 }\r
 \r
 \r
@@ -9745,8 +9800,9 @@ M68KMAKE_OP(suba, 32, ., a)
 M68KMAKE_OP(suba, 32, ., .)\r
 {\r
        uint* r_dst = &AX;\r
+       uint src = M68KMAKE_GET_OPER_AY_32; // notaz\r
 \r
-       *r_dst = MASK_OUT_ABOVE_32(*r_dst - M68KMAKE_GET_OPER_AY_32);\r
+       *r_dst = MASK_OUT_ABOVE_32(*r_dst - src);\r
 }\r
 \r
 \r
@@ -10150,12 +10206,20 @@ M68KMAKE_OP(tas, 8, ., .)
 {\r
        uint ea = M68KMAKE_GET_EA_AY_8;\r
        uint dst = m68ki_read_8(ea);\r
+       uint allow_writeback;\r
 \r
        FLAG_Z = dst;\r
        FLAG_N = NFLAG_8(dst);\r
        FLAG_V = VFLAG_CLEAR;\r
        FLAG_C = CFLAG_CLEAR;\r
-//     m68ki_write_8(ea, dst | 0x80); // notaz: genesis, but only to mem\r
+\r
+       /* The Genesis/Megadrive games Gargoyles and Ex-Mutants need the TAS writeback\r
+       disabled in order to function properly.  Some Amiga software may also rely\r
+       on this, but only when accessing specific addresses so additional functionality\r
+       will be needed. */\r
+       allow_writeback = m68ki_tas_callback();\r
+\r
+       if (allow_writeback==1) m68ki_write_8(ea, dst | 0x80);\r
 }\r
 \r
 \r