diff options
Diffstat (limited to 'trunk/src/emu/cpu/v60/op7a.c')
-rw-r--r-- | trunk/src/emu/cpu/v60/op7a.c | 1211 |
1 files changed, 1211 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/v60/op7a.c b/trunk/src/emu/cpu/v60/op7a.c new file mode 100644 index 00000000000..e2d062fa14a --- /dev/null +++ b/trunk/src/emu/cpu/v60/op7a.c @@ -0,0 +1,1211 @@ + +/* + * 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, 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, 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, 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, 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 = (cs)->program->read_byte((cs)->op1); + +#define F7CLOADOP2BYTE(cs,appb) \ + if ((cs)->flag2) \ + appb = (UINT8)((cs)->reg[(cs)->op2]&0xFF); \ + else \ + appb = (cs)->program->read_byte((cs)->op2); + + +#define F7CSTOREOP2BYTE(cs) \ + if ((cs)->flag2) \ + SETREG8((cs)->reg[(cs)->op2], appb); \ + else \ + (cs)->program->write_byte((cs)->op2, appb); + +#define F7CSTOREOP2HALF(cs) \ + if ((cs)->flag2) \ + SETREG16((cs)->reg[(cs)->op2], apph); \ + else \ + (cs)->program->write_word_unaligned((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++) + cpustate->program->write_byte(cpustate->op1 + i,(UINT8)cpustate->R26); + } + else if (cpustate->lenop2 < cpustate->lenop1) + { + for (i = cpustate->lenop2; i < cpustate->lenop1; i++) + cpustate->program->write_byte(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 = cpustate->program->read_byte(cpustate->op1 + i); + c2 = cpustate->program->read_byte(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++) + cpustate->program->write_word_unaligned(cpustate->op1 + i * 2,(UINT16)cpustate->R26); + } + else if (cpustate->lenop2 < cpustate->lenop1) + { + for (i = cpustate->lenop2; i < cpustate->lenop1; i++) + cpustate->program->write_word_unaligned(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 = cpustate->program->read_word_unaligned(cpustate->op1 + i * 2); + c2 = cpustate->program->read_word_unaligned(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++) + { + cpustate->program->write_byte(cpustate->op2 + i,(c1 = cpustate->program->read_byte(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++) + cpustate->program->write_byte(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++) + { + cpustate->program->write_byte(cpustate->op2 + (dest - i - 1),(c1 = cpustate->program->read_byte(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++) + cpustate->program->write_byte(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++) + { + cpustate->program->write_word_unaligned(cpustate->op2 + i * 2,(c1 = cpustate->program->read_word_unaligned(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++) + cpustate->program->write_word_unaligned(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++) + { + cpustate->program->write_word_unaligned(cpustate->op2 + (dest - i - 1) * 2,(c1 = cpustate->program->read_word_unaligned(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++) + cpustate->program->write_word_unaligned(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 = (cpustate->program->read_byte(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 = (cpustate->program->read_word_unaligned(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 = (cpustate->program->read_byte(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 = (cpustate->program->read_word_unaligned(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 = cpustate->program->read_byte(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 = cpustate->program->read_byte(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 = cpustate->program->read_dword_unaligned(cpustate->op2); + cpustate->bamoffset &= 7; + + appw &= ~(cpustate->lenop1 << cpustate->bamoffset); + appw |= (cpustate->lenop1 & cpustate->op1) << cpustate->bamoffset; + + cpustate->program->write_dword_unaligned(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 = cpustate->program->read_dword_unaligned(cpustate->op2); + cpustate->bamoffset &= 7; + + appw &= ~(cpustate->lenop1 << cpustate->bamoffset); + appw |= (cpustate->lenop1 & cpustate->op1) << cpustate->bamoffset; + + cpustate->program->write_dword_unaligned(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 = cpustate->program->read_byte(cpustate->op1); + dstdata = cpustate->program->read_byte(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 = cpustate->program->read_byte(cpustate->op1); + } + if (cpustate->bamoffset2 == 0) + { + cpustate->program->write_byte(cpustate->op2, dstdata); + cpustate->bamoffset2 = 8; + cpustate->op2--; + dstdata = cpustate->program->read_byte(cpustate->op2); + } + + cpustate->bamoffset1--; + cpustate->bamoffset2--; + } + + // Flush of the final data + if (cpustate->bamoffset2 != 7) + cpustate->program->write_byte(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 = cpustate->program->read_byte(cpustate->op1); + dstdata = cpustate->program->read_byte(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 = cpustate->program->read_byte(cpustate->op1); + } + if (cpustate->bamoffset2 == 8) + { + cpustate->program->write_byte(cpustate->op2, dstdata); + cpustate->bamoffset2 = 0; + cpustate->op2++; + dstdata = cpustate->program->read_byte(cpustate->op2); + } + } + + // Flush of the final data + if (cpustate->bamoffset2 != 0) + cpustate->program->write_byte(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, cpustate->PC + 1); + + return Op58Table[cpustate->subop & 0x1F](cpustate); +} + +static UINT32 op5A(v60_state *cpustate) +{ + cpustate->subop = OpRead8(cpustate, cpustate->PC + 1); + + return Op5ATable[cpustate->subop & 0x1F](cpustate); +} + +static UINT32 op5B(v60_state *cpustate) +{ + cpustate->subop = OpRead8(cpustate, cpustate->PC + 1); + + return Op5BTable[cpustate->subop & 0x1F](cpustate); +} + +static UINT32 op5D(v60_state *cpustate) +{ + cpustate->subop = OpRead8(cpustate, cpustate->PC + 1); + + return Op5DTable[cpustate->subop & 0x1F](cpustate); +} + +static UINT32 op59(v60_state *cpustate) +{ + cpustate->subop = OpRead8(cpustate, cpustate->PC + 1); + + return Op59Table[cpustate->subop & 0x1F](cpustate); +} |