diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-05-04 23:10:02 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-04 17:10:02 +0200 |
| commit | f7326b05333b8b9ec4fa93f05f585505a3a3e63e (patch) | |
| tree | 176ccf01f9490025215bcb9e10fdd70de0f9bffe | |
| parent | dbde650339a74b6dd09a7895679ca5c704b31a76 (diff) | |
| download | box64-f7326b05333b8b9ec4fa93f05f585505a3a3e63e.tar.gz box64-f7326b05333b8b9ec4fa93f05f585505a3a3e63e.zip | |
[RV64_DYNAREC] Added more opcode for Unciv and some fixes (#759)
* Added F2 AF SCASD opcode * Added DD FST opcode * Added DC FCOMP opcode * Added DD FFREE opcode * Added 66 0F 3A 21 INSERTPS opcode
| -rwxr-xr-x | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_2.c | 42 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 18 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_d8.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_dc.c | 112 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_dd.c | 11 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 |
8 files changed, 186 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b9841e1..b0af3605 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -639,7 +639,7 @@ if(RV64_DYNAREC) "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c" #"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_da.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_db.c" - #"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dc.c" + "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dc.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dd.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_de.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_df.c" diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index 0e9144b7..ec296574 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -690,8 +690,8 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING); CBZ_NEXT(xRCX); ANDI(x1, xRAX, 0xff); - ANDI(x1, xFlags, 1<<F_DF); - BNEZ_MARK2(x1); + ANDI(x2, xFlags, 1<<F_DF); + BNEZ_MARK2(x2); MARK; // Part with DF==0 LBU(x2, xRDI, 0); ADDI(xRDI, xRDI, 1); @@ -719,6 +719,44 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; } break; + case 0xAF: + switch (rep) { + case 1: + case 2: + if (rep==1) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");} + MAYSETFLAGS(); + SETFLAGS(X_ALL, SF_SET_PENDING); + CBZ_NEXT(xRCX); + if (rex.w) {MV(x1, xRAX);} else {AND(x1, xRAX, xMASK);} + ANDI(x2, xFlags, 1<<F_DF); + BNEZ_MARK2(x2); + MARK; // Part with DF==0 + LDxw(x2, xRDI, 0); + ADDI(xRDI, xRDI, rex.w?8:4); + SUBI(xRCX, xRCX, 1); + if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);} + BNE_MARK(xRCX, xZR); + B_MARK3_nocond; + MARK2; // Part with DF==1 + LDxw(x2, xRDI, 0); + SUBI(xRDI, xRDI, rex.w?8:4); + SUBI(xRCX, xRCX, 1); + if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);} + BNE_MARK2(xRCX, xZR); + MARK3; // end + emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6); + break; + default: + INST_NAME("SCASD"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETDIR(x3, x1, rex.w?8:4); + AND(x1, xRAX, xMASK); + LDxw(x2, xRDI, 0); + ADD(xRDI, xRDI, x3); + emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6); + break; + } + break; case 0xB0: case 0xB1: case 0xB2: diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 90332b60..4a548677 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -537,7 +537,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xDB: addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; - + case 0xDC: + addr = dynarec64_DC(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + break; case 0xDD: addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 08303f44..742a1209 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -27,7 +27,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int (void)ip; (void)need_epilog; uint8_t opcode = F8; - uint8_t nextop, u8; + uint8_t nextop, u8, s8; int32_t i32; uint8_t gd, ed; uint8_t wback, wb1, wb2, gback; @@ -466,6 +466,22 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 = F8; SB(ed, x3, u8&0xF); break; + case 0x21: + INST_NAME("INSERTPS GX, EX, Ib"); + nextop = F8; + GETGX(x1); + GETEX(x2, 1); + u8 = F8; + if(MODREG) s8 = (u8>>6)&3; else s8 = 0; + // GX->ud[(tmp8u>>4)&3] = EX->ud[tmp8s]; + LWU(x3, wback, fixedaddress+4*s8); + SW(x3, gback, 4*(u8>>4)); + for(int i=0; i<4; ++i) { + if(u8&(1<<i)) + // GX->ud[i] = 0; + SW(xZR, gback, 4*i); + } + break; case 0x22: INST_NAME("PINSRD Gx, ED, Ib"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_d8.c b/src/dynarec/rv64/dynarec_rv64_d8.c index 3a66bba4..c3c10166 100644 --- a/src/dynarec/rv64/dynarec_rv64_d8.c +++ b/src/dynarec/rv64/dynarec_rv64_d8.c @@ -62,7 +62,7 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AND(x5, x5, x4); BEQZ(x5, 24); // undefined/NaN FEQS(x5, v1, v2); - BNEZ(x5, 24); // equal + BNEZ(x5, 28); // equal FLTS(x3, v1, v2); // x3 = (v1<v2)?1:0 SLLI(x1, x3, 8); J(20); // end @@ -79,7 +79,7 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AND(x5, x5, x4); BEQZ(x5, 24); // undefined/NaN FEQD(x5, v1, v2); - BNEZ(x5, 24); // equal + BNEZ(x5, 28); // equal FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0 SLLI(x1, x3, 8); J(20); // end diff --git a/src/dynarec/rv64/dynarec_rv64_dc.c b/src/dynarec/rv64/dynarec_rv64_dc.c new file mode 100644 index 00000000..4facfe0e --- /dev/null +++ b/src/dynarec/rv64/dynarec_rv64_dc.c @@ -0,0 +1,112 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <pthread.h> +#include <errno.h> + +#include "debug.h" +#include "box64context.h" +#include "dynarec.h" +#include "emu/x64emu_private.h" +#include "emu/x64run_private.h" +#include "x64run.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "emu/x64run_private.h" +#include "x64trace.h" +#include "emu/x87emu_private.h" +#include "dynarec_native.h" + +#include "rv64_printer.h" +#include "dynarec_rv64_private.h" +#include "dynarec_rv64_helper.h" +#include "dynarec_rv64_functions.h" + + +uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog) +{ + (void)ip; (void)rep; (void)need_epilog; + + uint8_t nextop = F8; + uint8_t wback; + int64_t fixedaddress; + int unscaled; + int v1, v2; + + MAYUSE(v2); + MAYUSE(v1); + + switch(nextop) { + case 0xC0 ... 0xC7: + INST_NAME("FADD STx, ST0"); + DEFAULT; + break; + case 0xC8 ... 0xCF: + INST_NAME("FMUL STx, ST0"); + DEFAULT; + break; + case 0xD0 ... 0xD7: + INST_NAME("FCOM ST0, STx"); //yep + DEFAULT; + break; + case 0xD8 ... 0xDF: + INST_NAME("FCOMP ST0, STx"); + DEFAULT; + break; + case 0xE0 ... 0xE7: + INST_NAME("FSUBR STx, ST0"); + DEFAULT; + break; + break; + case 0xE8 ... 0xEF: + INST_NAME("FSUB STx, ST0"); + DEFAULT; + break; + case 0xF0 ... 0xF7: + INST_NAME("FDIVR STx, ST0"); + DEFAULT; + break; + case 0xF8 ... 0xFF: + INST_NAME("FDIV STx, ST0"); + DEFAULT; + break; + default: + switch((nextop>>3)&7) { + case 3: + INST_NAME("FCOMP ST0, double[ED]"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0); + FLD(v2, wback, fixedaddress); + + LHU(x3, xEmu, offsetof(x64emu_t, sw)); + MOV32w(x1, 0b1110100011111111); // mask off c0,c1,c2,c3 + AND(x3, x3, x1); + FEQD(x5, v1, v1); + FEQD(x4, v2, v2); + AND(x5, x5, x4); + BEQZ(x5, 24); // undefined/NaN + FEQD(x5, v1, v2); + BNEZ(x5, 28); // equal + FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0 + SLLI(x1, x3, 8); + J(20); // end + // undefined/NaN + LUI(x1, 1); + ADDI(x1, x1, 0b010100000000); + J(8); // end + // equal + LUI(x1, 1); + // end + OR(x3, x3, x1); + SH(x3, xEmu, offsetof(x64emu_t, sw)); + + x87_do_pop(dyn, ninst, x3); + break; + default: + DEFAULT; + } + } + return addr; +} diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c index ac5fb980..fa1a6a13 100644 --- a/src/dynarec/rv64/dynarec_rv64_dd.c +++ b/src/dynarec/rv64/dynarec_rv64_dd.c @@ -51,7 +51,10 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xC6: case 0xC7: INST_NAME("FFREE STx"); - DEFAULT; + MESSAGE(LOG_DUMP, "Need Optimization\n"); + x87_purgecache(dyn, ninst, 0, x1, x2, x3); + MOV32w(x1, nextop&7); + CALL(fpu_do_free, -1); break; case 0xD0: case 0xD1: @@ -139,6 +142,12 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0); FLD(v1, wback, fixedaddress); break; + case 2: + INST_NAME("FST double"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0); + FSD(v1, wback, fixedaddress); + break; case 3: INST_NAME("FSTP double"); v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index d8d44460..60d369d2 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1131,7 +1131,7 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); //uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); -//uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); +uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); |