better print, some cop0

This commit is contained in:
SimoneN64
2023-12-25 22:49:24 +01:00
parent 360d7a7ccd
commit 80c7e46a38
5 changed files with 194 additions and 144 deletions

View File

@@ -239,6 +239,16 @@ private:
void xor_(u32); void xor_(u32);
void xori(u32); void xori(u32);
void mtc0(u32);
void dmtc0(u32);
void mfc0(u32);
void dmfc0(u32);
void eret();
void tlbr();
void tlbw(int);
void tlbp();
void mtc2(u32); void mtc2(u32);
void mfc2(u32); void mfc2(u32);
void dmtc2(u32); void dmtc2(u32);

View File

@@ -6,141 +6,66 @@ template <> struct fmt::formatter<Entry> : formatter<string_view> {
auto format(Entry e, format_context& ctx) const { auto format(Entry e, format_context& ctx) const {
std::string op = "Unknown"; std::string op = "Unknown";
switch (e.op) { switch (e.op) {
case Entry::MOV: case Entry::MOV: op = "MOV"; break;
op = "MOV"; case Entry::ADD: op = "ADD"; break;
break; case Entry::SUB: op = "SUB"; break;
case Entry::ADD: case Entry::UMUL: op = "UMUL"; break;
op = "ADD"; case Entry::SMUL: op = "SMUL"; break;
break; case Entry::DIV: op = "DIV"; break;
case Entry::SUB: case Entry::AND: op = "AND"; break;
op = "SUB"; case Entry::NOR: op = "NOR"; break;
break; case Entry::XOR: op = "XOR"; break;
case Entry::UMUL: case Entry::OR: op = "OR"; break;
op = "UMUL"; case Entry::SRL: op = "SRL"; break;
break; case Entry::SLL: op = "SLL"; break;
case Entry::SMUL: case Entry::SRA: op = "SRA"; break;
op = "SMUL"; case Entry::LOADS8: op = "LOADS8"; break;
break; case Entry::LOADS8_SHIFT: op = "LOADS8_SHIFT"; break;
case Entry::DIV: case Entry::STORE8: op = "STORE8"; break;
op = "DIV"; case Entry::STORE8_SHIFT: op = "STORE8_SHIFT"; break;
break; case Entry::LOADS16: op = "LOADS16"; break;
case Entry::AND: case Entry::LOADS16_SHIFT: op = "LOADS16_SHIFT"; break;
op = "AND"; case Entry::STORE16: op = "STORE16"; break;
break; case Entry::STORE16_SHIFT: op = "STORE16_SHIFT"; break;
case Entry::NOR: case Entry::LOADS32: op = "LOADS32"; break;
op = "NOR"; case Entry::LOADS32_SHIFT: op = "LOADS32_SHIFT"; break;
break; case Entry::STORE32: op = "STORE32"; break;
case Entry::XOR: case Entry::STORE32_SHIFT: op = "STORE32_SHIFT"; break;
op = "XOR"; case Entry::LOADS64: op = "LOADS64"; break;
break; case Entry::LOADS64_SHIFT: op = "LOADS64_SHIFT"; break;
case Entry::OR: case Entry::STORE64: op = "STORE64"; break;
op = "OR"; case Entry::STORE64_SHIFT: op = "STORE64_SHIFT"; break;
break; case Entry::LOADU8: op = "LOADU8"; break;
case Entry::SRL: case Entry::LOADU8_SHIFT: op = "LOADU8_SHIFT"; break;
op = "SRL"; case Entry::LOADU16: op = "LOADU16"; break;
break; case Entry::LOADU16_SHIFT: op = "LOADU16_SHIFT"; break;
case Entry::SLL: case Entry::LOADU32: op = "LOADU32"; break;
op = "SLL"; case Entry::LOADU32_SHIFT: op = "LOADU32_SHIFT"; break;
break; case Entry::LOADU64: op = "LOADU64"; break;
case Entry::SRA: case Entry::LOADU64_SHIFT: op = "LOADU64_SHIFT"; break;
op = "SRA"; case Entry::BRANCH: op = "BRANCH"; break;
break; case Entry::JUMP: op = "JUMP"; break;
case Entry::LOADS8: case Entry::MTC0: op = "MTC0"; break;
op = "LOADS8"; case Entry::MFC0: op = "MFC0"; break;
break;
case Entry::LOADS8_SHIFT:
op = "LOADS8_SHIFT";
break;
case Entry::STORE8:
op = "STORE8";
break;
case Entry::STORE8_SHIFT:
op = "STORE8_SHIFT";
break;
case Entry::LOADS16:
op = "LOADS16";
break;
case Entry::LOADS16_SHIFT:
op = "LOADS16_SHIFT";
break;
case Entry::STORE16:
op = "STORE16";
break;
case Entry::STORE16_SHIFT:
op = "STORE16_SHIFT";
break;
case Entry::LOADS32:
op = "LOADS32";
break;
case Entry::LOADS32_SHIFT:
op = "LOADS32_SHIFT";
break;
case Entry::STORE32:
op = "STORE32";
break;
case Entry::STORE32_SHIFT:
op = "STORE32_SHIFT";
break;
case Entry::LOADS64:
op = "LOADS64";
break;
case Entry::LOADS64_SHIFT:
op = "LOADS64_SHIFT";
break;
case Entry::STORE64:
op = "STORE64";
break;
case Entry::STORE64_SHIFT:
op = "STORE64_SHIFT";
break;
case Entry::LOADU8:
op = "LOADU8";
break;
case Entry::LOADU8_SHIFT:
op = "LOADU8_SHIFT";
break;
case Entry::LOADU16:
op = "LOADU16";
break;
case Entry::LOADU16_SHIFT:
op = "LOADU16_SHIFT";
break;
case Entry::LOADU32:
op = "LOADU32";
break;
case Entry::LOADU32_SHIFT:
op = "LOADU32_SHIFT";
break;
case Entry::LOADU64:
op = "LOADU64";
break;
case Entry::LOADU64_SHIFT:
op = "LOADU64_SHIFT";
break;
case Entry::BRANCH:
op = "BRANCH";
break;
case Entry::JUMP:
op = "JUMP";
break;
} }
bool put_comma = false; bool put_comma = false;
op += " "; op += " ";
if (e.dst.isReg()) { if (e.dst.isReg()) {
if (e.dst.index_or_imm.has_value()) { if (e.dst.index_or_imm.has_value()) {
if (e.dst.index_or_imm.value() == 0) {
op = "NOP";
return formatter<string_view>::format(op, ctx);
} else {
std::string dst = fmt::format("R{}", e.dst.index_or_imm.value()); std::string dst = fmt::format("R{}", e.dst.index_or_imm.value());
op += dst; op += dst;
put_comma = true; put_comma = true;
} }
} else if(e.dst.isImm()) {
if(e.dst.type != Entry::Operand::NONE) {
std::string dst = fmt::format("0x{:0X}", e.dst.index_or_imm.value());
op += dst;
put_comma = true;
} }
} else { } else {
if(e.dst.type != Entry::Operand::NONE) { if(e.dst.type != Entry::Operand::NONE) {
std::string dst = fmt::format("0x{:0X}", e.dst.index_or_imm.value()); std::string dst = fmt::format("(0x{:0X})", e.dst.index_or_imm.value());
op += dst; op += dst;
put_comma = true; put_comma = true;
} }
@@ -151,20 +76,27 @@ template <> struct fmt::formatter<Entry> : formatter<string_view> {
std::string op1 = fmt::format("R{}", e.op1.index_or_imm.value()); std::string op1 = fmt::format("R{}", e.op1.index_or_imm.value());
if(put_comma) { if(put_comma) {
op += ", "; op += ", ";
} else {
put_comma = true;
} }
op += op1; op += op1;
put_comma = true;
} }
} else { } else if(e.op1.isImm()) {
if (e.op1.index_or_imm.has_value()) { if (e.op1.index_or_imm.has_value()) {
std::string op1 = fmt::format("0x{:0X}", e.op1.index_or_imm.value()); std::string op1 = fmt::format("0x{:0X}", e.op1.index_or_imm.value());
if(put_comma) { if(put_comma) {
op += ", "; op += ", ";
} else {
put_comma = true;
} }
op += op1; op += op1;
put_comma = true;
}
} else {
if (e.op1.index_or_imm.has_value()) {
std::string op1 = fmt::format("(0x{:0X})", e.op1.index_or_imm.value());
if(put_comma) {
op += ", ";
}
op += op1;
put_comma = false;
} }
} }
@@ -173,8 +105,6 @@ template <> struct fmt::formatter<Entry> : formatter<string_view> {
std::string op2 = fmt::format("R{}", e.op2.index_or_imm.value()); std::string op2 = fmt::format("R{}", e.op2.index_or_imm.value());
if(put_comma) { if(put_comma) {
op += ", "; op += ", ";
} else {
put_comma = true;
} }
op += op2; op += op2;
} }
@@ -183,8 +113,6 @@ template <> struct fmt::formatter<Entry> : formatter<string_view> {
std::string op2 = fmt::format("0x{:0X}", e.op2.index_or_imm.value()); std::string op2 = fmt::format("0x{:0X}", e.op2.index_or_imm.value());
if(put_comma) { if(put_comma) {
op += ", "; op += ", ";
} else {
put_comma = true;
} }
op += op2; op += op2;
} }
@@ -214,15 +142,15 @@ void IR::push(const Entry& e) {
code.push_back(e); code.push_back(e);
} }
void IR::optimize() { void IR::dead_code_elimination(std::vector<Entry>& code_) {
std::vector<Entry> optimized{};
for(const auto& i : code) { for(const auto& i : code) {
bool isOp1Reg = i.op1.isReg(); bool isOp1Reg = i.op1.isReg();
bool isOp2Reg = i.op2.isReg(); bool isOp2Reg = i.op2.isReg();
bool isDstReg = i.dst.isReg(); bool isDstReg = i.dst.isReg();
if(isDstReg) { if(isDstReg) {
if(i.zeroRendersItUseless() && i.dst.index_or_imm == 0) continue;
if(isOp1Reg) { if(isOp1Reg) {
if(i.op1.index_or_imm == i.dst.index_or_imm if(i.op1.index_or_imm == i.dst.index_or_imm
&& i.zeroRendersItUseless()) continue; && i.zeroRendersItUseless()) continue;
@@ -234,8 +162,14 @@ void IR::optimize() {
} }
} }
optimized.push_back(i); code_.push_back(i);
} }
}
void IR::optimize() {
std::vector<Entry> optimized{};
dead_code_elimination(optimized);
if(optimized.size() == code.size()) { if(optimized.size() == code.size()) {
return; return;

View File

@@ -9,7 +9,8 @@ struct Entry {
LINK = 0x100, LINK = 0x100,
LIKELY = 0x200, LIKELY = 0x200,
REGISTER = 0x400, REGISTER = 0x400,
SET_LLBIT = 0x800 SET_LLBIT = 0x800,
UNSET_LLBIT = 0x1000,
}; };
enum Shift { enum Shift {
@@ -26,7 +27,7 @@ struct Entry {
LOADU16, LOADU16_SHIFT, LOADU16, LOADU16_SHIFT,
LOADU32, LOADU32_SHIFT, LOADU32, LOADU32_SHIFT,
LOADU64, LOADU64_SHIFT, LOADU64, LOADU64_SHIFT,
BRANCH, JUMP, BRANCH, JUMP, MTC0, MFC0
} op; } op;
struct Operand { struct Operand {
@@ -83,6 +84,7 @@ struct IR {
void print(); void print();
void optimize(); void optimize();
private: private:
void dead_code_elimination(std::vector<Entry>&);
std::vector<Entry> code{}; std::vector<Entry> code{};
}; };
} }

View File

@@ -813,6 +813,91 @@ void JIT::mthi(u32 instr) {
ir.push({Entry::MOV, dst, src}); ir.push({Entry::MOV, dst, src});
} }
void JIT::mtc0(u32 instr) {
ir.push({Entry::MTC0,
{Entry::Operand::IMM_U5, RD(instr)},
{Entry::Operand::REG_S32, RT(instr)}});
}
void JIT::dmtc0(u32 instr) {
ir.push({Entry::MTC0,
{Entry::Operand::IMM_U5, RD(instr)},
{Entry::Operand::REG_S64, RT(instr)}});
}
void JIT::mfc0(u32 instr) {
ir.push({Entry::MFC0,
{Entry::Operand::REG_S32, RT(instr)},
{Entry::Operand::IMM_U5, RD(instr)}});
}
void JIT::dmfc0(u32 instr) {
ir.push({Entry::MFC0,
{Entry::Operand::REG_S64, RT(instr)},
{Entry::Operand::IMM_U5, RD(instr)}});
}
void JIT::eret() {
/*if(status.erl) {
regs.SetPC64(ErrorEPC);
status.erl = false;
} else {
regs.SetPC64(EPC);
status.exl = false;
}
regs.cop0.Update();
llbit = false;*/
}
void JIT::tlbr() {
/*if (index.i >= 32) {
Util::panic("TLBR with TLB index {}", index.i);
}
TLBEntry entry = tlb[index.i];
entryHi.raw = entry.entryHi.raw;
entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF;
entryLo1.raw = entry.entryLo1.raw & 0x3FFFFFFF;
entryLo0.g = entry.global;
entryLo1.g = entry.global;
pageMask.raw = entry.pageMask.raw;*/
}
void JIT::tlbw(int index_) {
/*PageMask page_mask{};
page_mask = pageMask;
u32 top = page_mask.mask & 0xAAA;
page_mask.mask = top | (top >> 1);
if(index_ >= 32) {
Util::panic("TLBWI with TLB index {}", index_);
}
tlb[index_].entryHi.raw = entryHi.raw;
tlb[index_].entryHi.vpn2 &= ~page_mask.mask;
tlb[index_].entryLo0.raw = entryLo0.raw & 0x03FFFFFE;
tlb[index_].entryLo1.raw = entryLo1.raw & 0x03FFFFFE;
tlb[index_].pageMask.raw = page_mask.raw;
tlb[index_].global = entryLo0.g && entryLo1.g;
tlb[index_].initialized = true;*/
}
void JIT::tlbp() {
/*int match = -1;
TLBEntry* entry = TLBTryMatch(regs, entryHi.raw, &match);
if(entry && match >= 0) {
index.raw = match;
} else {
index.raw = 0;
index.p = 1;
}*/
}
void JIT::mtc2(u32 instr) { void JIT::mtc2(u32 instr) {
} }

View File

@@ -1,6 +1,7 @@
#include <log.hpp> #include <log.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <core/Interpreter.hpp> #include <core/Interpreter.hpp>
#include <core/JIT.hpp>
namespace n64 { namespace n64 {
Cop0::Cop0() { Cop0::Cop0() {
@@ -336,7 +337,25 @@ template void Cop0::decode<Interpreter>(Interpreter&, u32);
template void Cop0::decode<JIT>(JIT&, u32); template void Cop0::decode<JIT>(JIT&, u32);
void Cop0::decodeJIT(JIT& cpu, u32 instr) { void Cop0::decodeJIT(JIT& cpu, u32 instr) {
u8 mask_cop = (instr >> 21) & 0x1F;
u8 mask_cop2 = instr & 0x3F;
switch(mask_cop) {
case 0x00: cpu.mfc0(instr); break;
case 0x01: cpu.dmfc0(instr); break;
case 0x04: cpu.mtc0(instr); break;
case 0x05: cpu.dmtc0(instr); break;
case 0x10 ... 0x1F:
switch(mask_cop2) {
case 0x01: cpu.tlbr(); break;
case 0x02: cpu.tlbw(index.i); break;
case 0x06: cpu.tlbw(GetRandom()); break;
case 0x08: cpu.tlbp(); break;
case 0x18: cpu.eret(); break;
default: Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, cpu.regs.oldPC);
}
break;
default: Util::panic("Unimplemented COP0 instruction {} {}", mask_cop >> 4, mask_cop & 7);
}
} }
void Cop0::decodeInterp(Registers& regs, u32 instr) { void Cop0::decodeInterp(Registers& regs, u32 instr) {