浏览代码

* SPARC: completely rewrote PIC-related code, got it twice shorter in source lines and much less instructions in generated code.
+ Enable registers %i0..%i5 and %o7 for use by reg.allocator.

Some notable properties of this implementation are:
o pi_needs_got flag can be safely set during pass 2, so not setting it occasionally in pass 1 does not result in internal error.
o Reg.allocator configuration is independent from PIC. If procedure requires GOT, register %l7 is allocated at the prologue, making it unavailable to RA.
o GOT is stored in fixed %l7 register, but it is trivial to switch over to virtual register.

git-svn-id: trunk@26293 -

sergei 11 年之前
父节点
当前提交
176d8434e4
共有 3 个文件被更改,包括 198 次插入388 次删除
  1. 154 308
      compiler/sparc/cgcpu.pas
  2. 42 80
      compiler/sparc/cpugas.pas
  3. 2 0
      compiler/sparc/cpupi.pas

+ 154 - 308
compiler/sparc/cgcpu.pas

@@ -43,7 +43,6 @@ interface
         function  getfpuregister(list:TAsmList;size:Tcgsize):Tregister;override;
         { sparc special, needed by cg64 }
         procedure make_simple_ref(list:TAsmList;var ref: treference);
-        procedure make_simple_ref_sparc(list:TAsmList;var ref: treference;loadaddr : boolean;addrreg : tregister);
         procedure handle_load_store(list:TAsmList;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
         procedure handle_reg_const_reg(list:TAsmList;op:Tasmop;src:tregister;a:tcgint;dst:tregister);
         { parameter }
@@ -142,8 +141,6 @@ implementation
 
     function TCgSparc.IsSimpleRef(const ref:treference):boolean;
       begin
-        if (ref.base=NR_NO) and (ref.index<>NR_NO) then
-          InternalError(2002100804);
         result :=not(assigned(ref.symbol))and
                   (((ref.index = NR_NO) and
                    (ref.offset >= simm13lo) and
@@ -154,181 +151,113 @@ implementation
 
 
     procedure tcgsparc.make_simple_ref(list:TAsmList;var ref: treference);
-      begin
-        make_simple_ref_sparc(list,ref,false,NR_NO);
-      end;
-
-    procedure tcgsparc.make_simple_ref_sparc(list:TAsmList;var ref: treference;loadaddr : boolean;addrreg : tregister);
       var
-        tmpreg,tmpreg2 : tregister;
-        tmpref : treference;
-        need_add_got,need_got_load : boolean;
+        href: treference;
+        hreg,hreg2: tregister;
       begin
-        if loadaddr then
-          tmpreg:=addrreg
-        else
-          tmpreg:=NR_NO;
-        need_add_got:=false;
-        need_got_load:=false;
-        { Be sure to have a base register }
+        if (ref.refaddr<>addr_no) then
+          InternalError(2013022802);
+
         if (ref.base=NR_NO) then
           begin
             ref.base:=ref.index;
             ref.index:=NR_NO;
           end;
-        if (cs_create_pic in current_settings.moduleswitches) and
-           (tf_pic_uses_got in target_info.flags) and
-           use_unlimited_pic_mode and
-           assigned(ref.symbol) then
+
+        if IsSimpleRef(ref) then
+          exit;
+
+        if (ref.symbol=nil) then
           begin
-            if not(pi_needs_got in current_procinfo.flags) then
+            hreg:=getintregister(list,OS_INT);
+            if (ref.index=NR_NO) then
+              a_load_const_reg(list,OS_INT,ref.offset,hreg)
+            else
               begin
-{$ifdef CHECK_PIC}
-                internalerror(200501161);
-{$endif CHECK_PIC}
-                include(current_procinfo.flags,pi_needs_got);
+                if (ref.offset<simm13lo) or (ref.offset>simm13hi-sizeof(pint)) then
+                  begin
+                    a_load_const_reg(list,OS_INT,ref.offset,hreg);
+                    list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,hreg));
+                  end
+                else
+                  list.concat(taicpu.op_reg_const_reg(A_ADD,ref.index,ref.offset,hreg));
               end;
-            if current_procinfo.got=NR_NO then
-              current_procinfo.got:=NR_L7;
-            need_got_load:=true;
-            need_add_got:=true;
+            if (ref.base=NR_NO) then
+              ref.base:=hreg
+            else
+              ref.index:=hreg;
+            ref.offset:=0;
+            exit;
           end;
-        if (cs_create_pic in current_settings.moduleswitches) and
-           (tf_pic_uses_got in target_info.flags) and
-           not use_unlimited_pic_mode and
-           assigned(ref.symbol) then
+
+        reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment);
+        hreg:=getintregister(list,OS_INT);
+        if not (cs_create_pic in current_settings.moduleswitches) then
           begin
-            if tmpreg=NR_NO then
-              tmpreg:=GetIntRegister(list,OS_INT);
-            reference_reset(tmpref,ref.alignment);
-            tmpref.symbol:=ref.symbol;
-            tmpref.refaddr:=addr_pic;
-            if not(pi_needs_got in current_procinfo.flags) then
+            { absolute loads allow any offset to be encoded into relocation }
+            href.refaddr:=addr_high;
+            list.concat(taicpu.op_ref_reg(A_SETHI,href,hreg));
+            if (ref.base=NR_NO) and (ref.index=NR_NO) then
               begin
-{$ifdef CHECK_PIC}
-                internalerror(200501161);
-{$endif CHECK_PIC}
-                include(current_procinfo.flags,pi_needs_got);
+                ref.base:=hreg;
+                ref.refaddr:=addr_low;
+                exit;
               end;
-            if current_procinfo.got=NR_NO then
-              current_procinfo.got:=NR_L7;
-            tmpref.index:=current_procinfo.got;
-            list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
+            { base present -> load the entire address and use it as index }
+            href.refaddr:=addr_low;
+            list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,href,hreg));
             ref.symbol:=nil;
+            ref.offset:=0;
             if (ref.index<>NR_NO) then
-              begin
-                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
-                ref.index:=tmpreg;
-              end
-            else
-              begin
-                if ref.base<>NR_NO then
-                  ref.index:=tmpreg
-                else
-                  ref.base:=tmpreg;
-              end;
-          end;
-        { When need to use SETHI, do it first }
-        if assigned(ref.symbol) or
-           (ref.offset<simm13lo) or
-           (ref.offset>simm13hi) then
+              list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.index,hreg,hreg));
+            ref.index:=hreg;
+          end
+        else
           begin
-            if tmpreg=NR_NO then
-              tmpreg:=GetIntRegister(list,OS_INT);
-            reference_reset(tmpref,ref.alignment);
-            tmpref.symbol:=ref.symbol;
-            if not need_got_load then
-              tmpref.offset:=ref.offset;
-            tmpref.refaddr:=addr_high;
-            list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
-            if (ref.offset=0) and (ref.index=NR_NO) and
-              (ref.base=NR_NO) and not need_add_got then
+            include(current_procinfo.flags,pi_needs_got);
+            href.offset:=0;
+            if use_unlimited_pic_mode then
               begin
-                ref.refaddr:=addr_low;
+                href.refaddr:=addr_high;
+                list.concat(taicpu.op_ref_reg(A_SETHI,href,hreg));
+                href.refaddr:=addr_low;
+                list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,href,hreg));
+                reference_reset_base(href,hreg,0,sizeof(pint));
+                href.index:=current_procinfo.got;
               end
             else
               begin
-                { Load the low part is left }
-                tmpref.refaddr:=addr_low;
-                list.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
-                if not need_got_load then
-                  ref.offset:=0;
-                { symbol is loaded }
-                ref.symbol:=nil;
+                href.base:=current_procinfo.got;
+                href.refaddr:=addr_pic;
               end;
-            if need_add_got then
-              begin
-                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,current_procinfo.got,tmpreg));
-                need_add_got:=false;
-              end;
-            if need_got_load then
+            list.concat(taicpu.op_ref_reg(A_LD,href,hreg));
+            ref.symbol:=nil;
+            { hreg now holds symbol address. Add remaining members. }
+            if (ref.offset>=simm13lo) and (ref.offset<=simm13hi-sizeof(pint)) then
               begin
-                tmpref.refaddr:=addr_no;
-                tmpref.base:=tmpreg;
-                tmpref.symbol:=nil;
-                list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
-                need_got_load:=false;
-                if (ref.offset<simm13lo) or
-                   (ref.offset>simm13hi) then
+                if (ref.base=NR_NO) then
+                  ref.base:=hreg
+                else
                   begin
-                    tmpref.symbol:=nil;
-                    tmpref.offset:=ref.offset;
-                    tmpref.base:=tmpreg;
-                    tmpref.refaddr := addr_high;
-                    tmpreg2:=GetIntRegister(list,OS_INT);
-                    a_load_const_reg(list,OS_INT,ref.offset,tmpreg2);
-                    list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg2,tmpreg));
+                    if (ref.offset<>0) then
+                      list.concat(taicpu.op_reg_const_reg(A_ADD,hreg,ref.offset,hreg));
+                    if (ref.index<>NR_NO) then
+                      list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,hreg));
+                    ref.index:=hreg;
                     ref.offset:=0;
                   end;
-              end;
-            if (ref.index<>NR_NO) then
-              begin
-                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
-                ref.index:=tmpreg;
-              end
-            else
-              begin
-                if ref.base<>NR_NO then
-                  ref.index:=tmpreg
-                else
-                  ref.base:=tmpreg;
-              end;
-          end;
-        if need_add_got then
-          begin
-            if tmpreg=NR_NO then
-              tmpreg:=GetIntRegister(list,OS_INT);
-            list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,current_procinfo.got,tmpreg));
-            ref.base:=tmpreg;
-            ref.index:=NR_NO;
-          end;
-        if need_got_load then
-          begin
-            if tmpreg=NR_NO then
-              tmpreg:=GetIntRegister(list,OS_INT);
-            list.concat(taicpu.op_ref_reg(A_LD,ref,tmpreg));
-            ref.base:=tmpreg;
-            ref.index:=NR_NO;
-          end;
-        if (ref.base<>NR_NO) or loadaddr then
-          begin
-            if loadaddr then
-              begin
-                if ref.index<>NR_NO then
-                  list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
-                ref.base:=tmpreg;
-                ref.index:=NR_NO;
-                if ref.offset<>0 then
-                  list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,ref.offset,tmpreg));
               end
-            else if (ref.index<>NR_NO) and
-               ((ref.offset<>0) or assigned(ref.symbol)) then
+            else    { large offset, need another register to deal with it }
               begin
-                if tmpreg=NR_NO then
-                  tmpreg:=GetIntRegister(list,OS_INT);
-                list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
-                ref.base:=tmpreg;
-                ref.index:=NR_NO;
+                hreg2:=getintregister(list,OS_INT);
+                a_load_const_reg(list,OS_INT,ref.offset,hreg2);
+                if (ref.index<>NR_NO) then
+                  list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg2,ref.index,hreg2));
+                if (ref.base<>NR_NO) then
+                  list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg2,ref.base,hreg2));
+                ref.base:=hreg;
+                ref.index:=hreg2;
+                ref.offset:=0;
               end;
           end;
       end;
@@ -376,21 +305,11 @@ implementation
       begin
         inherited init_register_allocators;
 
-        if (cs_create_pic in current_settings.moduleswitches) and
-           assigned(current_procinfo) and
-           (pi_needs_got in current_procinfo.flags) then
-          begin
-            current_procinfo.got:=NR_L7;
-            rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
-                [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,
-                 RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6],
-                first_int_imreg,[]);
-          end
-        else
-          rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
-              [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,
-               RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7],
-              first_int_imreg,[]);
+        rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
+            [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,RS_O7,
+             RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7,
+             RS_I0,RS_I1,RS_I2,RS_I3,RS_I4,RS_I5],
+            first_int_imreg,[]);
 
         rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBFS,
             [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
@@ -739,164 +658,89 @@ implementation
 
     procedure TCgSparc.a_loadaddr_ref_reg(list : TAsmList;const ref : TReference;r : tregister);
       var
-         tmpref,href : treference;
-         hreg,tmpreg,hreg2 : tregister;
-         need_got,need_got_load : boolean;
+         href: treference;
+         hreg: tregister;
       begin
-        href:=ref;
-{$ifdef TEST_SIMPLE_SPARC}
-        make_simple_ref_sparc(list,href,true,r);
-{$else}
-        need_got:=false;
-        need_got_load:=false;
-        if (href.base=NR_NO) and (href.index<>NR_NO) then
+        if (ref.base=NR_NO) and (ref.index<>NR_NO) then
           internalerror(200306171);
-        if (cs_create_pic in current_settings.moduleswitches) and
-           (tf_pic_uses_got in target_info.flags) and
-           use_unlimited_pic_mode and
-           assigned(ref.symbol) then
-          begin
-            if not(pi_needs_got in current_procinfo.flags) then
-              begin
-{$ifdef CHECK_PIC}
-                internalerror(200501161);
-{$endif CHECK_PIC}
-                include(current_procinfo.flags,pi_needs_got);
-              end;
-            if current_procinfo.got=NR_NO then
-              current_procinfo.got:=NR_L7;
-            need_got_load:=true;
-            need_got:=true;
-          end;
 
-        if (cs_create_pic in current_settings.moduleswitches) and
-           (tf_pic_uses_got in target_info.flags) and
-           not use_unlimited_pic_mode and
-           assigned(href.symbol) then
+        if (ref.symbol=nil) then
           begin
-            tmpreg:=GetIntRegister(list,OS_ADDR);
-            reference_reset(tmpref,href.alignment);
-            tmpref.symbol:=href.symbol;
-            tmpref.refaddr:=addr_pic;
-            if not(pi_needs_got in current_procinfo.flags) then
+            if (ref.base<>NR_NO) then
               begin
-{$ifdef CHECK_PIC}
-                internalerror(200501161);
-{$endif CHECK_PIC}
-                include(current_procinfo.flags,pi_needs_got);
-              end;
-            if current_procinfo.got=NR_NO then
-              current_procinfo.got:=NR_L7;
-            tmpref.base:=current_procinfo.got;
-            list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
-            href.symbol:=nil;
-            if (href.index<>NR_NO) then
-              begin
-                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,href.index,tmpreg));
-                href.index:=tmpreg;
+                if (ref.offset<simm13lo) or (ref.offset>simm13hi) then
+                  begin
+                    hreg:=getintregister(list,OS_INT);
+                    a_load_const_reg(list,OS_INT,ref.offset,hreg);
+                    list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.base,r));
+                    if (ref.index<>NR_NO) then
+                      list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
+                  end
+                else if (ref.offset<>0) then
+                  begin
+                    list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,ref.offset,r));
+                    if (ref.index<>NR_NO) then
+                      list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
+                  end
+                else if (ref.index<>NR_NO) then
+                  list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,r))
+                else
+                  a_load_reg_reg(list,OS_INT,OS_INT,ref.base,r);   { (try to) emit optimizable move }
               end
             else
-              begin
-                if href.base<>NR_NO then
-                  href.index:=tmpreg
-                else
-                  href.base:=tmpreg;
-              end;
+              a_load_const_reg(list,OS_INT,ref.offset,r);
+            exit;
           end;
 
-        { At least big offset (need SETHI), maybe base and maybe index }
-        if assigned(href.symbol) or
-           (href.offset<simm13lo) or
-           (href.offset>simm13hi) then
+        reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment);
+        if (cs_create_pic in current_settings.moduleswitches) then
           begin
-            hreg:=GetAddressRegister(list);
-            reference_reset(tmpref,href.alignment);
-            tmpref.symbol := href.symbol;
-            if not need_got_load then
-              tmpref.offset := href.offset;
-            tmpref.refaddr := addr_high;
-            list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
-            { Only the low part is left }
-            tmpref.refaddr:=addr_low;
-            list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
-            if need_got then
-              begin
-                list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,current_procinfo.got,hreg));
-                need_got:=false;
-              end;
-            if need_got_load then
+            include(current_procinfo.flags,pi_needs_got);
+            href.offset:=0;
+            if use_unlimited_pic_mode then
               begin
-                 tmpref.symbol:=nil;
-                 tmpref.base:=hreg;
-                 tmpref.refaddr:=addr_no;
-                 list.concat(taicpu.op_ref_reg(A_LD,tmpref,hreg));
-                 need_got_load:=false;
-                if (href.offset<simm13lo) or
-                   (href.offset>simm13hi) then
-                  begin
-                    tmpref.symbol:=nil;
-                    tmpref.offset:=href.offset;
-                    tmpref.refaddr := addr_high;
-                    hreg2:=GetIntRegister(list,OS_INT);
-                    a_load_const_reg(list,OS_INT,href.offset,hreg2);
-                    { Only the low part is left }
-                    list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,hreg2,hreg));
-                  end
-                else if (href.offset<>0) then
-                  begin
-                    list.concat(taicpu.op_reg_const_reg(A_ADD,hreg,href.offset,hreg));
-                  end;
-              end;
-            if href.base<>NR_NO then
-              begin
-                if href.index<>NR_NO then
-                  begin
-                    list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.base,hreg));
-                    list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.index,r));
-                  end
-                else
-                  list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.base,r));
+                href.refaddr:=addr_high;
+                list.concat(taicpu.op_ref_reg(A_SETHI,href,r));
+                href.refaddr:=addr_low;
+                list.concat(taicpu.op_reg_ref_reg(A_OR,r,href,r));
+                reference_reset_base(href,r,0,sizeof(pint));
+                href.index:=current_procinfo.got;
               end
             else
               begin
-                if hreg<>r then
-                  a_load_reg_reg(list,OS_ADDR,OS_ADDR,hreg,r);
+                href.base:=current_procinfo.got;
+                href.refaddr:=addr_pic;            { should it be done THAT way?? }
               end;
+            { load contents of GOT slot }
+            list.concat(taicpu.op_ref_reg(A_LD,href,r));
+            { add original base/index, if any }
+            if (ref.base<>NR_NO) then
+              list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.base,r));
+            if (ref.index<>NR_NO) then
+              list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
+            { finally, add offset }
+            if (ref.offset<simm13lo) or (ref.offset>simm13hi) then
+              begin
+                hreg:=getintregister(list,OS_INT);
+                a_load_const_reg(list,OS_INT,ref.offset,hreg);
+                list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,r,r));
+              end
+            else if (ref.offset<>0) then
+              list.concat(taicpu.op_reg_const_reg(A_ADD,r,ref.offset,r));
           end
         else
-        { At least small offset, maybe base and maybe index }
-          if href.offset<>0 then
-            begin
-              if href.base<>NR_NO then
-                begin
-                  if href.index<>NR_NO then
-                    begin
-                      hreg:=GetAddressRegister(list);
-                      list.concat(taicpu.op_reg_const_reg(A_ADD,href.base,href.offset,hreg));
-                      list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.index,r));
-                    end
-                  else
-                    list.concat(taicpu.op_reg_const_reg(A_ADD,href.base,href.offset,r));
-                end
-              else
-                list.concat(taicpu.op_const_reg(A_MOV,href.offset,r));
-            end
-        else
-        { Both base and index }
-          if href.index<>NR_NO then
-            list.concat(taicpu.op_reg_reg_reg(A_ADD,href.base,href.index,r))
-        else
-        { Only base }
-          if href.base<>NR_NO then
-            a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r)
-        else
-          { only offset, can be generated by absolute }
-          a_load_const_reg(list,OS_ADDR,href.offset,r);
-        if need_got then
-          list.concat(taicpu.op_reg_reg_reg(A_ADD,r,current_procinfo.got,r));
-        if need_got_load then
-          list.concat(taicpu.op_reg_reg(A_LD,r,r));
-{$endif}
+          begin
+            { load symbol+offset }
+            href.refaddr:=addr_high;
+            list.concat(taicpu.op_ref_reg(A_SETHI,href,r));
+            href.refaddr:=addr_low;
+            list.concat(taicpu.op_reg_ref_reg(A_OR,r,href,r));
+            { add original base/index, if any }
+            if (ref.base<>NR_NO) then
+              list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.base,r));
+            if (ref.index<>NR_NO) then
+              list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
+          end;
       end;
 
 
@@ -1261,9 +1105,9 @@ implementation
         hl : tasmlabel;
       begin
         if (cs_create_pic in current_settings.moduleswitches) and
-           (pi_needs_got in current_procinfo.flags) then
+           ((pi_needs_got in current_procinfo.flags) or
+           (current_procinfo.procdef.proctypeoption=potype_unitfinalize)) then
           begin
-            current_procinfo.got:=NR_L7;
             current_asmdata.getjumplabel(hl);
             list.concat(taicpu.op_sym(A_CALL,hl));
             { ABI recommends the following sequence:
@@ -1279,6 +1123,8 @@ implementation
             ref.offset:=8;
             list.concat(Taicpu.Op_reg_ref_reg(A_OR,NR_L7,ref,NR_L7));
             list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_L7,NR_O7,NR_L7));
+            { allocate NR_L7, so reg.allocator does not see it as available }
+            list.concat(tai_regalloc.alloc(NR_L7,nil));
           end;
       end;
 

+ 42 - 80
compiler/sparc/cpugas.pas

@@ -83,91 +83,53 @@ implementation
 
 
     function TSPARCInstrWriter.GetReferenceString(var ref:TReference):string;
-      var
-        asm_comment : string;
       begin
-        GetReferenceString:='';
-        asm_comment:='';
-        with ref do
+        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
-            if (base=NR_NO) and (index=NR_NO) then
-              begin
-                 if assigned(symbol) then
-                   GetReferenceString:=symbol.name;
-                 if offset>0 then
-                   GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
-                 else if offset<0 then
-                   GetReferenceString:=GetReferenceString+ToStr(offset);
-                 case refaddr of
-                   addr_high:
-                     GetReferenceString:='%hi('+GetReferenceString+')';
-                   addr_low:
-                     GetReferenceString:='%lo('+GetReferenceString+')';
-                   addr_pic:
-                     begin
-                       asm_comment:='addr_pic should use %l7 register as base or index: '+GetReferenceString;
-                       Comment(V_Warning,asm_comment);
-                       GetReferenceString:='%l7+'+GetReferenceString;
-                     end;
-                 end;
-              end
-            else
+            if assigned(ref.symbol) then
+              result:=result+'+';
+            result:=result+tostr(ref.offset);
+          end
+        { asmreader appears to treat literal numbers as references }
+        else if (ref.symbol=nil) and (ref.base=NR_NO) and (ref.index=NR_NO) then
+          result:='0';
+
+        case ref.refaddr of
+          addr_high:
+            result:='%hi('+result+')';
+          addr_low:
+            result:='%lo('+result+')';
+        end;
+
+        if assigned(ref.symbol) or (ref.offset<>0) then
+          begin
+            if (ref.base<>NR_NO) then
               begin
-                if (base=NR_NO) and (index<>NR_NO) then
-                  begin
-                    base:=index;
-                    index:=NR_NO;
-                  end;
-{$ifdef extdebug}
-                if assigned(symbol) and
-                  not(refaddr in [addr_pic,addr_low]) then
-                  internalerror(2003052601);
-{$endif extdebug}
-                GetReferenceString:=GetReferenceString+gas_regname(base);
-                if index=NR_NO then
-                  begin
-                    { if (Offset<simm13lo) or (Offset>simm13hi) then
-                      internalerror(2003053008); }
-                    if offset>0 then
-                      GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
-                    else if offset<0 then
-                      GetReferenceString:=GetReferenceString+ToStr(offset);
-                    {
-                    else if (offset=0) and not(assigned(symbol)) then
-                      GetReferenceString:=GetReferenceString+ToStr(offset);
-                    }
-                    if assigned(symbol) then
-                      begin
-                        if refaddr=addr_low then
-                          GetReferenceString:='%lo('+symbol.name+')+'+GetReferenceString
-                        else if refaddr=addr_pic then
-                          begin
-                            if assigned(current_procinfo) and (base <> current_procinfo.got) then
-                              begin
-                                asm_comment:=' pic address should use %l7 register: '+GetReferenceString; 
-                                Comment(V_Warning,asm_comment);
-                              end;
-                            GetReferenceString:=GetReferenceString+'+'+symbol.name;
-                          end
-                        else
-                          GetReferenceString:=symbol.name+'+'+GetReferenceString;
-                      end;
-                  end
+                if (ref.index<>NR_NO) then
+                  InternalError(2013013001);
+                if (result[1]='-') then
+                  result:=gas_regname(ref.base)+result
                 else
-                  begin
-{$ifdef extdebug}
-                    if (Offset<>0) or assigned(symbol) then
-                      internalerror(2003052603);
-{$endif extdebug}
-                    GetReferenceString:=GetReferenceString+'+'+gas_regname(index);
-                    
-                  end;
-              end;
-          end;
-        if asm_comment <> '' then
+                  result:=gas_regname(ref.base)+'+'+result;
+              end
+            else if (ref.index<>NR_NO) then
+              InternalError(2013122501);
+          end
+        else
           begin
-            owner.AsmWrite(target_asm.comment+' '+asm_comment);
-            owner.AsmLn;
+            if (ref.base<>NR_NO) then
+              begin
+                result:=gas_regname(ref.base);
+                if (ref.index<>NR_NO) then
+                  result:=result+'+'+gas_regname(ref.index);
+              end
+            else if (ref.index<>NR_NO) then
+              result:=gas_regname(ref.index);
           end;
       end;
 

+ 2 - 0
compiler/sparc/cpupi.pas

@@ -41,12 +41,14 @@ implementation
 
     uses
       systems,globals,
+      cpubase,cgbase,
       tgobj,paramgr,symconst;
 
     constructor tsparcprocinfo.create(aparent:tprocinfo);
       begin
         inherited create(aparent);
         maxpushedparasize:=0;
+        got:=NR_L7;
       end;