Continue big Instruction struct rewrite
This commit is contained in:
@@ -7,9 +7,11 @@ namespace n64 {
|
|||||||
Core::Core() {
|
Core::Core() {
|
||||||
auto cpuType = Options::GetInstance().GetValue<std::string>("cpu", "type");
|
auto cpuType = Options::GetInstance().GetValue<std::string>("cpu", "type");
|
||||||
if (cpuType == "interpreter") {
|
if (cpuType == "interpreter") {
|
||||||
|
cpuType = Interpreted;
|
||||||
cpu = std::make_unique<Interpreter>(parallel, *mem, regs);
|
cpu = std::make_unique<Interpreter>(parallel, *mem, regs);
|
||||||
} else if(cpuType == "jit") {
|
} else if(cpuType == "jit") {
|
||||||
#ifndef __aarch64__
|
#ifndef __aarch64__
|
||||||
|
cpuType = DynamicRecompiler;
|
||||||
cpu = std::make_unique<JIT>(parallel, *mem, regs);
|
cpu = std::make_unique<JIT>(parallel, *mem, regs);
|
||||||
#else
|
#else
|
||||||
panic("JIT currently unsupported on aarch64");
|
panic("JIT currently unsupported on aarch64");
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ struct Core {
|
|||||||
Interpreted,
|
Interpreted,
|
||||||
DynamicRecompiler,
|
DynamicRecompiler,
|
||||||
CachedInterpreter
|
CachedInterpreter
|
||||||
};
|
} cpuType = Interpreted;
|
||||||
|
|
||||||
explicit Core();
|
explicit Core();
|
||||||
|
|
||||||
@@ -28,6 +28,20 @@ struct Core {
|
|||||||
return *GetInstance().mem;
|
return *GetInstance().mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Interpreter& GetInterpreter() {
|
||||||
|
if(GetInstance().cpuType == Interpreted)
|
||||||
|
return *dynamic_cast<Interpreter*>(GetInstance().cpu.get());
|
||||||
|
|
||||||
|
panic("Tried to get interpreter when other cpu type is used.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static JIT& GetDynamicRecompiler() {
|
||||||
|
if(GetInstance().cpuType == DynamicRecompiler)
|
||||||
|
return *dynamic_cast<JIT*>(GetInstance().cpu.get());
|
||||||
|
|
||||||
|
panic("Tried to get interpreter when other cpu type is used.");
|
||||||
|
}
|
||||||
|
|
||||||
int StepCPU();
|
int StepCPU();
|
||||||
void StepRSP(int cpuCycles);
|
void StepRSP(int cpuCycles);
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|||||||
@@ -26,100 +26,100 @@ private:
|
|||||||
void CheckCompareInterrupt();
|
void CheckCompareInterrupt();
|
||||||
|
|
||||||
void cop2Decode(u32);
|
void cop2Decode(u32);
|
||||||
void special(u32);
|
void special(Instruction);
|
||||||
void regimm(u32);
|
void regimm(Instruction);
|
||||||
void Exec(u32);
|
void Exec(Instruction);
|
||||||
void add(u32);
|
void add(Instruction);
|
||||||
void addu(u32);
|
void addu(Instruction);
|
||||||
void addi(u32);
|
void addi(Instruction);
|
||||||
void addiu(u32);
|
void addiu(Instruction);
|
||||||
void andi(u32);
|
void andi(Instruction);
|
||||||
void and_(u32);
|
void and_(Instruction);
|
||||||
void branch(bool, s64);
|
void branch(bool, s64);
|
||||||
void branch_likely(bool, s64);
|
void branch_likely(bool, s64);
|
||||||
void b(u32, bool);
|
void b(Instruction, bool);
|
||||||
void blink(u32, bool);
|
void blink(Instruction, bool);
|
||||||
void bl(u32, bool);
|
void bl(Instruction, bool);
|
||||||
void bllink(u32, bool);
|
void bllink(Instruction, bool);
|
||||||
void dadd(u32);
|
void dadd(Instruction);
|
||||||
void daddu(u32);
|
void daddu(Instruction);
|
||||||
void daddi(u32);
|
void daddi(Instruction);
|
||||||
void daddiu(u32);
|
void daddiu(Instruction);
|
||||||
void ddiv(u32);
|
void ddiv(Instruction);
|
||||||
void ddivu(u32);
|
void ddivu(Instruction);
|
||||||
void div(u32);
|
void div(Instruction);
|
||||||
void divu(u32);
|
void divu(Instruction);
|
||||||
void dmult(u32);
|
void dmult(Instruction);
|
||||||
void dmultu(u32);
|
void dmultu(Instruction);
|
||||||
void dsll(u32);
|
void dsll(Instruction);
|
||||||
void dsllv(u32);
|
void dsllv(Instruction);
|
||||||
void dsll32(u32);
|
void dsll32(Instruction);
|
||||||
void dsra(u32);
|
void dsra(Instruction);
|
||||||
void dsrav(u32);
|
void dsrav(Instruction);
|
||||||
void dsra32(u32);
|
void dsra32(Instruction);
|
||||||
void dsrl(u32);
|
void dsrl(Instruction);
|
||||||
void dsrlv(u32);
|
void dsrlv(Instruction);
|
||||||
void dsrl32(u32);
|
void dsrl32(Instruction);
|
||||||
void dsub(u32);
|
void dsub(Instruction);
|
||||||
void dsubu(u32);
|
void dsubu(Instruction);
|
||||||
void j(u32);
|
void j(Instruction);
|
||||||
void jr(u32);
|
void jr(Instruction);
|
||||||
void jal(u32);
|
void jal(Instruction);
|
||||||
void jalr(u32);
|
void jalr(Instruction);
|
||||||
void lui(u32);
|
void lui(Instruction);
|
||||||
void lbu(u32);
|
void lbu(Instruction);
|
||||||
void lb(u32);
|
void lb(Instruction);
|
||||||
void ld(u32);
|
void ld(Instruction);
|
||||||
void ldl(u32);
|
void ldl(Instruction);
|
||||||
void ldr(u32);
|
void ldr(Instruction);
|
||||||
void lh(u32);
|
void lh(Instruction);
|
||||||
void lhu(u32);
|
void lhu(Instruction);
|
||||||
void ll(u32);
|
void ll(Instruction);
|
||||||
void lld(u32);
|
void lld(Instruction);
|
||||||
void lw(u32);
|
void lw(Instruction);
|
||||||
void lwl(u32);
|
void lwl(Instruction);
|
||||||
void lwu(u32);
|
void lwu(Instruction);
|
||||||
void lwr(u32);
|
void lwr(Instruction);
|
||||||
void mfhi(u32);
|
void mfhi(Instruction);
|
||||||
void mflo(u32);
|
void mflo(Instruction);
|
||||||
void mult(u32);
|
void mult(Instruction);
|
||||||
void multu(u32);
|
void multu(Instruction);
|
||||||
void mthi(u32);
|
void mthi(Instruction);
|
||||||
void mtlo(u32);
|
void mtlo(Instruction);
|
||||||
void nor(u32);
|
void nor(Instruction);
|
||||||
void sb(u32);
|
void sb(Instruction);
|
||||||
void sc(u32);
|
void sc(Instruction);
|
||||||
void scd(u32);
|
void scd(Instruction);
|
||||||
void sd(u32);
|
void sd(Instruction);
|
||||||
void sdl(u32);
|
void sdl(Instruction);
|
||||||
void sdr(u32);
|
void sdr(Instruction);
|
||||||
void sh(u32);
|
void sh(Instruction);
|
||||||
void sw(u32);
|
void sw(Instruction);
|
||||||
void swl(u32);
|
void swl(Instruction);
|
||||||
void swr(u32);
|
void swr(Instruction);
|
||||||
void slti(u32);
|
void slti(Instruction);
|
||||||
void sltiu(u32);
|
void sltiu(Instruction);
|
||||||
void slt(u32);
|
void slt(Instruction);
|
||||||
void sltu(u32);
|
void sltu(Instruction);
|
||||||
void sll(u32);
|
void sll(Instruction);
|
||||||
void sllv(u32);
|
void sllv(Instruction);
|
||||||
void sub(u32);
|
void sub(Instruction);
|
||||||
void subu(u32);
|
void subu(Instruction);
|
||||||
void sra(u32);
|
void sra(Instruction);
|
||||||
void srav(u32);
|
void srav(Instruction);
|
||||||
void srl(u32);
|
void srl(Instruction);
|
||||||
void srlv(u32);
|
void srlv(Instruction);
|
||||||
void trap(bool) const;
|
void trap(bool) const;
|
||||||
void or_(u32);
|
void or_(Instruction);
|
||||||
void ori(u32);
|
void ori(Instruction);
|
||||||
void xor_(u32);
|
void xor_(Instruction);
|
||||||
void xori(u32);
|
void xori(Instruction);
|
||||||
|
|
||||||
void mtc2(u32);
|
void mtc2(Instruction);
|
||||||
void mfc2(u32);
|
void mfc2(Instruction);
|
||||||
void dmtc2(u32);
|
void dmtc2(Instruction);
|
||||||
void dmfc2(u32);
|
void dmfc2(Instruction);
|
||||||
void ctc2(u32);
|
void ctc2(Instruction);
|
||||||
void cfc2(u32);
|
void cfc2(Instruction);
|
||||||
};
|
};
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
#include <Instruction.hpp>
|
#include <Instruction.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
void Interpreter::special(const u32 instr) {
|
void Interpreter::special(const Instruction instr) {
|
||||||
Instruction helper(instr);
|
|
||||||
// 00rr_rccc
|
// 00rr_rccc
|
||||||
switch (helper.special()) {
|
switch (instr.instr.opcode.special) {
|
||||||
case Instruction::SLL:
|
case Instruction::SLL:
|
||||||
if (instr != 0) {
|
if (instr.instr.raw != 0) {
|
||||||
sll(instr);
|
sll(instr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -130,22 +129,22 @@ void Interpreter::special(const u32 instr) {
|
|||||||
dsubu(instr);
|
dsubu(instr);
|
||||||
break;
|
break;
|
||||||
case Instruction::TGE:
|
case Instruction::TGE:
|
||||||
trap(regs.Read<s64>(RS(instr)) >= regs.Read<s64>(RT(instr)));
|
trap(regs.Read<s64>(instr.rs()) >= regs.Read<s64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case Instruction::TGEU:
|
case Instruction::TGEU:
|
||||||
trap(regs.Read<u64>(RS(instr)) >= regs.Read<u64>(RT(instr)));
|
trap(regs.Read<u64>(instr.rs()) >= regs.Read<u64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case Instruction::TLT:
|
case Instruction::TLT:
|
||||||
trap(regs.Read<s64>(RS(instr)) < regs.Read<s64>(RT(instr)));
|
trap(regs.Read<s64>(instr.rs()) < regs.Read<s64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case Instruction::TLTU:
|
case Instruction::TLTU:
|
||||||
trap(regs.Read<u64>(RS(instr)) < regs.Read<u64>(RT(instr)));
|
trap(regs.Read<u64>(instr.rs()) < regs.Read<u64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case Instruction::TEQ:
|
case Instruction::TEQ:
|
||||||
trap(regs.Read<s64>(RS(instr)) == regs.Read<s64>(RT(instr)));
|
trap(regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case Instruction::TNE:
|
case Instruction::TNE:
|
||||||
trap(regs.Read<s64>(RS(instr)) != regs.Read<s64>(RT(instr)));
|
trap(regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case Instruction::DSLL:
|
case Instruction::DSLL:
|
||||||
dsll(instr);
|
dsll(instr);
|
||||||
@@ -166,59 +165,59 @@ void Interpreter::special(const u32 instr) {
|
|||||||
dsra32(instr);
|
dsra32(instr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 7, mask & 7, instr,
|
panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.special_hi, instr.instr.opcode.special_lo, instr.instr.raw,
|
||||||
static_cast<u64>(regs.oldPC));
|
static_cast<u64>(regs.oldPC));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::regimm(const u32 instr) {
|
void Interpreter::regimm(const Instruction instr) {
|
||||||
// 000r_rccc
|
// 000r_rccc
|
||||||
switch (const u8 mask = instr >> 16 & 0x1F) {
|
switch (instr.instr.opcode.regimm) {
|
||||||
case BLTZ:
|
case Instruction::BLTZ:
|
||||||
b(instr, regs.Read<s64>(RS(instr)) < 0);
|
b(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||||
break;
|
break;
|
||||||
case BGEZ:
|
case Instruction::BGEZ:
|
||||||
b(instr, regs.Read<s64>(RS(instr)) >= 0);
|
b(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||||
break;
|
break;
|
||||||
case BLTZL:
|
case Instruction::BLTZL:
|
||||||
bl(instr, regs.Read<s64>(RS(instr)) < 0);
|
bl(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||||
break;
|
break;
|
||||||
case BGEZL:
|
case Instruction::BGEZL:
|
||||||
bl(instr, regs.Read<s64>(RS(instr)) >= 0);
|
bl(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||||
break;
|
break;
|
||||||
case TGEI:
|
case Instruction::TGEI:
|
||||||
trap(regs.Read<s64>(RS(instr)) >= static_cast<s64>(static_cast<s16>(instr)));
|
trap(regs.Read<s64>(instr.rs()) >= static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||||
break;
|
break;
|
||||||
case TGEIU:
|
case Instruction::TGEIU:
|
||||||
trap(regs.Read<u64>(RS(instr)) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
|
trap(regs.Read<u64>(instr.rs()) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr.instr.itype.imm))));
|
||||||
break;
|
break;
|
||||||
case TLTI:
|
case Instruction::TLTI:
|
||||||
trap(regs.Read<s64>(RS(instr)) < static_cast<s64>(static_cast<s16>(instr)));
|
trap(regs.Read<s64>(instr.rs()) < static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||||
break;
|
break;
|
||||||
case TLTIU:
|
case Instruction::TLTIU:
|
||||||
trap(regs.Read<u64>(RS(instr)) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
|
trap(regs.Read<u64>(instr.rs()) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr.instr.itype.imm))));
|
||||||
break;
|
break;
|
||||||
case TEQI:
|
case Instruction::TEQI:
|
||||||
trap(regs.Read<s64>(RS(instr)) == static_cast<s64>(static_cast<s16>(instr)));
|
trap(regs.Read<s64>(instr.rs()) == static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||||
break;
|
break;
|
||||||
case TNEI:
|
case Instruction::TNEI:
|
||||||
trap(regs.Read<s64>(RS(instr)) != static_cast<s64>(static_cast<s16>(instr)));
|
trap(regs.Read<s64>(instr.rs()) != static_cast<s64>(static_cast<s16>(instr.instr.itype.imm)));
|
||||||
break;
|
break;
|
||||||
case BLTZAL:
|
case Instruction::BLTZAL:
|
||||||
blink(instr, regs.Read<s64>(RS(instr)) < 0);
|
blink(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||||
break;
|
break;
|
||||||
case BGEZAL:
|
case Instruction::BGEZAL:
|
||||||
blink(instr, regs.Read<s64>(RS(instr)) >= 0);
|
blink(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||||
break;
|
break;
|
||||||
case BLTZALL:
|
case Instruction::BLTZALL:
|
||||||
bllink(instr, regs.Read<s64>(RS(instr)) < 0);
|
bllink(instr, regs.Read<s64>(instr.rs()) < 0);
|
||||||
break;
|
break;
|
||||||
case BGEZALL:
|
case Instruction::BGEZALL:
|
||||||
bllink(instr, regs.Read<s64>(RS(instr)) >= 0);
|
bllink(instr, regs.Read<s64>(instr.rs()) >= 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr,
|
panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.regimm_hi,
|
||||||
static_cast<u64>(regs.oldPC));
|
instr.instr.opcode.regimm_lo, instr, static_cast<u64>(regs.oldPC));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,203 +250,172 @@ void Interpreter::cop2Decode(const u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::Exec(const u32 instr) {
|
void Interpreter::Exec(const Instruction instr) {
|
||||||
// 00rr_rccc
|
// 00rr_rccc
|
||||||
switch (const u8 mask = instr >> 26 & 0x3f) {
|
switch (instr.instr.opcode.op) {
|
||||||
case SPECIAL:
|
case Instruction::SPECIAL:
|
||||||
special(instr);
|
special(instr);
|
||||||
break;
|
break;
|
||||||
case REGIMM:
|
case Instruction::REGIMM:
|
||||||
regimm(instr);
|
regimm(instr);
|
||||||
break;
|
break;
|
||||||
case J:
|
case Instruction::J:
|
||||||
j(instr);
|
j(instr);
|
||||||
break;
|
break;
|
||||||
case JAL:
|
case Instruction::JAL:
|
||||||
jal(instr);
|
jal(instr);
|
||||||
break;
|
break;
|
||||||
case BEQ:
|
case Instruction::BEQ:
|
||||||
b(instr, regs.Read<s64>(RS(instr)) == regs.Read<s64>(RT(instr)));
|
b(instr, regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case BNE:
|
case Instruction::BNE:
|
||||||
b(instr, regs.Read<s64>(RS(instr)) != regs.Read<s64>(RT(instr)));
|
b(instr, regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case BLEZ:
|
case Instruction::BLEZ:
|
||||||
b(instr, regs.Read<s64>(RS(instr)) <= 0);
|
b(instr, regs.Read<s64>(instr.rs()) <= 0);
|
||||||
break;
|
break;
|
||||||
case BGTZ:
|
case Instruction::BGTZ:
|
||||||
b(instr, regs.Read<s64>(RS(instr)) > 0);
|
b(instr, regs.Read<s64>(instr.rs()) > 0);
|
||||||
break;
|
break;
|
||||||
case ADDI:
|
case Instruction::ADDI:
|
||||||
addi(instr);
|
addi(instr);
|
||||||
break;
|
break;
|
||||||
case ADDIU:
|
case Instruction::ADDIU:
|
||||||
addiu(instr);
|
addiu(instr);
|
||||||
break;
|
break;
|
||||||
case SLTI:
|
case Instruction::SLTI:
|
||||||
slti(instr);
|
slti(instr);
|
||||||
break;
|
break;
|
||||||
case SLTIU:
|
case Instruction::SLTIU:
|
||||||
sltiu(instr);
|
sltiu(instr);
|
||||||
break;
|
break;
|
||||||
case ANDI:
|
case Instruction::ANDI:
|
||||||
andi(instr);
|
andi(instr);
|
||||||
break;
|
break;
|
||||||
case ORI:
|
case Instruction::ORI:
|
||||||
ori(instr);
|
ori(instr);
|
||||||
break;
|
break;
|
||||||
case XORI:
|
case Instruction::XORI:
|
||||||
xori(instr);
|
xori(instr);
|
||||||
break;
|
break;
|
||||||
case LUI:
|
case Instruction::LUI:
|
||||||
lui(instr);
|
lui(instr);
|
||||||
break;
|
break;
|
||||||
case COP0:
|
case Instruction::COP0:
|
||||||
regs.cop0.decode(instr);
|
regs.cop0.decode(instr);
|
||||||
break;
|
break;
|
||||||
case COP1:
|
case Instruction::COP1:
|
||||||
{
|
regs.cop1.decode(instr);
|
||||||
const u8 mask_sub = (instr >> 21) & 0x1F;
|
|
||||||
const u8 mask_branch = (instr >> 16) & 0x1F;
|
|
||||||
if (mask_sub == 0x08) {
|
|
||||||
switch (mask_branch) {
|
|
||||||
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}", mask_branch);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
regs.cop1.decode(instr);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case COP2:
|
case Instruction::COP2:
|
||||||
cop2Decode(instr);
|
cop2Decode(instr);
|
||||||
break;
|
break;
|
||||||
case BEQL:
|
case Instruction::BEQL:
|
||||||
bl(instr, regs.Read<s64>(RS(instr)) == regs.Read<s64>(RT(instr)));
|
bl(instr, regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case BNEL:
|
case Instruction::BNEL:
|
||||||
bl(instr, regs.Read<s64>(RS(instr)) != regs.Read<s64>(RT(instr)));
|
bl(instr, regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
|
||||||
break;
|
break;
|
||||||
case BLEZL:
|
case Instruction::BLEZL:
|
||||||
bl(instr, regs.Read<s64>(RS(instr)) <= 0);
|
bl(instr, regs.Read<s64>(instr.rs()) <= 0);
|
||||||
break;
|
break;
|
||||||
case BGTZL:
|
case Instruction::BGTZL:
|
||||||
bl(instr, regs.Read<s64>(RS(instr)) > 0);
|
bl(instr, regs.Read<s64>(instr.rs()) > 0);
|
||||||
break;
|
break;
|
||||||
case DADDI:
|
case Instruction::DADDI:
|
||||||
daddi(instr);
|
daddi(instr);
|
||||||
break;
|
break;
|
||||||
case DADDIU:
|
case Instruction::DADDIU:
|
||||||
daddiu(instr);
|
daddiu(instr);
|
||||||
break;
|
break;
|
||||||
case LDL:
|
case Instruction::LDL:
|
||||||
ldl(instr);
|
ldl(instr);
|
||||||
break;
|
break;
|
||||||
case LDR:
|
case Instruction::LDR:
|
||||||
ldr(instr);
|
ldr(instr);
|
||||||
break;
|
break;
|
||||||
case 0x1F:
|
case 0x1F:
|
||||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||||
break;
|
break;
|
||||||
case LB:
|
case Instruction::LB:
|
||||||
lb(instr);
|
lb(instr);
|
||||||
break;
|
break;
|
||||||
case LH:
|
case Instruction::LH:
|
||||||
lh(instr);
|
lh(instr);
|
||||||
break;
|
break;
|
||||||
case LWL:
|
case Instruction::LWL:
|
||||||
lwl(instr);
|
lwl(instr);
|
||||||
break;
|
break;
|
||||||
case LW:
|
case Instruction::LW:
|
||||||
lw(instr);
|
lw(instr);
|
||||||
break;
|
break;
|
||||||
case LBU:
|
case Instruction::LBU:
|
||||||
lbu(instr);
|
lbu(instr);
|
||||||
break;
|
break;
|
||||||
case LHU:
|
case Instruction::LHU:
|
||||||
lhu(instr);
|
lhu(instr);
|
||||||
break;
|
break;
|
||||||
case LWR:
|
case Instruction::LWR:
|
||||||
lwr(instr);
|
lwr(instr);
|
||||||
break;
|
break;
|
||||||
case LWU:
|
case Instruction::LWU:
|
||||||
lwu(instr);
|
lwu(instr);
|
||||||
break;
|
break;
|
||||||
case SB:
|
case Instruction::SB:
|
||||||
sb(instr);
|
sb(instr);
|
||||||
break;
|
break;
|
||||||
case SH:
|
case Instruction::SH:
|
||||||
sh(instr);
|
sh(instr);
|
||||||
break;
|
break;
|
||||||
case SWL:
|
case Instruction::SWL:
|
||||||
swl(instr);
|
swl(instr);
|
||||||
break;
|
break;
|
||||||
case SW:
|
case Instruction::SW:
|
||||||
sw(instr);
|
sw(instr);
|
||||||
break;
|
break;
|
||||||
case SDL:
|
case Instruction::SDL:
|
||||||
sdl(instr);
|
sdl(instr);
|
||||||
break;
|
break;
|
||||||
case SDR:
|
case Instruction::SDR:
|
||||||
sdr(instr);
|
sdr(instr);
|
||||||
break;
|
break;
|
||||||
case SWR:
|
case Instruction::SWR:
|
||||||
swr(instr);
|
swr(instr);
|
||||||
break;
|
break;
|
||||||
case CACHE:
|
case Instruction::CACHE:
|
||||||
break; // CACHE
|
break; // CACHE
|
||||||
case LL:
|
case Instruction::LL:
|
||||||
ll(instr);
|
ll(instr);
|
||||||
break;
|
break;
|
||||||
case LWC1:
|
case Instruction::LWC1:
|
||||||
regs.cop1.lwc1(instr);
|
regs.cop1.lwc1(instr);
|
||||||
break;
|
break;
|
||||||
case LLD:
|
case Instruction::LLD:
|
||||||
lld(instr);
|
lld(instr);
|
||||||
break;
|
break;
|
||||||
case LDC1:
|
case Instruction::LDC1:
|
||||||
regs.cop1.ldc1(instr);
|
regs.cop1.ldc1(instr);
|
||||||
break;
|
break;
|
||||||
case LD:
|
case Instruction::LD:
|
||||||
ld(instr);
|
ld(instr);
|
||||||
break;
|
break;
|
||||||
case SC:
|
case Instruction::SC:
|
||||||
sc(instr);
|
sc(instr);
|
||||||
break;
|
break;
|
||||||
case SWC1:
|
case Instruction::SWC1:
|
||||||
regs.cop1.swc1(instr);
|
regs.cop1.swc1(instr);
|
||||||
break;
|
break;
|
||||||
case SCD:
|
case Instruction::SCD:
|
||||||
scd(instr);
|
scd(instr);
|
||||||
break;
|
break;
|
||||||
case SDC1:
|
case Instruction::SDC1:
|
||||||
regs.cop1.sdc1(instr);
|
regs.cop1.sdc1(instr);
|
||||||
break;
|
break;
|
||||||
case SD:
|
case Instruction::SD:
|
||||||
sd(instr);
|
sd(instr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", mask, instr, static_cast<u64>(regs.oldPC));
|
panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.instr.opcode.op, u32(instr), static_cast<u64>(regs.oldPC));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -451,25 +451,23 @@ ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAccessTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop0::decode(const u32 instr) {
|
void Cop0::decode(const Instruction instr) {
|
||||||
Registers& regs = Core::GetRegs();
|
Registers& regs = Core::GetRegs();
|
||||||
const u8 mask_cop = instr >> 21 & 0x1F;
|
switch (instr.cop_rs()) {
|
||||||
const u8 mask_cop2 = instr & 0x3F;
|
|
||||||
switch (mask_cop) {
|
|
||||||
case 0x00:
|
case 0x00:
|
||||||
mfc0(instr);
|
mfc0(u32(instr));
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
dmfc0(instr);
|
dmfc0(u32(instr));
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
mtc0(instr);
|
mtc0(u32(instr));
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
dmtc0(instr);
|
dmtc0(u32(instr));
|
||||||
break;
|
break;
|
||||||
case 0x10 ... 0x1F:
|
case 0x10 ... 0x1F:
|
||||||
switch (mask_cop2) {
|
switch (instr.cop_funct()) {
|
||||||
case 0x01:
|
case 0x01:
|
||||||
tlbr();
|
tlbr();
|
||||||
break;
|
break;
|
||||||
@@ -486,7 +484,7 @@ void Cop0::decode(const u32 instr) {
|
|||||||
eret();
|
eret();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Unimplemented COP0 function {} {} ({:08X}) ({:016X})", mask_cop2 >> 3, mask_cop2 & 7, instr,
|
panic("Unimplemented COP0 function {} ({:08X}) ({:016X})", instr.cop_funct(), u32(instr),
|
||||||
regs.oldPC);
|
regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <common.hpp>
|
#include <common.hpp>
|
||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <Instruction.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
#define STATUS_MASK 0xFF57FFFF
|
#define STATUS_MASK 0xFF57FFFF
|
||||||
@@ -264,7 +265,7 @@ struct Cop0 {
|
|||||||
TLBEntry *TLBTryMatch(u64 vaddr);
|
TLBEntry *TLBTryMatch(u64 vaddr);
|
||||||
void HandleTLBException(u64 vaddr);
|
void HandleTLBException(u64 vaddr);
|
||||||
static ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType);
|
static ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType);
|
||||||
void decode(u32);
|
void decode(const Instruction);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] FORCE_INLINE u32 GetWired() const { return wired & 0x3F; }
|
[[nodiscard]] FORCE_INLINE u32 GetWired() const { return wired & 0x3F; }
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ void Cop1::Reset() {
|
|||||||
memset(fgr, 0, 32 * sizeof(FloatingPointReg));
|
memset(fgr, 0, 32 * sizeof(FloatingPointReg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::decode(const u32 instr) {
|
void Cop1::decode(const Instruction instr) {
|
||||||
const u8 mask_sub = (instr >> 21) & 0x1F;
|
auto cpu = Core::GetInstance().cpuType == Core::Interpreted ? Core::GetInterpreter() : Core::GetDynamicRecompiler();
|
||||||
const u8 mask_fun = instr & 0x3F;
|
switch (instr.cop_rs()) {
|
||||||
const u8 mask_branch = (instr >> 16) & 0x1F;
|
|
||||||
switch (mask_sub) {
|
|
||||||
// 000r_rccc
|
// 000r_rccc
|
||||||
case 0x00:
|
case 0x00:
|
||||||
mfc1(instr);
|
mfc1(instr);
|
||||||
@@ -40,8 +38,34 @@ void Cop1::decode(const u32 instr) {
|
|||||||
case 0x07:
|
case 0x07:
|
||||||
unimplemented();
|
unimplemented();
|
||||||
break;
|
break;
|
||||||
|
case 0x08:
|
||||||
|
switch (instr.cop_rt()) {
|
||||||
|
case 0:
|
||||||
|
if (!regs.cop1.CheckFPUUsable())
|
||||||
|
return;
|
||||||
|
cpu.b(instr, !regs.cop1.fcr31.compare);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (!regs.cop1.CheckFPUUsable())
|
||||||
|
return;
|
||||||
|
cpu.b(instr, regs.cop1.fcr31.compare);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!regs.cop1.CheckFPUUsable())
|
||||||
|
return;
|
||||||
|
cpu.bl(instr, !regs.cop1.fcr31.compare);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (!regs.cop1.CheckFPUUsable())
|
||||||
|
return;
|
||||||
|
cpu.bl(instr, regs.cop1.fcr31.compare);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
panic("Undefined BC COP1 {:02X}", instr.cop_rt());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 0x10: // s
|
case 0x10: // s
|
||||||
switch (mask_fun) {
|
switch (instr.cop_funct()) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
adds(instr);
|
adds(instr);
|
||||||
break;
|
break;
|
||||||
@@ -152,7 +176,7 @@ void Cop1::decode(const u32 instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x11: // d
|
case 0x11: // d
|
||||||
switch (mask_fun) {
|
switch (instr.cop_funct()) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
addd(instr);
|
addd(instr);
|
||||||
break;
|
break;
|
||||||
@@ -263,7 +287,7 @@ void Cop1::decode(const u32 instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x14: // w
|
case 0x14: // w
|
||||||
switch (mask_fun) {
|
switch (instr.cop_funct()) {
|
||||||
case 0x20:
|
case 0x20:
|
||||||
cvtsw(instr);
|
cvtsw(instr);
|
||||||
break;
|
break;
|
||||||
@@ -275,7 +299,7 @@ void Cop1::decode(const u32 instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x15: // l
|
case 0x15: // l
|
||||||
switch (mask_fun) {
|
switch (instr.cop_funct()) {
|
||||||
case 0x20:
|
case 0x20:
|
||||||
cvtsl(instr);
|
cvtsl(instr);
|
||||||
break;
|
break;
|
||||||
@@ -287,7 +311,7 @@ void Cop1::decode(const u32 instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
panic("Unimplemented COP1 instruction {}", instr.cop_rs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <core/registers/Cop0.hpp>
|
#include <core/registers/Cop0.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <Instruction.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Cop1;
|
struct Cop1;
|
||||||
@@ -117,7 +118,7 @@ struct Cop1 {
|
|||||||
bool fgrIsConstant[32]{};
|
bool fgrIsConstant[32]{};
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void decode(u32);
|
void decode(const Instruction);
|
||||||
friend struct Interpreter;
|
friend struct Interpreter;
|
||||||
friend struct JIT;
|
friend struct JIT;
|
||||||
|
|
||||||
@@ -156,91 +157,91 @@ private:
|
|||||||
auto FGR_S(const Cop0Status &, u32) -> T &;
|
auto FGR_S(const Cop0Status &, u32) -> T &;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto FGR_D(const Cop0Status &, u32) -> T &;
|
auto FGR_D(const Cop0Status &, u32) -> T &;
|
||||||
void absd(u32 instr);
|
void absd(const Instruction instr);
|
||||||
void abss(u32 instr);
|
void abss(const Instruction instr);
|
||||||
void adds(u32 instr);
|
void adds(const Instruction instr);
|
||||||
void addd(u32 instr);
|
void addd(const Instruction instr);
|
||||||
void subs(u32 instr);
|
void subs(const Instruction instr);
|
||||||
void subd(u32 instr);
|
void subd(const Instruction instr);
|
||||||
void ceills(u32 instr);
|
void ceills(const Instruction instr);
|
||||||
void ceilws(u32 instr);
|
void ceilws(const Instruction instr);
|
||||||
void ceilld(u32 instr);
|
void ceilld(const Instruction instr);
|
||||||
void ceilwd(u32 instr);
|
void ceilwd(const Instruction instr);
|
||||||
void cfc1(u32 instr);
|
void cfc1(const Instruction instr);
|
||||||
void ctc1(u32 instr);
|
void ctc1(const Instruction instr);
|
||||||
void unimplemented();
|
void unimplemented();
|
||||||
void roundls(u32 instr);
|
void roundls(const Instruction instr);
|
||||||
void roundld(u32 instr);
|
void roundld(const Instruction instr);
|
||||||
void roundws(u32 instr);
|
void roundws(const Instruction instr);
|
||||||
void roundwd(u32 instr);
|
void roundwd(const Instruction instr);
|
||||||
void floorls(u32 instr);
|
void floorls(const Instruction instr);
|
||||||
void floorld(u32 instr);
|
void floorld(const Instruction instr);
|
||||||
void floorws(u32 instr);
|
void floorws(const Instruction instr);
|
||||||
void floorwd(u32 instr);
|
void floorwd(const Instruction instr);
|
||||||
void cvtls(u32 instr);
|
void cvtls(const Instruction instr);
|
||||||
void cvtws(u32 instr);
|
void cvtws(const Instruction instr);
|
||||||
void cvtds(u32 instr);
|
void cvtds(const Instruction instr);
|
||||||
void cvtsw(u32 instr);
|
void cvtsw(const Instruction instr);
|
||||||
void cvtdw(u32 instr);
|
void cvtdw(const Instruction instr);
|
||||||
void cvtsd(u32 instr);
|
void cvtsd(const Instruction instr);
|
||||||
void cvtwd(u32 instr);
|
void cvtwd(const Instruction instr);
|
||||||
void cvtld(u32 instr);
|
void cvtld(const Instruction instr);
|
||||||
void cvtdl(u32 instr);
|
void cvtdl(const Instruction instr);
|
||||||
void cvtsl(u32 instr);
|
void cvtsl(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cf(u32 instr);
|
void cf(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cun(u32 instr);
|
void cun(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ceq(u32 instr);
|
void ceq(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cueq(u32 instr);
|
void cueq(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void colt(u32 instr);
|
void colt(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cult(u32 instr);
|
void cult(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cole(u32 instr);
|
void cole(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cule(u32 instr);
|
void cule(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void csf(u32 instr);
|
void csf(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cngle(u32 instr);
|
void cngle(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cseq(u32 instr);
|
void cseq(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cngl(u32 instr);
|
void cngl(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void clt(u32 instr);
|
void clt(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cnge(u32 instr);
|
void cnge(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cle(u32 instr);
|
void cle(const Instruction instr);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void cngt(u32 instr);
|
void cngt(const Instruction instr);
|
||||||
void divs(u32 instr);
|
void divs(const Instruction instr);
|
||||||
void divd(u32 instr);
|
void divd(const Instruction instr);
|
||||||
void muls(u32 instr);
|
void muls(const Instruction instr);
|
||||||
void muld(u32 instr);
|
void muld(const Instruction instr);
|
||||||
void movs(u32 instr);
|
void movs(const Instruction instr);
|
||||||
void movd(u32 instr);
|
void movd(const Instruction instr);
|
||||||
void negs(u32 instr);
|
void negs(const Instruction instr);
|
||||||
void negd(u32 instr);
|
void negd(const Instruction instr);
|
||||||
void sqrts(u32 instr);
|
void sqrts(const Instruction instr);
|
||||||
void sqrtd(u32 instr);
|
void sqrtd(const Instruction instr);
|
||||||
void lwc1(u32);
|
void lwc1(u32);
|
||||||
void swc1(u32);
|
void swc1(u32);
|
||||||
void ldc1(u32);
|
void ldc1(u32);
|
||||||
void sdc1(u32);
|
void sdc1(u32);
|
||||||
|
|
||||||
void mfc1(u32 instr);
|
void mfc1(const Instruction instr);
|
||||||
void dmfc1(u32 instr);
|
void dmfc1(const Instruction instr);
|
||||||
void mtc1(u32 instr);
|
void mtc1(const Instruction instr);
|
||||||
void dmtc1(u32 instr);
|
void dmtc1(const Instruction instr);
|
||||||
void truncws(u32 instr);
|
void truncws(const Instruction instr);
|
||||||
void truncwd(u32 instr);
|
void truncwd(const Instruction instr);
|
||||||
void truncls(u32 instr);
|
void truncls(const Instruction instr);
|
||||||
void truncld(u32 instr);
|
void truncld(const Instruction instr);
|
||||||
};
|
};
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -4,17 +4,82 @@
|
|||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Instruction {
|
struct Instruction {
|
||||||
Instruction(u32 v) : raw(v) {}
|
Instruction(u32 v) { instr.raw = v; }
|
||||||
void operator=(u32 v) { raw = v; }
|
void operator=(u32 v) { instr.raw = v; }
|
||||||
|
auto operator u32() { return instr.raw; }
|
||||||
|
|
||||||
|
inline u8 rs() const { return instr.rtype.rs; }
|
||||||
|
inline u8 rt() const { return instr.rtype.rt; }
|
||||||
|
inline u8 rd() const { return instr.rtype.rd; }
|
||||||
|
inline u8 sa() const { return instr.rtype.sa; }
|
||||||
|
inline u16 imm() const { return instr.itype.imm; }
|
||||||
|
inline u32 target() const { return instr.jtype.target; }
|
||||||
|
inline u8 cop_rs() const { return instr.opcode.cop_rs; }
|
||||||
|
inline u8 cop_rt() const { return instr.opcode.cop_rt; }
|
||||||
|
inline u8 cop_funct() const { return instr.opcode.funct; }
|
||||||
|
|
||||||
u32 raw;
|
union {
|
||||||
|
struct {
|
||||||
|
unsigned imm:16;
|
||||||
|
unsigned rt:5;
|
||||||
|
unsigned rs:5;
|
||||||
|
unsigned op:6;
|
||||||
|
} itype;
|
||||||
|
|
||||||
FORCE_INLINE u8 special() const { return raw & 0x3F; }
|
struct {
|
||||||
FORCE_INLINE u8 cop_funct() const { return special(); }
|
unsigned target:26;
|
||||||
FORCE_INLINE u8 regimm() const { return (raw >> 16) & 0x1F; }
|
unsigned op:6;
|
||||||
FORCE_INLINE u8 branch() const { return regimm(); }
|
} jtype;
|
||||||
FORCE_INLINE u8 decode() const { return (raw >> 26) & 0x3F; }
|
|
||||||
FORCE_INLINE u8 cop() const { return (raw >> 21) & 0x1F; }
|
struct {
|
||||||
|
unsigned funct:6;
|
||||||
|
unsigned sa:5;
|
||||||
|
unsigned rd:5;
|
||||||
|
unsigned rt:5;
|
||||||
|
unsigned rs:5;
|
||||||
|
unsigned op:6;
|
||||||
|
} rtype;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
unsigned special_lo:3;
|
||||||
|
unsigned special_hi:3;
|
||||||
|
unsigned:26;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned special:6;
|
||||||
|
unsigned:26;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
unsigned:16;
|
||||||
|
unsigned regimm_lo:3;
|
||||||
|
unsigned regimm_hi:2;
|
||||||
|
unsigned:11;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned:16;
|
||||||
|
unsigned regimm:5;
|
||||||
|
unsigned:11;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned:26;
|
||||||
|
unsigned op:6;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned funct:6;
|
||||||
|
unsigned:10;
|
||||||
|
unsigned cop_rt:5;
|
||||||
|
unsigned cop_rs:5;
|
||||||
|
unsigned:6;
|
||||||
|
};
|
||||||
|
} opcode;
|
||||||
|
|
||||||
|
u32 raw;
|
||||||
|
} instr{};
|
||||||
|
|
||||||
static constexpr u8 SPECIAL = 0b000000;
|
static constexpr u8 SPECIAL = 0b000000;
|
||||||
static constexpr u8 REGIMM = 0b000001;
|
static constexpr u8 REGIMM = 0b000001;
|
||||||
|
|||||||
Reference in New Issue
Block a user