Selaa lähdekoodia

* moved spilling code from taicpu to rg

peter 21 vuotta sitten
vanhempi
commit
c34c9af5ce
5 muutettua tiedostoa jossa 828 lisäystä ja 859 poistoa
  1. 4 263
      compiler/aasmtai.pas
  2. 422 204
      compiler/rgobj.pas
  3. 4 387
      compiler/x86/aasmcpu.pas
  4. 5 2
      compiler/x86/cpubase.pas
  5. 393 3
      compiler/x86/rgx86.pas

+ 4 - 263
compiler/aasmtai.pas

@@ -488,15 +488,6 @@ interface
           function is_reg_move:boolean;virtual;abstract;
           function is_same_reg_move:boolean;virtual;abstract;
           { register allocator }
-          function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister;var live_registers_int:Tsuperregisterworklist):Tai;
-          procedure forward_allocation(p:Tai;var live_registers_int:Tsuperregisterworklist);
-          function spill_registers(list:Taasmoutput;
-                                   rt:Tregistertype;
-                                   rgget:Trggetproc;
-                                   rgunget:Trgungetproc;
-                                   const r:tsuperregisterset;
-                                   var live_registers_int:Tsuperregisterworklist;
-                                   const spilltemplist:Tspill_temp_list):boolean;virtual;
           function spilling_create_load(const ref:treference;r:tregister): tai;virtual;abstract;
           function spilling_create_store(r:tregister; const ref:treference): tai;virtual;abstract;
           function spilling_get_operation_type(opnr: longint): topertype;virtual;abstract;
@@ -1763,259 +1754,6 @@ implementation
       end;
 
 
-{ ---------------------------------------------------------------------
-    Register allocator methods.
-  ---------------------------------------------------------------------}
-
-    function taicpu_abstract.get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister;
-                                            var live_registers_int:Tsuperregisterworklist):Tai;
-      var
-        back   : Tsuperregisterworklist;
-        supreg : tsuperregister;
-      begin
-        back.copyfrom(live_registers_int);
-        get_insert_pos:=p;
-        while (p<>nil) and (p.typ=ait_regalloc) do
-          begin
-            supreg:=getsupreg(Tai_regalloc(p).reg);
-            {Rewind the register allocation.}
-            if Tai_regalloc(p).allocation then
-              live_registers_int.delete(supreg)
-            else
-              begin
-                live_registers_int.add(supreg);
-                if supreg=huntfor1 then
-                  begin
-                    get_insert_pos:=Tai(p.previous);
-                    back.done;
-                    back.copyfrom(live_registers_int);
-                  end;
-                if supreg=huntfor2 then
-                  begin
-                    get_insert_pos:=Tai(p.previous);
-                    back.done;
-                    back.copyfrom(live_registers_int);
-                  end;
-                if supreg=huntfor3 then
-                  begin
-                    get_insert_pos:=Tai(p.previous);
-                    back.done;
-                    back.copyfrom(live_registers_int);
-                  end;
-              end;
-            p:=Tai(p.previous);
-          end;
-        live_registers_int.done;
-        live_registers_int.copyfrom(back);
-      end;
-
-
-    procedure taicpu_abstract.forward_allocation(p:Tai;var live_registers_int:Tsuperregisterworklist);
-      begin
-        {Forward the register allocation again.}
-        while (p<>self) do
-          begin
-            if p.typ<>ait_regalloc then
-              internalerror(200305311);
-            if Tai_regalloc(p).allocation then
-              live_registers_int.add(getsupreg(Tai_regalloc(p).reg))
-            else
-              live_registers_int.delete(getsupreg(Tai_regalloc(p).reg));
-            p:=Tai(p.next);
-          end;
-      end;
-
-
-    function taicpu_abstract.spill_registers(list:Taasmoutput;
-                             rt:Tregistertype;
-                             rgget:Trggetproc;
-                             rgunget:Trgungetproc;
-                             const r:Tsuperregisterset;
-                             var live_registers_int:Tsuperregisterworklist;
-                             const spilltemplist:Tspill_temp_list): boolean;
-      type
-        tspillreginfo = record
-          orgreg: tsuperregister;
-          newreg: tregister;
-          regread,regwritten, mustbespilled: boolean;
-        end;
-      var
-        counter, regindex: longint;
-        pos: tai;
-        regs: array[0..2] of tspillreginfo;
-        supreg: tsuperregister;
-        spilled: boolean;
-
-
-      procedure DoSpillRead(pos: tai; regidx: longint);
-        var
-          helpins: tai;
-        begin
-          helpins:=spilling_create_load(spilltemplist[regs[regidx].orgreg],regs[regidx].newreg);
-          if pos=nil then
-            list.insertafter(helpins,list.first)
-          else
-            list.insertafter(helpins,pos.next);
-          rgunget(list,self,regs[regidx].newreg);
-          forward_allocation(tai(helpins.next),live_registers_int);
-        end;
-
-
-      procedure DoSpillWritten(pos: tai; regidx: longint);
-        var
-          helpins: tai;
-        begin
-          helpins:=spilling_create_store(regs[regidx].newreg,spilltemplist[regs[regidx].orgreg]);
-          list.insertafter(helpins,self);
-          rgunget(list,helpins,regs[regidx].newreg);
-        end;
-
-
-      procedure DoSpillReadWritten(pos: tai; regidx: longint);
-        var
-          helpins1, helpins2: tai;
-        begin
-          helpins1:=spilling_create_load(spilltemplist[regs[regidx].orgreg],regs[regidx].newreg);
-          if pos=nil then
-            list.insertafter(helpins1,list.first)
-          else
-            list.insertafter(helpins1,pos.next);
-          helpins2:=spilling_create_store(regs[regidx].newreg,spilltemplist[regs[regidx].orgreg]);
-          list.insertafter(helpins2,self);
-          rgunget(list,helpins2,regs[regidx].newreg);
-          forward_allocation(tai(helpins1.next),live_registers_int);
-        end;
-
-
-      procedure addreginfo(reg: tsuperregister; operation: topertype);
-        var
-          i, tmpindex: longint;
-        begin
-          tmpindex := regindex;
-          // did we already encounter this register?
-          for i := 0 to pred(regindex) do
-            if (regs[i].orgreg = reg) then
-              begin
-                tmpindex := i;
-                break;
-              end;
-          if tmpindex > high(regs) then
-            internalerror(2003120301);
-          regs[tmpindex].orgreg := reg;
-          if supregset_in(r,reg) then
-            begin
-              // add/update info on this register
-              regs[tmpindex].mustbespilled := true;
-              case operation of
-                operand_read:
-                  regs[tmpindex].regread := true;
-                operand_write:
-                  regs[tmpindex].regwritten := true;
-                operand_readwrite:
-                  begin
-                    regs[tmpindex].regread := true;
-                    regs[tmpindex].regwritten := true;
-                  end;
-              end;
-              spilled := true;
-            end;
-          inc(regindex,ord(regindex=tmpindex));
-        end;
-
-
-      procedure tryreplacereg(var reg: tregister);
-        var
-          i: longint;
-          supreg: tsuperregister;
-        begin
-          if (getregtype(reg) = R_INTREGISTER) then
-            begin
-              supreg := getsupreg(reg);
-              for i := 0 to pred(regindex) do
-                if (regs[i].mustbespilled) and
-                   (regs[i].orgreg = supreg) then
-                  begin
-                    reg := regs[i].newreg;
-                    break;
-                  end;
-            end;
-        end;
-
-
-      begin
-        result := false;
-        fillchar(regs,sizeof(regs),0);
-        for counter := low(regs) to high(regs) do
-          regs[counter].orgreg := RS_INVALID;
-        spilled := false;
-        regindex := 0;
-
-        // check whether and if so which and how (read/written) this instructions contains
-        // registers that must be spilled
-        for counter := 0 to ops-1 do
-          begin
-            case oper[counter]^.typ of
-              top_reg:
-                if (getregtype(oper[counter]^.reg) = R_INTREGISTER) then
-                  begin
-                    addreginfo(getsupreg(oper[counter]^.reg),spilling_get_operation_type(counter));
-                  end;
-              top_ref:
-                begin
-                  if (oper[counter]^.ref^.base <> NR_NO) then
-                    begin
-                      addreginfo(getsupreg(oper[counter]^.ref^.base),operand_read);
-                    end;
-                  if (oper[counter]^.ref^.index <> NR_NO) then
-                    begin
-                      addreginfo(getsupreg(oper[counter]^.ref^.index),operand_read);
-                    end;
-                end;
-            end;
-          end;
-
-        // generate the spilling code
-        if spilled then
-          begin
-            result := true;
-            for counter := 0 to pred(regindex) do
-              begin
-                if regs[counter].mustbespilled then
-                  begin
-                    supreg := regs[counter].orgreg;
-                    pos := get_insert_pos(Tai(previous),regs[0].orgreg,regs[1].orgreg,regs[2].orgreg,live_registers_int);
-                    rgget(list,pos,R_SUBWHOLE,regs[counter].newreg);
-                    if regs[counter].regread then
-                      if regs[counter].regwritten then
-                        DoSpillReadWritten(pos,counter)
-                      else
-                        DoSpillRead(pos,counter)
-                    else
-                      DoSpillWritten(pos,counter)
-                  end;
-              end;
-          end
-        else
-          exit;
-
-        // substitute registers
-        for counter := 0 to ops-1 do
-          begin
-            case oper[counter]^.typ of
-              top_reg:
-                begin
-                  tryreplacereg(oper[counter]^.reg);
-                end;
-              top_ref:
-                begin
-                  tryreplacereg(oper[counter]^.ref^.base);
-                  tryreplacereg(oper[counter]^.ref^.index);
-                end;
-            end;
-          end;
-      end;
-
-
 { ---------------------------------------------------------------------
     Miscellaneous methods.
   ---------------------------------------------------------------------}
@@ -2208,7 +1946,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.63  2003-12-28 16:20:09  jonas
+  Revision 1.64  2004-01-12 16:37:59  peter
+    * moved spilling code from taicpu to rg
+
+  Revision 1.63  2003/12/28 16:20:09  jonas
     - removed unused methods from old generic spilling code
 
   Revision 1.62  2003/12/26 14:02:30  peter

+ 422 - 204
compiler/rgobj.pas

@@ -205,7 +205,16 @@ unit rgobj;
         regtype           : Tregistertype;
         { default subregister used }
         defaultsub        : tsubregister;
+        live_registers:Tsuperregisterworklist;
+        function  get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
+        procedure forward_allocation(pfrom,pto:Tai);
+        procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
+        procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
         procedure add_constraints(reg:Tregister);virtual;
+        function instr_spill_register(list:Taasmoutput;
+                                      instr:taicpu_abstract;
+                                      const r:Tsuperregisterset;
+                                      const spilltemplist:Tspill_temp_list): boolean;virtual;
       private
         {# First imaginary register.}
         first_imaginary   : Tsuperregister;
@@ -228,7 +237,6 @@ unit rgobj;
         frozen_moves,
         coalesced_moves,
         constrained_moves : Tlinkedlist;
-        live_registers:Tsuperregisterworklist;
 {$ifdef EXTDEBUG}
         procedure writegraph(loopidx:longint);
 {$endif EXTDEBUG}
@@ -242,10 +250,8 @@ unit rgobj;
         procedure insert_regalloc_info(list:Taasmoutput;headertai:tai);
         procedure generate_interference_graph(list:Taasmoutput;headertai:tai);
         procedure translate_registers(list:Taasmoutput);
-        function  spill_registers(list:Taasmoutput;headertai:tai):boolean;
+        function  spill_registers(list:Taasmoutput;headertai:tai):boolean;virtual;
         function  getnewreg(subreg:tsubregister):tsuperregister;
-        procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
-        procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
         procedure add_edges_used(u:Tsuperregister);
         procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
         function move_related(n:Tsuperregister):boolean;
@@ -731,20 +737,21 @@ implementation
        assign it to any of the registers, thus it is significant.}
       for n:=first_imaginary to maxreg-1 do
         begin
-        if reginfo[n].adjlist=nil then
-          reginfo[n].degree:=0
-        else
-          reginfo[n].degree:=reginfo[n].adjlist^.length;
-        if reginfo[n].degree>=usable_registers_cnt then
-          spillworklist.add(n)
-        else if move_related(n) then
-          freezeworklist.add(n)
-        else
-          simplifyworklist.add(n);
-        end;
+          if reginfo[n].adjlist=nil then
+            reginfo[n].degree:=0
+          else
+            reginfo[n].degree:=reginfo[n].adjlist^.length;
+          if reginfo[n].degree>=usable_registers_cnt then
+            spillworklist.add(n)
+          else if move_related(n) then
+            freezeworklist.add(n)
+          else
+            simplifyworklist.add(n);
+	end;    
       sort_simplify_worklist;
     end;
 
+
     procedure trgobj.prepare_colouring;
 
     var i:word;
@@ -1189,7 +1196,7 @@ implementation
             include(used_in_proc,reginfo[k].colour);
         end;
 {$ifdef ra_debug}
-      if aktfilepos.line=51 then
+      if aktfilepos.line=179 then
         begin
           writeln('colourlist');
           for i:=0 to maxreg-1 do
@@ -1218,9 +1225,8 @@ implementation
     end;
 
     procedure trgobj.epilogue_colouring;
-
-    var i:Tsuperregister;
-
+    var
+      i : Tsuperregister;
     begin
       worklist_moves.clear;
       active_moves.destroy;
@@ -1358,248 +1364,460 @@ implementation
           only symbols. }
         live_registers.clear;
         p:=headertai;
+        while assigned(p) do
+          begin
+            if p.typ=ait_regalloc then
+              begin
+                if (getregtype(Tai_regalloc(p).reg)=regtype) then
+                  begin
+                    supreg:=getsupreg(Tai_regalloc(p).reg);
+                    if Tai_regalloc(p).allocation then
+                      live_registers.add(supreg)
+                    else
+                      live_registers.delete(supreg);
+                    add_edges_used(supreg);
+                    add_constraints(Tai_regalloc(p).reg);
+                  end;
+              end;
+            p:=Tai(p.next);
+          end;
+
+{$ifdef EXTDEBUG}
+        if live_registers.length>0 then
+          begin
+            for i:=0 to live_registers.length-1 do
+              begin
+                { Only report for imaginary registers }
+                if live_registers.buf^[i]>=first_imaginary then
+                  Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf^[i],defaultsub))+' not released');
+              end;
+          end;
+{$endif}
+      end;
+
+
+    procedure Trgobj.translate_registers(list:taasmoutput);
+      var
+        hp,p,q:Tai;
+        i:shortint;
+        r:Preference;
+{$ifdef arm}
+        so:pshifterop;
+{$endif arm}
+
+
+      begin
+        { Leave when no imaginary registers are used }
+        if maxreg<=first_imaginary then
+          exit;
+        p:=Tai(list.first);
         while assigned(p) do
           begin
             case p.typ of
               ait_regalloc:
                 begin
                   if (getregtype(Tai_regalloc(p).reg)=regtype) then
+                    setsupreg(Tai_regalloc(p).reg,reginfo[getsupreg(Tai_regalloc(p).reg)].colour);
+
+                  {
+                    Remove sequences of release and
+                    allocation of the same register like:
+
+                       # Register X released
+                       # Register X allocated
+                  }
+                  if assigned(p.previous) and
+                     (Tai(p.previous).typ=ait_regalloc) and
+                     (Tai_regalloc(p.previous).reg=Tai_regalloc(p).reg) and
+                     { allocation,deallocation or deallocation,allocation }
+                     (Tai_regalloc(p.previous).allocation xor Tai_regalloc(p).allocation) then
                     begin
-                      supreg:=getsupreg(Tai_regalloc(p).reg);
-                      if Tai_regalloc(p).allocation then
-                        live_registers.add(supreg)
-                      else
-                        live_registers.delete(supreg);
-                      add_edges_used(supreg);
-                      add_constraints(Tai_regalloc(p).reg);
+                      q:=Tai(p.next);
+                      hp:=tai(p.previous);
+                      list.remove(hp);
+                      hp.free;
+                      list.remove(p);
+                      p.free;
+                      p:=q;
+                      continue;
                     end;
                 end;
-{              ait_instruction:
+              ait_instruction:
                 begin
-                  aktfilepos:=Taicpu_abstract(p).fileinfo;
                   for i:=0 to Taicpu_abstract(p).ops-1 do
-                    with Taicpu_abstract(p).oper[i]^ do
-                      begin
-                        case typ of
-                          top_reg :
-                            begin
-                              add_edges_used(getsupreg(reg));
-                              add_constraints(reg);
-                            end;
-                          top_ref :
+                    case Taicpu_abstract(p).oper[i]^.typ of
+                      Top_reg:
+                         if (getregtype(Taicpu_abstract(p).oper[i]^.reg)=regtype) then
+                           setsupreg(Taicpu_abstract(p).oper[i]^.reg,reginfo[getsupreg(Taicpu_abstract(p).oper[i]^.reg)].colour);
+                      Top_ref:
+                        begin
+                          if regtype=R_INTREGISTER then
                             begin
-                              add_edges_used(getsupreg(ref^.base));
-                              add_constraints(ref^.base);
-                              add_edges_used(getsupreg(ref^.index));
-                              add_constraints(ref^.index);
+                              r:=Taicpu_abstract(p).oper[i]^.ref;
+                              if r^.base<>NR_NO then
+                                setsupreg(r^.base,reginfo[getsupreg(r^.base)].colour);
+                              if r^.index<>NR_NO then
+                                setsupreg(r^.index,reginfo[getsupreg(r^.index)].colour);
                             end;
                         end;
-                      end;
-                end; }
+{$ifdef arm}
+                      Top_shifterop:
+                        begin
+                          so:=Taicpu_abstract(p).oper[i]^.shifterop;
+                          if so^.rs<>NR_NO then
+                            setsupreg(so^.rs,reginfo[getsupreg(so^.rs)].colour);
+                        end;
+{$endif arm}
+                    end;
+
+                  { Maybe the operation can be removed when
+                    it is a move and both arguments are the same }
+                  if Taicpu_abstract(p).is_same_reg_move then
+                    begin
+                      q:=Tai(p.next);
+                      list.remove(p);
+                      p.free;
+                      p:=q;
+                      continue;
+                    end;
+                end;
             end;
             p:=Tai(p.next);
           end;
+      end;
 
-{$ifdef EXTDEBUG}
-        if live_registers.length>0 then
+
+    function trgobj.get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
+      var
+        back   : Tsuperregisterworklist;
+        supreg : tsuperregister;
+      begin
+        back.copyfrom(live_registers);
+        result:=p;
+        while (p<>nil) and (p.typ=ait_regalloc) do
           begin
-            for i:=0 to live_registers.length-1 do
+            supreg:=getsupreg(Tai_regalloc(p).reg);
+            {Rewind the register allocation.}
+            if Tai_regalloc(p).allocation then
+              live_registers.delete(supreg)
+            else
               begin
-                { Only report for imaginary registers }
-                if live_registers.buf^[i]>=first_imaginary then
-                  Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf^[i],defaultsub))+' not released');
+                live_registers.add(supreg);
+                if supreg=huntfor1 then
+                  begin
+                    get_insert_pos:=Tai(p.previous);
+                    back.done;
+                    back.copyfrom(live_registers);
+                  end;
+                if supreg=huntfor2 then
+                  begin
+                    get_insert_pos:=Tai(p.previous);
+                    back.done;
+                    back.copyfrom(live_registers);
+                  end;
+                if supreg=huntfor3 then
+                  begin
+                    get_insert_pos:=Tai(p.previous);
+                    back.done;
+                    back.copyfrom(live_registers);
+                  end;
               end;
+            p:=Tai(p.previous);
           end;
-{$endif}
+        live_registers.done;
+        live_registers.copyfrom(back);
       end;
 
 
-    function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
+    procedure trgobj.forward_allocation(pfrom,pto:Tai);
+      var
+        p : tai;
+      begin
+        {Forward the register allocation again.}
+        p:=pfrom;
+        while (p<>pto) do
+          begin
+            if p.typ<>ait_regalloc then
+              internalerror(200305311);
+            if Tai_regalloc(p).allocation then
+              live_registers.add(getsupreg(Tai_regalloc(p).reg))
+            else
+              live_registers.delete(getsupreg(Tai_regalloc(p).reg));
+            p:=Tai(p.next);
+          end;
+      end;
 
-    {Returns true if any help registers have been used.}
 
-    var i : word;
+    function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
+    { Returns true if any help registers have been used }
+      var
+        i : word;
         t : tsuperregister;
         p,q : Tai;
         regs_to_spill_set:Tsuperregisterset;
         spill_temps : ^Tspill_temp_list;
         supreg : tsuperregister;
         templist : taasmoutput;
+      begin
+        spill_registers:=false;
+        live_registers.clear;
+        for i:=first_imaginary to maxreg-1 do
+          exclude(reginfo[i].flags,ri_selected);
+        spill_temps:=allocmem(sizeof(treference)*maxreg);
+        supregset_reset(regs_to_spill_set,false);
+        { Allocate temps and insert in front of the list }
+        templist:=taasmoutput.create;
+        {Safe: this procedure is only called if there are spilled nodes.}
+        for i:=0 to spillednodes.length-1 do
+          begin
+            t:=spillednodes.buf^[i];
+            {Alternative representation.}
+            supregset_include(regs_to_spill_set,t);
+            {Clear all interferences of the spilled register.}
+            clear_interferences(t);
+            {Get a temp for the spilled register}
+            tg.gettemp(templist,4,tt_noreuse,spill_temps^[t]);
+          end;
+        list.insertlistafter(headertai,templist);
+        templist.free;
+        { Walk through all instructions, we can start with the headertai,
+          because before the header tai is only symbols }
+        p:=headertai;
+        while assigned(p) do
+          begin
+            case p.typ of
+              ait_regalloc:
+                begin
+                  if (getregtype(Tai_regalloc(p).reg)=regtype) then
+                    begin
+                      {A register allocation of a spilled register can be removed.}
+                      supreg:=getsupreg(Tai_regalloc(p).reg);
+                      if supregset_in(regs_to_spill_set,supreg) then
+                        begin
+                          q:=Tai(p.next);
+                          list.remove(p);
+                          p.free;
+                          p:=q;
+                          continue;
+                        end
+                      else
+                        if Tai_regalloc(p).allocation then
+                          live_registers.add(supreg)
+                        else
+                          live_registers.delete(supreg);
+                    end;
+                end;
+              ait_instruction:
+                begin
+                  aktfilepos:=Taicpu_abstract(p).fileinfo;
+                  if instr_spill_register(list,Taicpu_abstract(p),regs_to_spill_set,spill_temps^) then
+                    spill_registers:=true;
+                  if Taicpu_abstract(p).is_reg_move then
+                    add_move_instruction(Taicpu(p));
+                end;
+            end;
+            p:=Tai(p.next);
+          end;
+        aktfilepos:=current_procinfo.exitpos;
+        {Safe: this procedure is only called if there are spilled nodes.}
+        for i:=0 to spillednodes.length-1 do
+          tg.ungettemp(list,spill_temps^[spillednodes.buf^[i]]);
+        freemem(spill_temps);
+      end;
 
-    begin
-      spill_registers:=false;
-      live_registers.clear;
-      for i:=first_imaginary to maxreg-1 do
-        exclude(reginfo[i].flags,ri_selected);
-      spill_temps:=allocmem(sizeof(treference)*maxreg);
-      supregset_reset(regs_to_spill_set,false);
-      { Allocate temps and insert in front of the list }
-      templist:=taasmoutput.create;
-      {Safe: this procedure is only called if there are spilled nodes.}
-      for i:=0 to spillednodes.length-1 do
-        begin
-          t:=spillednodes.buf^[i];
-          {Alternative representation.}
-          supregset_include(regs_to_spill_set,t);
-          {Clear all interferences of the spilled register.}
-          clear_interferences(t);
-          {Get a temp for the spilled register}
-          tg.gettemp(templist,4,tt_noreuse,spill_temps^[t]);
+
+    function trgobj.instr_spill_register(list:Taasmoutput;
+                                         instr:taicpu_abstract;
+                                         const r:Tsuperregisterset;
+                                         const spilltemplist:Tspill_temp_list): boolean;
+      type
+        tspillreginfo = record
+          orgreg : tsuperregister;
+          tempreg : tregister;
+          regread,regwritten, mustbespilled: boolean;
         end;
-      list.insertlistafter(headertai,templist);
-      templist.free;
-      { Walk through all instructions, we can start with the headertai,
-        because before the header tai is only symbols }
-      p:=headertai;
-      while assigned(p) do
+      var
+        counter, regindex: longint;
+        pos: tai;
+        regs: array[0..2] of tspillreginfo;
+        spilled: boolean;
+
+
+      procedure DoSpillRead(pos: tai; regidx: longint);
+        var
+          helpins: tai;
         begin
-          case p.typ of
-            ait_regalloc:
-              begin
-                if (getregtype(Tai_regalloc(p).reg)=regtype) then
-                  begin
-                    {A register allocation of a spilled register can be removed.}
-                    supreg:=getsupreg(Tai_regalloc(p).reg);
-                    if supregset_in(regs_to_spill_set,supreg) then
-                      begin
-                        q:=Tai(p.next);
-                        list.remove(p);
-                        p.free;
-                        p:=q;
-                        continue;
-                      end
-                    else
-                      if Tai_regalloc(p).allocation then
-                        live_registers.add(supreg)
-                      else
-                        live_registers.delete(supreg);
-                  end;
-              end;
-            ait_instruction:
-              begin
-                aktfilepos:=Taicpu_abstract(p).fileinfo;
-                if Taicpu_abstract(p).spill_registers(list,
-                                                      regtype,
-                                                      @getregisterinline,
-                                                      @ungetregisterinline,
-                                                      regs_to_spill_set,
-                                                      live_registers,
-                                                      spill_temps^) then
-                  spill_registers:=true;
-                if Taicpu_abstract(p).is_reg_move then
-                  add_move_instruction(Taicpu(p));
-              end;
-          end;
-          p:=Tai(p.next);
+          helpins:=instr.spilling_create_load(spilltemplist[regs[regidx].orgreg],regs[regidx].tempreg);
+          if pos=nil then
+            list.insertafter(helpins,list.first)
+          else
+            list.insertafter(helpins,pos.next);
+          ungetregisterinline(list,instr,regs[regidx].tempreg);
+          forward_allocation(tai(helpins.next),instr);
         end;
-      aktfilepos:=current_procinfo.exitpos;
-      {Safe: this procedure is only called if there are spilled nodes.}
-      for i:=0 to spillednodes.length-1 do
-        tg.ungettemp(list,spill_temps^[spillednodes.buf^[i]]);
-      freemem(spill_temps);
-    end;
 
 
-    procedure Trgobj.translate_registers(list:taasmoutput);
+      procedure DoSpillWritten(pos: tai; regidx: longint);
+        var
+          helpins: tai;
+        begin
+          helpins:=instr.spilling_create_store(regs[regidx].tempreg,spilltemplist[regs[regidx].orgreg]);
+          list.insertafter(helpins,instr);
+          ungetregisterinline(list,helpins,regs[regidx].tempreg);
+        end;
 
-    var hp,p,q:Tai;
-        i:shortint;
-        r:Preference;
-{$ifdef arm}
-        so:pshifterop;
-{$endif arm}
+
+      procedure DoSpillReadWritten(pos: tai; regidx: longint);
+        var
+          helpins1, helpins2: tai;
+        begin
+          helpins1:=instr.spilling_create_load(spilltemplist[regs[regidx].orgreg],regs[regidx].tempreg);
+          if pos=nil then
+            list.insertafter(helpins1,list.first)
+          else
+            list.insertafter(helpins1,pos.next);
+          helpins2:=instr.spilling_create_store(regs[regidx].tempreg,spilltemplist[regs[regidx].orgreg]);
+          list.insertafter(helpins2,instr);
+          ungetregisterinline(list,helpins2,regs[regidx].tempreg);
+          forward_allocation(tai(helpins1.next),instr);
+        end;
 
 
-    begin
-      { Leave when no imaginary registers are used }
-      if maxreg<=first_imaginary then
-        exit;
-      p:=Tai(list.first);
-      while assigned(p) do
+      procedure addreginfo(reg: tsuperregister; operation: topertype);
+        var
+          i, tmpindex: longint;
         begin
-          case p.typ of
-            ait_regalloc:
+          tmpindex := regindex;
+          // did we already encounter this register?
+          for i := 0 to pred(regindex) do
+            if (regs[i].orgreg = reg) then
               begin
-                if (getregtype(Tai_regalloc(p).reg)=regtype) then
-                  setsupreg(Tai_regalloc(p).reg,reginfo[getsupreg(Tai_regalloc(p).reg)].colour);
-
-                {
-                  Remove sequences of release and
-                  allocation of the same register like:
-
-                     # Register X released
-                     # Register X allocated
-                }
-                if assigned(p.previous) and
-                   (Tai(p.previous).typ=ait_regalloc) and
-                   (Tai_regalloc(p.previous).reg=Tai_regalloc(p).reg) and
-                   { allocation,deallocation or deallocation,allocation }
-                   (Tai_regalloc(p.previous).allocation xor Tai_regalloc(p).allocation) then
+                tmpindex := i;
+                break;
+              end;
+          if tmpindex > high(regs) then
+            internalerror(2003120301);
+          regs[tmpindex].orgreg := reg;
+          if supregset_in(r,reg) then
+            begin
+              // add/update info on this register
+              regs[tmpindex].mustbespilled := true;
+              case operation of
+                operand_read:
+                  regs[tmpindex].regread := true;
+                operand_write:
+                  regs[tmpindex].regwritten := true;
+                operand_readwrite:
                   begin
-                    q:=Tai(p.next);
-                    hp:=tai(p.previous);
-                    list.remove(hp);
-                    hp.free;
-                    list.remove(p);
-                    p.free;
-                    p:=q;
-                    continue;
+                    regs[tmpindex].regread := true;
+                    regs[tmpindex].regwritten := true;
                   end;
               end;
-            ait_instruction:
-              begin
-                for i:=0 to Taicpu_abstract(p).ops-1 do
-                  case Taicpu_abstract(p).oper[i]^.typ of
-                    Top_reg:
-                       if (getregtype(Taicpu_abstract(p).oper[i]^.reg)=regtype) then
-                         setsupreg(Taicpu_abstract(p).oper[i]^.reg,reginfo[getsupreg(Taicpu_abstract(p).oper[i]^.reg)].colour);
-                    Top_ref:
-                      begin
-                        if regtype=R_INTREGISTER then
-                          begin
-                            r:=Taicpu_abstract(p).oper[i]^.ref;
-                            if r^.base<>NR_NO then
-                              setsupreg(r^.base,reginfo[getsupreg(r^.base)].colour);
-                            if r^.index<>NR_NO then
-                              setsupreg(r^.index,reginfo[getsupreg(r^.index)].colour);
-                          end;
-                      end;
-{$ifdef arm}
-                    Top_shifterop:
-                      begin
-                        so:=Taicpu_abstract(p).oper[i]^.shifterop;
-                        if so^.rs<>NR_NO then
-                          setsupreg(so^.rs,reginfo[getsupreg(so^.rs)].colour);
-                      end;
-{$endif arm}
-                  end;
+              spilled := true;
+            end;
+          inc(regindex,ord(regindex=tmpindex));
+        end;
 
-                { Maybe the operation can be removed when
-                  it is a move and both arguments are the same }
-                if Taicpu_abstract(p).is_same_reg_move then
+
+      procedure tryreplacereg(var reg: tregister);
+        var
+          i: longint;
+          supreg: tsuperregister;
+        begin
+          if (getregtype(reg) = R_INTREGISTER) then
+            begin
+              supreg := getsupreg(reg);
+              for i := 0 to pred(regindex) do
+                if (regs[i].mustbespilled) and
+                   (regs[i].orgreg = supreg) then
                   begin
-                    q:=Tai(p.next);
-                    list.remove(p);
-                    p.free;
-                    p:=q;
-                    continue;
+                    reg := regs[i].tempreg;
+                    break;
                   end;
+            end;
+        end;
+
+
+      begin
+        result := false;
+        fillchar(regs,sizeof(regs),0);
+        for counter := low(regs) to high(regs) do
+          regs[counter].orgreg := RS_INVALID;
+        spilled := false;
+        regindex := 0;
+
+        { check whether and if so which and how (read/written) this instructions contains
+          registers that must be spilled }
+        for counter := 0 to instr.ops-1 do
+         with instr.oper[counter]^ do
+          begin
+            case typ of
+              top_reg:
+                begin
+                  if (getregtype(reg) = regtype) then
+                    addreginfo(getsupreg(reg),instr.spilling_get_operation_type(counter));
+                end;
+              top_ref:
+                begin
+                  if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+                    begin
+                      if (ref^.base <> NR_NO) then
+                        addreginfo(getsupreg(ref^.base),operand_read);
+                      if (ref^.index <> NR_NO) then
+                        addreginfo(getsupreg(ref^.index),operand_read);
+                    end;
+                end;
+            end;
+          end;
+
+        { if no spilling for this instruction we can leave }
+        if not spilled then
+          exit;
+
+        { generate the spilling code }
+        result := true;
+        for counter := 0 to pred(regindex) do
+          begin
+            if regs[counter].mustbespilled then
+              begin
+                pos := get_insert_pos(Tai(instr.previous),regs[0].orgreg,regs[1].orgreg,regs[2].orgreg);
+                getregisterinline(list,pos,defaultsub,regs[counter].tempreg);
+                if regs[counter].regread then
+                  if regs[counter].regwritten then
+                    DoSpillReadWritten(pos,counter)
+                  else
+                    DoSpillRead(pos,counter)
+                else
+                  DoSpillWritten(pos,counter)
               end;
           end;
-          p:=Tai(p.next);
-        end;
-    end;
+
+        { substitute registers }
+        for counter := 0 to instr.ops-1 do
+         with instr.oper[counter]^ do
+          begin
+            case typ of
+              top_reg:
+                begin
+                  tryreplacereg(reg);
+                end;
+              top_ref:
+                begin
+                  tryreplacereg(ref^.base);
+                  tryreplacereg(ref^.index);
+                end;
+            end;
+          end;
+      end;
+
+
 
 
 end.
 {
   $Log$
-  Revision 1.111  2004-01-11 13:21:35  daniel
-    * Register allocation bug fixed
-
-  Revision 1.110  2004/01/09 22:02:29  daniel
-    * Degree=0 problem fixed
-    * Degree to high problem fixed
+  Revision 1.112  2004-01-12 16:37:59  peter
+    * moved spilling code from taicpu to rg
 
   Revision 1.109  2003/12/26 14:02:30  peter
     * sparc updates

+ 4 - 387
compiler/x86/aasmcpu.pas

@@ -202,14 +202,6 @@ interface
          procedure SetOperandOrder(order:TOperandOrder);
          function is_same_reg_move:boolean;override;
          function is_reg_move:boolean;override;
-         function spill_registers(list:Taasmoutput;
-                                  rt:Tregistertype;
-                                  rgget:Trggetproc;
-                                  rgunget:Trgungetproc;
-                                  const r:Tsuperregisterset;
-{                                  var unusedregsint:Tsuperregisterset;}
-                                  var live_registers_int:Tsuperregisterworklist;
-                                  const spilltemplist:Tspill_temp_list):boolean;override;
       protected
          procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
          procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
@@ -1930,384 +1922,6 @@ implementation
       end;
 
 
-    function Taicpu.spill_registers(list:Taasmoutput;
-                                    rt:Tregistertype;
-                                    rgget:Trggetproc;
-                                    rgunget:Trgungetproc;
-                                    const r:Tsuperregisterset;
-                                    var live_registers_int:Tsuperregisterworklist;
-                                    const spilltemplist:Tspill_temp_list):boolean;
-
-    {Spill the registers in r in this instruction. Returns true if any help
-     registers are used. This procedure has become one big hack party, because
-     of the huge amount of situations you can have. The irregularity of the i386
-     instruction set doesn't help either. (DM)}
-
-
-    var i:byte;
-        supreg:Tsuperregister;
-        subreg:Tsubregister;
-        helpreg:Tregister;
-        helpins:Taicpu;
-        op:Tasmop;
-        hopsize:Topsize;
-        pos:Tai;
-
-    begin
-      {Situation examples are in intel notation, so operand order:
-       mov    eax       ,    ebx
-              ^^^            ^^^
-              oper[1]        oper[0]
-      (DM)}
-      spill_registers:=false;
-      case ops of
-        1:
-          begin
-            if (oper[0]^.typ=top_reg) and
-               (getregtype(oper[0]^.reg)=rt) then
-              begin
-                supreg:=getsupreg(oper[0]^.reg);
-                if supregset_in(r,supreg) then
-                  begin
-                    {Situation example:
-                     push r20d              ; r20d must be spilled into [ebp-12]
-
-                    Change into:
-                     push [ebp-12]          ; Replace register by reference }
-{                    hopsize:=reg2opsize(oper[0].reg);}
-                    oper[0]^.typ:=top_ref;
-                    new(oper[0]^.ref);
-                    oper[0]^.ref^:=spilltemplist[supreg];
-{                    oper[0]^.ref^.size:=hopsize;}
-                  end;
-              end;
-            if oper[0]^.typ=top_ref then
-              begin
-                supreg:=getsupreg(oper[0]^.ref^.base);
-                if supregset_in(r,supreg) then
-                  begin
-                    {Situation example:
-                     push [r21d+4*r22d]        ; r21d must be spilled into [ebp-12]
-
-                     Change into:
-
-                     mov r23d,[ebp-12]         ; Use a help register
-                     push [r23d+4*r22d]        ; Replace register by helpregister }
-                    subreg:=getsubreg(oper[0]^.ref^.base);
-                    if oper[0]^.ref^.index=NR_NO then
-                      pos:=Tai(previous)
-                    else
-                      pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.index),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
-                    rgget(list,pos,subreg,helpreg);
-                    spill_registers:=true;
-                    helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.base),spilltemplist[supreg],helpreg);
-                    if pos=nil then
-                      list.insertafter(helpins,list.first)
-                    else
-                      list.insertafter(helpins,pos.next);
-                    rgunget(list,helpins,helpreg);
-                    forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
-                    oper[0]^.ref^.base:=helpreg;
-                  end;
-                supreg:=getsupreg(oper[0]^.ref^.index);
-                if supregset_in(r,supreg) then
-                  begin
-                    {Situation example:
-                     push [r21d+4*r22d]        ; r22d must be spilled into [ebp-12]
-
-                     Change into:
-
-                     mov r23d,[ebp-12]         ; Use a help register
-                     push [r21d+4*r23d]        ; Replace register by helpregister }
-                    subreg:=getsubreg(oper[0]^.ref^.index);
-                    if oper[0]^.ref^.base=NR_NO then
-                      pos:=Tai(previous)
-                    else
-                      pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.base),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
-                    rgget(list,pos,subreg,helpreg);
-                    spill_registers:=true;
-                    helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.index),spilltemplist[supreg],helpreg);
-                    if pos=nil then
-                      list.insertafter(helpins,list.first)
-                    else
-                      list.insertafter(helpins,pos.next);
-                    rgunget(list,helpins,helpreg);
-                    forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
-                    oper[0]^.ref^.index:=helpreg;
-                  end;
-                end;
-          end;
-        2:
-          begin
-            { First spill the registers from the references. This is
-              required because the reference can be moved from this instruction
-              to a MOV instruction when spilling of the register operand is done }
-            for i:=0 to 1 do
-              if oper[i]^.typ=top_ref then
-                begin
-                  supreg:=getsupreg(oper[i]^.ref^.base);
-                  if supregset_in(r,supreg) then
-                    begin
-                      {Situation example:
-                       add r20d,[r21d+4*r22d]    ; r21d must be spilled into [ebp-12]
-
-                       Change into:
-
-                       mov r23d,[ebp-12]         ; Use a help register
-                       add r20d,[r23d+4*r22d]    ; Replace register by helpregister }
-                      subreg:=getsubreg(oper[i]^.ref^.base);
-                      if i=1 then
-                        pos:=get_insert_pos(Tai(previous),getsupreg(oper[i]^.ref^.index),getsupreg(oper[0]^.reg),
-                                            RS_INVALID,{unusedregsint}live_registers_int)
-                      else
-                        pos:=get_insert_pos(Tai(previous),getsupreg(oper[i]^.ref^.index),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
-                      rgget(list,pos,subreg,helpreg);
-                      spill_registers:=true;
-                      helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.base),spilltemplist[supreg],helpreg);
-                      if pos=nil then
-                        list.insertafter(helpins,list.first)
-                      else
-                        list.insertafter(helpins,pos.next);
-                      oper[i]^.ref^.base:=helpreg;
-                      rgunget(list,helpins,helpreg);
-                      forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
-                  end;
-                  supreg:=getsupreg(oper[i]^.ref^.index);
-                  if supregset_in(r,supreg) then
-                    begin
-                      {Situation example:
-                       add r20d,[r21d+4*r22d]    ; r22d must be spilled into [ebp-12]
-
-                       Change into:
-
-                       mov r23d,[ebp-12]         ; Use a help register
-                       add r20d,[r21d+4*r23d]    ; Replace register by helpregister }
-                      subreg:=getsubreg(oper[i]^.ref^.index);
-                      if i=1 then
-                        pos:=get_insert_pos(Tai(previous),getsupreg(oper[i]^.ref^.base),getsupreg(oper[0]^.reg),
-                                            RS_INVALID,{unusedregsint}live_registers_int)
-                      else
-                        pos:=get_insert_pos(Tai(previous),getsupreg(oper[i]^.ref^.base),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
-                      rgget(list,pos,subreg,helpreg);
-                      spill_registers:=true;
-                      helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.index),spilltemplist[supreg],helpreg);
-                      if pos=nil then
-                        list.insertafter(helpins,list.first)
-                      else
-                        list.insertafter(helpins,pos.next);
-                      oper[i]^.ref^.index:=helpreg;
-                      rgunget(list,helpins,helpreg);
-                      forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
-                    end;
-                end;
-            if (oper[0]^.typ=top_reg) and
-               (getregtype(oper[0]^.reg)=rt) then
-              begin
-                supreg:=getsupreg(oper[0]^.reg);
-                subreg:=getsubreg(oper[0]^.reg);
-                if supregset_in(r,supreg) then
-                  if oper[1]^.typ=top_ref then
-                    begin
-                      {Situation example:
-                       add [r20d],r21d      ; r21d must be spilled into [ebp-12]
-
-                       Change into:
-
-                       mov r22d,[ebp-12]    ; Use a help register
-                       add [r20d],r22d      ; Replace register by helpregister }
-                      pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.reg),
-                                          getsupreg(oper[1]^.ref^.base),getsupreg(oper[1]^.ref^.index),
-                                          {unusedregsint}live_registers_int);
-                      rgget(list,pos,subreg,helpreg);
-                      spill_registers:=true;
-                      helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.reg),spilltemplist[supreg],helpreg);
-                      if pos=nil then
-                        list.insertafter(helpins,list.first)
-                      else
-                        list.insertafter(helpins,pos.next);
-                      oper[0]^.reg:=helpreg;
-                      rgunget(list,helpins,helpreg);
-                      forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
-                    end
-                  else
-                    begin
-                      {Situation example:
-                       add r20d,r21d        ; r21d must be spilled into [ebp-12]
-
-                       Change into:
-
-                       add r20d,[ebp-12]    ; Replace register by reference }
-                      oper[0]^.typ:=top_ref;
-                      new(oper[0]^.ref);
-                      oper[0]^.ref^:=spilltemplist[supreg];
-                    end;
-              end;
-            if (oper[1]^.typ=top_reg) and
-               (getregtype(oper[1]^.reg)=rt) then
-              begin
-                supreg:=getsupreg(oper[1]^.reg);
-                subreg:=getsubreg(oper[1]^.reg);
-                if supregset_in(r,supreg) then
-                  begin
-                    if oper[0]^.typ=top_ref then
-                      begin
-                        {Situation example:
-                         add r20d,[r21d]      ; r20d must be spilled into [ebp-12]
-
-                         Change into:
-
-                         mov r22d,[r21d]      ; Use a help register
-                         add [ebp-12],r22d    ; Replace register by helpregister }
-                        pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.base),
-                                            getsupreg(oper[0]^.ref^.index),RS_INVALID,{unusedregsint}live_registers_int);
-                        rgget(list,pos,subreg,helpreg);
-                        spill_registers:=true;
-                        op:=A_MOV;
-                        hopsize:=opsize;  {Save old value...}
-                        if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
-                          begin
-                            {Because 'movzx memory,register' does not exist...}
-                            op:=opcode;
-                            opcode:=A_MOV;
-                            opsize:=reg2opsize(oper[1]^.reg);
-                          end;
-                        helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0]^.ref^,helpreg);
-                        if pos=nil then
-                          list.insertafter(helpins,list.first)
-                        else
-                          list.insertafter(helpins,pos.next);
-                        dispose(oper[0]^.ref);
-                        oper[0]^.typ:=top_reg;
-                        oper[0]^.reg:=helpreg;
-                        oper[1]^.typ:=top_ref;
-                        new(oper[1]^.ref);
-                        oper[1]^.ref^:=spilltemplist[supreg];
-                        rgunget(list,helpins,helpreg);
-                        forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
-                      end
-                    else
-                      begin
-                        {Situation example:
-                         add r20d,r21d        ; r20d must be spilled into [ebp-12]
-
-                         Change into:
-
-                         add [ebp-12],r21d    ; Replace register by reference }
-                        if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
-                          begin
-                            {Because 'movzx memory,register' does not exist...}
-                            spill_registers:=true;
-                            op:=opcode;
-                            hopsize:=opsize;
-                            opcode:=A_MOV;
-                            opsize:=reg2opsize(oper[1]^.reg);
-                            pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.reg),RS_INVALID,RS_INVALID,{unusedregsint}live_registers_int);
-                            rgget(list,pos,subreg,helpreg);
-                            helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0]^.reg,helpreg);
-                            if pos=nil then
-                              list.insertafter(helpins,list.first)
-                            else
-                              list.insertafter(helpins,pos.next);
-                            oper[0]^.reg:=helpreg;
-                            rgunget(list,helpins,helpreg);
-                            forward_allocation(Tai(helpins.next),{unusedregsint}live_registers_int);
-                          end;
-                        oper[1]^.typ:=top_ref;
-                        new(oper[1]^.ref);
-                        oper[1]^.ref^:=spilltemplist[supreg];
-                      end;
-                  end;
-              end;
-
-            { The i386 instruction set never gets boring...
-              some opcodes do not support a memory location as destination }
-            if (oper[1]^.typ=top_ref) and
-               (
-                (oper[0]^.typ=top_const) or
-                ((oper[0]^.typ=top_reg) and
-                 (getregtype(oper[0]^.reg)=rt))
-               ) then
-              begin
-                case opcode of
-                  A_IMUL :
-                    begin
-                      {Yikes! We just changed the destination register into
-                       a memory location above here.
-
-                       Situation examples:
-
-                       imul [ebp-12],r21d    ; We need a help register
-                       imul [ebp-12],<const> ; We need a help register
-
-                       Change into:
-
-                       mov r22d,[ebp-12]    ; Use a help instruction (only for IMUL)
-                       imul r22d,r21d       ; Replace reference by helpregister
-                       mov [ebp-12],r22d    ; Use another help instruction}
-                      rgget(list,Tai(previous),subreg,helpreg);
-                      spill_registers:=true;
-                      {First help instruction.}
-                      helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1]^.ref^,helpreg);
-                      if previous=nil then
-                        list.insert(helpins)
-                      else
-                        list.insertafter(helpins,previous);
-                      {Second help instruction.}
-                      helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1]^.ref^);
-                      dispose(oper[1]^.ref);
-                      oper[1]^.typ:=top_reg;
-                      oper[1]^.reg:=helpreg;
-                      list.insertafter(helpins,self);
-                      rgunget(list,self,helpreg);
-                    end;
-                end;
-              end;
-
-            { The i386 instruction set never gets boring...
-              some opcodes do not support a memory location as source }
-            if (oper[0]^.typ=top_ref) and
-               (oper[1]^.typ=top_reg) and
-               (getregtype(oper[1]^.reg)=rt) then
-              begin
-                case opcode of
-                  A_BT,A_BTS,
-                  A_BTC,A_BTR :
-                    begin
-                      {Yikes! We just changed the source register into
-                       a memory location above here.
-
-                       Situation example:
-
-                       bt  r21d,[ebp-12]   ; We need a help register
-
-                       Change into:
-
-                       mov r22d,[ebp-12]    ; Use a help instruction (only for IMUL)
-                       bt  r21d,r22d        ; Replace reference by helpregister}
-                      rgget(list,Tai(previous),subreg,helpreg);
-                      spill_registers:=true;
-                      {First help instruction.}
-                      helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[0]^.ref^,helpreg);
-                      if previous=nil then
-                        list.insert(helpins)
-                      else
-                        list.insertafter(helpins,previous);
-                      dispose(oper[0]^.ref);
-                      oper[0]^.typ:=top_reg;
-                      oper[0]^.reg:=helpreg;
-                      rgunget(list,helpins,helpreg);
-                    end;
-                end;
-              end;
-          end;
-        3:
-          begin
-            {$warning todo!!}
-          end;
-      end;
-    end;
-
-
 {*****************************************************************************
                               Instruction table
 *****************************************************************************}
@@ -2357,7 +1971,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.43  2003-12-26 14:02:30  peter
+  Revision 1.44  2004-01-12 16:37:59  peter
+    * moved spilling code from taicpu to rg
+
+  Revision 1.43  2003/12/26 14:02:30  peter
     * sparc updates
     * use registertype in spill_register
 

+ 5 - 2
compiler/x86/cpubase.pas

@@ -433,7 +433,7 @@ implementation
     function reg2opsize(r:Tregister):topsize;
       const
         subreg2opsize : array[tsubregister] of topsize =
-          (S_NO,S_B,S_B,S_W,S_L,S_D,S_NO);
+          (S_NO,S_B,S_B,S_W,S_L,S_D,S_NO,S_NO);
       begin
         reg2opsize:=S_L;
         case getregtype(r) of
@@ -535,7 +535,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.34  2003-12-26 13:19:16  florian
+  Revision 1.35  2004-01-12 16:37:59  peter
+    * moved spilling code from taicpu to rg
+
+  Revision 1.34  2003/12/26 13:19:16  florian
     * rtl and compiler compile with -Cfsse2
 
   Revision 1.33  2003/12/25 01:07:09  florian

+ 393 - 3
compiler/x86/rgx86.pas

@@ -35,6 +35,13 @@ unit rgx86;
       cclasses,globtype,cgbase,rgobj;
 
     type
+       trgx86 = class(trgobj)
+         function instr_spill_register(list:Taasmoutput;
+                                       instr:taicpu_abstract;
+                                       const r:Tsuperregisterset;
+                                       const spilltemplist:Tspill_temp_list): boolean;override;
+       end;
+
        tpushedsavedloc = record
          case byte of
            0: (pushed: boolean);
@@ -88,7 +95,8 @@ implementation
 
     uses
        systems,
-       verbose;
+       verbose,
+       aasmcpu;
 
     const
        { This value is used in tsaved. If the array value is equal
@@ -97,7 +105,386 @@ implementation
 
 
 {******************************************************************************
-                                    Trgobj
+                                    Trgcpu
+******************************************************************************}
+
+    function trgx86.instr_spill_register(list:Taasmoutput;
+                                         instr:taicpu_abstract;
+                                         const r:Tsuperregisterset;
+                                         const spilltemplist:Tspill_temp_list): boolean;
+    {
+      Spill the registers in r in this instruction. Returns true if any help
+      registers are used. This procedure has become one big hack party, because
+      of the huge amount of situations you can have. The irregularity of the i386
+      instruction set doesn't help either. (DM)
+    }
+    var i:byte;
+        supreg:Tsuperregister;
+        subreg:Tsubregister;
+        helpreg:Tregister;
+        helpins:Taicpu;
+        op:Tasmop;
+        hopsize:Topsize;
+        pos:Tai;
+
+    begin
+      {Situation examples are in intel notation, so operand order:
+       mov    eax       ,    ebx
+              ^^^            ^^^
+              oper[1]        oper[0]
+      (DM)}
+      result:=false;
+      with taicpu(instr) do
+       begin
+         case ops of
+           1:
+             begin
+               if (oper[0]^.typ=top_reg) and
+                  (getregtype(oper[0]^.reg)=regtype) then
+                 begin
+                   supreg:=getsupreg(oper[0]^.reg);
+                   if supregset_in(r,supreg) then
+                     begin
+                       {Situation example:
+                        push r20d              ; r20d must be spilled into [ebp-12]
+
+                       Change into:
+                        push [ebp-12]          ; Replace register by reference }
+   {                    hopsize:=reg2opsize(oper[0].reg);}
+                       oper[0]^.typ:=top_ref;
+                       new(oper[0]^.ref);
+                       oper[0]^.ref^:=spilltemplist[supreg];
+   {                    oper[0]^.ref^.size:=hopsize;}
+                     end;
+                 end;
+               if oper[0]^.typ=top_ref then
+                 begin
+                   supreg:=getsupreg(oper[0]^.ref^.base);
+                   if supregset_in(r,supreg) then
+                     begin
+                       {Situation example:
+                        push [r21d+4*r22d]        ; r21d must be spilled into [ebp-12]
+
+                        Change into:
+
+                        mov r23d,[ebp-12]         ; Use a help register
+                        push [r23d+4*r22d]        ; Replace register by helpregister }
+                       subreg:=getsubreg(oper[0]^.ref^.base);
+                       if oper[0]^.ref^.index=NR_NO then
+                         pos:=Tai(previous)
+                       else
+                         pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.index),RS_INVALID,RS_INVALID);
+                       getregisterinline(list,pos,subreg,helpreg);
+                       result:=true;
+                       helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.base),spilltemplist[supreg],helpreg);
+                       if pos=nil then
+                         list.insertafter(helpins,list.first)
+                       else
+                         list.insertafter(helpins,pos.next);
+                       ungetregisterinline(list,helpins,helpreg);
+                       forward_allocation(Tai(helpins.next),instr);
+                       oper[0]^.ref^.base:=helpreg;
+                     end;
+                   supreg:=getsupreg(oper[0]^.ref^.index);
+                   if supregset_in(r,supreg) then
+                     begin
+                       {Situation example:
+                        push [r21d+4*r22d]        ; r22d must be spilled into [ebp-12]
+
+                        Change into:
+
+                        mov r23d,[ebp-12]         ; Use a help register
+                        push [r21d+4*r23d]        ; Replace register by helpregister }
+                       subreg:=getsubreg(oper[0]^.ref^.index);
+                       if oper[0]^.ref^.base=NR_NO then
+                         pos:=Tai(instr.previous)
+                       else
+                         pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),RS_INVALID,RS_INVALID);
+                       getregisterinline(list,pos,subreg,helpreg);
+                       result:=true;
+                       helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.index),spilltemplist[supreg],helpreg);
+                       if pos=nil then
+                         list.insertafter(helpins,list.first)
+                       else
+                         list.insertafter(helpins,pos.next);
+                       ungetregisterinline(list,helpins,helpreg);
+                       forward_allocation(Tai(helpins.next),instr);
+                       oper[0]^.ref^.index:=helpreg;
+                     end;
+                   end;
+             end;
+           2:
+             begin
+               { First spill the registers from the references. This is
+                 required because the reference can be moved from this instruction
+                 to a MOV instruction when spilling of the register operand is done }
+               for i:=0 to 1 do
+                 if oper[i]^.typ=top_ref then
+                   begin
+                     supreg:=getsupreg(oper[i]^.ref^.base);
+                     if supregset_in(r,supreg) then
+                       begin
+                         {Situation example:
+                          add r20d,[r21d+4*r22d]    ; r21d must be spilled into [ebp-12]
+
+                          Change into:
+
+                          mov r23d,[ebp-12]         ; Use a help register
+                          add r20d,[r23d+4*r22d]    ; Replace register by helpregister }
+                         subreg:=getsubreg(oper[i]^.ref^.base);
+                         if i=1 then
+                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),getsupreg(oper[0]^.reg),RS_INVALID)
+                         else
+                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),RS_INVALID,RS_INVALID);
+                         getregisterinline(list,pos,subreg,helpreg);
+                         result:=true;
+                         helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.base),spilltemplist[supreg],helpreg);
+                         if pos=nil then
+                           list.insertafter(helpins,list.first)
+                         else
+                           list.insertafter(helpins,pos.next);
+                         oper[i]^.ref^.base:=helpreg;
+                         ungetregisterinline(list,helpins,helpreg);
+                         forward_allocation(Tai(helpins.next),instr);
+                     end;
+                     supreg:=getsupreg(oper[i]^.ref^.index);
+                     if supregset_in(r,supreg) then
+                       begin
+                         {Situation example:
+                          add r20d,[r21d+4*r22d]    ; r22d must be spilled into [ebp-12]
+
+                          Change into:
+
+                          mov r23d,[ebp-12]         ; Use a help register
+                          add r20d,[r21d+4*r23d]    ; Replace register by helpregister }
+                         subreg:=getsubreg(oper[i]^.ref^.index);
+                         if i=1 then
+                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),
+                                               getsupreg(oper[0]^.reg),RS_INVALID)
+                         else
+                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),RS_INVALID,RS_INVALID);
+                         getregisterinline(list,pos,subreg,helpreg);
+                         result:=true;
+                         helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.index),spilltemplist[supreg],helpreg);
+                         if pos=nil then
+                           list.insertafter(helpins,list.first)
+                         else
+                           list.insertafter(helpins,pos.next);
+                         oper[i]^.ref^.index:=helpreg;
+                         ungetregisterinline(list,helpins,helpreg);
+                         forward_allocation(Tai(helpins.next),instr);
+                       end;
+                   end;
+               if (oper[0]^.typ=top_reg) and
+                  (getregtype(oper[0]^.reg)=regtype) then
+                 begin
+                   supreg:=getsupreg(oper[0]^.reg);
+                   subreg:=getsubreg(oper[0]^.reg);
+                   if supregset_in(r,supreg) then
+                     if oper[1]^.typ=top_ref then
+                       begin
+                         {Situation example:
+                          add [r20d],r21d      ; r21d must be spilled into [ebp-12]
+
+                          Change into:
+
+                          mov r22d,[ebp-12]    ; Use a help register
+                          add [r20d],r22d      ; Replace register by helpregister }
+                         pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),
+                                             getsupreg(oper[1]^.ref^.base),getsupreg(oper[1]^.ref^.index));
+                         getregisterinline(list,pos,subreg,helpreg);
+                         result:=true;
+                         helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.reg),spilltemplist[supreg],helpreg);
+                         if pos=nil then
+                           list.insertafter(helpins,list.first)
+                         else
+                           list.insertafter(helpins,pos.next);
+                         oper[0]^.reg:=helpreg;
+                         ungetregisterinline(list,helpins,helpreg);
+                         forward_allocation(Tai(helpins.next),instr);
+                       end
+                     else
+                       begin
+                         {Situation example:
+                          add r20d,r21d        ; r21d must be spilled into [ebp-12]
+
+                          Change into:
+
+                          add r20d,[ebp-12]    ; Replace register by reference }
+                         oper[0]^.typ:=top_ref;
+                         new(oper[0]^.ref);
+                         oper[0]^.ref^:=spilltemplist[supreg];
+                       end;
+                 end;
+               if (oper[1]^.typ=top_reg) and
+                  (getregtype(oper[1]^.reg)=regtype) then
+                 begin
+                   supreg:=getsupreg(oper[1]^.reg);
+                   subreg:=getsubreg(oper[1]^.reg);
+                   if supregset_in(r,supreg) then
+                     begin
+                       if oper[0]^.typ=top_ref then
+                         begin
+                           {Situation example:
+                            add r20d,[r21d]      ; r20d must be spilled into [ebp-12]
+
+                            Change into:
+
+                            mov r22d,[r21d]      ; Use a help register
+                            add [ebp-12],r22d    ; Replace register by helpregister }
+                           pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),
+                                               getsupreg(oper[0]^.ref^.index),RS_INVALID);
+                           getregisterinline(list,pos,subreg,helpreg);
+                           result:=true;
+                           op:=A_MOV;
+                           hopsize:=opsize;  {Save old value...}
+                           if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
+                             begin
+                               {Because 'movzx memory,register' does not exist...}
+                               op:=opcode;
+                               opcode:=A_MOV;
+                               opsize:=reg2opsize(oper[1]^.reg);
+                             end;
+                           helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0]^.ref^,helpreg);
+                           if pos=nil then
+                             list.insertafter(helpins,list.first)
+                           else
+                             list.insertafter(helpins,pos.next);
+                           dispose(oper[0]^.ref);
+                           oper[0]^.typ:=top_reg;
+                           oper[0]^.reg:=helpreg;
+                           oper[1]^.typ:=top_ref;
+                           new(oper[1]^.ref);
+                           oper[1]^.ref^:=spilltemplist[supreg];
+                           ungetregisterinline(list,helpins,helpreg);
+                           forward_allocation(Tai(helpins.next),instr);
+                         end
+                       else
+                         begin
+                           {Situation example:
+                            add r20d,r21d        ; r20d must be spilled into [ebp-12]
+
+                            Change into:
+
+                            add [ebp-12],r21d    ; Replace register by reference }
+                           if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
+                             begin
+                               {Because 'movzx memory,register' does not exist...}
+                               result:=true;
+                               op:=opcode;
+                               hopsize:=opsize;
+                               opcode:=A_MOV;
+                               opsize:=reg2opsize(oper[1]^.reg);
+                               pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),RS_INVALID,RS_INVALID);
+                               getregisterinline(list,pos,subreg,helpreg);
+                               helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0]^.reg,helpreg);
+                               if pos=nil then
+                                 list.insertafter(helpins,list.first)
+                               else
+                                 list.insertafter(helpins,pos.next);
+                               oper[0]^.reg:=helpreg;
+                               ungetregisterinline(list,helpins,helpreg);
+                               forward_allocation(Tai(helpins.next),instr);
+                             end;
+                           oper[1]^.typ:=top_ref;
+                           new(oper[1]^.ref);
+                           oper[1]^.ref^:=spilltemplist[supreg];
+                         end;
+                     end;
+                 end;
+
+               { The i386 instruction set never gets boring...
+                 some opcodes do not support a memory location as destination }
+               if (oper[1]^.typ=top_ref) and
+                  (
+                   (oper[0]^.typ=top_const) or
+                   ((oper[0]^.typ=top_reg) and
+                    (getregtype(oper[0]^.reg)=regtype))
+                  ) then
+                 begin
+                   case opcode of
+                     A_IMUL :
+                       begin
+                         {Yikes! We just changed the destination register into
+                          a memory location above here.
+
+                          Situation examples:
+
+                          imul [ebp-12],r21d    ; We need a help register
+                          imul [ebp-12],<const> ; We need a help register
+
+                          Change into:
+
+                          mov r22d,[ebp-12]    ; Use a help instruction (only for IMUL)
+                          imul r22d,r21d       ; Replace reference by helpregister
+                          mov [ebp-12],r22d    ; Use another help instruction}
+                         getregisterinline(list,Tai(previous),subreg,helpreg);
+                         result:=true;
+                         {First help instruction.}
+                         helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1]^.ref^,helpreg);
+                         if previous=nil then
+                           list.insert(helpins)
+                         else
+                           list.insertafter(helpins,previous);
+                         {Second help instruction.}
+                         helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1]^.ref^);
+                         dispose(oper[1]^.ref);
+                         oper[1]^.typ:=top_reg;
+                         oper[1]^.reg:=helpreg;
+                         list.insertafter(helpins,instr);
+                         ungetregisterinline(list,instr,helpreg);
+                       end;
+                   end;
+                 end;
+
+               { The i386 instruction set never gets boring...
+                 some opcodes do not support a memory location as source }
+               if (oper[0]^.typ=top_ref) and
+                  (oper[1]^.typ=top_reg) and
+                  (getregtype(oper[1]^.reg)=regtype) then
+                 begin
+                   case opcode of
+                     A_BT,A_BTS,
+                     A_BTC,A_BTR :
+                       begin
+                         {Yikes! We just changed the source register into
+                          a memory location above here.
+
+                          Situation example:
+
+                          bt  r21d,[ebp-12]   ; We need a help register
+
+                          Change into:
+
+                          mov r22d,[ebp-12]    ; Use a help instruction (only for IMUL)
+                          bt  r21d,r22d        ; Replace reference by helpregister}
+                         getregisterinline(list,Tai(previous),subreg,helpreg);
+                         result:=true;
+                         {First help instruction.}
+                         helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[0]^.ref^,helpreg);
+                         if previous=nil then
+                           list.insert(helpins)
+                         else
+                           list.insertafter(helpins,previous);
+                         dispose(oper[0]^.ref);
+                         oper[0]^.typ:=top_reg;
+                         oper[0]^.reg:=helpreg;
+                         ungetregisterinline(list,helpins,helpreg);
+                       end;
+                   end;
+                 end;
+             end;
+           3:
+             begin
+               {$warning todo!!}
+             end;
+         end;
+       end;
+    end;
+
+
+{******************************************************************************
+                                  Trgx86fpu
 ******************************************************************************}
 
     constructor Trgx86fpu.create;
@@ -228,7 +615,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.1  2003-12-24 00:12:57  florian
+  Revision 1.2  2004-01-12 16:37:59  peter
+    * moved spilling code from taicpu to rg
+
+  Revision 1.1  2003/12/24 00:12:57  florian
     * rg unified for i386/x86-64
 
   Revision 1.40  2003/10/17 15:08:34  peter