📄 oparith.cpp
字号:
if (type)
{
ot(" mov r3,#0x00f00000\n");
ot(" ldrb r0,[r7,#0x45] ;@ Get X bit\n");
ot(" tst r0,#2\n");
ot(" and r0,r3,r10,lsr #4\n");
ot(" and r2,r3,r1,lsr #4\n");
ot(" add r0,r0,r2\n");
ot(" addne r0,r0,#0x00100000\n");
// ot(" tst r0,#0x00800000\n");
// ot(" orreq r9,r9,#0x01000000 ;@ Undefined V behavior\n");
ot(" cmp r0,#0x00900000\n");
ot(" addhi r0,r0,#0x00600000 ;@ Decimal adjust units\n");
ot(" mov r2,r1,lsr #28\n");
ot(" add r0,r0,r2,lsl #24\n");
ot(" mov r2,r10,lsr #28\n");
ot(" add r0,r0,r2,lsl #24\n");
ot(" cmp r0,#0x09900000\n");
ot(" orrhi r9,r9,#0x20000000 ;@ C\n");
ot(" subhi r0,r0,#0x0a000000\n");
// ot(" and r3,r9,r0,lsr #3 ;@ Undefined V behavior part II\n");
// ot(" orr r9,r9,r3,lsl #4 ;@ V\n");
ot(" movs r0,r0,lsl #4\n");
ot(" orrmi r9,r9,#0x90000000 ;@ Undefined N+V behavior\n"); // this is what Musashi really does
ot(" bicne r9,r9,#0x40000000 ;@ Z flag\n");
}
else
{
ot(" mov r3,#0x00f00000\n");
ot(" ldrb r0,[r7,#0x45] ;@ Get X bit\n");
ot(" tst r0,#2\n");
ot(" and r0,r3,r1,lsr #4\n");
ot(" and r2,r3,r10,lsr #4\n");
ot(" sub r0,r0,r2\n");
ot(" subne r0,r0,#0x00100000\n");
// ot(" tst r0,#0x00800000\n");
// ot(" orreq r9,r9,#0x01000000 ;@ Undefined V behavior\n");
ot(" cmp r0,#0x00900000\n");
ot(" subhi r0,r0,#0x00600000 ;@ Decimal adjust units\n");
ot(" mov r2,r1,lsr #28\n");
ot(" add r0,r0,r2,lsl #24\n");
ot(" mov r2,r10,lsr #28\n");
ot(" sub r0,r0,r2,lsl #24\n");
ot(" cmp r0,#0x09900000\n");
ot(" orrhi r9,r9,#0xa0000000 ;@ N and C\n");
ot(" addhi r0,r0,#0x0a000000\n");
// ot(" and r3,r9,r0,lsr #3 ;@ Undefined V behavior part II\n");
// ot(" orr r9,r9,r3,lsl #4 ;@ V\n");
ot(" movs r0,r0,lsl #4\n");
// ot(" orrmi r9,r9,#0x80000000 ;@ Undefined N behavior\n");
ot(" bicne r9,r9,#0x40000000 ;@ Z flag\n");
}
ot(" mov r2,r9,lsr #28\n");
ot(" strb r2,[r7,#0x45] ;@ Save X bit\n");
EaWrite(11, 0, dea,0,0x0e00,1);
OpEnd();
return 0;
}
// 01008000 00eeeeee - nbcd <ea>
int OpNbcd(int op)
{
int use=0;
int ea=0;
ea=op&0x3f;
if(EaCanWrite(ea)==0||EaAn(ea)) return 1;
use=OpBase(op);
if(op!=use) { OpUse(op,use); return 0; } // Use existing handler
OpStart(op); Cycles=6;
if(ea >= 8) Cycles+=2;
EaCalc(10,0x3f, ea,0,1);
EaRead(10, 0, ea,0,0x3f,1);
// this is rewrite of Musashi's code
ot(" ldrb r2,[r7,#0x45]\n");
ot(" tst r2,#2\n");
ot(" mov r2,r0\n");
ot(" addne r2,r0,#0x01000000 ;@ add X\n");
ot(" rsbs r1,r2,#0x9a000000 ;@ do arithmetic\n");
ot(" bic r9,r9,#0xb0000000 ;@ clear all flags, except Z\n");
ot(" orrmi r9,r9,#0x80000000 ;@ N\n");
ot(" cmp r1,#0x9a000000\n");
ot(" beq finish%.4x\n",op);
ot("\n");
ot(" mvn r3,r9,lsr #3 ;@ Undefined V behavior\n",op);
ot(" and r2,r1,#0x0f000000\n");
ot(" cmp r2,#0x0a000000\n");
ot(" andeq r1,r1,#0xf0000000\n");
ot(" addeq r1,r1,#0x10000000\n");
ot(" and r3,r3,r1,lsr #3 ;@ Undefined V behavior part II\n",op);
ot(" tst r1,r1\n");
ot(" orr r9,r9,r3 ;@ save V\n",op);
ot(" bicne r9,r9,#0x40000000 ;@ Z\n");
ot(" orr r9,r9,#0x20000000 ;@ C\n");
ot("\n");
EaWrite(10, 1, ea,0,0x3f,1);
ot("finish%.4x%s\n",op,ms?"":":");
ot(" mov r2,r9,lsr #28\n");
ot(" strb r2, [r7,#0x45]\n");
OpEnd();
return 0;
}
// --------------------- Opcodes 0x90c0+ ---------------------
// Suba/Cmpa/Adda 1tt1nnnx 11eeeeee (tt=type, x=size, eeeeee=Source EA)
int OpAritha(int op)
{
int use=0;
int type=0,size=0,sea=0,dea=0;
// Suba/Cmpa/Adda/(invalid):
type=(op>>13)&3; if (type>=3) return 1;
size=(op>>8)&1; size++;
dea=(op>>9)&7; dea|=8; // Dest=An
sea=op&0x003f; // Source
// See if we can do this opcode:
if (EaCanRead(sea,size)==0) return 1;
use=OpBase(op);
use&=~0x0e00; // Use same opcode for An
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
OpStart(op); Cycles=(size==2)?6:8;
if(size==2&&(sea<0x10||sea==0x3c)) Cycles+=2;
if(type==1) Cycles=6;
EaCalc ( 0,0x003f, sea,size);
EaRead ( 0, 10, sea,size,0x003f);
EaCalc ( 0,0x0e00, dea,2,1);
EaRead ( 0, 1, dea,2,0x0e00);
if (type==0) ot(" sub r1,r1,r10\n");
if (type==1) ot(" cmp r1,r10 ;@ Defines NZCV\n");
if (type==1) OpGetFlags(1,0); // Get Cmp flags
if (type==2) ot(" add r1,r1,r10\n");
ot("\n");
if (type!=1) EaWrite( 0, 1, dea,2,0x0e00,1);
OpEnd();
return 0;
}
// --------------------- Opcodes 0x9100+ ---------------------
// Emit a Subx/Addx opcode, 1t01ddd1 zz00rsss addx.z Ds,Dd
int OpAddx(int op)
{
int use=0;
int type=0,size=0,dea=0,sea=0,mem=0;
type=(op>>12)&5;
dea =(op>> 9)&7;
size=(op>> 6)&3; if (size>=3) return 1;
sea = op&7;
mem =(op>> 3)&1;
// See if we can do this opcode:
if (EaCanRead(sea,size)==0) return 1;
if (EaCanWrite(dea)==0) return 1;
if(mem) { sea+=0x20; dea+=0x20; }
use=op&~0x0e07; // Use same opcode for Dn
if (size==0&&(sea==0x27||dea==0x27)) use=op; // ___x.b -(a7)
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
OpStart(op); Cycles=4;
if(size>=2) Cycles+=4;
if(sea>=0x10) Cycles+=2;
ot(";@ Get r10=EA r11=EA value\n");
EaCalc( 0,0x0007,sea,size,1);
EaRead( 0, 11,sea,size,0x0007,1);
ot(";@ Get r0=Register r1=Register value\n");
EaCalc( 0,0x0e00,dea,size,1);
EaRead( 0, 1,dea,size,0x0e00,1);
ot(";@ Do arithmetic:\n");
GetXBit(type==1);
if (type==5 && size<2)
{
ot(";@ Make sure the carry bit will tip the balance:\n");
ot(" mvn r2,#0\n");
ot(" orr r11,r11,r2,lsr #%i\n",(size==0)?8:16);
ot("\n");
}
if (type==1) ot(" sbcs r1,r1,r11\n");
if (type==5) ot(" adcs r1,r1,r11\n");
ot(" orr r3,r9,#0xb0000000 ;@ for old Z\n");
OpGetFlags(type==1,1,0); // subtract
if (size<2) {
ot(" movs r2,r1,lsr #%i\n", size?16:24);
ot(" orreq r9,r9,#0x40000000 ;@ add potentially missed Z\n");
}
ot(" andeq r9,r9,r3 ;@ fix Z\n");
ot("\n");
ot(";@ Save result:\n");
EaWrite( 0, 1, dea,size,0x0e00,1);
OpEnd();
return 0;
}
// --------------------- Opcodes 0xb000+ ---------------------
// Emit a Cmp/Eor opcode, 1011rrrt xxeeeeee (rrr=Dn, t=cmp/eor, xx=size extension, eeeeee=ea)
int OpCmpEor(int op)
{
int rea=0,eor=0;
int size=0,ea=0,use=0;
// Get EA and register EA
rea=(op>>9)&7;
eor=(op>>8)&1;
size=(op>>6)&3; if (size>=3) return 1;
ea=op&0x3f;
if (eor && (ea>>3) == 1) return 1; // not a valid mode for eor
// See if we can do this opcode:
if (EaCanRead(ea,size)==0) return 1;
if (eor && EaCanWrite(ea)==0) return 1;
if (EaAn(ea)&&(eor||size==0)) return 1;
use=OpBase(op);
use&=~0x0e00; // Use 1 handler for register d0-7
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
OpStart(op); Cycles=4;
if(eor) {
if(ea>8) Cycles+=4;
if(size>=2) Cycles+=4;
} else {
if(size>=2) Cycles+=2;
}
ot(";@ Get EA into r10 and value into r0:\n");
EaCalc (10,0x003f, ea,size,1);
EaRead (10, 0, ea,size,0x003f,1);
ot(";@ Get register operand into r1:\n");
EaCalc (1, 0x0e00, rea,size,1);
EaRead (1, 1, rea,size,0x0e00,1);
ot(";@ Do arithmetic:\n");
if (eor==0) ot(" cmp r1,r0\n");
if (eor)
{
ot(" eor r1,r0,r1\n");
ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
}
OpGetFlags(eor==0,0); // Cmp like subtract
ot("\n");
if (eor) EaWrite(10, 1,ea,size,0x003f,1);
OpEnd();
return 0;
}
// Emit a Cmpm opcode, 1011ddd1 xx001sss (rrr=Adst, xx=size extension, sss=Asrc)
int OpCmpm(int op)
{
int size=0,sea=0,dea=0,use=0;
// get size, get EAs
size=(op>>6)&3; if (size>=3) return 1;
sea=(op&7)|0x18;
dea=(op>>9)&0x3f;
use=op&~0x0e07; // Use 1 handler for all registers..
if (size==0&&(sea==0x1f||dea==0x1f)) use=op; // ..except (a7)+
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
OpStart(op); Cycles=4;
ot(";@ Get src operand into r10:\n");
EaCalc (0,0x000f, sea,size,1);
EaRead (0, 10, sea,size,0x000f,1);
ot(";@ Get dst operand into r0:\n");
EaCalc (0,0x1e00, dea,size,1);
EaRead (0, 0, dea,size,0x1e00,1);
ot(" cmp r0,r10\n");
OpGetFlags(1,0); // Cmp like subtract
OpEnd();
return 0;
}
// Emit a Chk opcode, 0100ddd1 x0eeeeee (rrr=Dn, x=size extension, eeeeee=ea)
int OpChk(int op)
{
int rea=0;
int size=0,ea=0,use=0;
// Get EA and register EA
rea=(op>>9)&7;
if((op>>7)&1)
size=1; // word operation
else size=2; // long
ea=op&0x3f;
if (EaAn(ea)) return 1; // not a valid mode
if (size!=1) return 1; // 000 variant only supports word
// See if we can do this opcode:
if (EaCanRead(ea,size)==0) return 1;
use=OpBase(op);
use&=~0x0e00; // Use 1 handler for register d0-7
if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
OpStart(op); Cycles=10;
ot(";@ Get EA into r10 and value into r0:\n");
EaCalc (10,0x003f, ea,size,1);
EaRead (10, 0, ea,size,0x003f,1);
ot(";@ Get register operand into r1:\n");
EaCalc (1, 0x0e00, rea,size,1);
EaRead (1, 1, rea,size,0x0e00,1);
ot(";@ get flags, including undocumented ones\n");
ot(" and r3,r9,#0x80000000\n");
ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
OpGetFlags(0,0);
ot(";@ is reg negative?\n");
ot(" bmi chktrap%.4x\n",op);
ot(";@ Do arithmetic:\n");
ot(" cmp r1,r0\n");
ot(" bicgt r9,r9,#0x80000000 ;@ N\n");
ot(" bgt chktrap%.4x\n",op);
ot(";@ old N remains\n");
ot(" bic r9,r9,#0x80000000 ;@ N\n");
ot(" orr r9,r9,r3\n");
OpEnd();
ot("chktrap%.4x%s ;@ CHK exception:\n",op,ms?"":":");
ot(" mov r0,#0x18\n");
ot(" bl Exception\n");
Cycles+=40;
OpEnd();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -