improve dead code elimination and implement SLT
This commit is contained in:
@@ -32,12 +32,15 @@ void JIT::CheckCompareInterrupt() {
|
|||||||
|
|
||||||
Fn JIT::Recompile() {
|
Fn JIT::Recompile() {
|
||||||
bool stable = true;
|
bool stable = true;
|
||||||
|
bool old_stable = stable;
|
||||||
cycles = 0;
|
cycles = 0;
|
||||||
//prologue();
|
//prologue();
|
||||||
//mov(rbp, u64(this));
|
//mov(rbp, u64(this));
|
||||||
//mov(rdi, u64(this) + THIS_OFFSET(regs));
|
//mov(rdi, u64(this) + THIS_OFFSET(regs));
|
||||||
u64 pc = regs.pc;
|
u64 pc = regs.pc + 0x3D0;
|
||||||
while(stable) {
|
while(old_stable) {
|
||||||
|
old_stable = stable;
|
||||||
|
|
||||||
cycles++;
|
cycles++;
|
||||||
CheckCompareInterrupt();
|
CheckCompareInterrupt();
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ template <> struct fmt::formatter<Entry> : formatter<string_view> {
|
|||||||
case Entry::JUMP: op = "JUMP"; break;
|
case Entry::JUMP: op = "JUMP"; break;
|
||||||
case Entry::MTC0: op = "MTC0"; break;
|
case Entry::MTC0: op = "MTC0"; break;
|
||||||
case Entry::MFC0: op = "MFC0"; break;
|
case Entry::MFC0: op = "MFC0"; break;
|
||||||
|
case Entry::SLT: op = "SLT"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool put_comma = false;
|
bool put_comma = false;
|
||||||
@@ -148,17 +149,20 @@ void IR::dead_code_elimination(std::vector<Entry>& code_) {
|
|||||||
bool isOp2Reg = i.op2.isReg();
|
bool isOp2Reg = i.op2.isReg();
|
||||||
bool isDstReg = i.dst.isReg();
|
bool isDstReg = i.dst.isReg();
|
||||||
|
|
||||||
|
// check for operations like "add rx, rx, 0" or "add r0, anything"
|
||||||
if(isDstReg) {
|
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();
|
||||||
if(isOp1Reg) {
|
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(i.op1.index_or_imm == i.dst.index_or_imm
|
if (isDstR0) continue;
|
||||||
&& i.zeroRendersItUseless()) continue;
|
if (i.canDoDCE()) {
|
||||||
|
if (areDstAndOp1Same) {
|
||||||
|
if (i.op2.isImm() && i.op2.index_or_imm.value() == 0) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isOp2Reg) {
|
if (areDstAndOp2Same) {
|
||||||
if(i.op2.index_or_imm == i.dst.index_or_imm
|
if (i.op1.isImm() && i.op1.index_or_imm.value() == 0) continue;
|
||||||
&& i.zeroRendersItUseless()) continue;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ struct Entry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum Opcode : u16 {
|
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,
|
LOADS8, LOADS8_SHIFT, STORE8, STORE8_SHIFT,
|
||||||
LOADS16, LOADS16_SHIFT, STORE16, STORE16_SHIFT,
|
LOADS16, LOADS16_SHIFT, STORE16, STORE16_SHIFT,
|
||||||
LOADS32, LOADS32_SHIFT, STORE32, STORE32_SHIFT,
|
LOADS32, LOADS32_SHIFT, STORE32, STORE32_SHIFT,
|
||||||
@@ -45,8 +46,9 @@ struct Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isImm() const {
|
bool isImm() const {
|
||||||
return type == IMM_S64 || type == IMM_F32 || type == IMM_F64 || type == IMM_S32
|
return type == IMM_S64 || type == IMM_U16 || type == IMM_S16 ||
|
||||||
|| type == IMM_U64 || type == IMM_U32 || type == IMM_U5;
|
type == IMM_F32 || type == IMM_F64 || type == IMM_S32 ||
|
||||||
|
type == IMM_U64 || type == IMM_U32 || type == IMM_U5;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u64> index_or_imm = std::nullopt;
|
std::optional<u64> index_or_imm = std::nullopt;
|
||||||
@@ -56,7 +58,7 @@ struct Entry {
|
|||||||
: type(t), index_or_imm(imm) {}
|
: type(t), index_or_imm(imm) {}
|
||||||
} dst, op1, op2;
|
} dst, op1, op2;
|
||||||
|
|
||||||
bool zeroRendersItUseless() const {
|
bool canDoDCE() const {
|
||||||
return op == ADD || op == OR || op == SRL || op == SLL || op == SRA;
|
return op == ADD || op == OR || op == SRL || op == SLL || op == SRA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -476,35 +476,35 @@ void JIT::jalr(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JIT::slti(u32 instr) {
|
void JIT::slti(u32 instr) {
|
||||||
mov(rax, s64(s16(instr)));
|
Entry e(Entry::SLT,
|
||||||
mov(rcx, GPR(qword, RS(instr)));
|
{ Entry::Operand::REG_U5, RT(instr) },
|
||||||
cmp(rcx, rax);
|
{ Entry::Operand::REG_S64, RS(instr) },
|
||||||
setl(GPR(qword, RT(instr)));
|
{ Entry::Operand::IMM_S64, s64(s16(instr)) });
|
||||||
|
ir.push(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sltiu(u32 instr) {
|
void JIT::sltiu(u32 instr) {
|
||||||
mov(rax, s64(s16(instr)));
|
Entry e(Entry::SLT,
|
||||||
mov(rcx, GPR(qword, RS(instr)));
|
{ Entry::Operand::REG_U5, RT(instr) },
|
||||||
cmp(rcx, rax);
|
{ Entry::Operand::REG_U64, RS(instr) },
|
||||||
setb(GPR(qword, RT(instr)));
|
{ Entry::Operand::IMM_U64, u64(s64(s16(instr))) });
|
||||||
|
ir.push(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::slt(u32 instr) {
|
void JIT::slt(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
Entry e(Entry::SLT,
|
||||||
mov(rax, GPR(qword, RS(instr)));
|
{ Entry::Operand::REG_U5, RD(instr) },
|
||||||
mov(rcx, GPR(qword, RT(instr)));
|
{ Entry::Operand::REG_S64, RS(instr) },
|
||||||
cmp(rax, rcx);
|
{ Entry::Operand::REG_S64, RT(instr) });
|
||||||
setl(GPR(qword, RD(instr)));
|
ir.push(e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sltu(u32 instr) {
|
void JIT::sltu(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
Entry e(Entry::SLT,
|
||||||
mov(rax, GPR(qword, RS(instr)));
|
{ Entry::Operand::REG_U5, RD(instr) },
|
||||||
mov(rcx, GPR(qword, RT(instr)));
|
{ Entry::Operand::REG_U64, RS(instr) },
|
||||||
cmp(rax, rcx);
|
{ Entry::Operand::REG_U64, RT(instr) });
|
||||||
setb(GPR(qword, RD(instr)));
|
ir.push(e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::xori(u32 instr) {
|
void JIT::xori(u32 instr) {
|
||||||
|
|||||||
Reference in New Issue
Block a user