diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-03-31 14:16:33 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-31 08:16:33 +0200 |
| commit | 275550a9c387a69a6d5b2e5824577d3e2e25df57 (patch) | |
| tree | 07e5a7e2e6dbece73329a94fbebab63bb89d8177 /src | |
| parent | 38cf61209e1a5adcb25053b5bac8a3684cc400af (diff) | |
| download | box64-275550a9c387a69a6d5b2e5824577d3e2e25df57.tar.gz box64-275550a9c387a69a6d5b2e5824577d3e2e25df57.zip | |
[RV64_DYNAREC] Added more SS opcodes (#654)
* [RV64_DYNAREC] Added F3 0F 5E DIVSS opcode * [RV64_DYNAREC] Small optim for 0F 2E,2F COMISS opcode * [RV64_DYNAREC] Added F3 0F C2 CMPSS opcode * [RV64_DYNAREC] Added 9C PUSHF opcode
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 5 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 18 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f30f.c | 53 |
3 files changed, 65 insertions, 11 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 61327703..4efb0a97 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -913,6 +913,11 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ZEROUP(xRDX); } break; + case 0x9C: + INST_NAME("PUSHF"); + READFLAGS(X_ALL); + PUSH1(xFlags); + break; case 0xA4: if(rep) { INST_NAME("REP MOVSB"); diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 84d0b0a6..8198682b 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -206,13 +206,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");} SETFLAGS(X_ALL, SF_SET); nextop = F8; - GETGX(x3); + GETGXSS(d0); GETEXSS(v0, 0); CLEAR_FLAGS(); - // if isnan(gd) || isnan(v0) + // if isnan(d0) || isnan(v0) IFX(X_ZF | X_PF | X_CF) { - FLW(gd, x3, 0); - FEQS(x3, gd, gd); + FEQS(x3, d0, d0); FEQS(x2, v0, v0); AND(x2, x2, x3); XORI(x2, x2, 1); @@ -221,21 +220,20 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni B_NEXT_nocond; } MARK; - // else if isless(gd, v0) + // else if isless(d0, v0) IFX(X_CF) { - FLTS(x2, gd, v0); + FLTS(x2, d0, v0); BEQ_MARK2(x2, xZR); ORI(xFlags, xFlags, 1<<F_CF); B_NEXT_nocond; } MARK2; - // else if gd == v0 + // else if d0 == v0 IFX(X_ZF) { - FEQS(x2, gd, v0); - BEQ_MARK3(x2, xZR); + FEQS(x2, d0, v0); + CBZ_NEXT(x2); ORI(xFlags, xFlags, 1<<F_ZF); } - MARK3; break; case 0x31: INST_NAME("RDTSC"); diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c index 31f19c64..41c3d62d 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f.c @@ -29,7 +29,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int uint8_t opcode = F8; uint8_t nextop, u8; uint8_t gd, ed; - uint8_t wback; + uint8_t wback, gback; uint64_t u64; int v0, v1; int q0, q1; @@ -126,6 +126,13 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEXSS(d0, 0); FSUBS(v0, v0, d0); break; + case 0x5E: + INST_NAME("DIVSS Gx, Ex"); + nextop = F8; + GETGXSS(v0); + GETEXSS(d0, 0); + FDIVS(v0, v0, d0); + break; case 0x7E: INST_NAME("MOVQ Gx, Ex"); nextop = F8; @@ -142,7 +149,51 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } SD(xZR, xEmu, offsetof(x64emu_t, xmm[gd])+8); break; + case 0xC2: + INST_NAME("CMPSS Gx, Ex, Ib"); + nextop = F8; + GETGXSS(d0); + GETEXSS(d1, 1); + u8 = F8; + if ((u8&7) == 0) { // Equal + FEQS(x2, d0, d1); + } else if ((u8&7) == 4) { // Not Equal or unordered + FEQS(x2, d0, d1); + XORI(x2, x2, 1); + } else { + // x2 = !(isnan(d0) || isnan(d1)) + FEQS(x3, d0, d0); + FEQS(x2, d1, d1); + AND(x2, x2, x3); + switch(u8&7) { + case 1: BEQ_MARK(x2, xZR); FLTS(x2, d0, d1); break; // Less than + case 2: BEQ_MARK(x2, xZR); FLES(x2, d0, d1); break; // Less or equal + case 3: XORI(x2, x2, 1); break; // NaN + case 5: { // Greater or equal or unordered + BEQ_MARK2(x2, xZR); + FLES(x2, d1, d0); + B_MARK_nocond; + break; + } + case 6: { // Greater or unordered, test inverted, N!=V so unordered or less than (inverted) + BEQ_MARK2(x2, xZR); + FLTS(x2, d1, d0); + B_MARK_nocond; + break; + } + case 7: break; // Not NaN + } + + MARK2; + if ((u8&7) == 5 || (u8&7) == 6) { + MOV32w(x2, 1); + } + MARK; + } + NEG(x2, x2); + FMVWX(d0, x2); + break; default: DEFAULT; } |