diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2024-08-16 18:10:17 +0800 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-08-16 18:47:21 +0200 |
| commit | bc0b5b118115d8b220fd16d03e2729d2fe3ebf2d (patch) | |
| tree | 58ce7198a498bcef477fbfe5cd73ef965e907a87 /src | |
| parent | 38833b9cf468c6297b858f382a826de7f1345a9a (diff) | |
| download | box64-bc0b5b118115d8b220fd16d03e2729d2fe3ebf2d.tar.gz box64-bc0b5b118115d8b220fd16d03e2729d2fe3ebf2d.zip | |
[LA64_DYNAREC] Port recent RV64 fixes (#1739)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 9 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 40 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_emit_shift.c | 41 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.c | 6 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 2 |
5 files changed, 55 insertions, 43 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index b2ceb004..c6145cf4 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -1664,16 +1664,17 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 5: if (opcode == 0xD0) { INST_NAME("SHR Eb, 1"); + GETEB(x1, 0); MOV32w(x2, 1); } else { INST_NAME("SHR Eb, CL"); + GETEB(x1, 0); ANDI(x2, xRCX, 0x1F); BEQ_NEXT(x2, xZR); } SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined if (box64_dynarec_safeflags > 1) MAYSETFLAGS(); - GETEB(x1, 0); emit_shr8(dyn, ninst, x1, x2, x5, x4, x6); EBBACK(); break; @@ -1733,7 +1734,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("ROL Ed, CL"); SETFLAGS(X_OF | X_CF, SF_SUBSET); GETED(0); - emit_rol32(dyn, ninst, rex, ed, xRCX, x3, x4); + ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); + emit_rol32(dyn, ninst, rex, ed, x6, x3, x4); WBACK; if (!wback && !rex.w) ZEROUP(ed); break; @@ -1741,7 +1743,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("ROR Ed, CL"); SETFLAGS(X_OF | X_CF, SF_SUBSET); GETED(0); - emit_ror32(dyn, ninst, rex, ed, xRCX, x3, x4); + ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); + emit_ror32(dyn, ninst, rex, ed, x6, x3, x4); WBACK; if (!wback && !rex.w) ZEROUP(ed); break; diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 0f795e61..7a0fbf7e 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -669,12 +669,17 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xA4: nextop = F8; INST_NAME("SHLD Ed, Gd, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); - GETED(1); - GETGD; - u8 = F8; - emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4); - WBACK; + if (geted_ib(dyn, addr, ninst, nextop)) { + SETFLAGS(X_ALL, SF_SET_PENDING); + GETED(1); + GETGD; + u8 = F8; + emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4); + WBACK; + } else { + FAKEED; + F8; + } break; case 0xAB: INST_NAME("BTS Ed, Gd"); @@ -716,13 +721,18 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xAC: nextop = F8; INST_NAME("SHRD Ed, Gd, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); - GETED(1); - GETGD; - u8 = F8; - u8 &= (rex.w ? 0x3f : 0x1f); - emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4); - WBACK; + if (geted_ib(dyn, addr, ninst, nextop)) { + SETFLAGS(X_ALL, SF_SET_PENDING); + GETED(1); + GETGD; + u8 = F8; + u8 &= (rex.w ? 0x3f : 0x1f); + emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4); + WBACK; + } else { + FAKEED; + F8; + } break; case 0xAE: nextop = F8; @@ -916,6 +926,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (wback) { SDxw(ed, wback, fixedaddress); SMWRITE(); + } else if (!rex.w) { + ZEROUP(ed); } MARK; break; @@ -935,6 +947,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (wback) { SDxw(ed, wback, fixedaddress); SMWRITE(); + } else if (!rex.w) { + ZEROUP(ed); } MARK; break; diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c index 291674eb..2b83ccba 100644 --- a/src/dynarec/la64/dynarec_la64_emit_shift.c +++ b/src/dynarec/la64/dynarec_la64_emit_shift.c @@ -514,7 +514,7 @@ void emit_sar16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, IFX (X_PEND) { ST_H(s2, xEmu, offsetof(x64emu_t, op2)); ST_H(s1, xEmu, offsetof(x64emu_t, op1)); - SET_DF(s4, d_sar8); + SET_DF(s4, d_sar16); } else IFX (X_ALL) { SET_DFNONE(); } @@ -612,6 +612,8 @@ void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, } OR(xFlags, xFlags, s3); } + // For the SAR instruction, the OF flag is cleared for all 1-bit shifts. + // OF nop if (rex.w) { SRAI_D(s1, s1, c); @@ -714,17 +716,11 @@ void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s X64_ROTL_W(s1, s2); } - if (rex.w) { - ANDI(s4, s2, 0x3f); - } else { - ANDI(s4, s2, 0x1f); - } - if (!rex.w) ZEROUP(s1); - BEQ_NEXT(s4, xZR); + BEQ_NEXT(s2, xZR); - SLLxw(s3, s1, s4); - NEG_D(s4, s4); + SLLxw(s3, s1, s2); + NEG_D(s4, s2); ADDI_D(s4, s4, rex.w ? 64 : 32); SRLxw(s1, s1, s4); OR(s1, s3, s1); @@ -745,12 +741,13 @@ void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } IFX (X_OF) { // the OF flag is set to the exclusive OR of the CF bit (after the rotate) and the most-significant bit of the result. - ADDI_D(s3, xZR, 1); - BNE_NEXT(s2, s3); + ADDI_D(s3, s2, -1); + BNEZ_MARK(s3); SRLIxw(s3, s1, rex.w ? 63 : 31); XOR(s3, s3, s4); // s3: MSB, s4: CF bit SLLI_D(s3, s3, F_OF); OR(xFlags, xFlags, s3); + MARK; } } @@ -759,13 +756,10 @@ void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; - if (rex.w) { - ANDI(s4, s2, 0x3f); - } else { - ANDI(s4, s2, 0x1f); + if (!rex.w) { ZEROUP(s1); } - BEQ_NEXT(s4, xZR); + BEQ_NEXT(s2, xZR); IFX (X_PEND) { SDxw(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, rex.w ? d_ror64 : d_ror32); @@ -775,15 +769,15 @@ void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFXA ((X_CF | X_OF), la64_lbt) { if (rex.w) - X64_ROTR_D(s1, s4); + X64_ROTR_D(s1, s2); else - X64_ROTR_W(s1, s4); + X64_ROTR_W(s1, s2); } if (rex.w) { - ROTR_D(s1, s1, s4); + ROTR_D(s1, s1, s2); } else { - ROTR_W(s1, s1, s4); + ROTR_W(s1, s1, s2); } IFX (X_PEND) { @@ -802,14 +796,15 @@ void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } IFX (X_OF) { // the OF flag is set to the exclusive OR of the two most-significant bits of the result - ADDI_D(s3, xZR, 1); - BNE_NEXT(s2, s3); + ADDI_D(s3, s2, -1); + BNEZ_MARK(s3); SRLIxw(s3, s1, rex.w ? 63 : 31); SRLIxw(s4, s1, rex.w ? 62 : 30); XOR(s3, s3, s4); ANDI(s3, s3, 1); SLLI_D(s3, s3, F_OF); OR(xFlags, xFlags, s3); + MARK; } } diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index b5b721fe..b597cfa6 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -133,7 +133,7 @@ uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, i64 = F32S; else i64 = F8S; - if (i64 == 0 || ((i64 >= -2048) && (i64 <= 2047) && i12)) { + if (i64 == 0 || ((i64 >= -2048) && (i64 <= maxval) && i12)) { *fixaddress = i64; if ((nextop & 7) == 4) { if (sib_reg != 4) { @@ -265,7 +265,7 @@ static uintptr_t geted_32(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_ i32 = F32S; else i32 = F8S; - if (i32 == 0 || ((i32 >= -2048) && (i32 <= 2047) && i12)) { + if (i32 == 0 || ((i32 >= -2048) && (i32 <= maxval) && i12)) { *fixaddress = i32; if ((nextop & 7) == 4) { if (sib_reg != 4) { @@ -413,7 +413,7 @@ uintptr_t geted32(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop i64 = F32S; else i64 = F8S; - if (i64 == 0 || ((i64 >= -2048) && (i64 <= 2047) && i12)) { + if (i64 == 0 || ((i64 >= -2048) && (i64 <= maxval) && i12)) { *fixaddress = i64; if ((nextop & 7) == 4) { if (sib_reg != 4) { diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 4e2d8653..9c1f6aa5 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -279,7 +279,7 @@ ed = i; \ } else { \ SMREAD(); \ - addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, D); \ + addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 1, D); \ LD_B(i, wback, fixedaddress); \ wb1 = 1; \ ed = i; \ |