more instructions

This commit is contained in:
SimoneN64
2023-08-13 11:21:33 +02:00
parent 63a10053f9
commit 6137d37c33
3 changed files with 92 additions and 59 deletions

View File

@@ -3,7 +3,7 @@
namespace n64 { namespace n64 {
using namespace Xbyak; using namespace Xbyak;
JIT::JIT() : CodeGenerator(0x80000) { } JIT::JIT() : CodeGenerator(0x80000, AutoGrow) { }
void JIT::Reset() { void JIT::Reset() {
reset(); reset();
@@ -77,7 +77,6 @@ Fn JIT::Recompile() {
} }
_epilogue: _epilogue:
epilogue(); epilogue();
mov(rax, cycles);
ready(); ready();
return getCode<Fn>(); return getCode<Fn>();
} }

View File

@@ -58,10 +58,16 @@ private:
for(auto r : allRegs) { for(auto r : allRegs) {
pop(r); pop(r);
} }
mov(rax, cycles);
ret();
} }
Fn* blocks[0x80000]{}; Fn* blocks[0x80000]{};
enum BranchCond {
LT, GT, GE, LE, EQ, NE
};
void cop2Decode(u32); void cop2Decode(u32);
void special(u32); void special(u32);
void regimm(u32); void regimm(u32);
@@ -72,12 +78,11 @@ private:
void addiu(u32); void addiu(u32);
void andi(u32); void andi(u32);
void and_(u32); void and_(u32);
void branch(bool, s64); void emitCondition(const std::string&, BranchCond);
void branch_likely(bool, s64); void b(u32, Xbyak::Operand, Xbyak::Operand, BranchCond);
void b(u32, bool); void blink(u32, Xbyak::Operand, Xbyak::Operand, BranchCond);
void blink(u32, bool); void bl(u32, Xbyak::Operand, Xbyak::Operand, BranchCond);
void bl(u32, bool); void bllink(u32, Xbyak::Operand, Xbyak::Operand, BranchCond);
void bllink(u32, bool);
void dadd(u32); void dadd(u32);
void daddu(u32); void daddu(u32);
void daddi(u32); void daddi(u32);

View File

@@ -59,7 +59,7 @@ void JIT::daddiu(u32 instr) {
void JIT::div(u32 instr) { void JIT::div(u32 instr) {
movsxd(rax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // dividend movsxd(rax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // dividend
movsxd(rcx, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // divisor movsxd(rcx, dword[rdi + offsetof(Registers, gpr[RT(instr)])]); // divisor
cmp(rcx, 0); cmp(rcx, 0);
je("divisor==0"); je("divisor==0");
@@ -78,7 +78,7 @@ void JIT::div(u32 instr) {
void JIT::divu(u32 instr) { void JIT::divu(u32 instr) {
movsxd(rax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // dividend movsxd(rax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // dividend
movsxd(rcx, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // divisor movsxd(rcx, dword[rdi + offsetof(Registers, gpr[RT(instr)])]); // divisor
cmp(rcx, 0); cmp(rcx, 0);
je("divisor==0"); je("divisor==0");
@@ -94,67 +94,96 @@ void JIT::divu(u32 instr) {
void JIT::ddiv(u32 instr) { void JIT::ddiv(u32 instr) {
s64 dividend = regs.gpr[RS(instr)]; s64 dividend = regs.gpr[RS(instr)];
s64 divisor = regs.gpr[RT(instr)]; s64 divisor = regs.gpr[RT(instr)];
if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { mov(rax, qword[rdi + offsetof(Registers, gpr[RS(instr)])]);
regs.lo = dividend; mov(rcx, qword[rdi + offsetof(Registers, gpr[RT(instr)])]);
regs.hi = 0; mov(r8, 0x8000000000000000);
} else if(divisor == 0) { cmp(rax, r8);
regs.hi = dividend; jne("else");
if(dividend >= 0) { mov(r8, 0xFFFFFFFFFFFFFFFF);
regs.lo = -1; cmp(rcx, r8);
} else { jne("else");
regs.lo = 1; cmp(rcx, 0);
} jne("else");
} else { je("else if");
s64 quotient = dividend / divisor; mov(qword[rdi + offsetof(Registers, lo)], rax);
s64 remainder = dividend % divisor; mov(qword[rdi + offsetof(Registers, hi)], 0);
regs.lo = quotient; L("else if");
regs.hi = remainder; mov(qword[rdi + offsetof(Registers, hi)], rax);
} cmp(rax, 0);
jge("dividend>=0");
mov(qword[rdi + offsetof(Registers, lo)], 1);
L("dividend>=0");
mov(qword[rdi + offsetof(Registers, lo)], -1);
L("else");
CodeGenerator::div(rcx);
mov(qword[rdi + offsetof(Registers, lo)], rax);
mov(qword[rdi + offsetof(Registers, hi)], rdx);
} }
void JIT::ddivu(u32 instr) { void JIT::ddivu(u32 instr) {
u64 dividend = regs.gpr[RS(instr)]; mov(rax, qword[rdi + offsetof(Registers, gpr[RS(instr)])]);
u64 divisor = regs.gpr[RT(instr)]; mov(rcx, qword[rdi + offsetof(Registers, gpr[RT(instr)])]);
if(divisor == 0) { cmp(rcx, 0);
regs.lo = -1; je("divisor==0");
regs.hi = (s64)dividend; CodeGenerator::div(rcx);
} else { mov(qword[rdi + offsetof(Registers, lo)], rax);
u64 quotient = dividend / divisor; mov(qword[rdi + offsetof(Registers, hi)], rdx);
u64 remainder = dividend % divisor; L("divisor==0");
regs.lo = (s64)quotient; mov(qword[rdi + offsetof(Registers, lo)], -1);
regs.hi = (s64)remainder; mov(qword[rdi + offsetof(Registers, hi)], rax);
}
void JIT::emitCondition(const std::string& name, BranchCond cond) {
switch(cond) {
case LT:
jnl(name);
break;
case GT:
jng(name);
break;
case GE:
jnge(name);
break;
case LE:
jnle(name);
break;
case EQ:
jne(name);
break;
case NE:
je(name);
break;
} }
} }
void JIT::branch(bool cond, s64 address) { void JIT::b(u32 instr, Xbyak::Operand op1, Xbyak::Operand op2, BranchCond cond) {
regs.delaySlot = true;
if (cond) {
regs.nextPC = address;
}
}
void JIT::branch_likely(bool cond, s64 address) {
if (cond) {
regs.delaySlot = true;
regs.nextPC = address;
} else {
regs.SetPC64(regs.nextPC);
}
}
void JIT::b(u32 instr, bool cond) {
s16 imm = instr; s16 imm = instr;
s64 offset = u64((s64)imm) << 2; s64 offset = u64((s64)imm) << 2;
s64 address = regs.pc + offset;
branch(cond, address); cmp(op1, op2);
emitCondition("false", cond);
mov(byte[rdi + offsetof(Registers, delaySlot)], 1);
mov(rax, qword[rdi + offsetof(Registers, pc)]);
CodeGenerator::add(rax, offset);
mov(qword[rdi + offsetof(Registers, nextPC)], rax);
L("false");
} }
void JIT::blink(u32 instr, bool cond) { void JIT::blink(u32 instr, Xbyak::Operand op1, Xbyak::Operand op2, BranchCond cond) {
regs.gpr[31] = regs.nextPC;
s16 imm = instr; s16 imm = instr;
s64 offset = u64((s64)imm) << 2; s64 offset = u64((s64)imm) << 2;
s64 address = regs.pc + offset;
branch(cond, address); cmp(op1, op2);
emitCondition("false", cond);
mov(byte[rdi + offsetof(Registers, delaySlot)], 1);
mov(rax, qword[rdi + offsetof(Registers, pc)]);
CodeGenerator::add(rax, offset);
mov(rcx, qword[rdi + offsetof(Registers, nextPC)]);
mov(qword[rdi + offsetof(Registers, gpr[31])], rcx);
mov(qword[rdi + offsetof(Registers, nextPC)], rax);
L("false");
} }
void JIT::bl(u32 instr, bool cond) { void JIT::bl(u32 instr, bool cond) {