diff --git a/src/backend/core/dynarec/cop/cop0decode.cpp b/src/backend/core/dynarec/cop/cop0decode.cpp index 4f6304bc..b83bb9c8 100644 --- a/src/backend/core/dynarec/cop/cop0decode.cpp +++ b/src/backend/core/dynarec/cop/cop0decode.cpp @@ -3,21 +3,60 @@ #include namespace n64::JIT { -void cop0Decode(n64::Registers& regs, u32 instr) { +void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) { u8 mask_cop = (instr >> 21) & 0x1F; u8 mask_cop2 = instr & 0x3F; + Xbyak::CodeGenerator& code = cpu.code; + switch(mask_cop) { - case 0x00: mfc0(regs, instr); break; - case 0x01: dmfc0(regs, instr); break; - case 0x04: mtc0(regs, instr); break; - case 0x05: dmtc0(regs, instr); break; + case 0x00: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)mfc0); + code.call(code.rax); + break; + case 0x01: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dmfc0); + code.call(code.rax); + break; + case 0x04: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)mtc0); + code.call(code.rax); + break; + case 0x05: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dmtc0); + code.call(code.rax); + break; case 0x10 ... 0x1F: switch(mask_cop2) { - case 0x01: tlbr(regs); break; - case 0x02: tlbw(regs.cop0.index & 0x3F, regs); break; - case 0x06: tlbw(regs.cop0.GetRandom(), regs); break; - case 0x08: tlbp(regs); break; - case 0x18: eret(regs); break; + case 0x01: + code.mov(code.rax, (u64)tlbr); + code.call(code.rax); + break; + case 0x02: + code.mov(code.rbp, (u64)®s.cop0.index); + code.and_(code.dword[code.rbp], 0x3F); + code.mov(code.rsi, code.dword[code.rbp]); + code.mov(code.rax, (u64)tlbw); + code.call(code.rax); + break; + case 0x06: + code.mov(code.rax, (u64)regs.cop0.GetRandom()); + code.call(code.rax); + code.mov(code.rsi, code.rax); + code.mov(code.rax, (u64)tlbw); + code.call(code.rax); + break; + case 0x08: + code.mov(code.rax, (u64)tlbp); + code.call(code.rax); + break; + case 0x18: + code.mov(code.rax, (u64)eret); + code.call(code.rax); + break; default: util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC); } break; diff --git a/src/backend/core/dynarec/cop/cop0decode.hpp b/src/backend/core/dynarec/cop/cop0decode.hpp index 6b46e3a0..3cb4be8e 100644 --- a/src/backend/core/dynarec/cop/cop0decode.hpp +++ b/src/backend/core/dynarec/cop/cop0decode.hpp @@ -1,10 +1,10 @@ #pragma once -#include +#include namespace n64 { struct Registers; } namespace n64::JIT { -void cop0Decode(n64::Registers& regs, u32 instr); +void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu); } \ No newline at end of file diff --git a/src/backend/core/dynarec/cop/cop0instructions.cpp b/src/backend/core/dynarec/cop/cop0instructions.cpp index fc0fec3c..99d9778d 100644 --- a/src/backend/core/dynarec/cop/cop0instructions.cpp +++ b/src/backend/core/dynarec/cop/cop0instructions.cpp @@ -48,7 +48,7 @@ void tlbr(n64::Registers& regs) { regs.cop0.pageMask.raw = entry.pageMask.raw; } -void tlbw(int index_, n64::Registers& regs) { +void tlbw(n64::Registers& regs, int index_) { PageMask page_mask = regs.cop0.pageMask; u32 top = page_mask.mask & 0xAAA; page_mask.mask = top | (top >> 1); diff --git a/src/backend/core/dynarec/cop/cop0instructions.hpp b/src/backend/core/dynarec/cop/cop0instructions.hpp index 72049a7d..a43661a3 100644 --- a/src/backend/core/dynarec/cop/cop0instructions.hpp +++ b/src/backend/core/dynarec/cop/cop0instructions.hpp @@ -8,6 +8,6 @@ void mfc0(n64::Registers&, u32); void dmfc0(n64::Registers&, u32); void eret(n64::Registers&); void tlbr(n64::Registers&); -void tlbw(int, n64::Registers&); +void tlbw(n64::Registers&, int); void tlbp(n64::Registers&); } \ No newline at end of file diff --git a/src/backend/core/dynarec/cop/cop1decode.cpp b/src/backend/core/dynarec/cop/cop1decode.cpp index 9ae4f728..9ec45eb4 100644 --- a/src/backend/core/dynarec/cop/cop1decode.cpp +++ b/src/backend/core/dynarec/cop/cop1decode.cpp @@ -3,7 +3,7 @@ #include namespace n64::JIT { -bool cop1Decode(n64::Registers& regs, Dynarec& cpu, u32 instr) { +bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) { Xbyak::CodeGenerator& code = cpu.code; code.push(code.rbp); code.mov(code.rbp, (u64)®s.cop0.status.raw); diff --git a/src/backend/core/dynarec/cop/cop1decode.hpp b/src/backend/core/dynarec/cop/cop1decode.hpp index af3590e4..b13255e5 100644 --- a/src/backend/core/dynarec/cop/cop1decode.hpp +++ b/src/backend/core/dynarec/cop/cop1decode.hpp @@ -2,5 +2,5 @@ #include namespace n64::JIT { -bool cop1Decode(n64::Registers& regs, Dynarec& cpu, u32 instr); +bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu); } \ No newline at end of file diff --git a/src/backend/core/dynarec/decode.cpp b/src/backend/core/dynarec/decode.cpp index b8838b94..5a124998 100644 --- a/src/backend/core/dynarec/decode.cpp +++ b/src/backend/core/dynarec/decode.cpp @@ -5,7 +5,6 @@ namespace n64::JIT { void Dynarec::cop2Decode(n64::Registers& regs, u32 instr) { - code.push(code.rbp); code.mov(code.rbp, (u64)®s.cop0.status.raw); code.mov(code.eax, code.dword[code.rbp]); code.pop(code.rbp); @@ -13,7 +12,6 @@ void Dynarec::cop2Decode(n64::Registers& regs, u32 instr) { code.cmp(code.eax, 1); code.je("NoException2"); - code.mov(code.rdi, (u64)®s); code.mov(code.rsi, (u64)ExceptionCode::CoprocessorUnusable); code.mov(code.rdx, 2); code.mov(code.rcx, 1); @@ -54,88 +52,299 @@ void Dynarec::cop2Decode(n64::Registers& regs, u32 instr) { bool Dynarec::special(n64::Registers& regs, u32 instr) { u8 mask = (instr & 0x3F); bool res = false; + // 00rr_rccc switch (mask) { // TODO: named constants for clearer code case 0: - if (instr != 0) { - sll(regs, instr); + if (instr == 0) { + code.nop(); + } else { + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)sll); + code.call(code.rax); } break; - case 0x02: srl(regs, instr); break; - case 0x03: sra(regs, instr); break; - case 0x04: sllv(regs, instr); break; - case 0x06: srlv(regs, instr); break; - case 0x07: srav(regs, instr); break; + case 0x02: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)srl); + code.call(code.rax); + break; + case 0x03: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)sra); + code.call(code.rax); + break; + case 0x04: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)sllv); + code.call(code.rax); + break; + case 0x06: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)srlv); + code.call(code.rax); + break; + case 0x07: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)srav); + code.call(code.rax); + break; case 0x08: - jr(regs, instr); + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)jr); + code.call(code.rax); res = true; break; case 0x09: - jalr(regs, instr); + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)jalr); + code.call(code.rax); res = true; break; case 0x0C: util::panic("[RECOMPILER] Unhandled syscall instruction {:016X}\n", (u64)regs.pc); case 0x0D: util::panic("[RECOMPILER] Unhandled break instruction {:016X}\n", (u64)regs.pc); case 0x0F: code.nop(); break; // SYNC - case 0x10: mfhi(regs, instr); break; - case 0x11: mthi(regs, instr); break; - case 0x12: mflo(regs, instr); break; - case 0x13: mtlo(regs, instr); break; - case 0x14: dsllv(regs, instr); break; - case 0x16: dsrlv(regs, instr); break; - case 0x17: dsrav(regs, instr); break; - case 0x18: mult(regs, instr); break; - case 0x19: multu(regs, instr); break; - case 0x1A: div(regs, instr); break; - case 0x1B: divu(regs, instr); break; - case 0x1C: dmult(regs, instr); break; - case 0x1D: dmultu(regs, instr); break; - case 0x1E: ddiv(regs, instr); break; - case 0x1F: ddivu(regs, instr); break; - case 0x20: add(regs, instr); break; - case 0x21: addu(regs, instr); break; - case 0x22: sub(regs, instr); break; - case 0x23: subu(regs, instr); break; - case 0x24: and_(regs, instr); break; - case 0x25: or_(regs, instr); break; - case 0x26: xor_(regs, instr); break; - case 0x27: nor(regs, instr); break; - case 0x2A: slt(regs, instr); break; - case 0x2B: sltu(regs, instr); break; - case 0x2C: dadd(regs, instr); break; - case 0x2D: daddu(regs, instr); break; - case 0x2E: dsub(regs, instr); break; - case 0x2F: dsubu(regs, instr); break; + case 0x10: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)mfhi); + code.call(code.rax); + break; + case 0x11: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)mthi); + code.call(code.rax); + break; + case 0x12: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)mflo); + code.call(code.rax); + break; + case 0x13: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)mtlo); + code.call(code.rax); + break; + case 0x14: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsllv); + code.call(code.rax); + break; + case 0x16: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsrlv); + code.call(code.rax); + break; + case 0x17: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsrav); + code.call(code.rax); + break; + case 0x18: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)mult); + code.call(code.rax); + break; + case 0x19: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)multu); + code.call(code.rax); + break; + case 0x1A: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)div); + code.call(code.rax); + break; + case 0x1B: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)divu); + code.call(code.rax); + break; + case 0x1C: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dmult); + code.call(code.rax); + break; + case 0x1D: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dmultu); + code.call(code.rax); + break; + case 0x1E: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)ddiv); + code.call(code.rax); + break; + case 0x1F: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)ddivu); + code.call(code.rax); + break; + case 0x20: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)add); + code.call(code.rax); + break; + case 0x21: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)addu); + code.call(code.rax); + break; + case 0x22: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)sub); + code.call(code.rax); + break; + case 0x23: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)subu); + code.call(code.rax); + break; + case 0x24: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)and_); + code.call(code.rax); + break; + case 0x25: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)or_); + code.call(code.rax); + break; + case 0x26: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)xor_); + code.call(code.rax); + break; + case 0x27: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)nor); + code.call(code.rax); + break; + case 0x2A: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)slt); + code.call(code.rax); + break; + case 0x2B: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)sltu); + code.call(code.rax); + break; + case 0x2C: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dadd); + code.call(code.rax); + break; + case 0x2D: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)daddu); + code.call(code.rax); + break; + case 0x2E: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsub); + code.call(code.rax); + break; + case 0x2F: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsubu); + code.call(code.rax); + break; case 0x30: - trap(regs, regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmovge(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); res = true; break; case 0x31: - trap(regs, (u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmovae(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); res = true; break; case 0x32: - trap(regs, regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmovl(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); res = true; break; case 0x33: - trap(regs, (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmovb(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); res = true; break; case 0x34: - trap(regs, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmove(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); res = true; break; case 0x36: - trap(regs, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmovne(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); res = true; break; - case 0x38: dsll(regs, instr); break; - case 0x3A: dsrl(regs, instr); break; - case 0x3B: dsra(regs, instr); break; - case 0x3C: dsll32(regs, instr); break; - case 0x3E: dsrl32(regs, instr); break; - case 0x3F: dsra32(regs, instr); break; + case 0x38: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsll); + code.call(code.rax); + break; + case 0x3A: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsrl); + code.call(code.rax); + break; + case 0x3B: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsra); + code.call(code.rax); + break; + case 0x3C: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsll32); + code.call(code.rax); + break; + case 0x3E: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsrl32); + code.call(code.rax); + break; + case 0x3F: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)dsra32); + code.call(code.rax); + break; default: util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC); } @@ -147,20 +356,154 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { u8 mask = ((instr >> 16) & 0x1F); // 000r_rccc switch (mask) { // TODO: named constants for clearer code - case 0x00: b(regs, instr, regs.gpr[RS(instr)] < 0); break; - case 0x01: b(regs, instr, regs.gpr[RS(instr)] >= 0); break; - case 0x02: bl(regs, instr, regs.gpr[RS(instr)] < 0); break; - case 0x03: bl(regs, instr, regs.gpr[RS(instr)] >= 0); break; - case 0x08: trap(regs, regs.gpr[RS(instr)] >= s64(s16(instr))); break; - case 0x09: trap(regs, u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break; - case 0x0A: trap(regs, regs.gpr[RS(instr)] < s64(s16(instr))); break; - case 0x0B: trap(regs, u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break; - case 0x0C: trap(regs, regs.gpr[RS(instr)] == s64(s16(instr))); break; - case 0x0E: trap(regs, regs.gpr[RS(instr)] != s64(s16(instr))); break; - case 0x10: blink(regs, instr, regs.gpr[RS(instr)] < 0); break; - case 0x11: blink(regs, instr, regs.gpr[RS(instr)] >= 0); break; - case 0x12: bllink(regs, instr, regs.gpr[RS(instr)] < 0); break; - case 0x13: bllink(regs, instr, regs.gpr[RS(instr)] >= 0); break; + case 0x00: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovl(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)b); + code.call(code.rax); + break; + case 0x01: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovge(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)b); + code.call(code.rax); + break; + case 0x02: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovl(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)bl); + code.call(code.rax); + break; + case 0x03: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovge(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)bl); + code.call(code.rax); + break; + case 0x08: + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], s64(s16(instr))); + code.cmovge(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); + break; + case 0x09: + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], u64(s64(s16(instr)))); + code.cmovae(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); + break; + case 0x0A: + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], s64(s16(instr))); + code.cmovl(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); + break; + case 0x0B: + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], u64(s64(s16(instr)))); + code.cmovb(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); + break; + case 0x0C: + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], s64(s16(instr))); + code.cmove(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); + break; + case 0x0E: + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], s64(s16(instr))); + code.cmovne(code.cl, code.ch); + code.mov(code.rsi, code.cl.cvt64()); + code.mov(code.rax, (u64)trap); + code.call(code.rax); + break; + case 0x10: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovl(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)blink); + code.call(code.rax); + break; + case 0x11: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovge(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)blink); + code.call(code.rax); + break; + case 0x12: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovl(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)bllink); + code.call(code.rax); + break; + case 0x13: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)regs.gpr); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovge(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)bllink); + code.call(code.rax); + break; default: util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC); } @@ -171,84 +514,341 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { u8 mask = (instr >> 26) & 0x3f; bool res = false; + + code.mov(code.rdi, (u64)®s); + code.push(code.rbp); // 00rr_rccc switch(mask) { // TODO: named constants for clearer code case 0x00: res = special(regs, instr); break; case 0x01: res = regimm(regs, instr); break; case 0x02: - j(regs, instr); + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)j); + code.call(code.rax); res = true; break; case 0x03: - jal(regs, instr); + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)jal); + code.call(code.rax); res = true; break; case 0x04: - b(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)®s); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmove(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)b); + code.call(code.rax); res = true; break; case 0x05: - b(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)®s); + code.mov(code.r8, 0); + code.mov(code.r9, 1); + code.mov(code.rax, code.qword[code.rbp + offsetof(n64::Registers, gpr[RS(instr)])]); + code.mov(code.rcx, code.qword[code.rbp + offsetof(n64::Registers, gpr[RT(instr)])]); + code.cmp(code.rax, code.rcx); + code.cmovne(code.r8, code.r9); + code.mov(code.rdx, code.r8); + code.mov(code.rax, (u64)b); + code.call(code.rax); res = true; break; case 0x06: - b(regs, instr, regs.gpr[RS(instr)] <= 0); + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)®s); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovle(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)b); + code.call(code.rax); res = true; break; case 0x07: - b(regs, instr, regs.gpr[RS(instr)] > 0); + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)®s); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovg(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)b); + code.call(code.rax); res = true; break; - case 0x08: addi(regs, instr); break; - case 0x09: addiu(regs, instr); break; - case 0x0A: slti(regs, instr); break; - case 0x0B: sltiu(regs, instr); break; - case 0x0C: andi(regs, instr); break; - case 0x0D: ori(regs, instr); break; - case 0x0E: xori(regs, instr); break; - case 0x0F: lui(regs, instr); break; - case 0x10: cop0Decode(regs, instr); break; - case 0x11: res = cop1Decode(regs, *this, instr); break; + case 0x08: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)addi); + code.call(code.rax); + break; + case 0x09: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)addiu); + code.call(code.rax); + break; + case 0x0A: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)slti); + code.call(code.rax); + break; + case 0x0B: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)sltiu); + code.call(code.rax); + break; + case 0x0C: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)andi); + code.call(code.rax); + break; + case 0x0D: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)ori); + code.call(code.rax); + break; + case 0x0E: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)xori); + code.call(code.rax); + break; + case 0x0F: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)lui); + code.call(code.rax); + break; + case 0x10: cop0Decode(regs, instr, *this); break; + case 0x11: res = cop1Decode(regs, instr, *this); break; case 0x12: cop2Decode(regs, instr); break; - case 0x14: bl(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; - case 0x15: bl(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; - case 0x16: bl(regs, instr, regs.gpr[RS(instr)] <= 0); break; - case 0x17: bl(regs, instr, regs.gpr[RS(instr)] > 0); break; - case 0x18: daddi(regs, instr); break; - case 0x19: daddiu(regs, instr); break; - case 0x1A: ldl(regs, mem, instr); break; - case 0x1B: ldr(regs, mem, instr); break; - case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, true); break; - case 0x20: lb(regs, mem, instr); break; - case 0x21: lh(regs, mem, instr); break; - case 0x22: lwl(regs, mem, instr); break; - case 0x23: lw(regs, mem, instr); break; - case 0x24: lbu(regs, mem, instr); break; - case 0x25: lhu(regs, mem, instr); break; - case 0x26: lwr(regs, mem, instr); break; - case 0x27: lwu(regs, mem, instr); break; - case 0x28: sb(regs, mem, instr); break; - case 0x29: sh(regs, mem, instr); break; - case 0x2A: swl(regs, mem, instr); break; - case 0x2B: sw(regs, mem, instr); break; - case 0x2C: sdl(regs, mem, instr); break; - case 0x2D: sdr(regs, mem, instr); break; - case 0x2E: swr(regs, mem, instr); break; - case 0x2F: break; // CACHE - case 0x30: ll(regs, mem, instr); break; - case 0x31: lwc1(regs, mem, instr); break; - case 0x34: lld(regs, mem, instr); break; - case 0x35: ldc1(regs, mem, instr); break; - case 0x37: ld(regs, mem, instr); break; - case 0x38: sc(regs, mem, instr); break; - case 0x39: swc1(regs, mem, instr); break; - case 0x3C: scd(regs, mem, instr); break; - case 0x3D: sdc1(regs, mem, instr); break; - case 0x3F: sd(regs, mem, instr); break; + case 0x14: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)®s); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmove(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)bl); + code.call(code.rax); + break; + case 0x15: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)®s); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], code.qword[RT(instr)]); + code.cmovne(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)bl); + code.call(code.rax); + break; + case 0x16: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)®s); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovle(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)bl); + code.call(code.rax); + break; + case 0x17: + code.mov(code.rsi, (u64)instr); + code.mov(code.rbp, (u64)®s); + code.mov(code.cl, 0); + code.mov(code.ch, 1); + code.cmp(code.qword[RS(instr)], 0); + code.cmovg(code.cl, code.ch); + code.mov(code.rdx, code.cl.cvt64()); + code.mov(code.rax, (u64)b); + code.call(code.rax); + break; + case 0x18: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)daddi); + code.call(code.rax); + break; + case 0x19: + code.mov(code.rsi, (u64)instr); + code.mov(code.rax, (u64)daddiu); + code.call(code.rax); + break; + case 0x1A: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)ldl); + code.call(code.rax); + break; + case 0x1B: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)ldr); + code.call(code.rax); + break; + case 0x1F: util::panic("[RECOMPILER] Unhandled reserved instruction exception {:016X}\n", regs.oldPC); break; + case 0x20: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lb); + code.call(code.rax); + break; + case 0x21: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lh); + code.call(code.rax); + break; + case 0x22: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lwl); + code.call(code.rax); + break; + case 0x23: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lw); + code.call(code.rax); + break; + case 0x24: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lbu); + code.call(code.rax); + break; + case 0x25: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lhu); + code.call(code.rax); + break; + case 0x26: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lwr); + code.call(code.rax); + break; + case 0x27: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lwu); + code.call(code.rax); + break; + case 0x28: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)sb); + code.call(code.rax); + break; + case 0x29: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)sh); + code.call(code.rax); + break; + case 0x2A: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)swl); + code.call(code.rax); + break; + case 0x2B: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)sw); + code.call(code.rax); + break; + case 0x2C: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)sdl); + code.call(code.rax); + break; + case 0x2D: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)sdr); + code.call(code.rax); + break; + case 0x2E: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)swr); + code.call(code.rax); + break; + case 0x2F: code.nop(); break; // CACHE + case 0x30: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)ll); + code.call(code.rax); + break; + case 0x31: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lwc1); + code.call(code.rax); + break; + case 0x34: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)lld); + code.call(code.rax); + break; + case 0x35: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)ldc1); + code.call(code.rax); + break; + case 0x37: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)ld); + code.call(code.rax); + break; + case 0x38: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)sc); + code.call(code.rax); + break; + case 0x39: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)swc1); + code.call(code.rax); + break; + case 0x3C: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)scd); + code.call(code.rax); + break; + case 0x3D: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)sdc1); + code.call(code.rax); + break; + case 0x3F: + code.mov(code.rsi, (u64)&mem); + code.mov(code.rdx, (u64)instr); + code.mov(code.rax, (u64)sd); + code.call(code.rax); + break; default: util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC); } + code.pop(code.rbp); return res; } }