Procházet zdrojové kódy

* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed

peter před 21 roky
rodič
revize
ee3585f56f

+ 12 - 5
compiler/i386/csopt386.pas

@@ -140,7 +140,7 @@ begin
               end
       end;
     else
-      for opCount := 1 to MaxCh do
+      for opCount := 1 to maxinschanges do
         case InsProp[p.opcode].Ch[opCount] of
           Ch_MOp1,CH_WOp1,CH_RWOp1:
               if not(onlymem) or
@@ -904,7 +904,7 @@ begin
       begin
         NoHardCodedRegs := true;
         with InsProp[p.opcode] do
-          for chCount := 1 to MaxCh do
+          for chCount := 1 to maxinschanges do
             if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
               begin
                 NoHardCodedRegs := false;
@@ -1058,7 +1058,7 @@ begin
 {                updateStates(orgReg,newReg,p,false);}
                 doReplaceReadReg := true;
               end;
-        for opCount := 1 to MaxCh do
+        for opCount := 1 to maxinschanges do
           case InsProp[p.opcode].Ch[opCount] of
             Ch_ROp1:
               if p.oper[0]^.typ = top_reg then
@@ -1901,7 +1901,7 @@ begin
                         ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
               else
                 begin
-                  for cnt := 1 to maxch do
+                  for cnt := 1 to maxinschanges do
                     begin
                       case InsProp[taicpu(p).opcode].Ch[cnt] of
                         Ch_ROp1:
@@ -2109,7 +2109,14 @@ end.
 
 {
   $Log$
-  Revision 1.65  2004-09-21 17:25:12  peter
+  Revision 1.66  2004-10-04 20:46:22  peter
+    * spilling code rewritten for x86. It now used the generic
+      spilling routines. Special x86 optimization still needs
+      to be added.
+    * Spilling fixed when both operands needed to be spilled
+    * Cleanup of spilling routine, do_spill_readwritten removed
+
+  Revision 1.65  2004/09/21 17:25:12  peter
     * paraloc branch merged
 
   Revision 1.64.4.1  2004/09/20 19:28:23  peter

+ 14 - 7
compiler/i386/daopt386.pas

@@ -725,7 +725,7 @@ begin
               RegReadByInstruction := true;
               exit
             end;
-        for opcount := 1 to maxch do
+        for opcount := 1 to maxinschanges do
           case insprop[p.opcode].ch[opcount] of
             CH_REAX..CH_REDI,CH_RWEAX..CH_MEDI:
               if supreg = tch2reg(insprop[p.opcode].ch[opcount]) then
@@ -791,7 +791,7 @@ begin
          (supreg in [RS_EAX,RS_EDX])
     else
       begin
-        for opcount := 1 to MaxCh do
+        for opcount := 1 to maxinschanges do
           case insprop[p.opcode].Ch[opCount] of
             CH_REAX..CH_MEDI:
               if tch2reg(InsProp[p.opcode].Ch[opCount]) = supreg then
@@ -866,7 +866,7 @@ begin
         begin
           Cnt := 1;
           InstrProp := InsProp[taicpu(p1).OpCode];
-          while (Cnt <= MaxCh) and
+          while (Cnt <= maxinschanges) and
                 (InstrProp.Ch[Cnt] <> Ch_None) and
                 not(TmpResult) Do
             begin
@@ -901,7 +901,7 @@ begin
   case p.typ of
     ait_instruction:
       begin
-        for l := 1 to MaxCh do
+        for l := 1 to maxinschanges do
           if InsProp[taicpu(p).opcode].Ch[l] in [Ch_WFlags,Ch_RWFlags,Ch_All] then
             exit;
       end;
@@ -920,7 +920,7 @@ begin
   case p.typ of
     ait_instruction:
       begin
-        for l := 1 to MaxCh do
+        for l := 1 to maxinschanges do
           if InsProp[taicpu(p).opcode].Ch[l] in [Ch_RFlags,Ch_RWFlags,Ch_All] then
             exit;
       end;
@@ -2555,7 +2555,7 @@ begin
               else
                 begin
                   Cnt := 1;
-                  while (Cnt <= MaxCh) and
+                  while (Cnt <= maxinschanges) and
                         (InstrProp.Ch[Cnt] <> Ch_None) Do
                     begin
                       case InstrProp.Ch[Cnt] Of
@@ -2719,7 +2719,14 @@ end.
 
 {
   $Log$
-  Revision 1.69  2004-09-26 17:45:30  peter
+  Revision 1.70  2004-10-04 20:46:22  peter
+    * spilling code rewritten for x86. It now used the generic
+      spilling routines. Special x86 optimization still needs
+      to be added.
+    * Spilling fixed when both operands needed to be spilled
+    * Cleanup of spilling routine, do_spill_readwritten removed
+
+  Revision 1.69  2004/09/26 17:45:30  peter
     * simple regvar support, not yet finished
 
   Revision 1.68  2004/06/20 08:55:31  florian

+ 8 - 44
compiler/i386/optbase.pas

@@ -28,49 +28,6 @@ unit optbase;
 
 interface
 
-uses cpuinfo, cpubase;
-
-
-{*****************************************************************************
-                   Opcode propeties (needed for optimizer)
-*****************************************************************************}
-
-{$ifndef NOOPT}
-Type
-{What an instruction can change}
-  TInsChange = (Ch_None,
-     {Read from a register}
-     Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
-     {write from a register}
-     Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
-     {read and write from/to a register}
-     Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
-     {modify the contents of a register with the purpose of using
-      this changed content afterwards (add/sub/..., but e.g. not rep
-      or movsd)}
-     Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
-     Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
-     Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
-     Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
-     Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
-     Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
-     Ch_WMemEDI,
-     Ch_All
-  );
-
-
-const
-  MaxCh = 3; { Max things a instruction can change }
-type
-  TInsProp = packed record
-    Ch : Array[1..MaxCh] of TInsChange;
-  end;
-
-const
-  InsProp : array[tasmop] of TInsProp =
-{$i i386prop.inc}
-
-{$endif NOOPT}
 
 implementation
 
@@ -79,7 +36,14 @@ end.
 
 {
   $Log$
-  Revision 1.3  2004-06-20 08:55:31  florian
+  Revision 1.4  2004-10-04 20:46:22  peter
+    * spilling code rewritten for x86. It now used the generic
+      spilling routines. Special x86 optimization still needs
+      to be added.
+    * Spilling fixed when both operands needed to be spilled
+    * Cleanup of spilling routine, do_spill_readwritten removed
+
+  Revision 1.3  2004/06/20 08:55:31  florian
     * logs truncated
 
 }

+ 58 - 163
compiler/rgobj.pas

@@ -135,8 +135,6 @@ unit rgobj;
       trgobj=class
         preserved_by_proc : tcpuregisterset;
         used_in_proc : tcpuregisterset;
-//        is_reg_var : Tsuperregisterset; {old regvars}
-//        reg_var_loaded:Tsuperregisterset; {old regvars}
 
         constructor create(Aregtype:Tregistertype;
                            Adefaultsub:Tsubregister;
@@ -170,25 +168,12 @@ unit rgobj;
         live_registers:Tsuperregisterworklist;
         { can be overriden to add cpu specific interferences }
         procedure add_cpu_interferences(p : tai);virtual;
-        function  get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
-        procedure forward_allocation(pfrom,pto:Tai);
+        procedure add_constraints(reg:Tregister);virtual;
         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 get_spill_subreg(r : tregister) : tsubregister;virtual;
-        procedure do_spill_read(list:Taasmoutput;instr:Taicpu;
-                                pos:Tai;regidx:word;
-                                const spilltemplist:Tspill_temp_list;
-                                const regs:Tspillregsinfo);virtual;
-        procedure do_spill_written(list:Taasmoutput;instr:Taicpu;
-                                   pos:Tai;regidx:word;
-                                   const spilltemplist:Tspill_temp_list;
-                                   const regs:Tspillregsinfo);virtual;
-        procedure do_spill_readwritten(list:Taasmoutput;instr:Taicpu;
-                                       pos:Tai;regidx:word;
-                                       const spilltemplist:Tspill_temp_list;
-                                       const regs:Tspillregsinfo);virtual;
+        procedure do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);virtual;
+        procedure do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);virtual;
 
         function instr_spill_register(list:Taasmoutput;
                                       instr:taicpu;
@@ -603,22 +588,12 @@ unit rgobj;
     procedure trgobj.add_edges_used(u:Tsuperregister);
 
     var i:word;
-        v:tsuperregister;
 
     begin
       with live_registers do
         if length>0 then
           for i:=0 to length-1 do
-            begin
-              v:=buf^[i];
-              add_edge(u,v);
-              { add also conflicts with all coalesced registers }
-              while ri_coalesced in reginfo[v].flags do
-                begin
-                  v:=reginfo[v].alias;
-                  add_edge(u,v);
-                end;
-            end;
+            add_edge(u,get_alias(buf^[i]));
     end;
 
 {$ifdef EXTDEBUG}
@@ -1638,69 +1613,6 @@ unit rgobj;
       end;
 
 
-    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
-            supreg:=getsupreg(Tai_regalloc(p).reg);
-            {Rewind the register allocation.}
-            if (Tai_regalloc(p).ratype=ra_alloc) then
-              live_registers.delete(supreg)
-            else
-              begin
-                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;
-        live_registers.done;
-        live_registers:=back;
-      end;
-
-
-    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);
-            case Tai_regalloc(p).ratype of
-              ra_alloc :
-                live_registers.add(getsupreg(Tai_regalloc(p).reg));
-              ra_dealloc :
-                live_registers.delete(getsupreg(Tai_regalloc(p).reg));
-            end;
-            p:=Tai(p.next);
-          end;
-      end;
-
-
     function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
     { Returns true if any help registers have been used }
       var
@@ -1790,65 +1702,22 @@ unit rgobj;
       end;
 
 
-    procedure Trgobj.do_spill_read(list:Taasmoutput;instr:taicpu;
-                                   pos:Tai;regidx:word;
-                                   const spilltemplist:Tspill_temp_list;
-                                   const regs:Tspillregsinfo);
-
-    var helpins:Tai;
-
-    begin
-      with regs[regidx] do
-        begin
-          helpins:=spilling_create_load(spilltemplist[orgreg],tempreg);
-          if pos=nil then
-            list.insertafter(helpins,list.first)
-          else
-            list.insertafter(helpins,pos.next);
-          ungetregisterinline(list,instr,tempreg);
-          forward_allocation(tai(helpins.next),instr);
-        end;
-    end;
-
-
-    procedure Trgobj.do_spill_written(list:Taasmoutput;instr:taicpu;
-                                      pos:Tai;regidx:word;
-                                      const spilltemplist:Tspill_temp_list;
-                                      const regs:Tspillregsinfo);
-
-    var helpins:Tai;
-
-    begin
-      with regs[regidx] do
-        begin
-          helpins:=spilling_create_store(tempreg,spilltemplist[orgreg]);
-          list.insertafter(helpins,instr);
-          ungetregisterinline(list,helpins,tempreg);
-        end;
-    end;
-
-
-    procedure Trgobj.do_spill_readwritten(list:Taasmoutput;instr:taicpu;
-                                          pos:Tai;regidx:word;
-                                          const spilltemplist:Tspill_temp_list;
-                                          const regs:Tspillregsinfo);
+    procedure Trgobj.do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
+      var
+        helpins : Tai;
+      begin
+        helpins:=spilling_create_load(spilltemp,tempreg);
+        list.insertbefore(helpins,instr);
+      end;
 
-    var helpins1,helpins2:Tai;
 
-    begin
-      with regs[regidx] do
-        begin
-          helpins1:=spilling_create_load(spilltemplist[orgreg],tempreg);
-          if pos=nil then
-            list.insertafter(helpins1,list.first)
-          else
-            list.insertafter(helpins1,pos.next);
-          helpins2:=spilling_create_store(tempreg,spilltemplist[orgreg]);
-          list.insertafter(helpins2,instr);
-          ungetregisterinline(list,helpins2,tempreg);
-          forward_allocation(tai(helpins1.next),instr);
-        end;
-    end;
+    procedure Trgobj.do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
+      var
+        helpins : Tai;
+      begin
+        helpins:=spilling_create_store(tempreg,spilltemp);
+        list.insertafter(helpins,instr);
+      end;
 
 
     function trgobj.get_spill_subreg(r : tregister) : tsubregister;
@@ -1863,7 +1732,6 @@ unit rgobj;
                                          const spilltemplist:Tspill_temp_list): boolean;
       var
         counter, regindex: longint;
-        pos: tai;
         regs: tspillregsinfo;
         spilled: boolean;
 
@@ -1874,7 +1742,7 @@ unit rgobj;
         begin
           tmpindex := regindex;
           supreg:=getsupreg(reg);
-          // did we already encounter this register?
+          { did we already encounter this register? }
           for i := 0 to pred(regindex) do
             if (regs[i].orgreg = supreg) then
               begin
@@ -1887,7 +1755,7 @@ unit rgobj;
           regs[tmpindex].spillreg:=reg;
           if supregset_in(r,supreg) then
             begin
-              // add/update info on this register
+              { add/update info on this register }
               regs[tmpindex].mustbespilled := true;
               case operation of
                 operand_read:
@@ -1916,12 +1784,15 @@ unit rgobj;
             if (regs[i].mustbespilled) and
                (regs[i].orgreg=supreg) then
               begin
-                reg:=regs[i].tempreg;
+                { Only replace supreg }
+                setsupreg(reg,getsupreg(regs[i].tempreg));
                 break;
               end;
         end;
 
-
+      var
+        counter2 : longint;
+        oldlive_registers : tsuperregisterworklist;
       begin
         result := false;
         fillchar(regs,sizeof(regs),0);
@@ -1966,6 +1837,14 @@ unit rgobj;
         if not spilled then
           exit;
 
+        { Add conflicts with all non-spilled registers }
+        oldlive_registers.copyfrom(live_registers);
+        for counter2 := 0 to pred(regindex) do
+          begin
+            if (not regs[counter2].mustbespilled) then
+              live_registers.add(get_alias(regs[counter2].orgreg));
+          end;
+
         { generate the spilling code }
         result := true;
         for counter := 0 to pred(regindex) do
@@ -1973,18 +1852,27 @@ unit rgobj;
             begin
               if mustbespilled then
                 begin
-                  pos:=get_insert_pos(Tai(instr.previous),regs[0].orgreg,regs[1].orgreg,regs[2].orgreg);
-                  getregisterinline(list,pos,get_spill_subreg(regs[counter].spillreg),tempreg);
+                  getregisterinline(list,tai(instr.previous),get_spill_subreg(regs[counter].spillreg),tempreg);
+
                   if regread then
-                    if regwritten then
-                      do_spill_readwritten(list,instr,pos,counter,spilltemplist,regs)
-                    else
-                      do_spill_read(list,instr,pos,counter,spilltemplist,regs)
-                  else
-                    do_spill_written(list,instr,pos,counter,spilltemplist,regs)
+                    do_spill_read(list,instr,spilltemplist[orgreg],tempreg);
+                  if regwritten then
+                    do_spill_written(list,instr,spilltemplist[orgreg],tempreg);
                 end;
             end;
 
+        { Release temp registers after all registers for the instruction are spilled }
+        for counter := 0 to pred(regindex) do
+          with regs[counter] do
+            begin
+              if mustbespilled then
+                ungetregisterinline(list,instr,tempreg);
+            end;
+
+        { restore live registers }
+        live_registers.done;
+        live_registers:=oldlive_registers;
+
         { substitute registers }
         for counter:=0 to instr.ops-1 do
          with instr.oper[counter]^ do
@@ -2015,7 +1903,14 @@ unit rgobj;
 end.
 {
   $Log$
-  Revision 1.137  2004-09-26 17:45:30  peter
+  Revision 1.138  2004-10-04 20:46:22  peter
+    * spilling code rewritten for x86. It now used the generic
+      spilling routines. Special x86 optimization still needs
+      to be added.
+    * Spilling fixed when both operands needed to be spilled
+    * Cleanup of spilling routine, do_spill_readwritten removed
+
+  Revision 1.137  2004/09/26 17:45:30  peter
     * simple regvar support, not yet finished
 
   Revision 1.136  2004/09/25 14:23:54  peter

+ 45 - 119
compiler/sparc/rgcpu.pas

@@ -36,12 +36,8 @@ unit rgcpu;
       trgcpu=class(trgobj)
         procedure add_constraints(reg:tregister);override;
         function get_spill_subreg(r : tregister) : tsubregister;override;
-        procedure do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
-                                const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
-        procedure do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
-                                   const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
-        procedure do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
-                                       const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
+        procedure do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);override;
+        procedure do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);override;
       end;
 
 
@@ -91,159 +87,89 @@ implementation
       end;
 
 
-    procedure trgcpu.do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
-                                   const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
+    procedure trgcpu.do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
       var
-        helpins: tai;
-        tmpref,ref : treference;
+        helpins  : tai;
+        tmpref   : treference;
         helplist : taasmoutput;
-        tmpreg : tregister;
+        hreg     : tregister;
       begin
-        ref:=spilltemplist[regs[regidx].orgreg];
-        if abs(ref.offset)>4095 then
+        if abs(spilltemp.offset)>4095 then
           begin
             helplist:=taasmoutput.create;
-            reference_reset(tmpref);
-
-            if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
-              getregisterinline(helplist,nil,defaultsub,tmpreg)
-            else
-              tmpreg:=cg.getintregister(helplist,OS_ADDR);
-
-            tmpref.offset:=ref.offset;
-            tmpref.refaddr:=addr_hi;
-            helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
 
-            tmpref.refaddr:=addr_lo;
-            helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
-
-            if ref.index<>NR_NO then
-              internalerror(200401263);
-            ref.index:=tmpreg;
-            ref.offset:=0;
-
-            helpins:=spilling_create_load(ref,regs[regidx].tempreg);
-            helplist.concat(helpins);
-            if pos=nil then
-              list.insertlistafter(list.first,helplist)
+            if getregtype(tempreg)=R_INTREGISTER then
+              hreg:=tempreg
             else
-              list.insertlistafter(pos.next,helplist);
-            helplist.free;
+              hreg:=cg.getintregister(helplist,OS_ADDR);
 
-            ungetregisterinline(list,helpins,regs[regidx].tempreg);
-
-            if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
-              ungetregisterinline(list,helpins,tmpreg);
-
-            forward_allocation(tai(helpins.next),instr);
-          end
-        else
-          inherited do_spill_read(list,instr,pos,regidx,spilltemplist,regs);
-      end;
-
-
-    procedure trgcpu.do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
-                                      const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
-      var
-        helpins: tai;
-        ref,tmpref : treference;
-        helplist : taasmoutput;
-        tmpreg : tregister;
-      begin
-        ref:=spilltemplist[regs[regidx].orgreg];
-        if abs(ref.offset)>4095 then
-          begin
-            helplist:=taasmoutput.create;
             reference_reset(tmpref);
-
-            if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
-              getregisterinline(helplist,pos,defaultsub,tmpreg)
-            else
-              tmpreg:=cg.getintregister(helplist,OS_ADDR);
-
-            tmpref.offset:=ref.offset;
+            tmpref.offset:=spilltemp.offset;
             tmpref.refaddr:=addr_hi;
-            helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
+            helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
 
             tmpref.refaddr:=addr_lo;
-            helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
+            helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
 
-            if ref.index<>NR_NO then
-              internalerror(200401263);
-            ref.index:=tmpreg;
-            ref.offset:=0;
+            reference_reset_base(tmpref,hreg,0);
 
-            helpins:=spilling_create_store(regs[regidx].tempreg,ref);
+            helpins:=spilling_create_load(spilltemp,tempreg);
             helplist.concat(helpins);
-            list.insertlistafter(instr,helplist);
-            helplist.free;
-
-            ungetregisterinline(list,helpins,regs[regidx].tempreg);
-
-            if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
-              ungetregisterinline(list,helpins,tmpreg);
+            list.insertlistbefore(instr,helplist)
           end
         else
-          inherited do_spill_written(list,instr,pos,regidx,spilltemplist,regs);
+          inherited do_spill_read(list,instr,spilltemp,tempreg);
       end;
 
 
-    procedure trgcpu.do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
-                                          const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
+    procedure trgcpu.do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
       var
-        helpins1, helpins2: tai;
-        tmpref,ref : treference;
+        helpins  : tai;
+        tmpref   : treference;
         helplist : taasmoutput;
-         tmpreg : tregister;
+        hreg     : tregister;
       begin
-        ref:=spilltemplist[regs[regidx].orgreg];
-        if abs(ref.offset)>4095 then
+        if abs(spilltemp.offset)>4095 then
           begin
             helplist:=taasmoutput.create;
-            reference_reset(tmpref);
 
-            if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
-              getregisterinline(helplist,nil,defaultsub,tmpreg)
+            if getregtype(tempreg)=R_INTREGISTER then
+              getregisterinline(helplist,tai(helplist.first),R_SUBWHOLE,hreg)
             else
-              tmpreg:=cg.getintregister(helplist,OS_ADDR);
+              hreg:=cg.getintregister(helplist,OS_ADDR);
 
-            tmpref.offset:=ref.offset;
+            reference_reset(tmpref);
+            tmpref.offset:=spilltemp.offset;
             tmpref.refaddr:=addr_hi;
-            helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
+            helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
 
             tmpref.refaddr:=addr_lo;
-            helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
-
-            if ref.index<>NR_NO then
-              internalerror(200401263);
-            ref.index:=tmpreg;
-            ref.offset:=0;
+            helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
 
-            helpins1:=spilling_create_load(ref,regs[regidx].tempreg);
-            helplist.concat(helpins1);
-            if pos=nil then
-              list.insertlistafter(list.first,helplist)
-            else
-              list.insertlistafter(pos.next,helplist);
-            helplist.free;
-
-            helpins2:=spilling_create_store(regs[regidx].tempreg,ref);
-            list.insertafter(helpins2,instr);
-            ungetregisterinline(list,helpins2,regs[regidx].tempreg);
+            reference_reset_base(tmpref,hreg,0);
 
-            if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
-              ungetregisterinline(list,helpins2,tmpreg);
+            helpins:=spilling_create_store(tempreg,spilltemp);
+            helplist.concat(helpins);
+            if getregtype(tempreg)=R_INTREGISTER then
+              ungetregisterinline(helplist,tai(helplist.last),hreg);
 
-            forward_allocation(tai(helpins1.next),instr);
+            list.insertlistafter(instr,helplist)
           end
         else
-          inherited do_spill_readwritten(list,instr,pos,regidx,spilltemplist,regs);
-      end;
+          inherited do_spill_written(list,instr,spilltemp,tempreg);
+    end;
 
 end.
 {
   $Log$
-  Revision 1.27  2004-10-01 17:33:47  peter
+  Revision 1.28  2004-10-04 20:46:22  peter
+    * spilling code rewritten for x86. It now used the generic
+      spilling routines. Special x86 optimization still needs
+      to be added.
+    * Spilling fixed when both operands needed to be spilled
+    * Cleanup of spilling routine, do_spill_readwritten removed
+
+  Revision 1.27  2004/10/01 17:33:47  peter
     * indents
 
   Revision 1.26  2004/09/28 20:19:36  peter

+ 117 - 7
compiler/x86/aasmcpu.pas

@@ -130,6 +130,36 @@ interface
       instabentries = {$i i386nop.inc}
 {$endif x86_64}
       maxinfolen    = 8;
+      MaxInsChanges = 3; { Max things a instruction can change }
+
+    type
+      { What an instruction can change. Needed for optimizer and spilling code }
+      TInsChange = (Ch_None,
+        {Read from a register}
+        Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
+        {write from a register}
+        Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
+        {read and write from/to a register}
+        Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
+        {modify the contents of a register with the purpose of using
+         this changed content afterwards (add/sub/..., but e.g. not rep
+         or movsd)}
+        Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
+        Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
+        Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
+        Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
+        Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
+        Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
+        Ch_WMemEDI,
+        Ch_All
+      );
+
+      TInsProp = packed record
+        Ch : Array[1..MaxInsChanges] of TInsChange;
+      end;
+
+    const
+      InsProp : array[tasmop] of TInsProp = {$i i386prop.inc}
 
     type
       TOperandOrder = (op_intel,op_att);
@@ -201,6 +231,8 @@ interface
          procedure Pass2(objdata:TAsmObjectdata);virtual;
          procedure SetOperandOrder(order:TOperandOrder);
          function is_same_reg_move(regtype: Tregistertype):boolean;override;
+         { register spilling code }
+         function spilling_get_operation_type(opnr: longint): topertype;override;
       protected
          procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
          procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
@@ -366,6 +398,12 @@ implementation
       );
 {$endif x86_64}
 
+    { Operation type for spilling code }
+    type
+      toperation_type_table=array[tasmop,0..Max_Operands] of topertype;
+    var
+      operation_type_table : ^toperation_type_table;
+
 
 {****************************************************************************
                               TAI_ALIGN
@@ -1932,15 +1970,74 @@ implementation
       end;
 
 
+    procedure build_spilling_operation_type_table;
+      var
+        opcode : tasmop;
+        i      : integer;
+      begin
+        new(operation_type_table);
+        fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read));
+        for opcode:=low(tasmop) to high(tasmop) do
+          begin
+            for i:=1 to MaxInsChanges do
+              begin
+                case InsProp[opcode].Ch[i] of
+                  Ch_Rop1 :
+                    operation_type_table^[opcode,0]:=operand_read;
+                  Ch_Wop1 :
+                    operation_type_table^[opcode,0]:=operand_write;
+                  Ch_RWop1,
+                  Ch_Mop1 :
+                    operation_type_table^[opcode,0]:=operand_readwrite;
+                  Ch_Rop2 :
+                    operation_type_table^[opcode,1]:=operand_read;
+                  Ch_Wop2 :
+                    operation_type_table^[opcode,1]:=operand_write;
+                  Ch_RWop2,
+                  Ch_Mop2 :
+                    operation_type_table^[opcode,1]:=operand_readwrite;
+                  Ch_Rop3 :
+                    operation_type_table^[opcode,2]:=operand_read;
+                  Ch_Wop3 :
+                    operation_type_table^[opcode,2]:=operand_write;
+                  Ch_RWop3,
+                  Ch_Mop3 :
+                    operation_type_table^[opcode,2]:=operand_readwrite;
+                end;
+              end;
+          end;
+      end;
+
+
+    function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+      begin
+        result:=operation_type_table^[opcode,opnr];
+      end;
+
+
     function spilling_create_load(const ref:treference;r:tregister): tai;
       begin
-        internalerror(200406131);
+        case getregtype(r) of
+          R_INTREGISTER :
+            result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),ref,r);
+          R_MMREGISTER :
+            result:=taicpu.op_ref_reg(A_MOVSD,reg2opsize(r),ref,r);
+          else
+            internalerror(200401041);
+        end;
       end;
 
 
     function spilling_create_store(r:tregister; const ref:treference): tai;
       begin
-        internalerror(200406132);
+        case getregtype(r) of
+          R_INTREGISTER :
+            result:=taicpu.op_reg_ref(A_MOV,reg2opsize(r),r,ref);
+          R_MMREGISTER :
+            result:=taicpu.op_reg_ref(A_MOVSD,reg2opsize(r),r,ref);
+          else
+            internalerror(200401041);
+        end;
       end;
 
 
@@ -1970,6 +2067,7 @@ implementation
 
     procedure InitAsm;
       begin
+        build_spilling_operation_type_table;
 {$ifndef NOAG386BIN}
         if not assigned(instabcache) then
           BuildInsTabCache;
@@ -1979,12 +2077,17 @@ implementation
 
     procedure DoneAsm;
       begin
+        if assigned(operation_type_table) then
+          begin
+            dispose(operation_type_table);
+            operation_type_table:=nil;
+          end;
 {$ifndef NOAG386BIN}
         if assigned(instabcache) then
-        begin
-          dispose(instabcache);
-          instabcache:=nil;
-        end;
+          begin
+            dispose(instabcache);
+            instabcache:=nil;
+          end;
 {$endif NOAG386BIN}
       end;
 
@@ -1995,7 +2098,14 @@ begin
 end.
 {
   $Log$
-  Revision 1.58  2004-09-27 15:12:47  peter
+  Revision 1.59  2004-10-04 20:46:22  peter
+    * spilling code rewritten for x86. It now used the generic
+      spilling routines. Special x86 optimization still needs
+      to be added.
+    * Spilling fixed when both operands needed to be spilled
+    * Cleanup of spilling routine, do_spill_readwritten removed
+
+  Revision 1.58  2004/09/27 15:12:47  peter
     * IE when expecting top_ref
 
   Revision 1.57  2004/06/20 08:55:32  florian

+ 16 - 6
compiler/x86/cgx86.pas

@@ -551,11 +551,14 @@ unit cgx86;
         if s in [S_BL,S_WL,S_L] then
           reg2:=makeregsize(list,reg2,OS_32);
 {$endif x86_64}
-        instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
-        { Notify the register allocator that we have written a move instruction so
-          it can try to eliminate it. }
-        add_move_instruction(instr);
-        list.concat(instr);
+        if (reg1<>reg2) then
+          begin
+            instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
+            { Notify the register allocator that we have written a move instruction so
+              it can try to eliminate it. }
+            add_move_instruction(instr);
+            list.concat(instr);
+          end;
       end;
 
 
@@ -1672,7 +1675,14 @@ unit cgx86;
 end.
 {
   $Log$
-  Revision 1.126  2004-10-03 12:42:22  florian
+  Revision 1.127  2004-10-04 20:46:22  peter
+    * spilling code rewritten for x86. It now used the generic
+      spilling routines. Special x86 optimization still needs
+      to be added.
+    * Spilling fixed when both operands needed to be spilled
+    * Cleanup of spilling routine, do_spill_readwritten removed
+
+  Revision 1.126  2004/10/03 12:42:22  florian
     * made sqrt, sqr and abs internal for the sparc
 
   Revision 1.125  2004/09/25 14:23:55  peter

+ 79 - 1
compiler/x86/rgx86.pas

@@ -36,10 +36,21 @@ unit rgx86;
 
     type
        trgx86 = class(trgobj)
+{$ifdef OLDRGX86}
          function instr_spill_register(list:Taasmoutput;
                                        instr:taicpu;
                                        const r:Tsuperregisterset;
                                        const spilltemplist:Tspill_temp_list): boolean;override;
+{$endif OLDRGX86}
+        function  get_spill_subreg(r : tregister) : tsubregister;override;
+{
+        procedure do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
+                                const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
+        procedure do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
+                                   const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
+        procedure do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
+                                       const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
+}
        end;
 
        tpushedsavedloc = record
@@ -107,6 +118,7 @@ implementation
                                     Trgcpu
 ******************************************************************************}
 
+{$ifdef OLDRGX86}
     function trgx86.instr_spill_register(list:Taasmoutput;
                                          instr:taicpu;
                                          const r:Tsuperregisterset;
@@ -485,8 +497,67 @@ implementation
          end;
        end;
     end;
+{$endif OLDRGX86}
+
+
+    function trgx86.get_spill_subreg(r : tregister) : tsubregister;
+      begin
+        result:=getsubreg(r);
+      end;
+
+
+      (*
+    procedure trgx86.do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
+                                   const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
+      var
+        helpins: tai;
+        tmpref,ref : treference;
+        helplist : taasmoutput;
+        tmpreg : tregister;
+      begin
+{        ref:=spilltemplist[regs[regidx].orgreg];
+        if abs(ref.offset)>4095 then
+          begin
+          end
+        else }
+          inherited do_spill_read(list,instr,pos,regidx,spilltemplist,regs);
+      end;
 
 
+    procedure trgx86.do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
+                                      const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
+      var
+        helpins: tai;
+        ref,tmpref : treference;
+        helplist : taasmoutput;
+        tmpreg : tregister;
+      begin
+{        ref:=spilltemplist[regs[regidx].orgreg];
+        if abs(ref.offset)>4095 then
+          begin
+          end
+        else }
+          inherited do_spill_written(list,instr,pos,regidx,spilltemplist,regs);
+      end;
+
+
+    procedure trgx86.do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
+                                          const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
+      var
+        helpins1, helpins2: tai;
+        tmpref,ref : treference;
+        helplist : taasmoutput;
+         tmpreg : tregister;
+      begin
+{        ref:=spilltemplist[regs[regidx].orgreg];
+        if abs(ref.offset)>4095 then
+          begin
+          end
+        else  }
+          inherited do_spill_readwritten(list,instr,pos,regidx,spilltemplist,regs);
+      end;
+*)
+
 {******************************************************************************
                                   Trgx86fpu
 ******************************************************************************}
@@ -619,7 +690,14 @@ implementation
 end.
 {
   $Log$
-  Revision 1.6  2004-09-27 14:49:45  peter
+  Revision 1.7  2004-10-04 20:46:22  peter
+    * spilling code rewritten for x86. It now used the generic
+      spilling routines. Special x86 optimization still needs
+      to be added.
+    * Spilling fixed when both operands needed to be spilled
+    * Cleanup of spilling routine, do_spill_readwritten removed
+
+  Revision 1.6  2004/09/27 14:49:45  peter
     * handle 3 operand opcodes the same as 2 operand opcodes, the
       third operand can only be a const or register CL, so it doesn't
       affect spilling