mirror of
https://github.com/libretro/parallel-dc.git
synced 2026-11-07 04:25:58 -10:00
Rebase rec-ARM: (#1036)
* Rebase rec-ARM: * Update to latest files * Rename rec-ARM to arm_emitter * Create separate rec-ARM with ngen_arm.S and rec_arm.cpp files * Update rec-ARM files
This commit is contained in:
1 parent
689b9d5643
commit
d58c8fefc0
27 files changed
+292
-207
No files matched your search
File renamed without changes.
@@ -160,13 +160,14 @@ ADD.SP.REG 0x008D0000
|
||||
return ((i/2)<<8) | immv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static u32 ARMImmid8r4(u32 imm8r4)
|
||||
{
|
||||
u32 rv = ARMImmid8r4_enc(imm8r4);
|
||||
|
||||
verify(rv!=-1);
|
||||
return rv;
|
||||
}
|
||||
File renamed without changes.
@@ -309,4 +309,4 @@ EAPI POP(u32 RegList, ConditionCode CC=AL)
|
||||
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -627,7 +627,7 @@ namespace ARM
|
||||
eFSReg SnS=(eFSReg)(Sn*2);
|
||||
eFSReg SmS=(eFSReg)(Sm*2);
|
||||
|
||||
verify(Sd<32 && Sn<32 && Sm<32);
|
||||
verify((int)Sd < 32 && (int)Sn < 32 && (int)Sm < 32);
|
||||
|
||||
VDIV_VFP(SdS,SnS,SmS);
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -13,26 +13,27 @@ namespace ARM
|
||||
|
||||
|
||||
|
||||
inline static ptrdiff_t Literal(size_t FnAddr)
|
||||
inline static ptrdiff_t Literal(unat FnAddr)
|
||||
{
|
||||
u8* pc_addr = (u8*)EMIT_GET_PTR();
|
||||
return (ptrdiff_t)((ptrdiff_t)FnAddr - ((ptrdiff_t)pc_addr+8));
|
||||
//return -(ptrdiff_t)((pc_addr+8)-(ptrdiff_t)FnAddr);
|
||||
}
|
||||
|
||||
EAPI CALL(size_t FnAddr, ConditionCode CC=AL)
|
||||
EAPI CALL(unat FnAddr, ConditionCode CC=AL)
|
||||
{
|
||||
bool isThumb = FnAddr & 1;
|
||||
FnAddr &= ~1;
|
||||
ptrdiff_t lit = Literal(FnAddr);
|
||||
ptrdiff_t lit = Literal(FnAddr);
|
||||
|
||||
if(0==lit) {
|
||||
printf("Error, Compiler caught NULL literal, CALL(%08X)\n", FnAddr);
|
||||
printf("Error, Compiler caught NULL literal, CALL(%08zX)\n", FnAddr);
|
||||
verify(false);
|
||||
return;
|
||||
}
|
||||
if( (lit<-33554432) || (lit>33554428) ) // ..28 for BL ..30 for BLX
|
||||
{
|
||||
printf("Warning, CALL(%08X) is out of range for literal(%08X)\n", FnAddr, lit);
|
||||
printf("Warning, CALL(%08zX) is out of range for literal(%08zX)\n", FnAddr, lit);
|
||||
// verify(false);
|
||||
|
||||
MOV32(IP, FnAddr, CC);
|
||||
@@ -50,13 +51,13 @@ namespace ARM
|
||||
|
||||
|
||||
|
||||
EAPI JUMP(size_t FnAddr, ConditionCode CC=AL)
|
||||
EAPI JUMP(unat FnAddr, ConditionCode CC=AL)
|
||||
{
|
||||
bool isThumb = FnAddr & 1;
|
||||
FnAddr &= ~1;
|
||||
|
||||
verify(!isThumb);
|
||||
ptrdiff_t lit = Literal(FnAddr);
|
||||
ptrdiff_t lit = Literal(FnAddr);
|
||||
|
||||
/*if(0==lit) {
|
||||
printf("Error, Compiler caught NULL literal, JUMP(%08X)\n", FnAddr);
|
||||
@@ -65,7 +66,7 @@ namespace ARM
|
||||
}*/
|
||||
if( (lit<-33554432) || (lit>33554428) ) // ..28 for BL ..30 for BLX
|
||||
{
|
||||
printf("Warning, %X is out of range for imm jump! \n", FnAddr);
|
||||
printf("Warning, %zX is out of range for imm jump! \n", FnAddr);
|
||||
//verify(false);
|
||||
|
||||
MOV32(IP, FnAddr, CC);
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -23,7 +23,7 @@
|
||||
|
||||
//#include <sstream>
|
||||
#include "arm7.h"
|
||||
#include "rec-ARM/arm_coding.h"
|
||||
#include "arm_emitter/arm_coding.h"
|
||||
#include "deps/vixl/aarch64/macro-assembler-aarch64.h"
|
||||
using namespace vixl::aarch64;
|
||||
//#include "deps/vixl/aarch32/disasm-aarch32.h"
|
||||
|
||||
@@ -602,7 +602,7 @@ u8 ARM7_TCB[ICacheSize+4096] __attribute__((section("__TEXT, .text")));
|
||||
#error ARM7_TCB ALLOC
|
||||
#endif
|
||||
|
||||
#include "rec-ARM/arm_emitter.h"
|
||||
#include "arm_emitter/arm_emitter.h"
|
||||
#undef I
|
||||
|
||||
|
||||
|
||||
+18
-15
@@ -7,9 +7,8 @@
|
||||
|
||||
.equ SH4_TIMESLICE, 448
|
||||
.equ BM_BLOCKLIST_MASK, 65532 @FFFC
|
||||
.equ CPU_RATIO, 5
|
||||
|
||||
#ifdef __MACH__
|
||||
#if defined(__APPLE__)
|
||||
#define CSYM(n) _##n
|
||||
#define HIDDEN(n)
|
||||
#else
|
||||
@@ -57,7 +56,8 @@ bkpt #0
|
||||
#else
|
||||
bkpt
|
||||
#endif
|
||||
ubfx r0,r3,#5,#18 @ get vram offset
|
||||
ubfx r0,r3,#5,#19 @ get vram offset
|
||||
@ should be only 18 bits for 8MB VRAM but it wraps around on dc
|
||||
add r3,r1,#0x04000000 @ get vram ptr from r1, part 1
|
||||
add r3,#512 @ get ram ptr from r1, part 2
|
||||
add r3,r0,lsl #5 @ ram + offset
|
||||
@@ -137,7 +137,7 @@ CSYM(ngen_mainloop):
|
||||
push { r4-r12,lr }
|
||||
|
||||
|
||||
#ifdef __MACH__
|
||||
#if defined(__APPLE__)
|
||||
mov r11, #SH4_TIMESLICE @ load cycle counter
|
||||
#else
|
||||
mov r9, #SH4_TIMESLICE @ load cycle counter
|
||||
@@ -153,7 +153,7 @@ push { r4-r12,lr }
|
||||
.global CSYM(intc_sched)
|
||||
HIDDEN(intc_sched)
|
||||
CSYM(intc_sched): @ next_pc _MUST_ be on ram
|
||||
#ifdef __MACH__
|
||||
#if defined(__APPLE__)
|
||||
add r11,r11,#SH4_TIMESLICE
|
||||
#else
|
||||
add r9,r9,#SH4_TIMESLICE
|
||||
@@ -177,8 +177,16 @@ CSYM(no_update): @ next_pc _MUST_ be on r4 *R4 NOT R0 anymore*
|
||||
cmp r0,#0
|
||||
beq CSYM(cleanup)
|
||||
|
||||
#if RAM_SIZE_MAX == 33554432
|
||||
sub r2,r8,#0x4100000
|
||||
ubfx r1,r4,#1,#24
|
||||
ubfx r1,r4,#1,#24 @ 24+1 bits: 32 MB
|
||||
@ RAM wraps around so if actual RAM size is 16MB, we won't overflow
|
||||
#elif RAM_SIZE_MAX == 16777216
|
||||
sub r2,r8,#0x2100000
|
||||
ubfx r1,r4,#1,#23 @ 23+1 bits: 16 MB
|
||||
#else
|
||||
#error "Define RAM_SIZE_MAX"
|
||||
#endif
|
||||
ldr pc,[r2,r1,lsl #2]
|
||||
|
||||
@bic r1,r4,#0xFF000000
|
||||
@@ -210,7 +218,7 @@ XEntryPoints: .word CSYM(EntryPoints)
|
||||
HIDDEN(arm_mainloop)
|
||||
CSYM(arm_mainloop): @(cntx,lookup_base,cycles)
|
||||
|
||||
#ifdef __MACH__
|
||||
#if defined(__APPLE__)
|
||||
push {r4,r5,r8,r11,lr}
|
||||
#else
|
||||
push {r4,r5,r8,r9,lr}
|
||||
@@ -232,13 +240,8 @@ push {r4,r5,r8,r9,lr}
|
||||
.global CSYM(arm_dispatch)
|
||||
HIDDEN(arm_dispatch)
|
||||
CSYM(arm_dispatch):
|
||||
#ifdef TARGET_IPHONE
|
||||
ldrd r0,r1,[r8,#184] @load: Next PC, interrupt
|
||||
#else
|
||||
ldrd r0,[r8,#184] @load: Next PC, interrupt
|
||||
#endif
|
||||
|
||||
ubfx r2,r0,#2,#21
|
||||
ubfx r2,r0,#2,#21 @ assuming 8 MB address space max (23 bits)
|
||||
cmp r1,#0
|
||||
bne arm_dofiq
|
||||
|
||||
@@ -252,7 +255,7 @@ arm_dofiq:
|
||||
HIDDEN(arm_exit)
|
||||
CSYM(arm_exit):
|
||||
str r5,[r8,#192] @if timeslice is over, save remaining cycles
|
||||
#ifdef __MACH__
|
||||
#if defined(__APPLE__)
|
||||
pop {r4,r5,r8,r11,pc}
|
||||
#else
|
||||
pop {r4,r5,r8,r9,pc}
|
||||
@@ -260,7 +263,7 @@ CSYM(arm_exit):
|
||||
|
||||
@@@@@@
|
||||
@matrix mul
|
||||
#ifndef _ANDROID
|
||||
#ifndef __ANDROID__
|
||||
.global CSYM(ftrv_asm)
|
||||
HIDDEN(ftrv_asm)
|
||||
CSYM(ftrv_asm):
|
||||
|
||||
+134
-115
@@ -12,7 +12,9 @@
|
||||
#include "hw/sh4/sh4_mem.h"
|
||||
|
||||
#define _DEVEL 1
|
||||
#include "arm_emitter.h"
|
||||
#include "arm_emitter/arm_emitter.h"
|
||||
|
||||
//#define CANONICALTEST
|
||||
|
||||
/*
|
||||
|
||||
@@ -49,15 +51,17 @@ struct DynaRBI: RuntimeBlockInfo
|
||||
virtual u32 Relink();
|
||||
virtual void Relocate(void* dst)
|
||||
{
|
||||
|
||||
}
|
||||
ARM::eReg T_reg;
|
||||
};
|
||||
|
||||
#ifdef _ANDROID
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/syscall.h> // for cache flushing.
|
||||
#endif
|
||||
|
||||
#ifdef __MACH__
|
||||
#if defined(__APPLE__)
|
||||
#include <libkern/OSCacheControl.h>
|
||||
void CacheFlush(void* code, void* pEnd)
|
||||
{
|
||||
@@ -67,8 +71,8 @@ void CacheFlush(void* code, void* pEnd)
|
||||
#elif !defined(ARMCC)
|
||||
void CacheFlush(void* code, void* pEnd)
|
||||
{
|
||||
#if !defined(_ANDROID) && !defined(__MACH__)
|
||||
__builtin___clear_cache((char *)code, (char *)pEnd);
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
__builtin___clear_cache((char *)code, pEnd);
|
||||
#else
|
||||
void* start=code;
|
||||
size_t size=(u8*)pEnd-(u8*)start+4;
|
||||
@@ -220,7 +224,7 @@ void StoreSh4Reg_mem(eReg Rt,u32 Sh4_Reg, eCC CC=CC_AL)
|
||||
#include "hw/sh4/dyna/ssa_regalloc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __MACH__
|
||||
#if defined(__APPLE__)
|
||||
eReg alloc_regs[]={r5,r6,r7,r10,(eReg)-1};
|
||||
#else
|
||||
eReg alloc_regs[]={r5,r6,r7,r10,r11,(eReg)-1};
|
||||
@@ -228,7 +232,7 @@ eReg alloc_regs[]={r5,r6,r7,r10,r11,(eReg)-1};
|
||||
eFSReg alloc_fpu[]={f16,f17,f18,f19,f20,f21,f22,f23,
|
||||
f24,f25,f26,f27,f28,f29,f30,f31,(eFSReg)-1};
|
||||
|
||||
struct arm_reg_alloc: RegAlloc<eReg,eFSReg,false>
|
||||
struct arm_reg_alloc: RegAlloc<eReg, eFSReg>
|
||||
{
|
||||
virtual void Preload(u32 reg,eReg nreg)
|
||||
{
|
||||
@@ -240,7 +244,7 @@ struct arm_reg_alloc: RegAlloc<eReg,eFSReg,false>
|
||||
if (reg==reg_pc_dyn)
|
||||
// reg_pc_dyn has been stored in r4 by the jdyn op implementation
|
||||
// No need to write it back since it won't be used past the end of the block
|
||||
;//MOV(r4,nreg);
|
||||
; //MOV(r4,nreg);
|
||||
else
|
||||
StoreSh4Reg_mem(nreg,reg);
|
||||
}
|
||||
@@ -261,14 +265,12 @@ struct arm_reg_alloc: RegAlloc<eReg,eFSReg,false>
|
||||
{
|
||||
return mapf(prm);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
arm_reg_alloc reg;
|
||||
|
||||
u32 blockno=0;
|
||||
|
||||
|
||||
extern "C" void no_update();
|
||||
extern "C" void intc_sched();
|
||||
extern "C" void ngen_blockcheckfail();
|
||||
@@ -279,12 +281,11 @@ extern "C" void ngen_LinkBlock_cond_Branch_stub();
|
||||
extern "C" void ngen_LinkBlock_cond_Next_stub();
|
||||
|
||||
extern "C" void ngen_FailedToFindBlock_();
|
||||
void (*ngen_FailedToFindBlock)()=&ngen_FailedToFindBlock_; // in asm
|
||||
|
||||
#include <map>
|
||||
|
||||
map<shilop,ConditionCode> ccmap;
|
||||
map<shilop,ConditionCode> ccnmap;
|
||||
std::map<shilop,ConditionCode> ccmap;
|
||||
std::map<shilop,ConditionCode> ccnmap;
|
||||
|
||||
u32 DynaRBI::Relink()
|
||||
{
|
||||
@@ -396,8 +397,8 @@ u32 DynaRBI::Relink()
|
||||
{
|
||||
MOV32(r1,pBranchBlock->addr); //2
|
||||
CMP(r4,r1); //1
|
||||
JUMP((size_t)pBranchBlock->code,CC_EQ); //1
|
||||
CALL((size_t)ngen_LinkBlock_Generic_stub);//1
|
||||
JUMP((unat)pBranchBlock->code,CC_EQ); //1
|
||||
CALL((unat)ngen_LinkBlock_Generic_stub);//1
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -519,7 +520,7 @@ void ngen_Binary(shil_opcode* op, BinaryOP dtop, BinaryOPImm dtopimm)
|
||||
}
|
||||
else if (op->rs2.is_r32i())
|
||||
{
|
||||
rs2=reg.mapg(op->rs2);
|
||||
rs2 = reg.mapg(op->rs2);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -530,7 +531,7 @@ void ngen_Binary(shil_opcode* op, BinaryOP dtop, BinaryOPImm dtopimm)
|
||||
dtop(reg.mapg(op->rd), rs1, rs2, CC_AL);
|
||||
}
|
||||
|
||||
void ngen_fp_bin(shil_opcode* op, const FPBinOP fpop)
|
||||
void ngen_fp_bin(shil_opcode* op, FPBinOP fpop)
|
||||
{
|
||||
eFSReg rs1 = f0;
|
||||
if (op->rs1.is_imm())
|
||||
@@ -556,12 +557,13 @@ void ngen_fp_bin(shil_opcode* op, const FPBinOP fpop)
|
||||
|
||||
fpop(reg.mapfs(op->rd), rs1, rs2, CC_AL);
|
||||
}
|
||||
void ngen_fp_una(shil_opcode* op, const FPUnOP fpop)
|
||||
|
||||
void ngen_fp_una(shil_opcode* op, FPUnOP fpop)
|
||||
{
|
||||
verify(op->rd.is_r32f());
|
||||
verify(op->rs1.is_r32f());
|
||||
|
||||
fpop(reg.mapfs(op->rd),reg.mapfs(op->rs1),CC_AL);
|
||||
fpop(reg.mapfs(op->rd), reg.mapfs(op->rs1), CC_AL);
|
||||
}
|
||||
|
||||
struct CC_PS
|
||||
@@ -569,14 +571,12 @@ struct CC_PS
|
||||
CanonicalParamType type;
|
||||
shil_param* par;
|
||||
};
|
||||
vector<CC_PS> CC_pars;
|
||||
|
||||
void ngen_CC_Start_arm(shil_opcode* op)
|
||||
std::vector<CC_PS> CC_pars;
|
||||
void ngen_CC_Start(shil_opcode* op)
|
||||
{
|
||||
CC_pars.clear();
|
||||
}
|
||||
|
||||
void ngen_CC_Param_arm(shil_opcode* op,shil_param* par,CanonicalParamType tp)
|
||||
void ngen_CC_Param(shil_opcode* op,shil_param* par,CanonicalParamType tp)
|
||||
{
|
||||
switch(tp)
|
||||
{
|
||||
@@ -637,12 +637,12 @@ void ngen_CC_Param_arm(shil_opcode* op,shil_param* par,CanonicalParamType tp)
|
||||
}
|
||||
}
|
||||
|
||||
void ngen_CC_Call_arm(shil_opcode* op,void* function)
|
||||
void ngen_CC_Call(shil_opcode* op, void* function)
|
||||
{
|
||||
u32 rd=r0;
|
||||
u32 fd=f0;
|
||||
u32 rd = r0;
|
||||
u32 fd = f0;
|
||||
|
||||
for (int i=CC_pars.size();i-->0;)
|
||||
for (int i = CC_pars.size(); i-- > 0; )
|
||||
{
|
||||
CC_PS& param = CC_pars[i];
|
||||
if (param.type == CPT_ptr)
|
||||
@@ -698,8 +698,7 @@ void ngen_CC_Call_arm(shil_opcode* op,void* function)
|
||||
//printf("used reg r0 to r%d, %d params, calling %08X\n",rd-1,CC_pars.size(),function);
|
||||
CALL((u32)function);
|
||||
}
|
||||
|
||||
void ngen_CC_Finish_arm(shil_opcode* op)
|
||||
void ngen_CC_Finish(shil_opcode* op)
|
||||
{
|
||||
CC_pars.clear();
|
||||
}
|
||||
@@ -769,12 +768,12 @@ u32 memop_bytes(mem_op_type tp)
|
||||
call MEMHANDER<r1> // call MEMHANDLER64
|
||||
vmov rd,r0 // vmov.d rd,r3:r2
|
||||
*/
|
||||
size_t _mem_hndl_SQ32[14];
|
||||
size_t _mem_hndl[2][3][14];
|
||||
size_t _mem_func[2][5]=
|
||||
unat _mem_hndl_SQ32[14];
|
||||
unat _mem_hndl[2][3][14];
|
||||
unat _mem_func[2][5]=
|
||||
{
|
||||
{0,0,0,(size_t)_vmem_WriteMem32,(size_t)_vmem_WriteMem64},
|
||||
{0,0,0,(size_t)_vmem_ReadMem32,(size_t)_vmem_ReadMem64},
|
||||
{0,0,0,(unat)_vmem_WriteMem32,(unat)_vmem_WriteMem64},
|
||||
{0,0,0,(unat)_vmem_ReadMem32,(unat)_vmem_ReadMem64},
|
||||
};
|
||||
|
||||
struct
|
||||
@@ -962,7 +961,7 @@ u32* ngen_readm_fail_v2(u32* ptrv,u32* regs,u32 fault_addr)
|
||||
{
|
||||
MOV(r1,rt);
|
||||
|
||||
CALL((size_t)_mem_hndl_SQ32[raddr]);
|
||||
CALL((unat)_mem_hndl_SQ32[raddr]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1024,9 +1023,9 @@ u32* ngen_readm_fail_v2(u32* ptrv,u32* regs,u32 fault_addr)
|
||||
return (u32*)ptr;
|
||||
}
|
||||
|
||||
EAPI NEG(eReg Rd,eReg Rs)
|
||||
EAPI NEG(eReg Rd, eReg Rs)
|
||||
{
|
||||
RSB(Rd,Rs,0);
|
||||
RSB(Rd, Rs, 0);
|
||||
}
|
||||
|
||||
EAPI NEG(eReg Rd, eReg Rs, ConditionCode CC)
|
||||
@@ -1034,7 +1033,7 @@ EAPI NEG(eReg Rd, eReg Rs, ConditionCode CC)
|
||||
RSB(Rd, Rs, 0, CC);
|
||||
}
|
||||
|
||||
eReg GenMemAddr(shil_opcode* op,eReg raddr=r0)
|
||||
eReg GenMemAddr(shil_opcode* op, eReg raddr = r0)
|
||||
{
|
||||
if (op->rs3.is_imm())
|
||||
{
|
||||
@@ -1078,7 +1077,7 @@ bool ngen_readm_immediate(RuntimeBlockInfo* block, shil_opcode* op, bool staging
|
||||
bool isram = false;
|
||||
void* ptr = _vmem_read_const(op->rs1._imm, isram, std::min(4u, memop_bytes(optp)));
|
||||
eReg rd = (optp != SZ_32F && optp != SZ_64F) ? reg.mapg(op->rd) : r0;
|
||||
|
||||
|
||||
if (isram)
|
||||
{
|
||||
MOV32(r0, (u32)ptr);
|
||||
@@ -1097,7 +1096,7 @@ bool ngen_readm_immediate(RuntimeBlockInfo* block, shil_opcode* op, bool staging
|
||||
break;
|
||||
|
||||
case SZ_32F:
|
||||
VLDR(reg.mapfs(op->rd),r0,0);
|
||||
VLDR(reg.mapfs(op->rd), r0, 0);
|
||||
break;
|
||||
|
||||
case SZ_64F:
|
||||
@@ -1164,7 +1163,7 @@ bool ngen_writemem_immediate(RuntimeBlockInfo* block, shil_opcode* op, bool stag
|
||||
|
||||
mem_op_type optp = memop_type(op);
|
||||
bool isram = false;
|
||||
void* ptr = _vmem_write_const(op->rs1._imm, isram, max(4u, memop_bytes(optp)));
|
||||
void* ptr = _vmem_write_const(op->rs1._imm, isram, std::max(4u, memop_bytes(optp)));
|
||||
|
||||
eReg rs2 = r1;
|
||||
eFSReg rs2f = f0;
|
||||
@@ -1295,10 +1294,10 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
{
|
||||
if (!ngen_writemem_immediate(block, op, staging, optimise))
|
||||
{
|
||||
mem_op_type optp=memop_type(op);
|
||||
mem_op_type optp = memop_type(op);
|
||||
|
||||
eReg raddr=GenMemAddr(op);
|
||||
|
||||
|
||||
eReg rs2 = r2;
|
||||
eFSReg rs2f = f2;
|
||||
|
||||
@@ -1339,13 +1338,13 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
break;
|
||||
|
||||
case SZ_32F:
|
||||
ADD(r1,r1,r8); //3 opcodes: there's no [REG+REG] VLDR, also required for SQ
|
||||
ADD(r1, r1, r8); //3 opcodes: there's no [REG+REG] VLDR, also required for SQ
|
||||
VSTR(rs2f, r1, 0);
|
||||
break;
|
||||
|
||||
case SZ_64F:
|
||||
ADD(r1,r1,r8); //3 opcodes: there's no [REG+REG] VLDR, also required for SQ
|
||||
VSTR(d0,r1,0); //TODO: use reg alloc
|
||||
ADD(r1, r1, r8); //3 opcodes: there's no [REG+REG] VLDR, also required for SQ
|
||||
VSTR(d0, r1, 0); //TODO: use reg alloc
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -1384,7 +1383,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
if (op->rs2.is_imm())
|
||||
{
|
||||
MOV32(r2, op->rs2.imm_value());
|
||||
ADD(r4,reg.mapg(op->rs1),r2);
|
||||
ADD(r4, reg.mapg(op->rs1), r2);
|
||||
}
|
||||
else //if (r4!=rs1.reg)
|
||||
{
|
||||
@@ -1503,7 +1502,6 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
break;
|
||||
}
|
||||
|
||||
//#define CANONICALTEST
|
||||
#ifndef CANONICALTEST
|
||||
case shop_neg: ngen_Unary(op,NEG); break;
|
||||
case shop_not: ngen_Unary(op,NOT); break;
|
||||
@@ -1520,7 +1518,6 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
case shop_add: ngen_Binary(op,ADD,ADD); break;
|
||||
case shop_sub: ngen_Binary(op,SUB,SUB); break;
|
||||
case shop_ror: ngen_Binary(op,ROR,ROR); break;
|
||||
|
||||
|
||||
case shop_adc:
|
||||
{
|
||||
@@ -1543,7 +1540,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
|
||||
LSR(r0, rs3, 1, true); //C=rs3, r0=0
|
||||
ADC(reg.mapg(op->rd), rs1, rs2, true); //(C,rd)=rs1+rs2+rs3(C)
|
||||
ADC(reg.mapg(op->rd2),r0,0); //rd2=C, (or MOVCS rd2, 1)
|
||||
ADC(reg.mapg(op->rd2), r0, 0); //rd2=C, (or MOVCS rd2, 1)
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -1573,8 +1570,8 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
eReg rs1 = GetParam(op->rs1, r1);
|
||||
eReg rs2 = GetParam(op->rs2, r2);
|
||||
ORR(reg.mapg(op->rd), rs2, rs1, true, S_LSL, 1); //(C,rd)= rs1<<1 + (|) rs2
|
||||
MOVW(reg.mapg(op->rd2),0); //clear rd2 (for ADC/MOVCS)
|
||||
ADC(reg.mapg(op->rd2),reg.mapg(op->rd2),0); //rd2=C (or MOVCS rd2, 1)
|
||||
MOVW(reg.mapg(op->rd2), 0); //clear rd2 (for ADC/MOVCS)
|
||||
ADC(reg.mapg(op->rd2), reg.mapg(op->rd2), 0); //rd2=C (or MOVCS rd2, 1)
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1618,7 +1615,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
MOV(rd2, 1, CC_CC);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case shop_shld:
|
||||
//printf("shld: r%d r%d r%d\n",reg.mapg(op->rd),reg.mapg(op->rs1),reg.mapg(op->rs2));
|
||||
{
|
||||
@@ -1660,53 +1657,52 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
case shop_setgt:
|
||||
case shop_setae:
|
||||
case shop_setab:
|
||||
{
|
||||
eReg rd = reg.mapg(op->rd);
|
||||
eReg rs1 = GetParam(op->rs1, r0);
|
||||
|
||||
eReg rs2 = r1;
|
||||
bool is_imm = false;
|
||||
|
||||
if (op->rs2.is_imm())
|
||||
{
|
||||
eReg rd = reg.mapg(op->rd);
|
||||
eReg rs1 = GetParam(op->rs1, r0);
|
||||
|
||||
eReg rs2 = r1;
|
||||
bool is_imm=false;
|
||||
|
||||
if (op->rs2.is_imm())
|
||||
{
|
||||
if (!is_i8r4(op->rs2._imm))
|
||||
MOV32(rs2,(u32)op->rs2._imm);
|
||||
else
|
||||
is_imm=true;
|
||||
}
|
||||
else if (op->rs2.is_r32i())
|
||||
{
|
||||
rs2=reg.mapg(op->rs2);
|
||||
}
|
||||
if (!is_i8r4(op->rs2._imm))
|
||||
MOV32(rs2,(u32)op->rs2._imm);
|
||||
else
|
||||
{
|
||||
ERROR_LOG(DYNAREC, "ngen_Bin ??? %d", op->rs2.type);
|
||||
verify(false);
|
||||
}
|
||||
|
||||
if (op->op==shop_test)
|
||||
{
|
||||
if (is_imm)
|
||||
TST(rs1, op->rs2._imm);
|
||||
else
|
||||
TST(rs1, rs2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_imm)
|
||||
CMP(rs1, op->rs2._imm);
|
||||
else
|
||||
CMP(rs1, rs2);
|
||||
}
|
||||
|
||||
|
||||
eCC opcls2[]={CC_EQ,CC_EQ,CC_GE,CC_GT,CC_HS,CC_HI };
|
||||
|
||||
MOVW(rd, 0);
|
||||
MOVW(rd, 1, opcls2[op->op-shop_test]);
|
||||
break;
|
||||
is_imm = true;
|
||||
}
|
||||
|
||||
else if (op->rs2.is_r32i())
|
||||
{
|
||||
rs2 = reg.mapg(op->rs2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(DYNAREC, "ngen_Bin ??? %d", op->rs2.type);
|
||||
verify(false);
|
||||
}
|
||||
|
||||
if (op->op == shop_test)
|
||||
{
|
||||
if (is_imm)
|
||||
TST(rs1, op->rs2._imm);
|
||||
else
|
||||
TST(rs1, rs2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_imm)
|
||||
CMP(rs1, op->rs2._imm);
|
||||
else
|
||||
CMP(rs1, rs2);
|
||||
}
|
||||
|
||||
eCC opcls2[]={CC_EQ,CC_EQ,CC_GE,CC_GT,CC_HS,CC_HI };
|
||||
|
||||
MOVW(rd, 0);
|
||||
MOVW(rd, 1, opcls2[op->op-shop_test]);
|
||||
break;
|
||||
}
|
||||
|
||||
case shop_setpeq:
|
||||
{
|
||||
eReg rs1 = GetParam(op->rs1, r1);
|
||||
@@ -1729,7 +1725,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
eReg rs2 = GetParam(op->rs2, r2);
|
||||
UXTH(r1, reg.mapg(op->rs1));
|
||||
UXTH(r2, rs2);
|
||||
MUL(reg.mapg(op->rd),r1,r2);
|
||||
MUL(reg.mapg(op->rd), r1, r2);
|
||||
}
|
||||
break;
|
||||
case shop_mul_s16:
|
||||
@@ -1737,7 +1733,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
eReg rs2 = GetParam(op->rs2, r2);
|
||||
SXTH(r1, reg.mapg(op->rs1));
|
||||
SXTH(r2, rs2);
|
||||
MUL(reg.mapg(op->rd),r1,r2);
|
||||
MUL(reg.mapg(op->rd), r1, r2);
|
||||
}
|
||||
break;
|
||||
case shop_mul_i32:
|
||||
@@ -1888,7 +1884,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
case shop_fmul:
|
||||
case shop_fdiv:
|
||||
{
|
||||
const FPBinOP* opcds[]= { VADD_VFP,VSUB_VFP,VMUL_VFP,VDIV_VFP };
|
||||
FPBinOP* opcds[] = { VADD_VFP, VSUB_VFP, VMUL_VFP, VDIV_VFP };
|
||||
ngen_fp_bin(op, opcds[op->op-shop_fadd]);
|
||||
}
|
||||
break;
|
||||
@@ -1896,7 +1892,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
case shop_fabs:
|
||||
case shop_fneg:
|
||||
{
|
||||
const FPUnOP* opcds[]= { VABS_VFP,VNEG_VFP};
|
||||
FPUnOP* opcds[] = { VABS_VFP, VNEG_VFP };
|
||||
ngen_fp_una(op, opcds[op->op-shop_fabs]);
|
||||
}
|
||||
break;
|
||||
@@ -2004,7 +2000,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
||||
case shop_fsca:
|
||||
{
|
||||
//r1: base ptr
|
||||
MOVW(r1,((size_t)sin_table)&0xFFFF);
|
||||
MOVW(r1,((unat)sin_table)&0xFFFF);
|
||||
UXTH(r0,reg.mapg(op->rs1));
|
||||
MOVT(r1,((u32)sin_table)>>16);
|
||||
|
||||
@@ -2206,7 +2202,7 @@ __default:
|
||||
}
|
||||
|
||||
|
||||
void ngen_Compile_arm(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)
|
||||
{
|
||||
//printf("Compile: %08X, %d, %d\n",block->addr,staging,optimise);
|
||||
block->code=(DynarecCodeEntryPtr)EMIT_GET_PTR();
|
||||
@@ -2214,6 +2210,14 @@ void ngen_Compile_arm(RuntimeBlockInfo* block,bool force_checks, bool reset, boo
|
||||
//StoreImms(r0,r1,(u32)&last_run_block,(u32)code); //useful when code jumps to random locations ...
|
||||
++blockno;
|
||||
|
||||
if (settings.profile.run_counts)
|
||||
{
|
||||
MOV32(r1,(u32)&block->runs);
|
||||
LDR(r0,r1);
|
||||
ADD(r0,r0,1);
|
||||
STR(r0,r1);
|
||||
}
|
||||
|
||||
//reg alloc
|
||||
reg.DoAlloc(block,alloc_regs,alloc_fpu);
|
||||
|
||||
@@ -2278,7 +2282,7 @@ void ngen_Compile_arm(RuntimeBlockInfo* block,bool force_checks, bool reset, boo
|
||||
cyc&=~3;
|
||||
}
|
||||
|
||||
#ifdef __MACH__
|
||||
#if defined(__APPLE__)
|
||||
SUB(r11,r11,cyc,true,CC_AL);
|
||||
#else
|
||||
SUB(rfp_r9,rfp_r9,cyc,true,CC_AL);
|
||||
@@ -2365,8 +2369,15 @@ void ngen_Compile_arm(RuntimeBlockInfo* block,bool force_checks, bool reset, boo
|
||||
|
||||
//host code size needs to cover the entire range of the block
|
||||
block->host_code_size=(pEnd-(u8*)block->code);
|
||||
|
||||
void emit_WriteCodeCache();
|
||||
// emit_WriteCodeCache();
|
||||
}
|
||||
|
||||
void ngen_ResetBlocks()
|
||||
{
|
||||
INFO_LOG(DYNAREC, "@@ ngen_ResetBlocks()");
|
||||
}
|
||||
/*
|
||||
SHR ..
|
||||
CMP ..
|
||||
@@ -2375,13 +2386,15 @@ void ngen_Compile_arm(RuntimeBlockInfo* block,bool force_checks, bool reset, boo
|
||||
add
|
||||
str
|
||||
*/
|
||||
void ngen_init_arm(void)
|
||||
void ngen_init()
|
||||
{
|
||||
INFO_LOG(DYNAREC, "Initializing the ARM32 dynarec");
|
||||
verify(FPCB_OFFSET == -0x2100000 || FPCB_OFFSET == -0x4100000);
|
||||
verify(rcb_noffs(p_sh4rcb->fpcb) == FPCB_OFFSET);
|
||||
|
||||
for (int s=0;s<6;s++)
|
||||
ngen_FailedToFindBlock = &ngen_FailedToFindBlock_;
|
||||
|
||||
for (int s=0;s<6;s++)
|
||||
{
|
||||
void* fn=s==0?(void*)_vmem_ReadMem8SX32:
|
||||
s==1?(void*)_vmem_ReadMem16SX32:
|
||||
@@ -2399,14 +2412,14 @@ void ngen_init_arm(void)
|
||||
if (i==1 || i ==2 || i == 3 || i == 4 || i==12 || i==13)
|
||||
continue;
|
||||
|
||||
size_t v;
|
||||
unat v;
|
||||
if (read)
|
||||
{
|
||||
if (i==0)
|
||||
v=(size_t)fn;
|
||||
v=(unat)fn;
|
||||
else
|
||||
{
|
||||
v=(size_t)EMIT_GET_PTR();
|
||||
v=(unat)EMIT_GET_PTR();
|
||||
MOV(r0,(eReg)(i));
|
||||
JUMP((u32)fn);
|
||||
}
|
||||
@@ -2414,10 +2427,10 @@ void ngen_init_arm(void)
|
||||
else
|
||||
{
|
||||
if (i==0)
|
||||
v=(size_t)fn;
|
||||
v=(unat)fn;
|
||||
else
|
||||
{
|
||||
v=(size_t)EMIT_GET_PTR();
|
||||
v=(unat)EMIT_GET_PTR();
|
||||
MOV(r0,(eReg)(i));
|
||||
JUMP((u32)fn);
|
||||
}
|
||||
@@ -2432,7 +2445,7 @@ void ngen_init_arm(void)
|
||||
if (i==1 || i ==2 || i == 3 || i == 4 || i==12 || i==13)
|
||||
continue;
|
||||
|
||||
_mem_hndl_SQ32[i]=(size_t)EMIT_GET_PTR();
|
||||
_mem_hndl_SQ32[i]=(unat)EMIT_GET_PTR();
|
||||
|
||||
//UBFX(r3,(eReg)i,0,6);
|
||||
AND(r3,(eReg)i,0x3F);
|
||||
@@ -2440,7 +2453,7 @@ void ngen_init_arm(void)
|
||||
MOV(r0,(eReg)i);
|
||||
ADD(r3,r3,r8);
|
||||
CMP(r2,0x38);
|
||||
JUMP((size_t)&_vmem_WriteMem32,CC_NE);
|
||||
JUMP((unat)&_vmem_WriteMem32,CC_NE);
|
||||
STR(r1,r3,rcb_noffs(sq_both));
|
||||
BX(LR);
|
||||
}
|
||||
@@ -2473,9 +2486,15 @@ void ngen_init_arm(void)
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ngen_GetFeatures(ngen_features* dst)
|
||||
{
|
||||
dst->InterpreterFallback=false;
|
||||
dst->OnlyDynamicEnds=false;
|
||||
}
|
||||
|
||||
RuntimeBlockInfo* ngen_AllocateBlock()
|
||||
{
|
||||
return new DynaRBI();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -42,11 +42,7 @@ static eFReg alloc_fregs[] = { S8, S9, S10, S11, S12, S13, S14, S15, (eFReg)-1 }
|
||||
|
||||
class Arm64Assembler;
|
||||
|
||||
struct Arm64RegAlloc : RegAlloc<eReg, eFReg
|
||||
#ifndef EXPLODE_SPANS
|
||||
, false
|
||||
#endif
|
||||
>
|
||||
struct Arm64RegAlloc : RegAlloc<eReg, eFReg>
|
||||
{
|
||||
Arm64RegAlloc(Arm64Assembler *assembler) : assembler(assembler) {}
|
||||
|
||||
@@ -73,9 +69,6 @@ struct Arm64RegAlloc : RegAlloc<eReg, eFReg
|
||||
#ifdef OLD_REGALLOC
|
||||
eFReg ereg = mapfv(param, index);
|
||||
#else
|
||||
#ifdef EXPLODE_SPANS
|
||||
#error EXPLODE_SPANS not supported with ssa regalloc
|
||||
#endif
|
||||
verify(index == 0);
|
||||
eFReg ereg = mapf(param);
|
||||
#endif
|
||||
|
||||
+124
-56
@@ -28,7 +28,7 @@
|
||||
#include "deps/vixl/aarch64/macro-assembler-aarch64.h"
|
||||
using namespace vixl::aarch64;
|
||||
|
||||
//#define EXPLODE_SPANS
|
||||
//#define NO_BLOCK_LINKING
|
||||
|
||||
#include "hw/sh4/sh4_opcode_list.h"
|
||||
|
||||
@@ -52,6 +52,9 @@ extern "C" void ngen_FailedToFindBlock_nommu();
|
||||
extern void vmem_platform_flush_cache(void *icache_start, void *icache_end, void *dcache_start, void *dcache_end);
|
||||
static void generate_mainloop();
|
||||
|
||||
u32 mem_writes, mem_reads;
|
||||
u32 mem_rewrites_w, mem_rewrites_r;
|
||||
|
||||
struct DynaRBI : RuntimeBlockInfo
|
||||
{
|
||||
virtual u32 Relink() override;
|
||||
@@ -61,6 +64,8 @@ struct DynaRBI : RuntimeBlockInfo
|
||||
}
|
||||
};
|
||||
|
||||
double host_cpu_time;
|
||||
u64 guest_cpu_cycles;
|
||||
static jmp_buf jmp_env;
|
||||
static u32 cycle_counter;
|
||||
|
||||
@@ -68,7 +73,70 @@ static void (*mainloop)(void *context);
|
||||
static int (*arm64_intc_sched)();
|
||||
static void (*arm64_no_update)();
|
||||
|
||||
void(*ngen_FailedToFindBlock)();
|
||||
#ifdef PROFILING
|
||||
#include <time.h>
|
||||
|
||||
static clock_t slice_start;
|
||||
extern "C"
|
||||
{
|
||||
static __attribute((used)) void start_slice()
|
||||
{
|
||||
slice_start = clock();
|
||||
}
|
||||
static __attribute((used)) void end_slice()
|
||||
{
|
||||
host_cpu_time += (double)(clock() - slice_start) / CLOCKS_PER_SEC;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__asm__
|
||||
(
|
||||
".hidden ngen_LinkBlock_cond_Branch_stub \n\t"
|
||||
".globl ngen_LinkBlock_cond_Branch_stub \n\t"
|
||||
"ngen_LinkBlock_cond_Branch_stub: \n\t"
|
||||
"mov w1, #1 \n\t"
|
||||
"b ngen_LinkBlock_Shared_stub \n"
|
||||
|
||||
".hidden ngen_LinkBlock_cond_Next_stub \n\t"
|
||||
".globl ngen_LinkBlock_cond_Next_stub \n\t"
|
||||
"ngen_LinkBlock_cond_Next_stub: \n\t"
|
||||
"mov w1, #0 \n\t"
|
||||
"b ngen_LinkBlock_Shared_stub \n"
|
||||
|
||||
".hidden ngen_LinkBlock_Generic_stub \n\t"
|
||||
".globl ngen_LinkBlock_Generic_stub \n\t"
|
||||
"ngen_LinkBlock_Generic_stub: \n\t"
|
||||
"mov w1, w29 \n\t" // djump/pc -> in case we need it ..
|
||||
//"b ngen_LinkBlock_Shared_stub \n"
|
||||
|
||||
".hidden ngen_LinkBlock_Shared_stub \n\t"
|
||||
".globl ngen_LinkBlock_Shared_stub \n\t"
|
||||
"ngen_LinkBlock_Shared_stub: \n\t"
|
||||
"sub x0, lr, #4 \n\t" // go before the call
|
||||
"bl rdv_LinkBlock \n\t" // returns an RX addr
|
||||
"br x0 \n"
|
||||
|
||||
".hidden ngen_FailedToFindBlock_nommu \n\t"
|
||||
".globl ngen_FailedToFindBlock_nommu \n\t"
|
||||
"ngen_FailedToFindBlock_nommu: \n\t"
|
||||
"mov w0, w29 \n\t"
|
||||
"bl rdv_FailedToFindBlock \n\t"
|
||||
"br x0 \n"
|
||||
|
||||
".hidden ngen_FailedToFindBlock_mmu \n\t"
|
||||
".globl ngen_FailedToFindBlock_mmu \n\t"
|
||||
"ngen_FailedToFindBlock_mmu: \n\t"
|
||||
"bl rdv_FailedToFindBlock_pc \n\t"
|
||||
"br x0 \n"
|
||||
|
||||
".hidden ngen_blockcheckfail \n\t"
|
||||
".globl ngen_blockcheckfail \n\t"
|
||||
"ngen_blockcheckfail: \n\t"
|
||||
"bl rdv_BlockCheckFail \n\t"
|
||||
"br x0 \n"
|
||||
);
|
||||
|
||||
static bool restarting;
|
||||
|
||||
void ngen_mainloop(void* v_cntx)
|
||||
@@ -83,13 +151,13 @@ void ngen_mainloop(void* v_cntx)
|
||||
} while (restarting);
|
||||
}
|
||||
|
||||
void ngen_init_arm64()
|
||||
void ngen_init()
|
||||
{
|
||||
INFO_LOG(DYNAREC, "Initializing the ARM64 dynarec");
|
||||
ngen_FailedToFindBlock = &ngen_FailedToFindBlock_nommu;
|
||||
}
|
||||
|
||||
void ngen_ResetBlocks_arm64()
|
||||
void ngen_ResetBlocks()
|
||||
{
|
||||
mainloop = NULL;
|
||||
if (mmu_enabled())
|
||||
@@ -104,6 +172,12 @@ void ngen_ResetBlocks_arm64()
|
||||
}
|
||||
}
|
||||
|
||||
void ngen_GetFeatures(ngen_features* dst)
|
||||
{
|
||||
dst->InterpreterFallback = false;
|
||||
dst->OnlyDynamicEnds = false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T ReadMemNoEx(u32 addr, u32, u32 pc)
|
||||
{
|
||||
@@ -303,9 +377,12 @@ public:
|
||||
void ngen_Compile(RuntimeBlockInfo* block, bool force_checks, bool reset, bool staging, bool optimise)
|
||||
{
|
||||
//printf("REC-ARM64 compiling %08x\n", block->addr);
|
||||
#ifdef PROFILING
|
||||
SaveFramePointer();
|
||||
#endif
|
||||
this->block = block;
|
||||
CheckBlock(force_checks, block);
|
||||
|
||||
|
||||
// run register allocator
|
||||
regalloc.DoAlloc(block);
|
||||
|
||||
@@ -332,6 +409,12 @@ public:
|
||||
Bind(&cpu_running);
|
||||
Bind(&cycles_remaining);
|
||||
|
||||
#ifdef PROFILING
|
||||
Ldr(x11, (uintptr_t)&guest_cpu_cycles);
|
||||
Ldr(x0, MemOperand(x11));
|
||||
Add(x0, x0, block->guest_cycles);
|
||||
Str(x0, MemOperand(x11));
|
||||
#endif
|
||||
for (size_t i = 0; i < block->oplist.size(); i++)
|
||||
{
|
||||
shil_opcode& op = block->oplist[i];
|
||||
@@ -404,13 +487,8 @@ public:
|
||||
verify(op.rd.is_reg());
|
||||
verify(op.rs1.is_reg() || op.rs1.is_imm());
|
||||
|
||||
#ifdef EXPLODE_SPANS
|
||||
Fmov(regalloc.MapVRegister(op.rd, 0), regalloc.MapVRegister(op.rs1, 0));
|
||||
Fmov(regalloc.MapVRegister(op.rd, 1), regalloc.MapVRegister(op.rs1, 1));
|
||||
#else
|
||||
shil_param_to_host_reg(op.rs1, x15);
|
||||
host_reg_to_shil_param(op.rd, x15);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case shop_readm:
|
||||
@@ -923,13 +1001,8 @@ public:
|
||||
Add(x1, x1, Operand(regalloc.MapRegister(op.rs1), UXTH, 3));
|
||||
else
|
||||
Add(x1, x1, Operand(op.rs1.imm_value() << 3));
|
||||
#ifdef EXPLODE_SPANS
|
||||
Ldr(regalloc.MapVRegister(op.rd, 0), MemOperand(x1, 4, PostIndex));
|
||||
Ldr(regalloc.MapVRegister(op.rd, 1), MemOperand(x1));
|
||||
#else
|
||||
Ldr(x2, MemOperand(x1));
|
||||
Str(x2, sh4_context_mem_operand(op.rd.reg_ptr()));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case shop_fipr:
|
||||
@@ -1178,19 +1251,23 @@ public:
|
||||
case BET_StaticJump:
|
||||
case BET_StaticCall:
|
||||
// next_pc = block->BranchBlock;
|
||||
if (block->pBranchBlock == NULL)
|
||||
#ifndef NO_BLOCK_LINKING
|
||||
if (block->pBranchBlock != NULL)
|
||||
GenBranch(block->pBranchBlock->code);
|
||||
else
|
||||
{
|
||||
if (!mmu_enabled())
|
||||
GenCallRuntime(ngen_LinkBlock_Generic_stub);
|
||||
else
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
{
|
||||
Mov(w29, block->BranchBlock);
|
||||
Str(w29, sh4_context_mem_operand(&next_pc));
|
||||
GenBranch(*arm64_no_update);
|
||||
}
|
||||
}
|
||||
else
|
||||
GenBranch(block->pBranchBlock->code);
|
||||
break;
|
||||
|
||||
case BET_Cond_0:
|
||||
@@ -1210,6 +1287,7 @@ public:
|
||||
Label branch_not_taken;
|
||||
|
||||
B(ne, &branch_not_taken);
|
||||
#ifndef NO_BLOCK_LINKING
|
||||
if (block->pBranchBlock != NULL)
|
||||
GenBranch(block->pBranchBlock->code);
|
||||
else
|
||||
@@ -1217,6 +1295,9 @@ public:
|
||||
if (!mmu_enabled())
|
||||
GenCallRuntime(ngen_LinkBlock_cond_Branch_stub);
|
||||
else
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
{
|
||||
Mov(w29, block->BranchBlock);
|
||||
Str(w29, sh4_context_mem_operand(&next_pc));
|
||||
@@ -1226,6 +1307,7 @@ public:
|
||||
|
||||
Bind(&branch_not_taken);
|
||||
|
||||
#ifndef NO_BLOCK_LINKING
|
||||
if (block->pNextBlock != NULL)
|
||||
GenBranch(block->pNextBlock->code);
|
||||
else
|
||||
@@ -1233,6 +1315,9 @@ public:
|
||||
if (!mmu_enabled())
|
||||
GenCallRuntime(ngen_LinkBlock_cond_Next_stub);
|
||||
else
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
{
|
||||
Mov(w29, block->NextBlock);
|
||||
Str(w29, sh4_context_mem_operand(&next_pc));
|
||||
@@ -1367,7 +1452,7 @@ public:
|
||||
Br(x0);
|
||||
|
||||
// void mainloop(void *context)
|
||||
mainloop = (void (*)(void *)) CC_RW2RX(GetCursorAddress<uintptr_t>());
|
||||
mainloop = (void (*)(void *))CC_RW2RX(GetCursorAddress<uintptr_t>());
|
||||
|
||||
// Save registers
|
||||
Stp(x19, x20, MemOperand(sp, -160, PreIndex));
|
||||
@@ -1533,16 +1618,7 @@ private:
|
||||
if (size < 8)
|
||||
host_reg_to_shil_param(op.rd, w0);
|
||||
else
|
||||
{
|
||||
#ifdef EXPLODE_SPANS
|
||||
verify(op.rd.count() == 2 && regalloc.IsAllocf(op.rd, 0) && regalloc.IsAllocf(op.rd, 1));
|
||||
Fmov(regalloc.MapVRegister(op.rd, 0), w0);
|
||||
Lsr(x0, x0, 32);
|
||||
Fmov(regalloc.MapVRegister(op.rd, 1), w0);
|
||||
#else
|
||||
Str(x0, sh4_context_mem_operand(op.rd.reg_ptr()));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool GenReadMemoryImmediate(const shil_opcode& op)
|
||||
@@ -1552,8 +1628,7 @@ private:
|
||||
|
||||
u32 size = op.flags & 0x7f;
|
||||
u32 addr = op.rs1._imm;
|
||||
#ifndef NO_MMU
|
||||
if (mmu_enabled())
|
||||
if (mmu_enabled() && mmu_is_translated<MMU_TT_DREAD>(addr, size))
|
||||
{
|
||||
if ((addr >> 12) != (block->vaddr >> 12))
|
||||
// When full mmu is on, only consider addresses in the same 4k page
|
||||
@@ -1580,7 +1655,6 @@ private:
|
||||
return false;
|
||||
addr = paddr;
|
||||
}
|
||||
#endif // NO_MMU
|
||||
bool isram = false;
|
||||
void* ptr = _vmem_read_const(addr, isram, size > 4 ? 4 : size);
|
||||
|
||||
@@ -1699,6 +1773,7 @@ private:
|
||||
// Direct memory access. Need to handle SIGSEGV and rewrite block as needed. See ngen_Rewrite()
|
||||
if (!_nvmem_enabled() || (mmu_enabled() && !vmem32_enabled()))
|
||||
return false;
|
||||
mem_reads++;
|
||||
|
||||
Instruction *start_instruction = GetCursorAddress<Instruction *>();
|
||||
|
||||
@@ -1751,17 +1826,7 @@ private:
|
||||
if (size != 8)
|
||||
shil_param_to_host_reg(op.rs2, *call_regs[1]);
|
||||
else
|
||||
{
|
||||
#ifdef EXPLODE_SPANS
|
||||
verify(op.rs2.count() == 2 && regalloc.IsAllocf(op.rs2, 0) && regalloc.IsAllocf(op.rs2, 1));
|
||||
Fmov(*call_regs[1], regalloc.MapVRegister(op.rs2, 1));
|
||||
Lsl(*call_regs64[1], *call_regs64[1], 32);
|
||||
Fmov(w2, regalloc.MapVRegister(op.rs2, 0));
|
||||
Orr(*call_regs64[1], *call_regs64[1], x2);
|
||||
#else
|
||||
shil_param_to_host_reg(op.rs2, *call_regs64[1]);
|
||||
#endif
|
||||
}
|
||||
if (optimise && GenWriteMemoryFast(op, opid))
|
||||
return;
|
||||
|
||||
@@ -1775,8 +1840,7 @@ private:
|
||||
|
||||
u32 size = op.flags & 0x7f;
|
||||
u32 addr = op.rs1._imm;
|
||||
#ifndef NO_MMU
|
||||
if (mmu_enabled())
|
||||
if (mmu_enabled() && mmu_is_translated<MMU_TT_DWRITE>(addr, size))
|
||||
{
|
||||
if ((addr >> 12) != (block->vaddr >> 12) && ((addr >> 12) != ((block->vaddr + block->guest_opcodes * 2 - 1) >> 12)))
|
||||
// When full mmu is on, only consider addresses in the same 4k page
|
||||
@@ -1803,7 +1867,6 @@ private:
|
||||
return false;
|
||||
addr = paddr;
|
||||
}
|
||||
#endif // NO_MMU
|
||||
bool isram = false;
|
||||
void* ptr = _vmem_write_const(addr, isram, size > 4 ? 4 : size);
|
||||
|
||||
@@ -1845,14 +1908,8 @@ private:
|
||||
break;
|
||||
|
||||
case 8:
|
||||
#ifdef EXPLODE_SPANS
|
||||
verify(op.rs2.count() == 2 && regalloc.IsAllocf(op.rs2, 0) && regalloc.IsAllocf(op.rs2, 1));
|
||||
Str(regalloc.MapVRegister(op.rs2, 0), MemOperand(x1));
|
||||
Str(regalloc.MapVRegister(op.rs2, 1), MemOperand(x1, 4));
|
||||
#else
|
||||
shil_param_to_host_reg(op.rs2, x1);
|
||||
Str(x1, MemOperand(x0));
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1908,6 +1965,7 @@ private:
|
||||
// Direct memory access. Need to handle SIGSEGV and rewrite block as needed. See ngen_Rewrite()
|
||||
if (!_nvmem_enabled() || (mmu_enabled() && !vmem32_enabled()))
|
||||
return false;
|
||||
mem_writes++;
|
||||
|
||||
Instruction *start_instruction = GetCursorAddress<Instruction *>();
|
||||
|
||||
@@ -2105,34 +2163,34 @@ private:
|
||||
|
||||
static Arm64Assembler* compiler;
|
||||
|
||||
void ngen_Compile_arm64(RuntimeBlockInfo* block, bool force_checks, bool reset, bool staging, bool optimise)
|
||||
void ngen_Compile(RuntimeBlockInfo* block, bool smc_checks, bool reset, bool staging, bool optimise)
|
||||
{
|
||||
verify(emit_FreeSpace() >= 16 * 1024);
|
||||
|
||||
compiler = new Arm64Assembler();
|
||||
|
||||
compiler->ngen_Compile(block, force_checks, reset, staging, optimise);
|
||||
compiler->ngen_Compile(block, smc_checks, reset, staging, optimise);
|
||||
|
||||
delete compiler;
|
||||
compiler = NULL;
|
||||
}
|
||||
|
||||
void ngen_CC_Start_arm64(shil_opcode* op)
|
||||
void ngen_CC_Start(shil_opcode* op)
|
||||
{
|
||||
compiler->ngen_CC_Start(op);
|
||||
}
|
||||
|
||||
void ngen_CC_Param_arm64(shil_opcode* op, shil_param* par, CanonicalParamType tp)
|
||||
void ngen_CC_Param(shil_opcode* op, shil_param* par, CanonicalParamType tp)
|
||||
{
|
||||
compiler->ngen_CC_Param(*op, *par, tp);
|
||||
}
|
||||
|
||||
void ngen_CC_Call_arm64(shil_opcode*op, void* function)
|
||||
void ngen_CC_Call(shil_opcode*op, void* function)
|
||||
{
|
||||
compiler->ngen_CC_Call(op, function);
|
||||
}
|
||||
|
||||
void ngen_CC_Finish_arm64(shil_opcode* op)
|
||||
void ngen_CC_Finish(shil_opcode* op)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -2194,9 +2252,15 @@ bool ngen_Rewrite(unat& host_pc, unat, unat)
|
||||
u32 *code_rewrite = code_ptr - 1 - (!_nvmem_4gb_space() ? 1 : 0);
|
||||
Arm64Assembler *assembler = new Arm64Assembler(code_rewrite);
|
||||
if (is_read)
|
||||
{
|
||||
mem_rewrites_r++;
|
||||
assembler->GenReadMemorySlow(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_rewrites_w++;
|
||||
assembler->GenWriteMemorySlow(size);
|
||||
}
|
||||
assembler->Finalize(true);
|
||||
delete assembler;
|
||||
host_pc = (unat)CC_RW2RX(code_rewrite);
|
||||
@@ -2229,6 +2293,7 @@ void ngen_HandleException()
|
||||
|
||||
u32 DynaRBI::Relink()
|
||||
{
|
||||
#ifndef NO_BLOCK_LINKING
|
||||
//printf("DynaRBI::Relink %08x\n", this->addr);
|
||||
Arm64Assembler *compiler = new Arm64Assembler((u8 *)this->code + this->relink_offset);
|
||||
|
||||
@@ -2237,6 +2302,9 @@ u32 DynaRBI::Relink()
|
||||
delete compiler;
|
||||
|
||||
return code_size;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arm64RegAlloc::Preload(u32 reg, eReg nreg)
|
||||
|
||||
Reference in new issue
Block a user