Browse Source

* cgbase.pas: added more MIPS-specific address types, needed to support large GOT model.
* cpugas.pas: GetReferenceString: rewritten, it is easier than trying to fix it. Fixes incorrect writing of non-PIC references containing base, symbol and offset together, and some forms of PIC references. Also supports newly introduced address types.

git-svn-id: trunk@23555 -

sergei 12 years ago
parent
commit
503b132096
2 changed files with 61 additions and 82 deletions
  1. 9 4
      compiler/cgbase.pas
  2. 52 78
      compiler/mips/cpugas.pas

+ 9 - 4
compiler/cgbase.pas

@@ -23,7 +23,7 @@
 unit cgbase;
 unit cgbase;
 
 
 {$i fpcdefs.inc}
 {$i fpcdefs.inc}
-
+{$J-}
 interface
 interface
 
 
     uses
     uses
@@ -70,9 +70,6 @@ interface
          addr_full,
          addr_full,
          addr_pic,
          addr_pic,
          addr_pic_no_got
          addr_pic_no_got
-         {$ifdef mips}
-         ,addr_pic_call16
-         {$endif}
          {$IF defined(POWERPC) or defined(POWERPC64) or defined(SPARC) or defined(MIPS)}
          {$IF defined(POWERPC) or defined(POWERPC64) or defined(SPARC) or defined(MIPS)}
          ,
          ,
          addr_low,         // bits 48-63
          addr_low,         // bits 48-63
@@ -87,6 +84,14 @@ interface
          addr_highera,     // bits 32-47, adjusted
          addr_highera,     // bits 32-47, adjusted
          addr_highesta     // bits 48-63, adjusted
          addr_highesta     // bits 48-63, adjusted
          {$ENDIF}
          {$ENDIF}
+         {$ENDIF POWERPC or POWERPC64 or SPARC or MIPS}
+         {$IFDEF MIPS}
+         ,
+         addr_pic_call16,  // like addr_pic, but generates call16 reloc instead of got16
+         addr_low_pic,     // for large GOT model, generate got_hi16 and got_lo16 relocs
+         addr_high_pic,
+         addr_low_call,    // counterpart of two above, generate call_hi16 and call_lo16 relocs
+         addr_high_call
          {$ENDIF}
          {$ENDIF}
          {$IFDEF AVR}
          {$IFDEF AVR}
          ,addr_lo8
          ,addr_lo8

+ 52 - 78
compiler/mips/cpugas.pas

@@ -58,7 +58,6 @@ unit cpugas;
     function gas_std_regname(r:Tregister):string;
     function gas_std_regname(r:Tregister):string;
       var
       var
         hr: tregister;
         hr: tregister;
-        p:  longint;
       begin
       begin
         { Double uses the same table as single }
         { Double uses the same table as single }
         hr := r;
         hr := r;
@@ -109,89 +108,64 @@ unit cpugas;
 
 
     function GetReferenceString(var ref: TReference): string;
     function GetReferenceString(var ref: TReference): string;
       var
       var
-        hasgot : boolean;
-        gotprefix : string;
+        reg: TRegister;
+        regstr: string;
       begin
       begin
-        GetReferenceString := '';
-        hasgot:=false;
-        with ref do
-        begin
-          if (base = NR_NO) and (index = NR_NO) then
+        result:='';
+        if assigned(ref.symbol) then
+          result:=ref.symbol.name;
+        if (ref.offset<0) then
+          result:=result+tostr(ref.offset)
+        else if (ref.offset>0) then
           begin
           begin
-            if assigned(symbol) then
-              begin
-                GetReferenceString := symbol.Name;
-                if (symbol.typ=AT_FUNCTION) or (refaddr=addr_pic_call16) then
-                  gotprefix:='%call16('
-                else
-                  gotprefix:='%got(';
-                hasgot:=true;
-              end;
-            if offset > 0 then
-              GetReferenceString := GetReferenceString + '+' + ToStr(offset)
-            else if offset < 0 then
-              GetReferenceString := GetReferenceString + ToStr(offset);
-            case refaddr of
-              addr_full : ;
-              addr_high:
-                GetReferenceString := '%hi(' + GetReferenceString + ')';
-              addr_low:
-                GetReferenceString := '%lo(' + GetReferenceString + ')';
-              addr_pic,addr_pic_call16:
-                begin
-                  if hasgot then
-                    GetReferenceString := gotprefix + GetReferenceString + ')'
-                  else
-                    internalerror(2012070401);
-                end;
+            if assigned(ref.symbol) then
+              result:=result+'+';
+            result:=result+tostr(ref.offset);
+          end;
+
+        { either base or index may be present, but not both }
+        reg:=ref.base;
+        if (reg=NR_NO) then
+          reg:=ref.index
+        else if (ref.index<>NR_NO) then
+          InternalError(2013013001);
+
+        if (reg=NR_NO) then
+          regstr:=''
+        else
+          regstr:='('+asm_regname(reg)+')';
+
+        case ref.refaddr of
+          addr_no,
+          addr_full:
+            if assigned(ref.symbol) and (reg<>NR_NO) then
+              InternalError(2013013002)
             else
             else
-              internalerror(2012070401);
-            end;
-          end
-          else
-          begin
-      {$ifdef extdebug}
-            if assigned(symbol) and
-              not(refaddr in [addr_pic,addr_low]) then
-              internalerror(2003052601);
-      {$endif extdebug}
-            if base <> NR_NO then
-              GetReferenceString := GetReferenceString + '(' + asm_regname(base) + ')';
-            if index = NR_NO then
-            begin
-              if offset <> 0 then
-                GetReferenceString := ToStr(offset) + GetReferenceString;
-              if assigned(symbol) then
               begin
               begin
-                case refaddr of
-                  addr_full, addr_high :
-                  GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
-                addr_low :
-                  GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString;
-                addr_pic, addr_pic_call16 :
-                  begin
-                    if symbol.typ=AT_FUNCTION then
-                      gotprefix:='%call16('
-                    else
-                      gotprefix:='%got(';
-                    GetReferenceString := gotprefix + symbol.Name + ')' + GetReferenceString;
-                   end
-                else
-                  internalerror(2012070401);
-                end;
+                result:=result+regstr;
+                exit;
               end;
               end;
-            end
-            else
-            begin
-  {$ifdef extdebug}
-              if (Offset<>0) or assigned(symbol) then
-                internalerror(2003052603);
-  {$endif extdebug}
-              GetReferenceString := GetReferenceString + '(' + asm_regname(index) + ')';
-
-            end;
-          end;
+          addr_pic:
+            result:='%got('+result;
+          addr_high:
+            result:='%hi('+result;
+          addr_low:
+            result:='%lo('+result;
+          addr_pic_call16:
+            result:='%call16('+result;
+          addr_low_pic:
+            result:='%got_lo('+result;
+          addr_high_pic:
+            result:='%got_hi('+result;
+          addr_low_call:
+            result:='%call_lo('+result;
+          addr_high_call:
+            result:='%call_hi('+result;
+        else
+          InternalError(2013013003);
         end;
         end;
+
+        result:=result+')'+regstr;
       end;
       end;