diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-20 14:52:45 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-20 14:52:45 +0100 |
| commit | 4b3e632d14667af1a81e2a3125b5f1ee7d979fc6 (patch) | |
| tree | 37f0c60d841d096fd8809b5cc014b65ff681a30a /src | |
| parent | b52b3219696b851e96dc8d2e6543e91dbba909ff (diff) | |
| download | box64-4b3e632d14667af1a81e2a3125b5f1ee7d979fc6.tar.gz box64-4b3e632d14667af1a81e2a3125b5f1ee7d979fc6.zip | |
[DYNAREC] Added 66 F7 opcodes
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64_emitter.h | 6 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64.c | 2 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_66.c | 62 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_emit_math.c | 91 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_emit_tests.c | 65 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 5 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_pass2.h | 2 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_pass3.h | 2 |
8 files changed, 146 insertions, 89 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h index 100b0d74..ee83b14e 100755 --- a/src/dynarec/arm64_emitter.h +++ b/src/dynarec/arm64_emitter.h @@ -388,11 +388,11 @@ #define BFCw(Rd, lsb, width) BFMw(Rd, xZR, ((-lsb)%32)&0x1f, (width)-1) #define BFCxw(Rd, lsb, width) BFMxw(Rd, xZR, rex.w?(((-lsb)%64)&0x3f):(((-lsb)%32)&0x1f), (width)-1) // Insert lsb:width part of Rn into low part of Rd (leaving rest of Rd untouched) -#define BFXILx(Rd, Rn, lsb, width) BFM_gen(1, 0b01, 1, (lsb), (lsb)+(width)-1, Rn, Rd) +#define BFXILx(Rd, Rn, lsb, width) EMIT(BFM_gen(1, 0b01, 1, (lsb), (lsb)+(width)-1, Rn, Rd)) // Insert lsb:width part of Rn into low part of Rd (leaving rest of Rd untouched) -#define BFXILw(Rd, Rn, lsb, width) BFM_gen(0, 0b01, 0, (lsb), (lsb)+(width)-1, Rn, Rd) +#define BFXILw(Rd, Rn, lsb, width) EMIT(BFM_gen(0, 0b01, 0, (lsb), (lsb)+(width)-1, Rn, Rd)) // Insert lsb:width part of Rn into low part of Rd (leaving rest of Rd untouched) -#define BFXILxw(Rd, Rn, lsb, width) BFM_gen(rex.w, 0b01, rex.w, (lsb), (lsb)+(width)-1, Rn, Rd) +#define BFXILxw(Rd, Rn, lsb, width) EMIT(BFM_gen(rex.w, 0b01, rex.w, (lsb), (lsb)+(width)-1, Rn, Rd)) // 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/dynarec_arm64.c b/src/dynarec/dynarec_arm64.c index 79082ce0..679bc1e1 100755 --- a/src/dynarec/dynarec_arm64.c +++ b/src/dynarec/dynarec_arm64.c @@ -399,6 +399,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":""); } helper.arm_size = 0; + int oldtable64size = helper.table64size; arm_pass3(&helper, addr); if(sz!=(helper.arm_size + helper.table64size*8)) { printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size+helper.table64size*8); @@ -410,6 +411,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) { printf_log(LOG_NONE, " %02X", *dump); printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size); } + printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8); printf_log(LOG_NONE, " ------------\n"); } // add table64 if needed diff --git a/src/dynarec/dynarec_arm64_66.c b/src/dynarec/dynarec_arm64_66.c index e2ad11e6..2722dbc6 100755 --- a/src/dynarec/dynarec_arm64_66.c +++ b/src/dynarec/dynarec_arm64_66.c @@ -160,6 +160,68 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; + case 0xF7: + nextop = F8; + switch((nextop>>3)&7) { + case 0: + case 1: + INST_NAME("TEST Ew, Iw"); + SETFLAGS(X_ALL, SF_SET); + GETEW(x1, 2); + u16 = F16; + MOV32w(x2, u16); + emit_test16(dyn, ninst, x1, x2, x3, x4, x5); + break; + case 2: + INST_NAME("NOT Ew"); + GETEW(x1, 0); + MVNw_REG(ed, ed); + EWBACK; + break; + case 3: + INST_NAME("NEG Ew"); + SETFLAGS(X_ALL, SF_SET); + GETEW(x1, 0); + emit_neg16(dyn, ninst, ed, x2, x4); + EWBACK; + break; + case 4: + INST_NAME("MUL AX, Ew"); + SETFLAGS(X_ALL, SF_PENDING); + UFLAG_DF(x1, d_mul16); + GETEW(x1, 0); + UXTHw(x2, xRAX); + MULw(x1, x2, x1); + UFLAG_RES(x1); + BFIx(xRAX, x1, 0, 16); + BFXILx(xRDX, x1, 16, 16); + break; + case 5: + INST_NAME("IMUL AX, Ew"); + SETFLAGS(X_ALL, SF_PENDING); + UFLAG_DF(x1, d_imul16); + GETSEW(x1, 0); + SXTHw(x2, xRAX); + MULw(x1, x2, x1); + UFLAG_RES(x1); + BFIx(xRAX, x1, 0, 16); + BFXILx(xRDX, x1, 16, 16); + break; + case 6: + INST_NAME("DIV Ew"); + SETFLAGS(X_ALL, SF_SET); + GETEW(x1, 0); + CALL(div16, -1); + break; + case 7: + INST_NAME("IDIV Ew"); + SETFLAGS(X_ALL, SF_SET); + GETEW(x1, 0); + CALL(idiv16, -1); + break; + } + break; + default: DEFAULT; } diff --git a/src/dynarec/dynarec_arm64_emit_math.c b/src/dynarec/dynarec_arm64_emit_math.c index d76ded05..932af359 100755 --- a/src/dynarec/dynarec_arm64_emit_math.c +++ b/src/dynarec/dynarec_arm64_emit_math.c @@ -1780,53 +1780,50 @@ void emit_neg32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4 } // emit NEG16 instruction, from s1, store result in s1 using s3 and s4 as scratch -//void emit_neg16(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(s3, d_neg16); -// } else IFX(X_ALL) { -// SET_DFNONE(s3); -// } -// IFX(X_ZF|X_CF) { -// BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0); -// } -// IFX(X_CF) { -// TSTS_REG_LSL_IMM5(s1, s1, 0); -// ORR_IMM8_COND(cNE, xFlags, xFlags, 1<<F_CF, 0); -// } -// IFX(X_AF|X_OF) { -// MOV_REG_LSL_IMM5(s3, s1, 0); -// } -// RSB_IMM8(s1, s1, 0); -// IFX(X_PEND) { -// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res)); -// } -// IFX(X_AF|X_OF) { -// ORR_REG_LSL_IMM5(s3, s3, s1, 0); // bc = op1 | res -// IFX(X_AF) { -// MOV_REG_LSR_IMM5(s4, s3, 3); -// BFI(xFlags, s4, F_AF, 1); // AF: bc & 0x08 -// } -// IFX(X_OF) { -// MOV_REG_LSR_IMM5(s4, s3, 14); -// XOR_REG_LSR_IMM8(s4, s4, s4, 1); -// BFI(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1 -// } -// } -// IFX(X_ZF) { -// UXTH(s1, s1, 0); -// TSTS_REG_LSL_IMM5(s1, s1, 0); -// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0); -// } -// IFX(X_SF) { -// MOV_REG_LSR_IMM5(s3, s1, 15); -// BFI(xFlags, s3, F_SF, 1); -// } -// IFX(X_PF) { -// emit_pf(dyn, ninst, s1, s3, s4); -// } -//} +void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) +{ + IFX(X_PEND) { + STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s3, d_neg16); + } else IFX(X_ALL) { + SET_DFNONE(s3); + } + IFX(X_CF) { + TSTw_REG(s1, s1); + CSETw(s4, cNE); + BFIw(xFlags, s4, F_CF, 1); + } + IFX(X_AF|X_OF) { + MOVw_REG(s3, s1); + } + NEGSw_REG(s1, s1); + IFX(X_PEND) { + STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_AF|X_OF) { + ORRw_REG(s3, s3, s1); // bc = op1 | res + IFX(X_AF) { + LSRw(s4, s3, 3); + BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08 + } + IFX(X_OF) { + LSRw(s4, s3, 14); + EORw_REG_LSR(s4, s4, s4, 1); + BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1 + } + } + IFX(X_ZF) { + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } + IFX(X_SF) { + LSRw(s3, s1, 15); + BFIw(xFlags, s3, F_SF, 1); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} // emit NEG8 instruction, from s1, store result in s1 using s3 and s4 as scratch //void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) diff --git a/src/dynarec/dynarec_arm64_emit_tests.c b/src/dynarec/dynarec_arm64_emit_tests.c index c0ebea21..14b9eac1 100755 --- a/src/dynarec/dynarec_arm64_emit_tests.c +++ b/src/dynarec/dynarec_arm64_emit_tests.c @@ -320,41 +320,36 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } // emit TEST16 instruction, from test s1 , s2, using s3 and s4 as scratch -//void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) -//{ -// IFX(X_PEND) { -// SET_DF(s3, d_tst16); -// } else { -// SET_DFNONE(s4); -// } -// IFX(X_OF) { -// BFC(xFlags, F_OF, 1); -// } -// IFX(X_ZF|X_CF) { -// BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0); -// } -// ANDS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 & s2 -// IFX(X_PEND) { -// STR_IMM9(s3, xEmu, offsetof(x64emu_t, res)); -// } -// IFX(X_ZF) { -// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0); -// } -// IFX(X_SF) { -// MOV_REG_LSR_IMM5(s4, s3, 15); -// BFI(xFlags, s4, F_SF, 1); -// } -// // PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0) -// IFX(X_PF) { -// AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied -// MOV32(s4, GetParityTab()); -// LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer -// AND_REG_LSL_IMM5(s3, s1, s2, 0); -// AND_IMM8(s3, s3, 31); -// MVN_REG_LSR_REG(s4, s4, s3); -// BFI(xFlags, s4, F_PF, 1); -// } -//} +void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +{ + IFX(X_PEND) { + SET_DF(s3, d_tst16); + } else { + SET_DFNONE(s4); + } + IFX(X_OF) { + BFCw(xFlags, F_OF, 1); + } + IFX(X_CF) { + BFCw(xFlags, F_CF, 1); + } + ANDSw_REG(s5, s1, s2); // res = s1 & s2 + IFX(X_PEND) { + STRH_U12(s5, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_ZF) { + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } + IFX(X_SF) { + LSRw(s4, s5, 15); + BFIw(xFlags, s4, F_SF, 1); + } + // PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0) + IFX(X_PF) { + emit_pf(dyn, ninst, s5, s3, s4); + } +} // emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch //void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index ac26870e..fed7c411 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -446,6 +446,7 @@ #define GETIP(A) #define GETIP_(A) #else +// put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later... #define GETIP(A) \ if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) { \ uint64_t _delta_ip = (A)-dyn->last_ip; \ @@ -637,7 +638,7 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); //void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); //void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); -//void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); @@ -688,7 +689,7 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4 //void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4); //void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_neg32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); -//void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); +void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); //void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4); diff --git a/src/dynarec/dynarec_arm64_pass2.h b/src/dynarec/dynarec_arm64_pass2.h index 838ed665..7f1d0de1 100755 --- a/src/dynarec/dynarec_arm64_pass2.h +++ b/src/dynarec/dynarec_arm64_pass2.h @@ -7,4 +7,4 @@ #define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size; #define INST_NAME(name) #define NEW_BARRIER_INST if(ninst) ++dyn->sons_size -#define TABLE64(A, V) if((V)>0xffffffffL) {Table64(dyn, (V)); EMIT(0);} else {MOV64x(A, V);} \ No newline at end of file +#define TABLE64(A, V) if((V)>0xffffffffLL) {Table64(dyn, (V)); EMIT(0);} else {MOV64x(A, V);} \ No newline at end of file diff --git a/src/dynarec/dynarec_arm64_pass3.h b/src/dynarec/dynarec_arm64_pass3.h index f58e9364..74784196 100755 --- a/src/dynarec/dynarec_arm64_pass3.h +++ b/src/dynarec/dynarec_arm64_pass3.h @@ -32,4 +32,4 @@ ++dyn->sons_size; \ } -#define TABLE64(A, V) if((V)>0xffffffffL) {int val64offset = Table64(dyn, (V)); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);} else {MOV64x(A, V);} \ No newline at end of file +#define TABLE64(A, V) if((V)>0xffffffffLL) {int val64offset = Table64(dyn, (V)); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);} else {MOV64x(A, V);} \ No newline at end of file |