diff options
Diffstat (limited to 'src/emu/cpu/v60/op7a.c')
-rw-r--r-- | src/emu/cpu/v60/op7a.c | 1230 |
1 files changed, 1230 insertions, 0 deletions
diff --git a/src/emu/cpu/v60/op7a.c b/src/emu/cpu/v60/op7a.c new file mode 100644 index 00000000000..db7a859b7ce --- /dev/null +++ b/src/emu/cpu/v60/op7a.c @@ -0,0 +1,1230 @@ + +/* + * CMPC: What happens to _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 _S should be (src > dst)) + * MOVC: Why MOVCS does not exist in downward version? + * SHCHDB/SHCHDH: R27 is filled with the offset from the start or from the end? + * + * Strange stuff: + * SCHC opcodes does *not* modify _Z flag as stated in V60 manual: + * they do the opposite (set if not found, reset if found) + */ + +static UINT32 f7aOp1, f7aOp2; +static UINT8 f7aFlag1, f7aFlag2; +static UINT32 f7aLenOp1, f7aLenOp2; +static UINT8 subOp; + +static UINT32 f7bBamOffset1, f7bBamOffset2; + +#define f7bOp1 f7aOp1 +#define f7bFlag1 f7aFlag1 +#define f7bOp2 f7aOp2 +#define f7bFlag2 f7aFlag2 +#define f7bLen f7aLenOp1 + +#define f7cOp1 f7aOp1 +#define f7cOp2 f7aOp2 +#define f7cLen f7aLenOp1 +#define f7cFlag1 f7aFlag1 +#define f7cFlag2 f7aFlag2 + +#define F7AEND() \ + return amLength1 + amLength2 + 4; + +#define F7BEND() \ + return amLength1 + amLength2 + 3; + +#define F7CEND() \ + return amLength1 + amLength2 + 3; + +#define F7BCREATEBITMASK(x) \ + x=((1<<(x))-1) + +#define F7CCREATEBITMASK(x) \ + x=((1<<(x))-1) + +static void F7aDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*DecodeOp2)(void), UINT8 dim2) +{ + UINT8 appb; + // Decode first operand + modDim=dim1; + modM=subOp&0x40; + modAdd=PC+2; + amLength1=DecodeOp1(); + f7aFlag1=amFlag; + f7aOp1=amOut; + + // Decode length + appb=OpRead8(PC+2+amLength1); + if (appb&0x80) + f7aLenOp1=v60.reg[appb&0x1F]; + else + f7aLenOp1=appb; + + // Decode second operand + modDim=dim2; + modM=subOp&0x20; + modAdd=PC+3+amLength1; + amLength2=DecodeOp2(); + f7aFlag2=amFlag; + f7aOp2=amOut; + + // Decode length + appb=OpRead8(PC+3+amLength1+amLength2); + if (appb&0x80) + f7aLenOp2=v60.reg[appb&0x1F]; + else + f7aLenOp2=appb; +} + +static void F7bDecodeFirstOperand(UINT32 (*DecodeOp1)(void), UINT8 dim1) +{ + UINT8 appb; + // Decode first operand + modDim=dim1; + modM=subOp&0x40; + modAdd=PC+2; + amLength1=DecodeOp1(); + f7bFlag1=amFlag; + f7bOp1=amOut; + + // Decode ext + appb=OpRead8(PC+2+amLength1); + if (appb&0x80) + f7bLen=v60.reg[appb&0x1F]; + else + f7bLen=appb; +} + + +static void F7bWriteSecondOperand(UINT8 dim2) +{ + modDim=dim2; + modM=subOp&0x20; + modAdd=PC+3+amLength1; + amLength2=WriteAM(); +} + + +static void F7bDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*DecodeOp2)(void), UINT8 dim2) +{ + // Decode first operand + F7bDecodeFirstOperand(DecodeOp1,dim1); + f7bBamOffset1 = bamOffset; + + // Decode second operand + modDim=dim2; + modM=subOp&0x20; + modAdd=PC+3+amLength1; + amLength2=DecodeOp2(); + f7bFlag2=amFlag; + f7bOp2=amOut; + f7bBamOffset2 = bamOffset; +} + +static void F7cDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*DecodeOp2)(void), UINT8 dim2) +{ + UINT8 appb; + // Decode first operand + modDim=dim1; + modM=subOp&0x40; + modAdd=PC+2; + amLength1=DecodeOp1(); + f7cFlag1=amFlag; + f7cOp1=amOut; + + // Decode second operand + modDim=dim2; + modM=subOp&0x20; + modAdd=PC+2+amLength1; + amLength2=DecodeOp2(); + f7cFlag2=amFlag; + f7cOp2=amOut; + + // Decode ext + appb=OpRead8(PC+2+amLength1+amLength2); + if (appb&0x80) + f7cLen=v60.reg[appb&0x1F]; + else + f7cLen=appb; +} + +#define F7CLOADOP1BYTE(appb) \ + if (f7cFlag1) \ + appb = (UINT8)(v60.reg[f7cOp1]&0xFF); \ + else \ + appb = MemRead8(f7cOp1); + +#define F7CLOADOP2BYTE(appb) \ + if (f7cFlag2) \ + appb = (UINT8)(v60.reg[f7cOp2]&0xFF); \ + else \ + appb = MemRead8(f7cOp2); + + +#define F7CSTOREOP2BYTE() \ + if (f7cFlag2) \ + SETREG8(v60.reg[f7cOp2], appb); \ + else \ + MemWrite8(f7cOp2, appb); + +#define F7CSTOREOP2HALF() \ + if (f7cFlag2) \ + SETREG16(v60.reg[f7cOp2], apph); \ + else \ + MemWrite16(f7cOp2, apph); + +static UINT32 opCMPSTRB(UINT8 bFill, UINT8 bStop) +{ + UINT32 i,dest; + UINT8 c1,c2; + + F7aDecodeOperands(ReadAMAddress,0,ReadAMAddress,0); + + // Filling + if (bFill) + { + if (f7aLenOp1 < f7aLenOp2) + { + for (i=f7aLenOp1;i<f7aLenOp2;i++) + MemWrite8(f7aOp1+i,(UINT8)R26); + } + else if (f7aLenOp2 < f7aLenOp1) + { + for (i=f7aLenOp2;i<f7aLenOp1;i++) + MemWrite8(f7aOp2+i,(UINT8)R26); + } + } + + dest=(f7aLenOp1 < f7aLenOp2 ? f7aLenOp1 : f7aLenOp2); + + _Z = 0; + _S = 0; + if (bStop) _CY = 1; + + for (i=0;i<dest;i++) + { + c1=MemRead8(f7aOp1+i); + c2=MemRead8(f7aOp2+i); + + if (c1>c2) + { + _S=1; break; + } + else if (c2>c1) + { + _S=0; break; + } + + if (bStop) + if (c1==(UINT8)R26 || c2==(UINT8)R26) + { + _CY=0; + break; + } + } + + R28=f7aLenOp1+i; + R27=f7aLenOp2+i; + + if (i==dest) + { + if (f7aLenOp1 > f7aLenOp2) + _S=1; + else if (f7aLenOp2 > f7aLenOp1) + _S=0; + else + _Z=1; + } + + F7AEND(); +} + +static UINT32 opCMPSTRH(UINT8 bFill, UINT8 bStop) +{ + UINT32 i,dest; + UINT16 c1,c2; + + F7aDecodeOperands(ReadAMAddress,0,ReadAMAddress,0); + + // Filling + if (bFill) + { + if (f7aLenOp1 < f7aLenOp2) + { + for (i=f7aLenOp1;i<f7aLenOp2;i++) + MemWrite16(f7aOp1+i*2,(UINT16)R26); + } + else if (f7aLenOp2 < f7aLenOp1) + { + for (i=f7aLenOp2;i<f7aLenOp1;i++) + MemWrite16(f7aOp2+i*2,(UINT16)R26); + } + } + + dest=(f7aLenOp1 < f7aLenOp2 ? f7aLenOp1 : f7aLenOp2); + + _Z = 0; + _S = 0; + if (bStop) _CY = 1; + + for (i=0;i<dest;i++) + { + c1=MemRead16(f7aOp1+i*2); + c2=MemRead16(f7aOp2+i*2); + + if (c1>c2) + { + _S=1; break; + } + else if (c2>c1) + { + _S=0; break; + } + + if (bStop) + if (c1==(UINT16)R26 || c2==(UINT16)R26) + { + _CY=0; + break; + } + } + + R28=f7aLenOp1+i*2; + R27=f7aLenOp2+i*2; + + if (i==dest) + { + if (f7aLenOp1 > f7aLenOp2) + _S=1; + else if (f7aLenOp2 > f7aLenOp1) + _S=0; + else + _Z=1; + } + + F7AEND(); +} + + + +static UINT32 opMOVSTRUB(UINT8 bFill, UINT8 bStop) /* TRUSTED (0,0) (1,0) */ +{ + UINT32 i,dest; + UINT8 c1; + +// if (bStop) +// { +// int a=1; +// } + + F7aDecodeOperands(ReadAMAddress,0,ReadAMAddress,0); + + dest=(f7aLenOp1 < f7aLenOp2 ? f7aLenOp1 : f7aLenOp2); + + for (i=0;i<dest;i++) + { + MemWrite8(f7aOp2+i,(c1=MemRead8(f7aOp1+i))); + + if (bStop && c1==(UINT8)R26) + break; + } + + R28=f7aOp1+i; + R27=f7aOp2+i; + + if (bFill && f7aLenOp1 < f7aLenOp2) + { + for (;i<f7aLenOp2;i++) + MemWrite8(f7aOp2+i,(UINT8)R26); + + R27=f7aOp2+i; + } + + + F7AEND(); +} + +static UINT32 opMOVSTRDB(UINT8 bFill, UINT8 bStop) +{ + UINT32 i,dest; + UINT8 c1; + + F7aDecodeOperands(ReadAMAddress,0,ReadAMAddress,0); + + dest=(f7aLenOp1 < f7aLenOp2 ? f7aLenOp1 : f7aLenOp2); + + for (i=0;i<dest;i++) + { + MemWrite8(f7aOp2+(dest-i-1),(c1=MemRead8(f7aOp1+(dest-i-1)))); + + if (bStop && c1==(UINT8)R26) + break; + } + + R28=f7aOp1+(f7aLenOp1-i-1); + R27=f7aOp2+(f7aLenOp2-i-1); + + if (bFill && f7aLenOp1 < f7aLenOp2) + { + for (;i<f7aLenOp2;i++) + MemWrite8(f7aOp2+dest+(f7aLenOp2-i-1),(UINT8)R26); + + R27=f7aOp2+(f7aLenOp2-i-1); + } + + + F7AEND(); +} + + +static UINT32 opMOVSTRUH(UINT8 bFill, UINT8 bStop) /* TRUSTED (0,0) (1,0) */ +{ + UINT32 i,dest; + UINT16 c1; + +// if (bStop) +// { int a=1; } + + F7aDecodeOperands(ReadAMAddress,1,ReadAMAddress,1); + + dest=(f7aLenOp1 < f7aLenOp2 ? f7aLenOp1 : f7aLenOp2); + + for (i=0;i<dest;i++) + { + MemWrite16(f7aOp2+i*2,(c1=MemRead16(f7aOp1+i*2))); + + if (bStop && c1==(UINT16)R26) + break; + } + + R28=f7aOp1+i*2; + R27=f7aOp2+i*2; + + if (bFill && f7aLenOp1 < f7aLenOp2) + { + for (;i<f7aLenOp2;i++) + MemWrite16(f7aOp2+i*2,(UINT16)R26); + + R27=f7aOp2+i*2; + } + + F7AEND(); +} + +static UINT32 opMOVSTRDH(UINT8 bFill, UINT8 bStop) +{ + UINT32 i,dest; + UINT16 c1; + +// if (bFill | bStop) +// { int a=1; } + + F7aDecodeOperands(ReadAMAddress,1,ReadAMAddress,1); + +// if (f7aLenOp1 != f7aLenOp2) +// { int a=1; } + + dest=(f7aLenOp1 < f7aLenOp2 ? f7aLenOp1 : f7aLenOp2); + + for (i=0;i<dest;i++) + { + MemWrite16(f7aOp2+(dest-i-1)*2,(c1=MemRead16(f7aOp1+(dest-i-1)*2))); + + if (bStop && c1==(UINT16)R26) + break; + } + + R28=f7aOp1+(f7aLenOp1-i-1)*2; + R27=f7aOp2+(f7aLenOp2-i-1)*2; + + if (bFill && f7aLenOp1 < f7aLenOp2) + { + for (;i<f7aLenOp2;i++) + MemWrite16(f7aOp2+(f7aLenOp2-i-1)*2,(UINT16)R26); + + R27=f7aOp2+(f7aLenOp2-i-1)*2; + } + + F7AEND(); +} + +static UINT32 opSEARCHUB(UINT8 bSearch) +{ + UINT8 appb; + UINT32 i; + + F7bDecodeOperands(ReadAMAddress,0,ReadAM,0); + + for (i=0;i<f7bLen;i++) + { + appb = (MemRead8(f7bOp1+i)==(UINT8)f7bOp2); + if ((bSearch && appb) || (!bSearch && !appb)) + break; + } + + R28=f7bOp1+i; + R27=i; + + // This is the opposite as stated in V60 manual... + if (i!=f7bLen) + _Z=0; + else + _Z=1; + + F7BEND(); +} + +static UINT32 opSEARCHUH(UINT8 bSearch) +{ + UINT8 appb; + UINT32 i; + + F7bDecodeOperands(ReadAMAddress,1,ReadAM,1); + + for (i=0;i<f7bLen;i++) + { + appb = (MemRead16(f7bOp1+i*2)==(UINT16)f7bOp2); + if ((bSearch && appb) || (!bSearch && !appb)) + break; + } + + R28=f7bOp1+i*2; + R27=i; + + if (i!=f7bLen) + _Z=0; + else + _Z=1; + + F7BEND(); +} + +static UINT32 opSEARCHDB(UINT8 bSearch) +{ + UINT8 appb; + INT32 i; + + F7bDecodeOperands(ReadAMAddress,0,ReadAM,0); + + for (i=f7bLen;i>=0;i--) + { + appb = (MemRead8(f7bOp1+i)==(UINT8)f7bOp2); + if ((bSearch && appb) || (!bSearch && !appb)) + break; + } + + R28=f7bOp1+i; + R27=i; + + // This is the opposite as stated in V60 manual... + if ((UINT32)i!=f7bLen) + _Z=0; + else + _Z=1; + + F7BEND(); +} + +static UINT32 opSEARCHDH(UINT8 bSearch) +{ + UINT8 appb; + INT32 i; + + F7bDecodeOperands(ReadAMAddress,1,ReadAM,1); + + for (i=f7bLen-1;i>=0;i--) + { + appb = (MemRead16(f7bOp1+i*2)==(UINT16)f7bOp2); + if ((bSearch && appb) || (!bSearch && !appb)) + break; + } + + R28=f7bOp1+i*2; + R27=i; + + if ((UINT32)i!=f7bLen) + _Z=0; + else + _Z=1; + + F7BEND(); +} + + +static UINT32 opSCHCUB(void) { return opSEARCHUB(1); } +static UINT32 opSCHCUH(void) { return opSEARCHUH(1); } +static UINT32 opSCHCDB(void) { return opSEARCHDB(1); } +static UINT32 opSCHCDH(void) { return opSEARCHDH(1); } +static UINT32 opSKPCUB(void) { return opSEARCHUB(0); } +static UINT32 opSKPCUH(void) { return opSEARCHUH(0); } +static UINT32 opSKPCDB(void) { return opSEARCHDB(0); } +static UINT32 opSKPCDH(void) { return opSEARCHDH(0); } + +static UINT32 opCMPCB(void) { return opCMPSTRB(0,0); } +static UINT32 opCMPCH(void) { return opCMPSTRH(0,0); } +static UINT32 opCMPCFB(void) { return opCMPSTRB(1,0); } +static UINT32 opCMPCFH(void) { return opCMPSTRH(1,0); } +static UINT32 opCMPCSB(void) { return opCMPSTRB(0,1); } +static UINT32 opCMPCSH(void) { return opCMPSTRH(0,1); } + +static UINT32 opMOVCUB(void) { return opMOVSTRUB(0,0); } +static UINT32 opMOVCUH(void) { return opMOVSTRUH(0,0); } +static UINT32 opMOVCFUB(void) { return opMOVSTRUB(1,0); } +static UINT32 opMOVCFUH(void) { return opMOVSTRUH(1,0); } +static UINT32 opMOVCSUB(void) { return opMOVSTRUB(0,1); } +static UINT32 opMOVCSUH(void) { return opMOVSTRUH(0,1); } + +static UINT32 opMOVCDB(void) { return opMOVSTRDB(0,0); } +static UINT32 opMOVCDH(void) { return opMOVSTRDH(0,0); } +static UINT32 opMOVCFDB(void) { return opMOVSTRDB(1,0); } +static UINT32 opMOVCFDH(void) { return opMOVSTRDH(1,0); } + +static UINT32 opEXTBFZ(void) /* TRUSTED */ +{ + F7bDecodeFirstOperand(BitReadAM, 11); + + F7BCREATEBITMASK(f7bLen); + + modWriteValW=(f7bOp1 >> bamOffset) & f7bLen; + + F7bWriteSecondOperand(2); + + F7BEND(); +} + +static UINT32 opEXTBFS(void) /* TRUSTED */ +{ + F7bDecodeFirstOperand(BitReadAM, 11); + + F7BCREATEBITMASK(f7bLen); + + modWriteValW=(f7bOp1 >> bamOffset) & f7bLen; + if (modWriteValW & ((f7bLen+1)>>1)) + modWriteValW |= ~f7bLen; + + F7bWriteSecondOperand(2); + + F7BEND(); +} + +static UINT32 opEXTBFL(void) +{ + UINT32 appw; + + F7bDecodeFirstOperand(BitReadAM, 11); + + appw=f7bLen; + F7BCREATEBITMASK(f7bLen); + + modWriteValW=(f7bOp1 >> bamOffset) & f7bLen; + modWriteValW<<=32-appw; + + F7bWriteSecondOperand(2); + + F7BEND(); +} + +static UINT32 opSCHBS(UINT32 bSearch1) +{ + UINT32 i,data; + UINT32 offset; + + F7bDecodeFirstOperand(BitReadAMAddress,10); + + // Read first UINT8 + f7bOp1 += bamOffset/8; + data = MemRead8(f7bOp1); + offset = bamOffset&7; + + // Scan bitstring + for (i=0;i<f7bLen;i++) + { + // Update the work register + R28 = f7bOp1; + + // 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; + f7bOp1++; + data = MemRead8(f7bOp1); + } + } + + // Set zero if bit not found + _Z = (i == f7bLen); + + // Write to destination the final offset + modWriteValW = i; + F7bWriteSecondOperand(2); + + F7BEND(); +} + +static UINT32 opSCH0BSU(void) { return opSCHBS(0); } +static UINT32 opSCH1BSU(void) { return opSCHBS(1); } + +static UINT32 opINSBFR(void) +{ + UINT32 appw; + F7cDecodeOperands(ReadAM,2,BitReadAMAddress,11); + + F7CCREATEBITMASK(f7cLen); + + f7cOp2 += bamOffset/8; + appw = MemRead32(f7cOp2); + bamOffset &= 7; + + appw &= ~(f7cLen << bamOffset); + appw |= (f7cLen & f7cOp1) << bamOffset; + + MemWrite32(f7cOp2, appw); + + F7CEND(); +} + +static UINT32 opINSBFL(void) +{ + UINT32 appw; + F7cDecodeOperands(ReadAM,2,BitReadAMAddress,11); + + f7cOp1 >>= (32-f7cLen); + + F7CCREATEBITMASK(f7cLen); + + f7cOp2 += bamOffset/8; + appw = MemRead32(f7cOp2); + bamOffset &= 7; + + appw &= ~(f7cLen << bamOffset); + appw |= (f7cLen & f7cOp1) << bamOffset; + + MemWrite32(f7cOp2, appw); + + F7CEND(); +} + +static UINT32 opMOVBSD(void) +{ + UINT32 i; + UINT8 srcdata, dstdata; + + F7bDecodeOperands(BitReadAMAddress,10,BitReadAMAddress,10); + +// if (f7bLen!=1) +// { int a=1; } + + f7bBamOffset1 += f7bLen-1; + f7bBamOffset2 += f7bLen-1; + + f7bOp1 += f7bBamOffset1/8; + f7bOp2 += f7bBamOffset2/8; + + f7bBamOffset1 &= 7; + f7bBamOffset2 &= 7; + + srcdata = MemRead8(f7bOp1); + dstdata = MemRead8(f7bOp2); + + for (i=0;i<f7bLen;i++) + { + // Update work registers + R28 = f7bOp1; + R27 = f7bOp2; + + dstdata &= ~(1 << f7bBamOffset2); + dstdata |= ((srcdata >> f7bBamOffset1) & 1) << f7bBamOffset2; + + if (f7bBamOffset1 == 0) + { + f7bBamOffset1 = 8; + f7bOp1--; + srcdata = MemRead8(f7bOp1); + } + if (f7bBamOffset2 == 0) + { + MemWrite8(f7bOp2, dstdata); + f7bBamOffset2 = 8; + f7bOp2--; + dstdata = MemRead8(f7bOp2); + } + + f7bBamOffset1--; + f7bBamOffset2--; + } + + // Flush of the final data + if (f7bBamOffset2 != 7) + MemWrite8(f7bOp2, dstdata); + + F7BEND(); +} + +static UINT32 opMOVBSU(void) +{ + UINT32 i; + UINT8 srcdata, dstdata; + + F7bDecodeOperands(BitReadAMAddress,10,BitReadAMAddress,10); + + f7bOp1 += f7bBamOffset1/8; + f7bOp2 += f7bBamOffset2/8; + + f7bBamOffset1 &= 7; + f7bBamOffset2 &= 7; + + srcdata = MemRead8(f7bOp1); + dstdata = MemRead8(f7bOp2); + + for (i=0;i<f7bLen;i++) + { + // Update work registers + R28 = f7bOp1; + R27 = f7bOp2; + + dstdata &= ~(1 << f7bBamOffset2); + dstdata |= ((srcdata >> f7bBamOffset1) & 1) << f7bBamOffset2; + + f7bBamOffset1++; + f7bBamOffset2++; + if (f7bBamOffset1 == 8) + { + f7bBamOffset1 = 0; + f7bOp1++; + srcdata = MemRead8(f7bOp1); + } + if (f7bBamOffset2 == 8) + { + MemWrite8(f7bOp2, dstdata); + f7bBamOffset2 = 0; + f7bOp2++; + dstdata = MemRead8(f7bOp2); + } + } + + // Flush of the final data + if (f7bBamOffset2 != 0) + MemWrite8(f7bOp2, dstdata); + + F7BEND(); +} + +// RADM 0x20f4b8 holds the time left + +static UINT32 opADDDC(void) +{ + UINT8 appb; + UINT8 src, dst; + + F7cDecodeOperands(ReadAM, 0, ReadAMAddress, 0); + + if (f7cLen != 0) + { + logerror("ADDDC %x (pat: %x)\n", f7cOp1, f7cLen); + } + + F7CLOADOP2BYTE(appb); + + src = (UINT8)(f7cOp1 >> 4) * 10 + (UINT8)(f7cOp1 & 0xF); + dst = (appb >> 4) * 10 + (appb & 0xF); + + appb = src + dst + (_CY?1:0); + + if (appb >= 100) + { + appb -= 100; + _CY = 1; + } + else + _CY = 0; + + // compute z flag: + // cleared if result non-zero or carry generated + // unchanged otherwise + if (appb != 0 || _CY) + _Z = 0; + + appb = ((appb/10)<<4) | (appb % 10); + + F7CSTOREOP2BYTE(); + F7CEND(); +} + +static UINT32 opSUBDC(void) +{ + INT8 appb; + UINT32 src, dst; + + F7cDecodeOperands(ReadAM, 0, ReadAMAddress, 0); + + if (f7cLen != 0) + { + logerror("SUBDC %x (pat: %x)\n", f7cOp1, f7cLen); + } + + F7CLOADOP2BYTE(appb); + + src = (UINT32)(f7cOp1 >> 4) * 10 + (UINT32)(f7cOp1 & 0xF); + dst = ((appb & 0xF0) >> 4) * 10 + (appb & 0xF); + + // Note that this APPB must be SIGNED! + appb = (INT32)dst - (INT32)src - (_CY?1:0); + + if (appb < 0) + { + appb += 100; + _CY = 1; + } + else + _CY = 0; + + // compute z flag: + // cleared if result non-zero or carry generated + // unchanged otherwise + if (appb != 0 || _CY) + _Z = 0; + + appb = ((appb/10)<<4) | (appb % 10); + + F7CSTOREOP2BYTE(); + F7CEND(); +} + +static UINT32 opSUBRDC(void) +{ + INT8 appb; + UINT32 src, dst; + + F7cDecodeOperands(ReadAM, 0, ReadAMAddress, 0); + + if (f7cLen != 0) + { + logerror("SUBRDC %x (pat: %x)\n", f7cOp1, f7cLen); + } + + F7CLOADOP2BYTE(appb); + + src = (UINT32)(f7cOp1 >> 4) * 10 + (UINT32)(f7cOp1 & 0xF); + dst = ((appb & 0xF0) >> 4) * 10 + (appb & 0xF); + + // Note that this APPB must be SIGNED! + appb = (INT32)src - (INT32)dst - (_CY?1:0); + + if (appb < 0) + { + appb += 100; + _CY = 1; + } + else + _CY = 0; + + // compute z flag: + // cleared if result non-zero or carry generated + // unchanged otherwise + if (appb != 0 || _CY) + _Z = 0; + + appb = ((appb/10)<<4) | (appb % 10); + + F7CSTOREOP2BYTE(); + F7CEND(); +} + +static UINT32 opCVTDPZ(void) +{ + UINT16 apph; + + F7cDecodeOperands(ReadAM, 0, ReadAMAddress, 1); + + apph = (UINT16)(((f7cOp1 >> 4) & 0xF) | ((f7cOp1 & 0xF) << 8)); + apph |= (f7cLen); + apph |= (f7cLen<<8); + + // Z flag is unchanged if src is zero, cleared otherwise + if (f7cOp1 != 0) _Z = 0; + + F7CSTOREOP2HALF(); + F7CEND(); +} + +static UINT32 opCVTDZP(void) +{ + UINT8 appb; + F7cDecodeOperands(ReadAM, 1, ReadAMAddress, 0); + + if ((f7cOp1 & 0xF0) != (f7cLen & 0xF0) || ((f7cOp1 >> 8) & 0xF0) != (f7cLen & 0xF0)) + { + // Decimal exception + logerror("CVTD.ZP Decimal exception #1!\n"); + } + + if ((f7cOp1 & 0xF) > 9 || ((f7cOp1 >> 8) & 0xF) > 9) + { + // Decimal exception + logerror("CVTD.ZP Decimal exception #2!\n"); + } + + appb = (UINT8)(((f7cOp1 >> 8) & 0xF) | ((f7cOp1 & 0xF) << 4)); + if (appb != 0) _Z = 0; + + F7CSTOREOP2BYTE(); + F7CEND(); +} + +static UINT32 op58UNHANDLED(void) +{ + fatalerror("Unhandled 58 opcode at PC: /%06x", PC); + return 0; /* never reached, fatalerror won't return */ +} + +static UINT32 op5AUNHANDLED(void) +{ + fatalerror("Unhandled 5A opcode at PC: /%06x", PC); + return 0; /* never reached, fatalerror won't return */ +} + +static UINT32 op5BUNHANDLED(void) +{ + fatalerror("Unhandled 5B opcode at PC: /%06x", PC); + return 0; /* never reached, fatalerror won't return */ +} + +static UINT32 op5DUNHANDLED(void) +{ + fatalerror("Unhandled 5D opcode at PC: /%06x", PC); + return 0; /* never reached, fatalerror won't return */ +} + +static UINT32 op59UNHANDLED(void) +{ + fatalerror("Unhandled 59 opcode at PC: /%06x", PC); + return 0; /* never reached, fatalerror won't return */ +} + +static UINT32 (*const Op59Table[32])(void) = +{ + 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])(void) = +{ + 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])(void) = +{ + 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])(void) = +{ + 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])(void) = +{ + 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(void) +{ + subOp = OpRead8(PC + 1); + + return Op58Table[subOp&0x1F](); +} + +static UINT32 op5A(void) +{ + subOp = OpRead8(PC + 1); + + return Op5ATable[subOp&0x1F](); +} + +static UINT32 op5B(void) +{ + subOp = OpRead8(PC + 1); + + return Op5BTable[subOp&0x1F](); +} + +static UINT32 op5D(void) +{ + subOp = OpRead8(PC + 1); + + return Op5DTable[subOp&0x1F](); +} + +static UINT32 op59(void) +{ + subOp = OpRead8(PC + 1); + + return Op59Table[subOp&0x1F](); +} |