浏览代码

+ Implemented the actual register allocator
+ Scratch registers unavailable when new register allocator used
+ maybe_save/maybe_restore unavailable when new register allocator used

daniel 22 年之前
父节点
当前提交
25059e21b6

+ 51 - 1
compiler/aasmtai.pas

@@ -435,6 +435,7 @@ interface
           procedure loadref(opidx:longint;const r:treference);
           procedure loadref(opidx:longint;const r:treference);
           procedure loadreg(opidx:longint;r:tregister);
           procedure loadreg(opidx:longint;r:tregister);
           procedure loadoper(opidx:longint;o:toper);
           procedure loadoper(opidx:longint;o:toper);
+          function is_nop:boolean;virtual;abstract;
        end;
        end;
 
 
        { alignment for operator }
        { alignment for operator }
@@ -450,9 +451,12 @@ interface
           function calculatefillbuf(var buf : tfillbuffer):pchar;virtual;
           function calculatefillbuf(var buf : tfillbuffer):pchar;virtual;
        end;
        end;
 
 
+       Ttranstable=array[Tsuperregister] of Tsuperregister;
+
        taasmoutput = class(tlinkedlist)
        taasmoutput = class(tlinkedlist)
           function getlasttaifilepos : pfileposinfo;
           function getlasttaifilepos : pfileposinfo;
           procedure convert_registers;
           procedure convert_registers;
+          procedure translate_registers(const table:Ttranstable);
        end;
        end;
 
 
 
 
@@ -1767,10 +1771,56 @@ uses
         end;
         end;
     end;
     end;
 
 
+    procedure Taasmoutput.translate_registers(const table:Ttranstable);
+
+    var p,q:Tai;
+        i:shortint;
+        r:Preference;
+
+    begin
+      p:=Tai(first);
+      while assigned(p) do
+        begin
+          case p.typ of
+            ait_regalloc:
+              Tai_regalloc(p).reg.number:=(Tai_regalloc(p).reg.number and $ff) or
+                                          (table[Tai_regalloc(p).reg.number shr 8] shl 8);
+            ait_instruction:
+              begin
+                for i:=0 to Taicpu_abstract(p).ops-1 do
+                  if Taicpu_abstract(p).oper[i].typ=Top_reg then
+                    Taicpu_abstract(p).oper[i].reg.number:=(Taicpu_abstract(p).oper[i].reg.number and $ff) or
+                                                           (table[Taicpu_abstract(p).oper[i].reg.number shr 8] shl 8)
+                  else if Taicpu_abstract(p).oper[i].typ=Top_ref then
+                    begin
+                      r:=Taicpu_abstract(p).oper[i].ref;
+                      r^.base.number:=(r^.base.number and $ff) or
+                                      (table[r^.base.number shr 8] shl 8);
+                      r^.index.number:=(r^.index.number and $ff) or
+                                       (table[r^.index.number shr 8] shl 8);
+                    end;
+                if Taicpu_abstract(p).is_nop then
+                  begin
+                    q:=p;
+                    p:=Tai(p.next);
+                    remove(q);
+                    continue;
+                  end;
+              end;
+          end;
+          p:=Tai(p.next);
+        end;
+    end;
+
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.21  2003-02-19 22:00:14  daniel
+  Revision 1.22  2003-04-22 10:09:34  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.21  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
     - Horribily outdated todo.txt removed
 
 

+ 77 - 2
compiler/cg64f32.pas

@@ -97,7 +97,7 @@ unit cg64f32;
        globtype,globals,systems,
        globtype,globals,systems,
        cgbase,
        cgbase,
        verbose,
        verbose,
-       symbase,symconst,symdef,defutil;
+       symbase,symconst,symdef,defutil,rgobj;
 
 
 
 
     function joinreg64(reglo,reghi : tregister) : tregister64;
     function joinreg64(reglo,reghi : tregister) : tregister64;
@@ -170,7 +170,11 @@ unit cg64f32;
           internalerror(200302035);
           internalerror(200302035);
         if (tmpref.base.number=reg.reglo.number) then
         if (tmpref.base.number=reg.reglo.number) then
          begin
          begin
+         {$ifdef newra}
+           tmpreg:=rg.getaddressregister(list);
+         {$else}
            tmpreg := cg.get_scratch_reg_address(list);
            tmpreg := cg.get_scratch_reg_address(list);
+         {$endif}
            got_scratch:=true;
            got_scratch:=true;
            cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
            cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
            tmpref.base:=tmpreg;
            tmpref.base:=tmpreg;
@@ -181,7 +185,11 @@ unit cg64f32;
          { implementation FK                                              }
          { implementation FK                                              }
          if (tmpref.index.number=reg.reglo.number) then
          if (tmpref.index.number=reg.reglo.number) then
           begin
           begin
+          {$ifdef newra}
+            tmpreg:=rg.getaddressregister(list);
+          {$else}
             tmpreg:=cg.get_scratch_reg_address(list);
             tmpreg:=cg.get_scratch_reg_address(list);
+          {$endif}
             got_scratch:=true;
             got_scratch:=true;
             cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
             cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
             tmpref.index:=tmpreg;
             tmpref.index:=tmpreg;
@@ -189,8 +197,13 @@ unit cg64f32;
         cg.a_load_ref_reg(list,OS_32,tmpref,reg.reglo);
         cg.a_load_ref_reg(list,OS_32,tmpref,reg.reglo);
         inc(tmpref.offset,4);
         inc(tmpref.offset,4);
         cg.a_load_ref_reg(list,OS_32,tmpref,reg.reghi);
         cg.a_load_ref_reg(list,OS_32,tmpref,reg.reghi);
+{$ifdef newra}
+        if got_scratch then
+          rg.ungetregisterint(list,tmpreg);
+{$else}
         if got_scratch then
         if got_scratch then
           cg.free_scratch_reg(list,tmpreg);
           cg.free_scratch_reg(list,tmpreg);
+{$endif}
       end;
       end;
 
 
 
 
@@ -399,12 +412,22 @@ unit cg64f32;
       var
       var
         tempreg: tregister64;
         tempreg: tregister64;
       begin
       begin
+      {$ifdef newra}
+        tempreg.reghi:=rg.getregisterint(list,OS_INT);
+        tempreg.reglo:=rg.getregisterint(list,OS_INT);
+      {$else}
         tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
+      {$endif}
         a_load64_ref_reg(list,ref,tempreg);
         a_load64_ref_reg(list,ref,tempreg);
         a_op64_reg_reg(list,op,tempreg,reg);
         a_op64_reg_reg(list,op,tempreg,reg);
+      {$ifdef newra}
+        rg.ungetregisterint(list,tempreg.reglo);
+        rg.ungetregisterint(list,tempreg.reghi);
+      {$else}
         cg.free_scratch_reg(list,tempreg.reglo);
         cg.free_scratch_reg(list,tempreg.reglo);
         cg.free_scratch_reg(list,tempreg.reghi);
         cg.free_scratch_reg(list,tempreg.reghi);
+      {$endif}
       end;
       end;
 
 
 
 
@@ -412,13 +435,23 @@ unit cg64f32;
       var
       var
         tempreg: tregister64;
         tempreg: tregister64;
       begin
       begin
+      {$ifdef newra}
+        tempreg.reghi:=rg.getregisterint(list,OS_INT);
+        tempreg.reglo:=rg.getregisterint(list,OS_INT);
+      {$else}
         tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
+      {$endif}
         a_load64_ref_reg(list,ref,tempreg);
         a_load64_ref_reg(list,ref,tempreg);
         a_op64_reg_reg(list,op,reg,tempreg);
         a_op64_reg_reg(list,op,reg,tempreg);
         a_load64_reg_ref(list,tempreg,ref);
         a_load64_reg_ref(list,tempreg,ref);
+      {$ifdef newra}
+        rg.ungetregisterint(list,tempreg.reglo);
+        rg.ungetregisterint(list,tempreg.reghi);
+      {$else}
         cg.free_scratch_reg(list,tempreg.reglo);
         cg.free_scratch_reg(list,tempreg.reglo);
         cg.free_scratch_reg(list,tempreg.reghi);
         cg.free_scratch_reg(list,tempreg.reghi);
+      {$endif}
       end;
       end;
 
 
 
 
@@ -426,13 +459,23 @@ unit cg64f32;
       var
       var
         tempreg: tregister64;
         tempreg: tregister64;
       begin
       begin
+      {$ifdef newra}
+        tempreg.reghi:=rg.getregisterint(list,OS_INT);
+        tempreg.reglo:=rg.getregisterint(list,OS_INT);
+      {$else}
         tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
         tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
+      {$endif}
         a_load64_ref_reg(list,ref,tempreg);
         a_load64_ref_reg(list,ref,tempreg);
         a_op64_const_reg(list,op,value,tempreg);
         a_op64_const_reg(list,op,value,tempreg);
         a_load64_reg_ref(list,tempreg,ref);
         a_load64_reg_ref(list,tempreg,ref);
+      {$ifdef newra}
+        rg.ungetregisterint(list,tempreg.reglo);
+        rg.ungetregisterint(list,tempreg.reghi);
+      {$else}
         cg.free_scratch_reg(list,tempreg.reglo);
         cg.free_scratch_reg(list,tempreg.reglo);
         cg.free_scratch_reg(list,tempreg.reghi);
         cg.free_scratch_reg(list,tempreg.reghi);
+      {$endif}
       end;
       end;
 
 
     procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const locpara : tparalocation);
     procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const locpara : tparalocation);
@@ -539,7 +582,11 @@ unit cg64f32;
                end
                end
              else
              else
                begin
                begin
+               {$ifdef newra}
+                 hreg:=rg.getregisterint(list,OS_INT);
+               {$else}
                  hreg := cg.get_scratch_reg_int(list,OS_INT);
                  hreg := cg.get_scratch_reg_int(list,OS_INT);
+               {$endif}
                  got_scratch := true;
                  got_scratch := true;
                  a_load64high_ref_reg(list,p.location.reference,hreg);
                  a_load64high_ref_reg(list,p.location.reference,hreg);
                end;
                end;
@@ -555,8 +602,13 @@ unit cg64f32;
                  cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,aword(-1),hreg,neglabel);
                  cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,aword(-1),hreg,neglabel);
                end;
                end;
              { !!! freeing of register should happen directly after compare! (JM) }
              { !!! freeing of register should happen directly after compare! (JM) }
+           {$ifdef newra}
+             if got_scratch then
+               rg.ungetregisterint(list,hreg);
+           {$else}
              if got_scratch then
              if got_scratch then
                cg.free_scratch_reg(list,hreg);
                cg.free_scratch_reg(list,hreg);
+           {$endif}
              { For all other values we have a range check error }
              { For all other values we have a range check error }
              cg.a_call_name(list,'FPC_RANGEERROR');
              cg.a_call_name(list,'FPC_RANGEERROR');
 
 
@@ -587,7 +639,11 @@ unit cg64f32;
                    end
                    end
                  else
                  else
                    begin
                    begin
+                   {$ifdef newra}
+                     hreg:=rg.getregisterint(list,OS_INT);
+                   {$else}
                      hreg := cg.get_scratch_reg_int(list,OS_INT);
                      hreg := cg.get_scratch_reg_int(list,OS_INT);
+                   {$endif}
                      got_scratch := true;
                      got_scratch := true;
                      a_load64low_ref_reg(list,p.location.reference,hreg);
                      a_load64low_ref_reg(list,p.location.reference,hreg);
                    end;
                    end;
@@ -595,8 +651,13 @@ unit cg64f32;
                  objectlibrary.getlabel(neglabel);
                  objectlibrary.getlabel(neglabel);
                  cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
                  cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
                  { !!! freeing of register should happen directly after compare! (JM) }
                  { !!! freeing of register should happen directly after compare! (JM) }
+               {$ifdef newra}
+                 if got_scratch then
+                   rg.ungetregisterint(list,hreg);
+               {$else}
                  if got_scratch then
                  if got_scratch then
                    cg.free_scratch_reg(list,hreg);
                    cg.free_scratch_reg(list,hreg);
+               {$endif}
 
 
                  cg.a_call_name(list,'FPC_RANGEERROR');
                  cg.a_call_name(list,'FPC_RANGEERROR');
 
 
@@ -641,7 +702,11 @@ unit cg64f32;
                  end
                  end
                else
                else
                  begin
                  begin
+                 {$ifdef newra}
+                   hreg:=rg.getregisterint(list,OS_INT);
+                 {$else}
                    hreg := cg.get_scratch_reg_int(list,OS_INT);
                    hreg := cg.get_scratch_reg_int(list,OS_INT);
+                 {$endif}
                    got_scratch := true;
                    got_scratch := true;
 
 
                    opsize := def_cgsize(p.resulttype.def);
                    opsize := def_cgsize(p.resulttype.def);
@@ -654,8 +719,13 @@ unit cg64f32;
                cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
                cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
 
 
                { !!! freeing of register should happen directly after compare! (JM) }
                { !!! freeing of register should happen directly after compare! (JM) }
+             {$ifdef newra}
+               if got_scratch then
+                 rg.ungetregisterint(list,hreg);
+             {$else}
                if got_scratch then
                if got_scratch then
                  cg.free_scratch_reg(list,hreg);
                  cg.free_scratch_reg(list,hreg);
+             {$endif}
                cg.a_call_name(list,'FPC_RANGEERROR');
                cg.a_call_name(list,'FPC_RANGEERROR');
                cg.a_label(list,poslabel);
                cg.a_label(list,poslabel);
              end;
              end;
@@ -766,7 +836,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.38  2003-04-07 08:52:58  jonas
+  Revision 1.39  2003-04-22 10:09:34  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.38  2003/04/07 08:52:58  jonas
     * fixed compiling error
     * fixed compiling error
 
 
   Revision 1.37  2003/04/07 08:45:09  jonas
   Revision 1.37  2003/04/07 08:45:09  jonas

+ 128 - 3
compiler/cgobj.pas

@@ -59,9 +59,11 @@ unit cgobj;
           sould be @link(tcg64f32) and not @var(tcg).
           sould be @link(tcg64f32) and not @var(tcg).
        }
        }
        tcg = class
        tcg = class
+{$ifndef newra}
           scratch_register_array_pointer : aword;
           scratch_register_array_pointer : aword;
           {# List of currently unused scratch registers }
           {# List of currently unused scratch registers }
           unusedscratchregisters:Tsupregset;
           unusedscratchregisters:Tsupregset;
+{$endif}
 
 
           alignment : talignment;
           alignment : talignment;
           {************************************************}
           {************************************************}
@@ -79,6 +81,7 @@ unit cgobj;
           {# Deallocates register r by inserting a pa_regdealloc record}
           {# Deallocates register r by inserting a pa_regdealloc record}
           procedure a_reg_dealloc(list : taasmoutput;r : tregister);
           procedure a_reg_dealloc(list : taasmoutput;r : tregister);
 
 
+{$ifndef newra}
           {# @abstract(Returns an int register for use as scratch register)
           {# @abstract(Returns an int register for use as scratch register)
              This routine returns a register which can be used by
              This routine returns a register which can be used by
              the code generator as a general purpose scratch register.
              the code generator as a general purpose scratch register.
@@ -102,6 +105,7 @@ unit cgobj;
              was previously allocated using @link(get_scratch_reg).
              was previously allocated using @link(get_scratch_reg).
           }
           }
           procedure free_scratch_reg(list : taasmoutput;r : tregister);
           procedure free_scratch_reg(list : taasmoutput;r : tregister);
+{$endif newra}
           {# Pass a parameter, which is located in a register, to a routine.
           {# Pass a parameter, which is located in a register, to a routine.
 
 
              This routine should push/send the parameter to the routine, as
              This routine should push/send the parameter to the routine, as
@@ -503,7 +507,9 @@ unit cgobj;
        rgobj,cutils;
        rgobj,cutils;
 
 
     const
     const
+{$ifndef newra}
       max_scratch_regs = high(scratch_regs) - low(scratch_regs) + 1;
       max_scratch_regs = high(scratch_regs) - low(scratch_regs) + 1;
+{$endif}
 
 
       { Please leave this here, this module should NOT use
       { Please leave this here, this module should NOT use
         exprasmlist, the lists are always passed as arguments.
         exprasmlist, the lists are always passed as arguments.
@@ -520,9 +526,11 @@ unit cgobj;
          i : longint;
          i : longint;
 
 
       begin
       begin
+{$ifndef newra}
          scratch_register_array_pointer:=1;
          scratch_register_array_pointer:=1;
          for i:=low(scratch_regs) to high(scratch_regs) do
          for i:=low(scratch_regs) to high(scratch_regs) do
            include(unusedscratchregisters,scratch_regs[i]);
            include(unusedscratchregisters,scratch_regs[i]);
+{$endif}
       end;
       end;
 
 
     procedure tcg.a_reg_alloc(list : taasmoutput;r : tregister);
     procedure tcg.a_reg_alloc(list : taasmoutput;r : tregister);
@@ -543,6 +551,7 @@ unit cgobj;
          list.concat(tai_label.create(l));
          list.concat(tai_label.create(l));
       end;
       end;
 
 
+{$ifndef newra}
     function tcg.get_scratch_reg_int(list:taasmoutput;size:Tcgsize):tregister;
     function tcg.get_scratch_reg_int(list:taasmoutput;size:Tcgsize):tregister;
 
 
       var
       var
@@ -587,6 +596,7 @@ unit cgobj;
          include(unusedscratchregisters,r.number shr 8);
          include(unusedscratchregisters,r.number shr 8);
          a_reg_dealloc(list,r);
          a_reg_dealloc(list,r);
       end;
       end;
+{$endif newra}
 
 
 {*****************************************************************************
 {*****************************************************************************
           for better code generation these methods should be overridden
           for better code generation these methods should be overridden
@@ -626,20 +636,36 @@ unit cgobj;
          hr : tregister;
          hr : tregister;
 
 
       begin
       begin
+      {$ifdef newra}
+         hr:=rg.getregisterint(list,size);
+      {$else}
          hr:=get_scratch_reg_int(list,size);
          hr:=get_scratch_reg_int(list,size);
+      {$endif}
          a_load_const_reg(list,size,a,hr);
          a_load_const_reg(list,size,a,hr);
          a_param_reg(list,size,hr,locpara);
          a_param_reg(list,size,hr,locpara);
+      {$ifdef newra}
+         rg.ungetregisterint(list,hr);
+      {$else}
          free_scratch_reg(list,hr);
          free_scratch_reg(list,hr);
+      {$endif}
       end;
       end;
 
 
     procedure tcg.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
     procedure tcg.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
       var
       var
          hr : tregister;
          hr : tregister;
       begin
       begin
+      {$ifdef newra}
+         hr:=rg.getregisterint(list,size);
+      {$else}
          hr:=get_scratch_reg_int(list,size);
          hr:=get_scratch_reg_int(list,size);
+      {$endif}
          a_load_ref_reg(list,size,r,hr);
          a_load_ref_reg(list,size,r,hr);
          a_param_reg(list,size,hr,locpara);
          a_param_reg(list,size,hr,locpara);
+      {$ifdef newra}
+         rg.ungetregisterint(list,hr);
+      {$else}
          free_scratch_reg(list,hr);
          free_scratch_reg(list,hr);
+      {$endif}
       end;
       end;
 
 
 
 
@@ -664,10 +690,18 @@ unit cgobj;
       var
       var
          hr : tregister;
          hr : tregister;
       begin
       begin
+      {$ifdef newra}
+         hr:=rg.getaddressregister(list);
+      {$else newra}
          hr:=get_scratch_reg_address(list);
          hr:=get_scratch_reg_address(list);
+      {$endif}
          a_loadaddr_ref_reg(list,r,hr);
          a_loadaddr_ref_reg(list,r,hr);
          a_param_reg(list,OS_ADDR,hr,locpara);
          a_param_reg(list,OS_ADDR,hr,locpara);
+      {$ifdef newra}
+         rg.ungetregisterint(list,hr);
+      {$else}
          free_scratch_reg(list,hr);
          free_scratch_reg(list,hr);
+      {$endif}
       end;
       end;
 
 
 
 
@@ -732,7 +766,11 @@ unit cgobj;
             tmpreg := rg.getregisterint(list,size)
             tmpreg := rg.getregisterint(list,size)
         else
         else
 {$endif i386}
 {$endif i386}
+{$ifdef newra}
+        tmpreg:=rg.getregisterint(list,size);
+{$else}
         tmpreg := get_scratch_reg_int(list,size);
         tmpreg := get_scratch_reg_int(list,size);
+{$endif}
         a_load_ref_reg(list,size,sref,tmpreg);
         a_load_ref_reg(list,size,sref,tmpreg);
         a_load_reg_ref(list,size,tmpreg,dref);
         a_load_reg_ref(list,size,tmpreg,dref);
 {$ifdef i386}
 {$ifdef i386}
@@ -745,7 +783,11 @@ unit cgobj;
           end
           end
         else
         else
 {$endif i386}
 {$endif i386}
+{$ifdef newra}
+        rg.ungetregisterint(list,tmpreg);
+{$else}
         free_scratch_reg(list,tmpreg);
         free_scratch_reg(list,tmpreg);
+{$endif}
       end;
       end;
 
 
 
 
@@ -755,10 +797,18 @@ unit cgobj;
         tmpreg: tregister;
         tmpreg: tregister;
 
 
       begin
       begin
+{$ifdef newra}
+        tmpreg:=rg.getregisterint(list,size);
+{$else}
         tmpreg := get_scratch_reg_int(list,size);
         tmpreg := get_scratch_reg_int(list,size);
+{$endif}
         a_load_const_reg(list,size,a,tmpreg);
         a_load_const_reg(list,size,a,tmpreg);
         a_load_reg_ref(list,size,tmpreg,ref);
         a_load_reg_ref(list,size,tmpreg,ref);
+{$ifdef newra}
+        rg.ungetregisterint(list,tmpreg);
+{$else}
         free_scratch_reg(list,tmpreg);
         free_scratch_reg(list,tmpreg);
+{$endif}
       end;
       end;
 
 
 
 
@@ -949,11 +999,19 @@ unit cgobj;
         tmpreg: tregister;
         tmpreg: tregister;
 
 
       begin
       begin
+      {$ifdef newra}
+        tmpreg:=rg.getregisterint(list,size);
+      {$else}
         tmpreg := get_scratch_reg_int(list,size);
         tmpreg := get_scratch_reg_int(list,size);
+      {$endif}
         a_load_ref_reg(list,size,ref,tmpreg);
         a_load_ref_reg(list,size,ref,tmpreg);
         a_op_const_reg(list,op,a,tmpreg);
         a_op_const_reg(list,op,a,tmpreg);
         a_load_reg_ref(list,size,tmpreg,ref);
         a_load_reg_ref(list,size,tmpreg,ref);
+      {$ifdef newra}
+        rg.ungetregisterint(list,tmpreg);
+      {$else}
         free_scratch_reg(list,tmpreg);
         free_scratch_reg(list,tmpreg);
+      {$endif}
       end;
       end;
 
 
 
 
@@ -977,11 +1035,19 @@ unit cgobj;
         tmpreg: tregister;
         tmpreg: tregister;
 
 
       begin
       begin
+      {$ifdef newra}
+        tmpreg:=rg.getregisterint(list,size);
+      {$else}
         tmpreg := get_scratch_reg_int(list,size);
         tmpreg := get_scratch_reg_int(list,size);
+      {$endif}
         a_load_ref_reg(list,size,ref,tmpreg);
         a_load_ref_reg(list,size,ref,tmpreg);
         a_op_reg_reg(list,op,size,reg,tmpreg);
         a_op_reg_reg(list,op,size,reg,tmpreg);
         a_load_reg_ref(list,size,tmpreg,ref);
         a_load_reg_ref(list,size,tmpreg,ref);
+      {$ifdef newra}
+        rg.ungetregisterint(list,tmpreg);
+      {$else}
         free_scratch_reg(list,tmpreg);
         free_scratch_reg(list,tmpreg);
+      {$endif}
       end;
       end;
 
 
 
 
@@ -1000,10 +1066,18 @@ unit cgobj;
             end;
             end;
           else
           else
             begin
             begin
+            {$ifdef newra}
+              tmpreg:=rg.getregisterint(list,size);
+            {$else}
               tmpreg := get_scratch_reg_int(list,size);
               tmpreg := get_scratch_reg_int(list,size);
+            {$endif}
               a_load_ref_reg(list,size,ref,tmpreg);
               a_load_ref_reg(list,size,ref,tmpreg);
               a_op_reg_reg(list,op,size,tmpreg,reg);
               a_op_reg_reg(list,op,size,tmpreg,reg);
+            {$ifdef newra}
+              rg.ungetregisterint(list,tmpreg);
+            {$else}
               free_scratch_reg(list,tmpreg);
               free_scratch_reg(list,tmpreg);
+            {$endif}
             end;
             end;
         end;
         end;
       end;
       end;
@@ -1034,10 +1108,18 @@ unit cgobj;
             a_op_ref_reg(list,op,loc.size,ref,loc.register);
             a_op_ref_reg(list,op,loc.size,ref,loc.register);
           LOC_REFERENCE,LOC_CREFERENCE:
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
             begin
+            {$ifdef newra}
+              tmpreg:=rg.getregisterint(list,loc.size);
+            {$else}
               tmpreg := get_scratch_reg_int(list,loc.size);
               tmpreg := get_scratch_reg_int(list,loc.size);
+            {$endif}
               a_load_ref_reg(list,loc.size,ref,tmpreg);
               a_load_ref_reg(list,loc.size,ref,tmpreg);
               a_op_reg_ref(list,op,loc.size,tmpreg,loc.reference);
               a_op_reg_ref(list,op,loc.size,tmpreg,loc.reference);
+            {$ifdef newra}
+              rg.ungetregisterint(list,tmpreg);
+            {$else}
               free_scratch_reg(list,tmpreg);
               free_scratch_reg(list,tmpreg);
+            {$endif}
             end;
             end;
           else
           else
             internalerror(200109061);
             internalerror(200109061);
@@ -1067,10 +1149,18 @@ unit cgobj;
         tmpreg: tregister;
         tmpreg: tregister;
 
 
       begin
       begin
+      {$ifdef newra}
+        tmpreg:=rg.getregisterint(list,size);
+      {$else}
         tmpreg := get_scratch_reg_int(list,size);
         tmpreg := get_scratch_reg_int(list,size);
+      {$endif}
         a_load_ref_reg(list,size,ref,tmpreg);
         a_load_ref_reg(list,size,ref,tmpreg);
         a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
         a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
+      {$ifdef newra}
+        rg.ungetregisterint(list,tmpreg);
+      {$else}
         free_scratch_reg(list,tmpreg);
         free_scratch_reg(list,tmpreg);
+      {$endif}
       end;
       end;
 
 
     procedure tcg.a_cmp_const_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const loc : tlocation;
     procedure tcg.a_cmp_const_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const loc : tlocation;
@@ -1093,10 +1183,18 @@ unit cgobj;
         tmpreg: tregister;
         tmpreg: tregister;
 
 
       begin
       begin
+      {$ifdef newra}
+        tmpreg:=rg.getregisterint(list,size);
+      {$else}
         tmpreg := get_scratch_reg_int(list,size);
         tmpreg := get_scratch_reg_int(list,size);
+      {$endif}
         a_load_ref_reg(list,size,ref,tmpreg);
         a_load_ref_reg(list,size,ref,tmpreg);
         a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
         a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
+      {$ifdef newra}
+        rg.ungetregisterint(list,tmpreg);
+      {$else}
         free_scratch_reg(list,tmpreg);
         free_scratch_reg(list,tmpreg);
+      {$endif}
       end;
       end;
 
 
     procedure tcg.a_cmp_loc_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
     procedure tcg.a_cmp_loc_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
@@ -1128,6 +1226,12 @@ unit cgobj;
             a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
             a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
           LOC_REFERENCE,LOC_CREFERENCE:
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
             begin
+{$ifdef newra}
+              tmpreg := rg.getregisterint(list,size);
+              a_load_ref_reg(list,size,loc.reference,tmpreg);
+              a_cmp_ref_reg_label(list,size,cmp_op,ref,tmpreg,l);
+              rg.ungetregisterint(list,tmpreg);
+{$else newra}
 {$ifdef i386}
 {$ifdef i386}
               { the following is done with defines to avoid a speed penalty,  }
               { the following is done with defines to avoid a speed penalty,  }
               { since all this is only necessary for the 80x86 (because EDI   }
               { since all this is only necessary for the 80x86 (because EDI   }
@@ -1145,7 +1249,8 @@ unit cgobj;
                 rg.ungetregisterint(list,tmpreg)
                 rg.ungetregisterint(list,tmpreg)
               else
               else
 {$endif i386}
 {$endif i386}
-              free_scratch_reg(list,tmpreg);
+                free_scratch_reg(list,tmpreg);
+{$endif newra}
             end
             end
           else
           else
             internalerror(200109061);
             internalerror(200109061);
@@ -1392,8 +1497,11 @@ unit cgobj;
               if lto < 0 then
               if lto < 0 then
                 lto := 0;
                 lto := 0;
             end;
             end;
-
+{$ifdef newra}
+        hreg:=rg.getregisterint(list,OS_INT);
+{$else}
         hreg := get_scratch_reg_int(list,OS_INT);
         hreg := get_scratch_reg_int(list,OS_INT);
+{$endif}
         if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
         if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
           a_op_const_reg_reg(list,OP_SUB,def_cgsize(p.resulttype.def),
           a_op_const_reg_reg(list,OP_SUB,def_cgsize(p.resulttype.def),
            aword(lto),p.location.register,hreg)
            aword(lto),p.location.register,hreg)
@@ -1406,7 +1514,11 @@ unit cgobj;
         objectlibrary.getlabel(neglabel);
         objectlibrary.getlabel(neglabel);
         a_cmp_const_reg_label(list,OS_INT,OC_BE,aword(hto-lto),hreg,neglabel);
         a_cmp_const_reg_label(list,OS_INT,OC_BE,aword(hto-lto),hreg,neglabel);
         { !!! should happen right after the compare (JM) }
         { !!! should happen right after the compare (JM) }
+{$ifdef newra}
+        rg.ungetregisterint(list,hreg);
+{$else}
         free_scratch_reg(list,hreg);
         free_scratch_reg(list,hreg);
+{$endif}
         a_call_name(list,'FPC_RANGEERROR');
         a_call_name(list,'FPC_RANGEERROR');
         a_label(list,neglabel);
         a_label(list,neglabel);
       end;
       end;
@@ -1425,10 +1537,18 @@ unit cgobj;
       var
       var
         tmpreg : tregister;
         tmpreg : tregister;
       begin
       begin
+      {$ifdef newra}
+        tmpreg:=rg.getregisterint(list,size);
+      {$else}
         tmpreg := get_scratch_reg_int(list,size);
         tmpreg := get_scratch_reg_int(list,size);
+      {$endif}
         g_flags2reg(list,size,f,tmpreg);
         g_flags2reg(list,size,f,tmpreg);
         a_load_reg_ref(list,size,tmpreg,ref);
         a_load_reg_ref(list,size,tmpreg,ref);
+      {$ifdef newra}
+        rg.ungetregisterint(list,tmpreg);
+      {$else}
         free_scratch_reg(list,tmpreg);
         free_scratch_reg(list,tmpreg);
+      {$endif}
       end;
       end;
 
 
 
 
@@ -1719,7 +1839,12 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.81  2003-04-06 21:11:23  olle
+  Revision 1.82  2003-04-22 10:09:34  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.81  2003/04/06 21:11:23  olle
     * changed newasmsymbol to newasmsymboldata for data symbols
     * changed newasmsymbol to newasmsymboldata for data symbols
 
 
   Revision 1.80  2003/03/28 19:16:56  peter
   Revision 1.80  2003/03/28 19:16:56  peter

+ 18 - 1
compiler/i386/aasmcpu.pas

@@ -199,6 +199,7 @@ interface
          function  NeedAddrPrefix(opidx:byte):boolean;
          function  NeedAddrPrefix(opidx:byte):boolean;
          procedure Swapoperands;
          procedure Swapoperands;
     {$endif NOAG386BIN}
     {$endif NOAG386BIN}
+         function is_nop:boolean;override;
       end;
       end;
 
 
 
 
@@ -1898,6 +1899,17 @@ implementation
       end;
       end;
 {$endif NOAG386BIN}
 {$endif NOAG386BIN}
 
 
+    function Taicpu.is_nop:boolean;
+
+    begin
+      {We do not check the number of operands; we assume that nobody constructs
+       a mov or xchg instruction with less than 2 operands.}
+      is_nop:=(opcode=A_NOP) or
+              (opcode=A_MOV) and (oper[0].typ=top_reg) and (oper[1].typ=top_reg) and (oper[0].reg.number=oper[1].reg.number) or
+              (opcode=A_XCHG) and (oper[0].typ=top_reg) and (oper[1].typ=top_reg) and (oper[0].reg.number=oper[1].reg.number);
+    end;
+
+
 {*****************************************************************************
 {*****************************************************************************
                               Instruction table
                               Instruction table
 *****************************************************************************}
 *****************************************************************************}
@@ -1947,7 +1959,12 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.15  2003-03-26 12:50:54  armin
+  Revision 1.16  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.15  2003/03/26 12:50:54  armin
   * avoid problems with the ide in init/dome
   * avoid problems with the ide in init/dome
 
 
   Revision 1.14  2003/03/08 08:59:07  daniel
   Revision 1.14  2003/03/08 08:59:07  daniel

+ 7 - 2
compiler/i386/ag386nsm.pas

@@ -460,7 +460,7 @@ interface
                else
                else
                 regstr:=std_reg2str[tai_regalloc(hp).reg.enum];
                 regstr:=std_reg2str[tai_regalloc(hp).reg.enum];
                if (cs_asm_regalloc in aktglobalswitches) then
                if (cs_asm_regalloc in aktglobalswitches) then
-                 AsmWriteLn(target_asm.comment+'Register '+regstr+
+                 AsmWriteLn(#9#9+target_asm.comment+'Register '+regstr+
                    allocstr[tai_regalloc(hp).allocation]);
                    allocstr[tai_regalloc(hp).allocation]);
              end;
              end;
 
 
@@ -921,7 +921,12 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.32  2003-03-08 13:59:17  daniel
+  Revision 1.33  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.32  2003/03/08 13:59:17  daniel
     * Work to handle new register notation in ag386nsm
     * Work to handle new register notation in ag386nsm
     + Added newra version of Ti386moddivnode
     + Added newra version of Ti386moddivnode
 
 

+ 8 - 1
compiler/i386/cpubase.pas

@@ -552,8 +552,10 @@ uses
       {# Registers which are defined as scratch and no need to save across
       {# Registers which are defined as scratch and no need to save across
          routine calls or in assembler blocks.
          routine calls or in assembler blocks.
       }
       }
+{$ifndef newra}
       max_scratch_regs = 1;
       max_scratch_regs = 1;
       scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
       scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
+{$endif}
 
 
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -814,7 +816,12 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.46  2003-04-21 19:16:50  peter
+  Revision 1.47  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.46  2003/04/21 19:16:50  peter
     * count address regs separate
     * count address regs separate
 
 
   Revision 1.45  2003/03/28 19:16:57  peter
   Revision 1.45  2003/03/28 19:16:57  peter

+ 14 - 1
compiler/i386/n386add.pas

@@ -84,13 +84,17 @@ interface
         secondpass(left);
         secondpass(left);
 
 
         { are too few registers free? }
         { are too few registers free? }
+      {$ifndef newra}
         maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
         maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+      {$endif newra}
         if location.loc=LOC_FPUREGISTER then
         if location.loc=LOC_FPUREGISTER then
           pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
           pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
         else
         else
           pushedfpu:=false;
           pushedfpu:=false;
         secondpass(right);
         secondpass(right);
+      {$ifndef newra}
         maybe_restore(exprasmlist,left.location,pushedregs);
         maybe_restore(exprasmlist,left.location,pushedregs);
+      {$endif}
       end;
       end;
 
 
 
 
@@ -476,7 +480,9 @@ interface
                falselabel:=ofl;
                falselabel:=ofl;
              end;
              end;
 
 
+          {$ifndef newra}
             maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
             maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+          {$endif}
             isjump:=(right.location.loc=LOC_JUMP);
             isjump:=(right.location.loc=LOC_JUMP);
             if isjump then
             if isjump then
               begin
               begin
@@ -486,7 +492,9 @@ interface
                  objectlibrary.getlabel(falselabel);
                  objectlibrary.getlabel(falselabel);
               end;
               end;
             secondpass(right);
             secondpass(right);
+          {$ifndef newra}
             maybe_restore(exprasmlist,left.location,pushedregs);
             maybe_restore(exprasmlist,left.location,pushedregs);
+          {$endif newra}
             if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
             if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
              location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false);
              location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false);
             if isjump then
             if isjump then
@@ -1642,7 +1650,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.61  2003-04-17 10:02:48  daniel
+  Revision 1.62  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.61  2003/04/17 10:02:48  daniel
     * Tweaked register allocate/deallocate positition to less interferences
     * Tweaked register allocate/deallocate positition to less interferences
       are generated.
       are generated.
 
 

+ 22 - 1
compiler/i386/n386cal.pas

@@ -146,9 +146,17 @@ implementation
         { better than an add on all processors }
         { better than an add on all processors }
         if pop_size=4 then
         if pop_size=4 then
           begin
           begin
+          {$ifdef newra}
+            hreg:=rg.getregisterint(exprasmlist,OS_INT);
+          {$else}
             hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
             hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+          {$endif}
             exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
             exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
+          {$ifdef newra}
+            rg.ungetregisterint(exprasmlist,hreg);
+          {$else}
             cg.free_scratch_reg(exprasmlist,hreg);
             cg.free_scratch_reg(exprasmlist,hreg);
+          {$endif newra}
           end
           end
         { the pentium has two pipes and pop reg is pairable }
         { the pentium has two pipes and pop reg is pairable }
         { but the registers must be different!        }
         { but the registers must be different!        }
@@ -158,9 +166,17 @@ implementation
              (aktoptprocessor=ClassP5) and
              (aktoptprocessor=ClassP5) and
              (rg.countunusedregsint>0) then
              (rg.countunusedregsint>0) then
             begin
             begin
+            {$ifdef newra}
+               hreg:=rg.getregisterint(exprasmlist,OS_INT);
+            {$else}
                hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
                hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+            {$endif}
                exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
                exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
+            {$ifdef newra}
+               rg.ungetregisterint(exprasmlist,hreg);
+            {$else}
                cg.free_scratch_reg(exprasmlist,hreg);
                cg.free_scratch_reg(exprasmlist,hreg);
+            {$endif}
                hreg:=rg.getregisterint(exprasmlist,OS_INT);
                hreg:=rg.getregisterint(exprasmlist,OS_INT);
                exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
                exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
                rg.ungetregisterint(exprasmlist,hreg);
                rg.ungetregisterint(exprasmlist,hreg);
@@ -185,7 +201,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.87  2003-04-04 15:38:56  peter
+  Revision 1.88  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.87  2003/04/04 15:38:56  peter
     * moved generic code from n386cal to ncgcal, i386 now also
     * moved generic code from n386cal to ncgcal, i386 now also
       uses the generic ncgcal
       uses the generic ncgcal
 
 

+ 27 - 1
compiler/i386/n386cnv.pas

@@ -117,7 +117,11 @@ implementation
                    hregister:=left.location.register;
                    hregister:=left.location.register;
                  else
                  else
                    begin
                    begin
+                    {$ifdef newra}
+                     hregister:=rg.getregisterint(exprasmlist,OS_32);
+                    {$else}
                      hregister:=cg.get_scratch_reg_int(exprasmlist,OS_32);
                      hregister:=cg.get_scratch_reg_int(exprasmlist,OS_32);
+                    {$endif}
                      freereg:=true;
                      freereg:=true;
                      cg.a_load_reg_reg(exprasmlist,left.location.size,OS_32,left.location.register,hregister);
                      cg.a_load_reg_reg(exprasmlist,left.location.size,OS_32,left.location.register,hregister);
                    end;
                    end;
@@ -126,7 +130,11 @@ implementation
            LOC_REFERENCE,
            LOC_REFERENCE,
            LOC_CREFERENCE :
            LOC_CREFERENCE :
              begin
              begin
+              {$ifdef newra}
+               hregister:=rg.getregisterint(exprasmlist,OS_INT);
+              {$else}
                hregister:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
                hregister:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+              {$endif newra}
                freereg:=true;
                freereg:=true;
                if left.location.size in [OS_64,OS_S64] then
                if left.location.size in [OS_64,OS_S64] then
                 begin
                 begin
@@ -147,8 +155,13 @@ implementation
 
 
          { for 64 bit integers, the high dword is already pushed }
          { for 64 bit integers, the high dword is already pushed }
          exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,hregister));
          exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,hregister));
+        {$ifdef newra}
+         if freereg then
+           rg.ungetregisterint(exprasmlist,hregister);
+        {$else}
          if freereg then
          if freereg then
            cg.free_scratch_reg(exprasmlist,hregister);
            cg.free_scratch_reg(exprasmlist,hregister);
+        {$endif}
          r.enum:=R_INTREGISTER;
          r.enum:=R_INTREGISTER;
          r.number:=NR_ESP;
          r.number:=NR_ESP;
          reference_reset_base(href,r,0);
          reference_reset_base(href,r,0);
@@ -268,10 +281,18 @@ implementation
               begin
               begin
                 if left.location.size in [OS_64,OS_S64] then
                 if left.location.size in [OS_64,OS_S64] then
                  begin
                  begin
+                 {$ifdef newra}
+                   hregister:=rg.getregisterint(exprasmlist,OS_32);
+                 {$else}
                    hregister:=cg.get_scratch_reg_int(exprasmlist,OS_32);
                    hregister:=cg.get_scratch_reg_int(exprasmlist,OS_32);
+                 {$endif}
                    cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,left.location.registerlow,hregister);
                    cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,left.location.registerlow,hregister);
                    cg.a_op_reg_reg(exprasmlist,OP_OR,OS_32,left.location.registerhigh,hregister);
                    cg.a_op_reg_reg(exprasmlist,OP_OR,OS_32,left.location.registerhigh,hregister);
+                 {$ifdef newra}
+                   rg.ungetregisterint(exprasmlist,hregister);
+                 {$else}
                    cg.free_scratch_reg(exprasmlist,hregister);
                    cg.free_scratch_reg(exprasmlist,hregister);
+                 {$endif}
                  end
                  end
                 else
                 else
                  cg.a_op_reg_reg(exprasmlist,OP_OR,left.location.size,left.location.register,left.location.register);
                  cg.a_op_reg_reg(exprasmlist,OP_OR,left.location.size,left.location.register,left.location.register);
@@ -432,7 +453,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.57  2003-03-13 19:52:23  jonas
+  Revision 1.58  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.57  2003/03/13 19:52:23  jonas
     * and more new register allocator fixes (in the i386 code generator this
     * and more new register allocator fixes (in the i386 code generator this
       time). At least now the ppc cross compiler can compile the linux
       time). At least now the ppc cross compiler can compile the linux
       system unit again, but I haven't tested it.
       system unit again, but I haven't tested it.

+ 19 - 1
compiler/i386/n386inl.pas

@@ -288,10 +288,14 @@ implementation
           else
           else
             begin
             begin
               { generate code for the element to set }
               { generate code for the element to set }
+            {$ifndef newra}
               maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
               maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
                         tcallparanode(left).left.location,pushedregs);
                         tcallparanode(left).left.location,pushedregs);
+            {$endif}
               secondpass(tcallparanode(tcallparanode(left).right).left);
               secondpass(tcallparanode(tcallparanode(left).right).left);
+            {$ifndef newra}
               maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
               maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
+            {$endif}
               { determine asm operator }
               { determine asm operator }
               if inlinenumber=in_include_x_y then
               if inlinenumber=in_include_x_y then
                  asmop:=A_BTS
                  asmop:=A_BTS
@@ -316,15 +320,24 @@ implementation
               else
               else
                 begin
                 begin
                   scratch_reg := TRUE;
                   scratch_reg := TRUE;
+                {$ifdef newra}
+                  hregister:=rg.getregisterint(exprasmlist,OS_INT);
+                {$else}
                   hregister:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
                   hregister:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+                {$endif newra}
                 end;
                 end;
               cg.a_load_loc_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,hregister);
               cg.a_load_loc_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,hregister);
               if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
               if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
                 emit_reg_ref(asmop,S_L,hregister,tcallparanode(left).left.location.reference)
                 emit_reg_ref(asmop,S_L,hregister,tcallparanode(left).left.location.reference)
               else
               else
                 emit_reg_reg(asmop,S_L,hregister,tcallparanode(left).left.location.register);
                 emit_reg_reg(asmop,S_L,hregister,tcallparanode(left).left.location.register);
+            {$ifdef newra}
+              if scratch_reg then
+                rg.ungetregisterint(exprasmlist,hregister);
+            {$else}
               if scratch_reg then
               if scratch_reg then
                 cg.free_scratch_reg(exprasmlist,hregister);
                 cg.free_scratch_reg(exprasmlist,hregister);
+            {$endif newra}
             end;
             end;
         end;
         end;
 
 
@@ -334,7 +347,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.56  2003-02-19 22:00:15  daniel
+  Revision 1.57  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.56  2003/02/19 22:00:15  daniel
     * Code generator converted to new register notation
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
     - Horribily outdated todo.txt removed
 
 

+ 19 - 5
compiler/i386/n386mat.pas

@@ -77,9 +77,7 @@ implementation
       secondpass(left);
       secondpass(left);
       if codegenerror then
       if codegenerror then
         exit;
         exit;
-      maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
       secondpass(right);
       secondpass(right);
-      maybe_restore(exprasmlist,left.location,pushedregs);
       if codegenerror then
       if codegenerror then
         exit;
         exit;
 
 
@@ -154,15 +152,22 @@ implementation
             emit_none(A_CDQ,S_NO);
             emit_none(A_CDQ,S_NO);
 
 
           {Division depends on the right type.}
           {Division depends on the right type.}
-          if torddef(right.resulttype.def).typ=u32bit then
+          if Torddef(right.resulttype.def).typ=u32bit then
             op:=A_DIV
             op:=A_DIV
           else
           else
             op:=A_IDIV;
             op:=A_IDIV;
 
 
           if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
           if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
             emit_ref(op,S_L,right.location.reference)
             emit_ref(op,S_L,right.location.reference)
+          else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+            emit_reg(op,S_L,right.location.register)
           else
           else
-            emit_reg(op,S_L,right.location.register);
+            begin
+              hreg1:=rg.getregisterint(exprasmlist,right.location.size);
+              cg.a_load_loc_reg(exprasmlist,right.location,hreg1);
+              rg.ungetregisterint(exprasmlist,hreg1);
+              emit_reg(op,S_L,hreg1);
+            end;
           location_release(exprasmlist,right.location);
           location_release(exprasmlist,right.location);
 
 
           {Copy the result into a new register. Release EAX & EDX.}
           {Copy the result into a new register. Release EAX & EDX.}
@@ -425,9 +430,13 @@ implementation
 
 
     begin
     begin
       secondpass(left);
       secondpass(left);
+    {$ifndef newra}
       maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
       maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+    {$endif}
       secondpass(right);
       secondpass(right);
+    {$ifndef newra}
       maybe_restore(exprasmlist,left.location,pushedregs);
       maybe_restore(exprasmlist,left.location,pushedregs);
+    {$endif newra}
 
 
       { determine operator }
       { determine operator }
       if nodetype=shln then
       if nodetype=shln then
@@ -1172,7 +1181,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.50  2003-04-21 19:15:26  peter
+  Revision 1.51  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.50  2003/04/21 19:15:26  peter
     * when ecx is not available allocated another register
     * when ecx is not available allocated another register
 
 
   Revision 1.49  2003/04/17 10:02:48  daniel
   Revision 1.49  2003/04/17 10:02:48  daniel

+ 10 - 1
compiler/i386/n386set.pas

@@ -200,9 +200,13 @@ implementation
          { Only process the right if we are not generating jumps }
          { Only process the right if we are not generating jumps }
          if not genjumps then
          if not genjumps then
           begin
           begin
+          {$ifndef newra}
             maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
             maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+          {$endif}
             secondpass(right);
             secondpass(right);
+          {$ifndef newra}
             maybe_restore(exprasmlist,left.location,pushedregs);
             maybe_restore(exprasmlist,left.location,pushedregs);
+          {$endif newra}
           end;
           end;
          if codegenerror then
          if codegenerror then
           exit;
           exit;
@@ -720,7 +724,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.51  2003-03-13 19:52:23  jonas
+  Revision 1.52  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.51  2003/03/13 19:52:23  jonas
     * and more new register allocator fixes (in the i386 code generator this
     * and more new register allocator fixes (in the i386 code generator this
       time). At least now the ppc cross compiler can compile the linux
       time). At least now the ppc cross compiler can compile the linux
       system unit again, but I haven't tested it.
       system unit again, but I haven't tested it.

+ 9 - 4
compiler/i386/rgcpu.pas

@@ -329,9 +329,9 @@ unit rgcpu;
     procedure trgcpu.ungetreference(list: taasmoutput; const ref : treference);
     procedure trgcpu.ungetreference(list: taasmoutput; const ref : treference);
 
 
       begin
       begin
-         if ref.base.number<>NR_NO then
+         if (ref.base.number<>NR_NO) and (ref.base.number<>NR_FRAME_POINTER_REG) then
            ungetregisterint(list,ref.base);
            ungetregisterint(list,ref.base);
-         if ref.index.number<>NR_NO then
+         if (ref.index.number<>NR_NO) and (ref.index.number<>NR_FRAME_POINTER_REG) then
            ungetregisterint(list,ref.index);
            ungetregisterint(list,ref.index);
       end;
       end;
 
 
@@ -557,12 +557,17 @@ unit rgcpu;
 
 
 
 
 initialization
 initialization
-  rg := trgcpu.create;
+  rg := trgcpu.create(7);   {We use 7 int registers on i386.}
 end.
 end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.18  2003-04-21 19:16:50  peter
+  Revision 1.19  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.18  2003/04/21 19:16:50  peter
     * count address regs separate
     * count address regs separate
 
 
   Revision 1.17  2003/03/28 19:16:57  peter
   Revision 1.17  2003/03/28 19:16:57  peter

+ 7 - 2
compiler/m68k/rgcpu.pas

@@ -210,12 +210,17 @@ unit rgcpu;
 
 
 
 
 initialization
 initialization
-  rg := trgcpu.create;
+  rg := trgcpu.create(16);
 end.
 end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.7  2003-02-19 22:00:16  daniel
+  Revision 1.8  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.7  2003/02/19 22:00:16  daniel
     * Code generator converted to new register notation
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
     - Horribily outdated todo.txt removed
 
 

+ 61 - 3
compiler/ncgcal.pas

@@ -171,11 +171,19 @@ implementation
                      begin
                      begin
                        if calloption=pocall_inline then
                        if calloption=pocall_inline then
                          begin
                          begin
+                         {$ifdef newra}
+                           tmpreg:=rg.getaddressregister(exprasmlist);
+                         {$else}
                            tmpreg:=cg.get_scratch_reg_address(exprasmlist);
                            tmpreg:=cg.get_scratch_reg_address(exprasmlist);
+                         {$endif newra}
                            cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
                            cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
                            reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
                            reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
                            cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
                            cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
+                         {$ifdef newra}
+                           rg.ungetregisterint(exprasmlist,tmpreg);
+                         {$else}
                            cg.free_scratch_reg(exprasmlist,tmpreg);
                            cg.free_scratch_reg(exprasmlist,tmpreg);
+                         {$endif}
                          end
                          end
                        else
                        else
                          cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
                          cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
@@ -202,11 +210,19 @@ implementation
               inc(pushedparasize,POINTER_SIZE);
               inc(pushedparasize,POINTER_SIZE);
               if calloption=pocall_inline then
               if calloption=pocall_inline then
                 begin
                 begin
+                {$ifdef newra}
+                   tmpreg:=rg.getaddressregister(exprasmlist);
+                {$else}
                    tmpreg:=cg.get_scratch_reg_address(exprasmlist);
                    tmpreg:=cg.get_scratch_reg_address(exprasmlist);
+                {$endif}
                    cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
                    cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
                    reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
                    reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
                    cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
                    cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
+                {$ifdef newra}
+                   rg.ungetregisterint(exprasmlist,tmpreg);
+                {$else}
                    cg.free_scratch_reg(exprasmlist,tmpreg);
                    cg.free_scratch_reg(exprasmlist,tmpreg);
+                {$endif}
                 end
                 end
               else
               else
                 cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
                 cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
@@ -250,11 +266,19 @@ implementation
                    inc(pushedparasize,POINTER_SIZE);
                    inc(pushedparasize,POINTER_SIZE);
                    if calloption=pocall_inline then
                    if calloption=pocall_inline then
                      begin
                      begin
+                     {$ifdef newra}
+                        tmpreg:=rg.getaddressregister(exprasmlist);
+                     {$else}
                         tmpreg:=cg.get_scratch_reg_address(exprasmlist);
                         tmpreg:=cg.get_scratch_reg_address(exprasmlist);
+                     {$endif}
                         cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
                         cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
                         reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
                         reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
                         cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
                         cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
+                     {$ifdef newra}
+                        rg.ungetregisterint(exprasmlist,tmpreg);
+                     {$else}
                         cg.free_scratch_reg(exprasmlist,tmpreg);
                         cg.free_scratch_reg(exprasmlist,tmpreg);
+                     {$endif}
                      end
                      end
                    else
                    else
                      cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
                      cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
@@ -719,6 +743,14 @@ implementation
                         r.number:=NR_ACCUMULATOR;
                         r.number:=NR_ACCUMULATOR;
                         hregister.enum:=R_INTREGISTER;
                         hregister.enum:=R_INTREGISTER;
                         hregister.number:=NR_ACCUMULATORHIGH;
                         hregister.number:=NR_ACCUMULATORHIGH;
+{$ifdef newra}
+                        rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR);
+                        rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH);
+                        rg.ungetregisterint(exprasmlist,r);
+                        rg.ungetregisterint(exprasmlist,hregister);
+                        location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
+                        location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
+{$else newra}
                         cg.a_reg_alloc(exprasmlist,r);
                         cg.a_reg_alloc(exprasmlist,r);
                         cg.a_reg_alloc(exprasmlist,hregister);
                         cg.a_reg_alloc(exprasmlist,hregister);
                         if RS_ACCUMULATOR in rg.unusedregsint then
                         if RS_ACCUMULATOR in rg.unusedregsint then
@@ -729,6 +761,7 @@ implementation
                           location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH)
                           location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH)
                         else
                         else
                           location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
                           location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
+{$endif newra}
                         cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
                         cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
                             location.register64);
                             location.register64);
                       end
                       end
@@ -740,11 +773,17 @@ implementation
                         nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize);
                         nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize);
                         r.enum:=R_INTREGISTER;
                         r.enum:=R_INTREGISTER;
                         r.number:=nr;
                         r.number:=nr;
+{$ifdef newra}
+                        rg.getexplicitregisterint(exprasmlist,nr);
+                        rg.ungetregisterint(exprasmlist,r);
+                        location.register:=rg.getregisterint(exprasmlist,cgsize);
+{$else newra}
                         cg.a_reg_alloc(exprasmlist,r);
                         cg.a_reg_alloc(exprasmlist,r);
                         if RS_ACCUMULATOR in rg.unusedregsint then
                         if RS_ACCUMULATOR in rg.unusedregsint then
                           location.register:=rg.getexplicitregisterint(exprasmlist,nr)
                           location.register:=rg.getexplicitregisterint(exprasmlist,nr)
                         else
                         else
                           location.register:=rg.getregisterint(exprasmlist,cgsize);
                           location.register:=rg.getregisterint(exprasmlist,cgsize);
+{$endif newra}
                         cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,r,location.register);
                         cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,r,location.register);
                       end;
                       end;
                    end;
                    end;
@@ -783,12 +822,18 @@ implementation
               else
               else
                 begin
                 begin
                   location_reset(location,LOC_REGISTER,OS_INT);
                   location_reset(location,LOC_REGISTER,OS_INT);
+                  r.enum:=R_INTREGISTER;
+                  r.number:=NR_ACCUMULATOR;
+{$ifdef newra}
+                  rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR);
+                  rg.ungetregisterint(exprasmlist,r);
+                  location.register:=rg.getregisterint(exprasmlist,OS_INT);
+{$else newra}
                   if RS_ACCUMULATOR in rg.unusedregsint then
                   if RS_ACCUMULATOR in rg.unusedregsint then
                     location.register:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
                     location.register:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
                   else
                   else
                     location.register:=rg.getregisterint(exprasmlist,OS_INT);
                     location.register:=rg.getregisterint(exprasmlist,OS_INT);
-                  r.enum:=R_INTREGISTER;
-                  r.number:=NR_ACCUMULATOR;
+{$endif newra}
                   cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,r,location.register);
                   cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,r,location.register);
                 end;
                 end;
             end;
             end;
@@ -999,11 +1044,19 @@ implementation
                by function itself !   }
                by function itself !   }
              if inlined then
              if inlined then
                begin
                begin
+                {$ifdef newra}
+                  hregister:=rg.getaddressregister(exprasmlist);
+                {$else}
                   hregister:=cg.get_scratch_reg_address(exprasmlist);
                   hregister:=cg.get_scratch_reg_address(exprasmlist);
+                {$endif}
                   cg.a_loadaddr_ref_reg(exprasmlist,funcretref,hregister);
                   cg.a_loadaddr_ref_reg(exprasmlist,funcretref,hregister);
                   reference_reset_base(href,procinfo.framepointer,inlinecode.retoffset);
                   reference_reset_base(href,procinfo.framepointer,inlinecode.retoffset);
                   cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
                   cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
+                {$ifdef newra}
+                  rg.ungetregisterint(exprasmlist,hregister);
+                {$else}
                   cg.free_scratch_reg(exprasmlist,hregister);
                   cg.free_scratch_reg(exprasmlist,hregister);
+                {$endif}
                end
                end
              else
              else
                cg.a_paramaddr_ref(exprasmlist,funcretref,paramanager.getfuncretparaloc(procdefinition));
                cg.a_paramaddr_ref(exprasmlist,funcretref,paramanager.getfuncretparaloc(procdefinition));
@@ -1423,7 +1476,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.47  2003-04-22 09:49:44  peter
+  Revision 1.48  2003-04-22 10:09:34  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.47  2003/04/22 09:49:44  peter
     * do not load self when calling a non-inherited class constructor
     * do not load self when calling a non-inherited class constructor
 
 
   Revision 1.46  2003/04/21 20:03:32  peter
   Revision 1.46  2003/04/21 20:03:32  peter

+ 30 - 2
compiler/ncginl.pas

@@ -390,10 +390,14 @@ implementation
           { second_ argument specified?, must be a s32bit in register }
           { second_ argument specified?, must be a s32bit in register }
           if assigned(tcallparanode(left).right) then
           if assigned(tcallparanode(left).right) then
             begin
             begin
+            {$ifndef newra}
               maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
               maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
                  tcallparanode(left).left.location,pushedregs);
                  tcallparanode(left).left.location,pushedregs);
+            {$endif}
               secondpass(tcallparanode(tcallparanode(left).right).left);
               secondpass(tcallparanode(tcallparanode(left).right).left);
+            {$ifndef newra}
               maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
               maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
+            {$endif}
               { when constant, just multiply the addvalue }
               { when constant, just multiply the addvalue }
               if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
               if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
                  addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
                  addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
@@ -504,13 +508,21 @@ implementation
                    (tenumdef(tcallparanode(tcallparanode(left).right).left.resulttype.def).max<=32));
                    (tenumdef(tcallparanode(tcallparanode(left).right).left.resulttype.def).max<=32));
 
 
               { generate code for the element to set }
               { generate code for the element to set }
+            {$ifndef newra}
               maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
               maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
                         tcallparanode(left).left.location,pushedregs);
                         tcallparanode(left).left.location,pushedregs);
+            {$endif newra}
               secondpass(tcallparanode(tcallparanode(left).right).left);
               secondpass(tcallparanode(tcallparanode(left).right).left);
+            {$ifndef newra}
               maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
               maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
+            {$endif newra}
 
 
               { bitnumber - which must be loaded into register }
               { bitnumber - which must be loaded into register }
+            {$ifdef newra}
+              hregister:=rg.getregisterint(exprasmlist,OS_INT);
+            {$else}
               hregister := cg.get_scratch_reg_int(exprasmlist,OS_INT);
               hregister := cg.get_scratch_reg_int(exprasmlist,OS_INT);
+            {$endif}
               hregister2 := rg.getregisterint(exprasmlist,OS_INT);
               hregister2 := rg.getregisterint(exprasmlist,OS_INT);
 
 
               case tcallparanode(tcallparanode(left).right).left.location.loc of
               case tcallparanode(tcallparanode(left).right).left.location.loc of
@@ -568,7 +580,11 @@ implementation
                   }
                   }
                   { hregister contains the bitnumber (div 32 to get the correct offset) }
                   { hregister contains the bitnumber (div 32 to get the correct offset) }
                   cg.a_op_const_reg(exprasmlist, OP_SHR, 5, hregister);
                   cg.a_op_const_reg(exprasmlist, OP_SHR, 5, hregister);
+              {$ifdef newra}
+                  addrreg:=rg.getaddressregister(exprasmlist);
+              {$else}
                   addrreg := cg.get_scratch_reg_address(exprasmlist);
                   addrreg := cg.get_scratch_reg_address(exprasmlist);
+              {$endif}
                   { calculate the correct address of the operand }
                   { calculate the correct address of the operand }
                   cg.a_loadaddr_ref_reg(exprasmlist, tcallparanode(left).left.location.reference,addrreg);
                   cg.a_loadaddr_ref_reg(exprasmlist, tcallparanode(left).left.location.reference,addrreg);
                   cg.a_op_reg_reg(exprasmlist, OP_ADD, OS_INT, hregister, addrreg);
                   cg.a_op_reg_reg(exprasmlist, OP_ADD, OS_INT, hregister, addrreg);
@@ -583,10 +599,17 @@ implementation
                          cg.a_op_reg_reg(exprasmlist, OP_NOT, OS_32, hregister2, hregister2);
                          cg.a_op_reg_reg(exprasmlist, OP_NOT, OS_32, hregister2, hregister2);
                          cg.a_op_reg_ref(exprasmlist, OP_AND, OS_32, hregister2, href);
                          cg.a_op_reg_ref(exprasmlist, OP_AND, OS_32, hregister2, href);
                        end;
                        end;
-
+                {$ifdef newra}
+                  rg.ungetregisterint(exprasmlist,addrreg);
+                {$else}
                   cg.free_scratch_reg(exprasmlist, addrreg);
                   cg.free_scratch_reg(exprasmlist, addrreg);
+                {$endif}
                 end;
                 end;
+              {$ifdef newra}
+                rg.ungetregisterint(exprasmlist,hregister);
+              {$else}
                 cg.free_scratch_reg(exprasmlist,hregister);
                 cg.free_scratch_reg(exprasmlist,hregister);
+              {$endif}
                 rg.ungetregisterint(exprasmlist,hregister2);
                 rg.ungetregisterint(exprasmlist,hregister2);
             end;
             end;
         end;
         end;
@@ -646,7 +669,12 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.23  2003-04-06 21:11:23  olle
+  Revision 1.24  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.23  2003/04/06 21:11:23  olle
     * changed newasmsymbol to newasmsymboldata for data symbols
     * changed newasmsymbol to newasmsymboldata for data symbols
 
 
   Revision 1.22  2003/03/28 19:16:56  peter
   Revision 1.22  2003/03/28 19:16:56  peter

+ 38 - 1
compiler/ncgld.pas

@@ -363,10 +363,18 @@ implementation
                           rg.ungetregisterint(exprasmlist,hregister);
                           rg.ungetregisterint(exprasmlist,hregister);
                           { load address of the function }
                           { load address of the function }
                           reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
                           reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
+                        {$ifdef newra}
+                          hregister:=rg.getaddressregister(exprasmlist);
+                        {$else}
                           hregister:=cg.get_scratch_reg_address(exprasmlist);
                           hregister:=cg.get_scratch_reg_address(exprasmlist);
+                        {$endif}
                           cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
                           cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
                           cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
                           cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
+                        {$ifdef newra}
+                          rg.ungetregisterint(exprasmlist,hregister);
+                        {$else newra}
                           cg.free_scratch_reg(exprasmlist,hregister);
                           cg.free_scratch_reg(exprasmlist,hregister);
+                        {$endif}
                         end;
                         end;
                     end
                     end
                   else
                   else
@@ -443,12 +451,16 @@ implementation
             begin
             begin
               { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
               { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
               { can be false                                             }
               { can be false                                             }
+            {$ifndef newra}
               maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
               maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
+            {$endif}
               secondpass(left);
               secondpass(left);
               { decrement destination reference counter }
               { decrement destination reference counter }
               if (left.resulttype.def.needs_inittable) then
               if (left.resulttype.def.needs_inittable) then
                cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
                cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
+            {$ifndef newra}
               maybe_restore(exprasmlist,right.location,pushedregs);
               maybe_restore(exprasmlist,right.location,pushedregs);
+            {$endif newra}
               if codegenerror then
               if codegenerror then
                 exit;
                 exit;
             end;
             end;
@@ -469,14 +481,18 @@ implementation
 
 
            { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
            { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
            { can be false                                             }
            { can be false                                             }
+          {$ifndef newra}
            maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
            maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+          {$endif newra}
            secondpass(right);
            secondpass(right);
            { increment source reference counter, this is
            { increment source reference counter, this is
              useless for string constants}
              useless for string constants}
            if (right.resulttype.def.needs_inittable) and
            if (right.resulttype.def.needs_inittable) and
               (right.nodetype<>stringconstn) then
               (right.nodetype<>stringconstn) then
             cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
             cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
+          {$ifndef newra}
            maybe_restore(exprasmlist,left.location,pushedregs);
            maybe_restore(exprasmlist,left.location,pushedregs);
+          {$endif}
 
 
            if codegenerror then
            if codegenerror then
              exit;
              exit;
@@ -633,9 +649,13 @@ implementation
                   { generate the leftnode for the true case, and
                   { generate the leftnode for the true case, and
                     release the location }
                     release the location }
                   cg.a_label(exprasmlist,truelabel);
                   cg.a_label(exprasmlist,truelabel);
+                {$ifndef newra}
                   maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
                   maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
+                {$endif newra}
                   secondpass(left);
                   secondpass(left);
+                {$ifndef newra}
                   maybe_restore(exprasmlist,right.location,pushedregs);
                   maybe_restore(exprasmlist,right.location,pushedregs);
+                {$endif newra}
                   if codegenerror then
                   if codegenerror then
                     exit;
                     exit;
                   cg.a_load_const_loc(exprasmlist,1,left.location);
                   cg.a_load_const_loc(exprasmlist,1,left.location);
@@ -643,9 +663,13 @@ implementation
                   cg.a_jmp_always(exprasmlist,hlabel);
                   cg.a_jmp_always(exprasmlist,hlabel);
                   { generate the leftnode for the false case }
                   { generate the leftnode for the false case }
                   cg.a_label(exprasmlist,falselabel);
                   cg.a_label(exprasmlist,falselabel);
+                {$ifndef newra}
                   maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
                   maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
+                {$endif}
                   secondpass(left);
                   secondpass(left);
+                {$ifndef newra}
                   maybe_restore(exprasmlist,right.location,pushedregs);
                   maybe_restore(exprasmlist,right.location,pushedregs);
+                {$endif newra}
                   if codegenerror then
                   if codegenerror then
                     exit;
                     exit;
                   cg.a_load_const_loc(exprasmlist,0,left.location);
                   cg.a_load_const_loc(exprasmlist,0,left.location);
@@ -910,10 +934,18 @@ implementation
                     if vaddr then
                     if vaddr then
                      begin
                      begin
                        location_force_mem(exprasmlist,hp.left.location);
                        location_force_mem(exprasmlist,hp.left.location);
+                     {$ifdef newra}
+                       tmpreg:=rg.getaddressregister(exprasmlist);
+                     {$else}
                        tmpreg:=cg.get_scratch_reg_address(exprasmlist);
                        tmpreg:=cg.get_scratch_reg_address(exprasmlist);
+                     {$endif}
                        cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
                        cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
                        cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
                        cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
+                     {$ifdef newra}
+                       rg.ungetregisterint(exprasmlist,tmpreg);
+                     {$else}
                        cg.free_scratch_reg(exprasmlist,tmpreg);
                        cg.free_scratch_reg(exprasmlist,tmpreg);
+                     {$endif}
                        location_release(exprasmlist,hp.left.location);
                        location_release(exprasmlist,hp.left.location);
                        if freetemp then
                        if freetemp then
                          location_freetemp(exprasmlist,hp.left.location);
                          location_freetemp(exprasmlist,hp.left.location);
@@ -970,7 +1002,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.47  2003-04-06 21:11:23  olle
+  Revision 1.48  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.47  2003/04/06 21:11:23  olle
     * changed newasmsymbol to newasmsymboldata for data symbols
     * changed newasmsymbol to newasmsymboldata for data symbols
 
 
   Revision 1.46  2003/03/28 19:16:56  peter
   Revision 1.46  2003/03/28 19:16:56  peter

+ 23 - 1
compiler/ncgmat.pas

@@ -257,9 +257,13 @@ implementation
          secondpass(left);
          secondpass(left);
          if codegenerror then
          if codegenerror then
           exit;
           exit;
+        {$ifndef newra}
          maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
          maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+        {$endif}
          secondpass(right);
          secondpass(right);
+        {$ifndef newra}
          maybe_restore(exprasmlist,left.location,pushedregs);
          maybe_restore(exprasmlist,left.location,pushedregs);
+        {$endif newra}
          if codegenerror then
          if codegenerror then
           exit;
           exit;
          location_copy(location,left.location);
          location_copy(location,left.location);
@@ -350,9 +354,13 @@ implementation
       begin
       begin
          freescratch:=false;
          freescratch:=false;
          secondpass(left);
          secondpass(left);
+      {$ifndef newra}
          maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
          maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+      {$endif newra}
          secondpass(right);
          secondpass(right);
+      {$ifndef newra}
          maybe_restore(exprasmlist,left.location,pushedregs);
          maybe_restore(exprasmlist,left.location,pushedregs);
+      {$endif}
          { determine operator }
          { determine operator }
          case nodetype of
          case nodetype of
            shln: op:=OP_SHL;
            shln: op:=OP_SHL;
@@ -428,15 +436,24 @@ implementation
                      begin
                      begin
                        if right.location.loc<>LOC_CREGISTER then
                        if right.location.loc<>LOC_CREGISTER then
                         location_release(exprasmlist,right.location);
                         location_release(exprasmlist,right.location);
+                     {$ifdef newra}
+                       hcountreg:=rg.getregisterint(exprasmlist,OS_INT);
+                     {$else}
                        hcountreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
                        hcountreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+                     {$endif}
                        freescratch := true;
                        freescratch := true;
                        cg.a_load_loc_reg(exprasmlist,right.location,hcountreg);
                        cg.a_load_loc_reg(exprasmlist,right.location,hcountreg);
                      end
                      end
                    else
                    else
                      hcountreg:=right.location.register;
                      hcountreg:=right.location.register;
                    cg.a_op_reg_reg(exprasmlist,op,OS_INT,hcountreg,location.register);
                    cg.a_op_reg_reg(exprasmlist,op,OS_INT,hcountreg,location.register);
+                 {$ifdef newra}
+                   if freescratch then
+                      rg.ungetregisterint(exprasmlist,hcountreg);
+                 {$else}
                    if freescratch then
                    if freescratch then
                       cg.free_scratch_reg(exprasmlist,hcountreg);
                       cg.free_scratch_reg(exprasmlist,hcountreg);
+                 {$endif}
                 end;
                 end;
            end;
            end;
       end;
       end;
@@ -450,7 +467,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.7  2003-03-28 19:16:56  peter
+  Revision 1.8  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.7  2003/03/28 19:16:56  peter
     * generic constructor working for i386
     * generic constructor working for i386
     * remove fixed self register
     * remove fixed self register
     * esi added as address register for i386
     * esi added as address register for i386

+ 31 - 1
compiler/ncgmem.pas

@@ -406,12 +406,20 @@ implementation
                   usetemp:=true;
                   usetemp:=true;
                   if is_class_or_interface(left.resulttype.def) then
                   if is_class_or_interface(left.resulttype.def) then
                     begin
                     begin
+                    {$ifdef newra}
+                      tmpreg:=rg.getregisterint(exprasmlist,OS_INT);
+                    {$else}
                       tmpreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
                       tmpreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
+                    {$endif}
                       cg.a_load_loc_reg(exprasmlist,left.location,tmpreg)
                       cg.a_load_loc_reg(exprasmlist,left.location,tmpreg)
                     end
                     end
                   else
                   else
                     begin
                     begin
+                    {$ifdef newra}
+                      tmpreg:=rg.getaddressregister(exprasmlist);
+                    {$else}
                       tmpreg := cg.get_scratch_reg_address(exprasmlist);
                       tmpreg := cg.get_scratch_reg_address(exprasmlist);
+                    {$endif newra}
                       cg.a_loadaddr_ref_reg(exprasmlist,
                       cg.a_loadaddr_ref_reg(exprasmlist,
                         left.location.reference,tmpreg);
                         left.location.reference,tmpreg);
                     end;
                     end;
@@ -444,7 +452,11 @@ implementation
                   tg.GetTemp(exprasmlist,pointer_size,tt_persistant,withreference);
                   tg.GetTemp(exprasmlist,pointer_size,tt_persistant,withreference);
                   { move to temp reference }
                   { move to temp reference }
                   cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
                   cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
+                {$ifdef newra}
+                  rg.ungetregisterint(exprasmlist,tmpreg);
+                {$else}
                   cg.free_scratch_reg(exprasmlist,tmpreg);
                   cg.free_scratch_reg(exprasmlist,tmpreg);
+                {$endif}
 {$ifdef GDB}
 {$ifdef GDB}
                   if (cs_debuginfo in aktmoduleswitches) then
                   if (cs_debuginfo in aktmoduleswitches) then
                     begin
                     begin
@@ -580,7 +592,11 @@ implementation
                  hreg:=right.location.register
                  hreg:=right.location.register
                else
                else
                  begin
                  begin
+                 {$ifdef newra}
+                   hreg:=rg.getregisterint(exprasmlist,OS_INT);
+                 {$else}
                    hreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
                    hreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
+                 {$endif}
                    freereg:=true;
                    freereg:=true;
                    cg.a_load_loc_reg(exprasmlist,right.location,hreg);
                    cg.a_load_loc_reg(exprasmlist,right.location,hreg);
                  end;
                  end;
@@ -588,8 +604,13 @@ implementation
                objectlibrary.getlabel(poslabel);
                objectlibrary.getlabel(poslabel);
                cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
                cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
                cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
                cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
+             {$ifdef newra}
+               if freereg then
+                 rg.ungetregisterint(exprasmlist,hreg);
+             {$else}
                if freereg then
                if freereg then
                  cg.free_scratch_reg(exprasmlist,hreg);
                  cg.free_scratch_reg(exprasmlist,hreg);
+             {$endif}
                cg.a_label(exprasmlist,poslabel);
                cg.a_label(exprasmlist,poslabel);
                cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
                cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
                cg.a_label(exprasmlist,neglabel);
                cg.a_label(exprasmlist,neglabel);
@@ -843,9 +864,13 @@ implementation
                  ofl:=falselabel;
                  ofl:=falselabel;
                  objectlibrary.getlabel(falselabel);
                  objectlibrary.getlabel(falselabel);
                end;
                end;
+            {$ifndef newra}
               maybe_save(exprasmlist,right.registers32,location,pushedregs);
               maybe_save(exprasmlist,right.registers32,location,pushedregs);
+            {$endif}
               secondpass(right);
               secondpass(right);
+            {$ifndef newra}
               maybe_restore(exprasmlist,location,pushedregs);
               maybe_restore(exprasmlist,location,pushedregs);
+            {$endif}
 
 
               if cs_check_range in aktlocalswitches then
               if cs_check_range in aktlocalswitches then
                begin
                begin
@@ -919,7 +944,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.45  2003-04-06 21:11:23  olle
+  Revision 1.46  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.45  2003/04/06 21:11:23  olle
     * changed newasmsymbol to newasmsymboldata for data symbols
     * changed newasmsymbol to newasmsymboldata for data symbols
 
 
   Revision 1.44  2003/03/28 19:16:56  peter
   Revision 1.44  2003/03/28 19:16:56  peter

+ 56 - 2
compiler/ncgset.pas

@@ -110,11 +110,15 @@ implementation
        { also a second value ? }
        { also a second value ? }
          if assigned(right) then
          if assigned(right) then
            begin
            begin
+           {$ifndef newra}
              maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
              maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+           {$endif}
              secondpass(right);
              secondpass(right);
              if codegenerror then
              if codegenerror then
                exit;
                exit;
+           {$ifndef newra}
              maybe_restore(exprasmlist,left.location,pushedregs);
              maybe_restore(exprasmlist,left.location,pushedregs);
+           {$endif newra}
              if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
              if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
               location_force_reg(exprasmlist,right.location,OS_32,false);
               location_force_reg(exprasmlist,right.location,OS_32,false);
            end;
            end;
@@ -264,9 +268,13 @@ implementation
          { Only process the right if we are not generating jumps }
          { Only process the right if we are not generating jumps }
          if not genjumps then
          if not genjumps then
           begin
           begin
+          {$ifndef newra}
             maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
             maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+          {$endif}
             secondpass(right);
             secondpass(right);
+          {$ifndef newra}
             maybe_restore(exprasmlist,left.location,pushedregs);
             maybe_restore(exprasmlist,left.location,pushedregs);
+          {$endif}
           end;
           end;
          if codegenerror then
          if codegenerror then
           exit;
           exit;
@@ -312,7 +320,11 @@ implementation
             else
             else
              begin
              begin
                { load the value in a register }
                { load the value in a register }
+             {$ifdef newra}
+               pleftreg:=rg.getregisterint(exprasmlist,OS_INT);
+             {$else}
                pleftreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
                pleftreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
+             {$endif}
                opsize := OS_INT;
                opsize := OS_INT;
                cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),left.location.reference,pleftreg);
                cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),left.location.reference,pleftreg);
              end;
              end;
@@ -340,7 +352,11 @@ implementation
                       if (left.location.loc = LOC_CREGISTER) and
                       if (left.location.loc = LOC_CREGISTER) and
                          (hr.enum <> pleftreg.enum) then
                          (hr.enum <> pleftreg.enum) then
                         begin
                         begin
+                        {$ifdef newra}
+                          hr:=rg.getregisterint(exprasmlist,OS_INT);
+                        {$else}
                           hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
                           hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+                        {$endif}
                           cg.a_op_const_reg_reg(exprasmlist,OP_SUB,opsize,setparts[i].start,pleftreg,hr);
                           cg.a_op_const_reg_reg(exprasmlist,OP_SUB,opsize,setparts[i].start,pleftreg,hr);
                           pleftreg:=hr;
                           pleftreg:=hr;
                           opsize := OS_INT;
                           opsize := OS_INT;
@@ -388,13 +404,21 @@ implementation
              cg.a_label(exprasmlist,l3);
              cg.a_label(exprasmlist,l3);
              case left.location.loc of
              case left.location.loc of
                LOC_CREGISTER :
                LOC_CREGISTER :
+                {$ifdef newra}
+                 rg.ungetregisterint(exprasmlist,pleftreg);
+                {$else}
                  cg.free_scratch_reg(exprasmlist,pleftreg);
                  cg.free_scratch_reg(exprasmlist,pleftreg);
+                {$endif}
                LOC_REGISTER :
                LOC_REGISTER :
                  rg.ungetregister(exprasmlist,pleftreg);
                  rg.ungetregister(exprasmlist,pleftreg);
                else
                else
                  begin
                  begin
                    reference_release(exprasmlist,left.location.reference);
                    reference_release(exprasmlist,left.location.reference);
+                  {$ifdef newra}
+                   rg.ungetregisterint(exprasmlist,pleftreg);
+                  {$else}
                    cg.free_scratch_reg(exprasmlist,pleftreg);
                    cg.free_scratch_reg(exprasmlist,pleftreg);
+                  {$endif}
                  end;
                  end;
              end;
              end;
           end
           end
@@ -412,7 +436,11 @@ implementation
                 begin
                 begin
                   { clear the register value, indicating result is FALSE }
                   { clear the register value, indicating result is FALSE }
                   cg.a_load_const_reg(exprasmlist,OS_INT,0,location.register);
                   cg.a_load_const_reg(exprasmlist,OS_INT,0,location.register);
+                {$ifdef newra}
+                  hr:=rg.getregisterint(exprasmlist,OS_INT);
+                {$else}
                   hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
                   hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+                {$endif}
                   case right.location.loc of
                   case right.location.loc of
                     LOC_REGISTER,
                     LOC_REGISTER,
                     LOC_CREGISTER:
                     LOC_CREGISTER:
@@ -444,14 +472,23 @@ implementation
                      LOC_REGISTER,
                      LOC_REGISTER,
                      LOC_CREGISTER:
                      LOC_CREGISTER:
                        begin
                        begin
-                          hr3:=rg.makeregsize(left.location.register,OS_INT);
+                          hr3.enum:=R_INTREGISTER;
+                          hr3.number:=(left.location.register.number and not $ff) or R_SUBWHOLE;
                           cg.a_load_reg_reg(exprasmlist,left.location.size,OS_INT,left.location.register,hr3);
                           cg.a_load_reg_reg(exprasmlist,left.location.size,OS_INT,left.location.register,hr3);
+                        {$ifdef newra}
+                          hr:=rg.getregisterint(exprasmlist,OS_INT);
+                        {$else}
                           hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
                           hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+                        {$endif}
                           cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,hr3,hr);
                           cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,hr3,hr);
                        end;
                        end;
                   else
                   else
                     begin
                     begin
+                    {$ifdef newra}
+                      hr:=rg.getregisterint(exprasmlist,OS_INT);
+                    {$else}
                       hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
                       hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
+                    {$endif}
                       cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),
                       cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),
                          left.location.reference,hr);
                          left.location.reference,hr);
                       location_release(exprasmlist,left.location);
                       location_release(exprasmlist,left.location);
@@ -496,7 +533,11 @@ implementation
                        internalerror(2002032210);
                        internalerror(2002032210);
                   end;
                   end;
                   { free bitnumber register }
                   { free bitnumber register }
+                {$ifdef newra}
+                  rg.ungetregisterint(exprasmlist,hr);
+                {$else}
                   cg.free_scratch_reg(exprasmlist,hr);
                   cg.free_scratch_reg(exprasmlist,hr);
+                {$endif}
                 end;
                 end;
              end
              end
             else
             else
@@ -683,9 +724,17 @@ implementation
            begin
            begin
               last:=0;
               last:=0;
               first:=true;
               first:=true;
+            {$ifdef newra}
+              scratch_reg:=rg.getregisterint(exprasmlist,OS_INT);
+            {$else newra}
               scratch_reg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
               scratch_reg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
+            {$endif}
               genitem(hp);
               genitem(hp);
+            {$ifdef newra}
+              rg.ungetregisterint(exprasmlist,scratch_reg);
+            {$else}
               cg.free_scratch_reg(exprasmlist,scratch_reg);
               cg.free_scratch_reg(exprasmlist,scratch_reg);
+            {$endif}
               cg.a_jmp_always(exprasmlist,elselabel);
               cg.a_jmp_always(exprasmlist,elselabel);
            end;
            end;
       end;
       end;
@@ -1063,7 +1112,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.26  2003-02-19 22:00:14  daniel
+  Revision 1.27  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.26  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
     - Horribily outdated todo.txt removed
 
 

+ 34 - 1
compiler/ncgutil.pas

@@ -52,8 +52,10 @@ interface
     procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
     procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
     procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
     procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
 
 
+{$ifndef newra}
     procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
     procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
     procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
     procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
+{$endif}
     function  maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
     function  maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
 
 
     procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption;
     procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption;
@@ -607,6 +609,7 @@ implementation
                                   Maybe_Save
                                   Maybe_Save
 *****************************************************************************}
 *****************************************************************************}
 
 
+{$ifndef newra}
     procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
     procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
       begin
       begin
         s.saved:=false;
         s.saved:=false;
@@ -707,6 +710,7 @@ implementation
         end;
         end;
         tg.ungetiftemp(list,s.ref);
         tg.ungetiftemp(list,s.ref);
       end;
       end;
+{$endif newra}
 
 
 
 
     function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
     function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
@@ -1064,11 +1068,19 @@ implementation
              vs_out :
              vs_out :
                begin
                begin
                  reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
                  reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
+               {$ifdef newra}
+                 tmpreg:=rg.getaddressregister(list);
+               {$else}
                  tmpreg:=cg.get_scratch_reg_address(list);
                  tmpreg:=cg.get_scratch_reg_address(list);
+               {$endif}
                  cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
                  cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
                  reference_reset_base(href,tmpreg,0);
                  reference_reset_base(href,tmpreg,0);
                  cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
                  cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
+               {$ifdef newra}
+                 rg.ungetregisterint(list,tmpreg);
+               {$else}
                  cg.free_scratch_reg(list,tmpreg);
                  cg.free_scratch_reg(list,tmpreg);
+               {$endif newra}
                end;
                end;
            end;
            end;
          end;
          end;
@@ -1518,14 +1530,22 @@ function returns in a register and the caller receives it in an other one}
            reference_reset_base(href,procinfo.framepointer,procinfo.inheritedflag_offset);
            reference_reset_base(href,procinfo.framepointer,procinfo.inheritedflag_offset);
            cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,inheriteddesctructorlabel);
            cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,inheriteddesctructorlabel);
            reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
            reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
+         {$ifdef newra}
+           tmpreg:=rg.getaddressregister(list);
+         {$else}
            tmpreg:=cg.get_scratch_reg_address(list);
            tmpreg:=cg.get_scratch_reg_address(list);
+         {$endif}
            cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
            cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
            cg.a_param_reg(list,OS_ADDR,tmpreg,paramanager.getintparaloc(1));
            cg.a_param_reg(list,OS_ADDR,tmpreg,paramanager.getintparaloc(1));
            reference_reset_base(href,tmpreg,0);
            reference_reset_base(href,tmpreg,0);
            cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
            cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
            reference_reset_base(href,tmpreg,72);
            reference_reset_base(href,tmpreg,72);
            cg.a_call_ref(list,href);
            cg.a_call_ref(list,href);
+         {$ifdef newra}
+           rg.ungetregisterint(list,tmpreg);
+         {$else}
            cg.free_scratch_reg(list,tmpreg);
            cg.free_scratch_reg(list,tmpreg);
+         {$endif}
            cg.a_label(list,inheriteddesctructorlabel);
            cg.a_label(list,inheriteddesctructorlabel);
          end;
          end;
 
 
@@ -1801,11 +1821,19 @@ function returns in a register and the caller receives it in an other one}
                    cg.a_load_ref_reg(list,OS_ADDR,href,r);
                    cg.a_load_ref_reg(list,OS_ADDR,href,r);
                    cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1));
                    cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1));
                    reference_reset_base(href,r,0);
                    reference_reset_base(href,r,0);
+                 {$ifdef newra}
+                   tmpreg:=rg.getaddressregister(list);
+                 {$else newra}
                    tmpreg:=cg.get_scratch_reg_address(list);
                    tmpreg:=cg.get_scratch_reg_address(list);
+                 {$endif}
                    cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
                    cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
                    reference_reset_base(href,tmpreg,68);
                    reference_reset_base(href,tmpreg,68);
                    cg.a_call_ref(list,href);
                    cg.a_call_ref(list,href);
+                 {$ifdef newra}
+                   rg.ungetregisterint(list,tmpreg);
+                 {$else}
                    cg.free_scratch_reg(list,tmpreg);
                    cg.free_scratch_reg(list,tmpreg);
+                 {$endif}
                  end;
                  end;
                 { return the self pointer }
                 { return the self pointer }
                 cg.a_label(list,inheritedconstructorlabel);
                 cg.a_label(list,inheritedconstructorlabel);
@@ -2018,7 +2046,12 @@ function returns in a register and the caller receives it in an other one}
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.84  2003-04-16 09:26:55  jonas
+  Revision 1.85  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.84  2003/04/16 09:26:55  jonas
     * assembler procedures now again get a stackframe if they have local
     * assembler procedures now again get a stackframe if they have local
       variables. No space is reserved for a function result however.
       variables. No space is reserved for a function result however.
       Also, the register parameters aren't automatically saved on the stack
       Also, the register parameters aren't automatically saved on the stack

+ 7 - 2
compiler/powerpc/rgcpu.pas

@@ -70,12 +70,17 @@ unit rgcpu;
       end;
       end;
 
 
 initialization
 initialization
-  rg := trgcpu.create;
+  rg := trgcpu.create(32);  {PPC has 32 registers.}
 end.
 end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2003-02-19 22:00:16  daniel
+  Revision 1.6  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.5  2003/02/19 22:00:16  daniel
     * Code generator converted to new register notation
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
     - Horribily outdated todo.txt removed
 
 

+ 24 - 2
compiler/psub.pas

@@ -373,10 +373,26 @@ implementation
                 procinfo.aktproccode.insertlist(procinfo.aktentrycode);
                 procinfo.aktproccode.insertlist(procinfo.aktentrycode);
                 procinfo.aktproccode.concatlist(procinfo.aktexitcode);
                 procinfo.aktproccode.concatlist(procinfo.aktexitcode);
 {$ifdef newra}
 {$ifdef newra}
-                rg.writegraph;
+{                rg.writegraph;}
 {$endif}
 {$endif}
                 if not(cs_no_regalloc in aktglobalswitches) then
                 if not(cs_no_regalloc in aktglobalswitches) then
                   begin
                   begin
+{$ifdef newra}
+                    {Do register allocation.}
+                    repeat
+                      rg.prepare_colouring;
+                      rg.colour_registers;
+                      rg.epilogue_colouring;
+                      {Are there spilled registers? We cannot do that yet.}
+                      if rg.spillednodes<>'' then
+                        internalerror(200304221);
+                      {if not try_fast_spill(rg) then
+                        slow_spill(rg);
+                      }
+                    until rg.spillednodes='';
+                    procinfo.aktproccode.translate_registers(rg.colour);
+                    procinfo.aktproccode.convert_registers;
+{$else newra}
                     procinfo.aktproccode.convert_registers;
                     procinfo.aktproccode.convert_registers;
 {$ifndef NoOpt}
 {$ifndef NoOpt}
                     if (cs_optimize in aktglobalswitches) and
                     if (cs_optimize in aktglobalswitches) and
@@ -384,6 +400,7 @@ implementation
                        ((procinfo.flags and pi_is_assembler)=0)  then
                        ((procinfo.flags and pi_is_assembler)=0)  then
                       optimize(procinfo.aktproccode);
                       optimize(procinfo.aktproccode);
 {$endif NoOpt}
 {$endif NoOpt}
+{$endif newra}
                   end;
                   end;
                 { save local data (casetable) also in the same file }
                 { save local data (casetable) also in the same file }
                 if assigned(procinfo.aktlocaldata) and
                 if assigned(procinfo.aktlocaldata) and
@@ -867,7 +884,12 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.98  2003-04-17 07:50:24  daniel
+  Revision 1.99  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.98  2003/04/17 07:50:24  daniel
     * Some work on interference graph construction
     * Some work on interference graph construction
 
 
   Revision 1.97  2003/04/16 09:26:55  jonas
   Revision 1.97  2003/04/16 09:26:55  jonas

+ 589 - 18
compiler/rgobj.pas

@@ -42,8 +42,7 @@ published by Cambridge University Press.
 Reading this book is recommended for a complete understanding. Here is a small
 Reading this book is recommended for a complete understanding. Here is a small
 introduction.
 introduction.
 
 
-The code generator thinks it has an infinite amount of registers. Our processor
-has a limited amount of registers. Therefore we must reduce the amount of
+The code generator thinks it has an infinite amount of registers. Our processorhas a limited amount of registers. Therefore we must reduce the amount of
 registers until there are less enough to fit into the processors registers.
 registers until there are less enough to fit into the processors registers.
 
 
 Registers can interfere or not interfere. If two imaginary registers interfere
 Registers can interfere or not interfere. If two imaginary registers interfere
@@ -61,7 +60,7 @@ if two registers interfere there is a connection between them in the graph.
 In addition to the imaginary registers in the code generator, the psysical
 In addition to the imaginary registers in the code generator, the psysical
 CPU registers are also present in this graph. This allows us to make
 CPU registers are also present in this graph. This allows us to make
 interferences between imaginary registers and cpu registers. This is very
 interferences between imaginary registers and cpu registers. This is very
-usefull for describing archtectural constrains, like for example that
+usefull for describing archtectural constraints, like for example that
 the div instruction modifies edx, so variables that are in use at that time
 the div instruction modifies edx, so variables that are in use at that time
 cannot be stored into edx. This can be modelled by making edx interfere
 cannot be stored into edx. This can be modelled by making edx interfere
 with those variables.
 with those variables.
@@ -108,8 +107,21 @@ unit rgobj;
       end;
       end;
       Pinterferencegraph=^Tinterferencegraph;
       Pinterferencegraph=^Tinterferencegraph;
 
 
+      Tmovelist=record
+        count:cardinal;
+        data:array[0..$ffff] of Tlinkedlistitem;
+      end;
+      Pmovelist=^Tmovelist;
+
+      {In the register allocator we keep track of move instructions.
+       These instructions are moved between five linked lists. There
+       is also a linked list per register to keep track about the moves
+       it is associated with. Because we need to determine quickly in 
+       which of the five lists it is we add anu enumeradtion to each 
+       move instruction.}
+
       Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
       Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
-                ms_worklist_moves,ms_activemoves);
+                ms_worklist_moves,ms_active_moves);
       Tmoveins=class(Tlinkedlistitem)
       Tmoveins=class(Tlinkedlistitem)
         moveset:Tmoveset;
         moveset:Tmoveset;
         instruction:Taicpu;
         instruction:Taicpu;
@@ -129,7 +141,7 @@ unit rgobj;
           { aren't currently allocated to a regvar. The "unusedregsxxx"  }
           { aren't currently allocated to a regvar. The "unusedregsxxx"  }
           { contain all registers of type "xxx" that aren't currenly     }
           { contain all registers of type "xxx" that aren't currenly     }
           { allocated                                                    }
           { allocated                                                    }
-          lastintreg:Tsuperregister;
+          lastintreg,maxintreg:Tsuperregister;
           unusedregsint,usableregsint:Tsupregset;
           unusedregsint,usableregsint:Tsupregset;
           unusedregsaddr,usableregsaddr:Tsupregset;
           unusedregsaddr,usableregsaddr:Tsupregset;
           unusedregsfpu,usableregsfpu : tregisterset;
           unusedregsfpu,usableregsfpu : tregisterset;
@@ -161,12 +173,15 @@ unit rgobj;
           is_reg_var_int:Tsupregset;
           is_reg_var_int:Tsupregset;
           regvar_loaded: regvar_booleanarray;
           regvar_loaded: regvar_booleanarray;
           regvar_loaded_int: Tsupregset;
           regvar_loaded_int: Tsupregset;
-
+{$ifdef newra}
+          colour:array[Tsuperregister] of Tsuperregister;
+          spillednodes:string;
+{$endif}
 
 
           { tries to hold the amount of times which the current tree is processed  }
           { tries to hold the amount of times which the current tree is processed  }
           t_times: longint;
           t_times: longint;
 
 
-          constructor create;
+          constructor create(Acpu_registers:byte);
 
 
           {# Allocate a general purpose register
           {# Allocate a general purpose register
 
 
@@ -245,7 +260,12 @@ unit rgobj;
           }
           }
           procedure ungetreference(list: taasmoutput; const ref : treference); virtual;
           procedure ungetreference(list: taasmoutput; const ref : treference); virtual;
 
 
-          {# Reset the register allocator information (usable registers etc) }
+          {# Reset the register allocator information (usable registers etc).
+             Please note that it is mortal sins to call cleartempgen during
+             graph colouring (that is between prepare_colouring and
+             epilogue_colouring).
+          }
+
           procedure cleartempgen;virtual;
           procedure cleartempgen;virtual;
 
 
           {# Convert a register to a specified register size, and return that register size }
           {# Convert a register to a specified register size, and return that register size }
@@ -299,13 +319,26 @@ unit rgobj;
           procedure saveUnusedState(var state: pointer);virtual;
           procedure saveUnusedState(var state: pointer);virtual;
           procedure restoreUnusedState(var state: pointer);virtual;
           procedure restoreUnusedState(var state: pointer);virtual;
 {$ifdef newra}
 {$ifdef newra}
+{$ifdef ra_debug}
           procedure writegraph;
           procedure writegraph;
 {$endif}
 {$endif}
+          procedure add_move_instruction(instr:Taicpu);
+          procedure prepare_colouring;
+          procedure epilogue_colouring;
+          procedure colour_registers;
+{$endif newra}
        protected
        protected
+          cpu_registers:byte;
 {$ifdef newra}
 {$ifdef newra}
           igraph:Tinterferencegraph;
           igraph:Tinterferencegraph;
-          movelist:array[Tsuperregister] of Tlinkedlist;
-          worklistmoves:Tlinkedlist;
+          degree:array[0..255] of byte;
+          alias:array[Tsuperregister] of Tsuperregister;
+          simplifyworklist,freezeworklist,spillworklist:string;
+          coalescednodes:string;
+          selectstack:string;
+          movelist:array[Tsuperregister] of Pmovelist;
+          worklist_moves,active_moves,frozen_moves,
+          coalesced_moves,constrained_moves:Tlinkedlist;
 {$endif}
 {$endif}
           { the following two contain the common (generic) code for all }
           { the following two contain the common (generic) code for all }
           { get- and ungetregisterxxx functions/procedures              }
           { get- and ungetregisterxxx functions/procedures              }
@@ -332,6 +365,23 @@ unit rgobj;
 {$ifdef newra}
 {$ifdef newra}
          procedure add_edge(u,v:Tsuperregister);
          procedure add_edge(u,v:Tsuperregister);
          procedure add_edges_used(u:Tsuperregister);
          procedure add_edges_used(u:Tsuperregister);
+         procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
+         function move_related(n:Tsuperregister):boolean;
+         procedure make_work_list;
+         procedure enable_moves(n:Tsuperregister);
+         procedure decrement_degree(m:Tsuperregister);
+         procedure simplify;
+
+         function get_alias(n:Tsuperregister):Tsuperregister;
+         procedure add_worklist(u:Tsuperregister);
+         function adjacent_ok(u,v:Tsuperregister):boolean;
+         function conservative(u,v:Tsuperregister):boolean;
+         procedure combine(u,v:Tsuperregister);
+         procedure coalesce;
+         procedure freeze_moves(u:Tsuperregister);
+         procedure freeze;
+         procedure select_spill;
+         procedure assign_colours;
 {$endif}
 {$endif}
        end;
        end;
 
 
@@ -415,7 +465,7 @@ unit rgobj;
        globals,verbose,
        globals,verbose,
        cgobj,tgobj,regvars;
        cgobj,tgobj,regvars;
 
 
-    constructor trgobj.create;
+    constructor Trgobj.create(Acpu_registers:byte);
 
 
      begin
      begin
        usedinproc := [];
        usedinproc := [];
@@ -423,14 +473,17 @@ unit rgobj;
        t_times := 0;
        t_times := 0;
        resetusableregisters;
        resetusableregisters;
        lastintreg:=0;
        lastintreg:=0;
+       maxintreg:=first_imreg;
+       cpu_registers:=Acpu_registers;
 {$ifdef TEMPREGDEBUG}
 {$ifdef TEMPREGDEBUG}
        fillchar(reg_user,sizeof(reg_user),0);
        fillchar(reg_user,sizeof(reg_user),0);
        fillchar(reg_releaser,sizeof(reg_releaser),0);
        fillchar(reg_releaser,sizeof(reg_releaser),0);
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
 {$ifdef newra}
 {$ifdef newra}
        fillchar(igraph,sizeof(igraph),0);
        fillchar(igraph,sizeof(igraph),0);
+       fillchar(degree,sizeof(degree),0);
        fillchar(movelist,sizeof(movelist),0);
        fillchar(movelist,sizeof(movelist),0);
-       worklistmoves.create;
+       worklist_moves:=Tlinkedlist.create;
 {$endif}
 {$endif}
      end;
      end;
 
 
@@ -487,6 +540,8 @@ unit rgobj;
             list.concat(Tai_regalloc.alloc(r));
             list.concat(Tai_regalloc.alloc(r));
             result:=r;
             result:=r;
             lastintreg:=i;
             lastintreg:=i;
+            if i>maxintreg then
+              maxintreg:=i;
 {$ifdef newra}
 {$ifdef newra}
             add_edges_used(i);
             add_edges_used(i);
 {$endif}
 {$endif}
@@ -749,6 +804,8 @@ unit rgobj;
       countunusedregsint:=countusableregsint;
       countunusedregsint:=countusableregsint;
       countunusedregsfpu:=countusableregsfpu;
       countunusedregsfpu:=countusableregsfpu;
       countunusedregsmm:=countusableregsmm;
       countunusedregsmm:=countusableregsmm;
+      lastintreg:=0;
+      maxintreg:=first_imreg;
    {$ifdef newra}
    {$ifdef newra}
       unusedregsint:=[0..255];
       unusedregsint:=[0..255];
    {$else}
    {$else}
@@ -762,10 +819,12 @@ unit rgobj;
           if igraph.adjlist[i]<>nil then
           if igraph.adjlist[i]<>nil then
             dispose(igraph.adjlist[i]);
             dispose(igraph.adjlist[i]);
           if movelist[i]<>nil then
           if movelist[i]<>nil then
-            movelist[i].destroy;
+            dispose(movelist[i]);
         end;
         end;
+      fillchar(movelist,sizeof(movelist),0);
       fillchar(igraph,sizeof(igraph),0);
       fillchar(igraph,sizeof(igraph),0);
-      worklistmoves.destroy;
+      fillchar(degree,sizeof(degree),0);
+      worklist_moves.clear;
    {$endif}
    {$endif}
     end;
     end;
 
 
@@ -1224,9 +1283,15 @@ unit rgobj;
           include(igraph.bitmap[v],u);
           include(igraph.bitmap[v],u);
           {Precoloured nodes are not stored in the interference graph.}
           {Precoloured nodes are not stored in the interference graph.}
           if not(u in [first_supreg..last_supreg]) then
           if not(u in [first_supreg..last_supreg]) then
-            addadj(u,v);
+            begin
+              addadj(u,v);
+              inc(degree[u]);
+            end;
           if not(v in [first_supreg..last_supreg]) then
           if not(v in [first_supreg..last_supreg]) then
-            addadj(v,u);
+            begin
+              addadj(v,u);
+              inc(degree[v]);
+            end;
         end;
         end;
     end;
     end;
 
 
@@ -1240,13 +1305,18 @@ unit rgobj;
           add_edge(u,i);
           add_edge(u,i);
     end;
     end;
 
 
+{$ifdef ra_debug}
     procedure Trgobj.writegraph;
     procedure Trgobj.writegraph;
 
 
+    {This procedure writes out the current interference graph in the
+    register allocator.}
+
+
     var f:text;
     var f:text;
         i,j:Tsuperregister;
         i,j:Tsuperregister;
 
 
     begin
     begin
-      assign(f,'igraph');
+      assign(f,'igraph'+char(48+random(10))+char(48+random(10)));
       rewrite(f);
       rewrite(f);
       writeln(f,'Interference graph');
       writeln(f,'Interference graph');
       writeln(f);
       writeln(f);
@@ -1273,6 +1343,502 @@ unit rgobj;
     end;
     end;
 {$endif}
 {$endif}
 
 
+    procedure Trgobj.add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
+
+    begin
+      if movelist[u]=nil then
+        begin
+          getmem(movelist[u],64);
+          movelist[u]^.count:=0;
+        end
+      else if (movelist[u]^.count and 15)=15 then
+        reallocmem(movelist[u],(movelist[u]^.count+1)*4+64);
+      movelist[u]^.data[movelist[u]^.count]:=data;
+      inc(movelist[u]^.count);
+    end;
+
+    procedure Trgobj.add_move_instruction(instr:Taicpu);
+
+    {This procedure notifies a certain as a move instruction so the
+     register allocator can try to eliminate it.}
+
+    var i:Tmoveins;
+        ssupreg,dsupreg:Tsuperregister;
+
+    begin
+      i:=Tmoveins.create;
+      i.moveset:=ms_worklist_moves;
+      i.instruction:=instr;
+      worklist_moves.insert(i);
+      ssupreg:=instr.oper[0].reg.number shr 8;
+      add_to_movelist(ssupreg,i);
+      dsupreg:=instr.oper[1].reg.number shr 8;
+      add_to_movelist(dsupreg,i);
+    end;
+
+    function Trgobj.move_related(n:Tsuperregister):boolean;
+
+    var i:cardinal;
+
+    begin
+      move_related:=false;
+      if movelist[n]<>nil then
+        begin
+          for i:=0 to movelist[n]^.count-1 do
+            if Tmoveins(movelist[n]^.data[i]).moveset in
+               [ms_worklist_moves,ms_active_moves] then
+              begin
+                move_related:=true;
+                break;
+              end;
+        end;
+    end;
+
+    procedure Trgobj.make_work_list;
+
+    var n:Tsuperregister;
+
+    begin
+      for n:=first_imreg to maxintreg do
+        if degree[n]>cpu_registers then
+          spillworklist:=spillworklist+char(n)
+        else if move_related(n) then
+          freezeworklist:=freezeworklist+char(n)
+        else
+          simplifyworklist:=simplifyworklist+char(n);
+    end;
+
+    procedure Trgobj.prepare_colouring;
+
+    begin
+      make_work_list;
+      active_moves:=Tlinkedlist.create;
+      frozen_moves:=Tlinkedlist.create;
+      coalesced_moves:=Tlinkedlist.create;
+      constrained_moves:=Tlinkedlist.create;
+      fillchar(alias,sizeof(alias),0);
+      coalescednodes:='';
+      selectstack:='';
+    end;
+
+    procedure Trgobj.enable_moves(n:Tsuperregister);
+
+    var m:Tlinkedlistitem;
+        i:cardinal;
+
+    begin
+      if movelist[n]<>nil then
+        for i:=0 to movelist[n]^.count-1 do
+          begin 
+            m:=movelist[n]^.data[i];
+            if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
+              begin
+                if Tmoveins(m).moveset=ms_active_moves then
+                  begin
+                    {Move m from the set active_moves to the set worklist_moves.}
+                    active_moves.remove(m);
+                    Tmoveins(m).moveset:=ms_worklist_moves;
+                    worklist_moves.concat(m);
+                  end;
+              end;
+          end;
+    end;
+
+    procedure Trgobj.decrement_degree(m:Tsuperregister);
+
+    var adj:Pstring;
+        d:byte;
+        i:byte;
+        n:char;
+
+    begin
+      d:=degree[m];
+      dec(degree[m]);
+      if d=cpu_registers then
+        begin
+          {Enable moves for m.}
+          enable_moves(m);
+          {Enable moves for adjacent.}
+          adj:=igraph.adjlist[m];
+          if adj<>nil then
+            for i:=1 to length(adj^) do
+              begin
+                n:=adj^[i];
+                if (pos(n,selectstack) or pos(n,coalescednodes))=0 then
+                  enable_moves(Tsuperregister(n));
+              end;
+          {In case the node is in the spillworklist, delete it.}
+          delete(spillworklist,pos(char(m),spillworklist),1);
+          if move_related(m) then
+            freezeworklist:=freezeworklist+char(m)
+          else
+            simplifyworklist:=simplifyworklist+char(m);
+        end;
+    end;
+
+    procedure Trgobj.simplify;
+
+    var adj:Pstring;
+        i:byte;
+        m:char;
+        n:Tsuperregister;
+
+    begin
+      {We need to take a random element out of the simplifyworklist. We take
+       the last element. Dirty code!}
+      n:=Tsuperregister(simplifyworklist[byte(simplifyworklist[0])]);
+      dec(simplifyworklist[0]);
+      {Push it on the selectstack.}
+      selectstack:=selectstack+char(n);
+      adj:=igraph.adjlist[n];
+      if adj<>nil then
+        for i:=1 to length(adj^) do
+          begin
+            m:=adj^[i];
+            if (pos(m,selectstack) or pos(m,coalescednodes))=0 then
+              decrement_degree(Tsuperregister(m));
+          end;
+    end;
+
+    function Trgobj.get_alias(n:Tsuperregister):Tsuperregister;
+
+    begin
+      while pos(char(n),coalescednodes)<>0 do
+        n:=alias[n];
+      get_alias:=n;
+    end;
+
+    procedure Trgobj.add_worklist(u:Tsuperregister);
+
+    begin
+      if not(u in [first_supreg..last_supreg]) and not move_related(u) and
+         (degree[u]<cpu_registers) then
+        begin
+          delete(freezeworklist,pos(char(u),freezeworklist),1);
+          simplifyworklist:=simplifyworklist+char(u);
+        end;
+    end;
+
+    function Trgobj.adjacent_ok(u,v:Tsuperregister):boolean;
+
+    {Check wether u and v should be coalesced. u is precoloured.}
+
+      function ok(t,r:Tsuperregister):boolean;
+
+      begin
+        ok:=(degree[t]<cpu_registers) or
+            (t in [first_supreg..last_supreg]) or
+            (r in igraph.bitmap[t]);
+      end;
+
+    var adj:Pstring;
+        i:byte;
+        t:char;
+
+    begin
+      adjacent_ok:=true;
+      adj:=igraph.adjlist[v];
+      if adj<>nil then
+        for i:=1 to length(adj^) do
+          begin
+            t:=adj^[i];
+            if (pos(t,selectstack) or pos(t,coalescednodes))=0 then
+              if not ok(Tsuperregister(t),u) then
+                begin
+                  adjacent_ok:=false;
+                  break;
+                end;
+          end;
+    end;
+
+    function Trgobj.conservative(u,v:Tsuperregister):boolean;
+
+    var adj:Pstring;
+        done:set of char; {To prevent that we count nodes twice.}
+        i,k:byte;
+        n:char;
+
+    begin
+      k:=0;
+      done:=[];
+      adj:=igraph.adjlist[u];
+      if adj<>nil then
+        for i:=1 to length(adj^) do
+          begin
+            n:=adj^[i];
+            if (pos(n,selectstack) or pos(n,coalescednodes))=0 then
+              begin
+                include(done,n);
+                if degree[Tsuperregister(n)]>=cpu_registers then
+                  inc(k);
+              end;
+          end;
+      adj:=igraph.adjlist[v];
+      if adj<>nil then
+        for i:=1 to length(adj^) do
+          begin
+            n:=adj^[i];
+            if ((pos(n,selectstack) or pos(n,coalescednodes))=0) and
+               not (n in done) and
+               (degree[Tsuperregister(n)]>=cpu_registers) then
+              inc(k);
+         end;
+      conservative:=(k<cpu_registers);
+    end;
+
+    procedure Trgobj.combine(u,v:Tsuperregister);
+
+    var add:boolean;
+        adj:Pstring;
+        i,p:byte;
+        n,o:cardinal;
+        t:char;
+
+    begin
+      p:=pos(char(v),freezeworklist);
+      if p<>0 then
+        delete(freezeworklist,p,1)
+      else
+        delete(spillworklist,pos(char(v),spillworklist),1);
+      coalescednodes:=coalescednodes+char(v);
+      alias[v]:=u;
+
+      {Combine both movelists. Since the movelists are sets, only add
+       elements that are not already present.}
+      for n:=0 to movelist[v]^.count-1 do
+        begin
+          add:=true;
+          for o:=0 to movelist[u]^.count-1 do
+            if movelist[u]^.data[o]=movelist[v]^.data[n] then
+              begin
+                add:=false;
+                break;
+              end;
+          if add then
+            add_to_movelist(u,movelist[v]^.data[n]);
+        end;
+      enable_moves(v);
+
+      adj:=igraph.adjlist[v];
+      if adj<>nil then
+        for i:=1 to length(adj^) do
+          begin
+            t:=adj^[i];
+            if (pos(t,selectstack) or pos(t,coalescednodes))=0 then
+              begin
+                add_edge(Tsuperregister(t),u);
+                decrement_degree(Tsuperregister(t));
+              end;
+          end;
+      p:=pos(char(u),freezeworklist);
+      if (degree[u]>=cpu_registers) and (p<>0) then
+        begin
+          delete(freezeworklist,p,1);
+          spillworklist:=spillworklist+char(u);
+        end;
+    end;
+
+    procedure Trgobj.coalesce;
+
+    var m:Tmoveins;
+        x,y,u,v:Tsuperregister;
+
+    begin
+      m:=Tmoveins(worklist_moves.getfirst);
+      x:=get_alias(m.instruction.oper[0].reg.number shr 8);
+      y:=get_alias(m.instruction.oper[1].reg.number shr 8);
+      if y in [first_supreg..last_supreg] then
+        begin
+          u:=y;
+          v:=x;
+        end
+      else
+        begin
+          u:=x;
+          v:=y;
+        end;
+      if (u=v) then
+        begin
+          m.moveset:=ms_coalesced_moves;  {Already coalesced.}
+          coalesced_moves.insert(m);
+          add_worklist(u);
+        end
+      {Do u and v interfere? In that case the move is constrained. Two
+       precoloured nodes interfere allways. If v is precoloured, by the above
+       code u is precoloured, thus interference...}
+      else if (v in [first_supreg..last_supreg]) or (u in igraph.bitmap[v]) then
+        begin
+          m.moveset:=ms_constrained_moves;  {Cannot coalesce yet...}
+          constrained_moves.insert(m);
+          add_worklist(u);
+          add_worklist(v);
+        end
+      {Next test: is it possible and a good idea to coalesce??}
+      else if ((u in [first_supreg..last_supreg]) and adjacent_ok(u,v)) or
+              (not(u in [first_supreg..last_supreg]) and conservative(u,v)) then
+        begin
+          m.moveset:=ms_coalesced_moves;  {Move coalesced!}
+          coalesced_moves.insert(m);
+          combine(u,v);
+          add_worklist(u);
+        end
+      else
+        begin
+          m.moveset:=ms_active_moves;
+          active_moves.insert(m);
+        end;
+    end;
+
+    procedure Trgobj.freeze_moves(u:Tsuperregister);
+
+    var i:cardinal;
+        m:Tlinkedlistitem;
+        v,x,y:Tsuperregister;
+
+    begin
+      for i:=0 to movelist[u]^.count-1 do
+        begin
+          m:=movelist[u]^.data[i];
+          if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
+            begin
+              x:=Tmoveins(m).instruction.oper[0].reg.number shr 8;
+              y:=Tmoveins(m).instruction.oper[1].reg.number shr 8;
+              if get_alias(y)=get_alias(u) then
+                v:=get_alias(x)
+              else
+                v:=get_alias(y);
+              {Move m from active_moves/worklist_moves to frozen_moves.}
+              if Tmoveins(m).moveset=ms_active_moves then
+                active_moves.remove(m)
+              else
+                worklist_moves.remove(m);
+              Tmoveins(m).moveset:=ms_frozen_moves;
+              frozen_moves.insert(m);
+        
+              if not(move_related(v)) and (degree[v]<cpu_registers) then
+                begin
+                  delete(freezeworklist,pos(char(v),freezeworklist),1);
+                  simplifyworklist:=simplifyworklist+char(v);
+                end;
+            end;
+        end;
+    end;
+
+    procedure Trgobj.freeze;
+
+    var n:Tsuperregister;
+
+    begin
+      {We need to take a random element out of the freezeworklist. We take
+       the last element. Dirty code!}
+      n:=Tsuperregister(freezeworklist[byte(freezeworklist[0])]);
+      dec(freezeworklist[0]);
+      {Add it to the simplifyworklist.}
+      simplifyworklist:=simplifyworklist+char(n);
+      freeze_moves(n);
+    end;
+
+    procedure Trgobj.select_spill;
+
+    var n:char;
+
+    begin
+      {This code is WAY too naive. We need not to select just a register, but
+       the register that is used the least...}
+      n:=spillworklist[byte(spillworklist[0])];
+      dec(spillworklist[0]);
+      simplifyworklist:=simplifyworklist+n;
+      freeze_moves(Tsuperregister(n));
+    end;
+
+    procedure Trgobj.assign_colours;
+
+    {Assign_colours assigns the actual colours to the registers.}
+
+    var adj:Pstring;
+        i,j,k:byte;
+        n,a:Tsuperregister;
+        adj_colours,colourednodes:set of Tsuperregister;
+        w:char;
+
+    begin
+      spillednodes:='';
+      {Colour the cpu registers...}
+      colourednodes:=[first_supreg..last_supreg];
+      for i:=first_supreg to last_supreg do
+        colour[i]:=i;
+      {Now colour the imaginary registers on the select-stack.}
+      for i:=length(selectstack) downto 1 do
+        begin
+          n:=Tsuperregister(selectstack[i]);
+          {Create a list of colours that we cannot assign to n.}
+          adj_colours:=[];
+          adj:=igraph.adjlist[n];
+          if adj<>nil then
+            for j:=1 to length(adj^) do
+              begin
+                w:=adj^[j];
+                a:=get_alias(Tsuperregister(w));
+                if a in colourednodes then
+                  include(adj_colours,colour[a]);
+              end;
+          {Assume a spill by default...}
+          spillednodes:=spillednodes+char(n);
+          {Search for a colour not in this list.}
+          for k:=1 to cpu_registers do
+            if not(k in adj_colours) then
+              begin
+                colour[n]:=k;
+                dec(spillednodes[0]);  {Colour found: no spill.}
+                include(colourednodes,n);
+                break;
+              end;
+        end;
+      {Finally colour the nodes that were coalesced.}
+      for i:=1 to length(coalescednodes) do
+        begin
+          n:=Tsuperregister(coalescednodes[i]);
+          colour[n]:=colour[get_alias(n)];
+        end;
+      for i:=first_imreg to maxintreg do
+        writeln(i:4,'   ',colour[i]:4)
+    end;
+
+    procedure Trgobj.colour_registers;
+
+    begin
+      repeat
+        if length(simplifyworklist)<>0 then
+          simplify
+        else if not(worklist_moves.empty) then
+          coalesce
+        else if length(freezeworklist)<>0 then
+          freeze
+        else if length(spillworklist)<>0 then
+          select_spill;
+      until (length(simplifyworklist) or
+             byte(not(worklist_moves.empty)) or
+             length(freezeworklist) or
+             length(spillworklist)
+            )=0;
+      assign_colours;
+    end;
+
+    procedure Trgobj.epilogue_colouring;
+
+    begin
+      active_moves.destroy;
+      active_moves:=nil;
+      frozen_moves.destroy;
+      frozen_moves:=nil;
+      coalesced_moves.destroy;
+      coalesced_moves:=nil;
+      constrained_moves.destroy;
+      constrained_moves:=nil;
+    end;
+
+{$endif newra}
+
 
 
 {****************************************************************************
 {****************************************************************************
                                   TReference
                                   TReference
@@ -1403,7 +1969,12 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.35  2003-04-21 19:16:49  peter
+  Revision 1.36  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.35  2003/04/21 19:16:49  peter
     * count address regs separate
     * count address regs separate
 
 
   Revision 1.34  2003/04/17 16:48:21  daniel
   Revision 1.34  2003/04/17 16:48:21  daniel

+ 7 - 2
compiler/sparc/rgcpu.pas

@@ -66,11 +66,16 @@ procedure trgcpu.UngetRegisterInt(list:taasmoutput;reg:tregister);
       inherited ungetregisterint(list,reg);
       inherited ungetregisterint(list,reg);
   end;
   end;
 begin
 begin
-  rg := trgcpu.create;
+  rg := trgcpu.create(24); {24 registers.}
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.8  2003-03-15 22:51:58  mazen
+  Revision 1.9  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.8  2003/03/15 22:51:58  mazen
   * remaking sparc rtl compile
   * remaking sparc rtl compile
 
 
   Revision 1.7  2003/03/10 21:59:54  mazen
   Revision 1.7  2003/03/10 21:59:54  mazen

+ 35 - 7
compiler/x86/cgx86.pas

@@ -363,13 +363,24 @@ unit cgx86;
           OS_8,OS_S8,
           OS_8,OS_S8,
           OS_16,OS_S16:
           OS_16,OS_S16:
             begin
             begin
+            {$ifdef newra}
+              if target_info.alignment.paraalign = 2 then
+                tmpreg:=rg.getregisterint(list,OS_16)
+              else
+                tmpreg:=rg.getregisterint(list,OS_32);
+            {$else}
               if target_info.alignment.paraalign = 2 then
               if target_info.alignment.paraalign = 2 then
                 tmpreg:=get_scratch_reg_int(list,OS_16)
                 tmpreg:=get_scratch_reg_int(list,OS_16)
               else
               else
                 tmpreg:=get_scratch_reg_int(list,OS_32);
                 tmpreg:=get_scratch_reg_int(list,OS_32);
+            {$endif}
               a_load_ref_reg(list,size,r,tmpreg);
               a_load_ref_reg(list,size,r,tmpreg);
               list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
               list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
+            {$ifdef newra}
+              rg.ungetregisterint(list,tmpreg);
+            {$else}
               free_scratch_reg(list,tmpreg);
               free_scratch_reg(list,tmpreg);
+            {$endif}
             end;
             end;
           OS_32,OS_S32:
           OS_32,OS_S32:
             list.concat(taicpu.op_ref(A_PUSH,S_L,r));
             list.concat(taicpu.op_ref(A_PUSH,S_L,r));
@@ -405,10 +416,18 @@ unit cgx86;
           list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.base))
           list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.base))
         else
         else
           begin
           begin
+          {$ifdef newra}
+            tmpreg:=rg.getaddressregister(list);
+          {$else}
             tmpreg := get_scratch_reg_address(list);
             tmpreg := get_scratch_reg_address(list);
+          {$endif}
             a_loadaddr_ref_reg(list,r,tmpreg);
             a_loadaddr_ref_reg(list,r,tmpreg);
             list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
             list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
+          {$ifdef newra}
+            rg.ungetregisterint(list,tmpreg);
+          {$else}
             free_scratch_reg(list,tmpreg);
             free_scratch_reg(list,tmpreg);
+          {$endif}
           end;
           end;
       end;
       end;
 
 
@@ -780,7 +799,9 @@ unit cgx86;
           regloadsize: tcgsize;
           regloadsize: tcgsize;
           dstsize: topsize;
           dstsize: topsize;
           tmpreg : tregister;
           tmpreg : tregister;
+    {$ifndef newra}
           popecx : boolean;
           popecx : boolean;
+    {$endif}
           r:Tregister;
           r:Tregister;
           instr:Taicpu;
           instr:Taicpu;
 
 
@@ -805,6 +826,13 @@ unit cgx86;
               internalerror(200109233);
               internalerror(200109233);
             OP_SHR,OP_SHL,OP_SAR:
             OP_SHR,OP_SHL,OP_SAR:
               begin
               begin
+              {$ifdef newra}
+                tmpreg:=rg.getexplicitregisterint(list,NR_CL);
+                a_load_reg_reg(list,size,OS_8,dst,tmpreg);
+                list.concat(taicpu.op_reg_reg(Topcg2asmop[op],S_B,src,
+                            tmpreg));
+                rg.ungetregisterint(list,tmpreg);
+              {$else newra}
                 tmpreg.enum:=R_INTREGISTER;
                 tmpreg.enum:=R_INTREGISTER;
                 tmpreg.number:=NR_NO;
                 tmpreg.number:=NR_NO;
                 popecx := false;
                 popecx := false;
@@ -821,8 +849,6 @@ unit cgx86;
                         regloadsize:=OS_32;
                         regloadsize:=OS_32;
                     end;
                     end;
                     tmpreg := get_scratch_reg_int(list,OS_INT);
                     tmpreg := get_scratch_reg_int(list,OS_INT);
-                    tmpreg.enum:=R_INTREGISTER;
-                    tmpreg.number:=NR_EDI;
                     a_load_reg_reg(list,regloadsize,regloadsize,src,tmpreg);
                     a_load_reg_reg(list,regloadsize,regloadsize,src,tmpreg);
                   end;
                   end;
                 if src.number shr 8<>RS_ECX then
                 if src.number shr 8<>RS_ECX then
@@ -862,16 +888,13 @@ unit cgx86;
                   list.concat(taicpu.op_reg(A_POP,S_L,r))
                   list.concat(taicpu.op_reg(A_POP,S_L,r))
                 else if not (dst.number shr 8=RS_ECX) then
                 else if not (dst.number shr 8=RS_ECX) then
                   rg.ungetregisterint(list,r);
                   rg.ungetregisterint(list,r);
+              {$endif newra}
               end;
               end;
             else
             else
               begin
               begin
                 if reg2opsize(src) <> dstsize then
                 if reg2opsize(src) <> dstsize then
                   internalerror(200109226);
                   internalerror(200109226);
                 instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
                 instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
-{$ifdef newra}
-                if op in [_MOV,_XCHG] then
-                  rg.add_move_instruction(instr);
-{$endif newra}
                 list.concat(instr);
                 list.concat(instr);
               end;
               end;
           end;
           end;
@@ -1839,7 +1862,12 @@ unit cgx86;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.38  2003-04-17 16:48:21  daniel
+  Revision 1.39  2003-04-22 10:09:35  daniel
+    + Implemented the actual register allocator
+    + Scratch registers unavailable when new register allocator used
+    + maybe_save/maybe_restore unavailable when new register allocator used
+
+  Revision 1.38  2003/04/17 16:48:21  daniel
     * Added some code to keep track of move instructions in register
     * Added some code to keep track of move instructions in register
       allocator
       allocator