diff options
| author | Yang Liu <numbksco@gmail.com> | 2024-05-23 00:22:08 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-22 18:22:08 +0200 |
| commit | 9edb89fc222e06e76e3299871bd7c34c9910879f (patch) | |
| tree | be87898e64aa5b0ebfeaa710eccd6b9dfa07fefb /src/dynarec | |
| parent | 3faabb478d2f5ccaec250273750bd4b6d6adabea (diff) | |
| download | box64-9edb89fc222e06e76e3299871bd7c34c9910879f.tar.gz box64-9edb89fc222e06e76e3299871bd7c34c9910879f.zip | |
[LA64_DYNAREC] Fixed LOCK XCHG byte opcode fallback path (#1519)
* [LA64_DYNAREC] Fixed LOCK XCHG byte opcode fallback path * fix
Diffstat (limited to 'src/dynarec')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index 3eb172ab..21936bb9 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -772,7 +772,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_test32(dyn, ninst, rex, ed, gd, x3, x4, x5); break; case 0x86: - INST_NAME("(LOCK)XCHG Eb, Gb"); + INST_NAME("(LOCK) XCHG Eb, Gb"); nextop = F8; if (MODREG) { GETGB(x1); @@ -786,9 +786,39 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AMSWAP_DB_B(x1, gd, ed); else { SMDMB(); - LD_BU(x1, ed, 0); - ST_B(gd, ed, 0); - SMDMB(); + + // calculate shift amount + ANDI(x1, ed, 0x3); + SLLI_D(x1, x1, 3); + + // align address to 4-bytes to use ll.w/sc.w + ADDI_D(x4, xZR, 0xffc); + AND(x6, ed, x4); + + // load aligned data + LD_WU(x5, x6, 0); + + // insert gd byte into the aligned data + ADDI_D(x4, xZR, 0xff); + SLL_D(x4, x4, x1); + NOR(x4, x4, xZR); + AND(x4, x5, x4); + SLL_D(x5, gd, x1); + OR(x4, x4, x5); + + // do aligned ll/sc sequence + MARKLOCK; + LL_W(x1, x6, 0); + MV(x5, x4); + SC_W(x5, x6, 0); + BEQZ_MARKLOCK(x5); + + // calculate shift amount again + ANDI(x4, ed, 0x3); + SLLI_D(x4, x4, 3); + + // extract loaded byte + SRL_D(x1, x1, x4); } BSTRINS_D(gb1, x1, gb2 + 7, gb2); } |