diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2024-02-22 17:39:33 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-22 10:39:33 +0100 |
| commit | f2eb5326af6eabe8b6196279f278f2975094d2d8 (patch) | |
| tree | f8279ee75c9f2f8dc9ccfc818f85665d396c0c4e /src | |
| parent | f09b541ab73dc7eb753a812c3fdd4d0cc17f7b02 (diff) | |
| download | box64-f2eb5326af6eabe8b6196279f278f2975094d2d8.tar.gz box64-f2eb5326af6eabe8b6196279f278f2975094d2d8.zip | |
[RV64_DYNAREC] Added more opcodes (#1276)
* Added 66 9C/9D PUSHF/POPF opcodes * Added 0F E2 PSRAD opcode * Fix * More readable
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_2.c | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 37 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 26 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 12 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 12 |
7 files changed, 68 insertions, 31 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index b59e832d..a4d19285 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -721,10 +721,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SET_DFNONE(x1); if(box64_wine) { // should this be done all the time? TBZ_NEXT(xFlags, F_TF); - MOV64x(x1, addr); - STORE_XEMU_CALL(x1); - CALL(native_singlestep, -1); - BFCw(xFlags, F_TF, 1); + // go to epilog, TF should trigger at end of next opcode, so using Interpretor only + jump_to_epilog(dyn, addr, 0, ninst); } break; diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index bea16d2d..bc6ae6c9 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -491,7 +491,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("POPF"); SETFLAGS(X_ALL, SF_SET); POP1z(xFlags); - FLAGS_ADJUST_FROM11(xFlags, x2); + FLAGS_ADJUST_FROM11(xFlags, xFlags, x2); MOV32w(x1, 0x3F7FD7); AND(xFlags, xFlags, x1); ORI(xFlags, xFlags, 0x2); diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index f048936c..f98aaec5 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -1861,6 +1861,25 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AND(x1, x1, x2); SD(x1, gback, gdoffset); break; + case 0xE2: + INST_NAME("PSRAD Gm, Em"); + nextop = F8; + GETGM(); + GETEM(x4, 0); + LBU(x1, wback, fixedaddress); + ADDI(x2, xZR, 31); + if (rv64_zbb) { + MINU(x1, x1, x2); + } else { + BLTU(x1, x2, 4 + 4); + MV(x1, x2); + } + for (int i = 0; i < 2; ++i) { + LW(x3, gback, gdoffset + 4 * i); + SRAW(x3, x3, x1); + SW(x3, gback, gdoffset + 4 * i); + } + break; case 0xE5: INST_NAME("PMULHW Gm,Em"); nextop = F8; @@ -1874,24 +1893,6 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SH(x3, gback, gdoffset + 2 * i); } break; - INST_NAME("PSUBSW Gm,Em"); - nextop = F8; - GETGM(); - GETEM(x2, 0); - for (int i = 0; i < 4; ++i) { - LH(x3, gback, gdoffset + i * 2); - LH(x4, wback, fixedaddress); - SUBW(x3, x3, x4); - LUI(x4, 0xFFFF8); // -32768 - BGE(x3, x4, 12); - SH(x4, gback, gdoffset + i * 2); - J(20); // continue - LUI(x4, 8); // 32768 - BLT(x3, x4, 8); - ADDIW(x3, x4, -1); - SH(x4, gback, gdoffset + i * 2); - } - break; case 0xE7: INST_NAME("MOVNTQ Em, Gm"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index bb7b34f4..59350bcb 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -641,6 +641,32 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SLLI(xRDX, xRDX, 16); OR(xRDX, xRDX, x1); break; + case 0x9C: + INST_NAME("PUSHF"); + NOTEST(x1); + READFLAGS(X_ALL); + FLAGS_ADJUST_TO11(x3, xFlags, x2); + PUSH1_16(x3); + break; + case 0x9D: + INST_NAME("POPF"); + SETFLAGS(X_ALL, SF_SET); + POP1_16(x1); + FLAGS_ADJUST_FROM11(x1, x1, x2); + LUI(x2, 0xffff0); + AND(xFlags, xFlags, x2); + OR(xFlags, xFlags, x1); + MOV32w(x1, 0x3F7FD7); + AND(xFlags, xFlags, x1); + ORI(xFlags, xFlags, 0x2); + SET_DFNONE(); + if (box64_wine) { // should this be done all the time? + ANDI(x1, xFlags, 1 << F_TF); + CBZ_NEXT(x1); + // go to epilog, TF should trigger at end of next opcode, so using Interpretor only + jump_to_epilog(dyn, addr, 0, ninst); + } + break; case 0xA1: INST_NAME("MOV EAX,Od"); if (rex.is32bits) u64 = F32; else u64 = F64; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 68b00042..1bb36b07 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -736,7 +736,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav fpu_popcache(dyn, ninst, reg, 0); if(saveflags) { LD(xFlags, xEmu, offsetof(x64emu_t, eflags)); - FLAGS_ADJUST_FROM11(xFlags, reg); + FLAGS_ADJUST_FROM11(xFlags, xFlags, reg); } SET_NODF(); dyn->last_ip = 0; @@ -799,7 +799,7 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) fpu_popcache(dyn, ninst, x3, 1); LD(xFlags, xEmu, offsetof(x64emu_t, eflags)); - FLAGS_ADJUST_FROM11(xFlags, x3); + FLAGS_ADJUST_FROM11(xFlags, xFlags, x3); SET_NODF(); } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 0a1dcfa6..9fd7267d 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -874,11 +874,11 @@ } \ } -// Adjust the xFlags bit 11 -> bit 5, result in reg (can be xFlags, but not s1) -#define FLAGS_ADJUST_FROM11(reg, s1) \ - ANDI(reg, xFlags, ~(1 << 5)); \ - SRLI(s1, reg, 11 - 5); \ - ANDI(s1, s1, 1 << 5); \ +// Adjust the flags bit 11 -> bit 5, result in reg (can be same as flags, but not s1) +#define FLAGS_ADJUST_FROM11(reg, flags, s1) \ + ANDI(reg, flags, ~(1 << 5)); \ + SRLI(s1, reg, 11 - 5); \ + ANDI(s1, s1, 1 << 5); \ OR(reg, reg, s1) // Adjust the xFlags bit 5 -> bit 11, src and dst can be the same (and can be xFlags, but not s1) @@ -934,7 +934,7 @@ BEQ(x3, xZR, j64); \ } \ CALL_(UpdateFlags, -1, 0); \ - FLAGS_ADJUST_FROM11(xFlags, x3); \ + FLAGS_ADJUST_FROM11(xFlags, xFlags, x3); \ MARKF; \ dyn->f.pending = SF_SET; \ SET_DFOK(); \ diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index fdbfdfe3..6b675f6e 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -376,6 +376,18 @@ f28–31 ft8–11 FP temporaries Caller PUSH1(reg); \ } +#define PUSH1_16(reg) \ + do { \ + SH(reg, xRSP, -2); \ + SUBI(xRSP, xRSP, 2); \ + } while (0) + +#define POP1_16(reg) \ + do { \ + LHU(reg, xRSP, 0); \ + if (reg != xRSP) ADDI(xRSP, xRSP, 2); \ + } while (0) + #define FENCE_gen(pred, succ) (((pred) << 24) | ((succ) << 20) | 0b0001111) #define FENCE() EMIT(FENCE_gen(3, 3)) |