From 84abdd828772765d23d6d8fb68118c6d66b3699b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1roly=20Balogh?= Date: Sat, 3 Sep 2016 07:58:17 +0000 Subject: [PATCH] powerpc: simplified code generation for MorphOS syscalls git-svn-id: trunk@34417 - --- compiler/powerpc/cpupara.pas | 62 ++++++++++++------------------------ compiler/powerpc/nppccal.pas | 48 +++++++++++++++------------- 2 files changed, 45 insertions(+), 65 deletions(-) diff --git a/compiler/powerpc/cpupara.pas b/compiler/powerpc/cpupara.pas index 2a110aca07..c8ee79128a 100644 --- a/compiler/powerpc/cpupara.pas +++ b/compiler/powerpc/cpupara.pas @@ -664,8 +664,10 @@ unit cpupara; var paraloc : pcgparalocation; paracgsize : tcgsize; + offset : aint; begin result:=false; + offset:=-1; case target_info.system of system_powerpc_morphos: begin @@ -674,58 +676,34 @@ unit cpupara; p.paraloc[callerside].size:=paracgsize; p.paraloc[callerside].intsize:=tcgsize2size[paracgsize]; paraloc:=p.paraloc[callerside].add_location; - paraloc^.loc:=LOC_REFERENCE; + { The OS side should be zero extended and the entire "virtual" 68k register should be overwritten. This is what the C ppcinline macros do as well, by casting all arguments to ULONG. A call which breaks w/o this is for example exec/RawPutChar (KB) } paraloc^.size:=OS_ADDR; paraloc^.def:=p.vardef; - paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE); - { pattern is always uppercase'd } - if s='D0' then - paraloc^.reference.offset:=0 - else if s='D1' then - paraloc^.reference.offset:=4 - else if s='D2' then - paraloc^.reference.offset:=8 - else if s='D3' then - paraloc^.reference.offset:=12 - else if s='D4' then - paraloc^.reference.offset:=16 - else if s='D5' then - paraloc^.reference.offset:=20 - else if s='D6' then - paraloc^.reference.offset:=24 - else if s='D7' then - paraloc^.reference.offset:=28 - else if s='A0' then - paraloc^.reference.offset:=32 - else if s='A1' then - paraloc^.reference.offset:=36 - else if s='A2' then - paraloc^.reference.offset:=40 - else if s='A3' then - paraloc^.reference.offset:=44 - else if s='A4' then - paraloc^.reference.offset:=48 - else if s='A5' then - paraloc^.reference.offset:=52 - { 'A6' (offset 56) is used by mossyscall as libbase, so API - never passes parameters in it, - Indeed, but this allows to declare libbase either explicitly - or let the compiler insert it } - else if s='A6' then - paraloc^.reference.offset:=56 - { 'A7' is the stack pointer on 68k, can't be overwritten - by API calls, so it has no offset } - { 'R12' is special, used internally to support r12base sysv + + { convert d0-d7/a0-a6 virtual 68k reg patterns into offsets } + if length(s) = 2 then + begin + if (s[1] = 'D') and (s[2] in ['0'..'7']) then + offset:=(ord(s[2]) - ord('0')) * sizeof(pint) + else if (s[1] = 'A') and (s[2] in ['0'..'6']) then + offset:=(ord(s[2]) - ord('0') + 8) * sizeof(pint); + + if offset < 0 then + exit; + + paraloc^.loc:=LOC_REFERENCE; + paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE); + paraloc^.reference.offset:=offset; + end + { 'R12' is special, used internally to support r12base and sysv calling convention } else if s='R12' then begin paraloc^.loc:=LOC_REGISTER; - paraloc^.size:=OS_ADDR; - paraloc^.def:=voidpointertype; paraloc^.register:=NR_R12; end else diff --git a/compiler/powerpc/nppccal.pas b/compiler/powerpc/nppccal.pas index c33f1d9228..8812815670 100644 --- a/compiler/powerpc/nppccal.pas +++ b/compiler/powerpc/nppccal.pas @@ -75,6 +75,7 @@ implementation procedure tppccallnode.do_syscall; var tmpref: treference; + libparaloc: pcgparalocation; begin case target_info.system of system_powerpc_amiga: @@ -90,21 +91,35 @@ implementation end; system_powerpc_morphos: begin - if (po_syscall_sysv in tprocdef(procdefinition).procoptions) or - (po_syscall_sysvbase in tprocdef(procdefinition).procoptions) then + { all conventions but legacy } + if ([po_syscall_basesysv,po_syscall_sysv, + po_syscall_sysvbase,po_syscall_r12base] * tprocdef(procdefinition).procoptions) <> [] then begin cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0); cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12); - reference_reset(tmpref,sizeof(pint)); - tmpref.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(tcpuprocdef(procdefinition).libsym).mangledname,AT_DATA); - tmpref.refaddr:=addr_higha; - current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LIS,NR_R12,tmpref)); - tmpref.base:=NR_R12; - tmpref.refaddr:=addr_low; - current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R12,tmpref)); + if (po_syscall_sysvbase in tprocdef(procdefinition).procoptions) then + begin + { for sysvbase, find the last para, and get the libbase from there } + libparaloc:=paralocs[procdefinition.paras.count-1]^.location; + if libparaloc^.loc = LOC_REGISTER then + reference_reset_base(tmpref,libparaloc^.register,-tprocdef(procdefinition).extnumber,sizeof(pint)) + else if libparaloc^.loc = LOC_REFERENCE then + begin + reference_reset_base(tmpref,libparaloc^.reference.index,libparaloc^.reference.offset,sizeof(pint)); + cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,NR_R12); + reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint)); + end + else + internalerror(2016090202); + end + else + if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) then + reference_reset_base(tmpref,NR_R3,-tprocdef(procdefinition).extnumber,sizeof(pint)) + else + { other calling conventions expect the base in R12 at this point } + reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint)); - reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref)); current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0)); current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL)); @@ -112,19 +127,6 @@ implementation cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R12); cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0); end - else if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) or - (po_syscall_r12base in tprocdef(procdefinition).procoptions) then - begin - cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0); - if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) then - reference_reset_base(tmpref,NR_R3,-tprocdef(procdefinition).extnumber,sizeof(pint)) - else - reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint)); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref)); - current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0)); - current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL)); - cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0); - end else if po_syscall_legacy in tprocdef(procdefinition).procoptions then begin cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);