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