diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-15 17:35:52 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-15 17:35:52 +0100 |
| commit | 34c1fec8f7f0d8d5f6655ad2ccedb3a62467628b (patch) | |
| tree | e97851cb574b51192652dec907b818eb580cfdcd /src | |
| parent | 14ec226747d0e62d8be0684550859c2583eef99e (diff) | |
| download | box64-34c1fec8f7f0d8d5f6655ad2ccedb3a62467628b.tar.gz box64-34c1fec8f7f0d8d5f6655ad2ccedb3a62467628b.zip | |
[DYNAREC] Added 2D and 83 /5 opcodes
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64_emitter.h | 3 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_00.c | 35 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_emit_math.c | 159 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 2 |
4 files changed, 115 insertions, 84 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h index 46b14eb3..84d9cdaf 100755 --- a/src/dynarec/arm64_emitter.h +++ b/src/dynarec/arm64_emitter.h @@ -144,6 +144,7 @@ #define SUBw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 1, 0, 0, (imm12)&0xfff, Rn, Rd)) #define SUBSw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 1, 0, 0, (imm12)&0xfff, Rn, Rd)) #define SUBxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 1, 0, 0, (imm12)&0xfff, Rn, Rd)) +#define SUBSxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 1, 0, 0, (imm12)&0xfff, Rn, Rd)) // LDR #define LDR_gen(size, op1, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b01<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt)) @@ -217,10 +218,12 @@ #define LOGIC_gen(sf, opc, N, immr, imms, Rn, Rd) ((sf)<<31 | (opc)<<29 | 0b100100<<23 | (N)<<22 | (immr)<<16 | (imms)<<10 | (Rn) | Rd) #define ANDx_U13(Rd, Rn, imm13) EMIT(LOGIC_gen(1, 0b00, ((imm13)>>12)&1, (imm13)&0b111111, ((imm13)>>6)&0b111111, Rn, Rd)) #define ANDw_U12(Rd, Rn, imm12) EMIT(LOGIC_gen(0, 0b00, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd)) +#define ANDxw_U12(Rd, Rn, imm12) EMIT(LOGIC_gen(rex.w, 0b00, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd)) #define ANDSx_U13(Rd, Rn, imm13) EMIT(LOGIC_gen(1, 0b11, ((imm13)>>12)&1, (imm13)&0b111111, ((imm13)>>6)&0b111111, Rn, Rd)) #define ANDSw_U12(Rd, Rn, imm12) EMIT(LOGIC_gen(0, 0b11, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd)) #define ORRx_U13(Rd, Rn, imm13) EMIT(LOGIC_gen(1, 0b01, ((imm13)>>12)&1, (imm13)&0b111111, ((imm13)>>6)&0b111111, Rn, Rd)) #define ORRw_U12(Rd, Rn, imm12) EMIT(LOGIC_gen(0, 0b01, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd)) +#define ORRxw_U12(Rd, Rn, imm12) EMIT(LOGIC_gen(rex.w, 0b01, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd)) #define LOGIC_REG_gen(sf, opc, shift, N, Rm, imm6, Rn, Rd) ((sf)<<31 | (opc)<<29 | 0b01010<<24 | (shift)<<22 | (N)<<21 | (Rm)<<16 | (imm6)<<10 | (Rn)<<5 | (Rd)) #define ANDx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 0, Rm, 0, Rn, Rd)) diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c index 53b8f43e..17d0a8a9 100755 --- a/src/dynarec/dynarec_arm64_00.c +++ b/src/dynarec/dynarec_arm64_00.c @@ -67,6 +67,22 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin WBACK; break; + case 0x2B: + INST_NAME("SUB Gd, Ed"); + SETFLAGS(X_ALL, SF_SET); + nextop = F8; + GETGD; + GETED(0); + emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5); + break; + + case 0x2D: + INST_NAME("SUB EAX, Id"); + SETFLAGS(X_ALL, SF_SET); + i32 = F32S; + emit_sub32c(dyn, ninst, rex, xRAX, i32, x3, x4, x5); + break; + case 0x50: case 0x51: case 0x52: @@ -92,6 +108,25 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin POP1(gd); break; + case 0x81: + case 0x83: + nextop = F8; + switch((nextop>>3)&7) { + + case 5: //SUB + if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");} + SETFLAGS(X_ALL, SF_SET); + GETED((opcode==0x81)?4:1); + if(opcode==0x81) i32 = F32S; else i32 = F8S; + emit_sub32c(dyn, ninst, rex, ed, i32, x3, x4, x5); + WBACK; + break; + + default: + DEFAULT; + } + break; + case 0x89: INST_NAME("MOV Ed, Gd"); nextop=F8; diff --git a/src/dynarec/dynarec_arm64_emit_math.c b/src/dynarec/dynarec_arm64_emit_math.c index bc06904f..64a9a00d 100755 --- a/src/dynarec/dynarec_arm64_emit_math.c +++ b/src/dynarec/dynarec_arm64_emit_math.c @@ -211,89 +211,82 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } // emit SUB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch -//void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4) -//{ -// if(s1==xESP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND)) -// { -// // special case when doing math on ESP and only PEND is needed: ignoring it! -// if(c>=0 && c<256) { -// SUB_IMM8(s1, s1, c); -// } else { -// MOV32(s3, c); -// SUB_REG_LSL_IMM5(s1, s1, s3, 0); -// } -// return; -// } -// IFX(X_PEND) { -// MOV32(s3, c); -// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1)); -// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2)); -// SET_DF(s4, d_sub32); -// } else IFX(X_ALL) { -// SET_DFNONE(s4); -// } -// IFX(X_AF) { -// if(c>=0 && c<256) { -// MVN_REG_LSL_IMM5(s3, s1, 0); -// AND_IMM8(s4, s3, c); // s4 = ~op1 & op2 -// ORR_IMM8(s3, s3, c, 0); // s3 = ~op1 | op2 -// } else { -// IFX(X_PEND) {} else {MOV32(s3, c);} -// MVN_REG_LSL_IMM5(s4, s1, 0); -// ORR_REG_LSL_IMM5(s3, s4, s3, 0); -// MOV32(s4, c); -// BIC_REG_LSL_IMM5(s4, s4, s1, 0); -// PUSH(xSP, 1<<s3); -// } -// } -// if(c>=0 && c<256) { -// IFX(X_ALL) { -// SUBS_IMM8(s1, s1, c); -// } else { -// SUB_IMM8(s1, s1, c); -// } -// } else { -// IFXN(X_PEND, X_AF) {} else {MOV32(s3, c);} -// IFX(X_ALL) { -// SUBS_REG_LSL_IMM5(s1, s1, s3, 0); -// } else { -// SUB_REG_LSL_IMM5(s1, s1, s3, 0); -// } -// } -// IFX(X_PEND) { -// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res)); -// } -// IFX(X_AF) { -// if(c<0 || c>=256) { -// POP(xSP, 1<<s3); -// } -// AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res -// ORR_REG_LSL_IMM5(s3, s3, s4, 0); // s4 = (~op1 & op2) | ((~op1 | op2) & ~ res) -// MOV_REG_LSR_IMM5(s4, s3, 3); -// BFI(xFlags, s4, F_AF, 1); // AF: bc & 0x08 -// } -// IFX(X_ZF|X_CF) { -// BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0); -// } -// IFX(X_ZF) { -// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0); -// } -// IFX(X_CF) { -// // Inverted carry -// ORR_IMM8_COND(cCC, xFlags, xFlags, 1<<F_CF, 0); -// } -// IFX(X_OF) { -// ORR_IMM8_COND(cVS, xFlags, xFlags, 0b10, 0x0b); -// BIC_IMM8_COND(cVC, xFlags, xFlags, 0b10, 0x0b); -// } -// IFX(X_SF) { -// MOV_REG_LSR_IMM5(s3, s1, 31); -// BFI(xFlags, s3, F_SF, 1); -// } -// IFX(X_PF) { -// emit_pf(dyn, ninst, s1, s3, s4); -// } -//} +void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5) +{ + if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND)) + { + // special case when doing math on RSP and only PEND is needed: ignoring it! + SUBxw_U12(s1, s1, c); + return; + } + IFX(X_PEND) { + MOV64x(s3, c); + STRx_U12(s1, xEmu, offsetof(x64emu_t, op1)); + STRx_U12(s3, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s4, d_sub32); + } else IFX(X_ALL) { + SET_DFNONE(s4); + } + IFX(X_AF) { + if(c>=0 && c<0x1000) { + MVNxw(s3, s1); + ANDxw_U12(s4, s3, c); // s4 = ~op1 & op2 + ORRxw_U12(s3, s3, c); // s3 = ~op1 | op2 + } else { + MOV64x(s5, c); + MVNxw(s4, s1); + ORRxw_REG(s3, s4, s5); + BICxw_REG(s4, s5, s1); + } + } + if(c>=0 && c<0x1000) { + IFX(X_ALL) { + SUBSxw_U12(s1, s1, c); + } else { + SUBxw_U12(s1, s1, c); + } + } else { + IFXN(X_PEND, X_AF) {} else {MOV64x(s5, c);} + IFX(X_ALL) { + SUBSxw_REG(s1, s1, s5); + } else { + SUBxw_REG(s1, s1, s5); + } + } + IFX(X_PEND) { + STRx_U12(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_AF) { + ANDxw_REG(s3, s3, s1); // s3 = (~op1 | op2) & res + ORRxw_REG(s3, s3, s4); // s4 = (~op1 & op2) | ((~op1 | op2) & ~ res) + LSRxw(s4, s3, 3); + BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08 + } + IFX(X_ZF|X_CF|X_OF) { + MOVw(s5, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF)); + BICx(xFlags, xFlags, s5); + } + IFX(X_ZF) { + Bcond(cNE, +4); + ORRw_U12(xFlags, xFlags, 1<<F_ZF); + } + IFX(X_CF) { + // inverted carry + Bcond(cCS, +4); + ORRw_U12(xFlags, xFlags, 1<<F_CF); + } + IFX(X_OF) { + Bcond(cVC, +4); + ORRw_U12(xFlags, xFlags, 1<<F_OF); + } + IFX(X_SF) { + LSRxw(s3, s1, (rex.w)?63:31); + BFIx(xFlags, s3, F_SF, 1); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} // emit ADD8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved //void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4) diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index a9068b48..d4e5a543 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -546,7 +546,7 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save //void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4); //void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); -//void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); +void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); //void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4); //void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); //void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); |