arm64: implement swaplb and pref. Various optimizations
This commit is contained in:
parent
ec7787c56a
commit
e5ee48efa9
|
@ -34,11 +34,7 @@ enum eFReg {
|
||||||
S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31
|
S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31
|
||||||
};
|
};
|
||||||
|
|
||||||
#if HOST_OS == OS_DARWIN
|
|
||||||
#error "TODO static eReg alloc_regs[]={r5,r6,r7,r10,(eReg)-1};" // TODO
|
|
||||||
#else
|
|
||||||
static eReg alloc_regs[] = { W19, W20, W21, W22, W23, W24, W25, W26, (eReg)-1 };
|
static eReg alloc_regs[] = { W19, W20, W21, W22, W23, W24, W25, W26, (eReg)-1 };
|
||||||
#endif
|
|
||||||
static eFReg alloc_fregs[] = { S8, S9, S10, S11, S12, S13, S14, S15, (eFReg)-1 };
|
static eFReg alloc_fregs[] = { S8, S9, S10, S11, S12, S13, S14, S15, (eFReg)-1 };
|
||||||
|
|
||||||
class Arm64Assembler;
|
class Arm64Assembler;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "deps/vixl/aarch64/macro-assembler-aarch64.h"
|
#include "deps/vixl/aarch64/macro-assembler-aarch64.h"
|
||||||
using namespace vixl::aarch64;
|
using namespace vixl::aarch64;
|
||||||
|
@ -37,6 +38,8 @@ using namespace vixl::aarch64;
|
||||||
#include "hw/sh4/sh4_rom.h"
|
#include "hw/sh4/sh4_rom.h"
|
||||||
#include "arm64_regalloc.h"
|
#include "arm64_regalloc.h"
|
||||||
|
|
||||||
|
#undef do_sqw_nommu
|
||||||
|
|
||||||
struct DynaRBI : RuntimeBlockInfo
|
struct DynaRBI : RuntimeBlockInfo
|
||||||
{
|
{
|
||||||
virtual u32 Relink() {
|
virtual u32 Relink() {
|
||||||
|
@ -197,9 +200,8 @@ void ngen_blockcheckfail(u32 pc) {
|
||||||
|
|
||||||
class Arm64Assembler : public MacroAssembler
|
class Arm64Assembler : public MacroAssembler
|
||||||
{
|
{
|
||||||
typedef void (MacroAssembler::*Arm64Op)(const Register&, const Register&, const Operand&);
|
typedef void (MacroAssembler::*Arm64Op_RRO)(const Register&, const Register&, const Operand&);
|
||||||
typedef void (MacroAssembler::*Arm64Op2)(const Register&, const Register&, const Register&);
|
typedef void (MacroAssembler::*Arm64Op_RROF)(const Register&, const Register&, const Operand&, enum FlagsUpdate);
|
||||||
typedef void (MacroAssembler::*Arm64Op3)(const Register&, const Register&, const Operand&, enum FlagsUpdate);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Arm64Assembler() : MacroAssembler((u8 *)emit_GetCCPtr(), 64 * 1024), regalloc(this)
|
Arm64Assembler() : MacroAssembler((u8 *)emit_GetCCPtr(), 64 * 1024), regalloc(this)
|
||||||
|
@ -232,24 +234,66 @@ public:
|
||||||
call_fregs.push_back(&s7);
|
call_fregs.push_back(&s7);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngen_BinaryOp(shil_opcode* op, Arm64Op arm_op, Arm64Op2 arm_op2, Arm64Op3 arm_op3)
|
void ngen_BinaryOp_RRO(shil_opcode* op, Arm64Op_RRO arm_op, Arm64Op_RROF arm_op2)
|
||||||
{
|
{
|
||||||
const Register* reg3 = &wzr;
|
Operand op3 = Operand(0);
|
||||||
if (op->rs2.is_imm())
|
if (op->rs2.is_imm())
|
||||||
{
|
{
|
||||||
Mov(w10, op->rs2._imm);
|
op3 = Operand(op->rs2._imm);
|
||||||
reg3 = &w10;
|
|
||||||
}
|
}
|
||||||
else if (op->rs2.is_r32i())
|
else if (op->rs2.is_r32i())
|
||||||
{
|
{
|
||||||
reg3 = ®alloc.MapRegister(op->rs2);
|
op3 = Operand(regalloc.MapRegister(op->rs2));
|
||||||
}
|
}
|
||||||
if (arm_op != NULL)
|
if (arm_op != NULL)
|
||||||
((*this).*arm_op)(regalloc.MapRegister(op->rd), regalloc.MapRegister(op->rs1), *reg3);
|
((*this).*arm_op)(regalloc.MapRegister(op->rd), regalloc.MapRegister(op->rs1), op3);
|
||||||
else if (arm_op2 != NULL)
|
|
||||||
((*this).*arm_op2)(regalloc.MapRegister(op->rd), regalloc.MapRegister(op->rs1), *reg3);
|
|
||||||
else
|
else
|
||||||
((*this).*arm_op3)(regalloc.MapRegister(op->rd), regalloc.MapRegister(op->rs1), *reg3, LeaveFlags);
|
((*this).*arm_op2)(regalloc.MapRegister(op->rd), regalloc.MapRegister(op->rs1), op3, LeaveFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename... P>
|
||||||
|
void ngen_CallRuntime(R (*function)(P...))
|
||||||
|
{
|
||||||
|
if (!frame_reg_saved)
|
||||||
|
{
|
||||||
|
Str(x30, MemOperand(sp, -16, PreIndex));
|
||||||
|
frame_reg_saved = true;
|
||||||
|
}
|
||||||
|
Literal<uintptr_t> *function_address = function_literals[(void*)function];
|
||||||
|
if (function_address == NULL)
|
||||||
|
{
|
||||||
|
function_address = new Literal<uintptr_t>(reinterpret_cast<uintptr_t>(function), GetLiteralPool(), RawLiteral::kDeletedOnPoolDestruction);
|
||||||
|
function_literals[(void*)function] = function_address;
|
||||||
|
}
|
||||||
|
Ldr(x9, function_address);
|
||||||
|
Blr(x9);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Register& GenMemAddr(const shil_opcode& op, const Register* raddr = NULL)
|
||||||
|
{
|
||||||
|
const Register* ret_reg = raddr == NULL ? &w0 : raddr;
|
||||||
|
|
||||||
|
if (op.rs3.is_imm())
|
||||||
|
{
|
||||||
|
Add(*ret_reg, regalloc.MapRegister(op.rs1), op.rs3._imm);
|
||||||
|
}
|
||||||
|
else if (op.rs3.is_r32i())
|
||||||
|
{
|
||||||
|
Add(*ret_reg, regalloc.MapRegister(op.rs1), regalloc.MapRegister(op.rs3));
|
||||||
|
}
|
||||||
|
else if (!op.rs3.is_null())
|
||||||
|
{
|
||||||
|
die("invalid rs3");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (raddr == NULL)
|
||||||
|
ret_reg = ®alloc.MapRegister(op.rs1);
|
||||||
|
else
|
||||||
|
Mov(*ret_reg, regalloc.MapRegister(op.rs1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *ret_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngen_Compile(RuntimeBlockInfo* block, bool force_checks, bool reset, bool staging, bool optimise)
|
void ngen_Compile(RuntimeBlockInfo* block, bool force_checks, bool reset, bool staging, bool optimise)
|
||||||
|
@ -258,8 +302,6 @@ public:
|
||||||
if (force_checks)
|
if (force_checks)
|
||||||
CheckBlock(block);
|
CheckBlock(block);
|
||||||
|
|
||||||
Str(x30, MemOperand(sp, -16, PreIndex));
|
|
||||||
|
|
||||||
// run register allocator
|
// run register allocator
|
||||||
regalloc.DoAlloc(block);
|
regalloc.DoAlloc(block);
|
||||||
|
|
||||||
|
@ -281,19 +323,18 @@ public:
|
||||||
}
|
}
|
||||||
Mov(*call_regs[0], op.rs3._imm);
|
Mov(*call_regs[0], op.rs3._imm);
|
||||||
|
|
||||||
CallRuntime(OpDesc[op.rs3._imm]->oph);
|
ngen_CallRuntime(OpDesc[op.rs3._imm]->oph);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_jcond:
|
case shop_jcond:
|
||||||
case shop_jdyn:
|
case shop_jdyn:
|
||||||
Mov(w10, regalloc.MapRegister(op.rs1));
|
if (op.rs2.is_imm())
|
||||||
|
{
|
||||||
if (op.rs2.is_imm()) {
|
Add(w10, regalloc.MapRegister(op.rs1), op.rs2._imm);
|
||||||
Mov(w9, op.rs2._imm);
|
Mov(regalloc.MapRegister(op.rd), w10);
|
||||||
Add(w10, w10, w9);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
Mov(regalloc.MapRegister(op.rd), w10);
|
Mov(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_mov32:
|
case shop_mov32:
|
||||||
|
@ -340,7 +381,7 @@ public:
|
||||||
|
|
||||||
if (isram)
|
if (isram)
|
||||||
{
|
{
|
||||||
Mov(x1, reinterpret_cast<uintptr_t>(ptr));
|
Ldr(x1, reinterpret_cast<uintptr_t>(ptr));
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -367,17 +408,17 @@ public:
|
||||||
switch(size)
|
switch(size)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
CallRuntime((void (*)())ptr);
|
ngen_CallRuntime((void (*)())ptr);
|
||||||
Sxtb(w0, w0);
|
Sxtb(w0, w0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
CallRuntime((void (*)())ptr);
|
ngen_CallRuntime((void (*)())ptr);
|
||||||
Sxth(w0, w0);
|
Sxth(w0, w0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
CallRuntime((void (*)())ptr);
|
ngen_CallRuntime((void (*)())ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -432,31 +473,26 @@ public:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
shil_param_to_host_reg(op.rs1, *call_regs[0]);
|
GenMemAddr(op, call_regs[0]);
|
||||||
if (!op.rs3.is_null())
|
|
||||||
{
|
|
||||||
shil_param_to_host_reg(op.rs3, w10);
|
|
||||||
Add(*call_regs[0], *call_regs[0], w10);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
CallRuntime(ReadMem8);
|
ngen_CallRuntime(ReadMem8);
|
||||||
Sxtb(w0, w0);
|
Sxtb(w0, w0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
CallRuntime(ReadMem16);
|
ngen_CallRuntime(ReadMem16);
|
||||||
Sxth(w0, w0);
|
Sxth(w0, w0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
CallRuntime(ReadMem32);
|
ngen_CallRuntime(ReadMem32);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
CallRuntime(ReadMem64);
|
ngen_CallRuntime(ReadMem64);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -474,12 +510,7 @@ public:
|
||||||
|
|
||||||
case shop_writem:
|
case shop_writem:
|
||||||
{
|
{
|
||||||
shil_param_to_host_reg(op.rs1, *call_regs[0]);
|
GenMemAddr(op, call_regs[0]);
|
||||||
if (!op.rs3.is_null())
|
|
||||||
{
|
|
||||||
shil_param_to_host_reg(op.rs3, w10);
|
|
||||||
Add(*call_regs[0], *call_regs[0], w10);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 size = op.flags & 0x7f;
|
u32 size = op.flags & 0x7f;
|
||||||
if (size != 8)
|
if (size != 8)
|
||||||
|
@ -490,19 +521,19 @@ public:
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
CallRuntime(WriteMem8);
|
ngen_CallRuntime(WriteMem8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
CallRuntime(WriteMem16);
|
ngen_CallRuntime(WriteMem16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
CallRuntime(WriteMem32);
|
ngen_CallRuntime(WriteMem32);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
CallRuntime(WriteMem64);
|
ngen_CallRuntime(WriteMem64);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -513,7 +544,18 @@ public:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_sync_sr:
|
case shop_sync_sr:
|
||||||
CallRuntime(UpdateSR);
|
ngen_CallRuntime(UpdateSR);
|
||||||
|
break;
|
||||||
|
case shop_sync_fpscr:
|
||||||
|
ngen_CallRuntime(UpdateFPSCR);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case shop_swaplb:
|
||||||
|
// TODO Optimize
|
||||||
|
Mov(w9, Operand(regalloc.MapRegister(op.rs1), LSR, 16));
|
||||||
|
Rev16(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1));
|
||||||
|
Bfc(regalloc.MapRegister(op.rd), 16, 16);
|
||||||
|
Orr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rd), Operand(w9, LSL, 16));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_neg:
|
case shop_neg:
|
||||||
|
@ -523,32 +565,44 @@ public:
|
||||||
Mvn(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1));
|
Mvn(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_shl:
|
|
||||||
ngen_BinaryOp(&op, NULL, &MacroAssembler::Lsl, NULL);
|
|
||||||
break;
|
|
||||||
case shop_shr:
|
|
||||||
ngen_BinaryOp(&op, NULL, &MacroAssembler::Lsr, NULL);
|
|
||||||
break;
|
|
||||||
case shop_sar:
|
|
||||||
ngen_BinaryOp(& op, NULL, &MacroAssembler::Asr, NULL);
|
|
||||||
break;
|
|
||||||
case shop_and:
|
case shop_and:
|
||||||
ngen_BinaryOp(&op, &MacroAssembler::And, NULL, NULL);
|
ngen_BinaryOp_RRO(&op, &MacroAssembler::And, NULL);
|
||||||
break;
|
break;
|
||||||
case shop_or:
|
case shop_or:
|
||||||
ngen_BinaryOp(&op, &MacroAssembler::Orr, NULL, NULL);
|
ngen_BinaryOp_RRO(&op, &MacroAssembler::Orr, NULL);
|
||||||
break;
|
break;
|
||||||
case shop_xor:
|
case shop_xor:
|
||||||
ngen_BinaryOp(&op, &MacroAssembler::Eor, NULL, NULL);
|
ngen_BinaryOp_RRO(&op, &MacroAssembler::Eor, NULL);
|
||||||
break;
|
break;
|
||||||
case shop_add:
|
case shop_add:
|
||||||
ngen_BinaryOp(&op, NULL, NULL, &MacroAssembler::Add);
|
ngen_BinaryOp_RRO(&op, NULL, &MacroAssembler::Add);
|
||||||
break;
|
break;
|
||||||
case shop_sub:
|
case shop_sub:
|
||||||
ngen_BinaryOp(&op, NULL, NULL, &MacroAssembler::Sub);
|
ngen_BinaryOp_RRO(&op, NULL, &MacroAssembler::Sub);
|
||||||
|
break;
|
||||||
|
case shop_shl:
|
||||||
|
if (op.rs2.is_imm())
|
||||||
|
Lsl(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), op.rs2._imm);
|
||||||
|
else if (op.rs3.is_reg())
|
||||||
|
Lsl(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), regalloc.MapRegister(op.rs2));
|
||||||
|
break;
|
||||||
|
case shop_shr:
|
||||||
|
if (op.rs2.is_imm())
|
||||||
|
Lsr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), op.rs2._imm);
|
||||||
|
else if (op.rs3.is_reg())
|
||||||
|
Lsr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), regalloc.MapRegister(op.rs2));
|
||||||
|
break;
|
||||||
|
case shop_sar:
|
||||||
|
if (op.rs2.is_imm())
|
||||||
|
Asr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), op.rs2._imm);
|
||||||
|
else if (op.rs3.is_reg())
|
||||||
|
Asr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), regalloc.MapRegister(op.rs2));
|
||||||
break;
|
break;
|
||||||
case shop_ror:
|
case shop_ror:
|
||||||
ngen_BinaryOp(&op, NULL, &MacroAssembler::Ror, NULL);
|
if (op.rs2.is_imm())
|
||||||
|
Ror(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), op.rs2._imm);
|
||||||
|
else if (op.rs3.is_reg())
|
||||||
|
Ror(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), regalloc.MapRegister(op.rs2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_adc:
|
case shop_adc:
|
||||||
|
@ -563,10 +617,10 @@ public:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_rocr:
|
case shop_rocr:
|
||||||
Ubfm(w0, regalloc.MapRegister(op.rs1), 0, 0);
|
Ubfm(w0, regalloc.MapRegister(op.rs1), 0, 0); // w0 = rs1[0]
|
||||||
Mov(regalloc.MapRegister(op.rd), Operand(regalloc.MapRegister(op.rs1), LSR, 1));
|
Mov(regalloc.MapRegister(op.rd), Operand(regalloc.MapRegister(op.rs1), LSR, 1)); // rd = rs1 >> 1
|
||||||
Orr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rd), Operand(regalloc.MapRegister(op.rs2), LSL, 31));
|
Orr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rd), Operand(regalloc.MapRegister(op.rs2), LSL, 31)); // rd |= C << 31
|
||||||
Mov(regalloc.MapRegister(op.rd2), w0);
|
Mov(regalloc.MapRegister(op.rd2), w0); // rd2 = w0 (new C)
|
||||||
break;
|
break;
|
||||||
case shop_rocl:
|
case shop_rocl:
|
||||||
Tst(regalloc.MapRegister(op.rs1), 0x80000000); // Z = ~rs1[31]
|
Tst(regalloc.MapRegister(op.rs1), 0x80000000); // Z = ~rs1[31]
|
||||||
|
@ -575,14 +629,6 @@ public:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_shld:
|
case shop_shld:
|
||||||
// TODO optimize
|
|
||||||
Cmp(regalloc.MapRegister(op.rs2), 0);
|
|
||||||
Csel(w1, regalloc.MapRegister(op.rs2), wzr, ge);
|
|
||||||
Mov(w0, wzr); // wzr not supported by csneg
|
|
||||||
Csneg(w2, w0, regalloc.MapRegister(op.rs2), ge);
|
|
||||||
Lsl(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), w1);
|
|
||||||
Lsr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rd), w2);
|
|
||||||
break;
|
|
||||||
case shop_shad:
|
case shop_shad:
|
||||||
// TODO optimize
|
// TODO optimize
|
||||||
Cmp(regalloc.MapRegister(op.rs2), 0);
|
Cmp(regalloc.MapRegister(op.rs2), 0);
|
||||||
|
@ -590,7 +636,12 @@ public:
|
||||||
Mov(w0, wzr); // wzr not supported by csneg
|
Mov(w0, wzr); // wzr not supported by csneg
|
||||||
Csneg(w2, w0, regalloc.MapRegister(op.rs2), ge);
|
Csneg(w2, w0, regalloc.MapRegister(op.rs2), ge);
|
||||||
Lsl(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), w1);
|
Lsl(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1), w1);
|
||||||
Asr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rd), w2);
|
if (op.op == shop_shld)
|
||||||
|
// Logical shift
|
||||||
|
Lsr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rd), w2);
|
||||||
|
else
|
||||||
|
// Arithmetic shift
|
||||||
|
Asr(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rd), w2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_test:
|
case shop_test:
|
||||||
|
@ -661,6 +712,42 @@ public:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case shop_pref:
|
||||||
|
Mov(w0, regalloc.MapRegister(op.rs1));
|
||||||
|
if (op.flags != 0x1337)
|
||||||
|
{
|
||||||
|
Lsr(w1, regalloc.MapRegister(op.rs1), 26);
|
||||||
|
Cmp(w1, 0x38);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CCN_MMUCR.AT)
|
||||||
|
{
|
||||||
|
Mov(x9, reinterpret_cast<uintptr_t>(&do_sqw_mmu));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
verify(offsetof(Sh4RCB, cntx) - offsetof(Sh4RCB, do_sqw_nommu) > 0);
|
||||||
|
Sub(x9, x28, offsetof(Sh4RCB, cntx) - offsetof(Sh4RCB, do_sqw_nommu));
|
||||||
|
Ldr(x9, MemOperand(x9));
|
||||||
|
verify(offsetof(Sh4RCB, cntx) - offsetof(Sh4RCB, sq_buffer) > 0);
|
||||||
|
Sub(x1, x28, offsetof(Sh4RCB, cntx) - offsetof(Sh4RCB, sq_buffer));
|
||||||
|
}
|
||||||
|
if (!frame_reg_saved)
|
||||||
|
{
|
||||||
|
Str(x30, MemOperand(sp, -16, PreIndex));
|
||||||
|
frame_reg_saved = true;
|
||||||
|
}
|
||||||
|
if (op.flags == 0x1337)
|
||||||
|
Blr(x9);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Label no_branch;
|
||||||
|
B(&no_branch, ne);
|
||||||
|
Blr(x9);
|
||||||
|
Bind(&no_branch);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case shop_ext_s8:
|
case shop_ext_s8:
|
||||||
Sxtb(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1));
|
Sxtb(regalloc.MapRegister(op.rd), regalloc.MapRegister(op.rs1));
|
||||||
break;
|
break;
|
||||||
|
@ -714,13 +801,14 @@ public:
|
||||||
case shop_fsca:
|
case shop_fsca:
|
||||||
Mov(x1, reinterpret_cast<uintptr_t>(&sin_table));
|
Mov(x1, reinterpret_cast<uintptr_t>(&sin_table));
|
||||||
Add(x1, x1, Operand(regalloc.MapRegister(op.rs1), UXTH, 3));
|
Add(x1, x1, Operand(regalloc.MapRegister(op.rs1), UXTH, 3));
|
||||||
|
// TODO use regalloc
|
||||||
//Ldr(regalloc.MapVRegister(op.rd, 0), MemOperand(x1, 4, PostIndex));
|
//Ldr(regalloc.MapVRegister(op.rd, 0), MemOperand(x1, 4, PostIndex));
|
||||||
//Ldr(regalloc.MapVRegister(op.rd, 1), MemOperand(x1));
|
//Ldr(regalloc.MapVRegister(op.rd, 1), MemOperand(x1));
|
||||||
regalloc.writeback_fpu += 2;
|
regalloc.writeback_fpu += 2;
|
||||||
Ldr(w2, MemOperand(x1, 4, PostIndex));
|
Ldr(w2, MemOperand(x1, 4, PostIndex));
|
||||||
Str(w2, sh4_context_mem_operand(op.rd.reg_ptr())); // TODO use regalloc
|
Str(w2, sh4_context_mem_operand(op.rd.reg_ptr()));
|
||||||
Ldr(w2, MemOperand(x1));
|
Ldr(w2, MemOperand(x1));
|
||||||
Str(w2, sh4_context_mem_operand(GetRegPtr(op.rd._reg + 1))); // TODO use regalloc
|
Str(w2, sh4_context_mem_operand(GetRegPtr(op.rd._reg + 1)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shop_fipr:
|
case shop_fipr:
|
||||||
|
@ -835,14 +923,15 @@ public:
|
||||||
}
|
}
|
||||||
Str(w10, sh4_context_mem_operand(&next_pc));
|
Str(w10, sh4_context_mem_operand(&next_pc));
|
||||||
|
|
||||||
CallRuntime(UpdateINTC);
|
ngen_CallRuntime(UpdateINTC);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
die("Invalid block end type");
|
die("Invalid block end type");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ldr(x30, MemOperand(sp, 16, PostIndex));
|
if (frame_reg_saved)
|
||||||
|
Ldr(x30, MemOperand(sp, 16, PostIndex));
|
||||||
Ret();
|
Ret();
|
||||||
|
|
||||||
Label code_end;
|
Label code_end;
|
||||||
|
@ -950,7 +1039,7 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallRuntime((void (*)())function);
|
ngen_CallRuntime((void (*)())function);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemOperand sh4_context_mem_operand(void *p)
|
MemOperand sh4_context_mem_operand(void *p)
|
||||||
|
@ -973,11 +1062,11 @@ private:
|
||||||
// FIXME Can a block cross a RAM / non-RAM boundary??
|
// FIXME Can a block cross a RAM / non-RAM boundary??
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Mov(x9, reinterpret_cast<uintptr_t>(ptr));
|
Ldr(x9, reinterpret_cast<uintptr_t>(ptr));
|
||||||
|
|
||||||
while (sz > 0)
|
while (sz > 0)
|
||||||
{
|
{
|
||||||
if (sz >= 8 && (reinterpret_cast<uintptr_t>(ptr) & 7) == 0)
|
if (sz >= 8)
|
||||||
{
|
{
|
||||||
Ldr(x10, MemOperand(x9, 8, PostIndex));
|
Ldr(x10, MemOperand(x9, 8, PostIndex));
|
||||||
Ldr(x11, *(u64*)ptr);
|
Ldr(x11, *(u64*)ptr);
|
||||||
|
@ -985,7 +1074,7 @@ private:
|
||||||
sz -= 8;
|
sz -= 8;
|
||||||
ptr += 8;
|
ptr += 8;
|
||||||
}
|
}
|
||||||
else if (sz >= 4 && (reinterpret_cast<uintptr_t>(ptr) & 3) == 0)
|
else if (sz >= 4)
|
||||||
{
|
{
|
||||||
Ldr(w10, MemOperand(x9, 4, PostIndex));
|
Ldr(w10, MemOperand(x9, 4, PostIndex));
|
||||||
Ldr(w11, *(u32*)ptr);
|
Ldr(w11, *(u32*)ptr);
|
||||||
|
@ -1069,6 +1158,8 @@ private:
|
||||||
std::vector<const XRegister*> call_regs64;
|
std::vector<const XRegister*> call_regs64;
|
||||||
std::vector<const VRegister*> call_fregs;
|
std::vector<const VRegister*> call_fregs;
|
||||||
Arm64RegAlloc regalloc;
|
Arm64RegAlloc regalloc;
|
||||||
|
bool frame_reg_saved = false;
|
||||||
|
std::map<void*, Literal<uintptr_t>*> function_literals;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Arm64Assembler* compiler;
|
static Arm64Assembler* compiler;
|
||||||
|
@ -1134,10 +1225,8 @@ extern "C" void do_sqw_nommu_area_3(u32 dst, u8* sqb)
|
||||||
"add x1, x12, x1 \n\t" // SQ# selection, add to SQ ptr
|
"add x1, x12, x1 \n\t" // SQ# selection, add to SQ ptr
|
||||||
"add x11, x11, #512 \n\t" // get ram ptr from x1, part 2
|
"add x11, x11, #512 \n\t" // get ram ptr from x1, part 2
|
||||||
"add x11, x11, x0, lsl #5 \n\t" // ram + offset
|
"add x11, x11, x0, lsl #5 \n\t" // ram + offset
|
||||||
"ldp x9, x10, [x1], #16 \n\t"
|
"ld2 { v0.2D, v1.2D }, [x1] \n\t"
|
||||||
"stp x9, x10, [x11], #16 \n\t"
|
"st2 { v0.2D, v1.2D }, [x11] \n\t"
|
||||||
"ldp x9, x10, [x1] \n\t"
|
|
||||||
"stp x9, x10, [x11] \n\t"
|
|
||||||
"ret \n"
|
"ret \n"
|
||||||
|
|
||||||
: : : "memory"
|
: : : "memory"
|
||||||
|
|
Loading…
Reference in New Issue