mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 17:48:46 +02:00
powerpc: simplified code generation for MorphOS syscalls
git-svn-id: trunk@34417 -
This commit is contained in:
parent
464ecab542
commit
84abdd8287
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user