diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-17 12:58:20 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-17 12:58:20 +0100 |
| commit | 477617240a968da98a4d517fc38c11c385a46a36 (patch) | |
| tree | 2d6a721a9b63c178b482171d73a959db1b21c790 /src | |
| parent | e8d2b6d25d3718355bc2cd5c30fcab74e81eeb8b (diff) | |
| download | box64-477617240a968da98a4d517fc38c11c385a46a36.tar.gz box64-477617240a968da98a4d517fc38c11c385a46a36.zip | |
[DYNAREC] Added FF opcodes
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64_emitter.h | 5 | ||||
| -rwxr-xr-x | src/dynarec/arm64_printer.c | 6 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_00.c | 57 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_emit_math.c | 188 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.c | 13 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 18 |
6 files changed, 182 insertions, 105 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h index f15d9f85..f91732e2 100755 --- a/src/dynarec/arm64_emitter.h +++ b/src/dynarec/arm64_emitter.h @@ -137,6 +137,7 @@ #define ADDw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd)) #define ADDSw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd)) #define ADDxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd)) +#define ADDSxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd)) #define SUBx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, 0, Rn, Rd)) #define SUBSx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd)) @@ -176,7 +177,7 @@ #define LDR_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b01<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt)) #define LDRx_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt)) #define LDRx_REG_LSL3(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 1, Rn, Rt)) -#define LDRx_REG_UXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b010, 0, Rn, Rt)) +#define LDRx_REG_UXTW3(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b010, 1, Rn, Rt)) #define LDRw_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt)) #define LDRw_REG_LSL2(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b011, 1, Rn, Rt)) #define LDRB_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt)) @@ -292,8 +293,10 @@ #define BFMxw(Rd, Rn, immr, imms) EMIT(BFM_gen(rex.w, 0b01, rex.w, immr, imms, Rn, Rd)) #define BFIx(Rd, Rn, lsb, width) BFMx(Rd, Rn, ((-lsb)%64)&0x3f, (width)-1) #define BFIw(Rd, Rn, lsb, width) BFMw(Rd, Rn, ((-lsb)%32)&0x1f, (width)-1) +#define BFIxw(Rd, Rn, lsb, width) if(rex.w) {BFIx(Rd, Rn, lsb, width);} else {BFIw(Rd, Rn, lsb, width);} #define BFCx(Rd, Rn, lsb, width) BFMx(Rd, xZR, ((-lsb)%64)&0x3f, (width)-1) #define BFCw(Rd, Rn, lsb, width) BFMw(Rd, xZR, ((-lsb)%32)&0x1f, (width)-1) +#define BFCxw(Rd, Rn, lsb, width) if(rex.w) {BFCx(Rd, Rn, lsb, width);} else {BFCw(Rd, Rn, lsb, width);} // UBFX #define UBFM_gen(sf, N, immr, imms, Rn, Rd) ((sf)<<31 | 0b10<<29 | 0b100110<<23 | (N)<<22 | (immr)<<16 | (imms)<<10 | (Rn)<<5 | (Rd)) diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c index 9530b039..cb9a1957 100755 --- a/src/dynarec/arm64_printer.c +++ b/src/dynarec/arm64_printer.c @@ -140,9 +140,6 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) int amount = size*a.S; if(option==3 && !amount) snprintf(buff, sizeof(buff), "LDR %s, [%s, %s]", (size==2)?Wt[Rt]:Xt[Rt], XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm]); - else if(!amount) - if(option==3 && !amount) - snprintf(buff, sizeof(buff), "LDR %s, [%s, %s, %s]", (size==2)?Wt[Rt]:Xt[Rt], XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm], extend[option]); else snprintf(buff, sizeof(buff), "LDR %s, [%s, %s, %s %d]", (size==2)?Wt[Rt]:Xt[Rt], XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm], extend[option], amount); return buff; @@ -174,9 +171,6 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) int amount = size*a.S; if(option==3 && !amount) snprintf(buff, sizeof(buff), "STR %s, [%s, %s]", (size==2)?Wt[Rt]:Xt[Rt], XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm]); - else if(!amount) - if(option==3 && !amount) - snprintf(buff, sizeof(buff), "STR %s, [%s, %s, %s]", (size==2)?Wt[Rt]:Xt[Rt], XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm], extend[option]); else snprintf(buff, sizeof(buff), "STR %s, [%s, %s, %s %d]", (size==2)?Wt[Rt]:Xt[Rt], XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm], extend[option], amount); return buff; diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c index c9802203..1bd5aca5 100755 --- a/src/dynarec/dynarec_arm64_00.c +++ b/src/dynarec/dynarec_arm64_00.c @@ -369,6 +369,63 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; + case 0xFF: + nextop = F8; + switch((nextop>>3)&7) { + case 0: // INC Ed + INST_NAME("INC Ed"); + SETFLAGS(X_ALL&~X_CF, SF_SUBSET); + GETED(0); + emit_inc32(dyn, ninst, rex, ed, x3, x4); + WBACK; + break; + case 1: //DEC Ed + INST_NAME("DEC Ed"); + SETFLAGS(X_ALL&~X_CF, SF_SUBSET); + GETED(0); + emit_dec32(dyn, ninst, rex, ed, x3, x4); + WBACK; + break; + case 2: // CALL Ed + INST_NAME("CALL Ed"); + PASS2IF(ninst && dyn->insts && dyn->insts[ninst-1].x64.set_flags, 1) { + READFLAGS(X_PEND); // that's suspicious + } else { + SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state + } + GETEDx(0); + BARRIER(1); + BARRIER_NEXT(1); + if(!dyn->insts || ninst==dyn->size-1) { + *need_epilog = 0; + *ok = 0; + } + GETIP(addr); + PUSH1(xRIP); + /*TABLE64(x3, addr); + PUSH1(x3);*/ + jump_to_next(dyn, 0, ed, ninst); + break; + case 4: // JMP Ed + INST_NAME("JMP Ed"); + BARRIER(1); + GETEDx(0); + jump_to_next(dyn, 0, ed, ninst); + *need_epilog = 0; + *ok = 0; + break; + case 6: // Push Ed + INST_NAME("PUSH Ed"); + GETEDx(0); + PUSH1(ed); + break; + + default: + INST_NAME("Grp5 Ed"); + DEFAULT; + } + break; + default: DEFAULT; } diff --git a/src/dynarec/dynarec_arm64_emit_math.c b/src/dynarec/dynarec_arm64_emit_math.c index 0c20e331..d712f58a 100755 --- a/src/dynarec/dynarec_arm64_emit_math.c +++ b/src/dynarec/dynarec_arm64_emit_math.c @@ -734,48 +734,57 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in //} // emit INC32 instruction, from s1, store result in s1 using s3 and s4 as scratch -//void emit_inc32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) -//{ -// IFX(X_PEND) { -// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1)); -// SET_DF(s4, d_inc32); -// } else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) { -// SET_DFNONE(s4); -// } -// IFX(X_AF) { -// ORR_IMM8(s3, s1, 1, 0); // s3 = op1 | op2 -// AND_IMM8(s4, s1, 1); // s4 = op1 & op2 -// } -// IFX(X_ZF|X_OF) { -// ADDS_IMM8(s1, s1, 1); -// } else { -// ADD_IMM8(s1, s1, 1); -// } -// IFX(X_PEND) { -// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res)); -// } -// IFX(X_AF) { -// BIC_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) { -// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0); -// BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 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_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4) +{ + IFX(X_PEND) { + STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s4, rex.w?d_inc64:d_inc32); + } else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) { + SET_DFNONE(s4); + } + IFX(X_AF) { + if(rex.w) { + ORRx_mask(s3, s1, 1, 0, 0); // s3 = op1 | op2 + ANDx_mask(s4, s1, 1, 0, 0); // s4 = op1 & op2 + } else { + ORRw_mask(s3, s1, 0, 0); // s3 = op1 | op2 + ANDw_mask(s4, s1, 0, 0); // s4 = op1 & op2 + } + } + IFX(X_ZF|X_OF) { + ADDSxw_U12(s1, s1, 1); + } else { + ADDxw_U12(s1, s1, 1); + } + IFX(X_PEND) { + STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_AF) { + BICxw_REG(s3, s3, s1); // s3 = (op1 | op2) & ~ res + ORRxw_REG(s3, s3, s4); // s4 = (op1 & op2) | ((op1 | op2) & ~ res) + LSRxw(s4, s3, 3); + BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08 + } + IFX(X_ZF|X_OF) { + MOVw(s3, (1<<F_ZF)|(1<<F_OF)); + BICx(xFlags, xFlags, s3); + } + IFX(X_ZF) { + Bcond(cNE, +8); + ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40 + } + IFX(X_OF) { + Bcond(cVC, +8); + ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800 + } + IFX(X_SF) { + LSRxw(s3, s1, rex.w?63:31); + BFIxw(xFlags, s3, F_SF, 1); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} // emit INC8 instruction, from s1, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved //void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) @@ -870,49 +879,58 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in //} // emit DEC32 instruction, from s1, store result in s1 using s3 and s4 as scratch -//void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) -//{ -// IFX(X_PEND) { -// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1)); -// SET_DF(s4, d_dec32); -// } else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) { -// SET_DFNONE(s4); -// } -// IFX(X_AF) { -// MVN_REG_LSL_IMM5(s3, s1, 0); -// AND_IMM8(s4, s3, 1); // s4 = ~op1 & op2 -// ORR_IMM8(s3, s3, 1, 0); // s3 = ~op1 | op2 -// } -// IFX(X_ZF|X_OF) { -// SUBS_IMM8(s1, s1, 1); -// } else { -// SUB_IMM8(s1, s1, 1); -// } -// IFX(X_PEND) { -// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res)); -// } -// IFX(X_AF) { -// 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) { -// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0); -// BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 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_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4) +{ + IFX(X_PEND) { + STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s4, d_dec32); + } else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) { + SET_DFNONE(s4); + } + IFX(X_AF) { + MVNxw(s3, s1); + if(rex.w) { + ANDx_mask(s4, s3, 1, 0, 0); // s4 = ~op1 & op2 + ORRx_mask(s3, s3, 1, 0, 0); // s3 = ~op1 | op2 + } else { + ANDw_mask(s4, s3, 0, 0); // s4 = ~op1 & op2 + ORRw_mask(s3, s3, 0, 0); // s3 = ~op1 | op2 + } + } + IFX(X_ZF|X_OF) { + SUBSxw_U12(s1, s1, 1); + } else { + SUBxw_U12(s1, s1, 1); + } + IFX(X_PEND) { + STRxw_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); + BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08 + } + IFX(X_ZF|X_OF) { + MOVw(s3, (1<<F_ZF)|(1<<F_OF)); + BICx(xFlags, xFlags, s3); + } + IFX(X_ZF) { + Bcond(cNE, +8); + ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40 + } + IFX(X_OF) { + Bcond(cVC, +8); + ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800 + } + IFX(X_SF) { + LSRxw(s3, s1, rex.w?63:31); + BFIxw(xFlags, s3, F_SF, 1); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} // emit DEC8 instruction, from s1, store result in s1 using s3 and s4 as scratch //void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) diff --git a/src/dynarec/dynarec_arm64_helper.c b/src/dynarec/dynarec_arm64_helper.c index 2b5fd809..64ae31f7 100755 --- a/src/dynarec/dynarec_arm64_helper.c +++ b/src/dynarec/dynarec_arm64_helper.c @@ -247,14 +247,17 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst) LDRx_REG_LSL3(x2, x2, x3); UBFXx(x3, xRIP, 16, JMPTABL_SHIFT); LDRx_REG_LSL3(x2, x2, x3); - LDRx_REG_UXTW(x3, x2, xRIP); + UBFXx(x3, xRIP, 0, JMPTABL_SHIFT); + LDRx_REG_LSL3(x3, x2, x3); } else { uintptr_t p = getJumpTableAddress64(ip); TABLE64(x2, p); GETIP_(ip); LDRx_U12(x3, x2, 0); } - MOVx(x1, xRIP); + if(reg!=x1) { + MOVx(x1, xRIP); + } #ifdef HAVE_TRACE //MOVx(x2, 15); no access to PC reg #endif @@ -273,7 +276,8 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst) LDRx_REG_LSL3(x2, x2, x3); UBFXx(x3, xRIP, 16, JMPTABL_SHIFT); LDRx_REG_LSL3(x2, x2, x3); - LDRx_REG_UXTW(x2, x2, xRIP); + UBFXx(x3, xRIP, 0, JMPTABL_SHIFT); + LDRx_REG_LSL3(x2, x2, x3); BR(x2); } @@ -295,7 +299,8 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n) LDRx_REG_LSL3(x2, x2, x3); UBFXx(x3, xRIP, 16, JMPTABL_SHIFT); LDRx_REG_LSL3(x2, x2, x3); - LDRx_REG_UXTW(x2, x2, xRIP); + UBFXx(x3, xRIP, 0, JMPTABL_SHIFT); + LDRx_REG_LSL3(x2, x2, x3); BR(x2); } diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index 5f1b8e20..1a576f7c 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -56,13 +56,13 @@ ed = x1; \ } //GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI -#define GETEDH(hint) if((nextop&0xC0)==0xC0) { \ - ed = xEAX+(nextop&7); \ - wback = 0; \ - } else { \ - addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0); \ - LDR_IMM9(hint, wback, fixedaddress); \ - ed = hint; \ +#define GETEDH(hint, D) if(MODREG) { \ + ed = xRAX+(nextop&7)+(rex.b<<3); \ + wback = 0; \ + } else { \ + addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \ + LDRxw_U12(hint, wback, fixedaddress); \ + ed = hint; \ } //GETEDW can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI #define GETEDW(hint, ret) if((nextop&0xC0)==0xC0) { \ @@ -652,10 +652,10 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in //void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); //void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); -//void emit_inc32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); +void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); //void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); //void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); -//void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); +void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); //void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); //void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); //void emit_adc32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); |