mame/src/emu/cpu/v60/op7a.c
2008-12-08 06:35:28 +00:00

1212 lines
28 KiB
C

/*
* CMPC: What happens to cpustate->_S flag if the strings are identical?
* I suppose that it will be cleared. And is it set or cleared
* when the first one is a substring of the second? I suppose
* cleared (since cpustate->_S should be (src > dst))
* MOVC: Why MOVCS does not exist in downward version?
* SHCHDB / SHCHDH: cpustate->R27 is filled with the offset from the start or from the end?
*
* Strange stuff:
* SCHC opcodes does *not* modify cpustate->_Z flag as stated in V60 manual:
* they do the opposite (set if not found, reset if found)
*/
#define F7AEND(cs) \
return (cs)->amlength1 + (cs)->amlength2 + 4;
#define F7BEND(cs) \
return (cs)->amlength1 + (cs)->amlength2 + 3;
#define F7CEND(cs) \
return (cs)->amlength1 + (cs)->amlength2 + 3;
#define F7BCREATEBITMASK(x) \
x = ((1 << (x)) - 1)
#define F7CCREATEBITMASK(x) \
x = ((1 << (x)) - 1)
static void F7aDecodeOperands(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1, UINT32 (*DecodeOp2)(v60_state *), UINT8 dim2)
{
UINT8 appb;
// Decode first operand
cpustate->moddim = dim1;
cpustate->modm = cpustate->subop & 0x40;
cpustate->modadd = cpustate->PC + 2;
cpustate->amlength1 = DecodeOp1(cpustate);
cpustate->flag1 = cpustate->amflag;
cpustate->op1 = cpustate->amout;
// Decode length
appb = OpRead8(cpustate->program, cpustate->PC + 2 + cpustate->amlength1);
if (appb & 0x80)
cpustate->lenop1 = cpustate->reg[appb & 0x1F];
else
cpustate->lenop1 = appb;
// Decode second operand
cpustate->moddim = dim2;
cpustate->modm = cpustate->subop & 0x20;
cpustate->modadd = cpustate->PC + 3 + cpustate->amlength1;
cpustate->amlength2 = DecodeOp2(cpustate);
cpustate->flag2 = cpustate->amflag;
cpustate->op2 = cpustate->amout;
// Decode length
appb = OpRead8(cpustate->program, cpustate->PC + 3 + cpustate->amlength1 + cpustate->amlength2);
if (appb & 0x80)
cpustate->lenop2 = cpustate->reg[appb & 0x1F];
else
cpustate->lenop2 = appb;
}
static void F7bDecodeFirstOperand(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1)
{
UINT8 appb;
// Decode first operand
cpustate->moddim = dim1;
cpustate->modm = cpustate->subop & 0x40;
cpustate->modadd = cpustate->PC + 2;
cpustate->amlength1 = DecodeOp1(cpustate);
cpustate->flag1 = cpustate->amflag;
cpustate->op1 = cpustate->amout;
// Decode ext
appb = OpRead8(cpustate->program, cpustate->PC + 2 + cpustate->amlength1);
if (appb & 0x80)
cpustate->lenop1 = cpustate->reg[appb & 0x1F];
else
cpustate->lenop1 = appb;
}
static void F7bWriteSecondOperand(v60_state *cpustate, UINT8 dim2)
{
cpustate->moddim = dim2;
cpustate->modm = cpustate->subop & 0x20;
cpustate->modadd = cpustate->PC + 3 + cpustate->amlength1;
cpustate->amlength2 = WriteAM(cpustate);
}
static void F7bDecodeOperands(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1, UINT32 (*DecodeOp2)(v60_state *), UINT8 dim2)
{
// Decode first operand
F7bDecodeFirstOperand(cpustate, DecodeOp1, dim1);
cpustate->bamoffset1 = cpustate->bamoffset;
// Decode second operand
cpustate->moddim = dim2;
cpustate->modm = cpustate->subop & 0x20;
cpustate->modadd = cpustate->PC + 3 + cpustate->amlength1;
cpustate->amlength2 = DecodeOp2(cpustate);
cpustate->flag2 = cpustate->amflag;
cpustate->op2 = cpustate->amout;
cpustate->bamoffset2 = cpustate->bamoffset;
}
static void F7cDecodeOperands(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1, UINT32 (*DecodeOp2)(v60_state *), UINT8 dim2)
{
UINT8 appb;
// Decode first operand
cpustate->moddim = dim1;
cpustate->modm = cpustate->subop & 0x40;
cpustate->modadd = cpustate->PC + 2;
cpustate->amlength1 = DecodeOp1(cpustate);
cpustate->flag1 = cpustate->amflag;
cpustate->op1 = cpustate->amout;
// Decode second operand
cpustate->moddim = dim2;
cpustate->modm = cpustate->subop & 0x20;
cpustate->modadd = cpustate->PC + 2 + cpustate->amlength1;
cpustate->amlength2 = DecodeOp2(cpustate);
cpustate->flag2 = cpustate->amflag;
cpustate->op2 = cpustate->amout;
// Decode ext
appb = OpRead8(cpustate->program, cpustate->PC + 2 + cpustate->amlength1 + cpustate->amlength2);
if (appb & 0x80)
cpustate->lenop1 = cpustate->reg[appb & 0x1F];
else
cpustate->lenop1 = appb;
}
#define F7CLOADOP1BYTE(cs,appb) \
if ((cs)->flag1) \
appb = (UINT8)((cs)->reg[(cs)->op1]&0xFF); \
else \
appb = MemRead8((cs)->program, (cs)->op1);
#define F7CLOADOP2BYTE(cs,appb) \
if ((cs)->flag2) \
appb = (UINT8)((cs)->reg[(cs)->op2]&0xFF); \
else \
appb = MemRead8((cs)->program, (cs)->op2);
#define F7CSTOREOP2BYTE(cs) \
if ((cs)->flag2) \
SETREG8((cs)->reg[(cs)->op2], appb); \
else \
MemWrite8((cs)->program, (cs)->op2, appb);
#define F7CSTOREOP2HALF(cs) \
if ((cs)->flag2) \
SETREG16((cs)->reg[(cs)->op2], apph); \
else \
MemWrite16((cs)->program, (cs)->op2, apph);
static UINT32 opCMPSTRB(v60_state *cpustate, UINT8 bFill, UINT8 bStop)
{
UINT32 i, dest;
UINT8 c1, c2;
F7aDecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
// Filling
if (bFill)
{
if (cpustate->lenop1 < cpustate->lenop2)
{
for (i = cpustate->lenop1; i < cpustate->lenop2; i++)
MemWrite8(cpustate->program, cpustate->op1 + i,(UINT8)cpustate->R26);
}
else if (cpustate->lenop2 < cpustate->lenop1)
{
for (i = cpustate->lenop2; i < cpustate->lenop1; i++)
MemWrite8(cpustate->program, cpustate->op2 + i,(UINT8)cpustate->R26);
}
}
dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
cpustate->_Z = 0;
cpustate->_S = 0;
if (bStop) cpustate->_CY = 1;
for (i = 0; i < dest; i++)
{
c1 = MemRead8(cpustate->program, cpustate->op1 + i);
c2 = MemRead8(cpustate->program, cpustate->op2 + i);
if (c1 > c2)
{
cpustate->_S = 1; break;
}
else if (c2 > c1)
{
cpustate->_S = 0; break;
}
if (bStop)
if (c1 == (UINT8)cpustate->R26 || c2 == (UINT8)cpustate->R26)
{
cpustate->_CY = 0;
break;
}
}
cpustate->R28 = cpustate->lenop1 + i;
cpustate->R27 = cpustate->lenop2 + i;
if (i == dest)
{
if (cpustate->lenop1 > cpustate->lenop2)
cpustate->_S = 1;
else if (cpustate->lenop2 > cpustate->lenop1)
cpustate->_S = 0;
else
cpustate->_Z = 1;
}
F7AEND(cpustate);
}
static UINT32 opCMPSTRH(v60_state *cpustate, UINT8 bFill, UINT8 bStop)
{
UINT32 i, dest;
UINT16 c1, c2;
F7aDecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
// Filling
if (bFill)
{
if (cpustate->lenop1 < cpustate->lenop2)
{
for (i = cpustate->lenop1; i < cpustate->lenop2; i++)
MemWrite16(cpustate->program, cpustate->op1 + i * 2,(UINT16)cpustate->R26);
}
else if (cpustate->lenop2 < cpustate->lenop1)
{
for (i = cpustate->lenop2; i < cpustate->lenop1; i++)
MemWrite16(cpustate->program, cpustate->op2 + i * 2,(UINT16)cpustate->R26);
}
}
dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
cpustate->_Z = 0;
cpustate->_S = 0;
if (bStop) cpustate->_CY = 1;
for (i = 0; i < dest; i++)
{
c1 = MemRead16(cpustate->program, cpustate->op1 + i * 2);
c2 = MemRead16(cpustate->program, cpustate->op2 + i * 2);
if (c1 > c2)
{
cpustate->_S = 1; break;
}
else if (c2 > c1)
{
cpustate->_S = 0; break;
}
if (bStop)
if (c1 == (UINT16)cpustate->R26 || c2 == (UINT16)cpustate->R26)
{
cpustate->_CY = 0;
break;
}
}
cpustate->R28 = cpustate->lenop1 + i * 2;
cpustate->R27 = cpustate->lenop2 + i * 2;
if (i == dest)
{
if (cpustate->lenop1 > cpustate->lenop2)
cpustate->_S = 1;
else if (cpustate->lenop2 > cpustate->lenop1)
cpustate->_S = 0;
else
cpustate->_Z = 1;
}
F7AEND(cpustate);
}
static UINT32 opMOVSTRUB(v60_state *cpustate, UINT8 bFill, UINT8 bStop) /* TRUSTED (0, 0) (1, 0) */
{
UINT32 i, dest;
UINT8 c1;
// if (bStop)
// {
// int a = 1;
// }
F7aDecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
for (i = 0; i < dest; i++)
{
MemWrite8(cpustate->program, cpustate->op2 + i,(c1 = MemRead8(cpustate->program, cpustate->op1 + i)));
if (bStop && c1 == (UINT8)cpustate->R26)
break;
}
cpustate->R28 = cpustate->op1 + i;
cpustate->R27 = cpustate->op2 + i;
if (bFill && cpustate->lenop1 < cpustate->lenop2)
{
for (;i < cpustate->lenop2; i++)
MemWrite8(cpustate->program, cpustate->op2 + i,(UINT8)cpustate->R26);
cpustate->R27 = cpustate->op2 + i;
}
F7AEND(cpustate);
}
static UINT32 opMOVSTRDB(v60_state *cpustate, UINT8 bFill, UINT8 bStop)
{
UINT32 i, dest;
UINT8 c1;
F7aDecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
for (i = 0; i < dest; i++)
{
MemWrite8(cpustate->program, cpustate->op2 + (dest - i - 1),(c1 = MemRead8(cpustate->program, cpustate->op1 + (dest - i - 1))));
if (bStop && c1 == (UINT8)cpustate->R26)
break;
}
cpustate->R28 = cpustate->op1 + (cpustate->lenop1 - i - 1);
cpustate->R27 = cpustate->op2 + (cpustate->lenop2 - i - 1);
if (bFill && cpustate->lenop1 < cpustate->lenop2)
{
for (;i < cpustate->lenop2; i++)
MemWrite8(cpustate->program, cpustate->op2 + dest + (cpustate->lenop2 - i - 1),(UINT8)cpustate->R26);
cpustate->R27 = cpustate->op2 + (cpustate->lenop2 - i - 1);
}
F7AEND(cpustate);
}
static UINT32 opMOVSTRUH(v60_state *cpustate, UINT8 bFill, UINT8 bStop) /* TRUSTED (0, 0) (1, 0) */
{
UINT32 i, dest;
UINT16 c1;
// if (bStop)
// { int a = 1; }
F7aDecodeOperands(cpustate, ReadAMAddress, 1,ReadAMAddress, 1);
dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
for (i = 0; i < dest; i++)
{
MemWrite16(cpustate->program, cpustate->op2 + i * 2,(c1 = MemRead16(cpustate->program, cpustate->op1 + i * 2)));
if (bStop && c1 == (UINT16)cpustate->R26)
break;
}
cpustate->R28 = cpustate->op1 + i * 2;
cpustate->R27 = cpustate->op2 + i * 2;
if (bFill && cpustate->lenop1 < cpustate->lenop2)
{
for (;i < cpustate->lenop2; i++)
MemWrite16(cpustate->program, cpustate->op2 + i * 2,(UINT16)cpustate->R26);
cpustate->R27 = cpustate->op2 + i * 2;
}
F7AEND(cpustate);
}
static UINT32 opMOVSTRDH(v60_state *cpustate, UINT8 bFill, UINT8 bStop)
{
UINT32 i, dest;
UINT16 c1;
// if (bFill | bStop)
// { int a = 1; }
F7aDecodeOperands(cpustate, ReadAMAddress, 1,ReadAMAddress, 1);
// if (cpustate->lenop1 != cpustate->lenop2)
// { int a = 1; }
dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
for (i = 0; i < dest; i++)
{
MemWrite16(cpustate->program, cpustate->op2 + (dest - i - 1) * 2,(c1 = MemRead16(cpustate->program, cpustate->op1 + (dest - i - 1) * 2)));
if (bStop && c1 == (UINT16)cpustate->R26)
break;
}
cpustate->R28 = cpustate->op1 + (cpustate->lenop1 - i - 1) * 2;
cpustate->R27 = cpustate->op2 + (cpustate->lenop2 - i - 1) * 2;
if (bFill && cpustate->lenop1 < cpustate->lenop2)
{
for (;i < cpustate->lenop2; i++)
MemWrite16(cpustate->program, cpustate->op2 + (cpustate->lenop2 - i - 1) * 2,(UINT16)cpustate->R26);
cpustate->R27 = cpustate->op2 + (cpustate->lenop2 - i - 1) * 2;
}
F7AEND(cpustate);
}
static UINT32 opSEARCHUB(v60_state *cpustate, UINT8 bSearch)
{
UINT8 appb;
UINT32 i;
F7bDecodeOperands(cpustate, ReadAMAddress, 0,ReadAM, 0);
for (i = 0; i < cpustate->lenop1; i++)
{
appb = (MemRead8(cpustate->program, cpustate->op1 + i) == (UINT8)cpustate->op2);
if ((bSearch && appb) || (!bSearch && !appb))
break;
}
cpustate->R28 = cpustate->op1 + i;
cpustate->R27 = i;
// This is the opposite as stated in V60 manual...
if (i != cpustate->lenop1)
cpustate->_Z = 0;
else
cpustate->_Z = 1;
F7BEND(cpustate);
}
static UINT32 opSEARCHUH(v60_state *cpustate, UINT8 bSearch)
{
UINT8 appb;
UINT32 i;
F7bDecodeOperands(cpustate, ReadAMAddress, 1,ReadAM, 1);
for (i = 0; i < cpustate->lenop1; i++)
{
appb = (MemRead16(cpustate->program, cpustate->op1 + i * 2) == (UINT16)cpustate->op2);
if ((bSearch && appb) || (!bSearch && !appb))
break;
}
cpustate->R28 = cpustate->op1 + i * 2;
cpustate->R27 = i;
if (i != cpustate->lenop1)
cpustate->_Z = 0;
else
cpustate->_Z = 1;
F7BEND(cpustate);
}
static UINT32 opSEARCHDB(v60_state *cpustate, UINT8 bSearch)
{
UINT8 appb;
INT32 i;
F7bDecodeOperands(cpustate, ReadAMAddress, 0,ReadAM, 0);
for (i = cpustate->lenop1; i >= 0; i--)
{
appb = (MemRead8(cpustate->program, cpustate->op1 + i) == (UINT8)cpustate->op2);
if ((bSearch && appb) || (!bSearch && !appb))
break;
}
cpustate->R28 = cpustate->op1 + i;
cpustate->R27 = i;
// This is the opposite as stated in V60 manual...
if ((UINT32)i != cpustate->lenop1)
cpustate->_Z = 0;
else
cpustate->_Z = 1;
F7BEND(cpustate);
}
static UINT32 opSEARCHDH(v60_state *cpustate, UINT8 bSearch)
{
UINT8 appb;
INT32 i;
F7bDecodeOperands(cpustate, ReadAMAddress, 1,ReadAM, 1);
for (i = cpustate->lenop1 - 1; i >= 0; i--)
{
appb = (MemRead16(cpustate->program, cpustate->op1 + i * 2) == (UINT16)cpustate->op2);
if ((bSearch && appb) || (!bSearch && !appb))
break;
}
cpustate->R28 = cpustate->op1 + i * 2;
cpustate->R27 = i;
if ((UINT32)i != cpustate->lenop1)
cpustate->_Z = 0;
else
cpustate->_Z = 1;
F7BEND(cpustate);
}
static UINT32 opSCHCUB(v60_state *cpustate) { return opSEARCHUB(cpustate, 1); }
static UINT32 opSCHCUH(v60_state *cpustate) { return opSEARCHUH(cpustate, 1); }
static UINT32 opSCHCDB(v60_state *cpustate) { return opSEARCHDB(cpustate, 1); }
static UINT32 opSCHCDH(v60_state *cpustate) { return opSEARCHDH(cpustate, 1); }
static UINT32 opSKPCUB(v60_state *cpustate) { return opSEARCHUB(cpustate, 0); }
static UINT32 opSKPCUH(v60_state *cpustate) { return opSEARCHUH(cpustate, 0); }
static UINT32 opSKPCDB(v60_state *cpustate) { return opSEARCHDB(cpustate, 0); }
static UINT32 opSKPCDH(v60_state *cpustate) { return opSEARCHDH(cpustate, 0); }
static UINT32 opCMPCB(v60_state *cpustate) { return opCMPSTRB(cpustate, 0, 0); }
static UINT32 opCMPCH(v60_state *cpustate) { return opCMPSTRH(cpustate, 0, 0); }
static UINT32 opCMPCFB(v60_state *cpustate) { return opCMPSTRB(cpustate, 1, 0); }
static UINT32 opCMPCFH(v60_state *cpustate) { return opCMPSTRH(cpustate, 1, 0); }
static UINT32 opCMPCSB(v60_state *cpustate) { return opCMPSTRB(cpustate, 0, 1); }
static UINT32 opCMPCSH(v60_state *cpustate) { return opCMPSTRH(cpustate, 0, 1); }
static UINT32 opMOVCUB(v60_state *cpustate) { return opMOVSTRUB(cpustate, 0, 0); }
static UINT32 opMOVCUH(v60_state *cpustate) { return opMOVSTRUH(cpustate, 0, 0); }
static UINT32 opMOVCFUB(v60_state *cpustate) { return opMOVSTRUB(cpustate, 1, 0); }
static UINT32 opMOVCFUH(v60_state *cpustate) { return opMOVSTRUH(cpustate, 1, 0); }
static UINT32 opMOVCSUB(v60_state *cpustate) { return opMOVSTRUB(cpustate, 0, 1); }
static UINT32 opMOVCSUH(v60_state *cpustate) { return opMOVSTRUH(cpustate, 0, 1); }
static UINT32 opMOVCDB(v60_state *cpustate) { return opMOVSTRDB(cpustate, 0, 0); }
static UINT32 opMOVCDH(v60_state *cpustate) { return opMOVSTRDH(cpustate, 0, 0); }
static UINT32 opMOVCFDB(v60_state *cpustate) { return opMOVSTRDB(cpustate, 1, 0); }
static UINT32 opMOVCFDH(v60_state *cpustate) { return opMOVSTRDH(cpustate, 1, 0); }
static UINT32 opEXTBFZ(v60_state *cpustate) /* TRUSTED */
{
F7bDecodeFirstOperand(cpustate, BitReadAM, 11);
F7BCREATEBITMASK(cpustate->lenop1);
cpustate->modwritevalw = (cpustate->op1 >> cpustate->bamoffset) & cpustate->lenop1;
F7bWriteSecondOperand(cpustate, 2);
F7BEND(cpustate);
}
static UINT32 opEXTBFS(v60_state *cpustate) /* TRUSTED */
{
F7bDecodeFirstOperand(cpustate, BitReadAM, 11);
F7BCREATEBITMASK(cpustate->lenop1);
cpustate->modwritevalw = (cpustate->op1 >> cpustate->bamoffset) & cpustate->lenop1;
if (cpustate->modwritevalw & ((cpustate->lenop1 + 1) >> 1))
cpustate->modwritevalw |= ~cpustate->lenop1;
F7bWriteSecondOperand(cpustate, 2);
F7BEND(cpustate);
}
static UINT32 opEXTBFL(v60_state *cpustate)
{
UINT32 appw;
F7bDecodeFirstOperand(cpustate, BitReadAM, 11);
appw = cpustate->lenop1;
F7BCREATEBITMASK(cpustate->lenop1);
cpustate->modwritevalw = (cpustate->op1 >> cpustate->bamoffset) & cpustate->lenop1;
cpustate->modwritevalw <<= 32 - appw;
F7bWriteSecondOperand(cpustate, 2);
F7BEND(cpustate);
}
static UINT32 opSCHBS(v60_state *cpustate, UINT32 bSearch1)
{
UINT32 i, data;
UINT32 offset;
F7bDecodeFirstOperand(cpustate, BitReadAMAddress, 10);
// Read first UINT8
cpustate->op1 += cpustate->bamoffset / 8;
data = MemRead8(cpustate->program, cpustate->op1);
offset = cpustate->bamoffset & 7;
// Scan bitstring
for (i = 0; i < cpustate->lenop1; i++)
{
// Update the work register
cpustate->R28 = cpustate->op1;
// There is a 0 / 1 at current offset?
if ((bSearch1 && (data&(1 << offset))) ||
(!bSearch1 && !(data&(1 << offset))))
break;
// Next bit please
offset++;
if (offset == 8)
{
// Next UINT8 please
offset = 0;
cpustate->op1++;
data = MemRead8(cpustate->program, cpustate->op1);
}
}
// Set zero if bit not found
cpustate->_Z = (i == cpustate->lenop1);
// Write to destination the final offset
cpustate->modwritevalw = i;
F7bWriteSecondOperand(cpustate, 2);
F7BEND(cpustate);
}
static UINT32 opSCH0BSU(v60_state *cpustate) { return opSCHBS(cpustate, 0); }
static UINT32 opSCH1BSU(v60_state *cpustate) { return opSCHBS(cpustate, 1); }
static UINT32 opINSBFR(v60_state *cpustate)
{
UINT32 appw;
F7cDecodeOperands(cpustate, ReadAM, 2,BitReadAMAddress, 11);
F7CCREATEBITMASK(cpustate->lenop1);
cpustate->op2 += cpustate->bamoffset / 8;
appw = MemRead32(cpustate->program, cpustate->op2);
cpustate->bamoffset &= 7;
appw &= ~(cpustate->lenop1 << cpustate->bamoffset);
appw |= (cpustate->lenop1 & cpustate->op1) << cpustate->bamoffset;
MemWrite32(cpustate->program, cpustate->op2, appw);
F7CEND(cpustate);
}
static UINT32 opINSBFL(v60_state *cpustate)
{
UINT32 appw;
F7cDecodeOperands(cpustate, ReadAM, 2,BitReadAMAddress, 11);
cpustate->op1 >>= (32 - cpustate->lenop1);
F7CCREATEBITMASK(cpustate->lenop1);
cpustate->op2 += cpustate->bamoffset / 8;
appw = MemRead32(cpustate->program, cpustate->op2);
cpustate->bamoffset &= 7;
appw &= ~(cpustate->lenop1 << cpustate->bamoffset);
appw |= (cpustate->lenop1 & cpustate->op1) << cpustate->bamoffset;
MemWrite32(cpustate->program, cpustate->op2, appw);
F7CEND(cpustate);
}
static UINT32 opMOVBSD(v60_state *cpustate)
{
UINT32 i;
UINT8 srcdata, dstdata;
F7bDecodeOperands(cpustate, BitReadAMAddress, 10, BitReadAMAddress, 10);
// if (cpustate->lenop1 != 1)
// { int a = 1; }
cpustate->bamoffset1 += cpustate->lenop1 - 1;
cpustate->bamoffset2 += cpustate->lenop1 - 1;
cpustate->op1 += cpustate->bamoffset1 / 8;
cpustate->op2 += cpustate->bamoffset2 / 8;
cpustate->bamoffset1 &= 7;
cpustate->bamoffset2 &= 7;
srcdata = MemRead8(cpustate->program, cpustate->op1);
dstdata = MemRead8(cpustate->program, cpustate->op2);
for (i = 0; i < cpustate->lenop1; i++)
{
// Update work registers
cpustate->R28 = cpustate->op1;
cpustate->R27 = cpustate->op2;
dstdata &= ~(1 << cpustate->bamoffset2);
dstdata |= ((srcdata >> cpustate->bamoffset1) & 1) << cpustate->bamoffset2;
if (cpustate->bamoffset1 == 0)
{
cpustate->bamoffset1 = 8;
cpustate->op1--;
srcdata = MemRead8(cpustate->program, cpustate->op1);
}
if (cpustate->bamoffset2 == 0)
{
MemWrite8(cpustate->program, cpustate->op2, dstdata);
cpustate->bamoffset2 = 8;
cpustate->op2--;
dstdata = MemRead8(cpustate->program, cpustate->op2);
}
cpustate->bamoffset1--;
cpustate->bamoffset2--;
}
// Flush of the final data
if (cpustate->bamoffset2 != 7)
MemWrite8(cpustate->program, cpustate->op2, dstdata);
F7BEND(cpustate);
}
static UINT32 opMOVBSU(v60_state *cpustate)
{
UINT32 i;
UINT8 srcdata, dstdata;
F7bDecodeOperands(cpustate, BitReadAMAddress, 10, BitReadAMAddress, 10);
cpustate->op1 += cpustate->bamoffset1 / 8;
cpustate->op2 += cpustate->bamoffset2 / 8;
cpustate->bamoffset1 &= 7;
cpustate->bamoffset2 &= 7;
srcdata = MemRead8(cpustate->program, cpustate->op1);
dstdata = MemRead8(cpustate->program, cpustate->op2);
for (i = 0; i < cpustate->lenop1; i++)
{
// Update work registers
cpustate->R28 = cpustate->op1;
cpustate->R27 = cpustate->op2;
dstdata &= ~(1 << cpustate->bamoffset2);
dstdata |= ((srcdata >> cpustate->bamoffset1) & 1) << cpustate->bamoffset2;
cpustate->bamoffset1++;
cpustate->bamoffset2++;
if (cpustate->bamoffset1 == 8)
{
cpustate->bamoffset1 = 0;
cpustate->op1++;
srcdata = MemRead8(cpustate->program, cpustate->op1);
}
if (cpustate->bamoffset2 == 8)
{
MemWrite8(cpustate->program, cpustate->op2, dstdata);
cpustate->bamoffset2 = 0;
cpustate->op2++;
dstdata = MemRead8(cpustate->program, cpustate->op2);
}
}
// Flush of the final data
if (cpustate->bamoffset2 != 0)
MemWrite8(cpustate->program, cpustate->op2, dstdata);
F7BEND(cpustate);
}
// RADM 0x20f4b8 holds the time left
static UINT32 opADDDC(v60_state *cpustate)
{
UINT8 appb;
UINT8 src, dst;
F7cDecodeOperands(cpustate, ReadAM, 0, ReadAMAddress, 0);
if (cpustate->lenop1 != 0)
{
logerror("ADDDC %x (pat: %x)\n", cpustate->op1, cpustate->lenop1);
}
F7CLOADOP2BYTE(cpustate, appb);
src = (UINT8)(cpustate->op1 >> 4) * 10 + (UINT8)(cpustate->op1 & 0xF);
dst = (appb >> 4) * 10 + (appb & 0xF);
appb = src + dst + (cpustate->_CY?1:0);
if (appb >= 100)
{
appb -= 100;
cpustate->_CY = 1;
}
else
cpustate->_CY = 0;
// compute z flag:
// cleared if result non-zero or carry generated
// unchanged otherwise
if (appb != 0 || cpustate->_CY)
cpustate->_Z = 0;
appb = ((appb / 10) << 4) | (appb % 10);
F7CSTOREOP2BYTE(cpustate);
F7CEND(cpustate);
}
static UINT32 opSUBDC(v60_state *cpustate)
{
INT8 appb;
UINT32 src, dst;
F7cDecodeOperands(cpustate, ReadAM, 0, ReadAMAddress, 0);
if (cpustate->lenop1 != 0)
{
logerror("SUBDC %x (pat: %x)\n", cpustate->op1, cpustate->lenop1);
}
F7CLOADOP2BYTE(cpustate, appb);
src = (UINT32)(cpustate->op1 >> 4) * 10 + (UINT32)(cpustate->op1 & 0xF);
dst = ((appb & 0xF0) >> 4) * 10 + (appb & 0xF);
// Note that this APPB must be SIGNED!
appb = (INT32)dst - (INT32)src - (cpustate->_CY?1:0);
if (appb < 0)
{
appb += 100;
cpustate->_CY = 1;
}
else
cpustate->_CY = 0;
// compute z flag:
// cleared if result non-zero or carry generated
// unchanged otherwise
if (appb != 0 || cpustate->_CY)
cpustate->_Z = 0;
appb = ((appb / 10) << 4) | (appb % 10);
F7CSTOREOP2BYTE(cpustate);
F7CEND(cpustate);
}
static UINT32 opSUBRDC(v60_state *cpustate)
{
INT8 appb;
UINT32 src, dst;
F7cDecodeOperands(cpustate, ReadAM, 0, ReadAMAddress, 0);
if (cpustate->lenop1 != 0)
{
logerror("SUBRDC %x (pat: %x)\n", cpustate->op1, cpustate->lenop1);
}
F7CLOADOP2BYTE(cpustate, appb);
src = (UINT32)(cpustate->op1 >> 4) * 10 + (UINT32)(cpustate->op1 & 0xF);
dst = ((appb & 0xF0) >> 4) * 10 + (appb & 0xF);
// Note that this APPB must be SIGNED!
appb = (INT32)src - (INT32)dst - (cpustate->_CY?1:0);
if (appb < 0)
{
appb += 100;
cpustate->_CY = 1;
}
else
cpustate->_CY = 0;
// compute z flag:
// cleared if result non-zero or carry generated
// unchanged otherwise
if (appb != 0 || cpustate->_CY)
cpustate->_Z = 0;
appb = ((appb / 10) << 4) | (appb % 10);
F7CSTOREOP2BYTE(cpustate);
F7CEND(cpustate);
}
static UINT32 opCVTDPZ(v60_state *cpustate)
{
UINT16 apph;
F7cDecodeOperands(cpustate, ReadAM, 0, ReadAMAddress, 1);
apph = (UINT16)(((cpustate->op1 >> 4) & 0xF) | ((cpustate->op1 & 0xF) << 8));
apph |= (cpustate->lenop1);
apph |= (cpustate->lenop1 << 8);
// Z flag is unchanged if src is zero, cleared otherwise
if (cpustate->op1 != 0) cpustate->_Z = 0;
F7CSTOREOP2HALF(cpustate);
F7CEND(cpustate);
}
static UINT32 opCVTDZP(v60_state *cpustate)
{
UINT8 appb;
F7cDecodeOperands(cpustate, ReadAM, 1, ReadAMAddress, 0);
if ((cpustate->op1 & 0xF0) != (cpustate->lenop1 & 0xF0) || ((cpustate->op1 >> 8) & 0xF0) != (cpustate->lenop1 & 0xF0))
{
// Decimal exception
logerror("CVTD.ZP Decimal exception #1!\n");
}
if ((cpustate->op1 & 0xF) > 9 || ((cpustate->op1 >> 8) & 0xF) > 9)
{
// Decimal exception
logerror("CVTD.ZP Decimal exception #2!\n");
}
appb = (UINT8)(((cpustate->op1 >> 8) & 0xF) | ((cpustate->op1 & 0xF) << 4));
if (appb != 0) cpustate->_Z = 0;
F7CSTOREOP2BYTE(cpustate);
F7CEND(cpustate);
}
static UINT32 op58UNHANDLED(v60_state *cpustate)
{
fatalerror("Unhandled 58 opcode at cpustate->PC: /%06x", cpustate->PC);
return 0; /* never reached, fatalerror won't return */
}
static UINT32 op5AUNHANDLED(v60_state *cpustate)
{
fatalerror("Unhandled 5A opcode at cpustate->PC: /%06x", cpustate->PC);
return 0; /* never reached, fatalerror won't return */
}
static UINT32 op5BUNHANDLED(v60_state *cpustate)
{
fatalerror("Unhandled 5B opcode at cpustate->PC: /%06x", cpustate->PC);
return 0; /* never reached, fatalerror won't return */
}
static UINT32 op5DUNHANDLED(v60_state *cpustate)
{
fatalerror("Unhandled 5D opcode at cpustate->PC: /%06x", cpustate->PC);
return 0; /* never reached, fatalerror won't return */
}
static UINT32 op59UNHANDLED(v60_state *cpustate)
{
fatalerror("Unhandled 59 opcode at cpustate->PC: /%06x", cpustate->PC);
return 0; /* never reached, fatalerror won't return */
}
static UINT32 (*const Op59Table[32])(v60_state *) =
{
opADDDC,
opSUBDC,
opSUBRDC,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
opCVTDPZ,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
opCVTDZP,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED,
op59UNHANDLED
};
static UINT32 (*const Op5BTable[32])(v60_state *) =
{
opSCH0BSU,
op5BUNHANDLED,
opSCH1BSU,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
opMOVBSU,
opMOVBSD,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED,
op5BUNHANDLED
};
static UINT32 (*const Op5DTable[32])(v60_state *) =
{
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
opEXTBFS,
opEXTBFZ,
opEXTBFL,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
opINSBFR,
opINSBFL,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED,
op5DUNHANDLED
};
static UINT32 (*const Op58Table[32])(v60_state *) =
{
opCMPCB,
opCMPCFB,
opCMPCSB,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
opMOVCUB,
opMOVCDB,
opMOVCFUB,
opMOVCFDB,
opMOVCSUB,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
opSCHCUB,
opSCHCDB,
opSKPCUB,
opSKPCDB,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED,
op58UNHANDLED
};
static UINT32 (*const Op5ATable[32])(v60_state *) =
{
opCMPCH,
opCMPCFH,
opCMPCSH,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
opMOVCUH,
opMOVCDH,
opMOVCFUH,
opMOVCFDH,
opMOVCSUH,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
opSCHCUH,
opSCHCDH,
opSKPCUH,
opSKPCDH,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED,
op5AUNHANDLED
};
static UINT32 op58(v60_state *cpustate)
{
cpustate->subop = OpRead8(cpustate->program, cpustate->PC + 1);
return Op58Table[cpustate->subop & 0x1F](cpustate);
}
static UINT32 op5A(v60_state *cpustate)
{
cpustate->subop = OpRead8(cpustate->program, cpustate->PC + 1);
return Op5ATable[cpustate->subop & 0x1F](cpustate);
}
static UINT32 op5B(v60_state *cpustate)
{
cpustate->subop = OpRead8(cpustate->program, cpustate->PC + 1);
return Op5BTable[cpustate->subop & 0x1F](cpustate);
}
static UINT32 op5D(v60_state *cpustate)
{
cpustate->subop = OpRead8(cpustate->program, cpustate->PC + 1);
return Op5DTable[cpustate->subop & 0x1F](cpustate);
}
static UINT32 op59(v60_state *cpustate)
{
cpustate->subop = OpRead8(cpustate->program, cpustate->PC + 1);
return Op59Table[cpustate->subop & 0x1F](cpustate);
}