Browse Source

* Register allocator finished

daniel 22 years ago
parent
commit
41e0bc4cec

+ 24 - 7
compiler/aasmtai.pas

@@ -178,6 +178,8 @@ interface
        { Buffer type used for alignment }
        { Buffer type used for alignment }
        tfillbuffer = array[0..63] of char;
        tfillbuffer = array[0..63] of char;
 
 
+       Tspill_temp_list=array[0..255] of Treference;
+
        { abstract assembler item }
        { abstract assembler item }
        tai = class(TLinkedListItem)
        tai = class(TLinkedListItem)
 {$ifndef NOOPT}
 {$ifndef NOOPT}
@@ -402,6 +404,11 @@ interface
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
        end;
        end;
 
 
+      Taasmoutput=class;
+
+      Trggetproc=procedure(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister) of object;
+      Trgungetproc=procedure(list:Taasmoutput;position:Tai;const r:Tregister) of object;
+
        { Class template for assembler instructions
        { Class template for assembler instructions
        }
        }
        taicpu_abstract = class(tailineinfo)
        taicpu_abstract = class(tailineinfo)
@@ -436,6 +443,13 @@ interface
           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;
           function is_nop:boolean;virtual;abstract;
+          function is_move:boolean;virtual;abstract;
+          function spill_registers(list:Taasmoutput;
+                                   rgget:Trggetproc;
+                                   rgunget:Trgungetproc;
+                                   r:Tsupregset;
+                                   var unusedregsint:Tsupregset;
+                                   const spilltemplist:Tspill_temp_list):boolean;virtual;abstract;
        end;
        end;
 
 
        { alignment for operator }
        { alignment for operator }
@@ -1635,13 +1649,13 @@ uses
 
 
 
 
     procedure taicpu_abstract.derefimpl;
     procedure taicpu_abstract.derefimpl;
-      var
-        i : integer;
-      begin
-        for i:=1 to ops do
-          ppuderefoper(oper[i-1]);
-      end;
 
 
+    var i:byte;
+
+    begin
+      for i:=1 to ops do
+        ppuderefoper(oper[i-1]);
+    end;
 
 
 {****************************************************************************
 {****************************************************************************
                               tai_align_abstract
                               tai_align_abstract
@@ -1816,7 +1830,10 @@ uses
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.28  2003-05-12 18:13:57  peter
+  Revision 1.29  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.28  2003/05/12 18:13:57  peter
     * create rtti label using newasmsymboldata and update binding
     * create rtti label using newasmsymboldata and update binding
       only when calling tai_symbol.create
       only when calling tai_symbol.create
     * tai_symbol.create_global added
     * tai_symbol.create_global added

+ 32 - 18
compiler/cg64f32.pas

@@ -50,10 +50,10 @@ unit cg64f32;
         procedure a_reg_dealloc(list : taasmoutput;r : tregister64);override;
         procedure a_reg_dealloc(list : taasmoutput;r : tregister64);override;
         procedure a_load64_const_ref(list : taasmoutput;value : qword;const ref : treference);override;
         procedure a_load64_const_ref(list : taasmoutput;value : qword;const ref : treference);override;
         procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);override;
         procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);override;
-        procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);override;
-        procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);override;
+        procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64{$ifdef newra};delete:boolean{$endif});override;
+        procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64{$ifdef newra};delete:boolean{$endif});override;
         procedure a_load64_const_reg(list : taasmoutput;value: qword;reg : tregister64);override;
         procedure a_load64_const_reg(list : taasmoutput;value: qword;reg : tregister64);override;
-        procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);override;
+        procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64{$ifdef newra};delete: boolean{$endif});override;
         procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);override;
         procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);override;
         procedure a_load64_const_loc(list : taasmoutput;value : qword;const l : tlocation);override;
         procedure a_load64_const_loc(list : taasmoutput;value : qword;const l : tlocation);override;
         procedure a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);override;
         procedure a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);override;
@@ -97,7 +97,7 @@ unit cg64f32;
        globtype,globals,systems,
        globtype,globals,systems,
        cgbase,
        cgbase,
        verbose,
        verbose,
-       symbase,symconst,symdef,defutil,rgobj;
+       symbase,symconst,symdef,defutil,rgobj,tgobj;
 
 
 
 
     function joinreg64(reglo,reghi : tregister) : tregister64;
     function joinreg64(reglo,reghi : tregister) : tregister64;
@@ -150,7 +150,7 @@ unit cg64f32;
       end;
       end;
 
 
 
 
-    procedure tcg64f32.a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);
+    procedure tcg64f32.a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64{$ifdef newra};delete:boolean{$endif});
       var
       var
         tmpreg: tregister;
         tmpreg: tregister;
         tmpref: treference;
         tmpref: treference;
@@ -164,10 +164,6 @@ unit cg64f32;
           end;
           end;
         got_scratch:=false;
         got_scratch:=false;
         tmpref := ref;
         tmpref := ref;
-        if tmpref.base.enum<>R_INTREGISTER then
-          internalerror(200302035);
-        if reg.reglo.enum<>R_INTREGISTER then
-          internalerror(200302035);
         if (tmpref.base.number=reg.reglo.number) then
         if (tmpref.base.number=reg.reglo.number) then
          begin
          begin
          {$ifdef newra}
          {$ifdef newra}
@@ -196,6 +192,13 @@ unit cg64f32;
           end;
           end;
         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);
+{$ifdef newra}
+        if delete then
+          begin
+            tg.ungetiftemp(list,tmpref);
+            reference_release(list,tmpref);
+          end;
+{$endif}
         cg.a_load_ref_reg(list,OS_32,tmpref,reg.reghi);
         cg.a_load_ref_reg(list,OS_32,tmpref,reg.reghi);
 {$ifdef newra}
 {$ifdef newra}
         if got_scratch then
         if got_scratch then
@@ -207,10 +210,18 @@ unit cg64f32;
       end;
       end;
 
 
 
 
-    procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);
+    procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64{$ifdef newra};delete:boolean{$endif});
 
 
       begin
       begin
+      {$ifdef newra}
+        if delete then
+          rg.ungetregisterint(list,regsrc.reglo);
+      {$endif}
         cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
         cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
+      {$ifdef newra}
+        if delete then
+          rg.ungetregisterint(list,regsrc.reghi);
+      {$endif}
         cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
         cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
       end;
       end;
 
 
@@ -221,14 +232,14 @@ unit cg64f32;
         cg.a_load_const_reg(list,OS_32,hi(value),reg.reghi);
         cg.a_load_const_reg(list,OS_32,hi(value),reg.reghi);
       end;
       end;
 
 
-    procedure tcg64f32.a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);
+    procedure tcg64f32.a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64{$ifdef newra};delete :boolean{$endif});
 
 
       begin
       begin
         case l.loc of
         case l.loc of
           LOC_REFERENCE, LOC_CREFERENCE:
           LOC_REFERENCE, LOC_CREFERENCE:
-            a_load64_ref_reg(list,l.reference,reg);
+            a_load64_ref_reg(list,l.reference,reg{$ifdef newra},delete{$endif});
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
-            a_load64_reg_reg(list,l.register64,reg);
+            a_load64_reg_reg(list,l.register64,reg{$ifdef newra},delete{$endif});
           LOC_CONSTANT :
           LOC_CONSTANT :
             a_load64_const_reg(list,l.valueqword,reg);
             a_load64_const_reg(list,l.valueqword,reg);
           else
           else
@@ -271,7 +282,7 @@ unit cg64f32;
           LOC_REFERENCE, LOC_CREFERENCE:
           LOC_REFERENCE, LOC_CREFERENCE:
             a_load64_reg_ref(list,reg,l.reference);
             a_load64_reg_ref(list,reg,l.reference);
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
-            a_load64_reg_reg(list,reg,l.register64);
+            a_load64_reg_reg(list,reg,l.register64{$ifdef newra},false{$endif});
           else
           else
             internalerror(200112293);
             internalerror(200112293);
         end;
         end;
@@ -419,7 +430,7 @@ unit cg64f32;
         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}
       {$endif}
-        a_load64_ref_reg(list,ref,tempreg);
+        a_load64_ref_reg(list,ref,tempreg{$ifdef newra},false{$endif});
         a_op64_reg_reg(list,op,tempreg,reg);
         a_op64_reg_reg(list,op,tempreg,reg);
       {$ifdef newra}
       {$ifdef newra}
         rg.ungetregisterint(list,tempreg.reglo);
         rg.ungetregisterint(list,tempreg.reglo);
@@ -442,7 +453,7 @@ unit cg64f32;
         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}
       {$endif}
-        a_load64_ref_reg(list,ref,tempreg);
+        a_load64_ref_reg(list,ref,tempreg{$ifdef newra},false{$endif});
         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}
       {$ifdef newra}
@@ -466,7 +477,7 @@ unit cg64f32;
         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}
       {$endif}
-        a_load64_ref_reg(list,ref,tempreg);
+        a_load64_ref_reg(list,ref,tempreg{$ifdef newra},false{$endif});
         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}
       {$ifdef newra}
@@ -898,7 +909,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.45  2003-06-01 21:38:06  peter
+  Revision 1.46  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.45  2003/06/01 21:38:06  peter
     * getregisterfpu size parameter added
     * getregisterfpu size parameter added
     * op_const_reg size parameter added
     * op_const_reg size parameter added
     * sparc updates
     * sparc updates

+ 12 - 9
compiler/cgobj.pas

@@ -437,10 +437,10 @@ unit cgobj;
         procedure a_reg_dealloc(list : taasmoutput;r : tregister64);virtual;abstract;
         procedure a_reg_dealloc(list : taasmoutput;r : tregister64);virtual;abstract;
         procedure a_load64_const_ref(list : taasmoutput;value : qword;const ref : treference);virtual;abstract;
         procedure a_load64_const_ref(list : taasmoutput;value : qword;const ref : treference);virtual;abstract;
         procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);virtual;abstract;
         procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);virtual;abstract;
-        procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);virtual;abstract;
-        procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);virtual;abstract;
+        procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64{$ifdef newra};delete : boolean{$endif});virtual;abstract;
+        procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64{$ifdef newra};delete : boolean{$endif});virtual;abstract;
         procedure a_load64_const_reg(list : taasmoutput;value : qword;reg : tregister64);virtual;abstract;
         procedure a_load64_const_reg(list : taasmoutput;value : qword;reg : tregister64);virtual;abstract;
-        procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);virtual;abstract;
+        procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64{$ifdef newra};delete : boolean{$endif});virtual;abstract;
         procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);virtual;abstract;
         procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);virtual;abstract;
         procedure a_load64_const_loc(list : taasmoutput;value : qword;const l : tlocation);virtual;abstract;
         procedure a_load64_const_loc(list : taasmoutput;value : qword;const l : tlocation);virtual;abstract;
         procedure a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);virtual;abstract;
         procedure a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);virtual;abstract;
@@ -1172,10 +1172,10 @@ unit cgobj;
         else
         else
           begin
           begin
 {$ifdef newra}
 {$ifdef newra}
-            tmpreg := rg.getregisterint(list);
-            a_load_reg_reg(list,size,src2,tmpreg);
+            tmpreg := rg.getregisterint(list,size);
+            a_load_reg_reg(list,size,size,src2,tmpreg);
             a_op_reg_reg(list,op,size,src1,tmpreg);
             a_op_reg_reg(list,op,size,src1,tmpreg);
-            a_load_reg_reg,tmpreg,dst);
+            a_load_reg_reg(list,size,size,tmpreg,dst);
             rg.ungetregisterint(list,tmpreg);
             rg.ungetregisterint(list,tmpreg);
 {$else newra}
 {$else newra}
             internalerror(200305011);
             internalerror(200305011);
@@ -1691,14 +1691,14 @@ unit cgobj;
     procedure tcg64.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;
     procedure tcg64.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;
        regsrc,regdst : tregister64);
        regsrc,regdst : tregister64);
       begin
       begin
-        a_load64_reg_reg(list,regsrc,regdst);
+        a_load64_reg_reg(list,regsrc,regdst{$ifdef newra},false{$endif});
         a_op64_const_reg(list,op,value,regdst);
         a_op64_const_reg(list,op,value,regdst);
       end;
       end;
 
 
 
 
     procedure tcg64.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);
     procedure tcg64.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);
       begin
       begin
-        a_load64_reg_reg(list,regsrc2,regdst);
+        a_load64_reg_reg(list,regsrc2,regdst{$ifdef newra},false{$endif});
         a_op64_reg_reg(list,op,regsrc1,regdst);
         a_op64_reg_reg(list,op,regsrc1,regdst);
       end;
       end;
 
 
@@ -1712,7 +1712,10 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.105  2003-06-01 21:38:06  peter
+  Revision 1.106  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.105  2003/06/01 21:38:06  peter
     * getregisterfpu size parameter added
     * getregisterfpu size parameter added
     * op_const_reg size parameter added
     * op_const_reg size parameter added
     * sparc updates
     * sparc updates

+ 5 - 2
compiler/i386/ag386nsm.pas

@@ -384,7 +384,7 @@ interface
       found,
       found,
       do_line,
       do_line,
       quoted   : boolean;
       quoted   : boolean;
-      regstr:string[5];
+      regstr:string[6];
     begin
     begin
       if not assigned(p) then
       if not assigned(p) then
        exit;
        exit;
@@ -926,7 +926,10 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.34  2003-05-26 19:37:57  peter
+  Revision 1.35  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.34  2003/05/26 19:37:57  peter
     * don't generate align in .bss
     * don't generate align in .bss
 
 
   Revision 1.33  2003/04/22 10:09:35  daniel
   Revision 1.33  2003/04/22 10:09:35  daniel

+ 7 - 1
compiler/i386/cpubase.inc

@@ -147,7 +147,10 @@
 
 
       {# Stack pointer register }
       {# Stack pointer register }
       NR_STACK_POINTER_REG = NR_ESP;
       NR_STACK_POINTER_REG = NR_ESP;
+      RS_STACK_POINTER_REG = RS_ESP;
       {# Frame pointer register }
       {# Frame pointer register }
+      frame_pointer_reg = R_EBP;
+      RS_FRAME_POINTER_REG = RS_EBP;
       NR_FRAME_POINTER_REG = NR_EBP;
       NR_FRAME_POINTER_REG = NR_EBP;
       {# Register for addressing absolute data in a position independant way,
       {# Register for addressing absolute data in a position independant way,
          such as in PIC code. The exact meaning is ABI specific. For
          such as in PIC code. The exact meaning is ABI specific. For
@@ -202,7 +205,10 @@
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2003-05-31 15:05:28  peter
+  Revision 1.6  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.5  2003/05/31 15:05:28  peter
     * FUNCTION_RESULT64_LOW/HIGH_REG added for int64 results
     * FUNCTION_RESULT64_LOW/HIGH_REG added for int64 results
 
 
   Revision 1.4  2003/05/30 23:57:08  peter
   Revision 1.4  2003/05/30 23:57:08  peter

+ 42 - 4
compiler/i386/n386add.pas

@@ -350,7 +350,13 @@ interface
 
 
       var
       var
         cmpop      : boolean;
         cmpop      : boolean;
+      {$ifdef newra}
+        r          : Tregister;
+        i          : Tsuperregister;
+      {$else}
         pushed     : Tpushedsavedint;
         pushed     : Tpushedsavedint;
+      {$endif}
+        regstopush : Tsupregset;
       begin
       begin
         { string operations are not commutative }
         { string operations are not commutative }
         if nf_swaped in flags then
         if nf_swaped in flags then
@@ -362,16 +368,37 @@ interface
                    ltn,lten,gtn,gten,equaln,unequaln :
                    ltn,lten,gtn,gten,equaln,unequaln :
                      begin
                      begin
                        cmpop := true;
                        cmpop := true;
+                     {$ifndef newra}
                        rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
                        rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
+                     {$endif newra}
                        secondpass(left);
                        secondpass(left);
                        location_release(exprasmlist,left.location);
                        location_release(exprasmlist,left.location);
                        cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(2));
                        cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(2));
                        secondpass(right);
                        secondpass(right);
                        location_release(exprasmlist,right.location);
                        location_release(exprasmlist,right.location);
                        cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(1));
                        cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(1));
-                       rg.saveintregvars(exprasmlist,all_intregisters);
+                      {$ifdef newra}
+                        r.enum:=R_INTREGISTER;
+                        for i:=first_supreg to last_supreg do
+                          if i<>RS_FRAME_POINTER_REG then
+                            begin
+                              r.number:=i shl 8 or R_SUBWHOLE;
+                              rg.getexplicitregisterint(exprasmlist,r.number);
+                            end;
+                      {$else}
+                        rg.saveintregvars(exprasmlist,regstopush);
+                      {$endif}
                        cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
                        cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
-                       rg.restoreusedintregisters(exprasmlist,pushed);
+                      {$ifdef newra}
+                        for i:=first_supreg to last_supreg do
+                          if i<>RS_FRAME_POINTER_REG then
+                            begin
+                              r.number:=i shl 8 or R_SUBWHOLE;
+                              rg.ungetregisterint(exprasmlist,r);
+                            end;
+                      {$else}
+                        rg.restoreusedintregisters(exprasmlist,pushed);
+                      {$endif}
                        location_freetemp(exprasmlist,left.location);
                        location_freetemp(exprasmlist,left.location);
                        location_freetemp(exprasmlist,right.location);
                        location_freetemp(exprasmlist,right.location);
                      end;
                      end;
@@ -820,7 +847,7 @@ interface
         pushedfpu,
         pushedfpu,
         mboverflow,
         mboverflow,
         cmpop,
         cmpop,
-        unsigned   : boolean;
+        unsigned,delete:boolean;
         r:Tregister;
         r:Tregister;
 
 
       procedure firstjmp64bitcmp;
       procedure firstjmp64bitcmp;
@@ -944,14 +971,22 @@ interface
               { we can reuse a CREGISTER for comparison }
               { we can reuse a CREGISTER for comparison }
               if not((left.location.loc=LOC_CREGISTER) and cmpop) then
               if not((left.location.loc=LOC_CREGISTER) and cmpop) then
                begin
                begin
+               {$ifdef newra}
+                 delete:=left.location.loc<>LOC_CREGISTER;
+               {$else}
                  if (left.location.loc<>LOC_CREGISTER) then
                  if (left.location.loc<>LOC_CREGISTER) then
                   begin
                   begin
                     location_freetemp(exprasmlist,left.location);
                     location_freetemp(exprasmlist,left.location);
                     location_release(exprasmlist,left.location);
                     location_release(exprasmlist,left.location);
                   end;
                   end;
+               {$endif}
                  hregister:=rg.getregisterint(exprasmlist,OS_INT);
                  hregister:=rg.getregisterint(exprasmlist,OS_INT);
                  hregister2:=rg.getregisterint(exprasmlist,OS_INT);
                  hregister2:=rg.getregisterint(exprasmlist,OS_INT);
+               {$ifdef newra}
+                 cg64.a_load64_loc_reg(exprasmlist,left.location,joinreg64(hregister,hregister2),delete);
+               {$else}
                  cg64.a_load64_loc_reg(exprasmlist,left.location,joinreg64(hregister,hregister2));
                  cg64.a_load64_loc_reg(exprasmlist,left.location,joinreg64(hregister,hregister2));
+               {$endif}
                  location_reset(left.location,LOC_REGISTER,OS_64);
                  location_reset(left.location,LOC_REGISTER,OS_64);
                  left.location.registerlow:=hregister;
                  left.location.registerlow:=hregister;
                  left.location.registerhigh:=hregister2;
                  left.location.registerhigh:=hregister2;
@@ -1607,7 +1642,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.69  2003-05-30 23:49:18  jonas
+  Revision 1.70  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.69  2003/05/30 23:49:18  jonas
     * a_load_loc_reg now has an extra size parameter for the destination
     * a_load_loc_reg now has an extra size parameter for the destination
       register (properly fixes what I worked around in revision 1.106 of
       register (properly fixes what I worked around in revision 1.106 of
       ncgutil.pas)
       ncgutil.pas)

+ 6 - 2
compiler/i386/n386inl.pas

@@ -331,8 +331,9 @@ implementation
               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}
             {$ifdef newra}
-              if scratch_reg then
+{              if scratch_reg then}
                 rg.ungetregisterint(exprasmlist,hregister);
                 rg.ungetregisterint(exprasmlist,hregister);
+              location_release(exprasmlist,Tcallparanode(left).left.location);
             {$else}
             {$else}
               if scratch_reg then
               if scratch_reg then
                 cg.free_scratch_reg(exprasmlist,hregister);
                 cg.free_scratch_reg(exprasmlist,hregister);
@@ -346,7 +347,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.62  2003-06-01 21:38:06  peter
+  Revision 1.63  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.62  2003/06/01 21:38:06  peter
     * getregisterfpu size parameter added
     * getregisterfpu size parameter added
     * op_const_reg size parameter added
     * op_const_reg size parameter added
     * sparc updates
     * sparc updates

+ 7 - 14
compiler/i386/n386mat.pas

@@ -164,7 +164,7 @@ implementation
           else
           else
             begin
             begin
               hreg1:=rg.getregisterint(exprasmlist,right.location.size);
               hreg1:=rg.getregisterint(exprasmlist,right.location.size);
-              cg.a_load_loc_reg(exprasmlist,right.location,hreg1);
+              cg.a_load_loc_reg(exprasmlist,OS_32,right.location,hreg1);
               rg.ungetregisterint(exprasmlist,hreg1);
               rg.ungetregisterint(exprasmlist,hreg1);
               emit_reg(op,S_L,hreg1);
               emit_reg(op,S_L,hreg1);
             end;
             end;
@@ -430,13 +430,7 @@ implementation
 
 
     begin
     begin
       secondpass(left);
       secondpass(left);
-    {$ifndef newra}
-      maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
-    {$endif}
       secondpass(right);
       secondpass(right);
-    {$ifndef newra}
-      maybe_restore(exprasmlist,left.location,pushedregs);
-    {$endif newra}
 
 
       { determine operator }
       { determine operator }
       if nodetype=shln then
       if nodetype=shln then
@@ -452,10 +446,6 @@ implementation
           location_force_reg(exprasmlist,left.location,OS_64,false);
           location_force_reg(exprasmlist,left.location,OS_64,false);
           hregisterhigh:=left.location.registerhigh;
           hregisterhigh:=left.location.registerhigh;
           hregisterlow:=left.location.registerlow;
           hregisterlow:=left.location.registerlow;
-          if hregisterhigh.enum<>R_INTREGISTER then
-            internalerror(200302056);
-          if hregisterlow.enum<>R_INTREGISTER then
-            internalerror(200302056);
 
 
           { shifting by a constant directly coded: }
           { shifting by a constant directly coded: }
           if (right.nodetype=ordconstn) then
           if (right.nodetype=ordconstn) then
@@ -504,7 +494,7 @@ implementation
             begin
             begin
               { load right operators in a register }
               { load right operators in a register }
               hregister2:=rg.getexplicitregisterint(exprasmlist,NR_ECX);
               hregister2:=rg.getexplicitregisterint(exprasmlist,NR_ECX);
-              cg.a_load_loc_reg(exprasmlist,right.location,hregister2);
+              cg.a_load_loc_reg(exprasmlist,OS_32,right.location,hregister2);
               if right.location.loc<>LOC_CREGISTER then
               if right.location.loc<>LOC_CREGISTER then
                 location_release(exprasmlist,right.location);
                 location_release(exprasmlist,right.location);
 
 
@@ -576,7 +566,7 @@ implementation
               if right.location.loc<>LOC_CREGISTER then
               if right.location.loc<>LOC_CREGISTER then
                 location_release(exprasmlist,right.location);
                 location_release(exprasmlist,right.location);
               hregister2:=rg.getexplicitregisterint(exprasmlist,NR_ECX);
               hregister2:=rg.getexplicitregisterint(exprasmlist,NR_ECX);
-              cg.a_load_loc_reg(exprasmlist,right.location,hregister2);
+              cg.a_load_loc_reg(exprasmlist,OS_32,right.location,hregister2);
 
 
               { right operand is in ECX }
               { right operand is in ECX }
               emit_reg_reg(op,S_L,r2,location.register);
               emit_reg_reg(op,S_L,r2,location.register);
@@ -1183,7 +1173,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.55  2003-05-31 15:04:31  peter
+  Revision 1.56  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.55  2003/05/31 15:04:31  peter
     * load_loc_reg update
     * load_loc_reg update
 
 
   Revision 1.54  2003/05/22 21:32:29  peter
   Revision 1.54  2003/05/22 21:32:29  peter

+ 28 - 11
compiler/i386/rgcpu.pas

@@ -39,8 +39,10 @@ unit rgcpu;
           fpuvaroffset : byte;
           fpuvaroffset : byte;
 
 
           { to keep the same allocation order as with the old routines }
           { to keep the same allocation order as with the old routines }
+{$ifdef newra}
+          procedure add_constraints(reg:Tnewregister);override;
+{$else}
           function getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;override;
           function getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;override;
-{$ifndef newra}
           function getaddressregister(list:Taasmoutput):Tregister;override;
           function getaddressregister(list:Taasmoutput):Tregister;override;
           procedure ungetregisterint(list:Taasmoutput;r:Tregister); override;
           procedure ungetregisterint(list:Taasmoutput;r:Tregister); override;
           function getexplicitregisterint(list:Taasmoutput;r:Tnewregister):Tregister;override;
           function getexplicitregisterint(list:Taasmoutput;r:Tnewregister):Tregister;override;
@@ -59,30 +61,37 @@ unit rgcpu;
           function makeregsize(reg: tregister; size: tcgsize): tregister; override;
           function makeregsize(reg: tregister; size: tcgsize): tregister; override;
 
 
           { pushes and restores registers }
           { pushes and restores registers }
+{$ifndef newra}
           procedure pushusedintregisters(list:Taasmoutput;
           procedure pushusedintregisters(list:Taasmoutput;
                                          var pushed:Tpushedsavedint;
                                          var pushed:Tpushedsavedint;
                                          const s:Tsupregset);
                                          const s:Tsupregset);
+{$endif}
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
           procedure pushusedotherregisters(list:Taasmoutput;
           procedure pushusedotherregisters(list:Taasmoutput;
                                            var pushed:Tpushedsavedother;
                                            var pushed:Tpushedsavedother;
                                            const s:Tregisterset);
                                            const s:Tregisterset);
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
-
+{$ifndef newra}
           procedure popusedintregisters(list:Taasmoutput;
           procedure popusedintregisters(list:Taasmoutput;
                                         const pushed:Tpushedsavedint);
                                         const pushed:Tpushedsavedint);
+{$endif}
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
           procedure popusedotherregisters(list:Taasmoutput;
           procedure popusedotherregisters(list:Taasmoutput;
                                           const pushed:Tpushedsavedother);
                                           const pushed:Tpushedsavedother);
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
 
 
+{$ifndef newra}
           procedure saveusedintregisters(list:Taasmoutput;
           procedure saveusedintregisters(list:Taasmoutput;
                                          var saved:Tpushedsavedint;
                                          var saved:Tpushedsavedint;
                                          const s:Tsupregset);override;
                                          const s:Tsupregset);override;
+{$endif}
           procedure saveusedotherregisters(list:Taasmoutput;
           procedure saveusedotherregisters(list:Taasmoutput;
                                            var saved:Tpushedsavedother;
                                            var saved:Tpushedsavedother;
                                            const s:Tregisterset);override;
                                            const s:Tregisterset);override;
+{$ifndef newra}
           procedure restoreusedintregisters(list:Taasmoutput;
           procedure restoreusedintregisters(list:Taasmoutput;
                                             const saved:Tpushedsavedint);override;
                                             const saved:Tpushedsavedint);override;
+{$endif}
           procedure restoreusedotherregisters(list:Taasmoutput;
           procedure restoreusedotherregisters(list:Taasmoutput;
                                               const saved:Tpushedsavedother);override;
                                               const saved:Tpushedsavedother);override;
 
 
@@ -168,16 +177,15 @@ unit rgcpu;
 {************************************************************************}
 {************************************************************************}
 
 
 {$ifdef newra}
 {$ifdef newra}
-    function Trgcpu.getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;
+    procedure Trgcpu.add_constraints(reg:Tnewregister);
 
 
     begin
     begin
-      getregisterint:=inherited getregisterint(list,size);
-      if size in [OS_8,OS_S8] then
+      if reg and $ff in [R_SUBL,R_SUBH] then
         begin
         begin
           {These registers have no 8-bit subregister, so add interferences.}
           {These registers have no 8-bit subregister, so add interferences.}
-          add_edge(getregisterint.number shr 8,RS_ESI);
-          add_edge(getregisterint.number shr 8,RS_EDI);
-          add_edge(getregisterint.number shr 8,RS_EBP);
+          add_edge(reg shr 8,RS_ESI);
+          add_edge(reg shr 8,RS_EDI);
+          add_edge(reg shr 8,RS_EBP);
         end;
         end;
     end;
     end;
 {$endif}
 {$endif}
@@ -350,7 +358,7 @@ unit rgcpu;
            ungetregisterint(list,ref.index);
            ungetregisterint(list,ref.index);
       end;
       end;
 
 
-
+{$ifndef newra}
     procedure trgcpu.pushusedintregisters(list:Taasmoutput;
     procedure trgcpu.pushusedintregisters(list:Taasmoutput;
                                          var pushed:Tpushedsavedint;
                                          var pushed:Tpushedsavedint;
                                          const s:Tsupregset);
                                          const s:Tsupregset);
@@ -383,6 +391,7 @@ unit rgcpu;
       testregisters;
       testregisters;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
     end;
     end;
+{$endif}
 
 
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
     procedure trgcpu.pushusedotherregisters(list:Taasmoutput;
     procedure trgcpu.pushusedotherregisters(list:Taasmoutput;
@@ -422,6 +431,7 @@ unit rgcpu;
     end;
     end;
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
 
 
+{$ifndef newra}
     procedure trgcpu.popusedintregisters(list:Taasmoutput;
     procedure trgcpu.popusedintregisters(list:Taasmoutput;
                                          const pushed:Tpushedsavedint);
                                          const pushed:Tpushedsavedint);
 
 
@@ -448,6 +458,7 @@ unit rgcpu;
       testregisters;
       testregisters;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
     end;
     end;
+{$endif}
 
 
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
     procedure trgcpu.popusedotherregisters(list:Taasmoutput;
     procedure trgcpu.popusedotherregisters(list:Taasmoutput;
@@ -482,6 +493,7 @@ unit rgcpu;
     end;
     end;
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
 
 
+{$ifndef newra}
     procedure trgcpu.saveusedintregisters(list:Taasmoutput;
     procedure trgcpu.saveusedintregisters(list:Taasmoutput;
                                           var saved:Tpushedsavedint;
                                           var saved:Tpushedsavedint;
                                           const s:Tsupregset);
                                           const s:Tsupregset);
@@ -493,6 +505,7 @@ unit rgcpu;
       else
       else
         inherited saveusedintregisters(list,saved,s);
         inherited saveusedintregisters(list,saved,s);
     end;
     end;
+{$endif}
 
 
 
 
     procedure trgcpu.saveusedotherregisters(list:Taasmoutput;var saved:Tpushedsavedother;
     procedure trgcpu.saveusedotherregisters(list:Taasmoutput;var saved:Tpushedsavedother;
@@ -508,7 +521,7 @@ unit rgcpu;
         inherited saveusedotherregisters(list,saved,s);
         inherited saveusedotherregisters(list,saved,s);
     end;
     end;
 
 
-
+{$ifndef newra}
     procedure trgcpu.restoreusedintregisters(list:Taasmoutput;
     procedure trgcpu.restoreusedintregisters(list:Taasmoutput;
                                              const saved:tpushedsavedint);
                                              const saved:tpushedsavedint);
 
 
@@ -519,6 +532,7 @@ unit rgcpu;
       else
       else
         inherited restoreusedintregisters(list,saved);
         inherited restoreusedintregisters(list,saved);
     end;
     end;
+{$endif}
 
 
     procedure trgcpu.restoreusedotherregisters(list:Taasmoutput;
     procedure trgcpu.restoreusedotherregisters(list:Taasmoutput;
                                                const saved:tpushedsavedother);
                                                const saved:tpushedsavedother);
@@ -581,7 +595,10 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.23  2003-06-01 21:38:06  peter
+  Revision 1.24  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.23  2003/06/01 21:38:06  peter
     * getregisterfpu size parameter added
     * getregisterfpu size parameter added
     * op_const_reg size parameter added
     * op_const_reg size parameter added
     * sparc updates
     * sparc updates

+ 4 - 5
compiler/m68k/cpubase.pas

@@ -366,10 +366,6 @@ uses
 
 
       lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,LOC_CREGISTER];
       lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,LOC_CREGISTER];
 
 
-      {# Constant defining possibly all registers which might require saving }
-      ALL_REGISTERS = [R_D1..R_FPCR];
-      ALL_INTREGISTERS = [1..255];
-
       general_registers = [R_D0..R_D7];
       general_registers = [R_D0..R_D7];
       general_superregisters = [RS_D0..RS_D7];
       general_superregisters = [RS_D0..RS_D7];
 
 
@@ -709,7 +705,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.20  2003-04-23 13:40:33  peter
+  Revision 1.21  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.20  2003/04/23 13:40:33  peter
     * fix m68k compile
     * fix m68k compile
 
 
   Revision 1.19  2003/04/23 12:35:35  florian
   Revision 1.19  2003/04/23 12:35:35  florian

+ 8 - 1
compiler/ncal.pas

@@ -2300,8 +2300,10 @@ type
 
 
               { procedure does a call }
               { procedure does a call }
               if not (block_type in [bt_const,bt_type]) then
               if not (block_type in [bt_const,bt_type]) then
+            {$ifndef newra}
                 include(current_procinfo.flags,pi_do_call);
                 include(current_procinfo.flags,pi_do_call);
               rg.incrementintregisterpushed(all_intregisters);
               rg.incrementintregisterpushed(all_intregisters);
+            {$endif}
               rg.incrementotherregisterpushed(all_registers);
               rg.incrementotherregisterpushed(all_registers);
            end
            end
          else
          else
@@ -2336,7 +2338,9 @@ type
                 end;
                 end;
 
 
              { It doesn't hurt to calculate it already though :) (JM) }
              { It doesn't hurt to calculate it already though :) (JM) }
+          {$ifndef newra}
              rg.incrementintregisterpushed(tprocdef(procdefinition).usedintregisters);
              rg.incrementintregisterpushed(tprocdef(procdefinition).usedintregisters);
+          {$endif}
              rg.incrementotherregisterpushed(tprocdef(procdefinition).usedotherregisters);
              rg.incrementotherregisterpushed(tprocdef(procdefinition).usedotherregisters);
            end;
            end;
 
 
@@ -2569,7 +2573,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.162  2003-05-26 21:17:17  peter
+  Revision 1.163  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.162  2003/05/26 21:17:17  peter
     * procinlinenode removed
     * procinlinenode removed
     * aktexit2label removed, fast exit removed
     * aktexit2label removed, fast exit removed
     + tcallnode.inlined_pass_2 added
     + tcallnode.inlined_pass_2 added

+ 161 - 25
compiler/ncgcal.pas

@@ -497,7 +497,7 @@ implementation
                         location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
                         location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
 {$endif newra}
 {$endif newra}
                       cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
                       cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
-                          location.register64);
+                          location.register64{$ifdef newra},false{$endif});
                     end
                     end
                    else
                    else
 {$endif cpu64bit}
 {$endif cpu64bit}
@@ -508,7 +508,7 @@ implementation
                       r.enum:=R_INTREGISTER;
                       r.enum:=R_INTREGISTER;
                       r.number:=nr;
                       r.number:=nr;
 {$ifdef newra}
 {$ifdef newra}
-                      rg.getexplicitregisterint(exprasmlist,nr);
+{                      rg.getexplicitregisterint(exprasmlist,nr);}
                       rg.ungetregisterint(exprasmlist,r);
                       rg.ungetregisterint(exprasmlist,r);
                       location.register:=rg.getregisterint(exprasmlist,cgsize);
                       location.register:=rg.getregisterint(exprasmlist,cgsize);
 {$else newra}
 {$else newra}
@@ -573,26 +573,34 @@ implementation
                end;
                end;
              ppn:=tcallparanode(ppn.right);
              ppn:=tcallparanode(ppn.right);
           end;
           end;
-
       end;
       end;
 
 
 
 
     procedure tcgcallnode.normal_pass_2;
     procedure tcgcallnode.normal_pass_2;
       var
       var
-         regs_to_push_int : Tsupregset;
          regs_to_push_other : tregisterset;
          regs_to_push_other : tregisterset;
          unusedstate: pointer;
          unusedstate: pointer;
-         pushedother : tpushedsavedother;
+      {$ifdef newra}
+         i:Tsuperregister;
+         regs_to_alloc,regs_to_free:Tsupregset;
+      {$else}
+         regs_to_push_int : Tsupregset;
          pushedint : tpushedsavedint;
          pushedint : tpushedsavedint;
+         pushedregs : tmaybesave;
+      {$endif}
+         pushedother : tpushedsavedother;
          oldpushedparasize : longint;
          oldpushedparasize : longint;
          { adress returned from an I/O-error }
          { adress returned from an I/O-error }
          iolabel : tasmlabel;
          iolabel : tasmlabel;
          { help reference pointer }
          { help reference pointer }
-         href : treference;
-         pushedregs : tmaybesave;
+         href,helpref : treference;
+         hp : tnode;
+         pp : tcallparanode;
+         store_parast_fixup,
          para_alignment,
          para_alignment,
          pop_size : longint;
          pop_size : longint;
-         accreg : tregister;
+         r,accreg,
+         vmtreg,vmtreg2 : tregister;
          oldaktcallnode : tcallnode;
          oldaktcallnode : tcallnode;
       begin
       begin
          if not assigned(procdefinition) then
          if not assigned(procdefinition) then
@@ -605,7 +613,7 @@ implementation
          { already here, we avoid later a push/pop                    }
          { already here, we avoid later a push/pop                    }
          if is_widestring(resulttype.def) then
          if is_widestring(resulttype.def) then
            begin
            begin
-             tg.GetTemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
+             tg.gettemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
              cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
              cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
            end
            end
          else if is_ansistring(resulttype.def) then
          else if is_ansistring(resulttype.def) then
@@ -634,10 +642,12 @@ implementation
               else
               else
                 iolabel:=nil;
                 iolabel:=nil;
 
 
+{$ifdef newra}
+              regs_to_alloc:=Tprocdef(procdefinition).usedintregisters;
+{$else}
               { save all used registers and possible registers
               { save all used registers and possible registers
                 used for the return value }
                 used for the return value }
               regs_to_push_int := tprocdef(procdefinition).usedintregisters;
               regs_to_push_int := tprocdef(procdefinition).usedintregisters;
-              regs_to_push_other := tprocdef(procdefinition).usedotherregisters;
               if (not is_void(resulttype.def)) and
               if (not is_void(resulttype.def)) and
                  (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
                  (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
                begin
                begin
@@ -652,25 +662,35 @@ implementation
                    include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
                    include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
                end;
                end;
               rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
               rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
+{$endif}
+
+              regs_to_push_other := tprocdef(procdefinition).usedotherregisters;
               rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
               rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
 
 
               { on the ppc, ever procedure saves the non-volatile registers it uses itself }
               { on the ppc, ever procedure saves the non-volatile registers it uses itself }
               { and must make sure it saves its volatile registers before doing a call     }
               { and must make sure it saves its volatile registers before doing a call     }
 {$ifdef i386}
 {$ifdef i386}
               { give used registers through }
               { give used registers through }
+{$ifndef newra}
               rg.usedintinproc:=rg.usedintinproc + tprocdef(procdefinition).usedintregisters;
               rg.usedintinproc:=rg.usedintinproc + tprocdef(procdefinition).usedintregisters;
+{$endif}
               rg.usedinproc:=rg.usedinproc + tprocdef(procdefinition).usedotherregisters;
               rg.usedinproc:=rg.usedinproc + tprocdef(procdefinition).usedotherregisters;
 {$endif i386}
 {$endif i386}
            end
            end
          else
          else
            begin
            begin
-              regs_to_push_int := all_intregisters;
-              regs_to_push_other := all_registers;
+              {No procedure is allowed to destroy ebp.}
+{$ifdef newra}
+              regs_to_alloc:=ALL_INTREGISTERS-[RS_FRAME_POINTER_REG];
+{$else}
+              regs_to_push_int := all_intregisters-[RS_FRAME_POINTER_REG];
               rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
               rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
+{$endif}
+              regs_to_push_other := all_registers;
               rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
               rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
-{$ifdef i386}
+{$ifndef newra}
               rg.usedinproc:=all_registers;
               rg.usedinproc:=all_registers;
-{$endif i386}
+{$endif}
               { no IO check for methods and procedure variables }
               { no IO check for methods and procedure variables }
               iolabel:=nil;
               iolabel:=nil;
            end;
            end;
@@ -693,6 +713,7 @@ implementation
          if assigned(right) then
          if assigned(right) then
            secondpass(right);
            secondpass(right);
 
 
+{$ifdef disabled}
          if (po_virtualmethod in procdefinition.procoptions) and
          if (po_virtualmethod in procdefinition.procoptions) and
             assigned(methodpointer) then
             assigned(methodpointer) then
            begin
            begin
@@ -711,6 +732,7 @@ implementation
                 not(is_cppclass(tprocdef(procdefinition)._class)) then
                 not(is_cppclass(tprocdef(procdefinition)._class)) then
                cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
                cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
            end;
            end;
+{$endif disabled}
 
 
          if assigned(left) then
          if assigned(left) then
            begin
            begin
@@ -744,43 +766,124 @@ implementation
                  ((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
                  ((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
                 push_framepointer;
                 push_framepointer;
 
 
+{$ifndef newra}
               rg.saveintregvars(exprasmlist,regs_to_push_int);
               rg.saveintregvars(exprasmlist,regs_to_push_int);
+{$endif}
               rg.saveotherregvars(exprasmlist,regs_to_push_other);
               rg.saveotherregvars(exprasmlist,regs_to_push_other);
 
 
               if (po_virtualmethod in procdefinition.procoptions) and
               if (po_virtualmethod in procdefinition.procoptions) and
                  assigned(methodpointer) then
                  assigned(methodpointer) then
                 begin
                 begin
+                   secondpass(methodpointer);
+                   location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
+                   vmtreg:=methodpointer.location.register;
+
+                   { virtual methods require an index }
+                   if tprocdef(procdefinition).extnumber=-1 then
+                     internalerror(200304021);
+                   { VMT should already be loaded in a register }
+                   if vmtreg.number=NR_NO then
+                     internalerror(200304022);
+
+                   { test validity of VMT }
+                   if not(is_interface(tprocdef(procdefinition)._class)) and
+                      not(is_cppclass(tprocdef(procdefinition)._class)) then
+                     cg.g_maybe_testvmt(exprasmlist,vmtreg,tprocdef(procdefinition)._class);
+
+{$ifdef newra}
+                   { release self }
+                   rg.ungetaddressregister(exprasmlist,vmtreg);
+                   vmtreg2:=rg.getabtregisterint(exprasmlist,OS_ADDR);
+                   rg.ungetregisterint(exprasmlist,vmtreg2);
+                   cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,vmtreg,vmtreg2);
+                   for i:=first_supreg to last_supreg do
+                    if i in regs_to_alloc then
+                      begin
+                        r.number:=i shl 8 or R_SUBWHOLE;
+                        rg.getexplicitregisterint(exprasmlist,r.number);
+                      end;
+{$endif}
                    { call method }
                    { call method }
-                   reference_reset_base(href,methodpointer.location.register,
+                   reference_reset_base(href,{$ifdef newra}vmtreg2{$else}vmtreg{$endif},
                       tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
                       tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
                    cg.a_call_ref(exprasmlist,href);
                    cg.a_call_ref(exprasmlist,href);
-
-                   { release vmt register }
-                   rg.ungetaddressregister(exprasmlist,methodpointer.location.register);
+{$ifndef newra}
+                   { release self }
+                   rg.ungetaddressregister(exprasmlist,vmtreg);
+{$endif}
                 end
                 end
               else
               else
                 begin
                 begin
+{$ifdef newra}
+                  for i:=first_supreg to last_supreg do
+                    if i in regs_to_alloc then
+                      begin
+                        r.number:=i shl 8 or R_SUBWHOLE;
+                        rg.getexplicitregisterint(exprasmlist,r.number);
+                      end;
+{$endif}
                   { Calling interrupt from the same code requires some
                   { Calling interrupt from the same code requires some
                     extra code }
                     extra code }
                   if (po_interrupt in procdefinition.procoptions) then
                   if (po_interrupt in procdefinition.procoptions) then
                     extra_interrupt_code;
                     extra_interrupt_code;
-
                   cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
                   cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
                end;
                end;
            end
            end
          else
          else
            { now procedure variable case }
            { now procedure variable case }
            begin
            begin
+              secondpass(right);
+
+{$ifdef newra}
+              if right.location.loc in  [LOC_REFERENCE,LOC_CREFERENCE] then
+                begin
+                  helpref:=right.location.reference;
+                  if helpref.index.number<>NR_NO then
+                    begin
+                      rg.ungetregisterint(exprasmlist,helpref.index);
+                      helpref.index:=rg.getabtregisterint(exprasmlist,OS_ADDR);
+                      cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
+                                        right.location.reference.index,helpref.index);
+                    end;
+                  if helpref.base.number<>NR_NO then
+                    begin
+                      rg.ungetregisterint(exprasmlist,helpref.base);
+                      helpref.base:=rg.getabtregisterint(exprasmlist,OS_ADDR);
+                      cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
+                                        right.location.reference.base,helpref.base);
+                    end;
+                end
+              else
+                rg.ungetregisterint(exprasmlist,right.location.register);
+              
+              reference_release(exprasmlist,helpref);
+              location_freetemp(exprasmlist,right.location);
+              for i:=first_supreg to last_supreg do
+                if i in regs_to_alloc then
+                  begin
+                    r.number:=i shl 8 or R_SUBWHOLE;
+                    rg.getexplicitregisterint(exprasmlist,r.number);
+                  end;
+{$endif}
               { Calling interrupt from the same code requires some
               { Calling interrupt from the same code requires some
                 extra code }
                 extra code }
               if (po_interrupt in procdefinition.procoptions) then
               if (po_interrupt in procdefinition.procoptions) then
                 extra_interrupt_code;
                 extra_interrupt_code;
 
 
-              rg.saveintregvars(exprasmlist,ALL_INTREGISTERS);
-              rg.saveotherregvars(exprasmlist,ALL_REGISTERS);
-              cg.a_call_loc(exprasmlist,right.location);
-              location_release(exprasmlist,right.location);
-              location_freetemp(exprasmlist,right.location);
+            {$ifndef newra}
+               helpref:=right.location.reference;
+               rg.saveintregvars(exprasmlist,ALL_INTREGISTERS);
+            {$endif}
+               rg.saveotherregvars(exprasmlist,ALL_REGISTERS);
+               if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+                 cg.a_call_ref(exprasmlist,helpref)
+               else
+                 cg.a_call_reg(exprasmlist,right.location.register);
+{               cg.a_call_loc(exprasmlist,right.location);}
+            {$ifndef newra}
+               location_release(exprasmlist,right.location);
+               location_freetemp(exprasmlist,right.location);
+            {$endif newra}
            end;
            end;
 
 
          { Need to remove the parameters from the stack? }
          { Need to remove the parameters from the stack? }
@@ -811,6 +914,26 @@ implementation
          testregisters32;
          testregisters32;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
 
 
+       {$ifdef newra}
+         regs_to_free:=regs_to_alloc;
+         exclude(regs_to_alloc,RS_STACK_POINTER_REG);
+         if (not is_void(resulttype.def)) and
+            (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
+           begin
+             exclude(regs_to_free,RS_FUNCTION_RESULT_REG);
+          {$ifndef cpu64bit}
+             if resulttype.def.size>sizeof(aword) then
+               exclude(regs_to_free,RS_FUNCTION_RESULT64_HIGH_REG);
+          {$endif cpu64bit}
+           end;
+         r.enum:=R_INTREGISTER;
+         for i:=first_supreg to last_supreg do
+           if i in regs_to_free then
+             begin
+               r.number:=i shl 8 or R_SUBWHOLE;
+               rg.ungetregisterint(exprasmlist,r);
+             end;
+       {$endif}
          { handle function results }
          { handle function results }
          if (not is_void(resulttype.def)) then
          if (not is_void(resulttype.def)) then
            handle_return_value
            handle_return_value
@@ -827,7 +950,9 @@ implementation
 
 
          { restore registers }
          { restore registers }
          rg.restoreusedotherregisters(exprasmlist,pushedother);
          rg.restoreusedotherregisters(exprasmlist,pushedother);
+       {$ifndef newra}
          rg.restoreusedintregisters(exprasmlist,pushedint);
          rg.restoreusedintregisters(exprasmlist,pushedint);
+       {$endif}
 
 
          { release temps of paras }
          { release temps of paras }
          release_para_temps;
          release_para_temps;
@@ -866,7 +991,9 @@ implementation
          regs_to_push_other : tregisterset;
          regs_to_push_other : tregisterset;
          unusedstate: pointer;
          unusedstate: pointer;
          pushedother : tpushedsavedother;
          pushedother : tpushedsavedother;
+      {$ifndef newra}
          pushedint : tpushedsavedint;
          pushedint : tpushedsavedint;
+      {$endif}
          oldpushedparasize : longint;
          oldpushedparasize : longint;
          { adress returned from an I/O-error }
          { adress returned from an I/O-error }
          iolabel : tasmlabel;
          iolabel : tasmlabel;
@@ -1045,7 +1172,9 @@ implementation
 {$endif cpu64bit}
 {$endif cpu64bit}
                    include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
                    include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
           end;
           end;
+      {$ifndef newra}
          rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
          rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
+      {$endif}
          rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
          rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
 
 
 {$ifdef i386}
 {$ifdef i386}
@@ -1087,7 +1216,9 @@ implementation
            end;
            end;
          aktcallnode:=oldaktcallnode;
          aktcallnode:=oldaktcallnode;
 
 
+      {$ifndef newra}
          rg.saveintregvars(exprasmlist,regs_to_push_int);
          rg.saveintregvars(exprasmlist,regs_to_push_int);
+      {$endif}
          rg.saveotherregvars(exprasmlist,regs_to_push_other);
          rg.saveotherregvars(exprasmlist,regs_to_push_other);
 
 
          { takes care of local data initialization }
          { takes care of local data initialization }
@@ -1164,7 +1295,9 @@ implementation
 
 
          { restore registers }
          { restore registers }
          rg.restoreusedotherregisters(exprasmlist,pushedother);
          rg.restoreusedotherregisters(exprasmlist,pushedother);
+      {$ifndef newra}
          rg.restoreusedintregisters(exprasmlist,pushedint);
          rg.restoreusedintregisters(exprasmlist,pushedint);
+      {$endif}
 
 
          { release temps of paras }
          { release temps of paras }
          release_para_temps;
          release_para_temps;
@@ -1242,7 +1375,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.81  2003-06-01 21:38:06  peter
+  Revision 1.82  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.81  2003/06/01 21:38:06  peter
     * getregisterfpu size parameter added
     * getregisterfpu size parameter added
     * op_const_reg size parameter added
     * op_const_reg size parameter added
     * sparc updates
     * sparc updates

+ 20 - 4
compiler/ncgld.pas

@@ -68,7 +68,9 @@ implementation
         i : longint;
         i : longint;
         href : treference;
         href : treference;
         newsize : tcgsize;
         newsize : tcgsize;
+      {$ifndef newra}
         pushed : tpushedsavedint;
         pushed : tpushedsavedint;
+      {$endif}
         dorelocatelab,
         dorelocatelab,
         norelocatelab : tasmlabel;
         norelocatelab : tasmlabel;
       begin
       begin
@@ -143,19 +145,30 @@ implementation
                        cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
                        cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
                        cg.a_jmp_always(exprasmlist,norelocatelab);
                        cg.a_jmp_always(exprasmlist,norelocatelab);
                        cg.a_label(exprasmlist,dorelocatelab);
                        cg.a_label(exprasmlist,dorelocatelab);
-                       if hregister.enum<>R_INTREGISTER then
-                         internalerror(200301171);
                        { don't save the allocated register else the result will be destroyed later }
                        { don't save the allocated register else the result will be destroyed later }
+                    {$ifndef newra}
                        rg.saveusedintregisters(exprasmlist,pushed,[RS_FUNCTION_RESULT_REG]-[hregister.number shr 8]);
                        rg.saveusedintregisters(exprasmlist,pushed,[RS_FUNCTION_RESULT_REG]-[hregister.number shr 8]);
+                    {$endif}
                        reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),0);
                        reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),0);
                        cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
                        cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
+                    {$ifdef newra}
+                       rg.ungetregisterint(exprasmlist,hregister);
+                       r:=rg.getexplicitregisterint(exprasmlist,NR_EAX);
+                    {$endif}
                        { the called procedure isn't allowed to change }
                        { the called procedure isn't allowed to change }
                        { any register except EAX                    }
                        { any register except EAX                    }
                        cg.a_call_reg(exprasmlist,hregister);
                        cg.a_call_reg(exprasmlist,hregister);
+                    {$ifdef newra}
+                       rg.ungetregisterint(exprasmlist,r);
+                       hregister:=rg.getregisterint(exprasmlist,OS_ADDR);
+                    {$else}
                        r.enum:=R_INTREGISTER;
                        r.enum:=R_INTREGISTER;
                        r.number:=NR_FUNCTION_RESULT_REG;
                        r.number:=NR_FUNCTION_RESULT_REG;
+                    {$endif}
                        cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,r,hregister);
                        cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,r,hregister);
+                    {$ifndef newra}
                        rg.restoreusedintregisters(exprasmlist,pushed);
                        rg.restoreusedintregisters(exprasmlist,pushed);
+                    {$endif}
                        cg.a_label(exprasmlist,norelocatelab);
                        cg.a_label(exprasmlist,norelocatelab);
                        location.reference.base:=hregister;
                        location.reference.base:=hregister;
                     end
                     end
@@ -539,7 +552,7 @@ implementation
                         cgsize:=def_cgsize(left.resulttype.def);
                         cgsize:=def_cgsize(left.resulttype.def);
                         if cgsize in [OS_64,OS_S64] then
                         if cgsize in [OS_64,OS_S64] then
                          cg64.a_load64_ref_reg(exprasmlist,
                          cg64.a_load64_ref_reg(exprasmlist,
-                             right.location.reference,left.location.register64)
+                             right.location.reference,left.location.register64{$ifdef newra},false{$endif})
                         else
                         else
                          cg.a_load_ref_reg(exprasmlist,cgsize,
                          cg.a_load_ref_reg(exprasmlist,cgsize,
                              right.location.reference,left.location.register);
                              right.location.reference,left.location.register);
@@ -922,7 +935,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.64  2003-05-30 23:57:08  peter
+  Revision 1.65  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.64  2003/05/30 23:57:08  peter
     * more sparc cleanup
     * more sparc cleanup
     * accumulator removed, splitted in function_return_reg (called) and
     * accumulator removed, splitted in function_return_reg (called) and
       function_result_reg (caller)
       function_result_reg (caller)

+ 118 - 2
compiler/ncgmem.pas

@@ -455,7 +455,10 @@ implementation
          poslabel,
          poslabel,
          neglabel : tasmlabel;
          neglabel : tasmlabel;
          hreg : tregister;
          hreg : tregister;
+         i:Tsuperregister;
+      {$ifndef newra}
          pushed : tpushedsavedint;
          pushed : tpushedsavedint;
+      {$endif}
        begin
        begin
          if is_open_array(left.resulttype.def) or
          if is_open_array(left.resulttype.def) or
             is_array_of_const(left.resulttype.def) then
             is_array_of_const(left.resulttype.def) then
@@ -506,12 +509,33 @@ implementation
          else
          else
           if is_dynamic_array(left.resulttype.def) then
           if is_dynamic_array(left.resulttype.def) then
             begin
             begin
+            {$ifndef newra}
                rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
                rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
+            {$endif}
                cg.a_param_loc(exprasmlist,right.location,paramanager.getintparaloc(2));
                cg.a_param_loc(exprasmlist,right.location,paramanager.getintparaloc(2));
                cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(1));
                cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(1));
+            {$ifdef newra}
+               hreg.enum:=R_INTREGISTER;
+               for i:=first_supreg to last_supreg do
+                 if i<>RS_FRAME_POINTER_REG then
+                   begin
+                     hreg.number:=i shl 8 or R_SUBWHOLE;
+                     rg.getexplicitregisterint(exprasmlist,hreg.number);
+                   end;
+            {$else}
                rg.saveintregvars(exprasmlist,all_intregisters);
                rg.saveintregvars(exprasmlist,all_intregisters);
+            {$endif}
                cg.a_call_name(exprasmlist,'FPC_DYNARRAY_RANGECHECK');
                cg.a_call_name(exprasmlist,'FPC_DYNARRAY_RANGECHECK');
+            {$ifdef newra}
+               for i:=first_supreg to last_supreg do
+                 if i<>RS_FRAME_POINTER_REG then
+                   begin
+                     hreg.number:=i shl 8 or R_SUBWHOLE;
+                     rg.ungetregisterint(exprasmlist,hreg);
+                   end;
+            {$else}
                rg.restoreusedintregisters(exprasmlist,pushed);
                rg.restoreusedintregisters(exprasmlist,pushed);
+            {$endif}
             end
             end
          else
          else
            cg.g_rangecheck(exprasmlist,right,left.resulttype.def);
            cg.g_rangecheck(exprasmlist,right,left.resulttype.def);
@@ -524,7 +548,12 @@ implementation
          extraoffset : longint;
          extraoffset : longint;
          t : tnode;
          t : tnode;
          href : treference;
          href : treference;
+      {$ifdef newra}
+         hreg:Tregister;
+         i:Tsuperregister;
+      {$else}
          pushed : tpushedsavedint;
          pushed : tpushedsavedint;
+      {$endif}
          isjump  : boolean;
          isjump  : boolean;
          otl,ofl : tasmlabel;
          otl,ofl : tasmlabel;
          newsize : tcgsize;
          newsize : tcgsize;
@@ -546,11 +575,32 @@ implementation
                 begin
                 begin
                    if left.location.loc<>LOC_REFERENCE then
                    if left.location.loc<>LOC_REFERENCE then
                      internalerror(200304236);
                      internalerror(200304236);
+                {$ifndef newra}
                    rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
                    rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
+                {$endif}
                    cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(1));
                    cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(1));
+                {$ifdef newra}
+                   hreg.enum:=R_INTREGISTER;
+                   for i:=first_supreg to last_supreg do
+                     if i<>RS_FRAME_POINTER_REG then
+                       begin
+                         hreg.number:=i shl 8 or R_SUBWHOLE;
+                         rg.getexplicitregisterint(exprasmlist,hreg.number);
+                       end;
+                {$else}
                    rg.saveintregvars(exprasmlist,all_intregisters);
                    rg.saveintregvars(exprasmlist,all_intregisters);
+                {$endif}
                    cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_UNIQUE');
                    cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_UNIQUE');
+                {$ifdef newra}
+                   for i:=first_supreg to last_supreg do
+                     if i<>RS_FRAME_POINTER_REG then
+                       begin
+                         hreg.number:=i shl 8 or R_SUBWHOLE;
+                         rg.ungetregisterint(exprasmlist,hreg);
+                       end;
+                {$else}
                    rg.restoreusedintregisters(exprasmlist,pushed);
                    rg.restoreusedintregisters(exprasmlist,pushed);
+                {$endif}
                 end;
                 end;
 
 
               case left.location.loc of
               case left.location.loc of
@@ -572,11 +622,32 @@ implementation
                 we can use the ansistring routine here }
                 we can use the ansistring routine here }
               if (cs_check_range in aktlocalswitches) then
               if (cs_check_range in aktlocalswitches) then
                 begin
                 begin
+                {$ifndef newra}
                    rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
                    rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
+                {$endif}
                    cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
                    cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
+                {$ifdef newra}
+                   hreg.enum:=R_INTREGISTER;
+                   for i:=first_supreg to last_supreg do
+                     if i<>RS_FRAME_POINTER_REG then
+                       begin
+                         hreg.number:=i shl 8 or R_SUBWHOLE;
+                         rg.getexplicitregisterint(exprasmlist,hreg.number);
+                       end;
+                {$else}
                    rg.saveintregvars(exprasmlist,all_intregisters);
                    rg.saveintregvars(exprasmlist,all_intregisters);
-                   cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
+                {$endif}
+                   cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
+                {$ifdef newra}
+                   for i:=first_supreg to last_supreg do
+                     if i<>RS_FRAME_POINTER_REG then
+                       begin
+                         hreg.number:=i shl 8 or R_SUBWHOLE;
+                         rg.ungetregisterint(exprasmlist,hreg);
+                       end;
+                {$else}
                    rg.restoreusedintregisters(exprasmlist,pushed);
                    rg.restoreusedintregisters(exprasmlist,pushed);
+                {$endif}
                 end;
                 end;
 
 
               { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
               { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
@@ -649,14 +720,35 @@ implementation
                          st_widestring,
                          st_widestring,
                          st_ansistring:
                          st_ansistring:
                            begin
                            begin
+                            {$ifndef newra}
                               rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
                               rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
+                            {$endif}
                               cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paramanager.getintparaloc(2));
                               cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paramanager.getintparaloc(2));
                               href:=location.reference;
                               href:=location.reference;
                               dec(href.offset,7);
                               dec(href.offset,7);
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
+                            {$ifdef newra}
+                              hreg.enum:=R_INTREGISTER;
+                              for i:=first_supreg to last_supreg do
+                               if i<>RS_FRAME_POINTER_REG then
+                                  begin
+                                    hreg.number:=i shl 8 or R_SUBWHOLE;
+                                    rg.getexplicitregisterint(exprasmlist,hreg.number);
+                                  end;
+                            {$else}
                               rg.saveintregvars(exprasmlist,all_intregisters);
                               rg.saveintregvars(exprasmlist,all_intregisters);
+                            {$endif}
                               cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
                               cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
+                            {$ifdef newra}
+                              for i:=first_supreg to last_supreg do
+                               if i<>RS_FRAME_POINTER_REG then
+                                  begin
+                                    hreg.number:=i shl 8 or R_SUBWHOLE;
+                                    rg.ungetregisterint(exprasmlist,hreg);
+                                  end;
+                            {$else}
                               rg.restoreusedintregisters(exprasmlist,pushed);
                               rg.restoreusedintregisters(exprasmlist,pushed);
+                            {$endif}
                            end;
                            end;
 
 
                          st_shortstring:
                          st_shortstring:
@@ -783,14 +875,35 @@ implementation
                          st_widestring,
                          st_widestring,
                          st_ansistring:
                          st_ansistring:
                            begin
                            begin
+                            {$ifndef newra}
                               rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
                               rg.saveusedintregisters(exprasmlist,pushed,all_intregisters);
+                            {$endif}
                               cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paramanager.getintparaloc(2));
                               cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paramanager.getintparaloc(2));
                               href:=location.reference;
                               href:=location.reference;
                               dec(href.offset,7);
                               dec(href.offset,7);
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
                               cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
+                            {$ifdef newra}
+                              hreg.enum:=R_INTREGISTER;
+                              for i:=first_supreg to last_supreg do
+                               if i<>RS_FRAME_POINTER_REG then
+                                  begin
+                                    hreg.number:=i shl 8 or R_SUBWHOLE;
+                                    rg.getexplicitregisterint(exprasmlist,hreg.number);
+                                  end;
+                            {$else}
                               rg.saveintregvars(exprasmlist,all_intregisters);
                               rg.saveintregvars(exprasmlist,all_intregisters);
+                            {$endif}
                               cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
                               cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
+                            {$ifdef newra}
+                              for i:=first_supreg to last_supreg do
+                               if i<>RS_FRAME_POINTER_REG then
+                                  begin
+                                    hreg.number:=i shl 8 or R_SUBWHOLE;
+                                    rg.ungetregisterint(exprasmlist,hreg);
+                                  end;
+                            {$else}
                               rg.restoreusedintregisters(exprasmlist,pushed);
                               rg.restoreusedintregisters(exprasmlist,pushed);
+                            {$endif}
                            end;
                            end;
                          st_shortstring:
                          st_shortstring:
                            begin
                            begin
@@ -824,7 +937,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.57  2003-06-02 22:35:45  florian
+  Revision 1.58  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.57  2003/06/02 22:35:45  florian
     * better handling of CREGISTER in subscript nodes
     * better handling of CREGISTER in subscript nodes
 
 
   Revision 1.56  2003/06/01 21:38:06  peter
   Revision 1.56  2003/06/01 21:38:06  peter

+ 4 - 2
compiler/ncgopt.pas

@@ -196,14 +196,16 @@ begin
   location_copy(location,left.location);
   location_copy(location,left.location);
 end;
 end;
 
 
-
 begin
 begin
   caddsstringcharoptnode := tcgaddsstringcharoptnode;
   caddsstringcharoptnode := tcgaddsstringcharoptnode;
 end.
 end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.4  2003-06-01 21:38:06  peter
+  Revision 1.5  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.4  2003/06/01 21:38:06  peter
     * getregisterfpu size parameter added
     * getregisterfpu size parameter added
     * op_const_reg size parameter added
     * op_const_reg size parameter added
     * sparc updates
     * sparc updates

+ 110 - 76
compiler/ncgutil.pas

@@ -63,8 +63,9 @@ interface
                               para_offset:longint;alignment : longint;
                               para_offset:longint;alignment : longint;
                               const locpara : tparalocation);
                               const locpara : tparalocation);
 
 
-    procedure genentrycode(list : TAAsmoutput;stackframe:longint;inlined : boolean);
-    procedure genexitcode(list : TAAsmoutput;inlined:boolean);
+    procedure genentrycode(list:TAAsmoutput;inlined:boolean);
+    procedure gen_stackalloc_code(list:Taasmoutput;stackframe:cardinal);
+    procedure genexitcode(list:Taasmoutput;inlined:boolean);
 
 
     procedure geninlineentrycode(list : TAAsmoutput;stackframe:longint);
     procedure geninlineentrycode(list : TAAsmoutput;stackframe:longint);
     procedure geninlineexitcode(list : TAAsmoutput;inlined:boolean);
     procedure geninlineexitcode(list : TAAsmoutput;inlined:boolean);
@@ -382,7 +383,7 @@ implementation
               hreg64.reglo:=hregister;
               hreg64.reglo:=hregister;
               hreg64.reghi:=hregisterhi;
               hreg64.reghi:=hregisterhi;
               { load value in new register }
               { load value in new register }
-              cg64.a_load64_loc_reg(list,l,hreg64);
+              cg64.a_load64_loc_reg(list,l,hreg64{$ifdef newra},false{$endif});
               location_reset(l,LOC_REGISTER,dst_size);
               location_reset(l,LOC_REGISTER,dst_size);
               l.registerlow:=hregister;
               l.registerlow:=hregister;
               l.registerhigh:=hregisterhi;
               l.registerhigh:=hregisterhi;
@@ -430,6 +431,9 @@ implementation
                  hregister:=rg.getregisterint(list,dst_size);
                  hregister:=rg.getregisterint(list,dst_size);
              end;
              end;
            hregister.number:=(hregister.number and not $ff) or cgsize2subreg(dst_size);
            hregister.number:=(hregister.number and not $ff) or cgsize2subreg(dst_size);
+        {$ifdef newra}
+           rg.add_constraints(hregister.number);
+        {$endif}
            { load value in new register }
            { load value in new register }
            case l.loc of
            case l.loc of
              LOC_FLAGS :
              LOC_FLAGS :
@@ -596,6 +600,22 @@ implementation
      end;
      end;
 {$endif cpu64bit}
 {$endif cpu64bit}
 
 
+{$ifdef newra}
+    procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
+
+    var oldloc:Tlocation;
+
+      begin
+        oldloc:=l;
+        location_force(list, l, dst_size, maybeconst);
+        { release previous location before demanding a new register }
+        if (oldloc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+         begin
+           location_freetemp(list,oldloc);
+           location_release(list,oldloc);
+         end;
+      end;
+{$else}
     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);
       begin
       begin
         { release previous location before demanding a new register }
         { release previous location before demanding a new register }
@@ -606,7 +626,7 @@ implementation
          end;
          end;
         location_force(list, l, dst_size, maybeconst)
         location_force(list, l, dst_size, maybeconst)
       end;
       end;
-
+{$endif}
 
 
     procedure location_force_fpureg(list: TAAsmoutput;var l: tlocation;maybeconst:boolean);
     procedure location_force_fpureg(list: TAAsmoutput;var l: tlocation;maybeconst:boolean);
       var
       var
@@ -1286,7 +1306,7 @@ implementation
                     r2.enum:=R_INTREGISTER;
                     r2.enum:=R_INTREGISTER;
                     r2.number:=NR_FUNCTION_RETURN64_HIGH_REG;
                     r2.number:=NR_FUNCTION_RETURN64_HIGH_REG;
                     cg.a_reg_alloc(list,r2);
                     cg.a_reg_alloc(list,r2);
-                    cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2));
+                    cg64.a_load64_ref_reg(list,resloc,joinreg64(r,r2){$ifdef newra},false{$endif});
                   end
                   end
                  else
                  else
 {$endif cpu64bit}
 {$endif cpu64bit}
@@ -1323,7 +1343,11 @@ implementation
                        r2.enum:=R_INTREGISTER;
                        r2.enum:=R_INTREGISTER;
                        r2.number:=NR_FUNCTION_RETURN64_HIGH_REG;
                        r2.number:=NR_FUNCTION_RETURN64_HIGH_REG;
                        cg.a_reg_alloc(list,r2);
                        cg.a_reg_alloc(list,r2);
+<<<<<<< ncgutil.pas
+                       cg64.a_load64_ref_reg(list,href,joinreg64(r,r2){$ifdef newra},false{$endif});
+=======
                        cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2));
                        cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2));
+>>>>>>> 1.117
                      end
                      end
                     else
                     else
 {$endif cpu64bit}
 {$endif cpu64bit}
@@ -1339,17 +1363,13 @@ implementation
       end;
       end;
 
 
 
 
-    procedure genentrycode(list : TAAsmoutput;stackframe:longint;inlined : boolean);
+
+    procedure genentrycode(list:TAAsmoutput;inlined:boolean);
       var
       var
-        hs : string;
         href : treference;
         href : treference;
-        stackalloclist : taasmoutput;
         hp : tparaitem;
         hp : tparaitem;
         rsp : tregister;
         rsp : tregister;
       begin
       begin
-        if not inlined then
-           stackalloclist:=taasmoutput.Create;
-
         { the actual stack allocation code, symbol entry point and
         { the actual stack allocation code, symbol entry point and
           gdb stabs information is generated AFTER the rest of this
           gdb stabs information is generated AFTER the rest of this
           code, since temp. allocation might occur before - carl
           code, since temp. allocation might occur before - carl
@@ -1515,81 +1535,81 @@ implementation
         if inlined then
         if inlined then
           load_regvars(list,nil);
           load_regvars(list,nil);
 
 
-        {************************* Stack allocation **************************}
-        { and symbol entry point as well as debug information                 }
-        { will be inserted in front of the rest of this list.                 }
-        { Insert alignment and assembler names }
-        if not inlined then
-         begin
-           { Align, gprof uses 16 byte granularity }
-           if (cs_profile in aktmoduleswitches) then
-            stackalloclist.concat(Tai_align.Create(16))
-           else
-            stackalloclist.concat(Tai_align.Create(aktalignment.procalign));
+      end;
+
+    procedure gen_stackalloc_code(list:Taasmoutput;stackframe:cardinal);
+
+    var hs:string;
+
+    begin
+      {************************* Stack allocation **************************}
+      { and symbol entry point as well as debug information                 }
+      { will be inserted in front of the rest of this list.                 }
+      { Insert alignment and assembler names }
+      { Align, gprof uses 16 byte granularity }
+      if (cs_profile in aktmoduleswitches) then
+        list.concat(Tai_align.create(16))
+      else
+        list.concat(Tai_align.create(aktalignment.procalign));
 
 
 {$ifdef GDB}
 {$ifdef GDB}
-           if (cs_debuginfo in aktmoduleswitches) then
-            begin
-              if (po_public in current_procdef.procoptions) then
-                tprocsym(current_procdef.procsym).is_global:=true;
-              current_procdef.concatstabto(stackalloclist);
-              tprocsym(current_procdef.procsym).isstabwritten:=true;
-            end;
+      if (cs_debuginfo in aktmoduleswitches) then
+        begin
+          if (po_public in current_procdef.procoptions) then
+            Tprocsym(current_procdef.procsym).is_global:=true;
+          current_procdef.concatstabto(list);
+          Tprocsym(current_procdef.procsym).isstabwritten:=true;
+        end;
 {$endif GDB}
 {$endif GDB}
 
 
-           repeat
-             hs:=current_procdef.aliasnames.getfirst;
-             if hs='' then
-              break;
+      repeat
+        hs:=current_procdef.aliasnames.getfirst;
+        if hs='' then
+          break;
 {$ifdef GDB}
 {$ifdef GDB}
-             if (cs_debuginfo in aktmoduleswitches) and
-                target_info.use_function_relative_addresses then
-              stackalloclist.concat(Tai_stab_function_name.Create(strpnew(hs)));
+        if (cs_debuginfo in aktmoduleswitches) and
+           target_info.use_function_relative_addresses then
+        list.concat(Tai_stab_function_name.create(strpnew(hs)));
 {$endif GDB}
 {$endif GDB}
-             if (cs_profile in aktmoduleswitches) or
-                (po_public in current_procdef.procoptions) then
-              stackalloclist.concat(Tai_symbol.Createname_global(hs,0))
-             else
-              stackalloclist.concat(Tai_symbol.Createname(hs,0));
-           until false;
+        if (cs_profile in aktmoduleswitches) or
+           (po_public in current_procdef.procoptions) then
+          list.concat(Tai_symbol.createname_global(hs,0))
+        else
+          list.concat(Tai_symbol.createname(hs,0));
+      until false;
 
 
-          stackframe:=stackframe+tg.gettempsize;
+      stackframe:=stackframe+tg.gettempsize;
 {$ifndef m68k}
 {$ifndef m68k}
           { give a warning if the limit of local variables is reached }
           { give a warning if the limit of local variables is reached }
-          if stackframe > maxlocalsize then
-            Message(cg_w_localsize_too_big);
+      if stackframe>maxlocalsize then
+        message(cg_w_localsize_too_big);
 {$endif}
 {$endif}
 {$ifndef powerpc}
 {$ifndef powerpc}
-           { at least for the ppc this applies always, so this code isn't usable (FK) }
-           { omit stack frame ? }
-           if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
-            begin
-              CGMessage(cg_d_stackframe_omited);
-              if stackframe<>0 then
-                cg.g_stackpointer_alloc(stackalloclist,stackframe);
-            end
-           else
+      { at least for the ppc this applies always, so this code isn't usable (FK) }
+      { omit stack frame ? }
+      if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
+        begin
+          CGmessage(cg_d_stackframe_omited);
+          if stackframe<>0 then
+            cg.g_stackpointer_alloc(list,stackframe);
+        end
+      else
 {$endif powerpc}
 {$endif powerpc}
-            begin
-              if (po_interrupt in current_procdef.procoptions) then
-                cg.g_interrupt_stackframe_entry(stackalloclist);
+        begin
+          if (po_interrupt in current_procdef.procoptions) then
+            cg.g_interrupt_stackframe_entry(list);
 
 
-              cg.g_stackframe_entry(stackalloclist,stackframe);
+          cg.g_stackframe_entry(list,stackframe);
 
 
-              { never call stack checking before the standard system unit
-                has not been initialized
-              }
-              if (cs_check_stack in aktlocalswitches) and (current_procdef.proctypeoption<>potype_proginit) then
-                cg.g_stackcheck(stackalloclist,stackframe);
-            end;
-            list.insertlist(stackalloclist);
-            stackalloclist.free;
-         end;
-        {************************* End Stack allocation **************************}
-      end;
+          {Never call stack checking before the standard system unit
+           has been initialized.}
+           if (cs_check_stack in aktlocalswitches) and (current_procdef.proctypeoption<>potype_proginit) then
+             cg.g_stackcheck(list,stackframe);
+        end;
+    end;
 
 
+    procedure genexitcode(list : TAAsmoutput;inlined:boolean);
 
 
-   procedure genexitcode(list : TAAsmoutput;inlined:boolean);
       var
       var
 {$ifdef GDB}
 {$ifdef GDB}
         stabsendlabel : tasmlabel;
         stabsendlabel : tasmlabel;
@@ -1601,10 +1621,14 @@ implementation
         srsym : tsym;
         srsym : tsym;
         usesacc,
         usesacc,
         usesacchi,
         usesacchi,
-        usesfpu : boolean;
-        rsp,r  : Tregister;
-        retsize : longint;
+        usesself,usesfpu : boolean;
+        pd : tprocdef;
+        rsp,tmpreg,r  : Tregister;
+        retsize:cardinal;
+        nostackframe:boolean;
       begin
       begin
+{        nostackframe:=current_procinfo.framepointer.number=NR_STACK_POINTER_REG;}
+
         if aktexitlabel.is_used then
         if aktexitlabel.is_used then
           cg.a_label(list,aktexitlabel);
           cg.a_label(list,aktexitlabel);
 
 
@@ -1709,11 +1733,10 @@ implementation
            if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
            if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
             begin
             begin
               if (tg.gettempsize<>0) then
               if (tg.gettempsize<>0) then
-                cg.a_op_const_reg(list,OP_ADD,OS_ADDR,tg.gettempsize,current_procinfo.framepointer);
+                cg.a_op_const_reg(list,OP_ADD,OS_32,tg.gettempsize,current_procinfo.framepointer);
             end
             end
            else
            else
             cg.g_restore_frame_pointer(list);
             cg.g_restore_frame_pointer(list);
-             if not (po_assembler in current_procdef.procoptions) then
          end;
          end;
 {$endif}
 {$endif}
 
 
@@ -1848,7 +1871,11 @@ implementation
                   begin
                   begin
                     r:=rg.getregisterint(list,OS_INT);
                     r:=rg.getregisterint(list,OS_INT);
                     r2:=rg.getregisterint(list,OS_INT);
                     r2:=rg.getregisterint(list,OS_INT);
+<<<<<<< ncgutil.pas
+                    cg64.a_load64_ref_reg(list,href,joinreg64(r,r2){$ifdef newra},false{$endif});
+=======
                     cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2));
                     cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2));
+>>>>>>> 1.117
                   end
                   end
                  else
                  else
 {$endif cpu64bit}
 {$endif cpu64bit}
@@ -1877,7 +1904,11 @@ implementation
                      begin
                      begin
                        r:=rg.getregisterint(list,OS_INT);
                        r:=rg.getregisterint(list,OS_INT);
                        r2:=rg.getregisterint(list,OS_INT);
                        r2:=rg.getregisterint(list,OS_INT);
+<<<<<<< ncgutil.pas
+                       cg64.a_load64_ref_reg(list,href,joinreg64(r,r2){$ifdef newra},false{$endif});
+=======
                        cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2));
                        cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2));
+>>>>>>> 1.117
                      end
                      end
                     else
                     else
 {$endif cpu64bit}
 {$endif cpu64bit}
@@ -1952,7 +1983,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.117  2003-06-02 21:42:05  jonas
+  Revision 1.118  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.117  2003/06/02 21:42:05  jonas
     * function results can now also be regvars
     * function results can now also be regvars
     - removed tprocinfo.return_offset, never use it again since it's invalid
     - removed tprocinfo.return_offset, never use it again since it's invalid
       if the result is a regvar
       if the result is a regvar

+ 13 - 1
compiler/pass_2.pas

@@ -287,6 +287,15 @@ implementation
 {$ifndef i386}
 {$ifndef i386}
               cleanup_regvars(current_procinfo.aktexitcode);
               cleanup_regvars(current_procinfo.aktexitcode);
 {$endif i386}
 {$endif i386}
+{$ifdef newra}
+              if current_procinfo.framepointer.number=NR_EBP then
+                begin
+                  {Make sure the register allocator won't allocate registers
+                   into ebp.}
+                  include(rg.usedintinproc,RS_EBP);
+                  exclude(rg.unusedregsint,RS_EBP);
+                end;
+{$endif}
 
 
               do_secondpass(p);
               do_secondpass(p);
 
 
@@ -300,7 +309,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.53  2003-05-26 21:17:17  peter
+  Revision 1.54  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.53  2003/05/26 21:17:17  peter
     * procinlinenode removed
     * procinlinenode removed
     * aktexit2label removed, fast exit removed
     * aktexit2label removed, fast exit removed
     + tcallnode.inlined_pass_2 added
     + tcallnode.inlined_pass_2 added

+ 7 - 3
compiler/pmodules.pas

@@ -793,7 +793,8 @@ implementation
         { generate a dummy function }
         { generate a dummy function }
         objectlibrary.getlabel(aktexitlabel);
         objectlibrary.getlabel(aktexitlabel);
         include(current_procinfo.flags,pi_do_call);
         include(current_procinfo.flags,pi_do_call);
-        genentrycode(list,0,false);
+        gen_stackalloc_code(list,0);
+        genentrycode(list,false);
         genexitcode(list,false);
         genexitcode(list,false);
         list.convert_registers;
         list.convert_registers;
         release_main_proc(pd);
         release_main_proc(pd);
@@ -867,7 +868,7 @@ implementation
          { handle the global switches }
          { handle the global switches }
          setupglobalswitches;
          setupglobalswitches;
 
 
-         Message1(unit_u_loading_interface_units,current_module.modulename^);
+         message1(unit_u_loading_interface_units,current_module.modulename^);
 
 
          { update status }
          { update status }
          status.currentmodule:=current_module.realmodulename^;
          status.currentmodule:=current_module.realmodulename^;
@@ -1474,7 +1475,10 @@ So, all parameters are passerd into registers in sparc architecture.}
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.109  2003-05-26 21:17:17  peter
+  Revision 1.110  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.109  2003/05/26 21:17:17  peter
     * procinlinenode removed
     * procinlinenode removed
     * aktexit2label removed, fast exit removed
     * aktexit2label removed, fast exit removed
     + tcallnode.inlined_pass_2 added
     + tcallnode.inlined_pass_2 added

+ 36 - 13
compiler/psub.pas

@@ -554,6 +554,8 @@ implementation
         oldexitlabel : tasmlabel;
         oldexitlabel : tasmlabel;
         oldaktmaxfpuregisters : longint;
         oldaktmaxfpuregisters : longint;
         oldfilepos : tfileposinfo;
         oldfilepos : tfileposinfo;
+        stackalloccode : Taasmoutput;
+
       begin
       begin
         { the initialization procedure can be empty, then we
         { the initialization procedure can be empty, then we
           don't need to generate anything. When it was an empty
           don't need to generate anything. When it was an empty
@@ -584,7 +586,9 @@ implementation
         rg.usedinproc:=[];
         rg.usedinproc:=[];
         rg.usedintinproc:=[];
         rg.usedintinproc:=[];
         rg.usedbyproc:=[];
         rg.usedbyproc:=[];
+      {$ifndef newra}
         rg.usedintbyproc:=[];
         rg.usedintbyproc:=[];
+      {$endif}
 
 
         { set the start offset to the start of the temp area in the stack }
         { set the start offset to the start of the temp area in the stack }
         tg.setfirsttemp(current_procinfo.firsttemp_offset);
         tg.setfirsttemp(current_procinfo.firsttemp_offset);
@@ -594,7 +598,7 @@ implementation
         { first generate entry code with the correct position and switches }
         { first generate entry code with the correct position and switches }
         aktfilepos:=current_procinfo.entrypos;
         aktfilepos:=current_procinfo.entrypos;
         aktlocalswitches:=current_procinfo.entryswitches;
         aktlocalswitches:=current_procinfo.entryswitches;
-        genentrycode(current_procinfo.aktentrycode,0,false);
+        genentrycode(current_procinfo.aktentrycode,false);
 
 
         { now generate exit code with the correct position and switches }
         { now generate exit code with the correct position and switches }
         aktfilepos:=current_procinfo.exitpos;
         aktfilepos:=current_procinfo.exitpos;
@@ -602,8 +606,8 @@ implementation
         genexitcode(current_procinfo.aktexitcode,false);
         genexitcode(current_procinfo.aktexitcode,false);
 
 
         { now all the registers used are known }
         { now all the registers used are known }
-        current_procdef.usedintregisters:=rg.usedintinproc;
-        current_procdef.usedotherregisters:=rg.usedinproc;
+{        current_procdef.usedintregisters:=rg.usedintinproc;
+        current_procdef.usedotherregisters:=rg.usedinproc;}
         current_procinfo.aktproccode.insertlist(current_procinfo.aktentrycode);
         current_procinfo.aktproccode.insertlist(current_procinfo.aktentrycode);
         current_procinfo.aktproccode.concatlist(current_procinfo.aktexitcode);
         current_procinfo.aktproccode.concatlist(current_procinfo.aktexitcode);
 {$ifdef newra}
 {$ifdef newra}
@@ -617,13 +621,7 @@ implementation
               rg.prepare_colouring;
               rg.prepare_colouring;
               rg.colour_registers;
               rg.colour_registers;
               rg.epilogue_colouring;
               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='';
+            until (rg.spillednodes='') or not rg.spill_registers(current_procinfo.aktproccode,rg.spillednodes);
             current_procinfo.aktproccode.translate_registers(rg.colour);
             current_procinfo.aktproccode.translate_registers(rg.colour);
             current_procinfo.aktproccode.convert_registers;
             current_procinfo.aktproccode.convert_registers;
 {$else newra}
 {$else newra}
@@ -637,6 +635,21 @@ implementation
 {$endif newra}
 {$endif newra}
           end;
           end;
 
 
+        stackalloccode:=Taasmoutput.create;
+        gen_stackalloc_code(stackalloccode,0);
+        stackalloccode.convert_registers;
+        current_procinfo.aktproccode.insertlist(stackalloccode);
+        stackalloccode.destroy;
+
+        { now all the registers used are known }
+        { Remove all imaginary registers from the used list.}
+{$ifdef newra}
+        current_procdef.usedintregisters:=rg.usedintinproc*ALL_INTREGISTERS-rg.savedbyproc;
+{$else}
+        current_procdef.usedintregisters:=rg.usedintinproc;
+{$endif}
+        current_procdef.usedotherregisters:=rg.usedinproc;
+
         { save local data (casetable) also in the same file }
         { save local data (casetable) also in the same file }
         if assigned(current_procinfo.aktlocaldata) and
         if assigned(current_procinfo.aktlocaldata) and
            (not current_procinfo.aktlocaldata.empty) then
            (not current_procinfo.aktlocaldata.empty) then
@@ -648,8 +661,8 @@ implementation
 
 
         { add the procedure to the codesegment }
         { add the procedure to the codesegment }
         if (cs_create_smart in aktmoduleswitches) then
         if (cs_create_smart in aktmoduleswitches) then
-         codeSegment.concat(Tai_cut.Create);
-        codeSegment.concatlist(current_procinfo.aktproccode);
+         codesegment.concat(Tai_cut.Create);
+        codesegment.concatlist(current_procinfo.aktproccode);
 
 
         { all registers can be used again }
         { all registers can be used again }
         rg.resetusableregisters;
         rg.resetusableregisters;
@@ -751,6 +764,7 @@ implementation
     procedure tcgprocinfo.parse_body;
     procedure tcgprocinfo.parse_body;
       var
       var
          oldprocdef : tprocdef;
          oldprocdef : tprocdef;
+         stackalloccode : Taasmoutput;
          oldprocinfo : tprocinfo;
          oldprocinfo : tprocinfo;
       begin
       begin
          oldprocdef:=current_procdef;
          oldprocdef:=current_procdef;
@@ -785,6 +799,12 @@ implementation
          { constant symbols are inserted in this symboltable }
          { constant symbols are inserted in this symboltable }
          constsymtable:=symtablestack;
          constsymtable:=symtablestack;
 
 
+         { reset the temporary memory }
+         rg.cleartempgen;
+         rg.usedintinproc:=[];
+         rg.usedinproc:=[];
+         rg.usedbyproc:=[];
+
          { save entry info }
          { save entry info }
          entrypos:=aktfilepos;
          entrypos:=aktfilepos;
          entryswitches:=aktlocalswitches;
          entryswitches:=aktlocalswitches;
@@ -1213,7 +1233,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.121  2003-05-31 20:23:39  jonas
+  Revision 1.122  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.121  2003/05/31 20:23:39  jonas
     * added pi_do_call if a procedure has a value shortstring parameter
     * added pi_do_call if a procedure has a value shortstring parameter
       (it's copied to the local stackframe with a helper)
       (it's copied to the local stackframe with a helper)
 
 

+ 6 - 1
compiler/regvars.pas

@@ -150,6 +150,7 @@ implementation
       r : Tregister;
       r : Tregister;
       siz : tcgsize;
       siz : tcgsize;
     begin
     begin
+{$ifndef newra}
       { max. optimizations     }
       { max. optimizations     }
       { only if no asm is used }
       { only if no asm is used }
       { and no try statement   }
       { and no try statement   }
@@ -298,6 +299,7 @@ implementation
                   end;
                   end;
               end;
               end;
         end;
         end;
+{$endif}
      end;
      end;
 
 
 
 
@@ -606,7 +608,10 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.53  2003-05-31 20:33:57  jonas
+  Revision 1.54  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.53  2003/05/31 20:33:57  jonas
     * temp fix/hack for nested procedures (disable regvars in all procedures
     * temp fix/hack for nested procedures (disable regvars in all procedures
       that have nested procedures)
       that have nested procedures)
     * leave register parameters in their own register (instead of storing
     * leave register parameters in their own register (instead of storing

+ 432 - 26
compiler/rgobj.pas

@@ -86,6 +86,10 @@ unit rgobj;
 {$endif}
 {$endif}
       ;
       ;
 
 
+
+    const ALL_REGISTERS=[firstreg..lastreg];
+          ALL_INTREGISTERS=[first_supreg..last_supreg]-[RS_STACK_POINTER_REG];
+
     type
     type
 
 
 
 
@@ -101,7 +105,9 @@ unit rgobj;
        end;
        end;
 
 
        tpushedsavedother = array[firstreg..lastreg] of tpushedsavedloc;
        tpushedsavedother = array[firstreg..lastreg] of tpushedsavedloc;
+{$ifndef newra}
        Tpushedsavedint = array[first_supreg..last_supreg] of Tpushedsavedloc;
        Tpushedsavedint = array[first_supreg..last_supreg] of Tpushedsavedloc;
+{$endif}
 
 
       Tinterferencebitmap=array[Tsuperregister] of set of Tsuperregister;
       Tinterferencebitmap=array[Tsuperregister] of set of Tsuperregister;
       Tinterferenceadjlist=array[Tsuperregister] of Pstring;
       Tinterferenceadjlist=array[Tsuperregister] of Pstring;
@@ -128,6 +134,9 @@ unit rgobj;
                 ms_worklist_moves,ms_active_moves);
                 ms_worklist_moves,ms_active_moves);
       Tmoveins=class(Tlinkedlistitem)
       Tmoveins=class(Tlinkedlistitem)
         moveset:Tmoveset;
         moveset:Tmoveset;
+      { $ifdef ra_debug}
+        x,y:Tsuperregister;
+      { $endif}
         instruction:Taicpu;
         instruction:Taicpu;
       end;
       end;
 
 
@@ -168,13 +177,19 @@ unit rgobj;
           }
           }
           usedbyproc,
           usedbyproc,
           usedinproc : tregisterset;
           usedinproc : tregisterset;
+{$ifdef newra}
+          savedbyproc,
+{$else}
           usedintbyproc,
           usedintbyproc,
+{$endif}
           usedaddrbyproc,
           usedaddrbyproc,
           usedintinproc,
           usedintinproc,
           usedaddrinproc:Tsupregset;
           usedaddrinproc:Tsupregset;
 
 
           reg_pushes_other : regvarother_longintarray;
           reg_pushes_other : regvarother_longintarray;
+{$ifndef newra}
           reg_pushes_int : regvarint_longintarray;
           reg_pushes_int : regvarint_longintarray;
+{$endif}
           is_reg_var_other : regvarother_booleanarray;
           is_reg_var_other : regvarother_booleanarray;
           is_reg_var_int:Tsupregset;
           is_reg_var_int:Tsupregset;
           regvar_loaded_other: regvarother_booleanarray;
           regvar_loaded_other: regvarother_booleanarray;
@@ -194,7 +209,20 @@ unit rgobj;
              An internalerror will be generated if there
              An internalerror will be generated if there
              is no more free registers which can be allocated
              is no more free registers which can be allocated
           }
           }
-          function getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;virtual;
+          function getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;{$ifndef newra}virtual;{$endif}
+{$ifdef newra}
+          procedure add_constraints(reg:Tnewregister);virtual;
+
+          {# Allocate an ABT register
+
+             An internalerror will be generated if there
+             is no more free registers which can be allocated
+
+             An explanantion of abt registers can be found near the implementation.
+          }
+          function getabtregisterint(list:Taasmoutput;size:Tcgsize):Tregister;
+{$endif}
+
           {# Free a general purpose register
           {# Free a general purpose register
 
 
              @param(r register to free)
              @param(r register to free)
@@ -279,7 +307,9 @@ unit rgobj;
 
 
 
 
           {# saves register variables (restoring happens automatically) }
           {# saves register variables (restoring happens automatically) }
+{$ifndef newra}
           procedure saveintregvars(list:Taasmoutput;const s:Tsupregset);
           procedure saveintregvars(list:Taasmoutput;const s:Tsupregset);
+{$endif}
           procedure saveotherregvars(list:Taasmoutput;const s:Tregisterset);
           procedure saveotherregvars(list:Taasmoutput;const s:Tregisterset);
 
 
           {# Saves in temporary references (allocated via the temp. allocator)
           {# Saves in temporary references (allocated via the temp. allocator)
@@ -293,9 +323,11 @@ unit rgobj;
              @param(saved)  Array of saved register information
              @param(saved)  Array of saved register information
              @param(s)      Registers which might require saving
              @param(s)      Registers which might require saving
           }
           }
+{$ifndef newra}
           procedure saveusedintregisters(list:Taasmoutput;
           procedure saveusedintregisters(list:Taasmoutput;
                                          var saved:Tpushedsavedint;
                                          var saved:Tpushedsavedint;
                                          const s:Tsupregset);virtual;
                                          const s:Tsupregset);virtual;
+{$endif}
           procedure saveusedotherregisters(list:Taasmoutput;
           procedure saveusedotherregisters(list:Taasmoutput;
                                            var saved:Tpushedsavedother;
                                            var saved:Tpushedsavedother;
                                            const s:Tregisterset);virtual;
                                            const s:Tregisterset);virtual;
@@ -305,13 +337,17 @@ unit rgobj;
              On processors which have instructions which manipulate the stack,
              On processors which have instructions which manipulate the stack,
              this routine should be overriden for performance reasons.
              this routine should be overriden for performance reasons.
           }
           }
+{$ifndef newra}
           procedure restoreusedintregisters(list:Taasmoutput;
           procedure restoreusedintregisters(list:Taasmoutput;
                                             const saved:Tpushedsavedint);virtual;
                                             const saved:Tpushedsavedint);virtual;
+{$endif}
           procedure restoreusedotherregisters(list:Taasmoutput;
           procedure restoreusedotherregisters(list:Taasmoutput;
                                               const saved:Tpushedsavedother);virtual;
                                               const saved:Tpushedsavedother);virtual;
 
 
           { used when deciding which registers to use for regvars }
           { used when deciding which registers to use for regvars }
+{$ifndef newra}
           procedure incrementintregisterpushed(const s:Tsupregset);
           procedure incrementintregisterpushed(const s:Tsupregset);
+{$endif}
           procedure incrementotherregisterpushed(const s: tregisterset);
           procedure incrementotherregisterpushed(const s: tregisterset);
           procedure clearregistercount;
           procedure clearregistercount;
           procedure resetusableregisters;virtual;
           procedure resetusableregisters;virtual;
@@ -332,6 +368,7 @@ unit rgobj;
           procedure prepare_colouring;
           procedure prepare_colouring;
           procedure epilogue_colouring;
           procedure epilogue_colouring;
           procedure colour_registers;
           procedure colour_registers;
+          function spill_registers(list:Taasmoutput;const regs_to_spill:string):boolean;
 {$endif newra}
 {$endif newra}
        protected
        protected
           cpu_registers:byte;
           cpu_registers:byte;
@@ -342,6 +379,7 @@ unit rgobj;
           simplifyworklist,freezeworklist,spillworklist:string;
           simplifyworklist,freezeworklist,spillworklist:string;
           coalescednodes:string;
           coalescednodes:string;
           selectstack:string;
           selectstack:string;
+          abtlist:string;
           movelist:array[Tsuperregister] of Pmovelist;
           movelist:array[Tsuperregister] of Pmovelist;
           worklist_moves,active_moves,frozen_moves,
           worklist_moves,active_moves,frozen_moves,
           coalesced_moves,constrained_moves:Tlinkedlist;
           coalesced_moves,constrained_moves:Tlinkedlist;
@@ -352,7 +390,7 @@ unit rgobj;
               var unusedregs:Tregisterset;var countunusedregs:byte): tregister;
               var unusedregs:Tregisterset;var countunusedregs:byte): tregister;
           function getregistergenint(list:Taasmoutput;subreg:Tsubregister;
           function getregistergenint(list:Taasmoutput;subreg:Tsubregister;
                                      const lowreg,highreg:Tsuperregister;
                                      const lowreg,highreg:Tsuperregister;
-                                     var fusedinproc,fusedbyproc,unusedregs:Tsupregset
+                                     var fusedinproc,{$ifndef newra}fusedbyproc,{$endif}unusedregs:Tsupregset
                                      {$ifndef newra};var countunusedregs:byte{$endif}):Tregister;
                                      {$ifndef newra};var countunusedregs:byte{$endif}):Tregister;
           procedure ungetregistergen(list: taasmoutput; const r: tregister;
           procedure ungetregistergen(list: taasmoutput; const r: tregister;
               const usableregs:tregisterset;var unusedregs: tregisterset; var countunusedregs: byte);
               const usableregs:tregisterset;var unusedregs: tregisterset; var countunusedregs: byte);
@@ -360,6 +398,10 @@ unit rgobj;
                                         const usableregs:Tsupregset;
                                         const usableregs:Tsupregset;
                                         var unusedregs:Tsupregset
                                         var unusedregs:Tsupregset
                                         {$ifndef newra};var countunusedregs:byte{$endif});
                                         {$ifndef newra};var countunusedregs:byte{$endif});
+{$ifdef newra}
+          procedure getregisterintinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
+          procedure ungetregisterintinline(list:Taasmoutput;position:Tai;const r:Tregister);
+{$endif}
 {$ifdef TEMPREGDEBUG}
 {$ifdef TEMPREGDEBUG}
          reg_user   : regvar_ptreearray;
          reg_user   : regvar_ptreearray;
          reg_releaser : regvar_ptreearray;
          reg_releaser : regvar_ptreearray;
@@ -388,6 +430,7 @@ unit rgobj;
          procedure freeze;
          procedure freeze;
          procedure select_spill;
          procedure select_spill;
          procedure assign_colours;
          procedure assign_colours;
+         procedure clear_interferences(u:Tsuperregister);
 {$endif}
 {$endif}
        end;
        end;
 
 
@@ -495,6 +538,7 @@ unit rgobj;
        fillchar(degree,sizeof(degree),0);
        fillchar(degree,sizeof(degree),0);
        fillchar(movelist,sizeof(movelist),0);
        fillchar(movelist,sizeof(movelist),0);
        worklist_moves:=Tlinkedlist.create;
        worklist_moves:=Tlinkedlist.create;
+       abtlist:='';
 {$endif}
 {$endif}
      end;
      end;
 
 
@@ -525,7 +569,7 @@ unit rgobj;
     function Trgobj.getregistergenint(list:Taasmoutput;
     function Trgobj.getregistergenint(list:Taasmoutput;
                                       subreg:Tsubregister;
                                       subreg:Tsubregister;
                                       const lowreg,highreg:Tsuperregister;
                                       const lowreg,highreg:Tsuperregister;
-                                      var fusedinproc,fusedbyproc,unusedregs:Tsupregset
+                                      var fusedinproc,{$ifndef newra}fusedbyproc,{$endif}unusedregs:Tsupregset
                                       {$ifndef newra};var countunusedregs:byte{$endif}):Tregister;
                                       {$ifndef newra};var countunusedregs:byte{$endif}):Tregister;
 
 
 {$ifdef powerpc}
 {$ifdef powerpc}
@@ -551,12 +595,12 @@ unit rgobj;
           i:=lowreg
           i:=lowreg
         else
         else
           inc(i);
           inc(i);
-        if i in unusedregs then
+        if (i in unusedregs) {$ifdef newra} and (pos(char(i),abtlist)=0) {$endif} then
           begin
           begin
             exclude(unusedregs,i);
             exclude(unusedregs,i);
             include(fusedinproc,i);
             include(fusedinproc,i);
-            include(fusedbyproc,i);
           {$ifndef newra}
           {$ifndef newra}
+            include(fusedbyproc,i);
             dec(countunusedregs);
             dec(countunusedregs);
           {$endif}
           {$endif}
             r.enum:=R_INTREGISTER;
             r.enum:=R_INTREGISTER;
@@ -623,7 +667,7 @@ unit rgobj;
 {$ifdef EXTTEMPREGDEBUG}
 {$ifdef EXTTEMPREGDEBUG}
            begin
            begin
              comment(v_debug,'register freed twice '+supreg_name(supreg));
              comment(v_debug,'register freed twice '+supreg_name(supreg));
-             testregisters32;
+             testregisters32
              exit;
              exit;
            end
            end
 {$else EXTTEMPREGDEBUG}
 {$else EXTTEMPREGDEBUG}
@@ -666,8 +710,8 @@ unit rgobj;
 {$else}
 {$else}
                                 first_supreg,
                                 first_supreg,
                                 last_supreg,
                                 last_supreg,
-{$endif}
                                 usedintbyproc,
                                 usedintbyproc,
+{$endif}
                                 usedintinproc,
                                 usedintinproc,
                                 unusedregsint{$ifndef newra},
                                 unusedregsint{$ifndef newra},
                                 countunusedregsint{$endif});
                                 countunusedregsint{$endif});
@@ -675,8 +719,17 @@ unit rgobj;
       reg_user[result]:=curptree^;
       reg_user[result]:=curptree^;
       testregisters32;
       testregisters32;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
+{$ifdef newra}
+      add_constraints(getregisterint.number);
+{$endif}
     end;
     end;
 
 
+{$ifdef newra}
+    procedure Trgobj.add_constraints(reg:Tnewregister);
+
+    begin
+    end;
+{$endif}
 
 
     procedure trgobj.ungetregisterint(list : taasmoutput; r : tregister);
     procedure trgobj.ungetregisterint(list : taasmoutput; r : tregister);
 
 
@@ -708,7 +761,9 @@ unit rgobj;
 {$endif newra}
 {$endif newra}
           exclude(unusedregsint,r shr 8);
           exclude(unusedregsint,r shr 8);
           include(usedintinproc,r shr 8);
           include(usedintinproc,r shr 8);
+        {$ifndef newra}
           include(usedintbyproc,r shr 8);
           include(usedintbyproc,r shr 8);
+        {$endif}
           r2.enum:=R_INTREGISTER;
           r2.enum:=R_INTREGISTER;
           r2.number:=r;
           r2.number:=r;
           list.concat(tai_regalloc.alloc(r2));
           list.concat(tai_regalloc.alloc(r2));
@@ -846,6 +901,7 @@ unit rgobj;
       unusedregsfpu:=usableregsfpu;
       unusedregsfpu:=usableregsfpu;
       unusedregsmm:=usableregsmm;
       unusedregsmm:=usableregsmm;
    {$ifdef newra}
    {$ifdef newra}
+      savedbyproc:=[];
       for i:=low(Tsuperregister) to high(Tsuperregister) do
       for i:=low(Tsuperregister) to high(Tsuperregister) do
         begin
         begin
           if igraph.adjlist[i]<>nil then
           if igraph.adjlist[i]<>nil then
@@ -857,6 +913,7 @@ unit rgobj;
       fillchar(igraph,sizeof(igraph),0);
       fillchar(igraph,sizeof(igraph),0);
       fillchar(degree,sizeof(degree),0);
       fillchar(degree,sizeof(degree),0);
       worklist_moves.clear;
       worklist_moves.clear;
+      abtlist:='';
    {$endif}
    {$endif}
     end;
     end;
 
 
@@ -870,7 +927,7 @@ unit rgobj;
            ungetregisterint(list,ref.index);
            ungetregisterint(list,ref.index);
       end;
       end;
 
 
-
+{$ifndef newra}
     procedure trgobj.saveintregvars(list:Taasmoutput;const s:Tsupregset);
     procedure trgobj.saveintregvars(list:Taasmoutput;const s:Tsupregset);
 
 
     var r:Tsuperregister;
     var r:Tsuperregister;
@@ -887,6 +944,7 @@ unit rgobj;
             store_regvar(list,hr);
             store_regvar(list,hr);
           end;
           end;
     end;
     end;
+{$endif}
 
 
     procedure trgobj.saveotherregvars(list: taasmoutput; const s: tregisterset);
     procedure trgobj.saveotherregvars(list: taasmoutput; const s: tregisterset);
       var
       var
@@ -906,7 +964,7 @@ unit rgobj;
               store_regvar(list,r);
               store_regvar(list,r);
       end;
       end;
 
 
-
+{$ifndef newra}
     procedure trgobj.saveusedintregisters(list:Taasmoutput;
     procedure trgobj.saveusedintregisters(list:Taasmoutput;
                                           var saved:Tpushedsavedint;
                                           var saved:Tpushedsavedint;
                                           const s:Tsupregset);
                                           const s:Tsupregset);
@@ -935,15 +993,14 @@ unit rgobj;
               cg.a_load_reg_ref(list,OS_INT,r2,hr);
               cg.a_load_reg_ref(list,OS_INT,r2,hr);
               cg.a_reg_dealloc(list,r2);
               cg.a_reg_dealloc(list,r2);
               include(unusedregsint,r);
               include(unusedregsint,r);
-            {$ifndef newra}
               inc(countunusedregsint);
               inc(countunusedregsint);
-            {$endif}
             end;
             end;
         end;
         end;
 {$ifdef TEMPREGDEBUG}
 {$ifdef TEMPREGDEBUG}
       testregisters32;
       testregisters32;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
     end;
     end;
+{$endif}
 
 
     procedure trgobj.saveusedotherregisters(list: taasmoutput;
     procedure trgobj.saveusedotherregisters(list: taasmoutput;
         var saved : tpushedsavedother; const s: tregisterset);
         var saved : tpushedsavedother; const s: tregisterset);
@@ -1004,7 +1061,7 @@ unit rgobj;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
       end;
       end;
 
 
-
+{$ifndef newra}
     procedure trgobj.restoreusedintregisters(list:Taasmoutput;
     procedure trgobj.restoreusedintregisters(list:Taasmoutput;
                                              const saved:Tpushedsavedint);
                                              const saved:Tpushedsavedint);
 
 
@@ -1031,9 +1088,7 @@ unit rgobj;
                     may not be real (JM) }
                     may not be real (JM) }
                 else
                 else
                   begin
                   begin
-                  {$ifndef newra}
                     dec(countunusedregsint);
                     dec(countunusedregsint);
-                  {$endif}
                     exclude(unusedregsint,r);
                     exclude(unusedregsint,r);
                   end;
                   end;
                 tg.UnGetTemp(list,hr);
                 tg.UnGetTemp(list,hr);
@@ -1043,6 +1098,7 @@ unit rgobj;
         testregisters32;
         testregisters32;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
       end;
       end;
+{$endif}
 
 
     procedure trgobj.restoreusedotherregisters(list : taasmoutput;
     procedure trgobj.restoreusedotherregisters(list : taasmoutput;
         const saved : tpushedsavedother);
         const saved : tpushedsavedother);
@@ -1104,7 +1160,7 @@ unit rgobj;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
       end;
       end;
 
 
-
+{$ifndef newra}
     procedure trgobj.incrementintregisterpushed(const s:Tsupregset);
     procedure trgobj.incrementintregisterpushed(const s:Tsupregset);
 
 
     var regi:Tsuperregister;
     var regi:Tsuperregister;
@@ -1118,6 +1174,7 @@ unit rgobj;
         end;
         end;
 {$endif i386}
 {$endif i386}
     end;
     end;
+{$endif}
 
 
     procedure trgobj.incrementotherregisterpushed(const s:Tregisterset);
     procedure trgobj.incrementotherregisterpushed(const s:Tregisterset);
 
 
@@ -1145,14 +1202,18 @@ unit rgobj;
     procedure trgobj.clearregistercount;
     procedure trgobj.clearregistercount;
 
 
       begin
       begin
+      {$ifndef newra}
         fillchar(reg_pushes_int,sizeof(reg_pushes_int),0);
         fillchar(reg_pushes_int,sizeof(reg_pushes_int),0);
+      {$endif}
         fillchar(reg_pushes_other,sizeof(reg_pushes_other),0);
         fillchar(reg_pushes_other,sizeof(reg_pushes_other),0);
 {ifndef i386}
 {ifndef i386}
         { all used registers will have to be saved at the start and restored }
         { all used registers will have to be saved at the start and restored }
         { at the end, but otoh regpara's do not have to be saved to memory   }
         { at the end, but otoh regpara's do not have to be saved to memory   }
         { at the start (there is a move from regpara to regvar most of the   }
         { at the start (there is a move from regpara to regvar most of the   }
         { time though) -> set cost to 100+20                                 }
         { time though) -> set cost to 100+20                                 }
+      {$ifndef newra}
         filldword(reg_pushes_int[firstsaveintreg],lastsaveintreg-firstsaveintreg+1,120);
         filldword(reg_pushes_int[firstsaveintreg],lastsaveintreg-firstsaveintreg+1,120);
+      {$endif}
         filldword(reg_pushes_other[firstsavefpureg],ord(lastsavefpureg)-ord(firstsavefpureg)+1,120);
         filldword(reg_pushes_other[firstsavefpureg],ord(lastsavefpureg)-ord(firstsavefpureg)+1,120);
 {endif not i386}
 {endif not i386}
         fillchar(is_reg_var_other,sizeof(is_reg_var_other),false);
         fillchar(is_reg_var_other,sizeof(is_reg_var_other),false);
@@ -1254,7 +1315,9 @@ unit rgobj;
         psavedstate(state)^.countusableregsmm := countusableregsmm;
         psavedstate(state)^.countusableregsmm := countusableregsmm;
         psavedstate(state)^.usedinproc := usedinproc;
         psavedstate(state)^.usedinproc := usedinproc;
         psavedstate(state)^.usedbyproc := usedbyproc;
         psavedstate(state)^.usedbyproc := usedbyproc;
+      {$ifndef newra}
         psavedstate(state)^.reg_pushes_int := reg_pushes_int;
         psavedstate(state)^.reg_pushes_int := reg_pushes_int;
+      {$endif}
         psavedstate(state)^.reg_pushes_other := reg_pushes_other;
         psavedstate(state)^.reg_pushes_other := reg_pushes_other;
         psavedstate(state)^.is_reg_var_int := is_reg_var_int;
         psavedstate(state)^.is_reg_var_int := is_reg_var_int;
         psavedstate(state)^.is_reg_var_other := is_reg_var_other;
         psavedstate(state)^.is_reg_var_other := is_reg_var_other;
@@ -1285,7 +1348,9 @@ unit rgobj;
         countusableregsmm := psavedstate(state)^.countusableregsmm;
         countusableregsmm := psavedstate(state)^.countusableregsmm;
         usedinproc := psavedstate(state)^.usedinproc;
         usedinproc := psavedstate(state)^.usedinproc;
         usedbyproc := psavedstate(state)^.usedbyproc;
         usedbyproc := psavedstate(state)^.usedbyproc;
+      {$ifndef newra}
         reg_pushes_int := psavedstate(state)^.reg_pushes_int;
         reg_pushes_int := psavedstate(state)^.reg_pushes_int;
+      {$endif}
         reg_pushes_other := psavedstate(state)^.reg_pushes_other;
         reg_pushes_other := psavedstate(state)^.reg_pushes_other;
         is_reg_var_int := psavedstate(state)^.is_reg_var_int;
         is_reg_var_int := psavedstate(state)^.is_reg_var_int;
         is_reg_var_other := psavedstate(state)^.is_reg_var_other;
         is_reg_var_other := psavedstate(state)^.is_reg_var_other;
@@ -1370,7 +1435,7 @@ unit rgobj;
     var i:Tsuperregister;
     var i:Tsuperregister;
 
 
     begin
     begin
-      for i:=1 to 255 do
+      for i:=1 to maxintreg do
         if not(i in unusedregsint) then
         if not(i in unusedregsint) then
           add_edge(u,i);
           add_edge(u,i);
     end;
     end;
@@ -1443,7 +1508,11 @@ unit rgobj;
       ssupreg:=instr.oper[0].reg.number shr 8;
       ssupreg:=instr.oper[0].reg.number shr 8;
       add_to_movelist(ssupreg,i);
       add_to_movelist(ssupreg,i);
       dsupreg:=instr.oper[1].reg.number shr 8;
       dsupreg:=instr.oper[1].reg.number shr 8;
-      add_to_movelist(dsupreg,i);
+      if ssupreg<>dsupreg then
+        {Avoid adding the same move instruction twice to a single register.}
+        add_to_movelist(dsupreg,i);
+      i.x:=ssupreg;
+      i.y:=dsupreg;
     end;
     end;
 
 
     function Trgobj.move_related(n:Tsuperregister):boolean;
     function Trgobj.move_related(n:Tsuperregister):boolean;
@@ -1469,8 +1538,10 @@ unit rgobj;
     var n:Tsuperregister;
     var n:Tsuperregister;
 
 
     begin
     begin
+      {If we have 7 cpu registers, and the degree of a node is 7, we cannot
+       assign it to any of the registers, thus it is significant.}
       for n:=first_imreg to maxintreg do
       for n:=first_imreg to maxintreg do
-        if degree[n]>cpu_registers then
+        if degree[n]>=cpu_registers then
           spillworklist:=spillworklist+char(n)
           spillworklist:=spillworklist+char(n)
         else if move_related(n) then
         else if move_related(n) then
           freezeworklist:=freezeworklist+char(n)
           freezeworklist:=freezeworklist+char(n)
@@ -1518,7 +1589,7 @@ unit rgobj;
 
 
     var adj:Pstring;
     var adj:Pstring;
         d:byte;
         d:byte;
-        i:byte;
+        i,p:byte;
         n:char;
         n:char;
 
 
     begin
     begin
@@ -1537,8 +1608,14 @@ unit rgobj;
                 if (pos(n,selectstack) or pos(n,coalescednodes))=0 then
                 if (pos(n,selectstack) or pos(n,coalescednodes))=0 then
                   enable_moves(Tsuperregister(n));
                   enable_moves(Tsuperregister(n));
               end;
               end;
-          {In case the node is in the spillworklist, delete it.}
-          delete(spillworklist,pos(char(m),spillworklist),1);
+          {Remove the node from the spillworklist.}
+          p:=pos(char(m),spillworklist);
+          if p=0 then
+            internalerror(200305301); {must be found}
+          if length(spillworklist)>1 then
+            spillworklist[p]:=spillworklist[length(spillworklist)];
+          dec(spillworklist[0]);
+
           if move_related(m) then
           if move_related(m) then
             freezeworklist:=freezeworklist+char(m)
             freezeworklist:=freezeworklist+char(m)
           else
           else
@@ -1586,7 +1663,7 @@ unit rgobj;
           begin
           begin
             m:=adj^[i];
             m:=adj^[i];
             if (pos(m,selectstack) or pos(m,coalescednodes))=0 then
             if (pos(m,selectstack) or pos(m,coalescednodes))=0 then
-              decrement_degree(Tsuperregister(m));
+               decrement_degree(Tsuperregister(m));
           end;
           end;
     end;
     end;
 
 
@@ -1716,8 +1793,8 @@ unit rgobj;
             t:=adj^[i];
             t:=adj^[i];
             if (pos(t,selectstack) or pos(t,coalescednodes))=0 then
             if (pos(t,selectstack) or pos(t,coalescednodes))=0 then
               begin
               begin
-                add_edge(Tsuperregister(t),u);
                 decrement_degree(Tsuperregister(t));
                 decrement_degree(Tsuperregister(t));
+                add_edge(Tsuperregister(t),u);
               end;
               end;
           end;
           end;
       p:=pos(char(u),freezeworklist);
       p:=pos(char(u),freezeworklist);
@@ -1882,6 +1959,8 @@ unit rgobj;
                 colour[n]:=k;
                 colour[n]:=k;
                 dec(spillednodes[0]);  {Colour found: no spill.}
                 dec(spillednodes[0]);  {Colour found: no spill.}
                 include(colourednodes,n);
                 include(colourednodes,n);
+                if n in usedintinproc then
+                  include(usedintinproc,k);
                 break;
                 break;
               end;
               end;
         end;
         end;
@@ -1889,10 +1968,15 @@ unit rgobj;
       for i:=1 to length(coalescednodes) do
       for i:=1 to length(coalescednodes) do
         begin
         begin
           n:=Tsuperregister(coalescednodes[i]);
           n:=Tsuperregister(coalescednodes[i]);
-          colour[n]:=colour[get_alias(n)];
+          k:=get_alias(n);
+          colour[n]:=colour[k];
+          if n in usedintinproc then
+            include(usedintinproc,colour[k]);
         end;
         end;
+    {$ifdef ra_debug}
       for i:=first_imreg to maxintreg do
       for i:=first_imreg to maxintreg do
         writeln(i:4,'   ',colour[i]:4)
         writeln(i:4,'   ',colour[i]:4)
+    {$endif}
     end;
     end;
 
 
     procedure Trgobj.colour_registers;
     procedure Trgobj.colour_registers;
@@ -1917,7 +2001,33 @@ unit rgobj;
 
 
     procedure Trgobj.epilogue_colouring;
     procedure Trgobj.epilogue_colouring;
 
 
+{
+      procedure move_to_worklist_moves(list:Tlinkedlist);
+
+      var p:Tlinkedlistitem;
+
+      begin
+        p:=list.first;
+        while p<>nil do
+          begin
+            Tmoveins(p).moveset:=ms_worklist_moves;
+            p:=p.next;
+          end;
+        worklist_moves.concatlist(list);
+      end;
+}
+
+    var i:Tsuperregister;
+
     begin
     begin
+      worklist_moves.clear;
+{$ifdef Principle_wrong_by_definition}
+      {Move everything back to worklist_moves.}
+      move_to_worklist_moves(active_moves);
+      move_to_worklist_moves(frozen_moves);
+      move_to_worklist_moves(coalesced_moves);
+      move_to_worklist_moves(constrained_moves);
+{$endif}
       active_moves.destroy;
       active_moves.destroy;
       active_moves:=nil;
       active_moves:=nil;
       frozen_moves.destroy;
       frozen_moves.destroy;
@@ -1926,10 +2036,303 @@ unit rgobj;
       coalesced_moves:=nil;
       coalesced_moves:=nil;
       constrained_moves.destroy;
       constrained_moves.destroy;
       constrained_moves:=nil;
       constrained_moves:=nil;
+      for i:=0 to 255 do
+        if movelist[i]<>nil then
+          begin
+            dispose(movelist[i]);
+            movelist[i]:=0;
+          end;
     end;
     end;
 
 
-{$endif newra}
 
 
+    procedure Trgobj.clear_interferences(u:Tsuperregister);
+
+    {Remove node u from the interference graph and remove all collected
+     move instructions it is associated with.}
+
+    var i:byte; 
+        j,k,count:cardinal;
+        v:Tsuperregister;
+        m,n:Tmoveins;
+
+    begin
+      if igraph.adjlist[u]<>nil then
+        begin
+          for i:=1 to length(igraph.adjlist[u]^) do
+            begin
+              v:=Tsuperregister(igraph.adjlist[u]^[i]);
+              {Remove (u,v) and (v,u) from bitmap.}
+              exclude(igraph.bitmap[u],v);
+              exclude(igraph.bitmap[v],u);
+              {Remove (v,u) from adjacency list.}
+              if igraph.adjlist[v]<>nil then
+                begin
+                  delete(igraph.adjlist[v]^,pos(char(v),igraph.adjlist[v]^),1);
+                  if length(igraph.adjlist[v]^)=0 then
+                    begin
+                      dispose(igraph.adjlist[v]);
+                      igraph.adjlist[v]:=nil;
+                    end;
+                end;
+            end;
+          {Remove ( u,* ) from adjacency list.}
+          dispose(igraph.adjlist[u]);
+          igraph.adjlist[u]:=nil;
+        end;
+{$ifdef Principle_wrong_by_definition}
+      {Now remove the moves.}
+      if movelist[u]<>nil then
+        begin
+          for j:=0 to movelist[u]^.count-1 do
+            begin
+              m:=Tmoveins(movelist[u]^.data[j]);
+              {Get the other register of the move instruction.}
+              v:=m.instruction.oper[0].reg.number shr 8;
+              if v=u then
+                v:=m.instruction.oper[1].reg.number shr 8;
+              repeat
+                repeat
+                  if (u<>v) and (movelist[v]<>nil) then
+                    begin
+                      {Remove the move from it's movelist.}
+                      count:=movelist[v]^.count-1;
+                      for k:=0 to count do
+                        if m=movelist[v]^.data[k] then
+                          begin
+                            if k<>count then
+                              movelist[v]^.data[k]:=movelist[v]^.data[count];
+                            dec(movelist[v]^.count);
+                            if count=0 then
+                              begin
+                                dispose(movelist[v]);
+                                movelist[v]:=nil;
+                              end;
+                            break;
+                          end;
+                    end;
+                  {The complexity is enourmous: the register might have been
+                   coalesced. In that case it's movelists have been added to
+                   it's coalescing alias. (DM)}
+                  v:=alias[v];
+                until v=0;
+                {And also register u might have been coalesced.}
+                u:=alias[u];
+              until u=0;
+
+              case m.moveset of
+                ms_coalesced_moves:
+                  coalesced_moves.remove(m);
+                ms_constrained_moves:
+                  constrained_moves.remove(m);
+                ms_frozen_moves:
+                  frozen_moves.remove(m);
+                ms_worklist_moves:
+                  worklist_moves.remove(m);
+                ms_active_moves:
+                  active_moves.remove(m);
+              end;
+            end;
+          dispose(movelist[u]);
+          movelist[u]:=nil;
+        end;
+{$endif}
+    end;
+
+    procedure Trgobj.getregisterintinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
+
+    var i:Tsuperregister;
+        r:Tregister;
+
+    begin
+      if not (lastintreg in [first_imreg..last_imreg]) then
+        lastintreg:=first_imreg;
+      i:=lastintreg;
+      repeat
+        if i=last_imreg then
+          i:=first_imreg
+        else
+          inc(i);
+        if (i in unusedregsint) and (pos(char(i),abtlist)=0) then
+          begin
+            exclude(unusedregsint,i);
+            include(usedintinproc,i);
+            r.enum:=R_INTREGISTER;
+            r.number:=i shl 8 or subreg;
+            if position=nil then
+              list.insert(Tai_regalloc.alloc(r))
+            else
+              list.insertafter(Tai_regalloc.alloc(r),position);
+            result:=r;
+            lastintreg:=i;
+            if i>maxintreg then
+              maxintreg:=i;
+            add_edges_used(i);
+            add_constraints(result.number);
+            exit;
+          end;
+      until i=lastintreg;
+      internalerror(10);
+    end;
+
+    {In some cases we can get in big trouble. See this example:
+
+     ; register reg23d released
+     ; register eax allocated
+     ; register ebx allocated
+     ; register ecx allocated
+     ; register edx allocated
+     ; register esi allocated
+     ; register edi allocated
+     call [reg23d]
+
+    This code is ok, *except* when reg23d is spilled. In that case the
+    spilled would introduce a help register which can never get
+    allocated to a real register because it interferes with all of them.
+
+    To solve this we introduce the ABT ("avoid big trouble :)" ) registers.
+
+    If you allocate an ABT register you get a register that has less
+    than cpu_register interferences and will not be allocated ever again
+    by the normal register get procedures. In other words it is for sure it
+    will never get spilled.}
+
+    function Trgobj.getabtregisterint(list:Taasmoutput;size:Tcgsize):Tregister;
+
+    var i:Tsuperregister;
+        r:Tregister;
+        found:boolean;
+
+    begin
+      if not (lastintreg in [first_imreg..last_imreg]) then
+        lastintreg:=first_imreg;
+      found:=false;
+      for i:=1 to length(abtlist) do
+        if Tsuperregister(abtlist[i]) in unusedregsint then
+          begin
+            found:=true;
+            break;
+          end;
+      i:=lastintreg;
+      repeat
+        if i=last_imreg then
+          i:=first_imreg
+        else
+          inc(i);
+        if (i in unusedregsint) and ((igraph.adjlist[i]=nil) or (length(igraph.adjlist[i]^)<cpu_registers)) then
+          begin
+            found:=true;
+            break;
+          end;
+      until i=lastintreg;
+      if found then
+        begin
+          exclude(unusedregsint,i);
+          include(usedintinproc,i);
+          r.enum:=R_INTREGISTER;
+          r.number:=i shl 8 or cgsize2subreg(size);
+          list.concat(Tai_regalloc.alloc(r));
+          getabtregisterint:=r;
+          lastintreg:=i;
+          if i>maxintreg then
+            maxintreg:=i;
+          add_edges_used(i);
+          if pos(char(i),abtlist)=0 then
+            abtlist:=abtlist+char(i);
+        end
+      else
+        internalerror(10);
+{$ifdef newra}
+      add_constraints(getabtregisterint.number);
+{$endif}
+    end;
+
+    procedure Trgobj.ungetregisterintinline(list:Taasmoutput;position:Tai;const r:Tregister);
+
+    var supreg:Tsuperregister;
+
+    begin
+      if r.enum<=lastreg then
+        internalerror(2003010803);
+      supreg:=r.number shr 8;
+      { takes much time }
+      include(unusedregsint,supreg);
+      if position=nil then
+        list.insert(Tai_regalloc.dealloc(r))
+      else
+        list.insertafter(Tai_regalloc.dealloc(r),position);
+      add_edges_used(supreg);
+    end;
+
+    function Trgobj.spill_registers(list:Taasmoutput;const regs_to_spill:string):boolean;
+
+    {Returns true if any help registers have been used.}
+
+    var i:byte;
+        r:Tsuperregister;
+        p,q:Tai;
+        regs_to_spill_set:Tsupregset;
+        spill_temps:^Tspill_temp_list;
+
+    begin
+      spill_registers:=false;
+      unusedregsint:=[0..255];
+      fillchar(degree,sizeof(degree),0);
+      if current_procinfo.framepointer.number=NR_FRAME_POINTER_REG then
+        {Make sure the register allocator won't allocate registers into ebp.}
+        exclude(rg.unusedregsint,RS_FRAME_POINTER_REG);
+      new(spill_temps);
+      fillchar(spill_temps^,sizeof(spill_temps^),0);
+      regs_to_spill_set:=[];
+      for i:=1 to length(regs_to_spill) do
+        begin
+          {Alternative representation.}
+          include(regs_to_spill_set,Tsuperregister(regs_to_spill[i]));
+          {Clear all interferences of the spilled register.}
+          clear_interferences(Tsuperregister(regs_to_spill[i]));
+          {Get a temp for the spilled register.}
+          tg.gettemp(list,4,tt_noreuse,spill_temps^[Tsuperregister(regs_to_spill[i])]);
+        end;
+      p:=Tai(list.first);
+      while assigned(p) do
+        begin
+          case p.typ of
+            ait_regalloc:
+              begin
+                {A register allocation of a spilled register can be removed.}
+                if (Tai_regalloc(p).reg.number shr 8) in regs_to_spill_set then
+                  begin
+                    q:=p;
+                    p:=Tai(p.next);
+                    list.remove(q);
+                    continue;
+                  end
+                else
+                  if Tai_regalloc(p).allocation then
+                    exclude(unusedregsint,Tai_regalloc(p).reg.number shr 8)
+                  else
+                    include(unusedregsint,Tai_regalloc(p).reg.number shr 8);
+              end;
+            ait_instruction:
+              begin
+                if Taicpu_abstract(p).spill_registers(list,@getregisterintinline,
+                                                      @ungetregisterintinline,
+                                                      regs_to_spill_set,
+                                                      unusedregsint,
+                                                      spill_temps^) then
+                  spill_registers:=true;
+                if Taicpu_abstract(p).is_move then
+                  add_move_instruction(Taicpu(p));
+              end;
+          end;
+          p:=Tai(p.next);
+        end;
+      for i:=1 to length(regs_to_spill) do
+        begin
+          tg.ungettemp(list,spill_temps^[Tsuperregister(regs_to_spill[i])]);
+        end;
+      dispose(spill_temps);
+    end;
+{$endif newra}
 
 
 {****************************************************************************
 {****************************************************************************
                                   TReference
                                   TReference
@@ -2060,7 +2463,10 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.48  2003-06-01 21:38:06  peter
+  Revision 1.49  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.48  2003/06/01 21:38:06  peter
     * getregisterfpu size parameter added
     * getregisterfpu size parameter added
     * op_const_reg size parameter added
     * op_const_reg size parameter added
     * sparc updates
     * sparc updates

+ 8 - 4
compiler/symdef.pas

@@ -764,7 +764,8 @@ implementation
 {$endif GDB}
 {$endif GDB}
        fmodule,
        fmodule,
        { other }
        { other }
-       gendef
+       gendef,
+       rgobj
        ;
        ;
 
 
 
 
@@ -3420,7 +3421,7 @@ implementation
           end;
           end;
          lastref:=defref;
          lastref:=defref;
        { first, we assume that all registers are used }
        { first, we assume that all registers are used }
-         usedintregisters:=ALL_INTREGISTERS;
+         usedintregisters:=ALL_INTREGISTERS-[RS_FRAME_POINTER_REG];
          usedotherregisters:=ALL_REGISTERS;
          usedotherregisters:=ALL_REGISTERS;
          forwarddef:=true;
          forwarddef:=true;
          interfacedef:=false;
          interfacedef:=false;
@@ -3555,7 +3556,7 @@ implementation
          { set all registers to used for simplified compilation PM }
          { set all registers to used for simplified compilation PM }
          if simplify_ppu then
          if simplify_ppu then
            begin
            begin
-             usedintregisters:=ALL_INTREGISTERS;
+             usedintregisters:=ALL_INTREGISTERS-[RS_FRAME_POINTER_REG];
              usedotherregisters:=ALL_REGISTERS;
              usedotherregisters:=ALL_REGISTERS;
            end;
            end;
 
 
@@ -5740,7 +5741,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.147  2003-06-02 22:55:28  florian
+  Revision 1.148  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.147  2003/06/02 22:55:28  florian
     * classes and interfaces can be stored in integer registers
     * classes and interfaces can be stored in integer registers
 
 
   Revision 1.146  2003/05/26 21:17:18  peter
   Revision 1.146  2003/05/26 21:17:18  peter

+ 15 - 12
compiler/tgobj.pas

@@ -66,8 +66,8 @@ unit tgobj;
        private
        private
           { contains all free temps using nextfree links }
           { contains all free temps using nextfree links }
           tempfreelist  : ptemprecord;
           tempfreelist  : ptemprecord;
-          function AllocTemp(list: taasmoutput; size : longint; temptype : ttemptype) : longint;
-          procedure FreeTemp(list: taasmoutput; pos:longint;temptypes:ttemptypeset);
+          function alloctemp(list: taasmoutput; size : longint; temptype : ttemptype) : longint;
+          procedure freetemp(list: taasmoutput; pos:longint;temptypes:ttemptypeset);
        public
        public
           { contains all temps }
           { contains all temps }
           templist      : ptemprecord;
           templist      : ptemprecord;
@@ -88,11 +88,11 @@ unit tgobj;
           procedure setfirsttemp(l : longint);
           procedure setfirsttemp(l : longint);
           function gettempsize : longint;
           function gettempsize : longint;
 
 
-          procedure GetTemp(list: taasmoutput; size : longint;temptype:ttemptype;var ref : treference);
-          procedure UnGetTemp(list: taasmoutput; const ref : treference);
+          procedure gettemp(list: taasmoutput; size : longint;temptype:ttemptype;var ref : treference);
+          procedure ungettemp(list: taasmoutput; const ref : treference);
 
 
-          function SizeOfTemp(list: taasmoutput; const ref: treference): longint;
-          function ChangeTempType(list: taasmoutput; const ref:treference;temptype:ttemptype):boolean;
+          function sizeoftemp(list: taasmoutput; const ref: treference): longint;
+          function changetemptype(list: taasmoutput; const ref:treference;temptype:ttemptype):boolean;
 
 
           {# Returns TRUE if the reference ref is allocated in temporary volatile memory space,
           {# Returns TRUE if the reference ref is allocated in temporary volatile memory space,
              otherwise returns FALSE.
              otherwise returns FALSE.
@@ -244,7 +244,7 @@ unit tgobj;
          if freetype=tt_none then
          if freetype=tt_none then
           internalerror(200208201);
           internalerror(200208201);
          { Align needed size on 4 bytes }
          { Align needed size on 4 bytes }
-         size:=Align(size,4);
+         size:=align(size,4);
          { First check the tmpfreelist, but not when
          { First check the tmpfreelist, but not when
            we don't want to reuse an already allocated block }
            we don't want to reuse an already allocated block }
          if assigned(tempfreelist) and
          if assigned(tempfreelist) and
@@ -438,7 +438,7 @@ unit tgobj;
       end;
       end;
 
 
 
 
-    procedure ttgobj.GetTemp(list: taasmoutput; size : longint;temptype:ttemptype;var ref : treference);
+    procedure ttgobj.gettemp(list: taasmoutput; size : longint;temptype:ttemptype;var ref : treference);
 
 
     begin
     begin
       reference_reset_base(ref,current_procinfo.framepointer,alloctemp(list,size,temptype));
       reference_reset_base(ref,current_procinfo.framepointer,alloctemp(list,size,temptype));
@@ -471,7 +471,7 @@ unit tgobj;
       end;
       end;
 
 
 
 
-    function ttgobj.SizeOfTemp(list: taasmoutput; const ref: treference): longint;
+    function ttgobj.sizeoftemp(list: taasmoutput; const ref: treference): longint;
       var
       var
          hp : ptemprecord;
          hp : ptemprecord;
       begin
       begin
@@ -481,13 +481,13 @@ unit tgobj;
            begin
            begin
              if (hp^.pos=ref.offset) then
              if (hp^.pos=ref.offset) then
                begin
                begin
-                 SizeOfTemp := hp^.size;
+                 sizeoftemp := hp^.size;
                  exit;
                  exit;
                end;
                end;
              hp := hp^.next;
              hp := hp^.next;
            end;
            end;
 {$ifdef EXTDEBUG}
 {$ifdef EXTDEBUG}
-         Comment(V_Debug,'tgobj: (SizeOfTemp) temp at pos '+tostr(ref.offset)+' not found !');
+         comment(v_debug,'tgobj: (SizeOfTemp) temp at pos '+tostr(ref.offset)+' not found !');
          list.concat(tai_tempalloc.allocinfo(ref.offset,0,'temp not found'));
          list.concat(tai_tempalloc.allocinfo(ref.offset,0,'temp not found'));
 {$endif}
 {$endif}
       end;
       end;
@@ -554,7 +554,10 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.34  2003-05-17 13:30:08  jonas
+  Revision 1.35  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.34  2003/05/17 13:30:08  jonas
     * changed tt_persistant to tt_persistent :)
     * changed tt_persistant to tt_persistent :)
     * tempcreatenode now doesn't accept a boolean anymore for persistent
     * tempcreatenode now doesn't accept a boolean anymore for persistent
       temps, but a ttemptype, so you can also create ansistring temps etc
       temps, but a ttemptype, so you can also create ansistring temps etc

+ 374 - 4
compiler/x86/aasmcpu.pas

@@ -194,6 +194,14 @@ interface
          function  Pass1(offset:longint):longint;virtual;
          function  Pass1(offset:longint):longint;virtual;
          procedure Pass2(sec:TAsmObjectdata);virtual;
          procedure Pass2(sec:TAsmObjectdata);virtual;
          procedure SetOperandOrder(order:TOperandOrder);
          procedure SetOperandOrder(order:TOperandOrder);
+         function is_nop:boolean;override;
+         function is_move:boolean;override;
+         function spill_registers(list:Taasmoutput;
+                                  rgget:Trggetproc;
+                                  rgunget:Trgungetproc;
+                                  r:Tsupregset;
+                                  var unusedregsint:Tsupregset;
+                                  const spilltemplist:Tspill_temp_list):boolean;override;
       protected
       protected
          procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
          procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
          procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
          procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
@@ -212,10 +220,8 @@ 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;
 
 
-
     procedure InitAsm;
     procedure InitAsm;
     procedure DoneAsm;
     procedure DoneAsm;
 
 
@@ -1968,12 +1974,373 @@ implementation
 
 
     begin
     begin
       {We do not check the number of operands; we assume that nobody constructs
       {We do not check the number of operands; we assume that nobody constructs
-       a mov or xchg instruction with less than 2 operands.}
+       a mov or xchg instruction with less than 2 operands. (DM)}
       is_nop:=(opcode=A_NOP) or
       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_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);
               (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;
     end;
 
 
+    function Taicpu.is_move:boolean;
+
+    begin
+      {We do not check the number of operands; we assume that nobody constructs
+       a mov, movzx or movsx instruction with less than 2 operands. Note that
+       a move between a reference and a register is not a move that is of
+       interrest to the register allocation, therefore we only return true
+       for a move between two registers. (DM)}
+      is_move:=((opcode=A_MOV) or (opcode=A_MOVZX) or (opcode=A_MOVSX)) and
+        ((oper[0].typ=top_reg) and (oper[1].typ=top_reg));
+    end;
+
+    function Taicpu.spill_registers(list:Taasmoutput;
+                                    rgget:Trggetproc;
+                                    rgunget:Trgungetproc;
+                                    r:Tsupregset;
+                                    var unusedregsint:Tsupregset;
+                                    const spilltemplist:Tspill_temp_list):boolean;
+
+    {Spill the registers in r in this instruction. Returns true if any help
+     registers are used. This procedure has become one big hack party, because
+     of the huge amount of situations you can have. The irregularity of the i386
+     instruction set doesn't help either. (DM)}
+
+
+      function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
+
+      var back:Tsupregset;
+
+      begin
+        back:=unusedregsint;
+        get_insert_pos:=p;
+        while (p<>nil) and (p.typ=ait_regalloc) do
+          begin
+            {Rewind the register allocation.}
+            if Tai_regalloc(p).allocation then
+              include(unusedregsint,Tai_regalloc(p).reg.number shr 8)
+            else
+              begin
+                exclude(unusedregsint,Tai_regalloc(p).reg.number shr 8);
+                if Tai_regalloc(p).reg.number shr 8=huntfor1 then
+                  begin
+                    get_insert_pos:=Tai(p.previous);
+                    back:=unusedregsint;
+                  end;
+                if Tai_regalloc(p).reg.number shr 8=huntfor2 then
+                  begin
+                    get_insert_pos:=Tai(p.previous);
+                    back:=unusedregsint;
+                  end;
+                if Tai_regalloc(p).reg.number shr 8=huntfor3 then
+                  begin
+                    get_insert_pos:=Tai(p.previous);
+                    back:=unusedregsint;
+                  end;
+              end;
+            p:=Tai(p.previous);
+          end;
+        unusedregsint:=back;
+      end;
+
+      procedure forward_allocation(p:Tai);
+
+      begin
+        {Forward the register allocation again.}
+        while (p<>self) do
+          begin
+            if p.typ<>ait_regalloc then
+              internalerror(200305311);
+            if Tai_regalloc(p).allocation then
+              exclude(unusedregsint,Tai_regalloc(p).reg.number shr 8)
+            else
+              include(unusedregsint,Tai_regalloc(p).reg.number shr 8);
+            p:=Tai(p.next);
+          end;
+      end;
+
+    var i:byte;
+        supreg:Tsuperregister;
+        subreg:Tsubregister;
+        helpreg:Tregister;
+        helpins:Taicpu;
+        op:Tasmop;
+        hopsize:Topsize;
+        pos:Tai;
+
+    begin
+      {Situation examples are in intel notation, so operand order:
+       mov    eax       ,    ebx
+              ^^^            ^^^
+              oper[1]        oper[0]
+      (DM)}
+      spill_registers:=false;
+      case ops of
+        1:
+          begin
+            if oper[0].typ=top_reg then
+              begin
+                supreg:=oper[0].reg.number shr 8;
+                if supreg in r then
+                  begin
+                    {Situation example:
+                     push r20d              ; r20d must be spilled into [ebp-12]
+
+                    Change into:
+                     push [ebp-12]          ; Replace register by reference }
+{                    hopsize:=reg2opsize(oper[0].reg);}
+                    oper[0].typ:=top_ref;
+                    new(oper[0].ref);
+                    oper[0].ref^:=spilltemplist[supreg];
+{                    oper[0].ref^.size:=hopsize;}
+                  end;
+              end;
+            if oper[0].typ=top_ref then
+              begin
+                supreg:=oper[0].ref^.base.number shr 8;
+                if supreg in r then
+                  begin
+                    {Situation example:
+                     push [r21d+4*r22d]        ; r21d must be spilled into [ebp-12]
+
+                     Change into:
+
+                     mov r23d,[ebp-12]         ; Use a help register
+                     push [r23d+4*r22d]       ; Replace register by helpregister }
+                    subreg:=oper[0].ref^.base.number and $ff;
+                    if oper[0].ref^.index.number=NR_NO then
+                      pos:=Tai(previous)
+                    else
+                      pos:=get_insert_pos(Tai(previous),oper[0].ref^.index.number shr 8,0,0);
+                    rgget(list,pos,subreg,helpreg);
+                    spill_registers:=true;
+                    helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0].ref^.base),spilltemplist[supreg],helpreg);
+                    if pos=nil then
+                      list.insertafter(helpins,list.first)
+                    else
+                      list.insertafter(helpins,pos.next);
+                    rgunget(list,helpins,helpreg);
+                    forward_allocation(Tai(helpins.next));
+                    oper[0].ref^.base:=helpreg;
+                  end;
+                supreg:=oper[0].ref^.index.number shr 8;
+                if supreg in r then
+                  begin
+                    {Situation example:
+                     push [r21d+4*r22d]        ; r22d must be spilled into [ebp-12]
+
+                     Change into:
+
+                     mov r23d,[ebp-12]         ; Use a help register
+                     push [r21d+4*r23d]        ; Replace register by helpregister }
+                    subreg:=oper[0].ref^.index.number and $ff;
+                    if oper[0].ref^.base.number=NR_NO then
+                      pos:=Tai(previous)
+                    else
+                      pos:=get_insert_pos(Tai(previous),oper[0].ref^.base.number shr 8,0,0);
+                    rgget(list,pos,subreg,helpreg);
+                    spill_registers:=true;
+                    helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0].ref^.index),spilltemplist[supreg],helpreg);
+                    if pos=nil then
+                      list.insertafter(helpins,list.first)
+                    else
+                      list.insertafter(helpins,pos.next);
+                    rgunget(list,helpins,helpreg);
+                    forward_allocation(Tai(helpins.next));
+                    oper[0].ref^.index:=helpreg;
+                  end;
+                end;
+          end;
+        2:
+          begin
+            if oper[0].typ=top_reg then
+              begin
+                supreg:=oper[0].reg.number shr 8;
+                subreg:=oper[0].reg.number and $ff;
+                if supreg in r then
+                  if oper[1].typ=top_ref then
+                    begin
+                      {Situation example:
+                       add [r20d],r21d      ; r21d must be spilled into [ebp-12]
+
+                       Change into:
+
+                       mov r22d,[ebp-12]    ; Use a help register
+                       add [r20d],r22d      ; Replace register by helpregister }
+                      pos:=get_insert_pos(Tai(previous),oper[0].reg.number shr 8,
+                                          oper[1].ref^.base.number shr 8,oper[1].ref^.index.number shr 8);
+                      rgget(list,pos,subreg,helpreg);
+                      spill_registers:=true;
+                      helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0].reg),spilltemplist[supreg],helpreg);
+                      if pos=nil then
+                        list.insertafter(helpins,list.first)
+                      else
+                        list.insertafter(helpins,pos.next);
+                      oper[0].reg:=helpreg;
+                      rgunget(list,helpins,helpreg);
+                      forward_allocation(Tai(helpins.next));
+                    end
+                  else
+                    begin
+                      {Situation example:
+                       add r20d,r21d        ; r21d must be spilled into [ebp-12]
+
+                       Change into:
+
+                       add r20d,[ebp-12]    ; Replace register by reference }
+                      oper[0].typ:=top_ref;
+                      new(oper[0].ref);
+                      oper[0].ref^:=spilltemplist[supreg];
+                    end;
+              end;
+            if oper[1].typ=top_reg then
+              begin
+                supreg:=oper[1].reg.number shr 8;
+                subreg:=oper[1].reg.number and $ff;
+                if supreg in r then
+                  begin
+                    if oper[0].typ=top_ref then
+                      begin
+                        {Situation example:
+                         add r20d,[r21d]      ; r20d must be spilled into [ebp-12]
+  
+                         Change into:
+  
+                         mov r22d,[r21d]      ; Use a help register
+                         add [ebp-12],r22d    ; Replace register by helpregister }
+                        pos:=get_insert_pos(Tai(previous),oper[0].ref^.base.number shr 8,
+                                            oper[0].ref^.index.number shr 8,0);
+                        rgget(list,pos,subreg,helpreg);
+                        spill_registers:=true;
+                        op:=A_MOV;
+                        hopsize:=opsize;  {Save old value...}
+                        if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
+                          begin
+                            {Because 'movzx memory,register' does not exist...}
+                            op:=opcode;
+                            opcode:=A_MOV;
+                            opsize:=reg2opsize(oper[1].reg);
+                          end;
+                        helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0].ref^,helpreg);
+                        if pos=nil then
+                          list.insertafter(helpins,list.first)
+                        else
+                          list.insertafter(helpins,pos.next);
+                        dispose(oper[0].ref);
+                        oper[0].typ:=top_reg;
+                        oper[0].reg:=helpreg;
+                        oper[1].typ:=top_ref;
+                        new(oper[1].ref);
+                        oper[1].ref^:=spilltemplist[supreg];
+                        rgunget(list,helpins,helpreg);
+                        forward_allocation(Tai(helpins.next));
+                      end
+                    else
+                      begin
+                        {Situation example:
+                         add r20d,r21d        ; r20d must be spilled into [ebp-12]
+  
+                         Change into:
+  
+                         add [ebp-12],r21d    ; Replace register by reference }
+                        oper[1].typ:=top_ref;
+                        new(oper[1].ref);
+                        oper[1].ref^:=spilltemplist[supreg];
+                      end;
+                    {The i386 instruction set never gets boring... IMUL does
+                     not support a memory location as destination. Check if
+                     the opcode is IMUL and fix it. (DM)}
+                    if opcode=A_IMUL then
+                      begin
+                        {Yikes! We just changed the destination register into
+                         a memory location above here.
+
+                         Situation example:
+
+                         imul [ebp-12],r21d   ; We need a help register
+
+                         Change into:
+
+                         mov r22d,[ebp-12]    ; Use a help instruction (only for IMUL)
+                         imul r22d,r21d       ; Replace reference by helpregister
+                         mov [ebp-12],r22d    ; Use another help instruction}
+                        rgget(list,Tai(previous),subreg,helpreg);
+                        {First help instruction.}
+                        helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1].ref^,helpreg);
+                        if previous=nil then
+                          list.insert(helpins)
+                        else
+                          list.insertafter(helpins,previous);
+                        {Second help instruction.}
+                        helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1].ref^);
+                        dispose(oper[1].ref);
+                        oper[1].typ:=top_reg;
+                        oper[1].reg:=helpreg;
+                        list.insertafter(helpins,self);
+                      end;
+                  end;
+              end;
+            for i:=0 to 1 do
+              if oper[i].typ=top_ref then
+                begin
+                  supreg:=oper[i].ref^.base.number shr 8;
+                  if supreg in r then
+                    begin
+                      {Situation example:
+                       add r20d,[r21d+4*r22d]    ; r21d must be spilled into [ebp-12]
+
+                       Change into:
+
+                       mov r23d,[ebp-12]         ; Use a help register
+                       add r20d,[r23d+4*r22d]    ; Replace register by helpregister }
+                      subreg:=oper[i].ref^.base.number and $ff;
+                      if i=1 then
+                        pos:=get_insert_pos(Tai(previous),oper[i].ref^.index.number shr 8,oper[0].reg.number shr 8,0)
+                      else
+                        pos:=get_insert_pos(Tai(previous),oper[i].ref^.index.number shr 8,0,0);
+                      rgget(list,pos,subreg,helpreg);
+                      spill_registers:=true;
+                      helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i].ref^.base),spilltemplist[supreg],helpreg);
+                      if pos=nil then
+                        list.insertafter(helpins,list.first)
+                      else
+                        list.insertafter(helpins,pos.next);
+                      oper[i].ref^.base:=helpreg;
+                      rgunget(list,helpins,helpreg);
+                      forward_allocation(Tai(helpins.next));
+                  end;
+                  supreg:=oper[i].ref^.index.number shr 8;
+                  if supreg in r then
+                    begin
+                      {Situation example:
+                       add r20d,[r21d+4*r22d]    ; r22d must be spilled into [ebp-12]
+
+                       Change into:
+
+                       mov r23d,[ebp-12]         ; Use a help register
+                       add r20d,[r21d+4*r23d]    ; Replace register by helpregister }
+                      subreg:=oper[i].ref^.index.number and $ff;
+                      if i=1 then
+                        pos:=get_insert_pos(Tai(previous),oper[i].ref^.base.number shr 8,oper[0].reg.number shr 8,0)
+                      else
+                        pos:=get_insert_pos(Tai(previous),oper[i].ref^.base.number shr 8,0,0);
+                      rgget(list,pos,subreg,helpreg);
+                      spill_registers:=true;
+                      helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i].ref^.index),spilltemplist[supreg],helpreg);
+                      if pos=nil then
+                        list.insertafter(helpins,list.first)
+                      else
+                        list.insertafter(helpins,pos.next);
+                      oper[i].ref^.index:=helpreg;
+                      rgunget(list,helpins,helpreg);
+                      forward_allocation(Tai(helpins.next));
+                    end;
+                end;
+          end;
+        3:
+          begin
+            {$warning todo!!}
+          end;
+      end;
+    end;
 
 
 {*****************************************************************************
 {*****************************************************************************
                               Instruction table
                               Instruction table
@@ -2024,7 +2391,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.4  2003-05-30 23:57:08  peter
+  Revision 1.5  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.4  2003/05/30 23:57:08  peter
     * more sparc cleanup
     * more sparc cleanup
     * accumulator removed, splitted in function_return_reg (called) and
     * accumulator removed, splitted in function_return_reg (called) and
       function_result_reg (caller)
       function_result_reg (caller)

+ 40 - 20
compiler/x86/cgx86.pas

@@ -1800,21 +1800,33 @@ unit cgx86;
     var r,rsp:Tregister;
     var r,rsp:Tregister;
 
 
     begin
     begin
-        r.enum:=R_INTREGISTER;
-        r.number:=NR_EBP;
-        rsp.enum:=R_INTREGISTER;
-        rsp.number:=NR_ESP;
-        list.concat(Taicpu.Op_reg(A_PUSH,S_L,r));
-        list.concat(Taicpu.Op_reg_reg(A_MOV,S_L,rsp,r));
-        if localsize>0 then
-          g_stackpointer_alloc(list,localsize);
+      r.enum:=R_INTREGISTER;
+      r.number:=NR_EBP;
+    {$ifdef newra}
+      list.concat(tai_regalloc.alloc(r));
+      include(rg.savedbyproc,RS_EBP);
+    {$endif}
+      rsp.enum:=R_INTREGISTER;
+      rsp.number:=NR_ESP;
+      list.concat(Taicpu.op_reg(A_PUSH,S_L,r));
+      list.concat(Taicpu.op_reg_reg(A_MOV,S_L,rsp,r));
+      if localsize>0 then
+        g_stackpointer_alloc(list,localsize);
     end;
     end;
 
 
 
 
     procedure tcgx86.g_restore_frame_pointer(list : taasmoutput);
     procedure tcgx86.g_restore_frame_pointer(list : taasmoutput);
-      begin
-        list.concat(Taicpu.Op_none(A_LEAVE,S_NO));
-      end;
+
+    var r:Tregister;
+
+    begin
+    {$ifdef newra}
+      r.enum:=R_INTREGISTER;
+      r.number:=NR_EBP;
+      list.concat(tai_regalloc.dealloc(r));
+    {$endif}
+      list.concat(Taicpu.op_none(A_LEAVE,S_NO));
+    end;
 
 
 
 
     procedure tcgx86.g_return_from_proc(list : taasmoutput;parasize : aword);
     procedure tcgx86.g_return_from_proc(list : taasmoutput;parasize : aword);
@@ -1847,14 +1859,19 @@ unit cgx86;
     var r:Tregister;
     var r:Tregister;
 
 
     begin
     begin
-        r.enum:=R_INTREGISTER;
-        r.number:=NR_EBX;
-        if (RS_EBX in usedinproc) then
-          list.concat(Taicpu.Op_reg(A_PUSH,S_L,r));
-        r.number:=NR_ESI;
-        list.concat(Taicpu.Op_reg(A_PUSH,S_L,r));
-        r.number:=NR_EDI;
-        list.concat(Taicpu.Op_reg(A_PUSH,S_L,r));
+      r.enum:=R_INTREGISTER;
+      r.number:=NR_EBX;
+      if (RS_EBX in usedinproc) then
+        list.concat(Taicpu.op_reg(A_PUSH,S_L,r));
+      r.number:=NR_ESI;
+      list.concat(Taicpu.op_reg(A_PUSH,S_L,r));
+      r.number:=NR_EDI;
+      list.concat(Taicpu.op_reg(A_PUSH,S_L,r));
+    {$ifdef newra}
+      include(rg.savedbyproc,RS_EBX);
+      include(rg.savedbyproc,RS_ESI);
+      include(rg.savedbyproc,RS_EDI);
+    {$endif}
     end;
     end;
 
 
 
 
@@ -1936,7 +1953,10 @@ unit cgx86;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.49  2003-06-01 21:38:07  peter
+  Revision 1.50  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.49  2003/06/01 21:38:07  peter
     * getregisterfpu size parameter added
     * getregisterfpu size parameter added
     * op_const_reg size parameter added
     * op_const_reg size parameter added
     * sparc updates
     * sparc updates

+ 8 - 1
compiler/x86/cpubase.pas

@@ -170,7 +170,11 @@ uses
 
 
       {Number of first and last superregister.}
       {Number of first and last superregister.}
       first_supreg    = $01;
       first_supreg    = $01;
+{$ifdef x86_64}
       last_supreg     = $10;
       last_supreg     = $10;
+{$else}
+      last_supreg     = $08;
+{$endif}
       {Number of first and last imaginary register.}
       {Number of first and last imaginary register.}
       first_imreg     = $12;
       first_imreg     = $12;
       last_imreg      = $ff;
       last_imreg      = $ff;
@@ -712,7 +716,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2003-05-30 23:57:08  peter
+  Revision 1.6  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.5  2003/05/30 23:57:08  peter
     * more sparc cleanup
     * more sparc cleanup
     * accumulator removed, splitted in function_return_reg (called) and
     * accumulator removed, splitted in function_return_reg (called) and
       function_result_reg (caller)
       function_result_reg (caller)

+ 6 - 1
compiler/x86_64/cpubase.inc

@@ -165,6 +165,8 @@ const
       {# Stack pointer register }
       {# Stack pointer register }
       NR_STACK_POINTER_REG = NR_RSP;
       NR_STACK_POINTER_REG = NR_RSP;
       {# Frame pointer register }
       {# Frame pointer register }
+      frame_pointer_reg = R_RBP;
+      RS_FRAME_POINTER_REG = RS_EBP;
       NR_FRAME_POINTER_REG = NR_RBP;
       NR_FRAME_POINTER_REG = NR_RBP;
       { Register for addressing absolute data in a position independant way,
       { Register for addressing absolute data in a position independant way,
         such as in PIC code. The exact meaning is ABI specific. For
         such as in PIC code. The exact meaning is ABI specific. For
@@ -205,7 +207,10 @@ const
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2003-05-31 15:05:28  peter
+  Revision 1.6  2003-06-03 13:01:59  daniel
+    * Register allocator finished
+
+  Revision 1.5  2003/05/31 15:05:28  peter
     * FUNCTION_RESULT64_LOW/HIGH_REG added for int64 results
     * FUNCTION_RESULT64_LOW/HIGH_REG added for int64 results
 
 
   Revision 1.4  2003/05/30 23:57:08  peter
   Revision 1.4  2003/05/30 23:57:08  peter