浏览代码

+ darwin/ppc64 support to ppc64's fixref
* moved ppc32 a_load_store to cgppc and use it for darwin/ppc64 as
well (its relocatable symbols are only 32 bits large)

git-svn-id: branches/fpc_2_3@6397 -

Jonas Maebe 18 年之前
父节点
当前提交
87846054a2
共有 3 个文件被更改,包括 121 次插入100 次删除
  1. 0 98
      compiler/powerpc/cgcpu.pas
  2. 27 1
      compiler/powerpc64/cgcpu.pas
  3. 94 1
      compiler/ppcgen/cgppc.pas

+ 0 - 98
compiler/powerpc/cgcpu.pas

@@ -114,10 +114,6 @@ unit cgcpu;
         { instruction                                                      }
         function issimpleref(const 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); override;
-
         function save_regs(list : TAsmList):longint;
         procedure restore_regs(list : TAsmList);
      end;
@@ -1908,100 +1904,6 @@ const
       end;
 
 
-    procedure tcgppc.a_load_store(list:TAsmList;op: tasmop;reg:tregister;
-       ref: treference);
-
-      var
-        tmpreg: tregister;
-        tmpref: treference;
-        largeOffset: Boolean;
-
-      begin
-        tmpreg := NR_NO;
-
-        if target_info.system = system_powerpc_macos then
-          begin
-            largeOffset:= (cardinal(ref.offset-low(smallint)) >
-                  high(smallint)-low(smallint));
-
-            if assigned(ref.symbol) then
-              begin {Load symbol's value}
-                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
-
-                reference_reset(tmpref);
-                tmpref.symbol := ref.symbol;
-                tmpref.base := NR_RTOC;
-
-                if macos_direct_globals then
-                  list.concat(taicpu.op_reg_ref(A_LA,tmpreg,tmpref))
-                else
-                  list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
-              end;
-
-            if largeOffset then
-              begin {Add hi part of offset}
-                reference_reset(tmpref);
-
-                if Smallint(Lo(ref.offset)) < 0 then
-                  tmpref.offset := Hi(ref.offset) + 1 {Compensate when lo part is negative}
-                else
-                  tmpref.offset := Hi(ref.offset);
-
-                if (tmpreg <> NR_NO) then
-                  list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg, tmpreg,tmpref))
-                else
-                  begin
-                    tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
-                    list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
-                  end;
-              end;
-
-            if (tmpreg <> NR_NO) then
-              begin
-                {Add content of base register}
-                if ref.base <> NR_NO then
-                  list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,
-                    ref.base,tmpreg));
-
-                {Make ref ready to be used by op}
-                ref.symbol:= nil;
-                ref.base:= tmpreg;
-                if largeOffset then
-                  ref.offset := Smallint(Lo(ref.offset));
-
-                list.concat(taicpu.op_reg_ref(op,reg,ref));
-                //list.concat(tai_comment.create(strpnew('*** a_load_store indirect global')));
-              end
-            else
-              list.concat(taicpu.op_reg_ref(op,reg,ref));
-          end
-        else {if target_info.system <> system_powerpc_macos}
-          begin
-            if assigned(ref.symbol) or
-               (cardinal(ref.offset-low(smallint)) >
-                high(smallint)-low(smallint)) then
-              begin
-                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
-                reference_reset(tmpref);
-                tmpref.symbol := ref.symbol;
-                tmpref.relsymbol := ref.relsymbol;
-                tmpref.offset := ref.offset;
-                tmpref.refaddr := addr_hi;
-                if ref.base <> NR_NO then
-                  list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
-                    ref.base,tmpref))
-                else
-                  list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
-                ref.base := tmpreg;
-                ref.refaddr := addr_lo;
-                list.concat(taicpu.op_reg_ref(op,reg,ref));
-              end
-            else
-              list.concat(taicpu.op_reg_ref(op,reg,ref));
-          end;
-      end;
-
-
     procedure tcg64fppc.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
       begin
         a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);

+ 27 - 1
compiler/powerpc64/cgcpu.pas

@@ -1917,9 +1917,28 @@ begin
   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 }
   {$WARNING Hack for avoiding too long manglednames enabled!!}
-  if (cs_create_pic in current_settings.moduleswitches) and (assigned(ref.symbol) and
+  if (target_info.system <> system_powerpc64_darwin) and
+     (cs_create_pic in current_settings.moduleswitches) and (assigned(ref.symbol) and
     (length(ref.symbol.name) < MAX_GOT_SYMBOL_NAME_LENGTH_HACK)) then begin
     tmpreg := load_got_symbol(list, ref.symbol.name);
     if (ref.base = NR_NO) then
@@ -1962,6 +1981,13 @@ var
   tmpref: treference;
   largeOffset: Boolean;
 begin
+  if (target_info.system = system_powerpc64_darwin) then
+    begin
+      { darwin/ppc64 works with 32 bit relocatable symbol addresses }
+      inherited a_load_store(list,op,reg,ref);
+      exit
+    end;
+
   { at this point there must not be a combination of values in the ref treference
     which is not possible to directly map to instructions of the PowerPC architecture }
   if (ref.index <> NR_NO) and ((ref.offset <> 0) or (assigned(ref.symbol))) then

+ 94 - 1
compiler/ppcgen/cgppc.pas

@@ -63,7 +63,8 @@ unit cgppc;
         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;
-        procedure a_load_store(list:TAsmList;op: tasmop;reg:tregister;ref: treference);virtual;abstract;
+        { 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;
 
         { creates the correct branch instruction for a given combination }
         { of asmcondflags and destination addressing mode                }
@@ -517,5 +518,97 @@ unit cgppc;
       end;
 
 
+    procedure tcgppcgen.a_load_store(list:TAsmList;op: tasmop;reg:tregister;
+       ref: treference);
+
+      var
+        tmpreg: tregister;
+        tmpref: treference;
+        largeOffset: Boolean;
+
+      begin
+        tmpreg := NR_NO;
+        largeOffset:= hasLargeOffset(ref);
+
+        if target_info.system = system_powerpc_macos then
+          begin
+
+            if assigned(ref.symbol) then
+              begin {Load symbol's value}
+                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+
+                reference_reset(tmpref);
+                tmpref.symbol := ref.symbol;
+                tmpref.base := NR_RTOC;
+
+                if macos_direct_globals then
+                  list.concat(taicpu.op_reg_ref(A_LA,tmpreg,tmpref))
+                else
+                  list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
+              end;
+
+            if largeOffset then
+              begin {Add hi part of offset}
+                reference_reset(tmpref);
+
+                if Smallint(Lo(ref.offset)) < 0 then
+                  tmpref.offset := Hi(ref.offset) + 1 {Compensate when lo part is negative}
+                else
+                  tmpref.offset := Hi(ref.offset);
+
+                if (tmpreg <> NR_NO) then
+                  list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg, tmpreg,tmpref))
+                else
+                  begin
+                    tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+                    list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
+                  end;
+              end;
+
+            if (tmpreg <> NR_NO) then
+              begin
+                {Add content of base register}
+                if ref.base <> NR_NO then
+                  list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,
+                    ref.base,tmpreg));
+
+                {Make ref ready to be used by op}
+                ref.symbol:= nil;
+                ref.base:= tmpreg;
+                if largeOffset then
+                  ref.offset := Smallint(Lo(ref.offset));
+
+                list.concat(taicpu.op_reg_ref(op,reg,ref));
+                //list.concat(tai_comment.create(strpnew('*** a_load_store indirect global')));
+              end
+            else
+              list.concat(taicpu.op_reg_ref(op,reg,ref));
+          end
+        else {if target_info.system <> system_powerpc_macos}
+          begin
+            if assigned(ref.symbol) or
+               largeOffset then
+              begin
+                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+                reference_reset(tmpref);
+                tmpref.symbol := ref.symbol;
+                tmpref.relsymbol := ref.relsymbol;
+                tmpref.offset := ref.offset;
+                tmpref.refaddr := addr_hi;
+                if ref.base <> NR_NO then
+                  list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
+                    ref.base,tmpref))
+                else
+                  list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
+                ref.base := tmpreg;
+                ref.refaddr := addr_lo;
+                list.concat(taicpu.op_reg_ref(op,reg,ref));
+              end
+            else
+              list.concat(taicpu.op_reg_ref(op,reg,ref));
+          end;
+      end;
+
+
 end.