Parcourir la source

+ PIC support for darwin/ppc64
* added {$PIC+} for darwin to all library tests

git-svn-id: trunk@8868 -

Jonas Maebe il y a 18 ans
Parent
commit
45b7358d81

+ 0 - 71
compiler/powerpc/cgcpu.pas

@@ -100,14 +100,6 @@ unit cgcpu;
         { the upper 24/16 bits of a register after an operation          }
         procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
 
-        { Make sure ref is a valid reference for the PowerPC and sets the }
-        { base to the value of the index if (base = R_NO).                }
-        { Returns true if the reference contained a base, index and an    }
-        { offset or symbol, in which case the base will have been changed }
-        { to a tempreg (which has to be freed by the caller) containing   }
-        { the sum of part of the original reference                       }
-        function fixref(list: TAsmList; var ref: treference): boolean; override;
-
         { returns whether a reference can be used immediately in a powerpc }
         { instruction                                                      }
         function issimpleref(const ref: treference): boolean;
@@ -1656,69 +1648,6 @@ const
       end;
 
 
-    function tcgppc.fixref(list: TAsmList; var ref: treference): boolean;
-
-       var
-         tmpreg: tregister;
-       begin
-         result := false;
-
-         if (target_info.system = system_powerpc_darwin) and
-            assigned(ref.symbol) and
-            not assigned(ref.relsymbol) and
-            ((ref.symbol.bind = AB_EXTERNAL) or
-             (cs_create_pic in current_settings.moduleswitches))then
-           begin
-             if (ref.symbol.bind = AB_EXTERNAL) or
-                ((cs_create_pic in current_settings.moduleswitches) and
-                 (ref.symbol.bind in [AB_COMMON,AB_GLOBAL])) then
-               begin
-                 tmpreg := g_indirect_sym_load(list,ref.symbol.name);
-                 ref.symbol:=nil;
-               end
-             else
-               begin
-                 include(current_procinfo.flags,pi_needs_got);
-                 tmpreg := current_procinfo.got;
-                 if assigned(ref.relsymbol) then
-                   internalerror(2007093501);
-                 ref.relsymbol := current_procinfo.CurrGOTLabel;
-               end;
-             if (ref.base = NR_NO) then
-               ref.base := tmpreg
-             else if (ref.index = NR_NO) then
-               ref.index := tmpreg
-             else
-               begin
-                 list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
-                 ref.base := tmpreg;
-               end;
-           end;
-
-         if (ref.base = NR_NO) then
-           begin
-             ref.base := ref.index;
-             ref.index := NR_NO;
-           end;
-         if (ref.base <> NR_NO) then
-           begin
-             if (ref.index <> NR_NO) and
-                ((ref.offset <> 0) or assigned(ref.symbol)) then
-               begin
-                 result := true;
-                 tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
-                 list.concat(taicpu.op_reg_reg_reg(
-                   A_ADD,tmpreg,ref.base,ref.index));
-                 ref.index := NR_NO;
-                 ref.base := tmpreg;
-               end
-           end
-         else
-           if ref.index <> NR_NO then
-             internalerror(200208102);
-       end;
-
-
     { find out whether a is of the form 11..00..11b or 00..11...00. If }
     { that's the case, we can use rlwinm to do an AND operation        }
     function tcgppc.get_rlwi_const(a: aint; var l1, l2: longint): boolean;

+ 6 - 102
compiler/powerpc64/cgcpu.pas

@@ -107,16 +107,6 @@ type
 
     procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
 
-    { Make sure ref is a valid reference for the PowerPC and sets the }
-    { base to the value of the index if (base = R_NO).                }
-    { Returns true if the reference contained a base, index and an    }
-    { offset or symbol, in which case the base will have been changed }
-    { to a tempreg (which has to be freed by the caller) containing   }
-    { the sum of part of the original reference                       }
-    function fixref(list: TAsmList; var ref: treference): boolean; override;
-
-    function load_got_symbol(list : TAsmList; symbol : string) : tregister;
-
     { returns whether a reference can be used immediately in a powerpc }
     { instruction                                                      }
     function issimpleref(const ref: treference): boolean;
@@ -1397,7 +1387,8 @@ var
     { there are two ways to do this: manually, by generating a few "std" instructions,
      or via the restore helper functions. The latter are selected by the -Og switch,
      i.e. "optimize for size" }
-    if (cs_opt_size in current_settings.optimizerswitches) then begin
+    if (cs_opt_size in current_settings.optimizerswitches) and
+       (target_info.system <> system_powerpc64_darwin) then begin
       mayNeedLRStore := false;
       if ((fprcount > 0) and (gprcount > 0)) then begin
         a_op_const_reg_reg(list, OP_SUB, OS_INT, 8 * fprcount, NR_R1, NR_R12);
@@ -1450,10 +1441,10 @@ begin
   { determine whether we need to save the link register }
   needslinkreg :=
     not(nostackframe) and
-    (((not (po_assembler in current_procinfo.procdef.procoptions)) and
-       ((pi_do_call in current_procinfo.flags) or (cs_profile in init_settings.moduleswitches))) or
-     ((cs_opt_size in current_settings.optimizerswitches) and ((fprcount > 0) or (gprcount > 0))) or
-     ([cs_lineinfo, cs_debuginfo] * current_settings.moduleswitches <> []));
+    (save_lr_in_prologue or
+     ((cs_opt_size in current_settings.optimizerswitches) and
+      ((fprcount > 0) or
+       (gprcount > 0))));
 
   a_reg_alloc(list, NR_STACK_POINTER_REG);
   a_reg_alloc(list, NR_R0);
@@ -1944,93 +1935,6 @@ begin
     (ref.offset = 0)));
 end;
 
-function tcgppc.load_got_symbol(list: TAsmList; symbol : string) : tregister;
-var
-  l: tasmsymbol;
-  ref: treference;
-  symname : string;
-begin
-  l:=current_asmdata.getasmsymbol(symbol);
-  reference_reset_symbol(ref,l,0);
-  ref.base := NR_R2;
-  ref.refaddr := addr_pic;
-
-  result := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
-  {$IFDEF EXTDEBUG}
-  list.concat(tai_comment.create(strpnew('loading got reference for ' + symbol)));
-  {$ENDIF EXTDEBUG}
-//  cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
-  list.concat(taicpu.op_reg_ref(A_LD, result, ref));
-end;
-
-
-function tcgppc.fixref(list: TAsmList; var ref: treference): boolean;
-var
-  tmpreg: tregister;
-  name : string;
-begin
-  result := false;
-  { Avoids recursion. }
-  if (ref.refaddr = addr_pic) then exit;
-  {$IFDEF EXTDEBUG}
-  list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref))));
-  {$ENDIF EXTDEBUG}
-
-  if (target_info.system = system_powerpc64_darwin) and
-     assigned(ref.symbol) and
-     (ref.symbol.bind = AB_EXTERNAL) then
-    begin
-      tmpreg := g_indirect_sym_load(list,ref.symbol.name);
-      if (ref.base = NR_NO) then
-        ref.base := tmpreg
-      else if (ref.index = NR_NO) then
-        ref.index := tmpreg
-      else
-        begin
-          list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
-          ref.base := tmpreg;
-        end;
-      ref.symbol := nil;
-    end;
-
-  { if we have to create PIC, add the symbol to the TOC/GOT }
-  if (target_info.system <> system_powerpc64_darwin) and
-     (cs_create_pic in current_settings.moduleswitches) and 
-     (assigned(ref.symbol)) then begin
-    tmpreg := load_got_symbol(list, ref.symbol.name);
-    if (ref.base = NR_NO) then
-      ref.base := tmpreg
-    else if (ref.index = NR_NO) then
-      ref.index := tmpreg
-    else begin
-      a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, tmpreg, tmpreg);
-      ref.base := tmpreg;
-    end;
-    ref.symbol := nil;
-    {$IFDEF EXTDEBUG}
-    list.concat(tai_comment.create(strpnew('fixref-pic ' + ref2string(ref))));
-    {$ENDIF EXTDEBUG}
-  end;
-
-  if (ref.base = NR_NO) then begin
-    ref.base := ref.index;
-    ref.index := NR_NO;
-  end;
-  if (ref.base <> NR_NO) and (ref.index <> NR_NO) and
-    ((ref.offset <> 0) or assigned(ref.symbol)) then begin
-      result := true;
-      tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
-      a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, ref.index, tmpreg);
-      ref.base := tmpreg;
-      ref.index := NR_NO;
-  end;
-  if (ref.index <> NR_NO) and (assigned(ref.symbol) or (ref.offset <> 0)) then
-    internalerror(2006010506);
-  {$IFDEF EXTDEBUG}
-  list.concat(tai_comment.create(strpnew('fixref1 ' + ref2string(ref))));
-  {$ENDIF EXTDEBUG}
-end;
-
 procedure tcgppc.a_load_store(list: TAsmList; op: tasmop; reg: tregister;
   ref: treference);
 

+ 15 - 3
compiler/powerpc64/cpupi.pas

@@ -28,7 +28,7 @@ unit cpupi;
 interface
 
 uses
-  cutils,
+  cutils,aasmdata,
   procinfo, cpuinfo, psub;
 
 type
@@ -43,6 +43,8 @@ type
     function calc_stackframe_size(numgpr, numfpr : longint): longint;
 
     needs_frame_pointer : boolean;
+
+    procedure allocate_got_register(list: TAsmList); override;
   end;
 
 implementation
@@ -50,8 +52,8 @@ implementation
 uses
   globtype, globals, systems,
   cpubase, cgbase,
-  aasmtai,aasmdata,
-  tgobj,
+  aasmtai,
+  tgobj,cgobj,
   symconst, symsym, paramgr, symutil, symtable,
   verbose;
 
@@ -111,6 +113,16 @@ begin
   end;
 end;
 
+
+procedure tppcprocinfo.allocate_got_register(list: TAsmList);
+  begin
+    if (target_info.system = system_powerpc64_darwin) and
+       (cs_create_pic in current_settings.moduleswitches) then
+      begin
+        got := cg.getaddressregister(list);
+      end;
+  end;
+
 begin
   cprocinfo := tppcprocinfo;
 end.

+ 46 - 14
compiler/powerpc64/rappcgas.pas

@@ -151,6 +151,8 @@ procedure tppcattreader.BuildReference(oper: tppcoperand);
 
 var
   l: aint;
+  relsym: string;
+  asmsymtyp: tasmsymtype;
 
 begin
   Consume(AS_LPAREN);
@@ -207,20 +209,50 @@ begin
     AS_ID:
       begin
         ReadSym(oper);
-        { add a constant expression? }
-        if (actasmtoken = AS_PLUS) then
-        begin
-          l := BuildConstExpression(true, true);
-          case oper.opr.typ of
-            OPR_CONSTANT:
-              inc(oper.opr.val, l);
-            OPR_LOCAL:
-              inc(oper.opr.localsymofs, l);
-            OPR_REFERENCE:
-              inc(oper.opr.ref.offset, l);
-          else
-            internalerror(200309202);
-          end;
+        case actasmtoken of
+          AS_PLUS:
+            begin
+              { add a constant expression? }
+              l:=BuildConstExpression(true,true);
+              case oper.opr.typ of
+                OPR_CONSTANT :
+                  inc(oper.opr.val,l);
+                OPR_LOCAL :
+                  inc(oper.opr.localsymofs,l);
+                OPR_REFERENCE :
+                  inc(oper.opr.ref.offset,l);
+                else
+                  internalerror(200309202);
+              end;
+            end;
+          AS_MINUS:
+            begin
+              Consume(AS_MINUS);
+              BuildConstSymbolExpression(false,true,false,l,relsym,asmsymtyp);
+              if (relsym<>'') then
+                begin
+                  if (oper.opr.typ = OPR_REFERENCE) then
+                    oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym)
+                  else
+                    begin
+                      Message(asmr_e_invalid_reference_syntax);
+                      RecoverConsume(false);
+                    end
+                end
+              else
+                begin
+                  case oper.opr.typ of
+                    OPR_CONSTANT :
+                      dec(oper.opr.val,l);
+                    OPR_LOCAL :
+                      dec(oper.opr.localsymofs,l);
+                    OPR_REFERENCE :
+                      dec(oper.opr.ref.offset,l);
+                    else
+                      internalerror(2007092601);
+                  end;
+                end;
+            end;
         end;
         Consume(AS_RPAREN);
         if actasmtoken = AS_AT then

+ 135 - 5
compiler/ppcgen/cgppc.pas

@@ -66,7 +66,13 @@ unit cgppc;
        protected
         function  get_darwin_call_stub(const s: string): tasmsymbol;
         procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
-        function  fixref(list: TAsmList; var ref: treference): boolean; virtual; abstract;
+        { Make sure ref is a valid reference for the PowerPC and sets the }
+        { base to the value of the index if (base = R_NO).                }
+        { Returns true if the reference contained a base, index and an    }
+        { offset or symbol, in which case the base will have been changed }
+        { to a tempreg (which has to be freed by the caller) containing   }
+        { the sum of part of the original reference                       }
+        function  fixref(list: TAsmList; var ref: treference): boolean;
         { contains the common code of a_load_reg_ref and a_load_ref_reg }
         procedure a_load_store(list:TAsmList;op: tasmop;reg:tregister;ref: treference);virtual;
 
@@ -81,6 +87,8 @@ unit cgppc;
         function hasLargeOffset(const ref : TReference) : Boolean; inline;
 
         function save_lr_in_prologue: boolean;
+
+        function load_got_symbol(list : TAsmList; symbol : string) : tregister;
      end;
 
   const
@@ -105,8 +113,10 @@ unit cgppc;
     function tcgppcgen.save_lr_in_prologue: boolean;
       begin
         result:=
-          ((pi_do_call in current_procinfo.flags) or
-           ([cs_lineinfo,cs_debuginfo,cs_profile] * current_settings.moduleswitches <> []));
+        (not (po_assembler in current_procinfo.procdef.procoptions) and
+         ((pi_do_call in current_procinfo.flags) or 
+          (cs_profile in init_settings.moduleswitches)))  or
+        ([cs_lineinfo,cs_debuginfo] * current_settings.moduleswitches <> []);
       end;
 
 
@@ -168,7 +178,8 @@ unit cgppc;
             if (cs_create_pic in current_settings.moduleswitches) and
                (pi_needs_got in current_procinfo.flags) then
               case target_info.system of
-                system_powerpc_darwin:
+                system_powerpc_darwin,
+                system_powerpc64_darwin:
                   begin
                     savedlr:=save_lr_in_prologue;
                     if not savedlr then
@@ -185,7 +196,7 @@ unit cgppc;
                     list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR));
                     if not savedlr or
                        { in the following case lr is saved, but not restored }
-                       { (happens e.g. when generating debug info  for leaf  }
+                       { (happens e.g. when generating debug info for leaf   }
                        { procedures)                                         }
                        not(pi_do_call in current_procinfo.flags) then
                       list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0));
@@ -687,6 +698,125 @@ unit cgppc;
       end;
 
 
+    function tcgppcgen.load_got_symbol(list: TAsmList; symbol : string) : tregister;
+    var
+      l: tasmsymbol;
+      ref: treference;
+    begin
+      if (target_info.system <> system_powerpc64_linux) then
+        internalerror(2007102010);
+      l:=current_asmdata.getasmsymbol(symbol);
+      reference_reset_symbol(ref,l,0);
+      ref.base := NR_R2;
+      ref.refaddr := addr_pic;
+    
+      result := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+      {$IFDEF EXTDEBUG}
+      list.concat(tai_comment.create(strpnew('loading got reference for ' + symbol)));
+      {$ENDIF EXTDEBUG}
+    //  cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
+      
+{$ifdef cpu64bit}
+      list.concat(taicpu.op_reg_ref(A_LD, result, ref));
+{$else cpu64bit}
+      list.concat(taicpu.op_reg_ref(A_LWZ, result, ref));
+{$endif cpu64bit}
+    end;
+    
+    
+    function tcgppcgen.fixref(list: TAsmList; var ref: treference): boolean;
+      var
+        tmpreg: tregister;
+      begin
+        result := false;
+
+        { Avoid recursion. }
+        if (ref.refaddr = addr_pic) then
+          exit;
+
+        {$IFDEF EXTDEBUG}
+        list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref))));
+        {$ENDIF EXTDEBUG}
+        if (target_info.system in [system_powerpc_darwin,system_powerpc64_darwin]) and
+           assigned(ref.symbol) and
+           not assigned(ref.relsymbol) and
+           ((ref.symbol.bind = AB_EXTERNAL) or
+            (cs_create_pic in current_settings.moduleswitches))then
+          begin
+            if (ref.symbol.bind = AB_EXTERNAL) or
+               ((cs_create_pic in current_settings.moduleswitches) and
+                (ref.symbol.bind in [AB_COMMON,AB_GLOBAL])) then
+              begin
+                tmpreg := g_indirect_sym_load(list,ref.symbol.name);
+                ref.symbol:=nil;
+              end
+            else
+              begin
+                include(current_procinfo.flags,pi_needs_got);
+                tmpreg := current_procinfo.got;
+                if assigned(ref.relsymbol) then
+                  internalerror(2007093501);
+                ref.relsymbol := current_procinfo.CurrGOTLabel;
+              end;
+            if (ref.base = NR_NO) then
+              ref.base := tmpreg
+            else if (ref.index = NR_NO) then
+              ref.index := tmpreg
+            else
+              begin
+                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+                ref.base := tmpreg;
+              end;
+          end;
+
+        { if we have to create PIC, add the symbol to the TOC/GOT }
+        if (target_info.system = system_powerpc64_linux) and
+           (cs_create_pic in current_settings.moduleswitches) and 
+           (assigned(ref.symbol)) then
+          begin
+            tmpreg := load_got_symbol(list, ref.symbol.name);
+            if (ref.base = NR_NO) then
+              ref.base := tmpreg
+            else if (ref.index = NR_NO) then
+              ref.index := tmpreg
+            else begin
+              a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, tmpreg, tmpreg);
+              ref.base := tmpreg;
+            end;
+            ref.symbol := nil;
+            {$IFDEF EXTDEBUG}
+            list.concat(tai_comment.create(strpnew('fixref-pic ' + ref2string(ref))));
+            {$ENDIF EXTDEBUG}
+          end;
+
+        if (ref.base = NR_NO) then
+          begin
+            ref.base := ref.index;
+            ref.index := NR_NO;
+          end;
+        if (ref.base <> NR_NO) then
+          begin
+            if (ref.index <> NR_NO) and
+               ((ref.offset <> 0) or assigned(ref.symbol)) then
+              begin
+                result := true;
+                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+                list.concat(taicpu.op_reg_reg_reg(
+                  A_ADD,tmpreg,ref.base,ref.index));
+                ref.index := NR_NO;
+                ref.base := tmpreg;
+              end
+          end;
+        if (ref.index <> NR_NO) and
+           (assigned(ref.symbol) or
+            (ref.offset <> 0)) then
+          internalerror(200208102);
+        {$IFDEF EXTDEBUG}
+        list.concat(tai_comment.create(strpnew('fixref1 ' + ref2string(ref))));
+        {$ENDIF EXTDEBUG}
+       end;
+
+
     procedure tcgppcgen.a_load_store(list:TAsmList;op: tasmop;reg:tregister;
        ref: treference);
 

+ 14 - 4
rtl/powerpc64/math.inc

@@ -99,11 +99,21 @@ asm
   ori   r4, r4, longint_to_real_helper@highera
   sldi  r4, r4, 32
   oris  r4, r4, longint_to_real_helper@ha
-{$else darwin}
+  lfd   f4, longint_to_real_helper@l(r4)
+{$else not darwin}
+{$ifdef FPC_PIC}
+   mflr   r0
+   bcl    20,31,.Lpiclab
+.Lpiclab:
+   mflr   r5
+   mtlr   r0
+   addis  r4,r5,(longint_to_real_helper-.Lpiclab)@ha
+   lfd    f2,(longint_to_real_helper-.Lpiclab)@l(r4)
+{$else FPC_PIC}
   lis   r4, longint_to_real_helper@ha
-{$endif darwin}
   lfd   f4, longint_to_real_helper@l(r4)
-
+{$endif FPC_PIC}
+{$endif not darwin}
   rldicl r4,r3,32,32  // isolate high half
   rldicl r0,r3,0,32   // isolate low half
   std r4,temp1        // store dword both
@@ -114,4 +124,4 @@ asm
   fcfid f0,f0         // fpu int (no rnd)
   fmadd f0,f4,f2,f0   // (2**32)*high+low (only add can rnd)
 end;
- 
+

+ 5 - 1
tests/test/tlibrary1.pp

@@ -1,6 +1,10 @@
 { %NORUN }
 { %SKIPTARGET=macos }
 
+{$ifdef darwin}
+{$PIC+}
+{$endif darwin}
+
 {$ifdef CPUX86_64}
 {$ifndef WINDOWS}
 {$PIC+}
@@ -32,7 +36,7 @@ const
 procedure Test;export;
 
  begin
-//   writeln('Hoi');
+   writeln('Hoi');
  end;
 
 exports

+ 4 - 0
tests/test/tlibrary3.pp

@@ -1,6 +1,10 @@
 { %NORUN }
 { %SKIPTARGET=macos, win64 }
 
+{$ifdef darwin}
+{$PIC+}
+{$endif darwin}
+
 {$ifdef CPUX86_64}
 {$ifndef WINDOWS}
 {$PIC+}

+ 5 - 0
tests/webtbs/tw3082.pp

@@ -2,6 +2,11 @@
 { %cpu=x86_64,i386,powerpc,sparc}
 { %skiptarget = go32v2,macos }
 { execute this test only on reasonable fast cpus }
+
+{$ifdef darwin}
+{$PIC+}
+{$endif darwin}
+
 library lib;
 const
   s =

+ 4 - 0
tests/webtbs/tw3573.pp

@@ -4,6 +4,10 @@
 
 {$ifdef fpc}{$mode delphi}{$endif}
 
+{$ifdef darwin}
+{$PIC+}
+{$endif darwin}
+
 resourcestring
   wurst = 'jo' deprecated;