- Stop using inheritance for CPU, instead use composition.
- Introduce KAIZEN_JIT_ENABLED optional define instead of relying on __aarch64__ and the like. - More cache work
This commit is contained in:
@@ -4,452 +4,457 @@
|
||||
|
||||
namespace n64 {
|
||||
void Interpreter::special(const Instruction instr) {
|
||||
// 00rr_rccc
|
||||
switch (instr.special()) {
|
||||
case Instruction::SLL:
|
||||
if (instr.instr.raw != 0) {
|
||||
sll(instr);
|
||||
// 00rr_rccc
|
||||
switch (instr.special()) {
|
||||
case Instruction::SLL:
|
||||
if (instr.instr.raw != 0) {
|
||||
sll(instr);
|
||||
}
|
||||
break;
|
||||
case Instruction::SRL:
|
||||
srl(instr);
|
||||
break;
|
||||
case Instruction::SRA:
|
||||
sra(instr);
|
||||
break;
|
||||
case Instruction::SLLV:
|
||||
sllv(instr);
|
||||
break;
|
||||
case Instruction::SRLV:
|
||||
srlv(instr);
|
||||
break;
|
||||
case Instruction::SRAV:
|
||||
srav(instr);
|
||||
break;
|
||||
case Instruction::JR:
|
||||
jr(instr);
|
||||
break;
|
||||
case Instruction::JALR:
|
||||
jalr(instr);
|
||||
break;
|
||||
case Instruction::SYSCALL:
|
||||
regs.cop0.FireException(ExceptionCode::Syscall, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::BREAK:
|
||||
regs.cop0.FireException(ExceptionCode::Breakpoint, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::SYNC:
|
||||
break; // SYNC
|
||||
case Instruction::MFHI:
|
||||
mfhi(instr);
|
||||
break;
|
||||
case Instruction::MTHI:
|
||||
mthi(instr);
|
||||
break;
|
||||
case Instruction::MFLO:
|
||||
mflo(instr);
|
||||
break;
|
||||
case Instruction::MTLO:
|
||||
mtlo(instr);
|
||||
break;
|
||||
case Instruction::DSLLV:
|
||||
dsllv(instr);
|
||||
break;
|
||||
case Instruction::DSRLV:
|
||||
dsrlv(instr);
|
||||
break;
|
||||
case Instruction::DSRAV:
|
||||
dsrav(instr);
|
||||
break;
|
||||
case Instruction::MULT:
|
||||
mult(instr);
|
||||
break;
|
||||
case Instruction::MULTU:
|
||||
multu(instr);
|
||||
break;
|
||||
case Instruction::DIV:
|
||||
div(instr);
|
||||
break;
|
||||
case Instruction::DIVU:
|
||||
divu(instr);
|
||||
break;
|
||||
case Instruction::DMULT:
|
||||
dmult(instr);
|
||||
break;
|
||||
case Instruction::DMULTU:
|
||||
dmultu(instr);
|
||||
break;
|
||||
case Instruction::DDIV:
|
||||
ddiv(instr);
|
||||
break;
|
||||
case Instruction::DDIVU:
|
||||
ddivu(instr);
|
||||
break;
|
||||
case Instruction::ADD:
|
||||
add(instr);
|
||||
break;
|
||||
case Instruction::ADDU:
|
||||
addu(instr);
|
||||
break;
|
||||
case Instruction::SUB:
|
||||
sub(instr);
|
||||
break;
|
||||
case Instruction::SUBU:
|
||||
subu(instr);
|
||||
break;
|
||||
case Instruction::AND:
|
||||
and_(instr);
|
||||
break;
|
||||
case Instruction::OR:
|
||||
or_(instr);
|
||||
break;
|
||||
case Instruction::XOR:
|
||||
xor_(instr);
|
||||
break;
|
||||
case Instruction::NOR:
|
||||
nor(instr);
|
||||
break;
|
||||
case Instruction::SLT:
|
||||
slt(instr);
|
||||
break;
|
||||
case Instruction::SLTU:
|
||||
sltu(instr);
|
||||
break;
|
||||
case Instruction::DADD:
|
||||
dadd(instr);
|
||||
break;
|
||||
case Instruction::DADDU:
|
||||
daddu(instr);
|
||||
break;
|
||||
case Instruction::DSUB:
|
||||
dsub(instr);
|
||||
break;
|
||||
case Instruction::DSUBU:
|
||||
dsubu(instr);
|
||||
break;
|
||||
case Instruction::TGE:
|
||||
trap(regs.Read<s64>(instr.rs()) >= regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TGEU:
|
||||
trap(regs.Read<u64>(instr.rs()) >= regs.Read<u64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TLT:
|
||||
trap(regs.Read<s64>(instr.rs()) < regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TLTU:
|
||||
trap(regs.Read<u64>(instr.rs()) < regs.Read<u64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TEQ:
|
||||
trap(regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TNE:
|
||||
trap(regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::DSLL:
|
||||
dsll(instr);
|
||||
break;
|
||||
case Instruction::DSRL:
|
||||
dsrl(instr);
|
||||
break;
|
||||
case Instruction::DSRA:
|
||||
dsra(instr);
|
||||
break;
|
||||
case Instruction::DSLL32:
|
||||
dsll32(instr);
|
||||
break;
|
||||
case Instruction::DSRL32:
|
||||
dsrl32(instr);
|
||||
break;
|
||||
case Instruction::DSRA32:
|
||||
dsra32(instr);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.special_hi,
|
||||
instr.instr.opcode.special_lo, instr.instr.raw, static_cast<u64>(regs.oldPC));
|
||||
}
|
||||
break;
|
||||
case Instruction::SRL:
|
||||
srl(instr);
|
||||
break;
|
||||
case Instruction::SRA:
|
||||
sra(instr);
|
||||
break;
|
||||
case Instruction::SLLV:
|
||||
sllv(instr);
|
||||
break;
|
||||
case Instruction::SRLV:
|
||||
srlv(instr);
|
||||
break;
|
||||
case Instruction::SRAV:
|
||||
srav(instr);
|
||||
break;
|
||||
case Instruction::JR:
|
||||
jr(instr);
|
||||
break;
|
||||
case Instruction::JALR:
|
||||
jalr(instr);
|
||||
break;
|
||||
case Instruction::SYSCALL:
|
||||
regs.cop0.FireException(ExceptionCode::Syscall, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::BREAK:
|
||||
regs.cop0.FireException(ExceptionCode::Breakpoint, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::SYNC:
|
||||
break; // SYNC
|
||||
case Instruction::MFHI:
|
||||
mfhi(instr);
|
||||
break;
|
||||
case Instruction::MTHI:
|
||||
mthi(instr);
|
||||
break;
|
||||
case Instruction::MFLO:
|
||||
mflo(instr);
|
||||
break;
|
||||
case Instruction::MTLO:
|
||||
mtlo(instr);
|
||||
break;
|
||||
case Instruction::DSLLV:
|
||||
dsllv(instr);
|
||||
break;
|
||||
case Instruction::DSRLV:
|
||||
dsrlv(instr);
|
||||
break;
|
||||
case Instruction::DSRAV:
|
||||
dsrav(instr);
|
||||
break;
|
||||
case Instruction::MULT:
|
||||
mult(instr);
|
||||
break;
|
||||
case Instruction::MULTU:
|
||||
multu(instr);
|
||||
break;
|
||||
case Instruction::DIV:
|
||||
div(instr);
|
||||
break;
|
||||
case Instruction::DIVU:
|
||||
divu(instr);
|
||||
break;
|
||||
case Instruction::DMULT:
|
||||
dmult(instr);
|
||||
break;
|
||||
case Instruction::DMULTU:
|
||||
dmultu(instr);
|
||||
break;
|
||||
case Instruction::DDIV:
|
||||
ddiv(instr);
|
||||
break;
|
||||
case Instruction::DDIVU:
|
||||
ddivu(instr);
|
||||
break;
|
||||
case Instruction::ADD:
|
||||
add(instr);
|
||||
break;
|
||||
case Instruction::ADDU:
|
||||
addu(instr);
|
||||
break;
|
||||
case Instruction::SUB:
|
||||
sub(instr);
|
||||
break;
|
||||
case Instruction::SUBU:
|
||||
subu(instr);
|
||||
break;
|
||||
case Instruction::AND:
|
||||
and_(instr);
|
||||
break;
|
||||
case Instruction::OR:
|
||||
or_(instr);
|
||||
break;
|
||||
case Instruction::XOR:
|
||||
xor_(instr);
|
||||
break;
|
||||
case Instruction::NOR:
|
||||
nor(instr);
|
||||
break;
|
||||
case Instruction::SLT:
|
||||
slt(instr);
|
||||
break;
|
||||
case Instruction::SLTU:
|
||||
sltu(instr);
|
||||
break;
|
||||
case Instruction::DADD:
|
||||
dadd(instr);
|
||||
break;
|
||||
case Instruction::DADDU:
|
||||
daddu(instr);
|
||||
break;
|
||||
case Instruction::DSUB:
|
||||
dsub(instr);
|
||||
break;
|
||||
case Instruction::DSUBU:
|
||||
dsubu(instr);
|
||||
break;
|
||||
case Instruction::TGE:
|
||||
trap(regs.Read<s64>(instr.rs()) >= regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TGEU:
|
||||
trap(regs.Read<u64>(instr.rs()) >= regs.Read<u64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TLT:
|
||||
trap(regs.Read<s64>(instr.rs()) < regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TLTU:
|
||||
trap(regs.Read<u64>(instr.rs()) < regs.Read<u64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TEQ:
|
||||
trap(regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::TNE:
|
||||
trap(regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::DSLL:
|
||||
dsll(instr);
|
||||
break;
|
||||
case Instruction::DSRL:
|
||||
dsrl(instr);
|
||||
break;
|
||||
case Instruction::DSRA:
|
||||
dsra(instr);
|
||||
break;
|
||||
case Instruction::DSLL32:
|
||||
dsll32(instr);
|
||||
break;
|
||||
case Instruction::DSRL32:
|
||||
dsrl32(instr);
|
||||
break;
|
||||
case Instruction::DSRA32:
|
||||
dsra32(instr);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.special_hi, instr.instr.opcode.special_lo, instr.instr.raw,
|
||||
static_cast<u64>(regs.oldPC));
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::regimm(const Instruction instr) {
|
||||
// 000r_rccc
|
||||
switch (instr.regimm()) {
|
||||
case Instruction::BLTZ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||
break;
|
||||
case Instruction::BGEZ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||
break;
|
||||
case Instruction::BLTZL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||
break;
|
||||
case Instruction::BGEZL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||
break;
|
||||
case Instruction::TGEI:
|
||||
trap(regs.Read<s64>(instr.rs()) >= static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||
break;
|
||||
case Instruction::TGEIU:
|
||||
trap(regs.Read<u64>(instr.rs()) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr.instr.itype.imm))));
|
||||
break;
|
||||
case Instruction::TLTI:
|
||||
trap(regs.Read<s64>(instr.rs()) < static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||
break;
|
||||
case Instruction::TLTIU:
|
||||
trap(regs.Read<u64>(instr.rs()) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr.instr.itype.imm))));
|
||||
break;
|
||||
case Instruction::TEQI:
|
||||
trap(regs.Read<s64>(instr.rs()) == static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||
break;
|
||||
case Instruction::TNEI:
|
||||
trap(regs.Read<s64>(instr.rs()) != static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||
break;
|
||||
case Instruction::BLTZAL:
|
||||
blink(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||
break;
|
||||
case Instruction::BGEZAL:
|
||||
blink(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||
break;
|
||||
case Instruction::BLTZALL:
|
||||
bllink(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||
break;
|
||||
case Instruction::BGEZALL:
|
||||
bllink(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.regimm_hi,
|
||||
instr.instr.opcode.regimm_lo, u32(instr), static_cast<u64>(regs.oldPC));
|
||||
}
|
||||
// 000r_rccc
|
||||
switch (instr.regimm()) {
|
||||
case Instruction::BLTZ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||
break;
|
||||
case Instruction::BGEZ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||
break;
|
||||
case Instruction::BLTZL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||
break;
|
||||
case Instruction::BGEZL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||
break;
|
||||
case Instruction::TGEI:
|
||||
trap(regs.Read<s64>(instr.rs()) >= static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||
break;
|
||||
case Instruction::TGEIU:
|
||||
trap(regs.Read<u64>(instr.rs()) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr.instr.itype.imm))));
|
||||
break;
|
||||
case Instruction::TLTI:
|
||||
trap(regs.Read<s64>(instr.rs()) < static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||
break;
|
||||
case Instruction::TLTIU:
|
||||
trap(regs.Read<u64>(instr.rs()) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr.instr.itype.imm))));
|
||||
break;
|
||||
case Instruction::TEQI:
|
||||
trap(regs.Read<s64>(instr.rs()) == static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||
break;
|
||||
case Instruction::TNEI:
|
||||
trap(regs.Read<s64>(instr.rs()) != static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||
break;
|
||||
case Instruction::BLTZAL:
|
||||
blink(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||
break;
|
||||
case Instruction::BGEZAL:
|
||||
blink(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||
break;
|
||||
case Instruction::BLTZALL:
|
||||
bllink(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||
break;
|
||||
case Instruction::BGEZALL:
|
||||
bllink(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.regimm_hi,
|
||||
instr.instr.opcode.regimm_lo, u32(instr), static_cast<u64>(regs.oldPC));
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::cop2Decode(const Instruction instr) {
|
||||
if (!regs.cop0.status.cu2) {
|
||||
regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
switch (instr.rs()) {
|
||||
case 0x00:
|
||||
mfc2(instr);
|
||||
break;
|
||||
case 0x01:
|
||||
dmfc2(instr);
|
||||
break;
|
||||
case 0x02:
|
||||
cfc2(instr);
|
||||
break;
|
||||
case 0x04:
|
||||
mtc2(instr);
|
||||
break;
|
||||
case 0x05:
|
||||
dmtc2(instr);
|
||||
break;
|
||||
case 0x06:
|
||||
ctc2(instr);
|
||||
break;
|
||||
default:
|
||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 2, regs.oldPC);
|
||||
}
|
||||
if (!regs.cop0.status.cu2) {
|
||||
regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
switch (instr.rs()) {
|
||||
case 0x00:
|
||||
mfc2(instr);
|
||||
break;
|
||||
case 0x01:
|
||||
dmfc2(instr);
|
||||
break;
|
||||
case 0x02:
|
||||
cfc2(instr);
|
||||
break;
|
||||
case 0x04:
|
||||
mtc2(instr);
|
||||
break;
|
||||
case 0x05:
|
||||
dmtc2(instr);
|
||||
break;
|
||||
case 0x06:
|
||||
ctc2(instr);
|
||||
break;
|
||||
default:
|
||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 2, regs.oldPC);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::Exec(const Instruction instr) {
|
||||
// 00rr_rccc
|
||||
switch (instr.opcode()) {
|
||||
case Instruction::SPECIAL:
|
||||
special(instr);
|
||||
break;
|
||||
case Instruction::REGIMM:
|
||||
regimm(instr);
|
||||
break;
|
||||
case Instruction::J:
|
||||
j(instr);
|
||||
break;
|
||||
case Instruction::JAL:
|
||||
jal(instr);
|
||||
break;
|
||||
case Instruction::BEQ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::BNE:
|
||||
b(instr, regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::BLEZ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) <= 0);
|
||||
break;
|
||||
case Instruction::BGTZ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) > 0);
|
||||
break;
|
||||
case Instruction::ADDI:
|
||||
addi(instr);
|
||||
break;
|
||||
case Instruction::ADDIU:
|
||||
addiu(instr);
|
||||
break;
|
||||
case Instruction::SLTI:
|
||||
slti(instr);
|
||||
break;
|
||||
case Instruction::SLTIU:
|
||||
sltiu(instr);
|
||||
break;
|
||||
case Instruction::ANDI:
|
||||
andi(instr);
|
||||
break;
|
||||
case Instruction::ORI:
|
||||
ori(instr);
|
||||
break;
|
||||
case Instruction::XORI:
|
||||
xori(instr);
|
||||
break;
|
||||
case Instruction::LUI:
|
||||
lui(instr);
|
||||
break;
|
||||
case Instruction::COP0:
|
||||
regs.cop0.decode(instr);
|
||||
break;
|
||||
case Instruction::COP1:
|
||||
if(instr.cop_rs() == 0x08) {
|
||||
switch (instr.cop_rt()) {
|
||||
case 0:
|
||||
if (!regs.cop1.CheckFPUUsable())
|
||||
// 00rr_rccc
|
||||
switch (instr.opcode()) {
|
||||
case Instruction::SPECIAL:
|
||||
special(instr);
|
||||
break;
|
||||
case Instruction::REGIMM:
|
||||
regimm(instr);
|
||||
break;
|
||||
case Instruction::J:
|
||||
j(instr);
|
||||
break;
|
||||
case Instruction::JAL:
|
||||
jal(instr);
|
||||
break;
|
||||
case Instruction::BEQ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::BNE:
|
||||
b(instr, regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::BLEZ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) <= 0);
|
||||
break;
|
||||
case Instruction::BGTZ:
|
||||
b(instr, regs.Read<s64>(instr.rs()) > 0);
|
||||
break;
|
||||
case Instruction::ADDI:
|
||||
addi(instr);
|
||||
break;
|
||||
case Instruction::ADDIU:
|
||||
addiu(instr);
|
||||
break;
|
||||
case Instruction::SLTI:
|
||||
slti(instr);
|
||||
break;
|
||||
case Instruction::SLTIU:
|
||||
sltiu(instr);
|
||||
break;
|
||||
case Instruction::ANDI:
|
||||
andi(instr);
|
||||
break;
|
||||
case Instruction::ORI:
|
||||
ori(instr);
|
||||
break;
|
||||
case Instruction::XORI:
|
||||
xori(instr);
|
||||
break;
|
||||
case Instruction::LUI:
|
||||
lui(instr);
|
||||
break;
|
||||
case Instruction::COP0:
|
||||
regs.cop0.decode(instr);
|
||||
break;
|
||||
case Instruction::COP1:
|
||||
if (instr.cop_rs() == 0x08) {
|
||||
switch (instr.cop_rt()) {
|
||||
case 0:
|
||||
if (!regs.cop1.CheckFPUUsable())
|
||||
return;
|
||||
b(instr, !regs.cop1.fcr31.compare);
|
||||
break;
|
||||
case 1:
|
||||
if (!regs.cop1.CheckFPUUsable())
|
||||
return;
|
||||
b(instr, regs.cop1.fcr31.compare);
|
||||
break;
|
||||
case 2:
|
||||
if (!regs.cop1.CheckFPUUsable())
|
||||
return;
|
||||
bl(instr, !regs.cop1.fcr31.compare);
|
||||
break;
|
||||
case 3:
|
||||
if (!regs.cop1.CheckFPUUsable())
|
||||
return;
|
||||
bl(instr, regs.cop1.fcr31.compare);
|
||||
break;
|
||||
default:
|
||||
panic("Undefined BC COP1 {:02X}", instr.cop_rt());
|
||||
}
|
||||
return;
|
||||
b(instr, !regs.cop1.fcr31.compare);
|
||||
break;
|
||||
case 1:
|
||||
if (!regs.cop1.CheckFPUUsable())
|
||||
}
|
||||
regs.cop1.decode(instr);
|
||||
break;
|
||||
case Instruction::COP2:
|
||||
cop2Decode(instr);
|
||||
break;
|
||||
case Instruction::BEQL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::BNEL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::BLEZL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) <= 0);
|
||||
break;
|
||||
case Instruction::BGTZL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) > 0);
|
||||
break;
|
||||
case Instruction::DADDI:
|
||||
daddi(instr);
|
||||
break;
|
||||
case Instruction::DADDIU:
|
||||
daddiu(instr);
|
||||
break;
|
||||
case Instruction::LDL:
|
||||
ldl(instr);
|
||||
break;
|
||||
case Instruction::LDR:
|
||||
ldr(instr);
|
||||
break;
|
||||
case 0x1F:
|
||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::LB:
|
||||
lb(instr);
|
||||
break;
|
||||
case Instruction::LH:
|
||||
lh(instr);
|
||||
break;
|
||||
case Instruction::LWL:
|
||||
lwl(instr);
|
||||
break;
|
||||
case Instruction::LW:
|
||||
lw(instr);
|
||||
break;
|
||||
case Instruction::LBU:
|
||||
lbu(instr);
|
||||
break;
|
||||
case Instruction::LHU:
|
||||
lhu(instr);
|
||||
break;
|
||||
case Instruction::LWR:
|
||||
lwr(instr);
|
||||
break;
|
||||
case Instruction::LWU:
|
||||
lwu(instr);
|
||||
break;
|
||||
case Instruction::SB:
|
||||
sb(instr);
|
||||
break;
|
||||
case Instruction::SH:
|
||||
sh(instr);
|
||||
break;
|
||||
case Instruction::SWL:
|
||||
swl(instr);
|
||||
break;
|
||||
case Instruction::SW:
|
||||
sw(instr);
|
||||
break;
|
||||
case Instruction::SDL:
|
||||
sdl(instr);
|
||||
break;
|
||||
case Instruction::SDR:
|
||||
sdr(instr);
|
||||
break;
|
||||
case Instruction::SWR:
|
||||
swr(instr);
|
||||
break;
|
||||
case Instruction::CACHE:
|
||||
{
|
||||
panic("CACHE 0b{:05b}, 0x{:04X}({}/r{} = 0x{:08X})", instr.op(), instr.offset(),
|
||||
Registers::regNames[instr.base()], instr.base(), regs.Read<u64>(instr.base()));
|
||||
}
|
||||
break;
|
||||
case Instruction::LL:
|
||||
ll(instr);
|
||||
break;
|
||||
case Instruction::LWC1:
|
||||
if (!regs.cop1.CheckFPUUsable<true>())
|
||||
return;
|
||||
b(instr, regs.cop1.fcr31.compare);
|
||||
break;
|
||||
case 2:
|
||||
if (!regs.cop1.CheckFPUUsable())
|
||||
regs.cop1.lwc1(instr);
|
||||
break;
|
||||
case Instruction::LLD:
|
||||
lld(instr);
|
||||
break;
|
||||
case Instruction::LDC1:
|
||||
if (!regs.cop1.CheckFPUUsable<true>())
|
||||
return;
|
||||
bl(instr, !regs.cop1.fcr31.compare);
|
||||
break;
|
||||
case 3:
|
||||
if (!regs.cop1.CheckFPUUsable())
|
||||
regs.cop1.ldc1(instr);
|
||||
break;
|
||||
case Instruction::LD:
|
||||
ld(instr);
|
||||
break;
|
||||
case Instruction::SC:
|
||||
sc(instr);
|
||||
break;
|
||||
case Instruction::SWC1:
|
||||
if (!regs.cop1.CheckFPUUsable<true>())
|
||||
return;
|
||||
bl(instr, regs.cop1.fcr31.compare);
|
||||
break;
|
||||
default:
|
||||
panic("Undefined BC COP1 {:02X}", instr.cop_rt());
|
||||
}
|
||||
return;
|
||||
regs.cop1.swc1(instr);
|
||||
break;
|
||||
case Instruction::SCD:
|
||||
scd(instr);
|
||||
break;
|
||||
case Instruction::SDC1:
|
||||
if (!regs.cop1.CheckFPUUsable<true>())
|
||||
return;
|
||||
regs.cop1.sdc1(instr);
|
||||
break;
|
||||
case Instruction::SD:
|
||||
sd(instr);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.instr.opcode.op, u32(instr),
|
||||
static_cast<u64>(regs.oldPC));
|
||||
}
|
||||
regs.cop1.decode(instr);
|
||||
break;
|
||||
case Instruction::COP2:
|
||||
cop2Decode(instr);
|
||||
break;
|
||||
case Instruction::BEQL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::BNEL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||
break;
|
||||
case Instruction::BLEZL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) <= 0);
|
||||
break;
|
||||
case Instruction::BGTZL:
|
||||
bl(instr, regs.Read<s64>(instr.rs()) > 0);
|
||||
break;
|
||||
case Instruction::DADDI:
|
||||
daddi(instr);
|
||||
break;
|
||||
case Instruction::DADDIU:
|
||||
daddiu(instr);
|
||||
break;
|
||||
case Instruction::LDL:
|
||||
ldl(instr);
|
||||
break;
|
||||
case Instruction::LDR:
|
||||
ldr(instr);
|
||||
break;
|
||||
case 0x1F:
|
||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::LB:
|
||||
lb(instr);
|
||||
break;
|
||||
case Instruction::LH:
|
||||
lh(instr);
|
||||
break;
|
||||
case Instruction::LWL:
|
||||
lwl(instr);
|
||||
break;
|
||||
case Instruction::LW:
|
||||
lw(instr);
|
||||
break;
|
||||
case Instruction::LBU:
|
||||
lbu(instr);
|
||||
break;
|
||||
case Instruction::LHU:
|
||||
lhu(instr);
|
||||
break;
|
||||
case Instruction::LWR:
|
||||
lwr(instr);
|
||||
break;
|
||||
case Instruction::LWU:
|
||||
lwu(instr);
|
||||
break;
|
||||
case Instruction::SB:
|
||||
sb(instr);
|
||||
break;
|
||||
case Instruction::SH:
|
||||
sh(instr);
|
||||
break;
|
||||
case Instruction::SWL:
|
||||
swl(instr);
|
||||
break;
|
||||
case Instruction::SW:
|
||||
sw(instr);
|
||||
break;
|
||||
case Instruction::SDL:
|
||||
sdl(instr);
|
||||
break;
|
||||
case Instruction::SDR:
|
||||
sdr(instr);
|
||||
break;
|
||||
case Instruction::SWR:
|
||||
swr(instr);
|
||||
break;
|
||||
case Instruction::CACHE:
|
||||
break; // CACHE
|
||||
case Instruction::LL:
|
||||
ll(instr);
|
||||
break;
|
||||
case Instruction::LWC1:
|
||||
if (!regs.cop1.CheckFPUUsable<true>())
|
||||
return;
|
||||
regs.cop1.lwc1(instr);
|
||||
break;
|
||||
case Instruction::LLD:
|
||||
lld(instr);
|
||||
break;
|
||||
case Instruction::LDC1:
|
||||
if (!regs.cop1.CheckFPUUsable<true>())
|
||||
return;
|
||||
regs.cop1.ldc1(instr);
|
||||
break;
|
||||
case Instruction::LD:
|
||||
ld(instr);
|
||||
break;
|
||||
case Instruction::SC:
|
||||
sc(instr);
|
||||
break;
|
||||
case Instruction::SWC1:
|
||||
if (!regs.cop1.CheckFPUUsable<true>())
|
||||
return;
|
||||
regs.cop1.swc1(instr);
|
||||
break;
|
||||
case Instruction::SCD:
|
||||
scd(instr);
|
||||
break;
|
||||
case Instruction::SDC1:
|
||||
if (!regs.cop1.CheckFPUUsable<true>())
|
||||
return;
|
||||
regs.cop1.sdc1(instr);
|
||||
break;
|
||||
case Instruction::SD:
|
||||
sd(instr);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.instr.opcode.op, u32(instr), static_cast<u64>(regs.oldPC));
|
||||
}
|
||||
}
|
||||
} // namespace n64
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user