diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_0.c | 49 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 37 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66f0.c | 66 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f0.c | 98 |
4 files changed, 248 insertions, 2 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_0.c b/src/dynarec/rv64/dynarec_rv64_00_0.c index a0ff3746..4971849c 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_0.c +++ b/src/dynarec/rv64/dynarec_rv64_00_0.c @@ -167,7 +167,16 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int DEFAULT; } break; - + case 0x10: + INST_NAME("ADC Eb, Gb"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETEB(x1, 0); + GETGB(x2); + emit_adc8(dyn, ninst, x1, x2, x4, x5, x3); + EBBACK(x5, 0); + break; case 0x11: INST_NAME("ADC Ed, Gd"); READFLAGS(X_CF); @@ -178,7 +187,43 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); WBACK; break; - + case 0x12: + INST_NAME("ADC Gb, Eb"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETEB(x2, 0); + GETGB(x1); + emit_adc8(dyn, ninst, x1, x2, x4, x3, x5); + GBBACK(x5); + break; + case 0x13: + INST_NAME("ADC Gd, Ed"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGD; + GETED(0); + emit_adc32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6); + break; + case 0x14: + INST_NAME("ADC AL, Ib"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + u8 = F8; + ANDI(x1, xRAX, 0xff); + emit_adc8c(dyn, ninst, x1, u8, x3, x4, x5, x6); + ANDI(xRAX, xRAX, -256); + OR(xRAX, xRAX, x1); + break; + case 0x15: + INST_NAME("ADC EAX, Id"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + i64 = F32S; + MOV64xw(x1, i64); + emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); + break; case 0x18: INST_NAME("SBB Eb, Gb"); READFLAGS(X_CF); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 66a9f1c1..3e11d45f 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -117,6 +117,43 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x0F: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 0x11: + INST_NAME("ADC Ew, Gw"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x2); + GETEW(x1, 0); + emit_adc16(dyn, ninst, x1, x2, x4, x3, x5); + EWBACK; + break; + case 0x13: + INST_NAME("ADC Gw, Ew"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_adc16(dyn, ninst, x1, x2, x4, x3, x5); + GWBACK; + break; + case 0x15: + INST_NAME("ADC AX, Iw"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + i16 = F16; + SRLI(x6, xMASK, 16); + AND(x1, xRAX, x6); + MOV32w(x2, i16); + emit_adc16(dyn, ninst, x1, x2, x3, x4, x5); + if (rv64_zbb) { + ANDN(xRAX, xRAX, x6); + } else { + NOT(x6, x6); + AND(xRAX, xRAX, x6); + } + OR(xRAX, xRAX, x1); + break; case 0x19: INST_NAME("SBB Ew, Gw"); READFLAGS(X_CF); diff --git a/src/dynarec/rv64/dynarec_rv64_66f0.c b/src/dynarec/rv64/dynarec_rv64_66f0.c index 863e535d..84164227 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f0.c +++ b/src/dynarec/rv64/dynarec_rv64_66f0.c @@ -8,6 +8,7 @@ #include "dynarec.h" #include "emu/x64emu_private.h" #include "emu/x64run_private.h" +#include "rv64_emitter.h" #include "x64run.h" #include "x64emu.h" #include "box64stack.h" @@ -48,6 +49,71 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETREX(); switch(opcode) { + case 0x11: + INST_NAME("LOCK ADC Ew, Gw"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + SMDMB(); + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + MOV32w(x6, 0xFFFF); + AND(x2, ed, x6); + emit_adc16(dyn, ninst, x1, x2, x3, x4, x5); + if (rv64_zbb) { + ANDN(ed, ed, x6); + } else { + NOT(x6, x6); + AND(ed, ed, x6); + } + OR(ed, ed, x2); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, LOCK_LOCK, 0, 0); + ANDI(x3, wback, 0b10); + MOV32w(x4, 0xffff); // x4 = mask + BNEZ_MARK(x3); + // lower 16bits + MARKLOCK; + LR_W(x5, wback, 1, 1); + AND(x6, x5, x4); // x6 = Ed.h[0] + SRLIW(x5, x5, 16); + SLLIW(x5, x5, 16); // x5 = clear Ed.h[0] + ADDW(x2, x1, x6); // x2 = Gw + Ew + ANDI(x9, xFlags, 1 << F_CF); + ADDW(x2, x2, x9); // x2 = adc + AND(x2, x2, x4); + OR(x5, x5, x2); + SC_W(x2, x5, wback, 1, 1); + BNEZ_MARKLOCK(x2); + B_MARK3_nocond; + MARK; + // upper 16bits + SLLIW(x3, x4, 16); // x3 = mask + SUBI(wback, wback, 2); // aligning address + SLLI(x1, x1, 16); // x1 = extended Gw + MARK2; + LR_W(x6, wback, 1, 1); // x6 = Ed + AND(x5, x6, x3); // x5 = Ed.h[1] << 16 + ADDW(x5,x5, x1); + ANDI(x9, xFlags, 1 << F_CF); + SLLIW(x9, x9, 16); + ADDW(x5, x5, x9); // x5 = adc << 16 + AND(x9, x6, x4); // x9 = Ed.h[0] + OR(x5, x5, x9); + SC_W(x9, x5, wback, 1, 1); + BNEZ_MARK2(x9); + IFX(X_ALL|X_PEND) { + SRLIW(x6, x6, 16); + SRLIW(x1, x1, 16); + } + MARK3; + IFX(X_ALL|X_PEND) { + emit_adc16(dyn, ninst, x1, x6, x3, x4, x5); + } + } + SMDMB(); + break; case 0x81: case 0x83: nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index 348f2905..bb5c78c5 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -339,6 +339,101 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DEFAULT; } break; + case 0x10: + INST_NAME("LOCK ADC Eb, Gb"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGB(x2); + SMDMB(); + if((nextop&0xC0)==0xC0) { + if(rex.rex) { + wback = xRAX + (nextop&7) + (rex.b<<3); + wb2 = 0; + } else { + wback = (nextop&7); + wb2 = (wback>>2); + wback = xRAX+(wback&3); + } + SRLIW(x1, wback, wb2*8); + ANDI(x1, x1, 0xFF); + emit_adc8(dyn, ninst, x1, x2, x3, x4, x5); + SLLI(x1, x1, wb2*8); + MOV_U12(x3, 0xFF); + SLLI(x3, x3, wb2*8); + NOT(x3, x3); + AND(wback, wback, x3); + OR(wback, wback, x1); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x1, x3, &fixedaddress, rex, LOCK_LOCK, 0, 0); + ANDI(x3, wback, 0b11); + BNEZ_MARK(x3); + MARKLOCK; + LR_W(x5, wback, 1, 1); + ANDI(x4, x5, 0xff); // x4 = Ed.b[0] + ANDI(x5, x5, -256); // x5 = clear Ed.b[0] + ADDW(x6, x4, x2); + ANDI(x9, xFlags, 1 << F_CF); + ADDW(x6, x6, x9); // x6 = adc + ANDI(x6, x6, 0xff); + OR(x5, x5, x6); + SC_W(x9, x5, wback, 1, 1); + BNEZ_MARKLOCK(x9); + B_MARK3_nocond; + MARK; + SLLI(x3, x3, 3); + MOV_U12(x4, 0xff); + ANDI(wback, wback, ~3); // aligning address + SLLI(x4, x4, x3); // x4 = byte mask + NOT(x5, x4); // x5 = ~mask + SLL(x2, x2, x3); // x2 = extented Gb + MARK2; + LR_W(x6, wback, 1, 1); // x6 = Ed + AND(x9, x6, x4); // x9 = extended Ed.b[dest] + AND(x6, x6, x5); // x6 = clear Ed.b[dest] + ADDW(x5, x9, x2); + ANDI(x4, xFlags, 1 << F_CF); + SLL(x4, x4, x3); // extented + ADDW(x5, x5, x4); // x5 = adc + OR(x5, x5, x6); + SC_W(x4, x5, wback, 1, 1); + BNEZ_MARK2(x4); + IFX(X_ALL|X_PEND) { + SRLI(x2, x2, x3); // Gb + SRLI(x4, x9, x3); // Eb + } + MARK3; + IFX(X_ALL|X_PEND) { + emit_adc8(dyn, ninst, x4, x2, x3, x5, x6); + } + } + SMDMB(); + break; + case 0x11: + INST_NAME("LOCK ADC Ed, Gd"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGD; + SMDMB(); + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); + MARKLOCK; + LRxw(x1, wback, 1, 1); + ADDxw(x3, x1, gd); + ANDI(x4, xFlags, 1 << F_CF); + ADDxw(x3, x3, x4); + SCxw(x4, x3, wback, 1, 1); + BNEZ_MARKLOCK(x4); + IFX(X_ALL|X_PEND) { + emit_adc32(dyn, ninst, rex, x1, gd, x3, x4, x5, x6); + } + } + SMDMB(); + break; case 0x21: INST_NAME("LOCK AND Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -381,6 +476,9 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } SMDMB(); break; + case 0x66: + return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + case 0x80: nextop = F8; SMDMB(); |