Pārlūkot izejas kodu

powerpc: reworked syscall generation once more. instead of making various assumptions on the syscallib location based on the calling convention, simply search for the lib and use its location. also unified the call generation itself

git-svn-id: trunk@34435 -
Károly Balogh 9 gadi atpakaļ
vecāks
revīzija
7a6f18c496
1 mainītis faili ar 36 papildinājumiem un 43 dzēšanām
  1. 36 43
      compiler/powerpc/nppccal.pas

+ 36 - 43
compiler/powerpc/nppccal.pas

@@ -43,7 +43,7 @@ implementation
     uses
       globtype,systems,
       cutils,verbose,globals,
-      symconst,symbase,symsym,symcpu,symtable,defutil,paramgr,parabase,
+      symconst,symtype,symbase,symsym,symcpu,symtable,defutil,paramgr,parabase,
       cgbase,pass_2,
       cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
       nmem,nld,ncnv,
@@ -71,23 +71,28 @@ implementation
           end;
       end;
 
-
     procedure tppccallnode.do_syscall;
+
+      procedure do_call_ref(constref ref: treference);
+        begin
+          cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+          cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,ref,NR_R0);
+          cg.a_call_reg(current_asmdata.CurrAsmList,NR_R0);
+          cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
+        end;
+
       var
         tmpref: treference;
         libparaloc: pcgparalocation;
+        hsym: tsym;
       begin
         case target_info.system of
           system_powerpc_amiga:
             begin
-              // one syscall convention for Amiga/PowerPC
-              // which is very similar to basesysv on MorphOS
-              cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+              { one syscall convention for AmigaOS/PowerPC
+                which is very similar to basesysv on MorphOS }
               reference_reset_base(tmpref,NR_R3,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);
+              do_call_ref(tmpref);
             end;
           system_powerpc_morphos:
             begin
@@ -95,54 +100,42 @@ implementation
               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);
 
-                  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))
+                  hsym:=tsym(procdefinition.parast.Find('syscalllib'));
+                  if not assigned(hsym) then
+                    internalerror(2016090501);
+                  libparaloc:=tparavarsym(hsym).paraloc[callerside].location;
+                  if not assigned(libparaloc) then
+                    internalerror(2016090502);
+
+                  case libparaloc^.loc of
+                    LOC_REGISTER:
+                      reference_reset_base(tmpref,libparaloc^.register,-tprocdef(procdefinition).extnumber,sizeof(pint));
+                    LOC_REFERENCE:
+                      begin
+                        { this can happen for sysvbase; if we run out of regs, the libbase will be passed on the stack }
+                        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
-                      { other calling conventions expect the base in R12 at this point }
-                      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));
+                      internalerror(2016090202);
+                  end;
 
+                  do_call_ref(tmpref);
                   cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R12);
-                  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);
                   cg.getcpuregister(current_asmdata.CurrAsmList,NR_R3);
 
-                  { store call offset into R3 }
+                  { R3 must contain the call offset }
                   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI,NR_R3,-tprocdef(procdefinition).extnumber));
-
-                  { prepare LR, and call function }
                   reference_reset_base(tmpref,NR_R2,100,4); { 100 ($64) is EmulDirectCallOS offset }
-                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
-                  current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTLR,NR_R0));
-                  current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BLRL));
 
+                  do_call_ref(tmpref);
                   cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R3);
-                  cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
                 end
               else
                 internalerror(2005010403);