Emitting all instructions. Still boogs

This commit is contained in:
CocoSimone
2023-01-03 00:38:03 +01:00
parent f45f1417e8
commit 5da1e2a443
7 changed files with 772 additions and 133 deletions

View File

@@ -3,21 +3,60 @@
#include <dynarec/cop/cop0instructions.hpp>
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)&regs.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;

View File

@@ -1,10 +1,10 @@
#pragma once
#include <common.hpp>
#include <Dynarec.hpp>
namespace n64 {
struct Registers;
}
namespace n64::JIT {
void cop0Decode(n64::Registers& regs, u32 instr);
void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu);
}

View File

@@ -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);

View File

@@ -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&);
}

View File

@@ -3,7 +3,7 @@
#include <Registers.hpp>
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)&regs.cop0.status.raw);

View File

@@ -2,5 +2,5 @@
#include <dynarec/cop/cop1instructions.hpp>
namespace n64::JIT {
bool cop1Decode(n64::Registers& regs, Dynarec& cpu, u32 instr);
bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu);
}

View File

@@ -5,7 +5,6 @@
namespace n64::JIT {
void Dynarec::cop2Decode(n64::Registers& regs, u32 instr) {
code.push(code.rbp);
code.mov(code.rbp, (u64)&regs.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)&regs);
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)&regs);
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)&regs);
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)&regs);
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)&regs);
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)&regs);
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)&regs);
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)&regs);
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)&regs);
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)&regs);
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;
}
}