diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-05-03 14:18:49 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-03 08:18:49 +0200 |
| commit | 0079a08cb837ab0dbf24c32222e8a76ee8f54740 (patch) | |
| tree | 49f2eb9931ea9e2c4fdd7e359828b33e61ee0efc | |
| parent | d31ff6a83f6cac81cff3da6a0bd5fde128bad197 (diff) | |
| download | box64-0079a08cb837ab0dbf24c32222e8a76ee8f54740.tar.gz box64-0079a08cb837ab0dbf24c32222e8a76ee8f54740.zip | |
[RV64_DYNAREC] Added more opcodes for Bastion and some fixes (#753)
* Added AE SCASB opcode * Some small fixes * Added FSQRT opcode * Treat all PREFETCHh opcodes as nop * Added DF E0 FNSTSW opcode * Added DD FSTP opcode
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_2.c | 38 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 9 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 8 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_d9.c | 7 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_db.c | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_dd.c | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_df.c | 19 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f20f.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f30f.c | 6 |
9 files changed, 75 insertions, 24 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index f2fd1287..0e9144b7 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -681,6 +681,44 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ADD(xRDI, xRDI, x3); } break; + case 0xAE: + switch (rep) { + case 1: + case 2: + if (rep==1) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");} + MAYSETFLAGS(); + SETFLAGS(X_ALL, SF_SET_PENDING); + CBZ_NEXT(xRCX); + ANDI(x1, xRAX, 0xff); + ANDI(x1, xFlags, 1<<F_DF); + BNEZ_MARK2(x1); + MARK; // Part with DF==0 + LBU(x2, xRDI, 0); + ADDI(xRDI, xRDI, 1); + 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 + LBU(x2, xRDI, 0); + SUBI(xRDI, xRDI, 1); + SUBI(xRCX, xRCX, 1); + if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);} + BNE_MARK2(xRCX, xZR); + MARK3; // end + emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; + default: + INST_NAME("SCASB"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETDIR(x3, x1, 1); + ANDI(x1, xRAX, 0xff); + LBU(x2, xRDI, 0); + ADD(xRDI, xRDI, x3); + emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; + } + break; case 0xB0: case 0xB1: case 0xB2: diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index e6ac82d8..777d0ed2 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -229,16 +229,11 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else switch((nextop>>3)&7) { case 0: - DEFAULT; - break; case 1: - DEFAULT; - break; case 2: - DEFAULT; - break; case 3: - DEFAULT; + INST_NAME("PREFETCHh Ed"); + FAKEED; break; default: INST_NAME("NOP (multibyte)"); diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 6e19ab14..3fce8de1 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -1710,10 +1710,10 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEX(x2, 0); v0 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); - FLD(v0, wback, 0); - FLD(v1, wback, 8); + FLD(v0, wback, fixedaddress+0); + FLD(v1, wback, fixedaddress+8); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // // reset all bits + FSFLAGSI(0); // // reset all bits } FCVTWD(x3, v0, RD_RTZ); if(!box64_dynarec_fastround) { @@ -1722,7 +1722,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int BEQ_MARK(x5, xZR); MOV32w(x3, 0x80000000); MARK; - FSFLAGSI(xZR); // // reset all bits + FSFLAGSI(0); // // reset all bits } FCVTWD(x4, v1, RD_RTZ); if(!box64_dynarec_fastround) { diff --git a/src/dynarec/rv64/dynarec_rv64_d9.c b/src/dynarec/rv64/dynarec_rv64_d9.c index a6a7898e..f924eaff 100644 --- a/src/dynarec/rv64/dynarec_rv64_d9.c +++ b/src/dynarec/rv64/dynarec_rv64_d9.c @@ -263,7 +263,12 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xFA: INST_NAME("FSQRT"); - DEFAULT; + v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0); + if(ST_IS_F(0)) { + FSQRTS(v1, v1); + } else { + FSQRTD(v1, v1); + } break; case 0xFB: INST_NAME("FSINCOS"); diff --git a/src/dynarec/rv64/dynarec_rv64_db.c b/src/dynarec/rv64/dynarec_rv64_db.c index e037c3dd..08abacfd 100644 --- a/src/dynarec/rv64/dynarec_rv64_db.c +++ b/src/dynarec/rv64/dynarec_rv64_db.c @@ -196,7 +196,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0); v2 = fpu_get_scratch(dyn); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // reset all bits + FSFLAGSI(0); // reset all bits } FCVTWD(x4, v1, RD_DYN); x87_restoreround(dyn, ninst, u8); diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c index 71b1740a..ac5fb980 100644 --- a/src/dynarec/rv64/dynarec_rv64_dd.c +++ b/src/dynarec/rv64/dynarec_rv64_dd.c @@ -76,7 +76,11 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xDE: case 0xDF: INST_NAME("FSTP ST0, STx"); - DEFAULT; + // copy the cache value for st0 to stx + x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7)); + x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0); + x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7); + x87_do_pop(dyn, ninst, x3); break; case 0xE0: case 0xE1: diff --git a/src/dynarec/rv64/dynarec_rv64_df.c b/src/dynarec/rv64/dynarec_rv64_df.c index 61546975..aa5f1131 100644 --- a/src/dynarec/rv64/dynarec_rv64_df.c +++ b/src/dynarec/rv64/dynarec_rv64_df.c @@ -47,9 +47,18 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xE0: INST_NAME("FNSTSW AX"); - DEFAULT; + LHU(x2, xEmu, offsetof(x64emu_t, top)); + LHU(x1, xEmu, offsetof(x64emu_t, sw)); + MOV32w(x3, 0b1100011111111111); // mask + AND(x1, x1, x3); + NOT(x3, x3); + AND(x2, x2, x3); + OR(x1, x1, x2); // inject top + SH(x1, xEmu, offsetof(x64emu_t, sw)); + SRLI(xRAX, xRAX, 16); + SLLI(xRAX, xRAX, 16); + OR(xRAX, xRAX, x1); break; - case 0xE8 ... 0xF7: if (nextop < 0xF0) { INST_NAME("FUCOMIP ST0, STx"); @@ -122,7 +131,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_F); addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // reset all bits + FSFLAGSI(0); // reset all bits } FCVTWD(x4, v1, RD_RTZ); if(!box64_dynarec_fastround) { @@ -145,7 +154,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni u8 = x87_setround(dyn, ninst, x1, x2); addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // reset all bits + FSFLAGSI(0); // reset all bits } FCVTWD(x4, v1, RD_DYN); x87_restoreround(dyn, ninst, u8); @@ -170,7 +179,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0); v2 = fpu_get_scratch(dyn); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // reset all bits + FSFLAGSI(0); // reset all bits } FCVTLD(x4, v1, RD_DYN); x87_restoreround(dyn, ninst, u8); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 35fcf562..74937408 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -105,7 +105,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGD; GETEXSD(v0, 0); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // // reset all bits + FSFLAGSI(0); // // reset all bits } FCVTLDxw(gd, v0, RD_RTZ); if(!rex.w) @@ -127,7 +127,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGD; GETEXSD(v0, 0); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // // reset all bits + FSFLAGSI(0); // // reset all bits } u8 = sse_setround(dyn, ninst, x2, x3); FCVTLDxw(gd, v0, RD_DYN); diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c index ab7855da..bdb8fa3b 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f.c @@ -105,7 +105,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGD; GETEXSS(d0, 0); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // // reset all bits + FSFLAGSI(0); // // reset all bits } FCVTSxw(gd, d0, RD_RTZ); if(!rex.w) @@ -127,7 +127,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGD; GETEXSS(d0, 0); if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // // reset all bits + FSFLAGSI(0); // // reset all bits } u8 = sse_setround(dyn, ninst, x5, x6); FCVTSxw(gd, d0, RD_DYN); @@ -285,7 +285,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int v0 = fpu_get_scratch(dyn); for(int i=0; i<4; ++i) { if(!box64_dynarec_fastround) { - FSFLAGSI(xZR); // reset all bits + FSFLAGSI(0); // reset all bits } FLW(v0, wback, fixedaddress+i*4); FCVTWS(x3, v0, RD_RTZ); |