diff --git a/core/rec-ARM/E_Branches.h b/core/arm_emitter/E_Branches.h similarity index 100% rename from core/rec-ARM/E_Branches.h rename to core/arm_emitter/E_Branches.h diff --git a/core/rec-ARM/E_DataOp.h b/core/arm_emitter/E_DataOp.h similarity index 99% rename from core/rec-ARM/E_DataOp.h rename to core/arm_emitter/E_DataOp.h index 31dcdb47..046327ae 100644 --- a/core/rec-ARM/E_DataOp.h +++ b/core/arm_emitter/E_DataOp.h @@ -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; } diff --git a/core/rec-ARM/E_Extend.h b/core/arm_emitter/E_Extend.h similarity index 100% rename from core/rec-ARM/E_Extend.h rename to core/arm_emitter/E_Extend.h diff --git a/core/rec-ARM/E_LoadStore.h b/core/arm_emitter/E_LoadStore.h similarity index 99% rename from core/rec-ARM/E_LoadStore.h rename to core/arm_emitter/E_LoadStore.h index 525ad7e8..f01ada76 100644 --- a/core/rec-ARM/E_LoadStore.h +++ b/core/arm_emitter/E_LoadStore.h @@ -309,4 +309,4 @@ EAPI POP(u32 RegList, ConditionCode CC=AL) -}; \ No newline at end of file +}; diff --git a/core/rec-ARM/E_Misc.h b/core/arm_emitter/E_Misc.h similarity index 100% rename from core/rec-ARM/E_Misc.h rename to core/arm_emitter/E_Misc.h diff --git a/core/rec-ARM/E_Multiply.h b/core/arm_emitter/E_Multiply.h similarity index 100% rename from core/rec-ARM/E_Multiply.h rename to core/arm_emitter/E_Multiply.h diff --git a/core/rec-ARM/E_Parallel.h b/core/arm_emitter/E_Parallel.h similarity index 100% rename from core/rec-ARM/E_Parallel.h rename to core/arm_emitter/E_Parallel.h diff --git a/core/rec-ARM/E_Special.h b/core/arm_emitter/E_Special.h similarity index 100% rename from core/rec-ARM/E_Special.h rename to core/arm_emitter/E_Special.h diff --git a/core/rec-ARM/E_Status.h b/core/arm_emitter/E_Status.h similarity index 100% rename from core/rec-ARM/E_Status.h rename to core/arm_emitter/E_Status.h diff --git a/core/rec-ARM/E_VDataOp.h b/core/arm_emitter/E_VDataOp.h similarity index 99% rename from core/rec-ARM/E_VDataOp.h rename to core/arm_emitter/E_VDataOp.h index f33ebc74..81869fff 100644 --- a/core/rec-ARM/E_VDataOp.h +++ b/core/arm_emitter/E_VDataOp.h @@ -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); } diff --git a/core/rec-ARM/E_VLoadStore.h b/core/arm_emitter/E_VLoadStore.h similarity index 100% rename from core/rec-ARM/E_VLoadStore.h rename to core/arm_emitter/E_VLoadStore.h diff --git a/core/rec-ARM/E_VRegXfer.h b/core/arm_emitter/E_VRegXfer.h similarity index 100% rename from core/rec-ARM/E_VRegXfer.h rename to core/arm_emitter/E_VRegXfer.h diff --git a/core/rec-ARM/H_Branches.h b/core/arm_emitter/H_Branches.h similarity index 67% rename from core/rec-ARM/H_Branches.h rename to core/arm_emitter/H_Branches.h index a6d08f43..9a32385f 100644 --- a/core/rec-ARM/H_Branches.h +++ b/core/arm_emitter/H_Branches.h @@ -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); diff --git a/core/rec-ARM/H_LoadStore.h b/core/arm_emitter/H_LoadStore.h similarity index 100% rename from core/rec-ARM/H_LoadStore.h rename to core/arm_emitter/H_LoadStore.h diff --git a/core/rec-ARM/H_fp.h b/core/arm_emitter/H_fp.h similarity index 100% rename from core/rec-ARM/H_fp.h rename to core/arm_emitter/H_fp.h diff --git a/core/rec-ARM/H_psuedo.h b/core/arm_emitter/H_psuedo.h similarity index 100% rename from core/rec-ARM/H_psuedo.h rename to core/arm_emitter/H_psuedo.h diff --git a/core/rec-ARM/H_state.h b/core/arm_emitter/H_state.h similarity index 100% rename from core/rec-ARM/H_state.h rename to core/arm_emitter/H_state.h diff --git a/core/rec-ARM/arm_coding.h b/core/arm_emitter/arm_coding.h similarity index 100% rename from core/rec-ARM/arm_coding.h rename to core/arm_emitter/arm_coding.h diff --git a/core/rec-ARM/arm_disasm.h b/core/arm_emitter/arm_disasm.h similarity index 100% rename from core/rec-ARM/arm_disasm.h rename to core/arm_emitter/arm_disasm.h diff --git a/core/rec-ARM/arm_emitter.h b/core/arm_emitter/arm_emitter.h similarity index 100% rename from core/rec-ARM/arm_emitter.h rename to core/arm_emitter/arm_emitter.h diff --git a/core/rec-ARM/arm_registers.h b/core/arm_emitter/arm_registers.h similarity index 100% rename from core/rec-ARM/arm_registers.h rename to core/arm_emitter/arm_registers.h diff --git a/core/hw/arm7/arm64.cpp b/core/hw/arm7/arm64.cpp index 39d4e9e8..fbcdc63b 100644 --- a/core/hw/arm7/arm64.cpp +++ b/core/hw/arm7/arm64.cpp @@ -23,7 +23,7 @@ //#include #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" diff --git a/core/hw/arm7/arm7.cpp b/core/hw/arm7/arm7.cpp index cca150df..27d7a67a 100644 --- a/core/hw/arm7/arm7.cpp +++ b/core/hw/arm7/arm7.cpp @@ -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 diff --git a/core/rec-ARM/ngen_arm.S b/core/rec-ARM/ngen_arm.S index c0885e76..85f5a7a4 100644 --- a/core/rec-ARM/ngen_arm.S +++ b/core/rec-ARM/ngen_arm.S @@ -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): diff --git a/core/rec-ARM/rec_arm.cpp b/core/rec-ARM/rec_arm.cpp index 252da31b..032e84ef 100644 --- a/core/rec-ARM/rec_arm.cpp +++ b/core/rec-ARM/rec_arm.cpp @@ -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 // for cache flushing. #endif -#ifdef __MACH__ +#if defined(__APPLE__) #include 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 +struct arm_reg_alloc: RegAlloc { virtual void Preload(u32 reg,eReg nreg) { @@ -240,7 +244,7 @@ struct arm_reg_alloc: RegAlloc 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 { 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 ccmap; -map ccnmap; +std::map ccmap; +std::map 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_pars; - -void ngen_CC_Start_arm(shil_opcode* op) +std::vector 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 // 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 diff --git a/core/rec-ARM64/arm64_regalloc.h b/core/rec-ARM64/arm64_regalloc.h index 92404a34..cbdf470b 100644 --- a/core/rec-ARM64/arm64_regalloc.h +++ b/core/rec-ARM64/arm64_regalloc.h @@ -42,11 +42,7 @@ static eFReg alloc_fregs[] = { S8, S9, S10, S11, S12, S13, S14, S15, (eFReg)-1 } class Arm64Assembler; -struct Arm64RegAlloc : RegAlloc +struct Arm64RegAlloc : RegAlloc { Arm64RegAlloc(Arm64Assembler *assembler) : assembler(assembler) {} @@ -73,9 +69,6 @@ struct Arm64RegAlloc : RegAlloc + +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 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()); + mainloop = (void (*)(void *))CC_RW2RX(GetCursorAddress()); // 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(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(); @@ -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(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(); @@ -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)