Browse Source

powerpc: simplified code generation for MorphOS syscalls

git-svn-id: trunk@34417 -
Károly Balogh 9 years ago
parent
commit
84abdd8287
2 changed files with 45 additions and 65 deletions
  1. 20 42
      compiler/powerpc/cpupara.pas
  2. 25 23
      compiler/powerpc/nppccal.pas

+ 20 - 42
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

+ 25 - 23
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);