diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-19 16:16:23 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-19 16:16:23 +0100 |
| commit | f1625c0d928c6da87fa0c6e72cade44ad34565a0 (patch) | |
| tree | 070eb81cdc26905a7c454aa0917ab8d05b8ee83a | |
| parent | 5c4b0baf8b368c68a9e88a685d7427061d785211 (diff) | |
| download | box64-f1625c0d928c6da87fa0c6e72cade44ad34565a0.tar.gz box64-f1625c0d928c6da87fa0c6e72cade44ad34565a0.zip | |
[DYNAREC] Added 68 PUSH Id and fixed 80/7 cmp (but ThimbleweedPark, IntoTheBreach and WorldOfGoo are still broken, vvvvv works)
| -rwxr-xr-x | src/dynarec/arm64_emitter.h | 13 | ||||
| -rwxr-xr-x | src/dynarec/arm64_printer.c | 57 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_00.c | 17 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_0f.c | 2 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_emit_tests.c | 21 |
5 files changed, 93 insertions, 17 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h index ede5ef25..591968a6 100755 --- a/src/dynarec/arm64_emitter.h +++ b/src/dynarec/arm64_emitter.h @@ -146,7 +146,9 @@ #define SUBSx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd)) #define SUBx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, lsl, Rn, Rd)) #define SUBw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 1, 0, 0b00, Rm, 0, Rn, Rd)) +#define SUBw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 1, 0, 0b00, Rm, lsl, Rn, Rd)) #define SUBSw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, 0, Rn, Rd)) +#define SUBSw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, lsl, Rn, Rd)) #define SUBxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 1, 0, 0b00, Rm, 0, Rn, Rd)) #define SUBSxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b00, Rm, 0, Rn, Rd)) #define CMPSx_REG(Rn, Rm) SUBSx_REG(xZR, Rn, Rm) @@ -180,6 +182,10 @@ #define LDRB_S9_postindex(Rt, Rn, imm9) EMIT(LDR_gen(0b00, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt)) #define LDRB_S9_preindex(Rt, Rn, imm9) EMIT(LDR_gen(0b00, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt)) +#define LDRS_gen(size, op1, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt)) +#define LDRSW_S9_postindex(Rt, Rn, imm9) EMIT(LDRS_gen(0b10, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt)) +#define LDRSW_S9_preindex(Rt, Rn, imm9) EMIT(LDRS_gen(0b10, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt)) + #define LD_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b01<<22 | (imm12)<<10 | (Rn)<<5 | (Rt)) #define LDRx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b11, 0b01, ((uint32_t)(imm12>>3))&0xfff, Rn, Rt)) #define LDRw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt)) @@ -187,6 +193,9 @@ #define LDRH_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b01, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt)) #define LDRxw_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)(imm12>>(2+rex.w)))&0xfff, Rn, Rt)) +#define LDS_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm12)<<10 | (Rn)<<5 | (Rt)) +#define LDRSW_U12(Rt, Rn, imm12) EMIT(LDS_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt)) + #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)) @@ -197,8 +206,8 @@ #define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt)) #define LDRSH_gen(size, op1, opc, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt)) -#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b00, 0b10, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt)) -#define LDRSHw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b00, 0b11, ((uint32_t)(imm12>2))&0xfff, Rn, Rt)) +#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b00, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt)) +#define LDRSHw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b00, 0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt)) #define LDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | (imm19)<<5 | (Rt)) #define LDRx_literal(Rt, imm19) EMIT(LDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Rt)) diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c index e4782b47..0578d7f0 100755 --- a/src/dynarec/arm64_printer.c +++ b/src/dynarec/arm64_printer.c @@ -172,7 +172,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) } if(isMask(opcode, "0x011000iiiiiiiiiiiiiiiiiiittttt", &a)) { int size = ((opcode>>30)&1)?3:2; - int offset = signExtend(imm, 9)<<2; + int offset = signExtend(imm, 9)<<size; snprintf(buff, sizeof(buff), "LDR %s, [#%+d]\t;%p", (size==2)?Wt[Rt]:Xt[Rt], offset, (void*)(addr+offset)); return buff; } @@ -217,7 +217,48 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) 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; } - // --- MOV (REGS: see Logic MOV==ORR, MVN==ORN) + if(isMask(opcode, "0x111000010iiiiiiiii01nnnnnttttt", &a)) { + int size = a.x; + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDR%c %s, [%s], %s0x%x", size?'H':'B', Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "0x111000010iiiiiiiii11nnnnnttttt", &a)) { + int size = a.x; + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDR%c %s, [%s, %s0x%x]!", size?'H':'B', Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "0x11100101iiiiiiiiiiiinnnnnttttt", &a)) { + int size = a.x; + int offset = (imm)<<size; + if(offset) + snprintf(buff, sizeof(buff), "LDR%c %s, [%s, 0x%x]", size?'H':'B', Xt[Rt], XtSp[Rn], offset); + else + snprintf(buff, sizeof(buff), "LDR%c %s, [%s]", size?'H':'B', Xt[Rt], XtSp[Rn]); + return buff; + } + if(isMask(opcode, "0x111000000iiiiiiiii01nnnnnttttt", &a)) { + int size = a.x; + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "STR%c %s, [%s], %s0x%x", size?'H':'B', Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "0x111000000iiiiiiiii11nnnnnttttt", &a)) { + int size = a.x; + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "STR%c %s, [%s, %s0x%x]!", size?'H':'B', Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "0x11100100iiiiiiiiiiiinnnnnttttt", &a)) { + int size = a.x; + int offset = (imm)<<size; + if(offset) + snprintf(buff, sizeof(buff), "STR%c %s, [%s, 0x%x]", size?'H':'B', Xt[Rt], XtSp[Rn], offset); + else + snprintf(buff, sizeof(buff), "STR%c %s, [%s]", size?'H':'B', Xt[Rt], XtSp[Rn]); + return buff; + } // --- MOV (REGS: see Logic MOV==ORR, MVN==ORN) if(isMask(opcode, "f10100101wwiiiiiiiiiiiiiiiiddddd", &a)) { if(!hw) snprintf(buff, sizeof(buff), "MOVZ %s, 0x%x", sf?Xt[Rd]:Wt[Rd], imm); @@ -502,7 +543,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) else snprintf(buff, sizeof(buff), "BFI %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], lsb, width); } else - snprintf(buff, sizeof(buff), "BFM %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms); + snprintf(buff, sizeof(buff), "BFXIL %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1); return buff; } // ---- BRANCH / TEST @@ -534,6 +575,16 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) return buff; } + if(isMask(opcode, "f0011010100mmmmmcccc01nnnnnddddd", &a)) { + if(Rm!=31 && (cond&0b1110)!=0b1110 && Rn!=31 && Rn==Rm) + snprintf(buff, sizeof(buff), "CINC %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond^1]); + else if(Rm==31 && (cond&0b1110)!=0b1110 && Rn==31) + snprintf(buff, sizeof(buff), "CSET %s,%s", sf?Xt[Rd]:Wt[Rd], conds[cond^1]); + else + snprintf(buff, sizeof(buff), "CSINC %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond]); + return buff; + } + snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode)); return buff; } \ No newline at end of file diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c index b8c34ca8..6674b616 100755 --- a/src/dynarec/dynarec_arm64_00.c +++ b/src/dynarec/dynarec_arm64_00.c @@ -260,6 +260,20 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = dynarec64_66(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 0x68: + INST_NAME("PUSH Id"); + i64 = F32S; + if(PK(0)==0xC3) { + MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n"); + TABLE64(x3, ip+1); + LDRSW_U12(x1, x3, 0); + PUSH1(x1); + } else { + MOV64x(x3, i64); + PUSH1(x3); + } + break; + #define GO(GETFLAGS, NO, YES, F) \ READFLAGS(F); \ i8 = F8S; \ @@ -436,12 +450,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETEB(x1, 1); u8 = F8; if(u8) { - MOV32w(x2, u8); emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5); } else { emit_cmp8_0(dyn, ninst, x1, x3, x4); } break; + default: + DEFAULT; } break; case 0x81: diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c index 37393753..5270d981 100755 --- a/src/dynarec/dynarec_arm64_0f.c +++ b/src/dynarec/dynarec_arm64_0f.c @@ -94,7 +94,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETFLAGS; \ nextop=F8; \ GETGD; \ - if((nextop&0xC0)==0xC0) { \ + if(MODREG) { \ ed = xRAX+(nextop&7)+(rex.b<<3); \ CSELxw(gd, ed, gd, YES); \ } else { \ diff --git a/src/dynarec/dynarec_arm64_emit_tests.c b/src/dynarec/dynarec_arm64_emit_tests.c index a6430847..c0ebea21 100755 --- a/src/dynarec/dynarec_arm64_emit_tests.c +++ b/src/dynarec/dynarec_arm64_emit_tests.c @@ -34,8 +34,7 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 SET_DFNONE(s4); } IFX(X_AF) { - MVNxw_REG(s3, s1); - ORRxw_REG(s3, s3, s2); // s3 = ~op1 | op2 + ORNxw_REG(s3, s2, s1); // s3 = ~op1 | op2 BICxw(s4, s2, s1); // s4 = ~op1 & op2 } SUBSxw_REG(s5, s1, s2); // res = s1 - s2 @@ -212,25 +211,27 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in } else { SET_DFNONE(s4); } - SUBw_REG(s5, s1, s2); // res = s1 - s2 + IFX(X_ZF) { + SUBSw_REG(s5, s1, s2); // res = s1 - s2 + } else { + SUBw_REG(s5, s1, s2); // res = s1 - s2 + } IFX(X_PEND) { - STRB_REG(s5, xEmu, offsetof(x64emu_t, res)); + STRB_U12(s5, xEmu, offsetof(x64emu_t, res)); } IFX(X_ZF) { - ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff CSETw(s3, cEQ); BFIw(xFlags, s3, F_ZF, 1); } IFX(X_SF) { - LSRw(s5, s1, 7); - BFIw(xFlags, s5, F_SF, 1); + LSRw(s3, s5, 7); + BFIw(xFlags, s3, F_SF, 1); } // bc = (res & (~d | s)) | (~d & s) IFX(X_CF|X_AF|X_OF) { - MVNw_REG(s4, s1); // s4 = ~d - ORRw_REG(s4, s4, s2); // s4 = ~d | s + ORNw_REG(s4, s2, s1); // s4 = ~d | s ANDw_REG(s4, s4, s5); // s4 = res & (~d | s) - BICw_REG(s3, s2, s5); // s3 = s & ~d + BICw_REG(s3, s2, s1); // s3 = s & ~d ORRw_REG(s3, s4, s3); // s3 = (res & (~d | s)) | (s & ~d) IFX(X_CF) { LSRw(s4, s3, 7); |