diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-12-08 22:59:52 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-08 15:59:52 +0100 |
| commit | 9481df50b133c9bf1fa35fcd797e62fc9606591c (patch) | |
| tree | 97d6a468c62ccaedb6a7ccd4121574982a9b40ce /src | |
| parent | 840c454c1c06df4695008bea72ba4fc9a266e437 (diff) | |
| download | box64-9481df50b133c9bf1fa35fcd797e62fc9606591c.tar.gz box64-9481df50b133c9bf1fa35fcd797e62fc9606591c.zip | |
[DYNAREC_RV64] Added more and more opcodes for flatout.exe (#1128)
* [DYNAREC_RV64] Added F0 87 LOCK XCHG opcode * [DYNAREC_RV64] Added 66 (F2/F3) A7 CMPSW opcode * [DYNAREC_RV64] Added more DC opcodes * [DYNAREC_RV64] Added more D8 opcodes
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 42 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_d8.c | 55 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_dc.c | 50 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f0.c | 52 |
4 files changed, 179 insertions, 20 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 6e13c867..e78310f9 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -651,6 +651,48 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ADD(xRDI, xRDI, x3); } break; + case 0xA7: + switch (rep) { + case 1: + case 2: + if (rep == 1) { INST_NAME("REPNZ CMPSW"); } else { INST_NAME("REPZ CMPSW"); } + MAYSETFLAGS(); + SETFLAGS(X_ALL, SF_SET_PENDING); + CBZ_NEXT(xRCX); + ANDI(x1, xFlags, 1 << F_DF); + BNEZ_MARK2(x1); + MARK; // Part with DF==0 + LHU(x1, xRSI, 0); + ADDI(xRSI, xRSI, 2); + LHU(x2, xRDI, 0); + ADDI(xRDI, xRDI, 2); + SUBI(xRCX, xRCX, 1); + if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); } + BNEZ_MARK(xRCX); + B_MARK3_nocond; + MARK2; // Part with DF==1 + LHU(x1, xRSI, 0); + SUBI(xRSI, xRSI, 2); + LHU(x2, xRDI, 0); + SUBI(xRDI, xRDI, 2); + SUBI(xRCX, xRCX, 1); + if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); } + BNEZ_MARK2(xRCX); + MARK3; // end + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; + default: + INST_NAME("CMPSW"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETDIR(x3, x1, 2); + LHU(x1, xRSI, 0); + LHU(x2, xRDI, 0); + ADD(xRSI, xRSI, x3); + ADD(xRDI, xRDI, x3); + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; + } + break; case 0xA9: INST_NAME("TEST AX,Iw"); SETFLAGS(X_ALL, SF_SET_PENDING); diff --git a/src/dynarec/rv64/dynarec_rv64_d8.c b/src/dynarec/rv64/dynarec_rv64_d8.c index 3f7f2314..885eebfd 100644 --- a/src/dynarec/rv64/dynarec_rv64_d8.c +++ b/src/dynarec/rv64/dynarec_rv64_d8.c @@ -53,10 +53,24 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xC8 ... 0xCF: - DEFAULT; + INST_NAME("FMUL ST0, STx"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7)); + if (ST_IS_F(0)) { + FMULS(v1, v1, v2); + } else { + FMULD(v1, v1, v2); + } break; case 0xD0 ... 0xD7: - DEFAULT; + INST_NAME("FCOM ST0, STx"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7)); + if (ST_IS_F(0)) { + FCOMS(v1, v2, x1, x2, x3, x4, x5); + } else { + FCOMD(v1, v2, x1, x2, x3, x4, x5); + } break; case 0xD8 ... 0xDF: INST_NAME("FCOMP ST0, STx"); @@ -80,12 +94,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xE8 ... 0xEF: - DEFAULT; + INST_NAME("FSUBR ST0, STx"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7)); + if (ST_IS_F(0)) { + FSUBS(v1, v2, v1); + } else { + FSUBD(v1, v2, v1); + } break; case 0xF0 ... 0xF7: INST_NAME("FDIV ST0, STx"); - v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7)); - v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7)); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7)); if(ST_IS_F(0)) { FDIVS(v1, v1, v2); } else { @@ -93,7 +114,14 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xF8 ... 0xFF: - DEFAULT; + INST_NAME("FDIVR ST0, STx"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7)); + if (ST_IS_F(0)) { + FDIVS(v1, v2, v1); + } else { + FDIVD(v1, v2, v1); + } break; default: @@ -164,6 +192,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FSUBD(v1, v1, s0); } break; + case 5: + INST_NAME("FSUBR ST0, float[ED]"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0); + s0 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + FLW(s0, ed, fixedaddress); + if (ST_IS_F(0)) { + FSUBS(v1, s0, v1); + } else { + FCVTDS(s0, s0); + FSUBD(v1, s0, v1); + } + break; case 6: INST_NAME("FDIV ST0, float[ED]"); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0); @@ -190,8 +231,6 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FDIVD(v1, s0, v1); } break; - default: - DEFAULT; } } return addr; diff --git a/src/dynarec/rv64/dynarec_rv64_dc.c b/src/dynarec/rv64/dynarec_rv64_dc.c index 7f680f00..006587b3 100644 --- a/src/dynarec/rv64/dynarec_rv64_dc.c +++ b/src/dynarec/rv64/dynarec_rv64_dc.c @@ -114,6 +114,30 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; default: switch((nextop>>3)&7) { + case 0: + INST_NAME("FADD 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); + FADDD(v1, v1, v2); + break; + case 1: + INST_NAME("FMUL 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); + FMULD(v1, v1, v2); + break; + case 2: + INST_NAME("FCOM 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); + FCOMD(v1, v2, x1, x6, x3, x4, x5); + break; case 3: INST_NAME("FCOMP ST0, double[ED]"); v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); @@ -123,6 +147,22 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FCOMD(v1, v2, x1, x6, x3, x4, x5); X87_POP_OR_FAIL(dyn, ninst, x3); break; + case 4: + INST_NAME("FSUB 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); + FSUBD(v1, v1, v2); + break; + case 5: + INST_NAME("FSUBR 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); + FSUBD(v1, v2, v1); + break; case 6: INST_NAME("FDIV ST0, double[ED]"); v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); @@ -131,8 +171,14 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FLD(v2, wback, fixedaddress); FDIVD(v1, v1, v2); break; - default: - DEFAULT; + case 7: + INST_NAME("FDIVR 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); + FDIVD(v1, v2, v1); + break; } } return addr; diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index 469ae5bb..d90aa34e 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -49,8 +49,9 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETREX(); - // TODO: Take care of unligned memory access for all the LOCK ones. - // https://github.com/ptitSeb/box64/pull/604 + // TODO: Add support for unligned memory access for all the LOCK ones. + // TODO: Add support for BOX4_DYNAREC_ALIGNED_ATOMICS. + switch(opcode) { case 0x01: INST_NAME("LOCK ADD Ed, Gd"); @@ -214,7 +215,6 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else { SMDMB(); addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); - // TODO: Add support for BOX4_DYNAREC_ALIGNED_ATOMICS. ANDI(x1, wback, (1 << (rex.w + 2)) - 1); BNEZ_MARK3(x1); // Aligned @@ -553,7 +553,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMDMB(); addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1); if(opcode==0x81) i64 = F32S; else i64 = F8S; - // TODO: Add support for BOX4_DYNAREC_ALIGNED_ATOMICS. + if (i64 < -2048 || i64 >= 2048) + MOV64xw(x4, i64); ANDI(x1, wback, (1 << (rex.w + 2)) - 1); BNEZ_MARK3(x1); // Aligned @@ -561,10 +562,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LRxw(x1, wback, 1, 1); if (i64 >= -2048 && i64 < 2048) ADDIxw(x4, x1, i64); - else { - MOV64xw(x4, i64); + else ADDxw(x4, x1, x4); - } SCxw(x3, x4, wback, 1, 1); BNEZ_MARKLOCK(x3); B_MARK_nocond; @@ -576,10 +575,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LRxw(x1, x5, 1, 1); if (i64 >= -2048 && i64 < 2048) ADDIxw(x4, x6, i64); - else { - MOV64xw(x4, i64); + else ADDxw(x4, x6, x4); - } SCxw(x3, x1, x5, 1, 1); BNEZ_MARK2(x3); SDxw(x4, wback, 0); @@ -680,6 +677,41 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } SMDMB(); break; + case 0x87: + INST_NAME("LOCK XCHG Ed, Gd"); + nextop = F8; + if (MODREG) { + GETGD; + GETED(0); + MV(x1, gd); + MV(gd, ed); + MV(ed, x1); + } else { + SMDMB(); + GETGD; + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); + ANDI(x1, wback, (1 << (rex.w + 2)) - 1); + BNEZ_MARK3(x1); + // Aligned + MARKLOCK; + LRxw(x1, wback, 1, 1); + SCxw(x4, gd, wback, 1, 1); + BNEZ_MARKLOCK(x4); + B_MARK_nocond; + MARK3; + // Unaligned + ANDI(x5, wback, -(1 << (rex.w + 2))); + MARK2; // Use MARK2 as a "MARKLOCK" since we're running out of marks. + LDxw(x1, wback, 0); + LRxw(x3, x5, 1, 1); + SCxw(x4, x3, x5, 1, 1); + BNEZ_MARK2(x4); + SDxw(gd, wback, 0); + MARK; + MVxw(gd, x1); + SMDMB(); + } + break; case 0xFF: nextop = F8; switch((nextop>>3)&7) |