Files
kaizen/src/backend/core/jit/cop/cop1decode.cpp
2023-02-21 02:20:35 +01:00

466 lines
13 KiB
C++

#include <jit/cop/cop1decode.hpp>
#include <jit/instructions.hpp>
#include <Registers.hpp>
namespace n64 {
bool cop1Decode(Registers& regs, JIT& cpu, u32 instr) {
Xbyak::CodeGenerator& code = cpu.code;
u8 mask_sub = (instr >> 21) & 0x1F;
u8 mask_fun = instr & 0x3F;
u8 mask_branch = (instr >> 16) & 0x1F;
code.mov(code.rdi, (u64)&regs);
code.mov(code.esi, instr);
switch(mask_sub) {
// 000r_rccc
case 0x00:
code.mov(code.rax, (u64)mfc1);
code.call(code.rax);
break;
case 0x01:
code.mov(code.rax, (u64)dmfc1);
code.call(code.rax);
break;
case 0x02:
code.mov(code.rax, (u64)cfc1);
code.call(code.rax);
break;
case 0x03:
Util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
case 0x04:
code.mov(code.rax, (u64)mtc1);
code.call(code.rax);
break;
case 0x05:
code.mov(code.rax, (u64)dmtc1);
code.call(code.rax);
break;
case 0x06:
code.mov(code.rax, (u64)ctc1);
code.call(code.rax);
break;
case 0x07:
Util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
case 0x08:
switch(mask_branch) {
case 0:
code.mov(code.rdi, !regs.cop1.fcr31.compare);
code.mov(code.rax, (u64)b);
code.call(code.rax);
return true;
case 1:
code.mov(code.rdi, regs.cop1.fcr31.compare);
code.mov(code.rax, (u64)b);
code.call(code.rax);
return true;
case 2:
code.mov(code.rdi, !regs.cop1.fcr31.compare);
code.mov(code.rax, (u64)bl);
code.call(code.rax);
return true;
case 3:
code.mov(code.rdi, regs.cop1.fcr31.compare);
code.mov(code.rax, (u64)bl);
code.call(code.rax);
return true;
default: Util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
}
break;
case 0x10: // s
switch(mask_fun) {
case 0x00:
code.mov(code.rax, (u64)adds);
code.call(code.rax);
break;
case 0x01:
code.mov(code.rax, (u64)subs);
code.call(code.rax);
break;
case 0x02:
code.mov(code.rax, (u64)muls);
code.call(code.rax);
break;
case 0x03:
code.mov(code.rax, (u64)divs);
code.call(code.rax);
break;
case 0x04:
code.mov(code.rax, (u64)sqrts);
code.call(code.rax);
break;
case 0x05:
code.mov(code.rax, (u64)abss);
code.call(code.rax);
break;
case 0x06:
code.mov(code.rax, (u64)movs);
code.call(code.rax);
break;
case 0x07:
code.mov(code.rax, (u64)negs);
code.call(code.rax);
break;
case 0x08:
code.mov(code.rax, (u64)roundls);
code.call(code.rax);
break;
case 0x09:
code.mov(code.rax, (u64)truncls);
code.call(code.rax);
break;
case 0x0A:
code.mov(code.rax, (u64)ceills);
code.call(code.rax);
break;
case 0x0B:
code.mov(code.rax, (u64)floorls);
code.call(code.rax);
break;
case 0x0C:
code.mov(code.rax, (u64)roundws);
code.call(code.rax);
break;
case 0x0D:
code.mov(code.rax, (u64)truncws);
code.call(code.rax);
break;
case 0x0E:
code.mov(code.rax, (u64)ceilws);
code.call(code.rax);
break;
case 0x0F:
code.mov(code.rax, (u64)floorws);
code.call(code.rax);
break;
case 0x20:
Util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
case 0x21:
code.mov(code.rax, (u64)cvtds);
code.call(code.rax);
break;
case 0x24:
code.mov(code.rax, (u64)cvtws);
code.call(code.rax);
break;
case 0x25:
code.mov(code.rax, (u64)cvtls);
code.call(code.rax);
break;
case 0x30:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, F);
code.call(code.rax);
break;
case 0x31:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, UN);
code.call(code.rax);
break;
case 0x32:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, EQ);
code.call(code.rax);
break;
case 0x33:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, UEQ);
code.call(code.rax);
break;
case 0x34:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, OLT);
code.call(code.rax);
break;
case 0x35:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, ULT);
code.call(code.rax);
break;
case 0x36:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, OLE);
code.call(code.rax);
break;
case 0x37:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, ULE);
code.call(code.rax);
break;
case 0x38:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, SF);
code.call(code.rax);
break;
case 0x39:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, NGLE);
code.call(code.rax);
break;
case 0x3A:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, SEQ);
code.call(code.rax);
break;
case 0x3B:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, NGL);
code.call(code.rax);
break;
case 0x3C:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, LT);
code.call(code.rax);
break;
case 0x3D:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, NGE);
code.call(code.rax);
break;
case 0x3E:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, LE);
code.call(code.rax);
break;
case 0x3F:
code.mov(code.rax, (u64)ccond<float>);
code.mov(code.rdx, NGT);
code.call(code.rax);
break;
default: Util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
}
break;
case 0x11: // d
switch(mask_fun) {
case 0x00:
code.mov(code.rax, (u64)addd);
code.call(code.rax);
break;
case 0x01:
code.mov(code.rax, (u64)subd);
code.call(code.rax);
break;
case 0x02:
code.mov(code.rax, (u64)muld);
code.call(code.rax);
break;
case 0x03:
code.mov(code.rax, (u64)divd);
code.call(code.rax);
break;
case 0x04:
code.mov(code.rax, (u64)sqrtd);
code.call(code.rax);
break;
case 0x05:
code.mov(code.rax, (u64)absd);
code.call(code.rax);
break;
case 0x06:
code.mov(code.rax, (u64)movd);
code.call(code.rax);
break;
case 0x07:
code.mov(code.rax, (u64)negd);
code.call(code.rax);
break;
case 0x08:
code.mov(code.rax, (u64)roundld);
code.call(code.rax);
break;
case 0x09:
code.mov(code.rax, (u64)truncld);
code.call(code.rax);
break;
case 0x0A:
code.mov(code.rax, (u64)ceilld);
code.call(code.rax);
break;
case 0x0B:
code.mov(code.rax, (u64)floorld);
code.call(code.rax);
break;
case 0x0C:
code.mov(code.rax, (u64)roundwd);
code.call(code.rax);
break;
case 0x0D:
code.mov(code.rax, (u64)truncwd);
code.call(code.rax);
break;
case 0x0E:
code.mov(code.rax, (u64)ceilwd);
code.call(code.rax);
break;
case 0x0F:
code.mov(code.rax, (u64)floorwd);
code.call(code.rax);
break;
case 0x20:
code.mov(code.rax, (u64)cvtsd);
code.call(code.rax);
break;
case 0x21:
Util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
case 0x24:
code.mov(code.rax, (u64)cvtwd);
code.call(code.rax);
break;
case 0x25:
code.mov(code.rax, (u64)cvtld);
code.call(code.rax);
break;
case 0x30:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, F);
code.call(code.rax);
break;
case 0x31:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, UN);
code.call(code.rax);
break;
case 0x32:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, EQ);
code.call(code.rax);
break;
case 0x33:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, UEQ);
code.call(code.rax);
break;
case 0x34:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, OLT);
code.call(code.rax);
break;
case 0x35:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, ULT);
code.call(code.rax);
break;
case 0x36:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, OLE);
code.call(code.rax);
break;
case 0x37:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, ULE);
code.call(code.rax);
break;
case 0x38:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, SF);
code.call(code.rax);
break;
case 0x39:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, NGLE);
code.call(code.rax);
break;
case 0x3A:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, SEQ);
code.call(code.rax);
break;
case 0x3B:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, NGL);
code.call(code.rax);
break;
case 0x3C:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, LT);
code.call(code.rax);
break;
case 0x3D:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, NGE);
code.call(code.rax);
break;
case 0x3E:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, LE);
code.call(code.rax);
break;
case 0x3F:
code.mov(code.rax, (u64)ccond<double>);
code.mov(code.rdx, NGT);
code.call(code.rax);
break;
default: Util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
}
break;
case 0x14: // w
switch(mask_fun) {
case 0x01:
code.mov(code.rax, (u64)subw);
code.call(code.rax);
break;
case 0x05:
code.mov(code.rax, (u64)absw);
code.call(code.rax);
break;
case 0x02:
code.mov(code.rax, (u64)mulw);
code.call(code.rax);
break;
case 0x06:
code.mov(code.rax, (u64)movw);
code.call(code.rax);
break;
case 0x20:
code.mov(code.rax, (u64)cvtsw);
code.call(code.rax);
break;
case 0x21:
code.mov(code.rax, (u64)cvtdw);
code.call(code.rax);
break;
case 0x24:
Util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
default: Util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
}
break;
case 0x15: // l
switch(mask_fun) {
case 0x01:
code.mov(code.rax, (u64)subl);
code.call(code.rax);
break;
case 0x05:
code.mov(code.rax, (u64)absl);
code.call(code.rax);
break;
case 0x02:
code.mov(code.rax, (u64)mull);
code.call(code.rax);
break;
case 0x06:
code.mov(code.rax, (u64)movl);
code.call(code.rax);
break;
case 0x20:
code.mov(code.rax, (u64)cvtsl);
code.call(code.rax);
break;
case 0x21:
code.mov(code.rax, (u64)cvtdl);
code.call(code.rax);
break;
case 0x24:
Util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
case 0x25:
Util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
default: Util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
}
break;
default: Util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
}
return false;
}
}