diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp index 9fe222db..64760ce0 100644 --- a/src/backend/core/JIT.cpp +++ b/src/backend/core/JIT.cpp @@ -32,12 +32,15 @@ void JIT::CheckCompareInterrupt() { Fn JIT::Recompile() { bool stable = true; + bool old_stable = stable; cycles = 0; //prologue(); //mov(rbp, u64(this)); //mov(rdi, u64(this) + THIS_OFFSET(regs)); - u64 pc = regs.pc; - while(stable) { + u64 pc = regs.pc + 0x3D0; + while(old_stable) { + old_stable = stable; + cycles++; CheckCompareInterrupt(); diff --git a/src/backend/core/JIT/IR.cpp b/src/backend/core/JIT/IR.cpp index edb89b43..513e29c9 100644 --- a/src/backend/core/JIT/IR.cpp +++ b/src/backend/core/JIT/IR.cpp @@ -47,6 +47,7 @@ template <> struct fmt::formatter : formatter { case Entry::JUMP: op = "JUMP"; break; case Entry::MTC0: op = "MTC0"; break; case Entry::MFC0: op = "MFC0"; break; + case Entry::SLT: op = "SLT"; break; } bool put_comma = false; @@ -148,17 +149,20 @@ void IR::dead_code_elimination(std::vector& code_) { bool isOp2Reg = i.op2.isReg(); bool isDstReg = i.dst.isReg(); + // check for operations like "add rx, rx, 0" or "add r0, anything" if(isDstReg) { - if(i.zeroRendersItUseless() && i.dst.index_or_imm == 0) continue; + bool isDstR0 = i.dst.isReg() && i.dst.index_or_imm.has_value() && i.dst.index_or_imm.value() == 0; + bool areDstAndOp1Same = i.dst.isReg() && i.op1.isReg() && i.dst.index_or_imm.has_value() && i.op1.index_or_imm.has_value() && i.op1.index_or_imm.value() == i.dst.index_or_imm.value(); + bool areDstAndOp2Same = i.dst.isReg() && i.op2.isReg() && i.dst.index_or_imm.has_value() && i.op2.index_or_imm.has_value() && i.op2.index_or_imm.value() == i.dst.index_or_imm.value(); + if (isDstR0) continue; + if (i.canDoDCE()) { + if (areDstAndOp1Same) { + if (i.op2.isImm() && i.op2.index_or_imm.value() == 0) continue; + } - if(isOp1Reg) { - if(i.op1.index_or_imm == i.dst.index_or_imm - && i.zeroRendersItUseless()) continue; - } - - if(isOp2Reg) { - if(i.op2.index_or_imm == i.dst.index_or_imm - && i.zeroRendersItUseless()) continue; + if (areDstAndOp2Same) { + if (i.op1.isImm() && i.op1.index_or_imm.value() == 0) continue; + } } } diff --git a/src/backend/core/JIT/IR.hpp b/src/backend/core/JIT/IR.hpp index 802f9834..b0dea0ec 100644 --- a/src/backend/core/JIT/IR.hpp +++ b/src/backend/core/JIT/IR.hpp @@ -18,7 +18,8 @@ struct Entry { }; enum Opcode : u16 { - MOV, ADD, SUB, UMUL, SMUL, DIV, AND, NOR, XOR, OR, SRL, SLL, SRA, + MOV, SLT, ADD, SUB, UMUL, SMUL, DIV, AND, NOR, + XOR, OR, SRL, SLL, SRA, LOADS8, LOADS8_SHIFT, STORE8, STORE8_SHIFT, LOADS16, LOADS16_SHIFT, STORE16, STORE16_SHIFT, LOADS32, LOADS32_SHIFT, STORE32, STORE32_SHIFT, @@ -45,8 +46,9 @@ struct Entry { } bool isImm() const { - return type == IMM_S64 || type == IMM_F32 || type == IMM_F64 || type == IMM_S32 - || type == IMM_U64 || type == IMM_U32 || type == IMM_U5; + return type == IMM_S64 || type == IMM_U16 || type == IMM_S16 || + type == IMM_F32 || type == IMM_F64 || type == IMM_S32 || + type == IMM_U64 || type == IMM_U32 || type == IMM_U5; } std::optional index_or_imm = std::nullopt; @@ -56,7 +58,7 @@ struct Entry { : type(t), index_or_imm(imm) {} } dst, op1, op2; - bool zeroRendersItUseless() const { + bool canDoDCE() const { return op == ADD || op == OR || op == SRL || op == SLL || op == SRA; } diff --git a/src/backend/core/JIT/instructions.cpp b/src/backend/core/JIT/instructions.cpp index af108de8..6c49eda2 100644 --- a/src/backend/core/JIT/instructions.cpp +++ b/src/backend/core/JIT/instructions.cpp @@ -476,35 +476,35 @@ void JIT::jalr(u32 instr) { } void JIT::slti(u32 instr) { - mov(rax, s64(s16(instr))); - mov(rcx, GPR(qword, RS(instr))); - cmp(rcx, rax); - setl(GPR(qword, RT(instr))); + Entry e(Entry::SLT, + { Entry::Operand::REG_U5, RT(instr) }, + { Entry::Operand::REG_S64, RS(instr) }, + { Entry::Operand::IMM_S64, s64(s16(instr)) }); + ir.push(e); } void JIT::sltiu(u32 instr) { - mov(rax, s64(s16(instr))); - mov(rcx, GPR(qword, RS(instr))); - cmp(rcx, rax); - setb(GPR(qword, RT(instr))); + Entry e(Entry::SLT, + { Entry::Operand::REG_U5, RT(instr) }, + { Entry::Operand::REG_U64, RS(instr) }, + { Entry::Operand::IMM_U64, u64(s64(s16(instr))) }); + ir.push(e); } void JIT::slt(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, GPR(qword, RT(instr))); - cmp(rax, rcx); - setl(GPR(qword, RD(instr))); - } + Entry e(Entry::SLT, + { Entry::Operand::REG_U5, RD(instr) }, + { Entry::Operand::REG_S64, RS(instr) }, + { Entry::Operand::REG_S64, RT(instr) }); + ir.push(e); } void JIT::sltu(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, GPR(qword, RT(instr))); - cmp(rax, rcx); - setb(GPR(qword, RD(instr))); - } + Entry e(Entry::SLT, + { Entry::Operand::REG_U5, RD(instr) }, + { Entry::Operand::REG_U64, RS(instr) }, + { Entry::Operand::REG_U64, RT(instr) }); + ir.push(e); } void JIT::xori(u32 instr) {