Browse Source

* generic constructor working for i386
* remove fixed self register
* esi added as address register for i386

peter 22 years ago
parent
commit
c4ddcc78a8

+ 9 - 4
compiler/aoptcs.pas

@@ -99,9 +99,9 @@ End;
 Procedure TRegInfo.Clear;
 Begin
   RegsLoadedForRef   := [];
-  NewRegsEncountered := [ProcInfo.FramePointer, STACK_POINTER_REG];
-  OldRegsEncountered := [ProcInfo.FramePointer, STACK_POINTER_REG];
-  New2OldReg[ProcInfo.FramePointer] := ProcInfo.FramePointer;
+  NewRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG];
+  OldRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG];
+  New2OldReg[FRAME_POINTER_REG] := FRAME_POINTER_REG;
   New2OldReg[STACK_POINTER_REG] := STACK_POINTER_REG;
 End;
 
@@ -850,7 +850,12 @@ End.
 
 {
   $Log$
-  Revision 1.7  2002-05-18 13:34:05  peter
+  Revision 1.8  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.7  2002/05/18 13:34:05  peter
     * readded missing revisions
 
   Revision 1.6  2002/05/16 19:46:34  carl

+ 6 - 2
compiler/cg64f32.pas

@@ -138,7 +138,6 @@ unit cg64f32;
 
     procedure tcg64f32.a_load64_const_ref(list : taasmoutput;value : qword;const ref : treference);
       var
-        tmpvalue : DWord;
         tmpref: treference;
       begin
         if target_info.endian = endian_big then
@@ -752,7 +751,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.35  2003-02-19 22:00:14  daniel
+  Revision 1.36  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.35  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 12 - 1
compiler/cgbase.pas

@@ -76,6 +76,9 @@ unit cgbase;
           framepointer_offset : longint;
           {# offset from frame pointer to get self reference }
           selfpointer_offset : longint;
+          {# offset from frame pointer to get vmt reference (constructors only) }
+          inheritedflag_offset,
+          vmtpointer_offset  : longint;
           {# result value offset in stack (functions only) }
           return_offset : longint;
           {# firsttemp position }
@@ -373,11 +376,14 @@ implementation
         procdef:=nil;
         framepointer_offset:=0;
         selfpointer_offset:=0;
+        vmtpointer_offset:=0;
+        inheritedflag_offset:=0;
         return_offset:=0;
         firsttemp_offset:=0;
         para_offset:=0;
         flags:=0;
         framepointer.enum:=R_NO;
+        framepointer.number:=NR_NO;
         globalsymbol:=false;
         exported:=false;
         no_fast_exit:=false;
@@ -651,7 +657,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.37  2003-03-20 17:51:45  peter
+  Revision 1.38  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.37  2003/03/20 17:51:45  peter
     * dynamic arrays have size OS_ADDR
 
   Revision 1.36  2003/01/08 18:43:56  daniel

+ 118 - 126
compiler/cgobj.pas

@@ -302,8 +302,7 @@ unit cgobj;
           }
          procedure g_exception_reason_load(list : taasmoutput; const href : treference);virtual;
 
-
-          procedure g_maybe_loadself(list : taasmoutput);virtual;
+          function g_load_self(list : taasmoutput):tregister;
           procedure g_maybe_testself(list : taasmoutput;reg:tregister);
           procedure g_maybe_testvmt(list : taasmoutput;reg:tregister;objdef:tobjectdef);
           {# This should emit the opcode to copy len bytes from the source
@@ -506,6 +505,11 @@ unit cgobj;
     const
       max_scratch_regs = high(scratch_regs) - low(scratch_regs) + 1;
 
+      { Please leave this here, this module should NOT use
+        exprasmlist, the lists are always passed as arguments.
+        Declaring it as string here results in an error when compiling (PFV) }
+      exprasmlist = 'error';
+
 {*****************************************************************************
                             basic functionallity
 ******************************************************************************}
@@ -578,7 +582,7 @@ unit cgobj;
     procedure tcg.free_scratch_reg(list : taasmoutput;r : tregister);
 
       begin
-         if r.enum<>R_INTREGISTER then 
+         if r.enum<>R_INTREGISTER then
            internalerror(200302058);
          include(unusedscratchregisters,r.number shr 8);
          a_reg_dealloc(list,r);
@@ -670,7 +674,6 @@ unit cgobj;
     procedure tcg.a_param_copy_ref(list : taasmoutput;size : qword;const r : treference;const locpara : tparalocation);
       var
         ref : treference;
-        hr : tregister;
       begin
          if not(locpara.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
            internalerror(2003010901);
@@ -712,7 +715,7 @@ unit cgobj;
                 internalerror(200302037);
               if (dref.index.enum<>R_NO) and (dref.index.enum<>R_INTREGISTER) then
                 internalerror(200302037);
-                
+
               if (dref.base.number shr 8<>RS_EBX) and
                  (dref.index.number shr 8<>RS_EBX) then
                 pushed_reg.number:=NR_EBX
@@ -787,8 +790,6 @@ unit cgobj;
 
     procedure tcg.a_load_loc_reg(list : taasmoutput;const loc: tlocation; reg : tregister);
 
-    var r:Tregister;
-
       begin
         case loc.loc of
           LOC_REFERENCE,LOC_CREFERENCE:
@@ -1172,7 +1173,6 @@ unit cgobj;
          reference_release(list,source);
         a_param_const(list,OS_INT,len,paramanager.getintparaloc(1));
         a_call_name(list,'FPC_SHORTSTR_ASSIGN');
-        g_maybe_loadself(list);
       end;
 
 
@@ -1432,52 +1432,49 @@ unit cgobj;
       end;
 
 
-    procedure tcg.g_maybe_loadself(list : taasmoutput);
+    function tcg.g_load_self(list : taasmoutput):tregister;
       var
          hp : treference;
          p : tprocinfo;
          i : longint;
-         spr : Tregister;
+         self_reg : tregister;
       begin
-         spr.enum:=R_INTREGISTER;
-         spr.number:=NR_SELF_POINTER_REG;
-         if assigned(procinfo._class) then
+         if not assigned(procinfo._class) then
+           internalerror(200303211);
+         self_reg:=rg.getaddressregister(list);
+         if lexlevel>normal_function_level then
            begin
-              list.concat(tai_regalloc.Alloc(spr));
-              if lexlevel>normal_function_level then
-                begin
-                   reference_reset_base(hp,procinfo.framepointer,procinfo.framepointer_offset);
-                   a_load_ref_reg(list,OS_ADDR,hp,spr);
-                   p:=procinfo.parent;
-                   for i:=3 to lexlevel-1 do
-                     begin
-                        reference_reset_base(hp,spr,p.framepointer_offset);
-                        a_load_ref_reg(list,OS_ADDR,hp,spr);
-                        p:=p.parent;
-                     end;
-                   reference_reset_base(hp,spr,p.selfpointer_offset);
-                   a_load_ref_reg(list,OS_ADDR,hp,spr);
-                end
-              else
-                begin
-                   reference_reset_base(hp,procinfo.framepointer,procinfo.selfpointer_offset);
-                   a_load_ref_reg(list,OS_ADDR,hp,spr);
-                end;
+             reference_reset_base(hp,procinfo.framepointer,procinfo.framepointer_offset);
+             a_load_ref_reg(list,OS_ADDR,hp,self_reg);
+             p:=procinfo.parent;
+             for i:=3 to lexlevel-1 do
+               begin
+                  reference_reset_base(hp,self_reg,p.framepointer_offset);
+                  a_load_ref_reg(list,OS_ADDR,hp,self_reg);
+                  p:=p.parent;
+               end;
+             reference_reset_base(hp,self_reg,p.selfpointer_offset);
+             a_load_ref_reg(list,OS_ADDR,hp,self_reg);
+           end
+         else
+           begin
+             reference_reset_base(hp,procinfo.framepointer,procinfo.selfpointer_offset);
+             a_load_ref_reg(list,OS_ADDR,hp,self_reg);
            end;
+        g_load_self:=self_reg;
       end;
 
 
     procedure tcg.g_maybe_testself(list : taasmoutput;reg:tregister);
       var
         OKLabel : tasmlabel;
-        dummyloc : tparalocation;
       begin
         if (cs_check_object in aktlocalswitches) or
            (cs_check_range in aktlocalswitches) then
          begin
            objectlibrary.getlabel(oklabel);
            a_cmp_const_reg_label(list,OS_ADDR,OC_NE,0,reg,oklabel);
-           a_param_const(list,OS_INT,210,dummyloc);
+           a_param_const(list,OS_INT,210,paramanager.getintparaloc(1));
            a_call_name(list,'FPC_HANDLEERROR');
            a_label(list,oklabel);
          end;
@@ -1491,15 +1488,15 @@ unit cgobj;
         if (cs_check_object in aktlocalswitches) then
          begin
            reference_reset_symbol(hrefvmt,objectlibrary.newasmsymbol(objdef.vmt_mangledname),0);
-           a_paramaddr_ref(exprasmlist,hrefvmt,paramanager.getintparaloc(2));
-           a_param_reg(exprasmlist,OS_ADDR,reg,paramanager.getintparaloc(1));
-           a_call_name(exprasmlist,'FPC_CHECK_OBJECT_EXT');
+           a_paramaddr_ref(list,hrefvmt,paramanager.getintparaloc(2));
+           a_param_reg(list,OS_ADDR,reg,paramanager.getintparaloc(1));
+           a_call_name(list,'FPC_CHECK_OBJECT_EXT');
          end
         else
          if (cs_check_range in aktlocalswitches) then
           begin
-            a_param_reg(exprasmlist,OS_ADDR,reg,paramanager.getintparaloc(1));
-            a_call_name(exprasmlist,'FPC_CHECK_OBJECT');
+            a_param_reg(list,OS_ADDR,reg,paramanager.getintparaloc(1));
+            a_call_name(list,'FPC_CHECK_OBJECT');
           end;
       end;
 
@@ -1510,52 +1507,49 @@ unit cgobj;
 
     procedure tcg.g_call_constructor_helper(list : taasmoutput);
      var
-      href : treference;
-      hregister : tregister;
-      spr,acc : Tregister;
+       href : treference;
+       acc : Tregister;
      begin
+        if procinfo.vmtpointer_offset=0 then
+         internalerror(200303251);
+        if procinfo.selfpointer_offset=0 then
+         internalerror(200303252);
         acc.enum:=R_INTREGISTER;
         acc.number:=NR_ACCUMULATOR;
-        spr.enum:=R_INTREGISTER;
-        spr.number:=NR_SELF_POINTER_REG;
         if is_class(procinfo._class) then
           begin
             if (cs_implicit_exceptions in aktmoduleswitches) then
               procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
-            { parameter 2 : self pointer / flag }
-            {!! this is a terrible hack, normally the helper should get three params : }
-            {    one with self register, one with flag and one with VMT pointer        }
-            {reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset+POINTER_SIZE);}
-            a_param_reg(list, OS_ADDR, spr, paramanager.getintparaloc(2));
-
-            { parameter 1 : vmt pointer (stored at the selfpointer address on stack)  }
+            { parameter 2 : vmt pointer, 0 when called by inherited }
+            reference_reset_base(href, procinfo.framepointer,procinfo.vmtpointer_offset);
+            a_param_ref(list, OS_ADDR,href,paramanager.getintparaloc(1));
+            { parameter 1 : self pointer }
             reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
             a_param_ref(list, OS_ADDR,href,paramanager.getintparaloc(1));
             a_call_name(list,'FPC_NEW_CLASS');
-            a_load_reg_reg(list,OS_ADDR,OS_ADDR,acc,spr);
-            { save the self pointer result }
-            a_load_reg_ref(list,OS_ADDR,spr,href);
+            { save the self pointer }
+            reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
+            a_load_reg_ref(list,OS_ADDR,acc,href);
+            { fail? }
             a_cmp_const_reg_label(list,OS_ADDR,OC_EQ,0,acc,faillabel);
           end
         else if is_object(procinfo._class) then
           begin
-            { parameter 3 :vmt_offset     }
+            { parameter 3 : vmt_offset }
             a_param_const(list, OS_32, procinfo._class.vmt_offset, paramanager.getintparaloc(3));
-            { parameter 2 : address of pointer to vmt }
-            {  this is the first(?) parameter which was pushed to the constructor }
-            reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset-POINTER_SIZE);
-            hregister:=get_scratch_reg_address(list);
-            a_loadaddr_ref_reg(list, href, hregister);
-            a_param_reg(list, OS_ADDR,hregister,paramanager.getintparaloc(2));
-            free_scratch_reg(list, hregister);
-            { parameter 1 : address of self pointer   }
+            { parameter 2 : address of pointer to vmt,
+              this is required to allow setting the vmt to -1 to indicate
+              that memory was allocated }
+            reference_reset_base(href, procinfo.framepointer,procinfo.vmtpointer_offset);
+            a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
+            { parameter 1 : self pointer }
             reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
-            hregister:=get_scratch_reg_address(list);
-            a_loadaddr_ref_reg(list, href, hregister);
-            a_param_reg(list, OS_ADDR,hregister,paramanager.getintparaloc(1));
-            free_scratch_reg(list, hregister);
+            a_param_ref(list,OS_ADDR,href,paramanager.getintparaloc(1));
             a_call_name(list,'FPC_HELP_CONSTRUCTOR');
-            a_load_reg_reg(list,OS_ADDR,OS_ADDR,acc,spr);
+            { save the self pointer }
+            reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
+            a_load_reg_ref(list,OS_ADDR,acc,href);
+            { fail? }
             a_cmp_const_reg_label(list,OS_ADDR,OC_EQ,0,acc,faillabel);
           end
         else
@@ -1567,46 +1561,51 @@ unit cgobj;
       var
         nofinal : tasmlabel;
         href : treference;
-      hregister : tregister;
-        spr : Tregister;
-      begin
-        spr.enum:=R_INTREGISTER;
-        spr.number:=NR_SELF_POINTER_REG;
+        reg  : tregister;
+     begin
         if is_class(procinfo._class) then
          begin
-           { 2nd parameter  : flag }
-           reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset+POINTER_SIZE);
+           if procinfo.selfpointer_offset=0 then
+            internalerror(200303253);
+           { parameter 2 : flag }
+           if procinfo.inheritedflag_offset=0 then
+            internalerror(200303251);
+           reference_reset_base(href, procinfo.framepointer,procinfo.inheritedflag_offset);
            a_param_ref(list, OS_ADDR,href,paramanager.getintparaloc(2));
-           { 1st parameter to destructor : self }
+           { parameter 1 : self }
+           if procinfo.selfpointer_offset=0 then
+            internalerror(200303252);
            reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
            a_param_ref(list, OS_ADDR,href,paramanager.getintparaloc(1));
            a_call_name(list,'FPC_DISPOSE_CLASS')
          end
         else if is_object(procinfo._class) then
          begin
-           { must the object be finalized ? }
-           if procinfo._class.needs_inittable then
-            begin
-              objectlibrary.getlabel(nofinal);
-              reference_reset_base(href,procinfo.framepointer,target_info.first_parm_offset);
-              a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nofinal);
-              reference_reset_base(href,spr,0);
-              g_finalize(list,procinfo._class,href,false);
-              a_label(list,nofinal);
-            end;
-           { actually call destructor }
-            { parameter 3 :vmt_offset     }
+            if procinfo.selfpointer_offset=0 then
+             internalerror(200303254);
+            if procinfo.vmtpointer_offset=0 then
+             internalerror(200303255);
+            { must the object be finalized ? }
+            if procinfo._class.needs_inittable then
+             begin
+               objectlibrary.getlabel(nofinal);
+               reference_reset_base(href,procinfo.framepointer,target_info.first_parm_offset);
+               a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nofinal);
+               reg:=g_load_self(list);
+               reference_reset_base(href,reg,0);
+               g_finalize(list,procinfo._class,href,false);
+               reference_release(list,href);
+               a_label(list,nofinal);
+             end;
+            { actually call destructor }
+            { parameter 3 : vmt_offset }
             a_param_const(list, OS_32, procinfo._class.vmt_offset, paramanager.getintparaloc(3));
             { parameter 2 : pointer to vmt }
-            {  this is the first parameter which was pushed to the destructor }
-            reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset-POINTER_SIZE);
+            reference_reset_base(href, procinfo.framepointer,procinfo.vmtpointer_offset);
             a_param_ref(list, OS_ADDR, href ,paramanager.getintparaloc(2));
-            { parameter 1 : address of self pointer   }
+            { parameter 1 : address of self pointer }
             reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
-            hregister:=get_scratch_reg_address(list);
-            a_loadaddr_ref_reg(list, href, hregister);
-            a_param_reg(list, OS_ADDR,hregister,paramanager.getintparaloc(1));
-            free_scratch_reg(list, hregister);
+            a_param_ref(list, OS_ADDR, href ,paramanager.getintparaloc(1));
             a_call_name(list,'FPC_HELP_DESTRUCTOR');
          end
         else
@@ -1617,51 +1616,39 @@ unit cgobj;
     procedure tcg.g_call_fail_helper(list : taasmoutput);
       var
         href : treference;
-        hregister : tregister;
-        spr : Tregister;
-      begin
-        spr.enum:=R_INTREGISTER;
-        spr.number:=NR_SELF_POINTER_REG;
+     begin
         if is_class(procinfo._class) then
           begin
-            {
-              Dispose of the class then set self_pointer to nil
-              both in stack and in self register.
-            }
-            { 2nd parameter  : flag }
+            if procinfo.selfpointer_offset=0 then
+             internalerror(200303256);
+            { parameter 2 : flag, 0 -> inherited call (=no dispose) }
             a_param_const(list,OS_32,1,paramanager.getintparaloc(2));
-            { 1st parameter to destructor : self }
+            { parameter 1 : self }
             reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
             a_param_ref(list, OS_ADDR,href,paramanager.getintparaloc(1));
             a_call_name(list,'FPC_DISPOSE_CLASS');
-            { SET SELF TO NIL }
-            a_load_const_reg(list,OS_ADDR,0,spr);
-            { set the self pointer in the stack to nil }
-            a_load_reg_ref(list,OS_ADDR,spr,href);
           end
         else if is_object(procinfo._class) then
           begin
-            { parameter 3 :vmt_offset     }
+            if procinfo.selfpointer_offset=0 then
+             internalerror(200303257);
+            if procinfo.vmtpointer_offset=0 then
+             internalerror(200303258);
+            { parameter 3 : vmt_offset }
             a_param_const(list, OS_32, procinfo._class.vmt_offset, paramanager.getintparaloc(3));
-            { parameter 2 : address of pointer to vmt }
-            {  this is the first(?) parameter which was pushed to the constructor }
-            reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset-POINTER_SIZE);
-            hregister:=get_scratch_reg_address(list);
-            a_loadaddr_ref_reg(list, href, hregister);
-            a_param_reg(list, OS_ADDR,hregister,paramanager.getintparaloc(2));
-            free_scratch_reg(list, hregister);
+            { parameter 2 : address of pointer to vmt, will be reset to 0 when freed }
+            reference_reset_base(href, procinfo.framepointer,procinfo.vmtpointer_offset);
+            a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
             { parameter 1 : address of self pointer   }
             reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
-            hregister:=get_scratch_reg_address(list);
-            a_loadaddr_ref_reg(list, href, hregister);
-            a_param_reg(list, OS_ADDR,hregister,paramanager.getintparaloc(1));
-            free_scratch_reg(list, hregister);
+            a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
             a_call_name(list,'FPC_HELP_FAIL');
-            { SET SELF TO NIL }
-            a_load_const_reg(list,OS_ADDR,0,spr);
           end
         else
           internalerror(200006163);
+        { set self to nil }
+        reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
+        a_load_const_ref(list,OS_ADDR,0,href);
       end;
 
 
@@ -1732,7 +1719,12 @@ finalization
 end.
 {
   $Log$
-  Revision 1.79  2003-03-22 18:07:18  jonas
+  Revision 1.80  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.79  2003/03/22 18:07:18  jonas
     + add used scratch registers to usedintbyproc for non-i386
 
   Revision 1.78  2003/03/11 21:46:24  jonas

+ 9 - 14
compiler/i386/cpubase.pas

@@ -517,9 +517,9 @@ uses
 {$ifdef newra}
       usableregsint = [first_imreg..last_imreg];
 {$else}
-      usableregsint = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
+      usableregsint = [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI];
 {$endif}
-      c_countusableregsint = 4;
+      c_countusableregsint = 5;
 
       maxfpuregs = 8;
       fpuregs = [R_ST0..R_ST7];
@@ -537,7 +537,7 @@ uses
 
 
       firstsaveintreg = RS_EAX;
-      lastsaveintreg  = RS_EDX;
+      lastsaveintreg  = RS_ESI;
       firstsavefpureg = R_NO;
       lastsavefpureg  = R_NO;
       firstsavemmreg  = R_MM0;
@@ -604,16 +604,6 @@ uses
       {# Frame pointer register }
       frame_pointer_reg = R_EBP;
       NR_FRAME_POINTER_REG = NR_EBP;
-      {# Self pointer register : contains the instance address of an
-         object or class. }
-      self_pointer_reg  = R_ESI;
-{$ifdef newra}
-      RS_SELF_POINTER_REG  = $11;
-      NR_SELF_POINTER_REG  = $1103;
-{$else}
-      RS_SELF_POINTER_REG  = RS_ESI;
-      NR_SELF_POINTER_REG  = NR_ESI;
-{$endif}
       {# Register for addressing absolute data in a position independant way,
          such as in PIC code. The exact meaning is ABI specific. For
          further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
@@ -824,7 +814,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.44  2003-03-18 18:15:53  peter
+  Revision 1.45  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.44  2003/03/18 18:15:53  peter
     * changed reg2opsize to function
 
   Revision 1.43  2003/03/08 08:59:07  daniel

+ 14 - 11
compiler/i386/csopt386.pas

@@ -193,7 +193,7 @@ begin
     not(ref.base.enum in (rg.usableregsint+[R_EDI]));}
   isSimpleMemLoc :=
     (ref.index.enum = R_NO) and
-    not(ref.base.enum in [R_EAX,R_EBX,R_ECX,R_EDX,R_EDI]);
+    not(ref.base.enum in [R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,R_EDI]);
 end;
 
 {checks whether the current instruction sequence (starting with p) and the
@@ -277,7 +277,7 @@ var
 {    if (passedJump and not(reg.enum in (rg.usableregsint+[R_EDI]))) or
        not getLastInstruction(currentPrev,hp) then
       exit;}
-    if (passedJump and not(reg.enum in [R_EAX,R_EBX,R_ECX,R_EDX,R_EDI])) or
+    if (passedJump and not(reg.enum in [R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,R_EDI])) or
        not getLastInstruction(currentPrev,hp) then
       exit;
 
@@ -305,7 +305,7 @@ var
            { jump with a new value, since if the jump is taken, the old value }
            { is (probably) still necessary                                    }
 {           (passedJump and not(reg.enum in (rg.usableregsint+[R_EDI]))) or}
-           (passedJump and not(reg.enum in [R_EAX,R_EBX,R_ECX,R_EDX,R_EDI])) or
+           (passedJump and not(reg.enum in [R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,R_EDI])) or
            not getLastInstruction(hp,hp) then
           break;
       end;
@@ -363,8 +363,8 @@ Begin {CheckSequence}
   OrgRegResult := False;
   with startRegInfo do
     begin
-      newRegsEncountered := [procinfo.FramePointer.enum, STACK_POINTER_REG];
-      new2OldReg[procinfo.FramePointer.enum] := procinfo.FramePointer;
+      newRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG];
+      new2OldReg[FRAME_POINTER_REG].enum := FRAME_POINTER_REG;
       new2OldReg[STACK_POINTER_REG].enum := STACK_POINTER_REG;
       oldRegsEncountered := newRegsEncountered;
     end;
@@ -411,11 +411,9 @@ Begin {CheckSequence}
                     if (found <> 0) and
                        ((base.enum = R_NO) or
                         regModified[base.enum] or
-                        (base.enum = procinfo.framepointer.enum) or
-                        (assigned(procinfo._class) and (base.enum = R_ESI))) and
+                        (base.enum = procinfo.framepointer.enum)) and
                        ((index.enum = R_NO) or
-                        regModified[index.enum] or
-                        (assigned(procinfo._class) and (index.enum = R_ESI))) and
+                        regModified[index.enum]) and
                         not(regInRef(tmpReg,Taicpu(hp3).oper[0].ref^)) then
                       with pTaiprop(hp3.optinfo)^.regs[tmpreg.enum] do
                         if nrOfMods > (oldNrOfMods - found) then
@@ -1695,7 +1693,7 @@ Begin
                         if (Taicpu(p).oper[0].typ = top_reg) and
                            (Taicpu(p).oper[1].typ = top_reg) and
                            { only remove if we're not storing something in a regvar }
-                           (Taicpu(p).oper[1].reg.enum in [R_EAX,R_EBX,R_ECX,R_EDX,R_EDI]) and
+                           (Taicpu(p).oper[1].reg.enum in [R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,R_EDI]) and
 {                           (Taicpu(p).oper[1].reg.enum in (rg.usableregsint+[R_EDI])) and}
                            (Taicpu(p).opcode = A_MOV) and
                            getLastInstruction(p,hp4) and
@@ -1999,7 +1997,12 @@ End.
 
 {
   $Log$
-  Revision 1.42  2003-03-18 18:15:53  peter
+  Revision 1.43  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.42  2003/03/18 18:15:53  peter
     * changed reg2opsize to function
 
   Revision 1.41  2003/02/26 21:15:43  daniel

+ 12 - 9
compiler/i386/daopt386.pas

@@ -448,12 +448,12 @@ begin
     internalerror(200301081);
 { if not(reg.enum in rg.usableregsint) then
     exit;}
- if not(reg.enum in [R_ESI,R_EDI]) then
+ if not(reg.enum in [R_EDI]) then
     exit;
   getNoDeallocRegs(funcResRegs);
 {  funcResRegs := funcResRegs - rg.usableregsint;}
-{  funcResRegs := funcResRegs - [R_ESI,R_EDI];}
-  funcResRegs := funcResRegs - [R_EAX,R_EBX,R_ECX,R_EDX];
+{  funcResRegs := funcResRegs - [R_EDI];}
+  funcResRegs := funcResRegs - [R_EAX,R_EBX,R_ECX,R_EDX,R_ESI];
   funcResReg := reg.enum in funcResRegs;
   hp1 := p;
   while not(funcResReg and
@@ -499,7 +499,7 @@ Begin
             LabelTable^[Tai_Label(p).l.labelnr-LowLabel].TaiObj := p;
         ait_regAlloc:
           { ESI and EDI are (de)allocated manually, don't mess with them }
-          if not(tai_regalloc(p).Reg.enum in [R_EDI,R_ESI]) then
+          if not(tai_regalloc(p).Reg.enum in [R_EDI]) then
             begin
               if tai_regalloc(p).Allocation then
                 Begin
@@ -618,7 +618,7 @@ Begin
             prev.next := new_one;
             foll.previous := new_one;
             { shgould we update line information }
-            if (not (Tai(new_one).typ in SkipLineInfo)) and 
+            if (not (Tai(new_one).typ in SkipLineInfo)) and
                (not (Tai(foll).typ in SkipLineInfo)) then
             Tailineinfo(new_one).fileinfo := Tailineinfo(foll).fileinfo;
           End;
@@ -1738,9 +1738,7 @@ function isSimpleRef(const ref: treference): boolean;
 begin
   isSimpleRef :=
     assigned(ref.symbol) or
-    (ref.base.enum = procinfo.framepointer.enum) or
-    (assigned(procinfo._class) and
-     (ref.base.enum = R_ESI));
+    (ref.base.enum = procinfo.framepointer.enum);
 end;
 
 function containsPointerRef(p: Tai): boolean;
@@ -2671,7 +2669,12 @@ End.
 
 {
   $Log$
-  Revision 1.47  2003-02-26 21:15:43  daniel
+  Revision 1.48  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.47  2003/02/26 21:15:43  daniel
     * Fixed the optimizer
 
   Revision 1.46  2003/02/19 22:00:15  daniel

+ 8 - 7
compiler/i386/n386add.pas

@@ -195,8 +195,7 @@ interface
       var
         power : longint;
         hl4   : tasmlabel;
-        r:Tregister;
-        nr:Tnewregister;
+        r     : Tregister;
       begin
         { at this point, left.location.loc should be LOC_REGISTER }
         if right.location.loc=LOC_REGISTER then
@@ -399,7 +398,6 @@ interface
                         rg.saveintregvars(exprasmlist,regstopush);
                         cg.a_call_name(exprasmlist,'FPC_SHORTSTR_CONCAT');
                         tg.ungetiftemp(exprasmlist,right.location.reference);
-                        cg.g_maybe_loadself(exprasmlist);
                         rg.restoreusedintregisters(exprasmlist,pushed);
                         location_copy(location,left.location);
                      end;
@@ -415,7 +413,6 @@ interface
                        cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(1));
                        rg.saveintregvars(exprasmlist,all_intregisters);
                        cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
-                       cg.g_maybe_loadself(exprasmlist);
                        rg.restoreusedintregisters(exprasmlist,pushed);
                        location_freetemp(exprasmlist,left.location);
                        location_freetemp(exprasmlist,right.location);
@@ -1040,7 +1037,7 @@ interface
               rg.getexplicitregisterint(exprasmlist,NR_EDI);
               r.enum:=R_INTREGISTER;
               r.number:=NR_EDI;
-{$endif}            
+{$endif}
               cg64.a_load64low_loc_reg(exprasmlist,right.location,r);
               emit_reg_reg(op1,opsize,left.location.registerlow,r);
               emit_reg_reg(A_MOV,opsize,r,left.location.registerlow);
@@ -1459,7 +1456,6 @@ interface
          pushedfpu,
          mboverflow,cmpop : boolean;
          op : tasmop;
-         power : longint;
          opsize : topsize;
 
          { true, if unsigned types are compared }
@@ -1645,7 +1641,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.59  2003-03-13 19:52:23  jonas
+  Revision 1.60  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.59  2003/03/13 19:52:23  jonas
     * and more new register allocator fixes (in the i386 code generator this
       time). At least now the ppc cross compiler can compile the linux
       system unit again, but I haven't tested it.

File diff suppressed because it is too large
+ 381 - 468
compiler/i386/n386cal.pas


+ 12 - 5
compiler/i386/n386mat.pas

@@ -555,7 +555,7 @@ implementation
           { load left operators in a register }
           location_copy(location,left.location);
           location_force_reg(exprasmlist,location,OS_INT,false);
-             
+
           r2.enum:=R_INTREGISTER;
           r2.number:=NR_CL;
 
@@ -784,7 +784,7 @@ implementation
               { load left operators in a register }
               location_copy(location,left.location);
               location_force_reg(exprasmlist,location,OS_INT,false);
-              
+
               r.enum:=R_INTREGISTER;
               r.number:=NR_ECX;
               r2.enum:=R_INTREGISTER;
@@ -905,7 +905,7 @@ implementation
 
 
     procedure ti386unaryminusnode.pass_2;
-    
+
     var r:Tregister;
 
 {$ifdef SUPPORT_MMX}
@@ -1054,7 +1054,9 @@ implementation
       var
          hl : tasmlabel;
          opsize : topsize;
-         r,r2:Tregister;
+{$ifdef SUPPORT_MMX}
+         r,r2 : tregister;
+{$endif SUPPORT_MMX}
       begin
          if is_boolean(resulttype.def) then
           begin
@@ -1169,7 +1171,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.47  2003-03-08 20:36:41  daniel
+  Revision 1.48  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.47  2003/03/08 20:36:41  daniel
     + Added newra version of Ti386shlshrnode
     + Added interference graph construction code
 

+ 6 - 3
compiler/i386/n386mem.pas

@@ -77,8 +77,6 @@ implementation
 *****************************************************************************}
 
     procedure ti386derefnode.pass_2;
-      var
-        oldglobalswitches : tglobalswitches;
       begin
          inherited pass_2;
          if tpointerdef(left.resulttype.def).is_far then
@@ -156,7 +154,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.50  2003-02-19 22:00:15  daniel
+  Revision 1.51  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.50  2003/02/19 22:00:15  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 6 - 2
compiler/i386/n386opt.pas

@@ -238,7 +238,6 @@ begin
   rg.saveintregvars(exprasmlist,regstopush);
   cg.a_call_name(exprasmlist,'FPC_SHORTSTR_CONCAT');
   tg.ungetiftemp(exprasmlist,right.location.reference);
-  cg.g_maybe_loadself(exprasmlist);
   rg.restoreusedintregisters(exprasmlist,pushedregs);
   location_copy(location,left.location);
 end;
@@ -250,7 +249,12 @@ end.
 
 {
   $Log$
-  Revision 1.28  2003-02-19 22:00:15  daniel
+  Revision 1.29  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.28  2003/02/19 22:00:15  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 9 - 4
compiler/i386/popt386.pas

@@ -898,7 +898,7 @@ Begin
                 Begin
                   TmpUsedRegs := UsedRegs;
                   If (Taicpu(p).oper[1].typ = top_reg) And
-                     (Taicpu(p).oper[1].reg.enum In [R_EAX, R_EBX, R_EDX, R_EDI]) And
+                     (Taicpu(p).oper[1].reg.enum In [R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI]) And
                      GetNextInstruction(p, hp1) And
                      (Tai(hp1).typ = ait_instruction) And
                      (Taicpu(hp1).opcode = A_MOV) And
@@ -1135,9 +1135,9 @@ Begin
                                             allocRegBetween(asmL,Taicpu(p).oper[0].ref^.base,p,hp2);
                                           if (Taicpu(p).oper[0].ref^.index.enum in (rg.usableregsint+[R_EDI])) then
                                             allocRegBetween(asmL,Taicpu(p).oper[0].ref^.index,p,hp2);}
-                                          if (Taicpu(p).oper[0].ref^.base.enum in [R_ESI,R_EDI]) then
+                                          if (Taicpu(p).oper[0].ref^.base.enum in [R_EDI]) then
                                             allocRegBetween(asmL,Taicpu(p).oper[0].ref^.base,p,hp2);
-                                          if (Taicpu(p).oper[0].ref^.index.enum in [R_ESI,R_EDI]) then
+                                          if (Taicpu(p).oper[0].ref^.index.enum in [R_EDI]) then
                                             allocRegBetween(asmL,Taicpu(p).oper[0].ref^.index,p,hp2);
                                         End
                                       Else
@@ -2058,7 +2058,12 @@ End.
 
 {
   $Log$
-  Revision 1.41  2003-02-26 13:24:59  daniel
+  Revision 1.42  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.41  2003/02/26 13:24:59  daniel
     * Disabled mov reg,0 -> xor reg,reg optimization
 
   Revision 1.40  2003/02/25 07:41:54  daniel

+ 6 - 10
compiler/i386/ra386int.pas

@@ -1134,15 +1134,6 @@ Begin
                 { check if we can move the old base to the index register }
                 if (opr.ref.index.number<>NR_NO) then
                  Message(asmr_e_wrong_base_index)
-                else if assigned(procinfo._class) and
-                  (oldbase.number=NR_SELF_POINTER_REG) and
-                  (opr.ref.base.number=NR_SELF_POINTER_REG) then
-                  begin
-                    Message(asmr_w_possible_object_field_bug);
-                    { warn but accept... who knows what people
-                      caninvent in assembler ! }
-                    opr.ref.index:=oldbase;
-                  end
                 else
                  opr.ref.index:=oldbase;
               end
@@ -1980,7 +1971,12 @@ finalization
 end.
 {
   $Log$
-  Revision 1.43  2003-03-18 18:15:53  peter
+  Revision 1.44  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.43  2003/03/18 18:15:53  peter
     * changed reg2opsize to function
 
   Revision 1.42  2003/03/17 21:32:52  peter

+ 57 - 18
compiler/i386/rgcpu.pas

@@ -41,6 +41,7 @@ unit rgcpu;
           { to keep the same allocation order as with the old routines }
 {$ifndef newra}
           function getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;override;
+          function getaddressregister(list:Taasmoutput):Tregister;override;
           procedure ungetregisterint(list:Taasmoutput;r:Tregister); override;
           function getexplicitregisterint(list:Taasmoutput;r:Tnewregister):Tregister;override;
 {$endif newra}
@@ -176,7 +177,7 @@ unit rgcpu;
 
       if countunusedregsint=0 then
         internalerror(10);
-      getregisterint.enum:=R_INTREGISTER;
+      result.enum:=R_INTREGISTER;
 {$ifdef TEMPREGDEBUG}
       if curptree^.usableregsint-countunusedregsint>curptree^.registers32 then
         internalerror(10);
@@ -185,53 +186,87 @@ unit rgcpu;
       if curptree^.usableregs-countunusedregistersint>curptree^^.reallyusedregs then
         curptree^.reallyusedregs:=curptree^^.usableregs-countunusedregistersint;
 {$endif EXTTEMPREGDEBUG}
-      dec(countunusedregsint);
       if RS_EAX in unusedregsint then
         begin
+          dec(countunusedregsint);
           exclude(unusedregsint,RS_EAX);
           include(usedintinproc,RS_EAX);
-          getregisterint.number:=RS_EAX shl 8 or subreg;
+          result.number:=RS_EAX shl 8 or subreg;
 {$ifdef TEMPREGDEBUG}
           reg_user[R_EAX]:=curptree^;
 {$endif TEMPREGDEBUG}
-          exprasmlist.concat(tai_regalloc.alloc(getregisterint));
+          exprasmlist.concat(tai_regalloc.alloc(result));
         end
       else if RS_EDX in unusedregsint then
         begin
+          dec(countunusedregsint);
           exclude(unusedregsint,RS_EDX);
           include(usedintinproc,RS_EDX);
-          getregisterint.number:=RS_EDX shl 8 or subreg;
+          result.number:=RS_EDX shl 8 or subreg;
 {$ifdef TEMPREGDEBUG}
           reg_user[R_EDX]:=curptree^;
 {$endif TEMPREGDEBUG}
-          exprasmlist.concat(tai_regalloc.alloc(getregisterint));
+          exprasmlist.concat(tai_regalloc.alloc(result));
         end
       else if RS_EBX in unusedregsint then
         begin
+          dec(countunusedregsint);
           exclude(unusedregsint,RS_EBX);
           include(usedintinproc,RS_EBX);
-          getregisterint.number:=RS_EBX shl 8 or subreg;
+          result.number:=RS_EBX shl 8 or subreg;
 {$ifdef TEMPREGDEBUG}
           reg_user[R_EBX]:=curptree^;
 {$endif TEMPREGDEBUG}
-          exprasmlist.concat(tai_regalloc.alloc(getregisterint));
+          exprasmlist.concat(tai_regalloc.alloc(result));
         end
       else if RS_ECX in unusedregsint then
         begin
+          dec(countunusedregsint);
           exclude(unusedregsint,RS_ECX);
           include(usedintinproc,RS_ECX);
-          getregisterint.number:=RS_ECX shl 8 or subreg;
+          result.number:=RS_ECX shl 8 or subreg;
 {$ifdef TEMPREGDEBUG}
           reg_user[R_ECX]:=curptree^;
 {$endif TEMPREGDEBUG}
-          exprasmlist.concat(tai_regalloc.alloc(getregisterint));
+          exprasmlist.concat(tai_regalloc.alloc(result));
         end
-      else internalerror(10);
+      else
+        internalerror(10);
 {$ifdef TEMPREGDEBUG}
       testregisters;
 {$endif TEMPREGDEBUG}
     end;
 
+
+    function trgcpu.getaddressregister(list:Taasmoutput):Tregister;
+    begin
+      if countunusedregsint=0 then
+        internalerror(10);
+      result.enum:=R_INTREGISTER;
+{$ifdef TEMPREGDEBUG}
+      if curptree^.usableregsint-countunusedregsint>curptree^.registers32 then
+        internalerror(10);
+{$endif TEMPREGDEBUG}
+{$ifdef EXTTEMPREGDEBUG}
+      if curptree^.usableregs-countunusedregistersint>curptree^^.reallyusedregs then
+        curptree^.reallyusedregs:=curptree^^.usableregs-countunusedregistersint;
+{$endif EXTTEMPREGDEBUG}
+      if RS_ESI in unusedregsint then
+        begin
+          dec(countunusedregsint);
+          exclude(unusedregsint,RS_ESI);
+          include(usedintinproc,RS_ESI);
+          result.number:=NR_ESI;
+{$ifdef TEMPREGDEBUG}
+          reg_user[R_ESI]:=curptree^;
+{$endif TEMPREGDEBUG}
+          exprasmlist.concat(tai_regalloc.alloc(result));
+        end
+      else
+        result:=getregisterint(list,OS_ADDR);
+    end;
+
+
     procedure trgcpu.ungetregisterint(list: taasmoutput; r : tregister);
 
     var supreg:Tsuperregister;
@@ -242,13 +277,12 @@ unit rgcpu;
          if r.enum<>R_INTREGISTER then
             internalerror(200301234);
          supreg:=r.number shr 8;
-         if (supreg = RS_EDI) or
-            ((not assigned(procinfo._class)) and (supreg = RS_ESI)) then
+         if (supreg in [RS_EDI]) then
            begin
              list.concat(tai_regalloc.DeAlloc(r));
              exit;
            end;
-         if not(supreg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX]) then
+         if not(supreg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI]) then
            exit;
          inherited ungetregisterint(list,r);
       end;
@@ -259,7 +293,7 @@ unit rgcpu;
    var r2:Tregister;
 
     begin
-      if (r shr 8) in [RS_ESI,RS_EDI] then
+      if (r shr 8) in [RS_EDI] then
         begin
           r2.enum:=R_INTREGISTER;
           r2.number:=r;
@@ -308,7 +342,7 @@ unit rgcpu;
 
     begin
       usedintinproc:=usedintinproc+s;
-      for r:=RS_EAX to RS_EDX do
+      for r:=firstsaveintreg to lastsaveintreg do
         begin
           r2.enum:=R_INTREGISTER;
           r2.number:=r shl 8 or R_SUBWHOLE;
@@ -373,7 +407,7 @@ unit rgcpu;
         r2:Tregister;
     begin
       { restore in reverse order: }
-      for r:=RS_EDX downto RS_EAX do
+      for r:=lastsaveintreg downto firstsaveintreg do
         if pushed[r].pushed then
           begin
             r2.enum:=R_INTREGISTER;
@@ -525,7 +559,12 @@ end.
 
 {
   $Log$
-  Revision 1.16  2003-03-17 15:52:57  peter
+  Revision 1.17  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.16  2003/03/17 15:52:57  peter
     * SUPPORT_MMX define compile fix
 
   Revision 1.15  2003/03/08 13:59:17  daniel

+ 8 - 3
compiler/i386/rropt386.pas

@@ -333,8 +333,8 @@ begin
                      (Taicpu(p).opsize = S_L) and
 {                     (Taicpu(p).oper[0].reg.enum in (rg.usableregsint+[R_EDI])) and
                      (Taicpu(p).oper[1].reg.enum in (rg.usableregsint+[R_EDI])) then}
-                     (Taicpu(p).oper[0].reg.enum in ([R_ESI,R_EDI])) and
-                     (Taicpu(p).oper[1].reg.enum in ([R_ESI,R_EDI])) then
+                     (Taicpu(p).oper[0].reg.enum in ([R_EDI])) and
+                     (Taicpu(p).oper[1].reg.enum in ([R_EDI])) then
                     if switchRegs(asml,Taicpu(p).oper[0].reg,
                          Taicpu(p).oper[1].reg,p) then
                       begin
@@ -358,7 +358,12 @@ End.
 
 {
   $Log$
-  Revision 1.20  2003-02-19 22:00:16  daniel
+  Revision 1.21  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.20  2003/02/19 22:00:16  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 6 - 3
compiler/ncgbas.pas

@@ -209,8 +209,6 @@ interface
              else
                exprasmList.concatlist(p_asm);
            end;
-         if not (nf_object_preserved in flags) then
-           cg.g_maybe_loadself(exprasmlist);
        end;
 
 
@@ -290,7 +288,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.28  2002-11-27 15:33:19  peter
+  Revision 1.29  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.28  2002/11/27 15:33:19  peter
     * fixed relabeling to relabel only tasmlabel (formerly proclocal)
 
   Revision 1.27  2002/11/27 02:37:13  peter

+ 23 - 31
compiler/ncgcal.pas

@@ -44,11 +44,11 @@ interface
           funcretref : treference;
           refcountedtemp : treference;
           procedure handle_return_value(inlined,extended_new:boolean);
-          {# This routine is used to push the current frame pointer 
+          {# This routine is used to push the current frame pointer
              on the stack. This is used in nested routines where the
              value of the frame pointer is always pushed as an extra
              parameter.
-             
+
              The default handling is the standard handling used on
              most stack based machines, where the frame pointer is
              the first invisible parameter.
@@ -104,7 +104,7 @@ implementation
             begin
               secondpass(hightree);
               { this is a longint anyway ! }
-              push_value_para(hightree,calloption,para_offset,4,paraitem.paraloc);
+              push_value_para(exprasmlist,hightree,calloption,para_offset,4,paraitem.paraloc);
             end;
         end;
 {$endif VS_HIDDEN}
@@ -143,7 +143,7 @@ implementation
                  location_release(exprasmlist,left.location);
                end
              else
-               push_value_para(left,calloption,para_offset,para_alignment,paraitem.paraloc);
+               push_value_para(exprasmlist,left,calloption,para_offset,para_alignment,paraitem.paraloc);
            end
          { filter array constructor with c styled args }
          else if is_array_constructor(left.resulttype.def) and (nf_cargs in left.flags) then
@@ -296,7 +296,7 @@ implementation
                 end
               else
                 begin
-                   push_value_para(left,calloption,
+                   push_value_para(exprasmlist,left,calloption,
                      para_offset,para_alignment,paraitem.paraloc);
                 end;
            end;
@@ -331,12 +331,12 @@ implementation
          emit_reg(A_PUSH,S_L,r);
 {$endif i386}
       end;
-      
-      
+
+
       procedure tcgcallnode.load_framepointer;
         var href : treference;
             hregister : tregister;
-            i: integer; 
+            i: integer;
         begin
           { this routine is itself not nested }
           if lexlevel=(tprocdef(procdefinition).parast.symtablelevel) then
@@ -349,7 +349,7 @@ implementation
             begin
               cg.a_param_reg(exprasmlist,OS_ADDR,procinfo.framepointer,paramanager.getintparaloc(1));
             end
-          { very complex nesting level ... }  
+          { very complex nesting level ... }
           else if (lexlevel>(tprocdef(procdefinition).parast.symtablelevel)) then
             begin
               hregister:=rg.getaddressregister(exprasmlist);
@@ -364,7 +364,7 @@ implementation
               rg.ungetaddressregister(exprasmlist,hregister);
             end;
         end;
-      
+
 
 
 
@@ -403,24 +403,11 @@ implementation
               orddef :
                 begin
                   cgsize:=def_cgsize(resulttype.def);
-                  { an object constructor is a function with boolean result }
+
+                  { an object constructor is a function with pointer result }
                   if (inlined or (right=nil)) and
                      (procdefinition.proctypeoption=potype_constructor) then
-                   begin
-{$ifdef x86}
-                     if extended_new then
-                      cgsize:=OS_INT
-                     else
-                      begin
-                        cgsize:=OS_NO;
-                        { this fails if popsize > 0 PM }
-                        location_reset(location,LOC_FLAGS,OS_NO);
-                        location.resflags:=F_NE;
-                      end;
-{$else x86}
-                     cgsize:=OS_INT
-{$endif x86}
-                   end;
+                    cgsize:=OS_ADDR;
 
                   if cgsize<>OS_NO then
                    begin
@@ -1130,7 +1117,6 @@ implementation
                           Internalerror(200006165);
                      end;
                 end;
-{$endif dummy}
 
                 { call to BeforeDestruction? }
                 if (procdefinition.proctypeoption=potype_destructor) and
@@ -1150,6 +1136,8 @@ implementation
                      cg.a_call_ref(exprasmlist,href);
                      cg.free_scratch_reg(exprasmlist,tmpreg);
                   end;
+{$endif dummy}
+
 {$ifndef SPARC}{We don't need that on SPARC arch!}
               { push base pointer ?}
               { never when inlining, since if necessary, the base pointer }
@@ -1364,6 +1352,7 @@ implementation
               cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,r,faillabel);
            end;
 
+{$ifdef dummy}
          { call to AfterConstruction? }
          if is_class(resulttype.def) and
            (inlined or
@@ -1389,6 +1378,7 @@ implementation
               cg.a_label(exprasmlist,constructorfailed);
               cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,r,r2);
            end;
+{$endif dummy}
 
          { handle function results }
          if (not is_void(resulttype.def)) then
@@ -1413,9 +1403,6 @@ implementation
          rg.restoreusedotherregisters(exprasmlist,pushed);
          rg.restoreusedintregisters(exprasmlist,pushedint);
 
-         { at last, restore instance pointer (SELF) }
-         if loadesi then
-           cg.g_maybe_loadself(exprasmlist);
          pp:=tbinarynode(params);
          while assigned(pp) do
            begin
@@ -1666,7 +1653,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.40  2003-03-06 11:35:50  daniel
+  Revision 1.41  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.40  2003/03/06 11:35:50  daniel
     * Fixed internalerror 7843 issue
 
   Revision 1.39  2003/02/19 22:00:14  daniel

+ 8 - 2
compiler/ncgcnv.pas

@@ -76,7 +76,8 @@ interface
     procedure tcgtypeconvnode.second_int_to_int;
       var
         newsize : tcgsize;
-        ressize, leftsize: cardinal;
+        ressize,
+        leftsize : longint;
       begin
         newsize:=def_cgsize(resulttype.def);
 
@@ -510,7 +511,12 @@ end.
 
 {
   $Log$
-  Revision 1.36  2003-02-19 22:00:14  daniel
+  Revision 1.37  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.36  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 11 - 11
compiler/ncgflw.pas

@@ -327,9 +327,9 @@ implementation
          { first set the to value
            because the count var can be in the expression !! }
          rg.cleartempgen;
-         
+
          do_loopvar_at_end:=lnf_dont_mind_loopvar_on_exit in loopflags;
-         
+
          secondpass(right);
          { calculate pointer value and check if changeable and if so }
          { load into temporary variable                       }
@@ -384,7 +384,7 @@ implementation
                    t2.location,aktbreaklabel);
                end;
            end;
-           
+
          {If the loopvar doesn't mind on exit, we avoid this ugly
           dec instruction and do the loopvar inc/dec after the loop
           body.}
@@ -718,10 +718,10 @@ implementation
                         { get an 8-bit register }
                         allocated_acc := true;
                         cg.a_label(exprasmlist,truelabel);
-                        cg.a_load_const_reg(exprasmlist,OS_8,1,hreg);
+                        cg.a_load_const_reg(exprasmlist,OS_8,1,r);
                         cg.a_jmp_always(exprasmlist,aktexit2label);
                         cg.a_label(exprasmlist,falselabel);
-                        cg.a_load_const_reg(exprasmlist,OS_8,0,hreg);
+                        cg.a_load_const_reg(exprasmlist,OS_8,0,r);
                         goto do_jmp;
                       end;
                   end;
@@ -880,7 +880,6 @@ implementation
 
       var
          a : tasmlabel;
-         href : treference;
          href2: treference;
          r:Tregister;
       begin
@@ -974,7 +973,6 @@ implementation
          r.number:=NR_ACCUMULATOR;
          cg.a_param_reg(exprasmlist,OS_ADDR,r,paramanager.getintparaloc(1));
          cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
-         cg.g_maybe_loadself(exprasmlist);
       end;
 
 
@@ -1084,7 +1082,6 @@ implementation
               }
               cg.a_param_const(exprasmlist,OS_ADDR,aword(-1),paramanager.getintparaloc(1));
               cg.a_call_name(exprasmlist,'FPC_CATCHES');
-              cg.g_maybe_loadself(exprasmlist);
 
               { the destruction of the exception object must be also }
               { guarded by an exception frame                        }
@@ -1267,8 +1264,6 @@ implementation
                  aktbreaklabel:=breakonlabel;
                end;
 
-              { esi is destroyed by FPC_CATCHES }
-              cg.g_maybe_loadself(exprasmlist);
               secondpass(right);
            end;
          objectlibrary.getlabel(doobjectdestroy);
@@ -1488,7 +1483,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.51  2003-02-19 22:00:14  daniel
+  Revision 1.52  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.51  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 6 - 5
compiler/ncginl.pas

@@ -73,8 +73,6 @@ implementation
 
     procedure tcginlinenode.pass_2;
        var
-         asmop : tasmop;
-         l : longint;
          oldpushedparasize : longint;
       begin
          { save & reset pushedparasize }
@@ -456,9 +454,7 @@ implementation
 *****************************************************************************}
       procedure tcginlinenode.second_IncludeExclude;
         var
-         scratch_reg : boolean;
          hregister : tregister;
-         asmop : tasmop;
          L : longint;
          pushedregs : TMaybesave;
          cgop : topcg;
@@ -650,7 +646,12 @@ end.
 
 {
   $Log$
-  Revision 1.21  2003-02-19 22:00:14  daniel
+  Revision 1.22  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.21  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 9 - 6
compiler/ncgld.pas

@@ -66,7 +66,6 @@ implementation
 
     procedure tcgloadnode.pass_2;
       var
-        intreg,
         r,hregister : tregister;
         supreg:Tsuperregister;
         symtabletype : tsymtabletype;
@@ -252,9 +251,7 @@ implementation
                                      location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname)
                                    else
                                      begin
-                                        rg.getexplicitregisterint(exprasmlist,NR_SELF_POINTER_REG);
-                                        location.reference.base.enum:=R_INTREGISTER;
-                                        location.reference.base.number:=NR_SELF_POINTER_REG;
+                                        location.reference.base:=cg.g_load_self(exprasmlist);
                                         location.reference.offset:=tvarsym(symtableentry).address;
                                      end;
                                 end;
@@ -427,6 +424,7 @@ implementation
         { Try to determine which side to calculate first,  }
         if (right.location.loc<>LOC_FLAGS) and
            ((right.location.loc=LOC_JUMP) or
+            (right.nodetype=calln) or
             (right.registers32>=left.registers32)) then
          begin
            secondpass(right);
@@ -898,7 +896,7 @@ implementation
                      end
                     else
                       if vtype in [vtInt64,vtQword,vtExtended] then
-                        push_value_para(hp.left,pocall_cdecl,0,4,paralocdummy)
+                        push_value_para(exprasmlist,hp.left,pocall_cdecl,0,4,paralocdummy)
                     else
                       begin
                         cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
@@ -972,7 +970,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.45  2003-02-19 22:00:14  daniel
+  Revision 1.46  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.45  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 7 - 6
compiler/ncgmat.pas

@@ -249,13 +249,11 @@ implementation
     procedure tcgmoddivnode.pass_2;
       var
          hreg1 : tregister;
-         hdenom,hnumerator : tregister;
-         shrdiv,popeax,popedx : boolean;
+         hdenom : tregister;
          power : longint;
          hl : tasmlabel;
          pushedregs : tmaybesave;
       begin
-         shrdiv := false;
          secondpass(left);
          if codegenerror then
           exit;
@@ -288,7 +286,6 @@ implementation
                  (right.nodetype=ordconstn) and
                  ispowerof2(tordconstnode(right).value,power) then
                 Begin
-                  shrdiv := true;
                   { for signed numbers, the numerator must be adjusted before the
                     shift instruction, but not wih unsigned numbers! Otherwise,
                     "Cardinal($ffffffff) div 16" overflows! (JM) }
@@ -348,7 +345,6 @@ implementation
       var
          hcountreg : tregister;
          op : topcg;
-         l1,l2,l3 : tasmlabel;
          pushedregs : tmaybesave;
          freescratch : boolean;
       begin
@@ -454,7 +450,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.6  2003-02-19 22:00:14  daniel
+  Revision 1.7  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.6  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 9 - 10
compiler/ncgmem.pas

@@ -347,18 +347,17 @@ implementation
 
     procedure tcgselfnode.pass_2;
       begin
-         rg.getexplicitregisterint(exprasmlist,NR_SELF_POINTER_REG);
          if (resulttype.def.deftype=classrefdef) or
             (is_class(resulttype.def) or
              (po_staticmethod in aktprocdef.procoptions)) then
           begin
-            location_reset(location,LOC_CREGISTER,OS_ADDR);
-            location.register.number:=NR_SELF_POINTER_REG;
+            location_reset(location,LOC_REGISTER,OS_ADDR);
+            location.register:=cg.g_load_self(exprasmlist);
           end
          else
            begin
              location_reset(location,LOC_CREFERENCE,OS_ADDR);
-             location.reference.base.number:=NR_SELF_POINTER_REG;
+             location.reference.base:=cg.g_load_self(exprasmlist);
            end;
       end;
 
@@ -608,7 +607,6 @@ implementation
                rg.saveintregvars(exprasmlist,all_intregisters);
                cg.a_call_name(exprasmlist,'FPC_DYNARRAY_RANGECHECK');
                rg.restoreusedintregisters(exprasmlist,pushed);
-               cg.g_maybe_loadself(exprasmlist);
             end
          else
            cg.g_rangecheck(exprasmlist,right,left.resulttype.def);
@@ -648,7 +646,6 @@ implementation
                    cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(1));
                    rg.saveintregvars(exprasmlist,all_intregisters);
                    cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_UNIQUE');
-                   cg.g_maybe_loadself(exprasmlist);
                    rg.restoreusedintregisters(exprasmlist,pushed);
                 end;
 
@@ -675,7 +672,6 @@ implementation
                    cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
                    rg.saveintregvars(exprasmlist,all_intregisters);
                    cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
-                   cg.g_maybe_loadself(exprasmlist);
                    rg.restoreusedintregisters(exprasmlist,pushed);
                 end;
 
@@ -756,7 +752,6 @@ implementation
                               rg.saveintregvars(exprasmlist,all_intregisters);
                               cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
                               rg.restoreusedintregisters(exprasmlist,pushed);
-                              cg.g_maybe_loadself(exprasmlist);
                            end;
 
                          st_shortstring:
@@ -888,7 +883,6 @@ implementation
                               rg.saveintregvars(exprasmlist,all_intregisters);
                               cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
                               rg.restoreusedintregisters(exprasmlist,pushed);
-                              cg.g_maybe_loadself(exprasmlist);
                            end;
                          st_shortstring:
                            begin
@@ -925,7 +919,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.43  2003-03-12 22:43:38  jonas
+  Revision 1.44  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.43  2003/03/12 22:43:38  jonas
     * more powerpc and generic fixes related to the new register allocator
 
   Revision 1.42  2003/02/19 22:00:14  daniel

+ 77 - 103
compiler/ncgutil.pas

@@ -56,7 +56,7 @@ interface
     procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
     function  maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
 
-    procedure push_value_para(p:tnode;calloption:tproccalloption;
+    procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption;
                               para_offset:longint;alignment : longint;
                               const locpara : tparalocation);
 
@@ -109,6 +109,13 @@ implementation
     tgobj,cgobj,cgcpu;
 
 
+  const
+    { Please leave this here, this module should NOT use
+      exprasmlist, the lists are always passed as arguments.
+      Declaring it as string here results in an error when compiling (PFV) }
+    exprasmlist = 'error';
+
+
 {*****************************************************************************
                                   Misc Helpers
 *****************************************************************************}
@@ -570,7 +577,7 @@ implementation
             begin
               tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
               cg.a_loadfpu_reg_ref(list,l.size,l.register,r);
-              location_release(exprasmlist,l);
+              location_release(list,l);
               location_reset(l,LOC_REFERENCE,l.size);
               l.reference:=r;
             end;
@@ -583,7 +590,7 @@ implementation
                cg64.a_load64_loc_ref(list,l,r)
               else
                cg.a_load_loc_ref(list,l,r);
-              location_release(exprasmlist,l);
+              location_release(list,l);
               location_reset(l,LOC_REFERENCE,l.size);
               l.reference:=r;
 
@@ -616,16 +623,16 @@ implementation
 {$ifndef cpu64bit}
                  if l.size in [OS_64,OS_S64] then
                   begin
-                    tg.GetTemp(exprasmlist,8,tt_normal,s.ref);
-                    cg64.a_load64_reg_ref(exprasmlist,joinreg64(l.registerlow,l.registerhigh),s.ref);
+                    tg.GetTemp(list,8,tt_normal,s.ref);
+                    cg64.a_load64_reg_ref(list,joinreg64(l.registerlow,l.registerhigh),s.ref);
                   end
                  else
 {$endif cpu64bit}
                   begin
-                    tg.GetTemp(exprasmlist,TCGSize2Size[l.size],tt_normal,s.ref);
-                    cg.a_load_reg_ref(exprasmlist,l.size,l.register,s.ref);
+                    tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,s.ref);
+                    cg.a_load_reg_ref(list,l.size,l.register,s.ref);
                   end;
-                 location_release(exprasmlist,l);
+                 location_release(list,l);
                  s.saved:=true;
                end;
              LOC_REFERENCE,
@@ -652,10 +659,10 @@ implementation
                        reference_reset_base(l.reference,l.reference.base,0);
                      end;
                     { save base register }
-                    tg.GetTemp(exprasmlist,TCGSize2Size[OS_ADDR],tt_normal,s.ref);
-                    cg.a_load_reg_ref(exprasmlist,OS_ADDR,l.reference.base,s.ref);
+                    tg.GetTemp(list,TCGSize2Size[OS_ADDR],tt_normal,s.ref);
+                    cg.a_load_reg_ref(list,OS_ADDR,l.reference.base,s.ref);
                     { release }
-                    location_release(exprasmlist,l);
+                    location_release(list,l);
                     s.saved:=true;
                   end;
                end;
@@ -679,26 +686,26 @@ implementation
 {$ifndef cpu64bit}
               if l.size in [OS_64,OS_S64] then
                begin
-                 l.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
-                 l.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
-                 cg64.a_load64_ref_reg(exprasmlist,s.ref,joinreg64(l.registerlow,l.registerhigh));
+                 l.registerlow:=rg.getregisterint(list,OS_INT);
+                 l.registerhigh:=rg.getregisterint(list,OS_INT);
+                 cg64.a_load64_ref_reg(list,s.ref,joinreg64(l.registerlow,l.registerhigh));
                end
               else
 {$endif cpu64bit}
                begin
-                 l.register:=rg.getregisterint(exprasmlist,OS_INT);
-                 cg.a_load_ref_reg(exprasmlist,OS_INT,s.ref,l.register);
+                 l.register:=rg.getregisterint(list,OS_INT);
+                 cg.a_load_ref_reg(list,OS_INT,s.ref,l.register);
                end;
             end;
           LOC_CREFERENCE,
           LOC_REFERENCE :
             begin
               reference_reset(l.reference);
-              l.reference.base:=rg.getaddressregister(exprasmlist);
-              cg.a_load_ref_reg(exprasmlist,OS_ADDR,s.ref,l.reference.base);
+              l.reference.base:=rg.getaddressregister(list);
+              cg.a_load_ref_reg(list,OS_ADDR,s.ref,l.reference.base);
             end;
         end;
-        tg.ungetiftemp(exprasmlist,s.ref);
+        tg.ungetiftemp(list,s.ref);
       end;
 
 
@@ -719,7 +726,7 @@ implementation
                                 Push Value Para
 *****************************************************************************}
 
-    procedure push_value_para(p:tnode;calloption:tproccalloption;
+    procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption;
                               para_offset:longint;alignment : longint;
                               const locpara : tparalocation);
       var
@@ -737,7 +744,7 @@ implementation
 
         { Move flags and jump in register to make it less complex }
         if p.location.loc in [LOC_FLAGS,LOC_JUMP] then
-         location_force_reg(exprasmlist,p.location,def_cgsize(p.resulttype.def),false);
+         location_force_reg(list,p.location,def_cgsize(p.resulttype.def),false);
 
         { Handle Floating point types differently }
         if p.resulttype.def.deftype=floatdef then
@@ -751,11 +758,11 @@ implementation
                   inc(pushedparasize,size);
 
                   if calloption<>pocall_inline then
-                   cg.g_stackpointer_alloc(exprasmlist,size);
+                   cg.g_stackpointer_alloc(list,size);
 {$ifdef GDB}
                   if (cs_debuginfo in aktmoduleswitches) and
-                     (exprasmList.first=exprasmList.last) then
-                    exprasmList.concat(Tai_force_line.Create);
+                     (list.first=list.last) then
+                    list.concat(Tai_force_line.Create);
 {$endif GDB}
 
                   { this is the easiest case for inlined !! }
@@ -765,10 +772,10 @@ implementation
                   else
                    reference_reset_base(href,r,0);
 
-                  cg.a_loadfpu_reg_ref(exprasmlist,
+                  cg.a_loadfpu_reg_ref(list,
                     def_cgsize(p.resulttype.def),p.location.register,href);
 {$else i386}
-                  cg.a_paramfpu_reg(exprasmlist,def_cgsize(p.resulttype.def),p.location.register,locpara);
+                  cg.a_paramfpu_reg(list,def_cgsize(p.resulttype.def),p.location.register,locpara);
 {$endif i386}
 
                end;
@@ -797,16 +804,16 @@ implementation
                     if calloption=pocall_inline then
                      begin
                        reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
-                       cg.a_load_ref_ref(exprasmlist,cgsize,tempreference,href);
+                       cg.a_load_ref_ref(list,cgsize,tempreference,href);
                      end
                     else
-                     cg.a_param_ref(exprasmlist,cgsize,tempreference,locpara);
+                     cg.a_param_ref(list,cgsize,tempreference,locpara);
                   end;
                end;
              else
                internalerror(200204243);
            end;
-           location_release(exprasmlist,p.location);
+           location_release(list,p.location);
          end
         else
          begin
@@ -819,13 +826,13 @@ implementation
               { push on stack }
               size:=align(p.resulttype.def.size,alignment);
               inc(pushedparasize,size);
-              cg.g_stackpointer_alloc(exprasmlist,size);
+              cg.g_stackpointer_alloc(list,size);
               r.enum:=R_INTREGISTER;
               r.number:=NR_STACK_POINTER_REG;
               reference_reset_base(href,r,0);
-              cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false);
+              cg.g_concatcopy(list,p.location.reference,href,size,false,false);
 {$else i386}
-              cg.a_param_copy_ref(exprasmlist,p.resulttype.def.size,p.location.reference,locpara);
+              cg.a_param_copy_ref(list,p.resulttype.def.size,p.location.reference,locpara);
 {$endif i386}
             end
            else
@@ -847,13 +854,13 @@ implementation
                           if p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
                             begin
                               size:=align(p.resulttype.def.size,alignment);
-                              cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false)
+                              cg.g_concatcopy(list,p.location.reference,href,size,false,false)
                             end
                           else
-                            cg64.a_load64_loc_ref(exprasmlist,p.location,href);
+                            cg64.a_load64_loc_ref(list,p.location,href);
                         end
                        else
-                        cg64.a_param64_loc(exprasmlist,p.location,locpara);
+                        cg64.a_param64_loc(list,p.location,locpara);
                      end
                     else
                      begin
@@ -886,18 +893,18 @@ implementation
                           if p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
                             begin
                               size:=align(p.resulttype.def.size,alignment);
-                              cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false)
+                              cg.g_concatcopy(list,p.location.reference,href,size,false,false)
                             end
                           else
-                            cg.a_load_loc_ref(exprasmlist,p.location,href);
+                            cg.a_load_loc_ref(list,p.location,href);
                         end
                        else
-                        cg.a_param_loc(exprasmlist,p.location,locpara);
+                        cg.a_param_loc(list,p.location,locpara);
                        { restore old register }
                        if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
                          p.location.register:=hreg;
                      end;
-                    location_release(exprasmlist,p.location);
+                    location_release(list,p.location);
                   end;
 {$ifdef SUPPORT_MMX}
                 LOC_MMXREGISTER,
@@ -907,10 +914,10 @@ implementation
                      if calloption=pocall_inline then
                        begin
                           reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
-                          cg.a_loadmm_reg_ref(exprasmlist,p.location.register,href);
+                          cg.a_loadmm_reg_ref(list,p.location.register,href);
                        end
                      else
-                      cg.a_parammm_reg(exprasmlist,p.location.register);
+                      cg.a_parammm_reg(list,p.location.register);
                   end;
 {$endif SUPPORT_MMX}
                 else
@@ -1302,8 +1309,6 @@ function returns in a register and the caller receives it in an other one}
         stackalloclist : taasmoutput;
         hp : tparaitem;
         paraloc : tparalocation;
-        r:Tregister;
-
       begin
         if not inlined then
            stackalloclist:=taasmoutput.Create;
@@ -1313,7 +1318,6 @@ function returns in a register and the caller receives it in an other one}
           code, since temp. allocation might occur before - carl
         }
 
-
         { for the save all registers we can simply use a pusha,popa which
           push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
         if (po_saveregisters in aktprocdef.procoptions) then
@@ -1327,9 +1331,9 @@ function returns in a register and the caller receives it in an other one}
           therefore if the context must be saved, do it before
           the actual call to the profile code
         }
-        if (cs_profile in aktmoduleswitches)
-         and not(po_assembler in aktprocdef.procoptions)
-         and not(inlined) then
+        if (cs_profile in aktmoduleswitches) and
+           not(po_assembler in aktprocdef.procoptions) and
+           not(inlined) then
           begin
             { non-win32 can call mcout even in main }
             if not (target_info.system in [system_i386_win32,system_i386_wdosx])  then
@@ -1340,30 +1344,11 @@ function returns in a register and the caller receives it in an other one}
               cg.g_profilecode(list);
           end;
 
-
         { a constructor needs a help procedure }
         if (aktprocdef.proctypeoption=potype_constructor) then
-          cg.g_call_constructor_helper(list);
-
-        { don't load ESI, does the caller }
-        { we must do it for local function }
-        { that can be called from a foreach_static }
-        { of another object than self !! PM }
-        if assigned(procinfo._class) and  { !!!!! shouldn't we load ESI always? }
-           (lexlevel>normal_function_level) then
-         cg.g_maybe_loadself(list);
-
-        { When message method contains self as a parameter,
-          we must load it into ESI }
-        If (po_containsself in aktprocdef.procoptions) then
-          begin
-             r.enum:=R_INTREGISTER;
-             r.number:=NR_SELF_POINTER_REG;
-             list.concat(tai_regalloc.Alloc(r));
-             reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
-             cg.a_load_ref_reg(list,OS_ADDR,href,r);
-          end;
-
+         begin
+           cg.g_call_constructor_helper(list);
+         end;
 
         if not is_void(aktprocdef.rettype.def) then
           begin
@@ -1398,7 +1383,7 @@ function returns in a register and the caller receives it in an other one}
                end;
           end;
 
-        { initialisize local data like ansistrings }
+        { initialize local data like ansistrings }
         case aktprocdef.proctypeoption of
            potype_unitinit:
              begin
@@ -1502,8 +1487,6 @@ function returns in a register and the caller receives it in an other one}
               new_exception(list,procinfo.exception_jmp_ref,
                   procinfo.exception_env_ref,
                   procinfo.exception_result_ref,1,aktexitlabel);
-              { probably we've to reload self here }
-              cg.g_maybe_loadself(list);
             end;
 
 {$ifdef GDB}
@@ -1615,13 +1598,12 @@ function returns in a register and the caller receives it in an other one}
 {$endif GDB}
         okexitlabel,
         noreraiselabel,nodestroycall : tasmlabel;
-        tmpreg : tregister;
         href : treference;
         usesacc,
         usesacchi,
         usesself,usesfpu : boolean;
         pd : tprocdef;
-        r,r2:Tregister;
+        r  : Tregister;
       begin
         if aktexit2label.is_used and
            ((procinfo.flags and (pi_needs_implicit_finally or pi_uses_exceptions)) <> 0) then
@@ -1694,8 +1676,7 @@ function returns in a register and the caller receives it in an other one}
                             objectlibrary.getlabel(nodestroycall);
                             reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
                             cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nodestroycall);
-                            r.enum:=R_INTREGISTER;
-                            r.number:=NR_SELF_POINTER_REG;
+                            r:=cg.g_load_self(list);
                             if is_class(procinfo._class) then
                              begin
                                cg.a_param_const(list,OS_INT,1,paramanager.getintparaloc(2));
@@ -1712,14 +1693,13 @@ function returns in a register and the caller receives it in an other one}
                             if (po_virtualmethod in pd.procoptions) then
                              begin
                                reference_reset_base(href,r,0);
-                               tmpreg:=cg.get_scratch_reg_address(list);
-                               cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
-                               reference_reset_base(href,tmpreg,procinfo._class.vmtmethodoffset(pd.extnumber));
-                               cg.free_scratch_reg(list,tmpreg);
+                               cg.a_load_ref_reg(list,OS_ADDR,href,r);
+                               reference_reset_base(href,r,procinfo._class.vmtmethodoffset(pd.extnumber));
                                cg.a_call_ref(list,href);
                              end
                             else
                              cg.a_call_name(list,pd.mangledname);
+                            rg.ungetregisterint(list,r);
                             { not necessary because the result is never assigned in the
                               case of an exception (FK) }
                             cg.a_label(list,nodestroycall);
@@ -1770,30 +1750,18 @@ function returns in a register and the caller receives it in an other one}
                 { eax must be set to zero if the allocation failed !!! }
                 objectlibrary.getlabel(okexitlabel);
                 cg.a_jmp_always(list,okexitlabel);
+                { fail }
                 cg.a_label(list,faillabel);
                 cg.g_call_fail_helper(list);
+                { return the self pointer }
                 cg.a_label(list,okexitlabel);
-
-                { for classes this is done after the call to }
-                { AfterConstruction                          }
-                if is_object(procinfo._class) then
-                  begin
-                    r.enum:=R_INTREGISTER;
-                    r.number:=NR_SELF_POINTER_REG;
-                    r2.enum:=R_INTREGISTER;
-                    r2.number:=NR_ACCUMULATOR;
-                    cg.a_reg_alloc(list,r2);
-                    cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,r,r2);
-                    usesacc:=true;
-                  end;
-{$ifdef i386}
                 r.enum:=R_INTREGISTER;
-                r.number:=NR_SELF_POINTER_REG;
-                list.concat(taicpu.op_reg_reg(A_TEST,S_L,r,r));
-{$else}
-{$warning constructor returns in flags for i386}
-{$endif i386}
-                usesself:=true;
+                r.number:=NR_ACCUMULATOR;
+                cg.a_reg_alloc(list,r);
+                reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
+                cg.a_load_ref_reg(list,OS_ADDR,href,r);
+                rg.ungetregisterint(list,r);
+                usesacc:=true;
               end;
           end;
 
@@ -1891,9 +1859,10 @@ function returns in a register and the caller receives it in an other one}
                     st:='*'
                   else
                     st:='';
-                  list.concat(Tai_stabs.Create(strpnew(
+{$warning GDB self}
+                  {list.concat(Tai_stabs.Create(strpnew(
                    '"$t:r'+st+procinfo._class.numberstring+'",'+
-                   tostr(N_RSYM)+',0,0,'+tostr(stab_regindex[SELF_POINTER_REG]))));
+                   tostr(N_RSYM)+',0,0,'+tostr(stab_regindex[SELF_POINTER_REG]))));}
                 end;
 
             { define calling EBP as pseudo local var PM }
@@ -1996,7 +1965,12 @@ function returns in a register and the caller receives it in an other one}
 end.
 {
   $Log$
-  Revision 1.80  2003-03-17 15:52:20  peter
+  Revision 1.81  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.80  2003/03/17 15:52:20  peter
     * fix range error
 
   Revision 1.79  2003/03/11 21:46:24  jonas

+ 7 - 2
compiler/nld.pas

@@ -446,7 +446,7 @@ implementation
                       { call by value open arrays are also indirect addressed }
                       is_open_array(tvarsym(symtableentry).vartype.def) then
                      registers32:=1;
-                   if symtable.symtabletype=withsymtable then
+                   if symtable.symtabletype in [withsymtable,objectsymtable] then
                      inc(registers32);
 
                    if ([vo_is_thread_var,vo_is_dll_var]*tvarsym(symtableentry).varoptions)<>[] then
@@ -1257,7 +1257,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.81  2003-03-11 21:46:24  jonas
+  Revision 1.82  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.81  2003/03/11 21:46:24  jonas
     * lots of new regallocator fixes, both in generic and ppc-specific code
       (ppc compiler still can't compile the linux system unit though)
 

+ 6 - 4
compiler/node.pas

@@ -265,9 +265,6 @@ interface
          nf_isproperty,
          nf_varstateset,
 
-         { tasmnode }
-         nf_object_preserved,   { 30th }
-
          { taddnode }
          nf_use_strconcat
        );
@@ -976,7 +973,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.50  2003-03-17 16:54:41  peter
+  Revision 1.51  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.50  2003/03/17 16:54:41  peter
     * support DefaultHandler and anonymous inheritance fixed
       for message methods
 

+ 7 - 1
compiler/options.pas

@@ -1643,6 +1643,7 @@ begin
   def_symbol('VALUEFREEMEM');
   def_symbol('HASCURRENCY');
   def_symbol('HASTHREADVAR');
+  def_symbol('HAS_GENERICCONSTRUCTOR');
 
 { using a case is pretty useless here (FK) }
 { some stuff for TP compatibility }
@@ -1898,7 +1899,12 @@ finalization
 end.
 {
   $Log$
-  Revision 1.93  2003-03-23 23:20:38  hajny
+  Revision 1.94  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.93  2003/03/23 23:20:38  hajny
     + emx target added
 
   Revision 1.92  2003/03/08 08:59:07  daniel

+ 45 - 20
compiler/pdecsub.pas

@@ -659,26 +659,46 @@ implementation
             aktprocdef.parast.symtablelevel:=lexlevel;
           end;
 
-        if assigned (procinfo._Class)  and
-           is_object(procinfo._Class) and
-           (aktprocdef.proctypeoption in [potype_constructor,potype_destructor]) then
-          inc(paramoffset,pointer_size);
-
-        { self pointer offset, must be done after parsing the parameters }
-        { self isn't pushed in nested procedure of methods }
-        if assigned(procinfo._class) and (lexlevel=normal_function_level) then
-          begin
-            procinfo.selfpointer_offset:=paramoffset;
-            if assigned(aktprocdef) and
-               not(po_containsself in aktprocdef.procoptions) then
-              inc(paramoffset,pointer_size);
-          end;
+        { Get self, vmt offsets }
+        if assigned (procinfo._Class) then
+         begin
+           { self pointer offset, must be done after parsing the parameters }
+           { self isn't pushed in nested procedure of methods }
+           if (lexlevel=normal_function_level) then
+            begin
+              if assigned(aktprocdef) and
+                 not(po_containsself in aktprocdef.procoptions) then
+                begin
+                  procinfo.selfpointer_offset:=paramoffset;
+                  inc(paramoffset,POINTER_SIZE);
+                end;
+            end;
 
-        { con/-destructor flag ? }
-        if assigned (procinfo._Class) and
-           is_class(procinfo._class) and
-           (aktprocdef.proctypeoption in [potype_destructor,potype_constructor]) then
-          inc(paramoffset,pointer_size);
+           { Special parameters for de-/constructors }
+           case aktprocdef.proctypeoption of
+             potype_constructor :
+               begin
+                 procinfo.vmtpointer_offset:=paramoffset;
+                 inc(paramoffset,POINTER_SIZE);
+               end;
+             potype_destructor :
+               begin
+                 if is_object(procinfo._class) then
+                  begin
+                    procinfo.vmtpointer_offset:=paramoffset;
+                    inc(paramoffset,POINTER_SIZE);
+                  end
+                 else
+                  if is_class(procinfo._class) then
+                   begin
+                     procinfo.inheritedflag_offset:=paramoffset;
+                     inc(paramoffset,POINTER_SIZE);
+                   end
+                 else
+                  internalerror(200303261);
+               end;
+           end;
+         end;
 
         procinfo.para_offset:=paramoffset;
 
@@ -2123,7 +2143,12 @@ const
 end.
 {
   $Log$
-  Revision 1.109  2003-03-23 23:21:42  hajny
+  Revision 1.110  2003-03-28 19:16:56  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.109  2003/03/23 23:21:42  hajny
     + emx target added
 
   Revision 1.108  2003/03/19 17:34:04  peter

+ 6 - 4
compiler/pstatmnt.pas

@@ -758,14 +758,11 @@ implementation
               begin
                 repeat
                   { it's possible to specify the modified registers }
-                  include(asmstat.flags,nf_object_preserved);
                   hs:=upper(pattern);
                   found:=false;
                   for r.enum:=firstreg to lastreg do
                    if hs=upper(std_reg2str[r.enum]) then
                     begin
-                      if r.enum = SELF_POINTER_REG then
-                        exclude(asmstat.flags,nf_object_preserved);
                       include(rg.usedinproc,r.enum);
                       include(rg.usedbyproc,r.enum);
                       found:=true;
@@ -1126,7 +1123,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.87  2003-03-17 18:55:30  peter
+  Revision 1.88  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.87  2003/03/17 18:55:30  peter
     * allow more tokens instead of only semicolon after inherited
 
   Revision 1.86  2003/02/19 22:00:14  daniel

+ 9 - 19
compiler/rautils.pas

@@ -811,24 +811,9 @@ Begin
         case tvarsym(sym).owner.symtabletype of
           objectsymtable :
             begin
-              { this is not allowed, because we don't know if the self
-                register is still free, and loading it first is also
-                not possible, because this could break code }
-              { Be TP/Delphi compatible in Delphi or TP modes }
-              if (m_tp7 in aktmodeswitches) or
-                 (m_delphi in aktmodeswitches) then
-                begin
-                  opr.typ:=OPR_CONSTANT;
-                  opr.val:=tvarsym(sym).address;
-                end
-              { I do not agree here people using method vars should ensure
-                that %esi is valid there }
-              else
-                begin
-                  opr.ref.base.enum:=R_INTREGISTER;
-                  opr.ref.base.number:=NR_SELF_POINTER_REG;
-                  opr.ref.offset:=tvarsym(sym).address;
-                end;
+              { We return the address of the field, just like Delphi/TP }
+              opr.typ:=OPR_CONSTANT;
+              opr.val:=tvarsym(sym).address;
               hasvar:=true;
               SetupVar:=true;
               Exit;
@@ -1597,7 +1582,12 @@ end;
 end.
 {
   $Log$
-  Revision 1.53  2003-02-19 22:00:14  daniel
+  Revision 1.54  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.53  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 7 - 2
compiler/regvars.pas

@@ -274,7 +274,7 @@ implementation
 
 
     procedure store_regvar_int(asml:Taasmoutput;reg:Tsuperregister);
-    
+
     begin
       internalerror(200301104);
     end;
@@ -497,7 +497,12 @@ end.
 
 {
   $Log$
-  Revision 1.45  2003-02-19 22:00:14  daniel
+  Revision 1.46  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.45  2003/02/19 22:00:14  daniel
     * Code generator converted to new register notation
     - Horribily outdated todo.txt removed
 

+ 10 - 12
compiler/rgobj.pas

@@ -606,22 +606,13 @@ unit rgobj;
           r2.enum:=R_INTREGISTER;
           r2.number:=r;
           list.concat(tai_regalloc.alloc(r2));
-          getexplicitregisterint:=r2;
 {$ifdef TEMPREGDEBUG}
           testregisters32;
 {$endif TEMPREGDEBUG}
          end
        else
-{         getexplicitregisterint:=getregisterint(list,r and $ff);}
-{$ifndef i386}
-          // not very cleanm I know :/ The self pointer is allocated a lot
-          // more than necessary (in tcgselfnode.pass_2), but a lot of those
-          // allocations are necessary for the optimizer.
-          // The i386 doesn't care, probably because esi isn't a normal
-          // allocatable register (JM)
-          if (r <> NR_SELF_POINTER_REG) then
-{$endif i386}
-            internalerror(200301103);
+         internalerror(200301103);
+       getexplicitregisterint:=r2;
     end;
 
 
@@ -727,7 +718,9 @@ unit rgobj;
 
     procedure Trgobj.cleartempgen;
 
+   {$ifdef newra}
     var i:Tsuperregister;
+   {$endif newra}
 
     begin
       countunusedregsint:=countusableregsint;
@@ -1350,7 +1343,12 @@ end.
 
 {
   $Log$
-  Revision 1.31  2003-03-11 21:46:24  jonas
+  Revision 1.32  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.31  2003/03/11 21:46:24  jonas
     * lots of new regallocator fixes, both in generic and ppc-specific code
       (ppc compiler still can't compile the linux system unit though)
 

+ 67 - 137
compiler/x86/cgx86.pas

@@ -28,6 +28,8 @@ unit cgx86;
 
   interface
 
+{$define TEST_GENERIC}
+
     uses
        cginfo,cgbase,cgobj,
        aasmbase,aasmtai,aasmcpu,
@@ -115,11 +117,6 @@ unit cgx86;
         procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
         procedure g_restore_frame_pointer(list : taasmoutput);override;
         procedure g_return_from_proc(list : taasmoutput;parasize : aword);override;
-{$ifndef TEST_GENERIC}
-        procedure g_call_constructor_helper(list : taasmoutput);override;
-        procedure g_call_destructor_helper(list : taasmoutput);override;
-        procedure g_call_fail_helper(list : taasmoutput);override;
-{$endif}
         procedure g_save_standard_registers(list:Taasmoutput;usedinproc:Tsupregset);override;
         procedure g_restore_standard_registers(list:Taasmoutput;usedinproc:Tsupregset);override;
         procedure g_save_all_registers(list : taasmoutput);override;
@@ -1145,42 +1142,41 @@ unit cgx86;
 
     procedure tcgx86.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);
       var
-         ecxpushed : boolean;
+         ecxpushed,esipushed : boolean;
          helpsize : longint;
          i : byte;
          reg8,reg32 : tregister;
          srcref,dstref : treference;
          swap : boolean;
-         r : Tregister;
-
-         procedure maybepushecx;
-
-         var r:Tregister;
+         srcreg,destreg,r : Tregister;
 
+         function maybepush(r:tnewregister;var pushed:boolean):tregister;
          begin
-           r.enum:=R_INTREGISTER;
-           r.number:=NR_ECX;
-           if not(RS_ECX in rg.unusedregsint) then
+           pushed:=false;
+           result.enum:=R_INTREGISTER;
+           result.number:=r;
+           if not((r shr 8) in rg.unusedregsint) then
              begin
-               list.concat(Taicpu.Op_reg(A_PUSH,S_L,r));
-               ecxpushed:=true;
+               list.concat(Taicpu.Op_reg(A_PUSH,S_L,result));
+               pushed:=true;
              end
-           else rg.getexplicitregisterint(list,NR_ECX);
+           else
+             rg.getexplicitregisterint(list,r);
          end;
 
       begin
+         ecxpushed:=false;
+         esipushed:=false;
          if (not loadref) and
             ((len<=8) or
              (not(cs_littlesize in aktglobalswitches ) and (len<=12))) then
            begin
-              r.enum:=R_INTREGISTER;
               helpsize:=len shr 2;
               dstref:=dest;
               srcref:=source;
               for i:=1 to helpsize do
                 begin
-                   rg.getexplicitregisterint(list,NR_EDI);
-                   r.number:=NR_EDI;
+                   r:=rg.getexplicitregisterint(list,NR_EDI);
                    a_load_ref_reg(list,OS_32,srcref,r);
                    If (len = 4) and delsource then
                      reference_release(list,source);
@@ -1192,8 +1188,7 @@ unit cgx86;
                 end;
               if len>1 then
                 begin
-                   rg.getexplicitregisterint(list,NR_DI);
-                   r.number:=NR_DI;
+                   r:=rg.getexplicitregisterint(list,NR_DI);
                    a_load_ref_reg(list,OS_16,srcref,r);
                    If (len = 2) and delsource then
                      reference_release(list,source);
@@ -1238,8 +1233,7 @@ unit cgx86;
                    if swap then
                      { was earlier XCHG, of course nonsense }
                      begin
-                       rg.getexplicitregisterint(list,NR_EDI);
-                       r.number:=NR_EDI;
+                       r:=rg.getexplicitregisterint(list,NR_EDI);
                        a_load_reg_reg(list,OS_32,OS_32,reg32,r);
                      end;
                    a_load_ref_reg(list,OS_8,srcref,reg8);
@@ -1258,27 +1252,45 @@ unit cgx86;
            end
          else
            begin
-              r.enum:=R_INTREGISTER;
-              r.number:=NR_EDI;
-              rg.getexplicitregisterint(list,NR_EDI);
-              a_loadaddr_ref_reg(list,dest,r);
-              r.number:=NR_ESI;
-              list.concat(tai_regalloc.alloc(r));
+              destreg:=rg.getexplicitregisterint(list,NR_EDI);
+              a_loadaddr_ref_reg(list,dest,destreg);
               if loadref then
-                a_load_ref_reg(list,OS_ADDR,source,r)
+                begin
+                  srcreg:=maybepush(NR_ESI,esipushed);
+                  a_load_ref_reg(list,OS_ADDR,source,srcreg)
+                end
               else
                 begin
-                  a_loadaddr_ref_reg(list,source,r);
                   if delsource then
-                    reference_release(list,source);
+                    begin
+                      if (source.base.number=NR_ESI) then
+                        srcreg:=source.base
+                      else if (source.index.number=NR_ESI) then
+                        srcreg:=source.index
+                      else
+                        srcreg:=maybepush(NR_ESI,esipushed);
+                    end
+                  else
+                    srcreg:=maybepush(NR_ESI,esipushed);
+                  a_loadaddr_ref_reg(list,source,srcreg);
+                  if delsource then
+                   begin
+                     srcref:=source;
+                     { Don't release ESI register yet, it's needed
+                       by the movsl }
+                     if (srcref.base.number=NR_ESI) then
+                       srcref.base.number:=NR_NO
+                     else if (srcref.index.number=NR_ESI) then
+                       srcref.index.number:=NR_NO;
+                     reference_release(list,srcref);
+                   end;
                 end;
 
               list.concat(Taicpu.Op_none(A_CLD,S_NO));
               ecxpushed:=false;
-              r.number:=NR_ECX;
               if cs_littlesize in aktglobalswitches  then
                 begin
-                   maybepushecx;
+                   r:=maybepush(NR_ECX,ecxpushed);
                    a_load_const_reg(list,OS_INT,len,r);
                    list.concat(Taicpu.Op_none(A_REP,S_NO));
                    list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
@@ -1289,7 +1301,7 @@ unit cgx86;
                    len:=len and 3;
                    if helpsize>1 then
                     begin
-                      maybepushecx;
+                      r:=maybepush(NR_ECX,ecxpushed);
                       a_load_const_reg(list,OS_INT,helpsize,r);
                       list.concat(Taicpu.Op_none(A_REP,S_NO));
                     end;
@@ -1304,10 +1316,6 @@ unit cgx86;
                      list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
                 end;
               r.enum:=R_INTREGISTER;
-              r.number:=NR_EDI;
-              rg.ungetregisterint(list,r);
-              r.number:=NR_ESI;
-              list.concat(tai_regalloc.dealloc(r));
               if ecxpushed then
                 begin
                   r.number:=NR_ECX;
@@ -1318,9 +1326,17 @@ unit cgx86;
                   r.number:=NR_ECX;
                   rg.ungetregisterint(list,r);
                 end;
-
-              { loading SELF-reference again }
-              g_maybe_loadself(list);
+              if esipushed then
+                begin
+                  r.number:=NR_ESI;
+                  list.concat(Taicpu.Op_reg(A_POP,S_L,r))
+                end
+              else
+                begin
+                  r.number:=NR_ESI;
+                  rg.ungetregisterint(list,r);
+                end;
+              rg.ungetregisterint(list,destreg);
            end;
          if delsource then
           tg.ungetiftemp(list,source);
@@ -1484,8 +1500,8 @@ unit cgx86;
     procedure tcgx86.g_removevaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer);
       var
         lenref : treference;
-        power,len  : longint;
-        r,rsp:Tregister;
+        power  : longint;
+        r,rsp  : Tregister;
       begin
         lenref:=ref;
         inc(lenref.offset,4);
@@ -1726,97 +1742,6 @@ unit cgx86;
          end;
       end;
 
-{$ifndef TEST_GENERIC}
-    procedure tcgx86.g_call_constructor_helper(list : taasmoutput);
-
-    var r:Tregister;
-
-      begin
-        r.enum:=R_INTREGISTER;
-        r.number:=NR_EDI;
-        if is_class(procinfo._class) then
-          begin
-            if (cs_implicit_exceptions in aktmoduleswitches) then
-              procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
-            a_call_name(list,'FPC_NEW_CLASS');
-            list.concat(Taicpu.Op_cond_sym(A_Jcc,C_Z,S_NO,faillabel));
-          end
-        else if is_object(procinfo._class) then
-          begin
-            rg.getexplicitregisterint(list,NR_EDI);
-            a_load_const_reg(list,OS_ADDR,procinfo._class.vmt_offset,r);
-            a_call_name(list,'FPC_HELP_CONSTRUCTOR');
-            list.concat(Taicpu.Op_cond_sym(A_Jcc,C_Z,S_NO,faillabel));
-          end
-        else
-          internalerror(200006161);
-      end;
-
-    procedure tcgx86.g_call_destructor_helper(list : taasmoutput);
-      var
-        nofinal : tasmlabel;
-        href : treference;
-        r : Tregister;
-
-      begin
-        r.enum:=R_INTREGISTER;
-        if is_class(procinfo._class) then
-         begin
-           a_call_name(list,'FPC_DISPOSE_CLASS')
-         end
-        else if is_object(procinfo._class) then
-         begin
-           { must the object be finalized ? }
-           if procinfo._class.needs_inittable then
-            begin
-              objectlibrary.getlabel(nofinal);
-              r.number:=NR_EBP;
-              reference_reset_base(href,r,8);
-              a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nofinal);
-              r.number:=NR_ESI;
-              reference_reset_base(href,r,0);
-              g_finalize(list,procinfo._class,href,false);
-              a_label(list,nofinal);
-            end;
-           rg.getexplicitregisterint(list,NR_EDI);
-           r.number:=NR_EDI;
-           a_load_const_reg(list,OS_ADDR,procinfo._class.vmt_offset,r);
-           rg.ungetregisterint(list,r);
-           a_call_name(list,'FPC_HELP_DESTRUCTOR')
-         end
-        else
-         internalerror(200006162);
-      end;
-
-    procedure tcgx86.g_call_fail_helper(list : taasmoutput);
-      var
-        href : treference;
-        r : Tregister;
-      begin
-        r.enum:=R_INTREGISTER;
-        if is_class(procinfo._class) then
-          begin
-            reference_reset_base(href,procinfo.framepointer,8);
-            r.number:=NR_ESI;
-            a_load_ref_reg(list,OS_ADDR,href,r);
-            a_call_name(list,'FPC_HELP_FAIL_CLASS');
-          end
-        else if is_object(procinfo._class) then
-          begin
-            reference_reset_base(href,procinfo.framepointer,12);
-            r.number:=NR_ESI;
-            a_load_ref_reg(list,OS_ADDR,href,r);
-            rg.getexplicitregisterint(list,NR_EDI);
-            r.number:=NR_EDI;
-            a_load_const_reg(list,OS_ADDR,procinfo._class.vmt_offset,r);
-            a_call_name(list,'FPC_HELP_FAIL');
-            rg.ungetregisterint(list,r);
-          end
-        else
-          internalerror(200006163);
-      end;
-{$endif}
-
 
     procedure tcgx86.g_save_standard_registers(list:Taasmoutput;usedinproc:Tsupregset);
 
@@ -1918,7 +1843,12 @@ unit cgx86;
 end.
 {
   $Log$
-  Revision 1.36  2003-03-18 18:17:46  peter
+  Revision 1.37  2003-03-28 19:16:57  peter
+    * generic constructor working for i386
+    * remove fixed self register
+    * esi added as address register for i386
+
+  Revision 1.36  2003/03/18 18:17:46  peter
     * reg2opsize()
 
   Revision 1.35  2003/03/13 19:52:23  jonas

Some files were not shown because too many files changed in this diff