Prechádzať zdrojové kódy

+ SPARC: generate position-independent case jump tables, as specified by ABI.
Generate them also for non-PIC mode: absolute code is just 2 instructions shorter, trying to save them is probably not worth the effort.

git-svn-id: trunk@26468 -

sergei 11 rokov pred
rodič
commit
c673c32ad9
2 zmenil súbory, kde vykonal 39 pridanie a 27 odobranie
  1. 5 1
      compiler/sparc/cpugas.pas
  2. 34 26
      compiler/sparc/ncpuset.pas

+ 5 - 1
compiler/sparc/cpugas.pas

@@ -86,7 +86,11 @@ implementation
       begin
         result:='';
         if assigned(ref.symbol) then
-          result:=ref.symbol.name;
+          begin
+            result:=ref.symbol.name;
+            if assigned(ref.relsymbol) then
+              result:=result+'-'+ref.relsymbol.name;
+          end;
         if (ref.offset<0) then
           result:=result+tostr(ref.offset)
         else if (ref.offset>0) then

+ 34 - 26
compiler/sparc/ncpuset.pas

@@ -37,8 +37,6 @@ unit ncpuset;
            procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
            function has_jumptable : boolean;override;
            procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
-         public
-           function pass_1:tnode;override;
        end;
 
 
@@ -65,18 +63,9 @@ unit ncpuset;
       end;
 
 
-    function tcpucasenode.pass_1:tnode;
-      begin
-        result:=inherited pass_1;
-        { TODO: ABI-compliant position-independent case code does not involve GOT }
-        if (cs_create_pic in current_settings.moduleswitches) and
-          (tf_pic_uses_got in target_info.flags) then
-          include(current_procinfo.flags,pi_needs_got);
-      end;
-
-
     procedure tcpucasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
       var
+        base,
         table : tasmlabel;
         last : TConstExprInt;
         indexreg,jmpreg,basereg : tregister;
@@ -91,9 +80,9 @@ unit ncpuset;
               genitem(list,t^.less);
             { fill possible hole }
             for i:=last.svalue+1 to t^._low.svalue-1 do
-              list.concat(Tai_const.Create_sym(elselabel));
+              list.concat(Tai_const.Create_rel_sym(aitconst_ptr,base,elselabel));
             for i:=t^._low.svalue to t^._high.svalue do
-              list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+              list.concat(Tai_const.Create_rel_sym(aitconst_ptr,base,blocklabel(t^.blockid)));
             last:=t^._high;
             if assigned(t^.greater) then
               genitem(list,t^.greater);
@@ -112,26 +101,45 @@ unit ncpuset;
         indexreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
         cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,2,hregister,indexreg);
         { create reference }
-        reference_reset_symbol(href,table,0,sizeof(pint));
-        href.offset:=(-aint(min_))*4;
+        current_asmdata.getjumplabel(base);
+        cg.a_label(current_asmdata.CurrAsmList,base);
+        reference_reset_symbol(href,table,(-aint(min_))*4,sizeof(pint));
+        href.relsymbol:=base;
+        { Generate the following code:
+          .Lbase:
+              call  .+8                           # mov   %pc,%o7
+              sethi %hi(.LTable-.Lbase),%basereg
+              or    %basereg,%lo(.LTable-.Lbase),%basereg
+              add   %indexreg,%basereg%,%basereg
+              ld    [%o7+%basereg],%jmpreg
+              jmp   %o7+%jmpreg                              }
+        { CALL overwrites %o7, tell reg.allocator about that }
+        cg.getcpuregister(current_asmdata.CurrAsmList,NR_O7);
+        current_asmdata.CurrAsmList.concat(taicpu.op_sym_ofs(A_CALL,base,8));
+
         basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
-        cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,basereg);
+        { TODO: incorporate handling such references into cg.a_loadaddr_ref_reg? }
+        href.refaddr:=addr_high;
+        current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_SETHI,href,basereg));
+        href.refaddr:=addr_low;
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref_reg(A_OR,basereg,href,basereg));
+        { add index }
+        cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,basereg,indexreg,basereg);
 
         jmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
-
-        reference_reset(href,sizeof(pint));
-        href.index:=indexreg;
-        href.base:=basereg;
+        reference_reset_base(href,NR_O7,0,sizeof(pint));
+        href.index:=basereg;
         cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,jmpreg);
-
-        current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_JMP,jmpreg));
+        href.index:=jmpreg;
+        href.refaddr:=addr_full;
+        current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_JMP,href));
         { Delay slot }
         current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
+        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_O7);
         { generate jump table }
-        new_section(current_procinfo.aktlocaldata,sec_data,current_procinfo.procdef.mangledname,sizeof(pint));
-        current_procinfo.aktlocaldata.concat(Tai_label.Create(table));
         last:=min_;
-        genitem(current_procinfo.aktlocaldata,hp);
+        cg.a_label(current_asmdata.CurrAsmList,table);
+        genitem(current_asmdata.CurrAsmList,hp);
       end;