diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-11-14 18:54:40 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-11-14 18:54:40 +0100 |
| commit | 8c17a37d1ae4258e7a7a7fdf87a43305f40dc2a1 (patch) | |
| tree | cc5e5cfb52ca5ca707e8a26b9a4dbc4b0fc2a324 /src | |
| parent | 979a3232f9d23c34b6c8c86fb3913fb34b3da333 (diff) | |
| download | box64-8c17a37d1ae4258e7a7a7fdf87a43305f40dc2a1.tar.gz box64-8c17a37d1ae4258e7a7a7fdf87a43305f40dc2a1.zip | |
[ARM64_DYNAREC] Reworked 8/16/32/64bits TEST opcodes
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/arm64_emitter.h | 1 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_64.c | 3 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_67.c | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_tests.c | 243 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_f0.c | 3 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 6 |
8 files changed, 236 insertions, 38 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index a4269283..ec16b71b 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -598,6 +598,7 @@ int convert_bitmask(uint64_t bitmask); #define ANDSx_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(1, 0b11, 0b00, 0, Rm, 0, Rn, Rd)) #define ANDSw_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, 0, Rn, Rd)) #define ANDSxw_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(rex.w, 0b11, 0b00, 0, Rm, 0, Rn, Rd)) +#define ANDSw_REG_LSL(Rd, Rn, Rm, lsl) FEMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, lsl, Rn, Rd)) #define ORRx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, 0, Rn, Rd)) #define ORRx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, lsl, Rn, Rd)) #define ORRw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, lsl, Rn, Rd)) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index f1bc34f7..cd886163 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1690,8 +1690,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("TEST EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING); i64 = F32S; - MOV64xw(x2, i64); - emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); + emit_test32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5); break; case 0xAA: WILLWRITE(); @@ -3335,8 +3334,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEDH(x1, 4); i64 = F32S; - MOV64xw(x2, i64); - emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5); + emit_test32c(dyn, ninst, rex, ed, i64, x3, x4, x5); break; case 2: INST_NAME("NOT Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c index 9ad0be88..636b9b02 100644 --- a/src/dynarec/arm64/dynarec_arm64_64.c +++ b/src/dynarec/arm64/dynarec_arm64_64.c @@ -1306,8 +1306,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEDO(x6, 4); i64 = F32S; - MOV64xw(x2, i64); - emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5); + emit_test32c(dyn, ninst, rex, ed, i64, x3, x4, x5); break; case 2: INST_NAME("NOT Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index 0c6ef67b..c6e209c5 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -860,9 +860,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("TEST AX,Iw"); SETFLAGS(X_ALL, SF_SET_PENDING); u16 = F16; - MOV32w(x2, u16); UBFXx(x1, xRAX, 0, 16); - emit_test16(dyn, ninst, x1, x2, x3, x4, x5); + emit_test16c(dyn, ninst, x1, u16, x3, x4, x5); break; case 0xAB: @@ -1329,8 +1328,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEW(x1, 2); u16 = F16; - MOV32w(x2, u16); - emit_test16(dyn, ninst, x1, x2, x3, x4, x5); + emit_test16c(dyn, ninst, x1, u16, x3, x4, x5); break; case 2: INST_NAME("NOT Ew"); diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index a77d88a5..bce01f5c 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -1204,8 +1204,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("TEST EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING); i64 = F32S; - MOV64xw(x2, i64); - emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); + emit_test32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5); break; case 0xC1: @@ -1445,8 +1444,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETED32H(x1, 4); i64 = F32S; - MOV64xw(x2, i64); - emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5); + emit_test32c(dyn, ninst, rex, ed, i64, x3, x4, x5); break; case 2: INST_NAME("NOT Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_emit_tests.c b/src/dynarec/arm64/dynarec_arm64_emit_tests.c index 77937ab0..1c78fa53 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_tests.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_tests.c @@ -354,22 +354,37 @@ 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, s4 and s5 as scratch -void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch +void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5) { - MAYUSE(s1); MAYUSE(s2); + MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + int mask = convert_bitmask_xw(c); IFX_PENDOR0 { - SET_DF(s3, d_tst16); + SET_DF(s3, rex.w?d_tst64:d_tst32); } else { SET_DFNONE(s4); } - IFX(X_CF | X_AF | X_OF) { - MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF)); - BICw(xFlags, xFlags, s3); + IFX(X_CF) { + IFNATIVE(NF_CF) {} else { + BFCw(xFlags, F_CF, 1); + } + } + IFX(X_OF) { + IFNATIVE(NF_VF) {} else { + BFCw(xFlags, F_OF, 1); + } + } + IFX(X_AF) { + BFCw(xFlags, F_AF, 1); + } + if(mask) { + ANDSxw_mask(s3, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F); + } else { + MOV64xw(s3, c); + ANDSxw_REG(s3, s1, s3); // res = s1 & s2 } - ANDSw_REG(s5, s1, s2); // res = s1 & s2 IFX_PENDOR0 { - STRH_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRxw_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { @@ -378,8 +393,117 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, } } IFX(X_SF) { - LSRw(s4, s5, 15); - BFIw(xFlags, s4, F_SF, 1); + IFNATIVE(NF_SF) {} else { + LSRxw(s4, s3, rex.w?63:31); + BFIw(xFlags, s4, F_SF, 1); + } + } + IFX(X_PF) { + emit_pf(dyn, ninst, s3, s5); + } +} + +// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch +void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +{ + MAYUSE(s1); MAYUSE(s2); + IFX_PENDOR0 { + SET_DF(s3, d_tst16); + } else { + SET_DFNONE(s4); + } + IFX(X_CF|X_ZF|X_SF|X_OF) { + LSLw(s5, s1, 16); + ANDSw_REG_LSL(s5, s5, s2, 16); + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } + } + IFX(X_CF) { + IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);} + } + IFX(X_OF) { + IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);} + } + IFX(X_SF) { + IFNATIVE(NF_SF) {} else { + CSETw(s4, cMI); + BFIw(xFlags, s4, F_SF, 1); + } + } + IFX(X_PF|X_PEND) { + LSRw(s5, s5, 16); + } + } else { + ANDw_REG(s5, s1, s2); // res = s1 & s2 + } + IFX(X_AF) { + BFCw(xFlags, F_AF, 1); + } + IFX_PENDOR0 { + STRH_U12(s5, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s5, s4); + } +} + +// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch +void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5) +{ + MAYUSE(s1); + int mask = 0; + IFX_PENDOR0 { + SET_DF(s3, d_tst16); + } else { + SET_DFNONE(s4); + } + IFX(X_CF|X_ZF|X_SF|X_OF) { + LSLw(s5, s1, 16); + mask = convert_bitmask_w(c<<16); + if(mask) { + ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F); + } else { + MOV32w(s3, c); + ANDSw_REG_LSL(s5, s5, s3, 16); + } + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } + } + IFX(X_CF) { + IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);} + } + IFX(X_OF) { + IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);} + } + IFX(X_SF) { + IFNATIVE(NF_SF) {} else { + CSETw(s4, cMI); + BFIw(xFlags, s4, F_SF, 1); + } + } + IFX(X_PF|X_PEND) { + LSRw(s5, s5, 16); + } + } else { + mask = convert_bitmask_w(c); + if(mask) { + ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F); + } else { + MOV32w(s5, c); + ANDw_REG(s5, s1, s5); // res = s1 & s2 + } + } + IFX(X_AF) { + BFCw(xFlags, F_AF, 1); + } + IFX_PENDOR0 { + STRH_U12(s5, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { emit_pf(dyn, ninst, s5, s4); @@ -395,23 +519,98 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i } else { SET_DFNONE(s4); } - IFX(X_CF | X_AF | X_OF) { - MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF)); - BICw(xFlags, xFlags, s3); + IFX(X_CF|X_ZF|X_SF|X_OF) { + LSLw(s5, s1, 24); + ANDSw_REG_LSL(s5, s5, s2, 24); + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } + } + IFX(X_CF) { + IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);} + } + IFX(X_OF) { + IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);} + } + IFX(X_SF) { + IFNATIVE(NF_SF) {} else { + CSETw(s4, cMI); + BFIw(xFlags, s4, F_SF, 1); + } + } + IFX(X_PF|X_PEND) { + LSRw(s5, s5, 24); + } + } else { + ANDw_REG(s5, s1, s2); // res = s1 & s2 + } + IFX(X_AF) { + BFCw(xFlags, F_AF, 1); } - ANDSw_REG(s5, s1, s2); // res = s1 & s2 IFX_PENDOR0 { STRB_U12(s5, xEmu, offsetof(x64emu_t, res)); } - IFX(X_ZF) { - IFNATIVE(NF_EQ) {} else { - CSETw(s4, cEQ); - BFIw(xFlags, s4, F_ZF, 1); + IFX(X_PF) { + emit_pf(dyn, ninst, s5, s4); + } +} + +// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch +void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5) +{ + MAYUSE(s1); + int mask = 0; + IFX_PENDOR0 { + SET_DF(s3, d_tst8); + } else { + SET_DFNONE(s4); + } + IFX(X_CF|X_ZF|X_SF|X_OF) { + LSLw(s5, s1, 24); + mask = convert_bitmask_w(c<<24); + if(mask) { + ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F); + } else { + MOV32w(s3, c); + ANDSw_REG_LSL(s5, s5, s3, 24); + } + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } + } + IFX(X_CF) { + IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);} + } + IFX(X_OF) { + IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);} + } + IFX(X_SF) { + IFNATIVE(NF_SF) {} else { + CSETw(s4, cMI); + BFIw(xFlags, s4, F_SF, 1); + } + } + IFX(X_PF|X_PEND) { + LSRw(s5, s5, 24); + } + } else { + mask = convert_bitmask_w(c); + if(mask) { + ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F); + } else { + MOV32w(s5, c); + ANDw_REG(s5, s1, s5); // res = s1 & s2 } } - IFX(X_SF) { - LSRw(s4, s5, 7); - BFIw(xFlags, s4, F_SF, 1); + IFX(X_AF) { + BFCw(xFlags, F_AF, 1); + } + IFX_PENDOR0 { + STRB_U12(s5, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { emit_pf(dyn, ninst, s5, s4); diff --git a/src/dynarec/arm64/dynarec_arm64_f0.c b/src/dynarec/arm64/dynarec_arm64_f0.c index 26f594d8..00cb91f2 100644 --- a/src/dynarec/arm64/dynarec_arm64_f0.c +++ b/src/dynarec/arm64/dynarec_arm64_f0.c @@ -1579,8 +1579,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SMDMB(); GETEB(x1, 1); u8 = F8; - MOV32w(x2, u8); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8c(dyn, ninst, x1, u8, x3, x4, x5); break; case 2: INST_NAME("LOCK NOT Eb"); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index 5b4e5c1d..803e15e1 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1275,8 +1275,11 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr); #define emit_cmp16_0 STEPNAME(emit_cmp16_0) #define emit_cmp32_0 STEPNAME(emit_cmp32_0) #define emit_test8 STEPNAME(emit_test8) +#define emit_test8c STEPNAME(emit_test8c) #define emit_test16 STEPNAME(emit_test16) +#define emit_test16c STEPNAME(emit_test16c) #define emit_test32 STEPNAME(emit_test32) +#define emit_test32c STEPNAME(emit_test32c) #define emit_add32 STEPNAME(emit_add32) #define emit_add32c STEPNAME(emit_add32c) #define emit_add8 STEPNAME(emit_add8) @@ -1440,8 +1443,11 @@ 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, int s5); +void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5); void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); +void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, 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, int s5); +void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); 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); void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); |