summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/v60/op7a.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/v60/op7a.c')
-rw-r--r--trunk/src/emu/cpu/v60/op7a.c1211
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);
+}