From 225e50a32aa9c15eb71ee8eef6bf45748074c7fa Mon Sep 17 00:00:00 2001 From: xctan Date: Sat, 22 Apr 2023 23:06:03 +0800 Subject: [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 --- src/dynarec/rv64/dynarec_rv64_00_2.c | 13 ++++++- src/dynarec/rv64/dynarec_rv64_0f.c | 54 +++++++++++++++++++++++++++ src/dynarec/rv64/dynarec_rv64_66.c | 61 +++++++++++++++++++++++++------ src/dynarec/rv64/dynarec_rv64_660f.c | 7 ++++ src/dynarec/rv64/dynarec_rv64_emit_math.c | 61 +++++++++++++++++++++++++++++-- src/dynarec/rv64/dynarec_rv64_helper.h | 4 +- 6 files changed, 182 insertions(+), 18 deletions(-) (limited to 'src') 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<>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); -- cgit 1.4.1