diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 24 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 48 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 62 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 |
4 files changed, 135 insertions, 1 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 126e342e..7d382802 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -974,6 +974,30 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni #endif } break; + case 0xD0: + case 0xD2: // TODO: Jump if CL is 0 + nextop = F8; + switch((nextop>>3)&7) { + case 5: + if(opcode==0xD0) { + INST_NAME("SHR Eb, 1"); + MOV32w(x2, 1); + } else { + INST_NAME("SHR Eb, CL"); + ANDI(x2, xRCX, 0x1F); + } + SETFLAGS(X_ALL, SF_PENDING); + GETEB(x1, 0); + UFLAG_OP12(ed, x2); + SRLW(ed, ed, x2); + EBBACK(x3); + UFLAG_RES(ed); + UFLAG_DF(x3, d_shr8); + break; + default: + DEFAULT; + } + break; case 0xD1: nextop = F8; switch((nextop>>3)&7) { diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 0cd1f5e8..84aadad5 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -113,6 +113,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x83: nextop = F8; switch((nextop>>3)&7) { + case 0: //ADD + if(opcode==0x81) {INST_NAME("ADD Ew, Iw");} else {INST_NAME("ADD Ew, Ib");} + SETFLAGS(X_ALL, SF_SET_PENDING); + 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); + EWBACK; + break; case 1: // OR if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");} SETFLAGS(X_ALL, SF_SET_PENDING); @@ -122,6 +131,17 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_or16(dyn, ninst, x1, x5, x2, x4); EWBACK; break; + case 7: //CMP + if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");} + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEW(x1, (opcode==0x81)?2:1); + if(opcode==0x81) i16 = F16S; else i16 = F8S; + if(i16) { + MOV64xw(x2, i16); + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); + } else + emit_cmp16_0(dyn, ninst, x1, x3, x4); + break; default: DEFAULT; } @@ -299,6 +319,34 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; + case 0xF7: + nextop = F8; + switch((nextop>>3)&7) { + case 6: + INST_NAME("DIV Ew"); + SETFLAGS(X_ALL, SF_SET); + GETEW(x1, 0); + SLLI(x2, xRAX, 48); + SLLI(x3, xRDX, 48); + SRLI(x2, x2, 48); + SRLI(x3, x3, 32); + OR(x2, x2, x3); + DIVUW(x3, x2, ed); + REMUW(x4, x2, ed); + MOV64x(x5, ~0xffff); + AND(xRAX, xRAX, x5); + AND(xRDX, xRDX, x5); + NOT(x5, x5); + AND(x3, x3, x5); + AND(x4, x4, x5); + OR(xRAX, xRAX, x3); + OR(xRDX, xRDX, x4); + break; + default: + DEFAULT; + } + break; + default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index 9b25e423..5f79a385 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -192,6 +192,68 @@ 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) +{ + CLEAR_FLAGS(); + IFX(X_PEND) { + SH(s1, xEmu, offsetof(x64emu_t, op1)); + SH(s2, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s3, d_add16); + } else IFX(X_ALL) { + SET_DFNONE(); + } + IFX(X_AF | X_OF) { + OR(s3, s1, s2); // s3 = op1 | op2 + AND(s4, s1, s2); // s4 = op1 & op2 + } + ADD(s1, s1, s2); + + IFX(X_PEND) { + 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) + 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); + } + } + + IFX(X_CF) { + SRLI(s3, s1, 16); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_CF); + } + + 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 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 0ab1a76d..d803da35 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -742,7 +742,7 @@ void emit_or8(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); //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); //void emit_sub16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); |