68k cores: fix bcd instructions
[picodrive.git] / cpu / musashi / m68k_in.c
index 5c9cc06..d1756a5 100644 (file)
@@ -918,13 +918,15 @@ M68KMAKE_OP(abcd, 8, rr, .)
        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
@@ -944,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
@@ -970,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
@@ -996,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
@@ -1022,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
@@ -7794,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
@@ -7828,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
@@ -9359,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
@@ -9391,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
@@ -9423,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
@@ -9455,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
@@ -9487,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