Browse Source

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 năm trước cách đây
mục cha
commit
7a6f18c496
1 tập tin đã thay đổi với 36 bổ sung43 xóa
  1. 36 43
      compiler/powerpc/nppccal.pas

+ 36 - 43
compiler/powerpc/nppccal.pas

@@ -43,7 +43,7 @@ implementation
     uses
     uses
       globtype,systems,
       globtype,systems,
       cutils,verbose,globals,
       cutils,verbose,globals,
-      symconst,symbase,symsym,symcpu,symtable,defutil,paramgr,parabase,
+      symconst,symtype,symbase,symsym,symcpu,symtable,defutil,paramgr,parabase,
       cgbase,pass_2,
       cgbase,pass_2,
       cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
       cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
       nmem,nld,ncnv,
       nmem,nld,ncnv,
@@ -71,23 +71,28 @@ implementation
           end;
           end;
       end;
       end;
 
 
-
     procedure tppccallnode.do_syscall;
     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
       var
         tmpref: treference;
         tmpref: treference;
         libparaloc: pcgparalocation;
         libparaloc: pcgparalocation;
+        hsym: tsym;
       begin
       begin
         case target_info.system of
         case target_info.system of
           system_powerpc_amiga:
           system_powerpc_amiga:
             begin
             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));
               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;
             end;
           system_powerpc_morphos:
           system_powerpc_morphos:
             begin
             begin
@@ -95,54 +100,42 @@ implementation
               if ([po_syscall_basesysv,po_syscall_sysv,
               if ([po_syscall_basesysv,po_syscall_sysv,
                    po_syscall_sysvbase,po_syscall_r12base] * tprocdef(procdefinition).procoptions) <> [] then
                    po_syscall_sysvbase,po_syscall_r12base] * tprocdef(procdefinition).procoptions) <> [] then
                 begin
                 begin
-                  cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
                   cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12);
                   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
                     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_R12);
-                  cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
                 end
                 end
               else if po_syscall_legacy in tprocdef(procdefinition).procoptions then
               else if po_syscall_legacy in tprocdef(procdefinition).procoptions then
                 begin
                 begin
-                  cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
                   cg.getcpuregister(current_asmdata.CurrAsmList,NR_R3);
                   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));
                   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 }
                   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_R3);
-                  cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
                 end
                 end
               else
               else
                 internalerror(2005010403);
                 internalerror(2005010403);