/* * 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); }