Files
kaizen/src/n64/core/cpu/decode.cpp
CocoSimone 1265279069 minor fixes
2022-10-30 15:33:53 +01:00

160 lines
6.5 KiB
C++

#include <n64/core/Cpu.hpp>
#include <util.hpp>
namespace n64 {
void Cpu::special(Mem& mem, u32 instr) {
u8 mask = (instr & 0x3F);
// 00rr_rccc
switch (mask) { // TODO: named constants for clearer code
case 0:
if (instr != 0) {
sll(instr);
}
break;
case 0x02: srl(instr); break;
case 0x03: sra(instr); break;
case 0x04: sllv(instr); break;
case 0x06: srlv(instr); break;
case 0x07: srav(instr); break;
case 0x08: jr(instr); break;
case 0x09: jalr(instr); break;
case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break;
case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break;
case 0x0F: break; // SYNC
case 0x10: mfhi(instr); break;
case 0x11: mthi(instr); break;
case 0x12: mflo(instr); break;
case 0x13: mtlo(instr); break;
case 0x14: dsllv(instr); break;
case 0x16: dsrlv(instr); break;
case 0x17: dsrav(instr); break;
case 0x18: mult(instr); break;
case 0x19: multu(instr); break;
case 0x1A: div(instr); break;
case 0x1B: divu(instr); break;
case 0x1C: dmult(instr); break;
case 0x1D: dmultu(instr); break;
case 0x1E: ddiv(instr); break;
case 0x1F: ddivu(instr); break;
case 0x20: add(instr); break;
case 0x21: addu(instr); break;
case 0x22: sub(instr); break;
case 0x23: subu(instr); break;
case 0x24: and_(instr); break;
case 0x25: or_(instr); break;
case 0x26: xor_(instr); break;
case 0x27: nor(instr); break;
case 0x2A: slt(instr); break;
case 0x2B: sltu(instr); break;
case 0x2C: dadd(instr); break;
case 0x2D: daddu(instr); break;
case 0x2E: dsub(instr); break;
case 0x2F: dsubu(instr); break;
case 0x30: trap(regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break;
case 0x31: trap((u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break;
case 0x32: trap(regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break;
case 0x33: trap((u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break;
case 0x34: trap(regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
case 0x36: trap(regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
case 0x38: dsll(instr); break;
case 0x3A: dsrl(instr); break;
case 0x3B: dsra(instr); break;
case 0x3C: dsll32(instr); break;
case 0x3E: dsrl32(instr); break;
case 0x3F: dsra32(instr); break;
default:
util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC);
}
}
void Cpu::regimm(u32 instr) {
u8 mask = ((instr >> 16) & 0x1F);
// 000r_rccc
switch (mask) { // TODO: named constants for clearer code
case 0x00: b(instr, regs.gpr[RS(instr)] < 0); break;
case 0x01: b(instr, regs.gpr[RS(instr)] >= 0); break;
case 0x02: bl(instr, regs.gpr[RS(instr)] < 0); break;
case 0x03: bl(instr, regs.gpr[RS(instr)] >= 0); break;
case 0x08: trap(regs.gpr[RS(instr)] >= s64(s16(instr))); break;
case 0x09: trap(u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break;
case 0x0A: trap(regs.gpr[RS(instr)] < s64(s16(instr))); break;
case 0x0B: trap(u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break;
case 0x0C: trap(regs.gpr[RS(instr)] == s64(s16(instr))); break;
case 0x0E: trap(regs.gpr[RS(instr)] != s64(s16(instr))); break;
case 0x10: blink(instr, regs.gpr[RS(instr)] < 0); break;
case 0x11: blink(instr, regs.gpr[RS(instr)] >= 0); break;
case 0x12: bllink(instr, regs.gpr[RS(instr)] < 0); break;
case 0x13: bllink(instr, regs.gpr[RS(instr)] >= 0); break;
default:
util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC);
}
}
void Cpu::Exec(Mem& mem, u32 instr) {
u8 mask = (instr >> 26) & 0x3f;
// 00rr_rccc
switch(mask) { // TODO: named constants for clearer code
case 0x00: special(mem, instr); break;
case 0x01: regimm(instr); break;
case 0x02: j(instr); break;
case 0x03: jal(instr); break;
case 0x04: b(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
case 0x05: {
//fmt::print("RS: {:016X}, RT: {:016X}\n", (u64)regs.gpr[RS(instr)], (u64)regs.gpr[RT(instr)]);
b(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]);
} break;
case 0x06: b(instr, regs.gpr[RS(instr)] <= 0); break;
case 0x07: b(instr, regs.gpr[RS(instr)] > 0); break;
case 0x08: addi(instr); break;
case 0x09: addiu(instr); break;
case 0x0A: slti(instr); break;
case 0x0B: sltiu(instr); break;
case 0x0C: andi(instr); break;
case 0x0D: ori(instr); break;
case 0x0E: xori(instr); break;
case 0x0F: lui(instr); break;
case 0x10: regs.cop0.decode(regs, mem, instr); break;
case 0x11: regs.cop1.decode(*this, instr); break;
case 0x12:
FireException(regs, ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
break;
case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break;
case 0x17: bl(instr, regs.gpr[RS(instr)] > 0); break;
case 0x18: daddi(instr); break;
case 0x19: daddiu(instr); break;
case 0x1A: ldl(mem, instr); break;
case 0x1B: ldr(mem, instr); break;
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break;
case 0x20: lb(mem, instr); break;
case 0x21: lh(mem, instr); break;
case 0x22: lwl(mem, instr); break;
case 0x23: lw(mem, instr); break;
case 0x24: lbu(mem, instr); break;
case 0x25: lhu(mem, instr); break;
case 0x26: lwr(mem, instr); break;
case 0x27: lwu(mem, instr); break;
case 0x28: sb(mem, instr); break;
case 0x29: sh(mem, instr); break;
case 0x2A: swl(mem, instr); break;
case 0x2B: sw(mem, instr); break;
case 0x2C: sdl(mem, instr); break;
case 0x2D: sdr(mem, instr); break;
case 0x2E: swr(mem, instr); break;
case 0x2F: break; // CACHE
case 0x30: ll(mem, instr); break;
case 0x31: regs.cop1.lwc1(regs, mem, instr); break;
case 0x34: lld(mem, instr); break;
case 0x35: regs.cop1.ldc1(regs, mem, instr); break;
case 0x37: ld(mem, instr); break;
case 0x38: sc(mem, instr); break;
case 0x39: regs.cop1.swc1(regs, mem, instr); break;
case 0x3C: scd(mem, instr); break;
case 0x3D: regs.cop1.sdc1(regs, mem, instr); break;
case 0x3F: sd(mem, instr); break;
default:
util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC);
}
}
}