Things to neat up that I noticed with Hazel <3
This commit is contained in:
@@ -10,6 +10,5 @@ struct BaseCPU {
|
||||
virtual void Reset() = 0;
|
||||
virtual Mem &GetMem() = 0;
|
||||
virtual Registers &GetRegs() = 0;
|
||||
[[nodiscard]] virtual Disassembler::DisassemblyResult Disassemble(u32) = 0;
|
||||
};
|
||||
} // namespace n64
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include <Disassembler.hpp>
|
||||
#include <Core.hpp>
|
||||
|
||||
Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 address, const u32 instruction) const {
|
||||
cs_insn *insn;
|
||||
const auto bytes = Util::IntegralToBuffer(instruction);
|
||||
const auto bytes = Util::IntegralToBuffer(std::byteswap(instruction));
|
||||
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
|
||||
|
||||
if (count <= 0)
|
||||
@@ -15,9 +16,21 @@ Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 addres
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] Disassembler::DisassemblyResult Disassembler::Disassemble(const u32 address) const {
|
||||
n64::Core& core = n64::Core::GetInstance();
|
||||
n64::Mem& mem = core.cpu->GetMem();
|
||||
u32 paddr;
|
||||
if(!core.cpu->GetRegs().cop0.MapVAddr(n64::Cop0::TLBAccessType::LOAD, address, paddr))
|
||||
return DisassemblyResult{false, ""};
|
||||
|
||||
u32 instruction = mem.Read<u32>(paddr);
|
||||
|
||||
return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction);
|
||||
}
|
||||
|
||||
Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 address, const u32 instruction) const {
|
||||
cs_insn *insn;
|
||||
const auto bytes = Util::IntegralToBuffer(instruction);
|
||||
const auto bytes = Util::IntegralToBuffer(std::byteswap(instruction));
|
||||
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
|
||||
|
||||
if (count <= 0)
|
||||
@@ -29,29 +42,41 @@ Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 addr
|
||||
|
||||
result.full += std::format("0x{:016X}", result.address) + ":\t";
|
||||
result.full += result.mnemonic + "\t";
|
||||
result.comment = "// ";
|
||||
|
||||
const cs_detail *details = insn[0].detail;
|
||||
auto formatOperand = [&](const cs_mips_op &operand) {
|
||||
switch (operand.type) {
|
||||
case MIPS_OP_IMM:
|
||||
return std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm);
|
||||
return DisassemblyResult::Operand{
|
||||
0xffcbf1ae,
|
||||
std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm)
|
||||
};
|
||||
case MIPS_OP_MEM:
|
||||
return std::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp);
|
||||
return DisassemblyResult::Operand{
|
||||
0xffaef1c3,
|
||||
std::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp)
|
||||
};
|
||||
case MIPS_OP_REG:
|
||||
return std::format("{}", cs_reg_name(handle, operand.reg));
|
||||
return DisassemblyResult::Operand{
|
||||
0xffaef1eb,
|
||||
std::format("{}", cs_reg_name(handle, operand.reg))
|
||||
};
|
||||
default:
|
||||
return std::string{""};
|
||||
return DisassemblyResult::Operand { 0xff808080, "" };
|
||||
}
|
||||
};
|
||||
|
||||
auto formatComment = [&](const cs_mips_op &operand) {
|
||||
return "";
|
||||
};
|
||||
|
||||
for (u8 i = 0; i < details->mips.op_count && i < 3; i++) {
|
||||
result.ops[i] = formatOperand(details->mips.operands[i]);
|
||||
result.full += result.ops[i] + "\t";
|
||||
result.full += result.ops[i].str + "\t";
|
||||
}
|
||||
|
||||
result.full += "\t// ";
|
||||
|
||||
// TODO: generate a comment
|
||||
result.full += result.comment;
|
||||
|
||||
cs_free(insn, count);
|
||||
|
||||
|
||||
@@ -10,24 +10,25 @@ struct Disassembler {
|
||||
std::string full;
|
||||
u64 address;
|
||||
std::string mnemonic;
|
||||
std::array<std::string, 3> ops{};
|
||||
struct Operand {
|
||||
u32 color;
|
||||
std::string str;
|
||||
};
|
||||
std::array<Operand, 3> ops{};
|
||||
std::string comment;
|
||||
};
|
||||
|
||||
~Disassembler() { cs_close(&handle); }
|
||||
|
||||
static Disassembler &GetInstance(bool rsp = false) {
|
||||
static Disassembler ret(rsp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[[nodiscard]] DisassemblyResult Disassemble(const u32 address, const u32 instruction) const {
|
||||
return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction);
|
||||
}
|
||||
|
||||
~Disassembler() { cs_close(&handle); }
|
||||
|
||||
private:
|
||||
[[nodiscard]] DisassemblyResult Disassemble(const u32 address) const;
|
||||
[[nodiscard]] DisassemblyResult DisassembleDetailed(u32 address, u32 instruction) const;
|
||||
[[nodiscard]] DisassemblyResult DisassembleSimple(u32 address, u32 instruction) const;
|
||||
|
||||
private:
|
||||
explicit Disassembler(const bool rsp) : rsp(rsp) {
|
||||
if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>((rsp ? CS_MODE_32 : CS_MODE_64) | CS_MODE_BIG_ENDIAN), &handle) !=
|
||||
CS_ERR_OK) {
|
||||
|
||||
@@ -21,14 +21,6 @@ void Interpreter::CheckCompareInterrupt() {
|
||||
}
|
||||
}
|
||||
|
||||
Disassembler::DisassemblyResult Interpreter::Disassemble(const u32 address) {
|
||||
u32 paddr;
|
||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) {
|
||||
return {};
|
||||
}
|
||||
return Disassembler::GetInstance().Disassemble(address, mem.Read<u32>(paddr));
|
||||
}
|
||||
|
||||
int Interpreter::Step() {
|
||||
CheckCompareInterrupt();
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ struct Interpreter : BaseCPU {
|
||||
Mem &GetMem() override { return mem; }
|
||||
|
||||
Registers &GetRegs() override { return regs; }
|
||||
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32) override;
|
||||
|
||||
private:
|
||||
Registers regs;
|
||||
Mem mem;
|
||||
|
||||
@@ -107,8 +107,26 @@ int JIT::Step() {
|
||||
trace("\tMIPS code (guest PC = 0x{:016X}):", blockPC);
|
||||
while (!instrEndsBlock) {
|
||||
// CheckCompareInterrupt();
|
||||
paddr = 0;
|
||||
|
||||
instruction = FetchInstruction();
|
||||
if (check_address_error(0b11, u64(blockPC))) [[unlikely]] {
|
||||
/*regs.cop0.HandleTLBException(blockPC);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, blockPC);
|
||||
return 1;*/
|
||||
|
||||
panic("[JIT]: Unhandled exception ADL due to unaligned PC virtual value! (0x{:016X})", blockPC);
|
||||
}
|
||||
|
||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, blockPC, paddr)) {
|
||||
/*regs.cop0.HandleTLBException(blockPC);
|
||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC);
|
||||
return 1;*/
|
||||
panic(
|
||||
"[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016X})",
|
||||
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
|
||||
}
|
||||
|
||||
instruction = mem.Read<u32>(paddr);
|
||||
instructionsInBlock++;
|
||||
|
||||
blockOldPC = blockPC;
|
||||
@@ -118,17 +136,9 @@ int JIT::Step() {
|
||||
if((instrEndsBlock = InstrEndsBlock(instruction)))
|
||||
continue;
|
||||
|
||||
/*u32 bswapped = std::byteswap(instruction);
|
||||
auto count = cs_disasm(disassemblerMips, reinterpret_cast<const u8 *>(&bswapped), 4, blockPC, 0, &insn);
|
||||
trace("{}", Disassembler::GetInstance().DisassembleSimple(paddr, instruction).full);
|
||||
|
||||
if (count > 0) {
|
||||
trace("\t\t0x{:016X}:\t{}\t\t{}\n", insn->address, insn->mnemonic, insn->op_str);
|
||||
cs_free(insn, count);
|
||||
} else {
|
||||
trace("\t\tCould not disassemble 0x{:08X} due to error {}\n", instruction, (int)cs_errno(disassemblerMips));
|
||||
}
|
||||
|
||||
if(ShouldServiceInterrupt()) {
|
||||
/*if(ShouldServiceInterrupt()) {
|
||||
regs.cop0.FireException(ExceptionCode::Interrupt, 0, blockPC);
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
@@ -39,9 +39,6 @@ struct JIT : BaseCPU {
|
||||
Mem &GetMem() override { return mem; }
|
||||
|
||||
Registers &GetRegs() override { return regs; }
|
||||
|
||||
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32) override { return {}; }
|
||||
|
||||
private:
|
||||
Xbyak::CodeGenerator code{kCodeCacheAllocSize};
|
||||
Registers regs;
|
||||
|
||||
@@ -13,7 +13,6 @@ Mem::Mem(JIT *jit) : flash(saveData), jit(jit) {
|
||||
}
|
||||
|
||||
void Mem::Reset() {
|
||||
std::ranges::fill(rom.cart, 0);
|
||||
std::ranges::fill(isviewer, 0);
|
||||
flash.Reset();
|
||||
if (saveData.is_mapped()) {
|
||||
@@ -454,7 +453,7 @@ void Mem::Write<u32>(const u32 paddr, const u32 val) {
|
||||
}
|
||||
|
||||
#ifndef __aarch64__
|
||||
void Mem::WriteJIT(const const u32 paddr, const u64 val) {
|
||||
void Mem::WriteJIT(const u32 paddr, const u64 val) {
|
||||
WriteInterpreter(paddr, val);
|
||||
if (jit)
|
||||
jit->InvalidateBlock(paddr);
|
||||
|
||||
@@ -76,7 +76,7 @@ void Cop0::tlbw(const int index_) {
|
||||
|
||||
void Cop0::tlbp() {
|
||||
int match = -1;
|
||||
if (const TLBEntry *entry = TLBTryMatch(entryHi.raw, match); entry && match >= 0) {
|
||||
if (const TLBEntry *entry = TLBTryMatch(entryHi.raw, match); match >= 0) {
|
||||
index.raw = match;
|
||||
} else {
|
||||
index.raw = 0;
|
||||
|
||||
Reference in New Issue
Block a user