summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author notaz <notasas@gmail.com>2017-09-18 10:33:15 +0300
committer Olivier Galibert <galibert@pobox.com>2017-09-18 09:33:15 +0200
commit1680634bcf715647e9c2931941b20d200c6fc17e (patch)
tree8d3c3efe0af2e329b84aca87a9e2ced42e3e919f
parent796b585f722b5d74d9c2f7db839baaa6a332a4b0 (diff)
m68k: fix abcd/sbcd/nbcd to pass 68k-bcd-verifier [notaz]
Flamewing has a test that claims to exhaustively test BCD instructions: https://github.com/flamewing/68k-bcd-verifier I've verified the test indeed passes on my Megadrive model1 (68000).
-rw-r--r--src/devices/cpu/m68000/m68k_in.cpp173
1 files changed, 89 insertions, 84 deletions
diff --git a/src/devices/cpu/m68000/m68k_in.cpp b/src/devices/cpu/m68000/m68k_in.cpp
index dd58233b747..6c56274a60a 100644
--- a/src/devices/cpu/m68000/m68k_in.cpp
+++ b/src/devices/cpu/m68000/m68k_in.cpp
@@ -929,13 +929,14 @@ M68KMAKE_OP(abcd, 8, rr, .)
uint32_t src = DY(mc68kcpu);
uint32_t dst = *r_dst;
uint32_t res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_1(mc68kcpu);
-
- (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ uint32_t corf = 0;
if(res > 9)
- res += 6;
+ corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
- (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x99) << 8;
+ (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ res += corf;
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x9f) << 8;
if((mc68kcpu)->c_flag)
res -= 0xa0;
@@ -955,13 +956,14 @@ M68KMAKE_OP(abcd, 8, mm, ax7)
uint32_t ea = EA_A7_PD_8(mc68kcpu);
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
uint32_t res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_1(mc68kcpu);
-
- (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ uint32_t corf = 0;
if(res > 9)
- res += 6;
+ corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
- (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x99) << 8;
+ (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ res += corf;
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x9f) << 8;
if((mc68kcpu)->c_flag)
res -= 0xa0;
@@ -981,13 +983,14 @@ M68KMAKE_OP(abcd, 8, mm, ay7)
uint32_t ea = EA_AX_PD_8(mc68kcpu);
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
uint32_t res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_1(mc68kcpu);
-
- (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ uint32_t corf = 0;
if(res > 9)
- res += 6;
+ corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
- (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x99) << 8;
+ (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ res += corf;
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x9f) << 8;
if((mc68kcpu)->c_flag)
res -= 0xa0;
@@ -1007,13 +1010,14 @@ M68KMAKE_OP(abcd, 8, mm, axy7)
uint32_t ea = EA_A7_PD_8(mc68kcpu);
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
uint32_t res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_1(mc68kcpu);
-
- (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ uint32_t corf = 0;
if(res > 9)
- res += 6;
+ corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
- (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x99) << 8;
+ (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ res += corf;
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x9f) << 8;
if((mc68kcpu)->c_flag)
res -= 0xa0;
@@ -1033,13 +1037,14 @@ M68KMAKE_OP(abcd, 8, mm, .)
uint32_t ea = EA_AX_PD_8(mc68kcpu);
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
uint32_t res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_1(mc68kcpu);
-
- (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ uint32_t corf = 0;
if(res > 9)
- res += 6;
+ corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
- (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x99) << 8;
+ (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ res += corf;
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = (res > 0x9f) << 8;
if((mc68kcpu)->c_flag)
res -= 0xa0;
@@ -7606,18 +7611,18 @@ M68KMAKE_OP(nbcd, 8, ., d)
{
uint32_t* r_dst = &DY(mc68kcpu);
uint32_t dst = *r_dst;
- uint32_t res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_1(mc68kcpu));
+ uint32_t res = -dst - XFLAG_1(mc68kcpu);
- if(res != 0x9a)
+ if(res != 0)
{
- (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ (mc68kcpu)->v_flag = res; /* Undefined V behavior */
- if((res & 0x0f) == 0xa)
- res = (res & 0xf0) + 0x10;
+ if(((res|dst) & 0x0f) == 0)
+ res = (res & 0xf0) | 6;
- res = MASK_OUT_ABOVE_8(res);
+ res = MASK_OUT_ABOVE_8(res + 0x9a);
- (mc68kcpu)->v_flag &= res; /* Undefined V behavior part II */
+ (mc68kcpu)->v_flag &= ~res; /* Undefined V behavior part II */
*r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
@@ -7639,18 +7644,18 @@ M68KMAKE_OP(nbcd, 8, ., .)
{
uint32_t ea = M68KMAKE_GET_EA_AY_8;
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
- uint32_t res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_1(mc68kcpu));
+ uint32_t res = -dst - XFLAG_1(mc68kcpu);
- if(res != 0x9a)
+ if(res != 0)
{
- (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
+ (mc68kcpu)->v_flag = res; /* Undefined V behavior */
- if((res & 0x0f) == 0xa)
- res = (res & 0xf0) + 0x10;
+ if(((res|dst) & 0x0f) == 0)
+ res = (res & 0xf0) | 6;
- res = MASK_OUT_ABOVE_8(res);
+ res = MASK_OUT_ABOVE_8(res + 0x9a);
- (mc68kcpu)->v_flag &= res; /* Undefined V behavior part II */
+ (mc68kcpu)->v_flag &= ~res; /* Undefined V behavior part II */
m68ki_write_8((mc68kcpu), ea, MASK_OUT_ABOVE_8(res));
@@ -9181,26 +9186,26 @@ M68KMAKE_OP(sbcd, 8, rr, .)
uint32_t src = DY(mc68kcpu);
uint32_t dst = *r_dst;
uint32_t res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_1(mc68kcpu);
+ uint32_t corf = 0;
-// (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
- (mc68kcpu)->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to assume cleared. */
-
- if(res > 9)
- res -= 6;
+ if(res > 0xf)
+ corf = 6;
res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
- if(res > 0x99)
+ (mc68kcpu)->v_flag = res; /* Undefined V behavior */
+ if(res > 0xff)
{
res += 0xa0;
(mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
- (mc68kcpu)->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
+ else if(res < corf)
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
else
(mc68kcpu)->n_flag = (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = 0;
- res = MASK_OUT_ABOVE_8(res);
+ res = MASK_OUT_ABOVE_8(res - corf);
-// (mc68kcpu)->v_flag &= res; /* Undefined V behavior part II */
-// (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ (mc68kcpu)->v_flag &= ~res; /* Undefined V behavior part II */
+ (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
(mc68kcpu)->not_z_flag |= res;
*r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
@@ -9213,26 +9218,26 @@ M68KMAKE_OP(sbcd, 8, mm, ax7)
uint32_t ea = EA_A7_PD_8(mc68kcpu);
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
uint32_t res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_1(mc68kcpu);
+ uint32_t corf = 0;
-// (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
- (mc68kcpu)->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */
-
- if(res > 9)
- res -= 6;
+ if(res > 0xf)
+ corf = 6;
res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
- if(res > 0x99)
+ (mc68kcpu)->v_flag = res; /* Undefined V behavior */
+ if(res > 0xff)
{
res += 0xa0;
(mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
- (mc68kcpu)->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
+ else if(res < corf)
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
else
(mc68kcpu)->n_flag = (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = 0;
- res = MASK_OUT_ABOVE_8(res);
+ res = MASK_OUT_ABOVE_8(res - corf);
-// (mc68kcpu)->v_flag &= res; /* Undefined V behavior part II */
-// (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ (mc68kcpu)->v_flag &= ~res; /* Undefined V behavior part II */
+ (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
(mc68kcpu)->not_z_flag |= res;
m68ki_write_8((mc68kcpu), ea, res);
@@ -9245,26 +9250,26 @@ M68KMAKE_OP(sbcd, 8, mm, ay7)
uint32_t ea = EA_AX_PD_8(mc68kcpu);
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
uint32_t res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_1(mc68kcpu);
+ uint32_t corf = 0;
-// (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
- (mc68kcpu)->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */
-
- if(res > 9)
- res -= 6;
+ if(res > 0xf)
+ corf = 6;
res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
- if(res > 0x99)
+ (mc68kcpu)->v_flag = res; /* Undefined V behavior */
+ if(res > 0xff)
{
res += 0xa0;
(mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
- (mc68kcpu)->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
+ else if(res < corf)
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
else
(mc68kcpu)->n_flag = (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = 0;
- res = MASK_OUT_ABOVE_8(res);
+ res = MASK_OUT_ABOVE_8(res - corf);
-// (mc68kcpu)->v_flag &= res; /* Undefined V behavior part II */
-// (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ (mc68kcpu)->v_flag &= ~res; /* Undefined V behavior part II */
+ (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
(mc68kcpu)->not_z_flag |= res;
m68ki_write_8((mc68kcpu), ea, res);
@@ -9277,26 +9282,26 @@ M68KMAKE_OP(sbcd, 8, mm, axy7)
uint32_t ea = EA_A7_PD_8(mc68kcpu);
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
uint32_t res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_1(mc68kcpu);
+ uint32_t corf = 0;
-// (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
- (mc68kcpu)->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */
-
- if(res > 9)
- res -= 6;
+ if(res > 0xf)
+ corf = 6;
res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
- if(res > 0x99)
+ (mc68kcpu)->v_flag = res; /* Undefined V behavior */
+ if(res > 0xff)
{
res += 0xa0;
(mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
- (mc68kcpu)->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
+ else if(res < corf)
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
else
(mc68kcpu)->n_flag = (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = 0;
- res = MASK_OUT_ABOVE_8(res);
+ res = MASK_OUT_ABOVE_8(res - corf);
-// (mc68kcpu)->v_flag &= res; /* Undefined V behavior part II */
-// (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ (mc68kcpu)->v_flag &= ~res; /* Undefined V behavior part II */
+ (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
(mc68kcpu)->not_z_flag |= res;
m68ki_write_8((mc68kcpu), ea, res);
@@ -9309,26 +9314,26 @@ M68KMAKE_OP(sbcd, 8, mm, .)
uint32_t ea = EA_AX_PD_8(mc68kcpu);
uint32_t dst = m68ki_read_8((mc68kcpu), ea);
uint32_t res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_1(mc68kcpu);
+ uint32_t corf = 0;
-// (mc68kcpu)->v_flag = ~res; /* Undefined V behavior */
- (mc68kcpu)->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */
-
- if(res > 9)
- res -= 6;
+ if(res > 0xf)
+ corf = 6;
res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
- if(res > 0x99)
+ (mc68kcpu)->v_flag = res; /* Undefined V behavior */
+ if(res > 0xff)
{
res += 0xa0;
(mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
- (mc68kcpu)->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
+ else if(res < corf)
+ (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = CFLAG_SET;
else
(mc68kcpu)->n_flag = (mc68kcpu)->x_flag = (mc68kcpu)->c_flag = 0;
- res = MASK_OUT_ABOVE_8(res);
+ res = MASK_OUT_ABOVE_8(res - corf);
-// (mc68kcpu)->v_flag &= res; /* Undefined V behavior part II */
-// (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ (mc68kcpu)->v_flag &= ~res; /* Undefined V behavior part II */
+ (mc68kcpu)->n_flag = NFLAG_8(res); /* Undefined N behavior */
(mc68kcpu)->not_z_flag |= res;
m68ki_write_8((mc68kcpu), ea, res);