more instructions
This commit is contained in:
@@ -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>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user