diff options
| author | xctan <xctan@cirno.icu> | 2023-04-22 23:06:03 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-22 17:06:03 +0200 |
| commit | 225e50a32aa9c15eb71ee8eef6bf45748074c7fa (patch) | |
| tree | d17ad5ff3802d77cf090543b6d8aa65249dfba86 | |
| parent | d546877e7dddba58f21b67f2595d5be3a2d3cbb7 (diff) | |
| download | box64-225e50a32aa9c15eb71ee8eef6bf45748074c7fa.tar.gz box64-225e50a32aa9c15eb71ee8eef6bf45748074c7fa.zip | |
[RV64_DYNAREC] Added more opcodes for SV (#726)
* [RV64_DYNAREC] Added 66 FF /0 INC opcode and fixed emit_add16 * [RV64_DYNAREC] Added 66 0F F9 PSUBW opcode * [RV64_DYNAREC] Added 0F BA /6 BTR opcode * [RV64_DYNAREC] Added 0F BA /5 BTS opcode * [RV64_DYNAREC] Added 8C MOV opcode * [RV64_DYNAREC] Added 66 8B MOV opcode
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_2.c | 13 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 54 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 61 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 7 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 61 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 4 |
6 files changed, 182 insertions, 18 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index f962a507..4a6e6827 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -375,7 +375,18 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int LDxw(gd, ed, fixedaddress); } break; - + case 0x8C: + INST_NAME("MOV Ed, Seg"); + nextop=F8; + if((nextop&0xC0)==0xC0) { // reg <= seg + LHU(xRAX+(nextop&7)+(rex.b<<3), xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3])); + } else { // mem <= seg + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LHU(x3, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3])); + SH(x3, ed, fixedaddress); + SMWRITE2(); + } + break; case 0x8D: INST_NAME("LEA Gd, Ed"); nextop=F8; diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index d60f7be0..c2d526cf 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -819,6 +819,60 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ANDI(xFlags, xFlags, ~1); OR(xFlags, xFlags, x3); break; + case 5: + INST_NAME("BTS Ed, Ib"); + SETFLAGS(X_CF, SF_SUBSET); + SET_DFNONE(); + GETED(1); + u8 = F8; + u8&=(rex.w?0x3f:0x1f); + ORI(xFlags, xFlags, 1<<F_CF); + if (u8 <= 10) { + ANDI(x6, ed, 1<<u8); + BNE_MARK(x6, xZR); + ANDI(xFlags, xFlags, ~(1<<F_CF)); + XORI(ed, ed, 1<<u8); + } else { + ORI(x6, xZR, 1); + SLLI(x6, x6, u8); + AND(x4, ed, x6); + BNE_MARK(x4, xZR); + ANDI(xFlags, xFlags, ~(1<<F_CF)); + XOR(ed, ed, x6); + } + if (wback) { + SDxw(ed, wback, fixedaddress); + SMWRITE(); + } + MARK; + break; + case 6: + INST_NAME("BTR Ed, Ib"); + SETFLAGS(X_CF, SF_SUBSET); + SET_DFNONE(); + GETED(1); + u8 = F8; + u8&=(rex.w?0x3f:0x1f); + ANDI(xFlags, xFlags, ~(1<<F_CF)); + if (u8 <= 10) { + ANDI(x6, ed, 1<<u8); + BEQ_MARK(x6, xZR); + ORI(xFlags, xFlags, 1<<F_CF); + XORI(ed, ed, 1<<u8); + } else { + ORI(x6, xZR, 1); + SLLI(x6, x6, u8); + AND(x6, ed, x6); + BEQ_MARK(x6, xZR); + ORI(xFlags, xFlags, 1<<F_CF); + XOR(ed, ed, x6); + } + if (wback) { + SDxw(ed, wback, fixedaddress); + SMWRITE(); + } + MARK; + break; case 7: INST_NAME("BTC Ed, Ib"); SETFLAGS(X_CF, SF_SUBSET); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index aa2d5f7c..8b4a94f5 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -67,7 +67,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni nextop = F8; GETGW(x2); GETEW(x1, 0); - emit_add16(dyn, ninst, x1, x2, x4, x5); + emit_add16(dyn, ninst, x1, x2, x4, x5, x6); EWBACK; break; case 0x03: @@ -76,7 +76,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni nextop = F8; GETGW(x1); GETEW(x2, 0); - emit_add16(dyn, ninst, x1, x2, x3, x4); + emit_add16(dyn, ninst, x1, x2, x3, x4, x6); GWBACK; break; case 0x05: @@ -86,7 +86,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SLLI(x1 , xRAX, 48); SRLI(x1, x1, 48); MOV32w(x2, i32); - emit_add16(dyn, ninst, x1, x2, x3, x4); + emit_add16(dyn, ninst, x1, x2, x3, x4, x6); LUI(x3, 0xffff0); AND(xRAX, xRAX, x3); OR(xRAX, xRAX, x1); @@ -292,7 +292,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETEW(x1, (opcode==0x81)?2:1); if(opcode==0x81) i16 = F16S; else i16 = F8S; MOV64x(x5, i16); - emit_add16(dyn, ninst, ed, x5, x2, x4); + emit_add16(dyn, ninst, ed, x5, x2, x4, x6); EWBACK; break; case 1: // OR @@ -384,14 +384,36 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITELOCK(lock); } break; - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: + case 0x8B: + INST_NAME("MOV Gw, Ew"); + nextop = F8; + GETGD; // don't need GETGW neither + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + if(ed!=gd) { + LUI(x1, 0xffff0); + AND(gd, gd, x1); + SLLI(x2, ed, 48); + SRLI(x2, x2, 48); + OR(gd, gd, x2); + } + } else { + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0); + SMREADLOCK(lock); + LHU(x1, ed, fixedaddress); + LUI(x4, 0xffff0); + AND(gd, gd, x4); + OR(gd, gd, x1); + } + break; + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: gd = xRAX+(opcode&0x07)+(rex.b<<3); if(gd==xRAX) { INST_NAME("NOP"); @@ -683,6 +705,21 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; + case 0xFF: + nextop = F8; + switch((nextop>>3)&7) { + case 0: + INST_NAME("INC Ew"); + SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING); + GETEW(x1, 0); + emit_inc16(dyn, ninst, x1, x2, x4, x5); + EWBACK; + break; + default: + DEFAULT; + } + break; + default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index b42d3bea..91283c6f 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -1393,6 +1393,13 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SB(x3, gback, i); } break; + case 0xF9: + INST_NAME("PSUBW Gx,Ex"); + nextop = F8; + GETGX(x1); + GETEX(x2, 0); + SSE_LOOP_W(x3, x4, SUBW(x3, x3, x4)); + break; case 0xFA: INST_NAME("PSUBD Gx,Ex"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index df70eac4..90031672 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -193,7 +193,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } // emit ADD16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch -void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) +void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) { CLEAR_FLAGS(); IFX(X_PEND) { @@ -213,8 +213,8 @@ void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) SW(s1, xEmu, offsetof(x64emu_t, res)); } IFX(X_AF | X_OF) { - NOT(s2, s1); // s2 = ~res - AND(s3, s2, s3); // s3 = ~res & (op1 | op2) + NOT(s5, s1); // s5 = ~res + AND(s3, s5, s3); // s3 = ~res & (op1 | op2) OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2) IFX(X_AF) { ANDI(s4, s3, 0x08); // AF: cc & 0x08 @@ -778,6 +778,61 @@ void emit_dec32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } } +// emit INC16 instruction, from s1, store result in s1 using s3 and s4 as scratch +void emit_inc16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) +{ + IFX(X_PEND) { + SH(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s3, d_inc16); + } else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) { + SET_DFNONE(); + } + IFX(X_AF | X_OF) { + ORI(s3, s1, 1); // s3 = op1 | op2 + ANDI(s4, s1, 1); // s4 = op1 & op2 + } + + ADDI(s1, s1, 1); + + IFX(X_PEND) { + SH(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_AF | X_OF) { + NOT(s2, s1); // s2 = ~res + AND(s3, s2, s3); // s3 = ~res & (op1 | op2) + OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2) + IFX(X_AF) { + ANDI(s4, s3, 0x08); // AF: cc & 0x08 + BEQZ(s4, 8); + ORI(xFlags, xFlags, 1 << F_AF); + } + IFX(X_OF) { + SRLI(s3, s3, 14); + SRLI(s4, s3, 1); + XOR(s3, s3, s4); + ANDI(s3, s3, 1); // OF: xor of two MSB's of cc + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_OF2); + } + } + + SLLI(s1, s1, 48); + SRLI(s1, s1, 48); + + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_SF) { + SRLI(s3, s1, 15); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit SBB8 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch void emit_sbb8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 90d2598e..189fa7bc 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -933,7 +933,7 @@ void emit_xor8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_xor8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_and8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_and8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); -void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); //void emit_add16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_sub16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); //void emit_sub16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); @@ -944,7 +944,7 @@ void emit_xor16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, void emit_and16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_and16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); -//void emit_inc16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); +void emit_inc16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_inc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_dec32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); //void emit_dec16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); |