diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-02-13 18:38:19 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-13 11:38:19 +0100 |
| commit | 95bdaf6eca65f3b45422c83abcf152c7022e6a26 (patch) | |
| tree | 5bc0a1db9eb913a7db303474b3023c789705797f /src | |
| parent | 9dc10bdc476e2a29f0755c5727e83f506a86a6f6 (diff) | |
| download | box64-95bdaf6eca65f3b45422c83abcf152c7022e6a26.tar.gz box64-95bdaf6eca65f3b45422c83abcf152c7022e6a26.zip | |
[RV64_DYNAREC] Minor fixes and improvements to TEST opcodes (#2352)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 14 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_tests.c | 59 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 |
3 files changed, 61 insertions, 14 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 0764618e..a3e4aee6 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -1111,10 +1111,18 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 1: INST_NAME("TEST Eb, Ib"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEB(x1, 1); + if (MODREG && (rex.rex || (((nextop & 7) >> 2) == 0))) { + // quick path for low 8bit registers + if (rex.rex) + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + else + ed = TO_NAT(nextop & 3); + } else { + GETEB(x1, 1); + ed = x1; + } u8 = F8; - MOV32w(x2, u8); - emit_test8(dyn, ninst, x1, x2, x6, x4, x5); + emit_test8c(dyn, ninst, ed, u8, x6, x4, x5); break; case 2: INST_NAME("NOT Eb"); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c index b122736c..1fa0b8ab 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c @@ -333,6 +333,42 @@ void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, } } +// emit TEST8 instruction, from test s1, c, using s3, s4 and s5 as scratch +void emit_test8c(dynarec_rv64_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4, int s5) +{ + CLEAR_FLAGS(); + IFX_PENDOR0 { + SET_DF(s3, d_tst8); + } else { + SET_DFNONE(); + } + + ANDI(s3, s1, c); // res = s1 & c + + IFX_PENDOR0 { + SD(s3, xEmu, offsetof(x64emu_t, res)); + } + + if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR); + + IFX (X_SF) { + SRLI(s4, s3, 7); + SET_FLAGS_NEZ(s4, F_SF, s5); + } + IFX (X_ZF) { + SET_FLAGS_EQZ(s3, F_ZF, s5); + } + IFX (X_PF) { + emit_pf(dyn, ninst, s3, s4, s5); + } + + NAT_FLAGS_ENABLE_SIGN(); + if (dyn->insts[ninst].nat_flags_fusion && dyn->insts[ninst].nat_flags_needsign) { + SLLI(s3, s3, 56); + SRAI(s3, s3, 56); + } +} + // emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) { @@ -387,8 +423,6 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int IFX (X_SF | X_ZF) { if (!rex.w) ZEROUP(s3); - } else if (dyn->insts[ninst].nat_flags_fusion) { - if (!rex.w) ZEROUP(s3); } if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR); @@ -407,10 +441,11 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int NAT_FLAGS_ENABLE_SIGN(); if (dyn->insts[ninst].nat_flags_fusion && !rex.w) { if (dyn->insts[ninst].nat_flags_needsign) { - SLLI(s3, s3, 32); - SRAI(s3, s3, 32); + SEXT_W(s3, s3); } else { - ZEROUP(s3); + IFX (X_SF | X_ZF) { + } else + ZEROUP(s3); } } } @@ -427,14 +462,15 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, if (c >= -2048 && c <= 2047) { ANDI(s3, s1, c); - IFX (X_SF | X_ZF) { - if (!rex.w && c < 0) ZEROUP(s3); - } } else { MOV64xw(s3, c); AND(s3, s1, s3); // res = s1 & s2 } + IFX (X_SF | X_ZF) { + if (!rex.w && c < 0) ZEROUP(s3); + } + IFX_PENDOR0 { SDxw(s3, xEmu, offsetof(x64emu_t, res)); } @@ -455,10 +491,11 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, NAT_FLAGS_ENABLE_SIGN(); if (dyn->insts[ninst].nat_flags_fusion && !rex.w) { if (dyn->insts[ninst].nat_flags_needsign) { - SLLI(s3, s3, 32); - SRAI(s3, s3, 32); + SEXT_W(s3, s3); } else { - ZEROUP(s3); + IFX (X_SF | X_ZF) { + } else if (c < 0) + ZEROUP(s3); } } } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 26820441..ca1e40d0 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1240,6 +1240,7 @@ void* rv64_next(void); #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_test32 STEPNAME(emit_test32) #define emit_test32c STEPNAME(emit_test32) @@ -1411,6 +1412,7 @@ void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); void emit_cmp16_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); +void emit_test8c(dynarec_rv64_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4, int s5); void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); |