[Core/CPU] fixed 68k undocumented behaviors for ABCD/SBCD/NBCD instructions (thanks to flamewing for his test ROM)

This commit is contained in:
EkeEke 2017-03-30 15:02:15 +02:00
parent a62c6f9ffe
commit 5a74df31ee
6 changed files with 192 additions and 163 deletions

View File

@ -78,6 +78,7 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
[Core/CPU]
---------------
* improved 68k auto-vectored interrupts acknowledge cycle timing accuracy (Bubsy background color corruption during cutscenes)
* fixed 68k undocumented behaviors for ABCD/SBCD/NBCD instructions (thanks to flamewing for his test ROM)
* fixed Z80 interrupt duration (Bomb on Basic City music running too fast)
* fixed Z80 SP register initialization on power-on for Master System & Game Gear
(Ace of Aces, Shadow Dancer, Ecco the Dolphin, Evander Holyfield Real Deal Boxing)

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -31,6 +31,8 @@
- added proper cycle use on reset
- added cycle accurate timings for MUL/DIV instructions (thanks to Jorge Cwik !)
- fixed undocumented flags for DIV instructions (Blood Shot)
- fixed undocumented behaviors for ABCD/SBCD/NBCD instructions (thanks to flamewing for his test ROM)
- improved auto-vectored interrupts acknowledge cycle timing accuracy
- added MAIN-CPU & SUB-CPU support for Mega CD emulation
*/

View File

@ -143,13 +143,15 @@ static void m68k_op_abcd_8_rr(void)
uint src = DY;
uint dst = *r_dst;
uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();
FLAG_V = ~res; /* Undefined V behavior */
uint corf = 0;
if(res > 9)
res += 6;
corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
FLAG_X = FLAG_C = (res > 0x99) << 8;
FLAG_V = ~res; /* Undefined V behavior */
res += corf;
FLAG_X = FLAG_C = (res > 0x9f) << 8;
if(FLAG_C)
res -= 0xa0;
@ -169,13 +171,15 @@ static void m68k_op_abcd_8_mm_ax7(void)
uint ea = EA_A7_PD_8();
uint dst = m68ki_read_8(ea);
uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();
FLAG_V = ~res; /* Undefined V behavior */
uint corf = 0;
if(res > 9)
res += 6;
corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
FLAG_X = FLAG_C = (res > 0x99) << 8;
FLAG_V = ~res; /* Undefined V behavior */
res += corf;
FLAG_X = FLAG_C = (res > 0x9f) << 8;
if(FLAG_C)
res -= 0xa0;
@ -195,13 +199,15 @@ static void m68k_op_abcd_8_mm_ay7(void)
uint ea = EA_AX_PD_8();
uint dst = m68ki_read_8(ea);
uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();
FLAG_V = ~res; /* Undefined V behavior */
uint corf = 0;
if(res > 9)
res += 6;
corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
FLAG_X = FLAG_C = (res > 0x99) << 8;
FLAG_V = ~res; /* Undefined V behavior */
res += corf;
FLAG_X = FLAG_C = (res > 0x9f) << 8;
if(FLAG_C)
res -= 0xa0;
@ -221,13 +227,15 @@ static void m68k_op_abcd_8_mm_axy7(void)
uint ea = EA_A7_PD_8();
uint dst = m68ki_read_8(ea);
uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();
FLAG_V = ~res; /* Undefined V behavior */
uint corf = 0;
if(res > 9)
res += 6;
corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
FLAG_X = FLAG_C = (res > 0x99) << 8;
FLAG_V = ~res; /* Undefined V behavior */
res += corf;
FLAG_X = FLAG_C = (res > 0x9f) << 8;
if(FLAG_C)
res -= 0xa0;
@ -247,13 +255,15 @@ static void m68k_op_abcd_8_mm(void)
uint ea = EA_AX_PD_8();
uint dst = m68ki_read_8(ea);
uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1();
FLAG_V = ~res; /* Undefined V behavior */
uint corf = 0;
if(res > 9)
res += 6;
corf = 6;
res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
FLAG_X = FLAG_C = (res > 0x99) << 8;
FLAG_V = ~res; /* Undefined V behavior */
res += corf;
FLAG_X = FLAG_C = (res > 0x9f) << 8;
if(FLAG_C)
res -= 0xa0;
@ -15846,32 +15856,33 @@ static void m68k_op_nbcd_8_d(void)
{
uint* r_dst = &DY;
uint dst = *r_dst;
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
*r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -15879,32 +15890,33 @@ static void m68k_op_nbcd_8_ai(void)
{
uint ea = EA_AY_AI_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -15912,32 +15924,33 @@ static void m68k_op_nbcd_8_pi(void)
{
uint ea = EA_AY_PI_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -15945,32 +15958,33 @@ static void m68k_op_nbcd_8_pi7(void)
{
uint ea = EA_A7_PI_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -15978,32 +15992,33 @@ static void m68k_op_nbcd_8_pd(void)
{
uint ea = EA_AY_PD_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -16011,32 +16026,33 @@ static void m68k_op_nbcd_8_pd7(void)
{
uint ea = EA_A7_PD_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -16044,32 +16060,33 @@ static void m68k_op_nbcd_8_di(void)
{
uint ea = EA_AY_DI_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -16077,32 +16094,33 @@ static void m68k_op_nbcd_8_ix(void)
{
uint ea = EA_AY_IX_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -16110,32 +16128,33 @@ static void m68k_op_nbcd_8_aw(void)
{
uint ea = EA_AW_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -16143,32 +16162,33 @@ static void m68k_op_nbcd_8_al(void)
{
uint ea = EA_AL_8();
uint dst = m68ki_read_8(ea);
uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1());
uint res = -dst - XFLAG_AS_1();
if(res != 0x9a)
if(res)
{
FLAG_V = ~res; /* Undefined V behavior */
FLAG_V = res; /* Undefined V behavior */
if((res & 0x0f) == 0xa)
res = (res & 0xf0) + 0x10;
if(((res|dst) & 0x0f) == 0x0)
res = (res & 0xf0) + 6;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res+0x9a);
FLAG_V &= res; /* Undefined V behavior part II */
FLAG_V &= ~res; /* Undefined V behavior part II */
m68ki_write_8(ea, MASK_OUT_ABOVE_8(res));
m68ki_write_8(ea, res);
FLAG_Z |= res;
FLAG_C = CFLAG_SET;
FLAG_X = XFLAG_SET;
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
else
{
FLAG_V = VFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
FLAG_X = XFLAG_CLEAR;
FLAG_N = NFLAG_CLEAR;
}
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
}
@ -19736,26 +19756,28 @@ static void m68k_op_sbcd_8_rr(void)
uint src = DY;
uint dst = *r_dst;
uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();
uint corf = 0;
/* FLAG_V = ~res; */ /* Undefined V behavior */
FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to assume cleared. */
if(res > 0xf)
corf = 6;
if(res > 9)
res -= 6;
res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
if(res > 0x99)
FLAG_V = res; /* Undefined V behavior */
if(res > 0xff)
{
res += 0xa0;
FLAG_X = FLAG_C = CFLAG_SET;
FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
else if(res < corf)
FLAG_X = FLAG_C = CFLAG_SET;
else
FLAG_N = FLAG_X = FLAG_C = 0;
FLAG_X = FLAG_C = 0;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res-corf);
/* FLAG_V &= res; */ /* Undefined V behavior part II */
/* FLAG_N = NFLAG_8(res); */ /* Undefined N behavior */
FLAG_V &= ~res; /* Undefined V behavior part II */
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
FLAG_Z |= res;
*r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
@ -19768,26 +19790,27 @@ static void m68k_op_sbcd_8_mm_ax7(void)
uint ea = EA_A7_PD_8();
uint dst = m68ki_read_8(ea);
uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();
uint corf = 0;
/* FLAG_V = ~res; */ /* Undefined V behavior */
FLAG_V = 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)
FLAG_V = res; /* Undefined V behavior */
if(res > 0xff)
{
res += 0xa0;
FLAG_X = FLAG_C = CFLAG_SET;
FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
else if(res < corf)
FLAG_X = FLAG_C = CFLAG_SET;
else
FLAG_N = FLAG_X = FLAG_C = 0;
FLAG_X = FLAG_C = 0;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res-corf);
/* FLAG_V &= res; */ /* Undefined V behavior part II */
/* FLAG_N = NFLAG_8(res); */ /* Undefined N behavior */
FLAG_V &= ~res; /* Undefined V behavior part II */
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
FLAG_Z |= res;
m68ki_write_8(ea, res);
@ -19800,26 +19823,27 @@ static void m68k_op_sbcd_8_mm_ay7(void)
uint ea = EA_AX_PD_8();
uint dst = m68ki_read_8(ea);
uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();
uint corf = 0;
/* FLAG_V = ~res; */ /* Undefined V behavior */
FLAG_V = 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)
FLAG_V = res; /* Undefined V behavior */
if(res > 0xff)
{
res += 0xa0;
FLAG_X = FLAG_C = CFLAG_SET;
FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
else if(res < corf)
FLAG_X = FLAG_C = CFLAG_SET;
else
FLAG_N = FLAG_X = FLAG_C = 0;
FLAG_X = FLAG_C = 0;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res-corf);
/* FLAG_V &= res; */ /* Undefined V behavior part II */
/* FLAG_N = NFLAG_8(res); */ /* Undefined N behavior */
FLAG_V &= ~res; /* Undefined V behavior part II */
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
FLAG_Z |= res;
m68ki_write_8(ea, res);
@ -19832,26 +19856,27 @@ static void m68k_op_sbcd_8_mm_axy7(void)
uint ea = EA_A7_PD_8();
uint dst = m68ki_read_8(ea);
uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();
uint corf = 0;
/* FLAG_V = ~res; */ /* Undefined V behavior */
FLAG_V = 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)
FLAG_V = res; /* Undefined V behavior */
if(res > 0xff)
{
res += 0xa0;
FLAG_X = FLAG_C = CFLAG_SET;
FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
else if(res < corf)
FLAG_X = FLAG_C = CFLAG_SET;
else
FLAG_N = FLAG_X = FLAG_C = 0;
FLAG_X = FLAG_C = 0;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res-corf);
/* FLAG_V &= res; */ /* Undefined V behavior part II */
/* FLAG_N = NFLAG_8(res); */ /* Undefined N behavior */
FLAG_V &= ~res; /* Undefined V behavior part II */
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
FLAG_Z |= res;
m68ki_write_8(ea, res);
@ -19864,26 +19889,27 @@ static void m68k_op_sbcd_8_mm(void)
uint ea = EA_AX_PD_8();
uint dst = m68ki_read_8(ea);
uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1();
uint corf = 0;
/* FLAG_V = ~res; */ /* Undefined V behavior */
FLAG_V = 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)
FLAG_V = res; /* Undefined V behavior */
if(res > 0xff)
{
res += 0xa0;
FLAG_X = FLAG_C = CFLAG_SET;
FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
}
else if(res < corf)
FLAG_X = FLAG_C = CFLAG_SET;
else
FLAG_N = FLAG_X = FLAG_C = 0;
FLAG_X = FLAG_C = 0;
res = MASK_OUT_ABOVE_8(res);
res = MASK_OUT_ABOVE_8(res-corf);
/* FLAG_V &= res; */ /* Undefined V behavior part II */
/* FLAG_N = NFLAG_8(res); */ /* Undefined N behavior */
FLAG_V &= ~res; /* Undefined V behavior part II */
FLAG_N = NFLAG_8(res); /* Undefined N behavior */
FLAG_Z |= res;
m68ki_write_8(ea, res);