diff options
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 16 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_64.c | 9 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 12 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 14 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 61 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 17 |
6 files changed, 128 insertions, 1 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index ca7ec07e..726f9edb 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -189,6 +189,14 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETED(0); emit_xor32(dyn, ninst, rex, gd, ed, x3, x4); break; + case 0x38: + INST_NAME("CMP Eb, Gb"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETEB(x1, 0); + GETGB(x2); + emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; case 0x39: INST_NAME("CMP Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -400,6 +408,14 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x80: nextop = F8; switch((nextop>>3)&7) { + case 0: //ADD + INST_NAME("ADD Eb, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEB(x1, 1); + u8 = F8; + emit_add8c(dyn, ninst, x1, u8, x2, x4, x5); + EBBACK(x3); + break; case 3: // SBB INST_NAME("SBB Eb, Ib"); READFLAGS(X_CF); diff --git a/src/dynarec/rv64/dynarec_rv64_64.c b/src/dynarec/rv64/dynarec_rv64_64.c index bbcdc681..9d1f8823 100644 --- a/src/dynarec/rv64/dynarec_rv64_64.c +++ b/src/dynarec/rv64/dynarec_rv64_64.c @@ -64,6 +64,15 @@ uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } switch(opcode) { + case 0x2B: + INST_NAME("SUB Gd, Seg:Ed"); + SETFLAGS(X_ALL, SF_SET_PENDING); + grab_segdata(dyn, addr, ninst, x4, seg); + nextop = F8; + GETGD; + GETEDO(x4, 0, x5); + emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5); + break; case 0x8B: INST_NAME("MOV Gd, Seg:Ed"); grab_segdata(dyn, addr, ninst, x4, seg); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 84aadad5..cef86d4d 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -202,6 +202,18 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni OR(gd, gd, x2); } break; + + case 0x98: + INST_NAME("CBW"); + SLLI(x1, xRAX, 56); + SRAI(x1, x1, 56); + LUI(x2, 0xffff0); + AND(xRAX, xRAX, x2); + NOT(x2, x2); + AND(x1, x1, x2); + OR(xRAX, xRAX, x1); + break; + case 0xC1: nextop = F8; switch((nextop>>3)&7) { diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 8210a27d..83569f0e 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -80,6 +80,20 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GOCOND(0x40, "CMOV", "Gw, Ew"); #undef GO + case 0xAF: + INST_NAME("IMUL Gw,Ew"); + SETFLAGS(X_ALL, SF_PENDING); + nextop = F8; + UFLAG_DF(x1, d_imul16); + GETSEW(x1, 0); + GETSGW(x2); + MULW(x2, x2, x1); + UFLAG_RES(x2); + SLLI(x2, x2, 48); + SRLI(x2, x2, 48); + GWBACK; + break; + default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index 5f79a385..36ef6e29 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -255,6 +255,67 @@ void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) } +// emit ADD8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch +void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s2, int s3, int s4) +{ + CLEAR_FLAGS(); + IFX(X_PEND) { + MOV32w(s4, c&0xff); + SB(s1, xEmu, offsetof(x64emu_t, op1)); + SB(s4, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s3, d_add8); + } else IFX(X_ALL) { + SET_DFNONE(); + } + IFX(X_AF | X_OF) { + if(X_PEND) {} else {MOV32w(s4, c&0xff);} + OR(s3, s1, s4); // s3 = op1 | op2 + AND(s4, s1, s4); // s4 = op1 & op2 + } + ADDI(s1, s1, c); + + 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, 6); + 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); + } + } + IFX(X_CF) { + SRLI(s3, s1, 8); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_CF); + } + IFX(X_PEND) { + SH(s1, xEmu, offsetof(x64emu_t, res)); + } + ANDI(s1, s1, 0xff); + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_SF) { + SRLI(s3, s1, 7); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + + // emit SUB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, 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 eb758e5f..fbb61e73 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -148,11 +148,26 @@ // Write back gd in correct register (gd needs to be 16bits only!) #define GWBACK do{int g=xRAX+((nextop&0x38)>>3)+(rex.r<<3); SRLI(g, g, 16); SLLI(g, g, 16); OR(g, g, gd);}while(0) +//GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI +#define GETEDO(O, D, S) if(MODREG) { \ + ed = xRAX+(nextop&7)+(rex.b<<3); \ + wback = 0; \ + } else { \ + SMREAD(); \ + addr = geted(dyn, addr, ninst, nextop, &wback, x2, S, &fixedaddress, rex, NULL, 0, D); \ + ADD(S, wback, O); \ + LDxw(x1, S, 0); \ + ed = x1; \ + } + // FAKEED like GETED, but doesn't get anything #define FAKEED if(!MODREG) { \ addr = fakeed(dyn, addr, ninst, nextop); \ } +// GETGW extract x64 register in gd, that is i, Signed extented +#define GETSGW(i) gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); SLLIW(i, gd, 16); SRAIW(i, i, 16); gd = i; + // Write back ed in wback (if wback not 0) #define WBACK if(wback) {SDxw(ed, wback, fixedaddress); SMWRITE();} @@ -725,7 +740,7 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5); //void emit_add8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); -//void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); +void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4); void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5); //void emit_sub8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); |