Browse Source

* removed n386ld and n386util units
* maybe_save/maybe_restore added instead of the old maybe_push

peter 23 years ago
parent
commit
4a176c81bc

+ 11 - 20
compiler/cginfo.pas

@@ -31,7 +31,7 @@ interface
 
     type
        {# Generic opcodes, which must be supporrted by all processors }
-       TOpCg = 
+       TOpCg =
        (
           OP_NONE,
           OP_ADD,       { simple addition          }
@@ -51,9 +51,9 @@ interface
         );
 
        {# Generic flag values - used for jump locations }
-       TOpCmp = 
+       TOpCmp =
        (
-          OC_NONE,          
+          OC_NONE,
           OC_EQ,           { equality comparison }
           OC_GT,
           OC_LT,
@@ -78,35 +78,22 @@ interface
                   OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,OS_MS8,OS_MS16,OS_MS32,
                   OS_MS64,OS_MS128);
 
-{$ifdef powerpc}
-       OS_ADDR = OS_32;
-       OS_INT = OS_32;
-       OS_FLOAT = OS_F64;
-       OS_VECTOR = OS_M128;
-{$endif powercc}
-{$ifdef ia64}
-       OS_ADDR = OS_64;
-       OS_INT = OS_64;
-       OS_FLOAT = OS_F??;
-       OS_VECTOR = OS_NO; { the normal registers can also be used as vectors }
-{$endif ia64}
-
     const
        tcgsize2size : Array[tcgsize] of integer =
          { integer values }
         (0,1,2,4,8,1,2,4,8,
-         { floating point values } 
+         { floating point values }
          4,8,EXTENDED_SIZE,8,
          { multimedia values }
          1,2,4,8,16,1,2,4,8,16);
-         
+
        tfloat2tcgsize: array[tfloattype] of tcgsize =
          (OS_F32,OS_F64,OS_F80,OS_C64);
 
        tcgsize2tfloat: array[OS_F32..OS_C64] of tfloattype =
          (s32real,s64real,s80real,s64comp);
 
-         
+
 
 
 implementation
@@ -114,7 +101,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.6  2002-05-06 19:48:26  carl
+  Revision 1.7  2002-05-13 19:54:36  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.6  2002/05/06 19:48:26  carl
   + added more patches from Mazen for SPARC port
 
   Revision 1.5  2002/04/21 19:46:52  carl

+ 9 - 4
compiler/cgobj.pas

@@ -230,6 +230,7 @@ unit cgobj;
           procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); virtual; abstract;
 
           procedure g_flags2reg(list: taasmoutput; const f: tresflags; reg: TRegister); virtual; abstract;
+          procedure g_flags2ref(list: taasmoutput; const f: tresflags; const ref:TReference); virtual; abstract;
 
           { some processors like the PPC doesn't allow to change the stack in }
           { a procedure, so we need to maintain an extra stack for the        }
@@ -1053,8 +1054,8 @@ unit cgobj;
          a_param_const(list,OS_32,stackframesize,1);
          a_call_name(list,'FPC_STACKCHECK');
       end;
-      
-      
+
+
     procedure tcg.g_maybe_loadself(list : taasmoutput);
       var
          hp : treference;
@@ -1085,7 +1086,7 @@ unit cgobj;
                 end;
            end;
       end;
-      
+
 
 
 {*****************************************************************************
@@ -1112,7 +1113,11 @@ finalization
 end.
 {
   $Log$
-  Revision 1.21  2002-05-12 19:57:16  carl
+  Revision 1.22  2002-05-13 19:54:36  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.21  2002/05/12 19:57:16  carl
   * maybe_loadself portable
 
   Revision 1.20  2002/05/12 16:53:04  peter

+ 8 - 24
compiler/i386/cga.pas

@@ -61,29 +61,9 @@ interface
 implementation
 
     uses
-       cutils,cclasses,
-       globtype,systems,globals,verbose,
-       fmodule,
-       symbase,symsym,symtable,types,
-       tainst,cgbase,regvars,cgobj,tgobj,rgobj,rgcpu
-{$ifdef GDB}
-  {$ifdef delphi}
-       ,sysutils
-  {$else}
-       ,strings
-  {$endif}
-       ,gdb
-{$endif}
-       ;
-
-{$ifdef NOTARGETWIN32}
- {$define __NOWINPECOFF__}
-{$endif}
-
-{$ifdef NOTARGETWDOSX}
- {$define __NOWINPECOFF__}
-{$endif}
-
+       cutils,
+       systems,globals,verbose,
+       cgbase,cgobj,tgobj,rgobj,rgcpu;
 
 
 {*****************************************************************************
@@ -194,7 +174,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.28  2002-05-12 16:53:16  peter
+  Revision 1.29  2002-05-13 19:54:37  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.28  2002/05/12 16:53:16  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 50 - 4
compiler/i386/cgcpu.pas

@@ -28,7 +28,9 @@ unit cgcpu;
   interface
 
     uses
-       cginfo,cgbase,cgobj,cg64f32,aasm,cpuasm,cpubase,cpuinfo,symconst;
+       cginfo,cgbase,cgobj,cg64f32,
+       aasm,cpuasm,cpubase,cpuinfo,
+       node,symconst;
 
     type
       tcg386 = class(tcg64f32)
@@ -91,6 +93,7 @@ unit cgcpu;
         procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
 
         procedure g_flags2reg(list: taasmoutput; const f: tresflags; reg: TRegister); override;
+        procedure g_flags2ref(list: taasmoutput; const f: tresflags; const ref: TReference); override;
 
         procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reglo,reghi : tregister);override;
         procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;reglosrc,reghisrc,reglodst,reghidst : tregister);override;
@@ -120,7 +123,9 @@ unit cgcpu;
         procedure g_save_all_registers(list : taasmoutput);override;
         procedure g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);override;
 
-       private
+        procedure g_overflowcheck(list: taasmoutput; const p: tnode);override;
+
+      private
 
         procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
         procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
@@ -152,7 +157,7 @@ unit cgcpu;
 
     uses
        globtype,globals,verbose,systems,cutils,
-       symtable,symdef,symsym,types,
+       symdef,symsym,types,
        rgobj,tgobj,rgcpu,tainst;
 
 {$ifndef NOTARGETWIN32}
@@ -1047,6 +1052,17 @@ unit cgcpu;
        end;
 
 
+     procedure tcg386.g_flags2ref(list: taasmoutput; const f: tresflags; const ref: TReference);
+
+       var
+         ai : taicpu;
+       begin
+          ai:=Taicpu.Op_ref(A_Setcc,S_B,ref);
+          ai.SetCondition(flags_to_cond(f));
+          list.concat(ai);
+       end;
+
+
 { ************* 64bit operations ************ }
 
     procedure tcg386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
@@ -1732,13 +1748,43 @@ unit cgcpu;
       end;
 
 
+    { produces if necessary overflowcode }
+    procedure tcg386.g_overflowcheck(list: taasmoutput; const p: tnode);
+      var
+         hl : tasmlabel;
+         ai : taicpu;
+         cond : TAsmCond;
+      begin
+         if not(cs_check_overflow in aktlocalswitches) then
+          exit;
+         getlabel(hl);
+         if not ((p.resulttype.def.deftype=pointerdef) or
+                ((p.resulttype.def.deftype=orddef) and
+                 (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
+                                                    bool8bit,bool16bit,bool32bit]))) then
+           cond:=C_NO
+         else
+           cond:=C_NB;
+         ai:=Taicpu.Op_Sym(A_Jcc,S_NO,hl);
+         ai.SetCondition(cond);
+         ai.is_jmp:=true;
+         list.concat(ai);
+
+         a_call_name(list,'FPC_OVERFLOW');
+         a_label(list,hl);
+      end;
+
 
 begin
   cg := tcg386.create;
 end.
 {
   $Log$
-  Revision 1.16  2002-05-12 19:59:05  carl
+  Revision 1.17  2002-05-13 19:54:37  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.16  2002/05/12 19:59:05  carl
   * some small portability fixes
 
   Revision 1.15  2002/05/12 16:53:16  peter

+ 6 - 2
compiler/i386/cpunode.pas

@@ -30,7 +30,7 @@ unit cpunode;
 
     uses
        ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,
-       n386ld,n386add,n386cal,n386con,n386cnv,n386flw,n386mat,n386mem,
+       n386add,n386cal,n386con,n386cnv,n386flw,n386mat,n386mem,
        n386set,n386inl,n386opt,
        { this not really a node }
        n386obj, rgcpu;
@@ -38,7 +38,11 @@ unit cpunode;
 end.
 {
   $Log$
-  Revision 1.9  2002-04-19 15:39:35  peter
+  Revision 1.10  2002-05-13 19:54:37  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.9  2002/04/19 15:39:35  peter
     * removed some more routines from cga
     * moved location_force_reg/mem to ncgutil
     * moved arrayconstructnode secondpass to ncgld

+ 18 - 16
compiler/i386/n386add.pas

@@ -60,7 +60,7 @@ interface
       cgbase,pass_2,regvars,
       cpuasm,
       ncon,nset,
-      tainst,cga,ncgutil,n386util,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+      tainst,cga,ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
 
 {*****************************************************************************
                                   Helpers
@@ -71,7 +71,7 @@ interface
 
     procedure ti386addnode.pass_left_and_right(var pushedfpu:boolean);
       var
-        pushed : boolean;
+        pushedregs : tmaybesave;
       begin
         { calculate the operator which is more difficult }
         firstcomplex(self);
@@ -82,14 +82,13 @@ interface
         secondpass(left);
 
         { are too few registers free? }
-        pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
+        maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
         if location.loc=LOC_FPUREGISTER then
-          pushedfpu:=maybe_pushfpu(right.registersfpu,left)
+          pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
         else
           pushedfpu:=false;
         secondpass(right);
-        if pushed then
-          restore(left,is_64bitint(left.resulttype.def));
+        maybe_restore(exprasmlist,left.location,pushedregs);
       end;
 
 
@@ -337,7 +336,7 @@ interface
       var
         href       : treference;
         cmpop      : boolean;
-        pushedregs : tpushedsaved;
+        pushed     : tpushedsaved;
         regstopush : tregisterset;
       begin
         { string operations are not commutative }
@@ -378,7 +377,7 @@ interface
                         { registers) (JM)                                  }
                         regstopush := all_registers;
                         remove_non_regvars_from_loc(right.location,regstopush);
-                        rg.saveusedregisters(exprasmlist,pushedregs,regstopush);
+                        rg.saveusedregisters(exprasmlist,pushed,regstopush);
                         { push the maximum possible length of the result }
                         cg.a_paramaddr_ref(exprasmlist,left.location.reference,2);
                         { the optimizer can more easily put the          }
@@ -391,13 +390,13 @@ interface
                         cg.a_call_name(exprasmlist,'FPC_SHORTSTR_CONCAT');
                         tg.ungetiftemp(exprasmlist,right.location.reference);
                         cg.g_maybe_loadself(exprasmlist);
-                        rg.restoreusedregisters(exprasmlist,pushedregs);
+                        rg.restoreusedregisters(exprasmlist,pushed);
                         location_copy(location,left.location);
                      end;
                    ltn,lten,gtn,gten,equaln,unequaln :
                      begin
                        cmpop := true;
-                       rg.saveusedregisters(exprasmlist,pushedregs,all_registers);
+                       rg.saveusedregisters(exprasmlist,pushed,all_registers);
                        secondpass(left);
                        location_release(exprasmlist,left.location);
                        cg.a_paramaddr_ref(exprasmlist,left.location.reference,2);
@@ -407,7 +406,7 @@ interface
                        rg.saveregvars(exprasmlist,all_registers);
                        cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
                        cg.g_maybe_loadself(exprasmlist);
-                       rg.restoreusedregisters(exprasmlist,pushedregs);
+                       rg.restoreusedregisters(exprasmlist,pushed);
                        location_freetemp(exprasmlist,left.location);
                        location_freetemp(exprasmlist,right.location);
                      end;
@@ -429,9 +428,9 @@ interface
         op      : TAsmOp;
         opsize  : TOpsize;
         cmpop,
-        pushed,
         isjump  : boolean;
         otl,ofl : tasmlabel;
+        pushedregs : tmaybesave;
       begin
         { calculate the operator which is more difficult }
         firstcomplex(self);
@@ -470,7 +469,7 @@ interface
                falselabel:=ofl;
              end;
 
-            pushed:=maybe_push(right.registers32,left,false);
+            maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
             isjump:=(right.location.loc=LOC_JUMP);
             if isjump then
               begin
@@ -480,8 +479,7 @@ interface
                  getlabel(falselabel);
               end;
             secondpass(right);
-            if pushed then
-             restore(left,false);
+            maybe_restore(exprasmlist,left.location,pushedregs);
             if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
              location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false);
             if isjump then
@@ -1574,7 +1572,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.35  2002-05-12 16:53:17  peter
+  Revision 1.36  2002-05-13 19:54:37  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.35  2002/05/12 16:53:17  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 8 - 4
compiler/i386/n386cal.pas

@@ -51,7 +51,7 @@ implementation
     uses
       globtype,systems,
       cutils,verbose,globals,
-      symconst,symbase,symsym,symtable,aasm,types,
+      symconst,symbase,symsym,symtable,types,
 {$ifdef GDB}
   {$ifdef delphi}
       sysutils,
@@ -61,9 +61,9 @@ implementation
       gdb,
 {$endif GDB}
       cginfo,cgbase,pass_2,
-      cpubase,
+      cpubase,aasm,tainst,
       nmem,nld,ncnv,
-      tainst,cga,cgobj,tgobj,n386ld,n386util,ncgutil,regvars,rgobj,rgcpu,cg64f32,cgcpu;
+      ncgutil,cga,cgobj,tgobj,regvars,rgobj,rgcpu,cg64f32,cgcpu;
 
 {*****************************************************************************
                              TI386CALLPARANODE
@@ -1484,7 +1484,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.49  2002-05-12 16:53:17  peter
+  Revision 1.50  2002-05-13 19:54:38  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.49  2002/05/12 16:53:17  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 15 - 13
compiler/i386/n386inl.pas

@@ -43,7 +43,7 @@ implementation
       cginfo,cgbase,pass_1,pass_2,
       cpubase,
       nbas,ncon,ncal,ncnv,nld,
-      cga,tgobj,n386util,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
+      cga,tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
 
 
 {*****************************************************************************
@@ -65,7 +65,7 @@ implementation
          href : treference;
          hp2 : tstringconstnode;
          l : longint;
-         ispushed : boolean;
+         pushedregs : tmaybesave;
          hregisterhi,
          hregister : tregister;
          lengthlab,
@@ -190,7 +190,7 @@ implementation
                  else
                   cg.a_op_const_reg(exprasmlist,cgop,1,location.register);
 
-                 emitoverflowcheck(self);
+                 cg.g_overflowcheck(exprasmlist,self);
                  cg.g_rangecheck(exprasmlist,self,resulttype.def);
               end;
             in_dec_x,
@@ -219,11 +219,10 @@ implementation
                 { second argument specified?, must be a s32bit in register }
                 if assigned(tcallparanode(left).right) then
                  begin
-                   ispushed:=maybe_push(tcallparanode(tcallparanode(left).right).left.registers32,
-                     tcallparanode(left).left,false);
+                   maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
+                     tcallparanode(left).left.location,pushedregs);
                    secondpass(tcallparanode(tcallparanode(left).right).left);
-                   if ispushed then
-                     restore(tcallparanode(left).left,false);
+                   maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
                    { when constant, just multiply the addvalue }
                    if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
                     addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
@@ -258,7 +257,7 @@ implementation
                        hregister,tcallparanode(left).left.location);
                    location_release(exprasmlist,tcallparanode(tcallparanode(left).right).left.location);
                  end;
-                emitoverflowcheck(tcallparanode(left).left);
+                cg.g_overflowcheck(exprasmlist,tcallparanode(left).left);
                 cg.g_rangecheck(exprasmlist,tcallparanode(left).left,tcallparanode(left).left.resulttype.def);
               end;
 
@@ -323,11 +322,10 @@ implementation
                  else
                    begin
                       { generate code for the element to set }
-                      ispushed:=maybe_push(tcallparanode(tcallparanode(left).right).left.registers32,
-                        tcallparanode(left).left,false);
+                      maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
+                        tcallparanode(left).left.location,pushedregs);
                       secondpass(tcallparanode(tcallparanode(left).right).left);
-                      if ispushed then
-                        restore(tcallparanode(left).left,false);
+                      maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
                       { determine asm operator }
                       if inlinenumber=in_include_x_y then
                         asmop:=A_BTS
@@ -468,7 +466,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.40  2002-05-12 16:53:17  peter
+  Revision 1.41  2002-05-13 19:54:38  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.40  2002/05/12 16:53:17  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 0 - 913
compiler/i386/n386ld.pas

@@ -1,913 +0,0 @@
-{
-    $Id$
-    Copyright (c) 1998-2000 by Florian Klaempfl
-
-    Generate i386 assembler for load/assignment nodes
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ****************************************************************************
-}
-unit n386ld;
-
-{$i defines.inc}
-
-interface
-
-    uses
-      node,nld;
-
-    type
-       ti386loadnode = class(tloadnode)
-          procedure pass_2;override;
-       end;
-
-       ti386assignmentnode = class(tassignmentnode)
-          procedure pass_2;override;
-       end;
-
-       ti386funcretnode = class(tfuncretnode)
-          procedure pass_2;override;
-       end;
-
-
-implementation
-
-    uses
-      systems,
-      cutils,verbose,globals,
-      symconst,symdef,symsym,symtable,aasm,types,
-      cginfo,cgbase,pass_2,
-      nmem,ncon,ncnv,
-      cpubase,cpuasm,
-      cga,tgobj,n386util,regvars,cgobj,cg64f32,rgobj,rgcpu;
-
-{*****************************************************************************
-                             SecondLoad
-*****************************************************************************}
-
-    procedure ti386loadnode.pass_2;
-      var
-         hregister : tregister;
-         symtabletype : tsymtabletype;
-         i : longint;
-         href : treference;
-         newsize : tcgsize;
-         popeax : boolean;
-      begin
-         { we don't know the size of all arrays }
-         newsize:=def_cgsize(resulttype.def);
-         location_reset(location,LOC_REFERENCE,newsize);
-         case symtableentry.typ of
-              { this is only for toasm and toaddr }
-              absolutesym :
-                 begin
-                    location.reference.symbol:=nil;
-                    if (tabsolutesym(symtableentry).abstyp=toaddr) then
-                     begin
-                       if tabsolutesym(symtableentry).absseg then
-                        location.reference.segment:=R_FS;
-                       location.reference.offset:=tabsolutesym(symtableentry).address;
-                     end
-                    else
-                     location.reference.symbol:=newasmsymbol(tabsolutesym(symtableentry).mangledname);
-                 end;
-              constsym:
-                begin
-                   if tconstsym(symtableentry).consttyp=constresourcestring then
-                     begin
-                        location_reset(location,LOC_CREFERENCE,OS_ADDR);
-                        location.reference.symbol:=newasmsymbol(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
-                        location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
-                     end
-                   else
-                     internalerror(22798);
-                end;
-              varsym :
-                 begin
-                    hregister:=R_NO;
-                    { C variable }
-                    if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
-                      begin
-                         location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
-                      end
-                    { DLL variable }
-                    else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
-                      begin
-                         hregister:=rg.getregisterint(exprasmlist);
-                         location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
-                         emit_ref_reg(A_MOV,S_L,location.reference,hregister);
-                         location.reference.symbol:=nil;
-                         location.reference.base:=hregister;
-                      end
-                    { external variable }
-                    else if (vo_is_external in tvarsym(symtableentry).varoptions) then
-                      begin
-                         location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
-                      end
-                    { thread variable }
-                    else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
-                      begin
-                         popeax:=not(R_EAX in rg.unusedregsint);
-                         if popeax then
-                           emit_reg(A_PUSH,S_L,R_EAX);
-                         reference_reset_symbol(href,newasmsymbol(tvarsym(symtableentry).mangledname),0);
-                         emit_ref(A_PUSH,S_L,href);
-                         { the called procedure isn't allowed to change }
-                         { any register except EAX                    }
-                         cg.a_call_name(exprasmlist,'FPC_RELOCATE_THREADVAR');
-
-                         location.reference.base:=rg.getregisterint(exprasmlist);
-                         emit_reg_reg(A_MOV,S_L,R_EAX,location.reference.base);
-                         if popeax then
-                           emit_reg(A_POP,S_L,R_EAX);
-
-                      end
-                    { normal variable }
-                    else
-                      begin
-                         symtabletype:=symtable.symtabletype;
-                         { in case it is a register variable: }
-                         if tvarsym(symtableentry).reg<>R_NO then
-                           begin
-                              if tvarsym(symtableentry).reg in [R_ST0..R_ST7] then
-                                begin
-                                   location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
-                                   location.register:=tvarsym(symtableentry).reg;
-                                end
-                              else
-                                if not(rg.makeregsize(tvarsym(symtableentry).reg,OS_INT) in [R_EAX..R_EBX]) or
-                                   rg.regvar_loaded[rg.makeregsize(tvarsym(symtableentry).reg,OS_INT)] then
-                                begin
-                                   location_reset(location,LOC_CREGISTER,
-                                       cg.reg_cgsize(tvarsym(symtableentry).reg));
-                                   location.register:=tvarsym(symtableentry).reg;
-                                   exclude(rg.unusedregsint,rg.makeregsize(tvarsym(symtableentry).reg,OS_INT));
-                                end
-                              else
-                                begin
-                                  load_regvar(exprasmlist,tvarsym(symtableentry));
-                                  location_reset(location,LOC_CREGISTER,
-                                      cg.reg_cgsize(tvarsym(symtableentry).reg));
-                                  location.register:=tvarsym(symtableentry).reg;
-                                  exclude(rg.unusedregsint,rg.makeregsize(tvarsym(symtableentry).reg,OS_INT));
-                                end
-                           end
-                         else
-                           begin
-                              { first handle local and temporary variables }
-                              if (symtabletype in [parasymtable,inlinelocalsymtable,
-                                                   inlineparasymtable,localsymtable]) then
-                                begin
-                                   location.reference.base:=procinfo^.framepointer;
-                                   if (symtabletype in [inlinelocalsymtable,
-                                                        localsymtable]) then
-                                     location.reference.offset:=
-                                       tvarsym(symtableentry).address-symtable.address_fixup
-                                   else
-                                     location.reference.offset:=
-                                       tvarsym(symtableentry).address+symtable.address_fixup;
-
-                                   if (symtabletype in [localsymtable,inlinelocalsymtable]) then
-                                     begin
-                                        if use_esp_stackframe then
-                                          dec(location.reference.offset,
-                                            tvarsym(symtableentry).getvaluesize)
-                                        else
-                                          location.reference.offset:=-location.reference.offset;
-                                     end;
-                                   if (lexlevel>symtable.symtablelevel) then
-                                     begin
-                                        hregister:=rg.getregisterint(exprasmlist);
-
-                                        { make a reference }
-                                        reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
-
-                                        emit_ref_reg(A_MOV,S_L,href,hregister);
-
-                                        i:=lexlevel-1;
-                                        while (i>symtable.symtablelevel) do
-                                          begin
-                                             { make a reference }
-                                             reference_reset_base(href,hregister,8);
-                                             emit_ref_reg(A_MOV,S_L,href,hregister);
-                                             dec(i);
-                                          end;
-                                        location.reference.base:=hregister;
-                                     end;
-                                end
-                              else
-                                case symtabletype of
-                                   globalsymtable,
-                                   staticsymtable :
-                                     begin
-                                       location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
-                                     end;
-                                   stt_exceptsymtable:
-                                     begin
-                                        location.reference.base:=procinfo^.framepointer;
-                                        location.reference.offset:=tvarsym(symtableentry).address;
-                                     end;
-                                   objectsymtable:
-                                     begin
-                                        rg.getexplicitregisterint(exprasmlist,R_ESI);
-                                        if (sp_static in tvarsym(symtableentry).symoptions) then
-                                          begin
-                                             location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
-                                          end
-                                        else
-                                          begin
-                                             location.reference.base:=R_ESI;
-                                             location.reference.offset:=tvarsym(symtableentry).address;
-                                          end;
-                                     end;
-                                   withsymtable:
-                                     begin
-                                        { make a reference }
-                                        { symtable datasize field
-                                          contains the offset of the temp
-                                          stored }
-{                                       hp:=reference_new_base(procinfo^.framepointer,
-                                          symtable.datasize);
-
-                                        emit_ref_reg(A_MOV,S_L,hp,hregister);}
-
-                                        if nf_islocal in tnode(twithsymtable(symtable).withnode).flags then
-                                         begin
-                                           location.reference:=twithnode(twithsymtable(symtable).withnode).withreference;
-                                         end
-                                        else
-                                         begin
-                                           hregister:=rg.getregisterint(exprasmlist);
-                                           location.reference.base:=hregister;
-                                           emit_ref_reg(A_MOV,S_L,
-                                             twithnode(twithsymtable(symtable).withnode).withreference,
-                                             hregister);
-                                         end;
-                                        inc(location.reference.offset,tvarsym(symtableentry).address);
-                                     end;
-                                end;
-                           end;
-                         { in case call by reference, then calculate. Open array
-                           is always an reference! }
-                         if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
-                            is_open_array(tvarsym(symtableentry).vartype.def) or
-                            is_array_of_const(tvarsym(symtableentry).vartype.def) or
-                            ((tvarsym(symtableentry).varspez=vs_const) and
-                             push_addr_param(tvarsym(symtableentry).vartype.def)) then
-                           begin
-                              if hregister=R_NO then
-                                hregister:=rg.getregisterint(exprasmlist);
-                              case location.loc of
-                                LOC_CREGISTER :
-                                   emit_reg_reg(A_MOV,S_L,location.register,hregister);
-                                LOC_REFERENCE,
-                                LOC_CREFERENCE :
-                                   emit_ref_reg(A_MOV,S_L,location.reference,hregister);
-                                else
-                                  internalerror(2002032218);
-                              end;
-                              location_reset(location,LOC_REFERENCE,newsize);
-                              location.reference.base:=hregister;
-                          end;
-                      end;
-                 end;
-              procsym:
-                 begin
-                    if assigned(left) then
-                      begin
-                         location_reset(location,LOC_CREFERENCE,OS_64);
-                         tg.gettempofsizereference(exprasmlist,8,location.reference);
-
-                         { called as type.method, then we only need to return
-                           the address of the function, not the self pointer }
-                         if left.nodetype=typen then
-                          begin
-                            { there is no instance, we return 0 }
-                            cg.a_load_const_ref(exprasmlist,OS_ADDR,0,location.reference);
-                          end
-                         else
-                          begin
-                            secondpass(left);
-
-                            { load class instance address }
-                            case left.location.loc of
-
-                               LOC_CREGISTER,
-                               LOC_REGISTER:
-                                 begin
-                                    hregister:=left.location.register;
-                                    if is_object(left.resulttype.def) then
-                                      CGMessage(cg_e_illegal_expression);
-                                 end;
-
-                               LOC_CREFERENCE,
-                               LOC_REFERENCE:
-                                 begin
-                                    rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                    hregister:=R_EDI;
-                                    if is_class_or_interface(left.resulttype.def) then
-                                      emit_ref_reg(A_MOV,S_L,left.location.reference,R_EDI)
-                                    else
-                                      emit_ref_reg(A_LEA,S_L,left.location.reference,R_EDI);
-                                 end;
-                               else internalerror(26019);
-
-                            end;
-                            location_release(exprasmlist,left.location);
-                            location_freetemp(exprasmlist,left.location);
-
-                            { store the class instance address }
-                            href:=location.reference;
-                            inc(href.offset,4);
-                            emit_reg_ref(A_MOV,S_L,hregister,href);
-                          end;
-
-                         { virtual method ? }
-                         if (po_virtualmethod in tprocdef(resulttype.def).procoptions) then
-                           begin
-                              reference_reset_base(href,hregister,0);
-                              { load vmt pointer }
-                              emit_ref_reg(A_MOV,S_L,href,R_EDI);
-{$IfDef regallocfix}
-                              rg.del_reference(exprasmlist,hp^);
-{$EndIf regallocfix}
-                              { load method address }
-                              reference_reset_base(href,R_EDI,tprocdef(resulttype.def)._class.vmtmethodoffset(
-                                                   tprocdef(resulttype.def).extnumber));
-                              emit_ref_reg(A_MOV,S_L,href,R_EDI);
-                              { ... and store it }
-                              cg.a_load_reg_loc(exprasmlist,OS_ADDR,R_EDI,location);
-                              rg.ungetregisterint(exprasmlist,R_EDI);
-                           end
-                         else
-                           begin
-                              reference_reset_symbol(href,newasmsymbol(tprocdef(resulttype.def).mangledname),0);
-                              cg.a_loadaddr_ref_reg(exprasmlist,href,R_EDI);
-                              cg.a_load_reg_loc(exprasmlist,OS_ADDR,R_EDI,location);
-                              rg.ungetregisterint(exprasmlist,R_EDI);
-                           end;
-                      end
-                    else
-                      begin
-                         {!!!!! Be aware, work on virtual methods too }
-                         location.reference.symbol:=newasmsymbol(tprocdef(resulttype.def).mangledname);
-                      end;
-                 end;
-              typedconstsym :
-                 begin
-                    location.reference.symbol:=newasmsymbol(ttypedconstsym(symtableentry).mangledname);
-                 end;
-              else internalerror(4);
-         end;
-      end;
-
-
-{*****************************************************************************
-                             SecondAssignment
-*****************************************************************************}
-
-    procedure ti386assignmentnode.pass_2;
-      var
-         otlabel,hlabel,oflabel : tasmlabel;
-         fputyp : tfloattype;
-         href : treference;
-         ai : taicpu;
-         releaseright,
-         pushed : boolean;
-         cgsize : tcgsize;
-
-      begin
-        otlabel:=truelabel;
-        oflabel:=falselabel;
-        getlabel(truelabel);
-        getlabel(falselabel);
-
-        {
-          in most cases we can process first the right node which contains
-          the most complex code. But not when the result is in the flags, then
-          loading the left node afterwards can destroy the flags.
-
-          when the right node returns as LOC_JUMP then we will generate
-          the following code:
-
-          rightnode
-          true:
-            leftnode
-            assign 1
-          false:
-            leftnode
-            assign 0
-        }
-
-        { Try to determine which side to calculate first,  }
-        if (right.location.loc<>LOC_FLAGS) and
-           ((right.location.loc=LOC_JUMP) or
-            (right.registers32>=left.registers32)) then
-         begin
-           secondpass(right);
-           { increment source reference counter, this is
-             useless for string constants}
-           if (right.resulttype.def.needs_inittable) and
-              (right.nodetype<>stringconstn) then
-            cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
-           if codegenerror then
-             exit;
-
-           { We skip the generation of the left node when it's a jump, see
-             explanation above }
-           if (right.location.loc<>LOC_JUMP) and
-              not(nf_concat_string in flags) then
-            begin
-              { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
-              { can be false                                             }
-              pushed:=maybe_push(left.registers32,right,false);
-              secondpass(left);
-              { decrement destination reference counter }
-              if (left.resulttype.def.needs_inittable) then
-               cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
-              if pushed then
-                restore(right,false);
-              if codegenerror then
-                exit;
-            end;
-         end
-        else
-         begin
-           { calculate left sides }
-           { don't do it yet if it's a crgister (JM) }
-           if not(nf_concat_string in flags) then
-            begin
-              secondpass(left);
-              { decrement destination reference counter }
-              if (left.resulttype.def.needs_inittable) then
-               cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
-              if codegenerror then
-               exit;
-            end;
-
-           { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
-           { can be false                                             }
-           pushed:=maybe_push(right.registers32,left,is_64bitint(right.resulttype.def));
-           secondpass(right);
-           { increment source reference counter, this is
-             useless for string constants}
-           if (right.resulttype.def.needs_inittable) and
-              (right.nodetype<>stringconstn) then
-            cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
-           if pushed  then
-             restore(left,false);
-
-           if codegenerror then
-             exit;
-         end;
-
-        if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
-                                     LOC_CREGISTER,LOC_CMMXREGISTER]) then
-          begin
-             CGMessage(cg_e_illegal_expression);
-             exit;
-          end;
-
-        releaseright:=true;
-
-        { shortstring assignments are handled separately }
-        if is_shortstring(left.resulttype.def) then
-          begin
-            {
-              we can get here only in the following situations
-              for the right node:
-               - empty constant string
-               - char
-            }
-
-            { empty constant string }
-            if (right.nodetype=stringconstn) and
-               (tstringconstnode(right).len=0) then
-              begin
-                emit_const_ref(A_MOV,S_B,0,left.location.reference);
-              end
-            { char loading }
-            else if is_char(right.resulttype.def) then
-              begin
-                if right.nodetype=ordconstn then
-                  emit_const_ref(A_MOV,S_W,tordconstnode(right).value*256+1,left.location.reference)
-                else
-                  begin
-                     if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
-                       begin
-                          href := left.location.reference;
-                          emit_const_ref(A_MOV,S_B,1,href);
-                          inc(href.offset,1);
-                          emit_reg_ref(A_MOV,S_B,rg.makeregsize(right.location.register,OS_8),href);
-                       end
-                     else
-                     { not so elegant (goes better with extra register    }
-                       begin
-                          { not "movl", because then we may read past the }
-                          { end of the heap! "movw" would be ok too, but  }
-                          { I don't think that would be faster (JM)       }
-                          rg.getexplicitregisterint(exprasmlist,R_EDI);
-                          emit_ref_reg(A_MOVZX,S_BL,right.location.reference,R_EDI);
-                          emit_const_reg(A_SHL,S_L,8,R_EDI);
-                          emit_const_reg(A_OR,S_L,1,R_EDI);
-                          emit_reg_ref(A_MOV,S_W,R_DI,left.location.reference);
-                          rg.ungetregisterint(exprasmlist,R_EDI);
-                       end;
-                  end;
-              end
-            else
-              internalerror(200204249);
-          end
-        else
-          begin
-            case right.location.loc of
-              LOC_CONSTANT :
-                begin
-                  if right.location.size in [OS_64,OS_S64] then
-                   tcg64f32(cg).a_load64_const_loc(exprasmlist,
-                       right.location.valuelow,right.location.valuehigh,left.location)
-                  else
-                   cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
-                end;
-              LOC_REFERENCE,
-              LOC_CREFERENCE :
-                begin
-                  case left.location.loc of
-                    LOC_CREGISTER :
-                      begin
-                        cgsize:=def_cgsize(left.resulttype.def);
-                        if cgsize in [OS_64,OS_S64] then
-                         tcg64f32(cg).a_load64_ref_reg(exprasmlist,
-                             right.location.reference,left.location.registerlow,left.location.registerhigh)
-                        else
-                         cg.a_load_ref_reg(exprasmlist,cgsize,
-                             right.location.reference,left.location.register);
-                        location_release(exprasmlist,right.location);
-                      end;
-                    LOC_CFPUREGISTER :
-                      begin
-                        cg.a_loadfpu_ref_reg(exprasmlist,
-                            def_cgsize(right.resulttype.def),
-                            right.location.reference,
-                            left.location.register);
-                      end;
-                    LOC_REFERENCE,
-                    LOC_CREFERENCE :
-                      begin
-                        cg.g_concatcopy(exprasmlist,right.location.reference,
-                                        left.location.reference,left.resulttype.def.size,true,false);
-                        { right.location is already released by concatcopy }
-                        releaseright:=false;
-                      end;
-                    else
-                      internalerror(200203284);
-                  end;
-                end;
-{$ifdef SUPPORT_MMX}
-              LOC_CMMXREGISTER,
-              LOC_MMXREGISTER:
-                begin
-                  if left.location.loc=LOC_CMMXREGISTER then
-                   emit_reg_reg(A_MOVQ,S_NO,right.location.register,left.location.register)
-                  else
-                   emit_reg_ref(A_MOVQ,S_NO,right.location.register,left.location.reference);
-                end;
-{$endif SUPPORT_MMX}
-              LOC_REGISTER,
-              LOC_CREGISTER :
-                begin
-                  cgsize:=def_cgsize(left.resulttype.def);
-                  if cgsize in [OS_64,OS_S64] then
-                   tcg64f32(cg).a_load64_reg_loc(exprasmlist,
-                       right.location.registerlow,right.location.registerhigh,left.location)
-                  else
-                   cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
-                end;
-              LOC_FPUREGISTER,LOC_CFPUREGISTER :
-                begin
-                  if (left.resulttype.def.deftype=floatdef) then
-                   fputyp:=tfloatdef(left.resulttype.def).typ
-                  else
-                   if (right.resulttype.def.deftype=floatdef) then
-                    fputyp:=tfloatdef(right.resulttype.def).typ
-                  else
-                   if (right.nodetype=typeconvn) and
-                      (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
-                    fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
-                  else
-                    fputyp:=s32real;
-                  cg.a_loadfpu_reg_loc(exprasmlist,
-                      tfloat2tcgsize[fputyp],
-                      right.location.register,left.location);
-                end;
-              LOC_JUMP :
-                begin
-                  cgsize:=def_cgsize(left.resulttype.def);
-                  getlabel(hlabel);
-                  { generate the leftnode for the true case, and
-                    release the location }
-                  cg.a_label(exprasmlist,truelabel);
-                  pushed:=maybe_push(left.registers32,right,false);
-                  secondpass(left);
-                  if pushed then
-                    restore(right,false);
-                  if codegenerror then
-                    exit;
-                  cg.a_load_const_loc(exprasmlist,1,left.location);
-                  location_release(exprasmlist,left.location);
-                  cg.a_jmp_always(exprasmlist,hlabel);
-                  { generate the leftnode for the false case }
-                  cg.a_label(exprasmlist,falselabel);
-                  pushed:=maybe_push(left.registers32,right,false);
-                  secondpass(left);
-                  if pushed then
-                    restore(right,false);
-                  if codegenerror then
-                    exit;
-                  cg.a_load_const_loc(exprasmlist,0,left.location);
-                  cg.a_label(exprasmlist,hlabel);
-                end;
-              LOC_FLAGS :
-                begin
-                  if left.location.loc=LOC_CREGISTER then
-                    cg.g_flags2reg(exprasmlist,right.location.resflags,left.location.register)
-                  else
-                    begin
-                      if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
-                       internalerror(200203273);
-                      ai:=Taicpu.Op_ref(A_Setcc,S_B,left.location.reference);
-                      ai.SetCondition(flags_to_cond(right.location.resflags));
-                      exprasmList.concat(ai);
-                    end;
-                end;
-            end;
-
-         end;
-
-        if releaseright then
-         location_release(exprasmlist,right.location);
-        location_release(exprasmlist,left.location);
-
-        truelabel:=otlabel;
-        falselabel:=oflabel;
-      end;
-
-
-{*****************************************************************************
-                             SecondFuncRet
-*****************************************************************************}
-
-    procedure ti386funcretnode.pass_2;
-      var
-         hreg : tregister;
-         href : treference;
-         pp : pprocinfo;
-         hr_valid : boolean;
-         i : integer;
-      begin
-         location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
-         hr_valid:=false;
-         if (not inlining_procedure) and
-            (lexlevel<>funcretsym.owner.symtablelevel) then
-           begin
-              hreg:=rg.getregisterint(exprasmlist);
-              hr_valid:=true;
-              reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
-              emit_ref_reg(A_MOV,S_L,href,hreg);
-
-              { walk up the stack frame }
-              pp:=procinfo^.parent;
-              i:=lexlevel-1;
-              while i>funcretsym.owner.symtablelevel do
-               begin
-                 reference_reset_base(href,hreg,pp^.framepointer_offset);
-                 emit_ref_reg(A_MOV,S_L,href,hreg);
-                 pp:=pp^.parent;
-                 dec(i);
-               end;
-              location.reference.base:=hreg;
-              location.reference.offset:=pp^.return_offset;
-           end
-         else
-           begin
-             location.reference.base:=procinfo^.framepointer;
-             location.reference.offset:=procinfo^.return_offset;
-           end;
-         if ret_in_param(resulttype.def) then
-           begin
-              if not hr_valid then
-                hreg:=rg.getregisterint(exprasmlist);
-              emit_ref_reg(A_MOV,S_L,location.reference,hreg);
-              location.reference.base:=hreg;
-              location.reference.offset:=0;
-           end;
-      end;
-
-begin
-   cloadnode:=ti386loadnode;
-   cassignmentnode:=ti386assignmentnode;
-   cfuncretnode:=ti386funcretnode;
-end.
-{
-  $Log$
-  Revision 1.41  2002-05-12 16:53:17  peter
-    * moved entry and exitcode to ncgutil and cgobj
-    * foreach gets extra argument for passing local data to the
-      iterator function
-    * -CR checks also class typecasts at runtime by changing them
-      into as
-    * fixed compiler to cycle with the -CR option
-    * fixed stabs with elf writer, finally the global variables can
-      be watched
-    * removed a lot of routines from cga unit and replaced them by
-      calls to cgobj
-    * u32bit-s32bit updates for and,or,xor nodes. When one element is
-      u32bit then the other is typecasted also to u32bit without giving
-      a rangecheck warning/error.
-    * fixed pascal calling method with reversing also the high tree in
-      the parast, detected by tcalcst3 test
-
-  Revision 1.40  2002/04/26 15:19:05  peter
-    * use saveregisters for incr routines, saves also problems with
-      the optimizer
-
-  Revision 1.39  2002/04/25 20:16:40  peter
-    * moved more routines from cga/n386util
-
-  Revision 1.38  2002/04/22 16:30:06  peter
-    * fixed @methodpointer
-
-  Revision 1.37  2002/04/21 15:36:13  carl
-  * changeregsize -> rg.makeregsize
-
-  Revision 1.36  2002/04/19 15:39:35  peter
-    * removed some more routines from cga
-    * moved location_force_reg/mem to ncgutil
-    * moved arrayconstructnode secondpass to ncgld
-
-  Revision 1.35  2002/04/15 19:44:21  peter
-    * fixed stackcheck that would be called recursively when a stack
-      error was found
-    * generic changeregsize(reg,size) for i386 register resizing
-    * removed some more routines from cga unit
-    * fixed returnvalue handling
-    * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
-
-  Revision 1.34  2002/04/07 09:16:07  carl
-  - remove unused variable
-
-  Revision 1.33  2002/04/04 19:06:12  peter
-    * removed unused units
-    * use tlocation.size in cg.a_*loc*() routines
-
-  Revision 1.32  2002/04/03 10:43:37  jonas
-    * fixed regvar-related bugs (the load node set the location to
-      LOC_REGISTER instead of LOC_CREGISTER and the assignment node didn't
-      support loading constants in LOC_CREGISTER's)
-
-  Revision 1.31  2002/04/02 17:11:36  peter
-    * tlocation,treference update
-    * LOC_CONSTANT added for better constant handling
-    * secondadd splitted in multiple routines
-    * location_force_reg added for loading a location to a register
-      of a specified size
-    * secondassignment parses now first the right and then the left node
-      (this is compatible with Kylix). This saves a lot of push/pop especially
-      with string operations
-    * adapted some routines to use the new cg methods
-
-  Revision 1.30  2002/03/31 20:26:39  jonas
-    + a_loadfpu_* and a_loadmm_* methods in tcg
-    * register allocation is now handled by a class and is mostly processor
-      independent (+rgobj.pas and i386/rgcpu.pas)
-    * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
-    * some small improvements and fixes to the optimizer
-    * some register allocation fixes
-    * some fpuvaroffset fixes in the unary minus node
-    * push/popusedregisters is now called rg.save/restoreusedregisters and
-      (for i386) uses temps instead of push/pop's when using -Op3 (that code is
-      also better optimizable)
-    * fixed and optimized register saving/restoring for new/dispose nodes
-    * LOC_FPU locations now also require their "register" field to be set to
-      R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
-    - list field removed of the tnode class because it's not used currently
-      and can cause hard-to-find bugs
-
-  Revision 1.29  2002/03/04 19:10:14  peter
-    * removed compiler warnings
-
-  Revision 1.28  2001/12/30 17:24:46  jonas
-    * range checking is now processor independent (part in cgobj,
-      part in cg64f32) and should work correctly again (it needed
-      some changes after the changes of the low and high of
-      tordef's to int64)
-    * maketojumpbool() is now processor independent (in ncgutil)
-    * getregister32 is now called getregisterint
-
-  Revision 1.27  2001/12/17 23:16:05  florian
-    * array of const can now take widestring parameters as well
-
-  Revision 1.26  2001/11/02 22:58:11  peter
-    * procsym definition rewrite
-
-  Revision 1.25  2001/10/28 17:22:25  peter
-    * allow assignment of overloaded procedures to procvars when we know
-      which procedure to take
-
-  Revision 1.24  2001/10/14 11:49:51  jonas
-    * finetuned register allocation info for assignments
-
-  Revision 1.23  2001/10/04 14:33:28  jonas
-    * fixed range check errors
-
-  Revision 1.22  2001/09/09 08:51:09  jonas
-    * fixed bug with assigning ansistrings (left^.location was released too
-      early, caused bug reported by Aleksey V. Vaneev in mailing list on
-      2001/09/07 regarding 'problems with nested procedures and local vars'
-      ("merged" from cga.pas in the fixes branch)
-
-  Revision 1.21  2001/08/30 20:13:57  peter
-    * rtti/init table updates
-    * rttisym for reusable global rtti/init info
-    * support published for interfaces
-
-  Revision 1.20  2001/08/30 11:57:20  michael
-  + Patch for wrong paramsize
-
-  Revision 1.19  2001/08/26 13:36:59  florian
-    * some cg reorganisation
-    * some PPC updates
-
-  Revision 1.18  2001/08/06 21:40:50  peter
-    * funcret moved from tprocinfo to tprocdef
-
-  Revision 1.17  2001/08/05 13:19:51  peter
-    * partly fix for proc of obj=nil
-
-  Revision 1.15  2001/07/28 15:13:17  peter
-    * fixed opsize for assignment with LOC_JUMP
-
-  Revision 1.14  2001/05/27 14:30:56  florian
-    + some widestring stuff added
-
-  Revision 1.13  2001/04/13 01:22:19  peter
-    * symtable change to classes
-    * range check generation and errors fixed, make cycle DEBUG=1 works
-    * memory leaks fixed
-
-  Revision 1.12  2001/04/02 21:20:37  peter
-    * resulttype rewrite
-
-  Revision 1.11  2000/12/25 00:07:33  peter
-    + new tlinkedlist class (merge of old tstringqueue,tcontainer and
-      tlinkedlist objects)
-
-  Revision 1.10  2000/12/05 11:44:33  jonas
-    + new integer regvar handling, should be much more efficient
-
-  Revision 1.9  2000/11/29 00:30:48  florian
-    * unused units removed from uses clause
-    * some changes for widestrings
-
-  Revision 1.8  2000/11/13 14:44:36  jonas
-    * fixes so no more range errors with improved range checking code
-
-  Revision 1.7  2000/11/12 23:24:15  florian
-    * interfaces are basically running
-
-  Revision 1.6  2000/11/11 22:59:20  florian
-    * fixed resourcestrings, made a stupid mistake yesterday
-
-  Revision 1.5  2000/11/09 18:52:06  florian
-    * resourcestrings doesn't need the helper anymore they
-      access the table now direct
-
-  Revision 1.4  2000/11/06 23:15:02  peter
-    * added copyvaluepara call again
-
-  Revision 1.3  2000/11/04 14:25:23  florian
-    + merged Attila's changes for interfaces, not tested yet
-
-  Revision 1.2  2000/10/31 22:02:56  peter
-    * symtable splitted, no real code changes
-
-  Revision 1.1  2000/10/15 09:33:31  peter
-    * moved n386*.pas to i386/ cpu_target dir
-
-  Revision 1.1  2000/10/14 10:14:49  peter
-    * moehrendorf oct 2000 rewrite
-
-}

+ 14 - 11
compiler/i386/n386mat.pas

@@ -56,7 +56,7 @@ implementation
       cginfo,cgbase,pass_1,pass_2,
       ncon,
       cpubase,
-      cga,tgobj,n386util,ncgutil,cgobj,rgobj,rgcpu;
+      cga,tgobj,ncgutil,cgobj,rgobj,rgcpu;
 
 {*****************************************************************************
                              TI386MODDIVNODE
@@ -66,18 +66,18 @@ implementation
       var
          hreg1 : tregister;
          hreg2 : tregister;
-         shrdiv, pushed,popeax,popedx : boolean;
+         shrdiv,popeax,popedx : boolean;
          power : longint;
          hl : tasmlabel;
+         pushedregs : tmaybesave;
       begin
          shrdiv := false;
          secondpass(left);
          if codegenerror then
           exit;
-         pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
+         maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
          secondpass(right);
-         if pushed then
-           restore(left,is_64bitint(left.resulttype.def));
+         maybe_restore(exprasmlist,left.location,pushedregs);
          if codegenerror then
           exit;
          location_copy(location,left.location);
@@ -270,18 +270,17 @@ implementation
       var
          hregister2,hregister3,
          hregisterhigh,hregisterlow : tregister;
-         pushed,popecx : boolean;
+         popecx : boolean;
          op : tasmop;
          l1,l2,l3 : tasmlabel;
-
+         pushedregs : tmaybesave;
       begin
          popecx:=false;
 
          secondpass(left);
-         pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
+         maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
          secondpass(right);
-         if pushed then
-           restore(left,is_64bitint(left.resulttype.def));
+         maybe_restore(exprasmlist,left.location,pushedregs);
 
          { determine operator }
          case nodetype of
@@ -831,7 +830,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.27  2002-05-12 16:53:17  peter
+  Revision 1.28  2002-05-13 19:54:38  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.27  2002/05/12 16:53:17  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 9 - 7
compiler/i386/n386mem.pas

@@ -54,7 +54,7 @@ implementation
       cginfo,cgbase,pass_2,
       pass_1,nld,ncon,nadd,
       cpubase,
-      cgobj,cga,tgobj,rgobj,ncgutil,n386util;
+      cgobj,cga,tgobj,rgobj,ncgutil;
 
 {*****************************************************************************
                              TI386ADDRNODE
@@ -99,8 +99,6 @@ implementation
 *****************************************************************************}
 
     procedure ti386vecnode.pass_2;
-      var
-        is_pushed : boolean;
 
           function get_mul_size:longint;
           begin
@@ -146,6 +144,7 @@ implementation
          isjump  : boolean;
          otl,ofl : tasmlabel;
          newsize : tcgsize;
+         pushedregs : tmaybesave;
       begin
          newsize:=def_cgsize(resulttype.def);
          location_reset(location,LOC_REFERENCE,newsize);
@@ -397,10 +396,9 @@ implementation
                  ofl:=falselabel;
                  getlabel(falselabel);
                end;
-              is_pushed:=maybe_push(right.registers32,self,false);
+              maybe_save(exprasmlist,right.registers32,location,pushedregs);
               secondpass(right);
-              if is_pushed then
-                restore(self,false);
+              maybe_restore(exprasmlist,location,pushedregs);
               { here we change the location of right
                 and the update was forgotten so it
                 led to wrong code in emitrangecheck later PM
@@ -521,7 +519,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.29  2002-05-12 16:53:17  peter
+  Revision 1.30  2002-05-13 19:54:38  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.29  2002/05/12 16:53:17  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 6 - 2
compiler/i386/n386opt.pas

@@ -47,7 +47,7 @@ uses
   aasm,
   ncnv, ncon, pass_2,
   cginfo, cgbase, cpubase,
-  tgobj, rgobj, cgobj, n386util;
+  tgobj, rgobj, cgobj, ncgutil;
 
 
 {*****************************************************************************
@@ -248,7 +248,11 @@ end.
 
 {
   $Log$
-  Revision 1.13  2002-05-12 16:53:17  peter
+  Revision 1.14  2002-05-13 19:54:38  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.13  2002/05/12 16:53:17  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 12 - 11
compiler/i386/n386set.pas

@@ -50,7 +50,7 @@ implementation
       cginfo,cgbase,pass_2,
       ncon,
       cpubase,
-      cga,cgobj,tgobj,ncgutil,n386util,regvars,rgobj;
+      cga,cgobj,tgobj,ncgutil,regvars,rgobj;
 
      const
        bytes2Sxx:array[1..8] of Topsize=(S_B,S_W,S_NO,S_L,S_NO,S_NO,S_NO,S_Q);
@@ -61,7 +61,7 @@ implementation
 
     procedure ti386setelementnode.pass_2;
        var
-         pushed: boolean;
+         pushedregs : tmaybesave;
        begin
        { load first value in 32bit register }
          secondpass(left);
@@ -71,12 +71,11 @@ implementation
        { also a second value ? }
          if assigned(right) then
            begin
-             pushed:=maybe_push(right.registers32,left,false);
+             maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
              secondpass(right);
              if codegenerror then
                exit;
-             if pushed then
-               restore(left,false);
+             maybe_restore(exprasmlist,left.location,pushedregs);
              if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
               location_force_reg(exprasmlist,right.location,OS_32,false);
            end;
@@ -99,7 +98,6 @@ implementation
        var
          genjumps,
          use_small,
-         pushed,
          ranges     : boolean;
          hr,hr2,
          pleftreg   : tregister;
@@ -108,7 +106,7 @@ implementation
          setparts   : array[1..8] of Tsetpart;
          i,numparts : byte;
          adjustment : longint;
-         {href,href2 : Treference;}
+         pushedregs : tmaybesave;
          l,l2       : tasmlabel;
 {$ifdef CORRECT_SET_IN_FPC}
          AM         : tasmop;
@@ -194,10 +192,9 @@ implementation
          { Only process the right if we are not generating jumps }
          if not genjumps then
           begin
-            pushed:=maybe_push(right.registers32,left,false);
+            maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
             secondpass(right);
-            if pushed then
-             restore(left,false);
+            maybe_restore(exprasmlist,left.location,pushedregs);
           end;
          if codegenerror then
           exit;
@@ -1019,7 +1016,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.27  2002-05-12 16:53:17  peter
+  Revision 1.28  2002-05-13 19:54:38  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.27  2002/05/12 16:53:17  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 0 - 760
compiler/i386/n386util.pas

@@ -1,760 +0,0 @@
-{
-    $Id$
-    Copyright (c) 1998-2000 by Florian Klaempfl
-
-    Helper routines for the i386 code generator
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ****************************************************************************
-}
-unit n386util;
-
-{$i defines.inc}
-
-interface
-
-    uses
-      symtype,node,cpubase,cginfo;
-
-    function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
-    function maybe_pushfpu(needed : byte;p : tnode) : boolean;
-{$ifdef TEMPS_NOT_PUSH}
-    function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
-{$endif TEMPS_NOT_PUSH}
-    procedure restore(p : tnode;isint64 : boolean);
-{$ifdef TEMPS_NOT_PUSH}
-    procedure restorefromtemp(p : tnode;isint64 : boolean);
-{$endif TEMPS_NOT_PUSH}
-    procedure remove_non_regvars_from_loc(const t: tlocation; var regs: tregisterset);
-    procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
-                              para_offset:longint;alignment : longint);
-
-    procedure emitoverflowcheck(p:tnode);
-    procedure firstcomplex(p : tbinarynode);
-
-
-implementation
-
-    uses
-       globtype,globals,systems,verbose,
-       cutils,
-       aasm,cpuasm,
-       symconst,symdef,
-{$ifdef GDB}
-       gdb,
-{$endif GDB}
-       types,
-       ncgutil,ncon,nld,
-       cgbase,tgobj,
-       cga,regvars,cgobj,cg64f32,rgobj,rgcpu,cgcpu;
-
-
-{*****************************************************************************
-                           Emit Push Functions
-*****************************************************************************}
-
-    function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
-      var
-         pushed : boolean;
-         {hregister : tregister; }
-{$ifdef TEMPS_NOT_PUSH}
-         href : treference;
-{$endif TEMPS_NOT_PUSH}
-      begin
-         if p.location.loc = LOC_CREGISTER then
-           begin
-             maybe_push := true;
-             exit;
-           end;
-         if needed>rg.countunusedregsint then
-           begin
-              if (p.location.loc=LOC_REGISTER) then
-                begin
-                   if isint64 then
-                     begin
-{$ifdef TEMPS_NOT_PUSH}
-                        tg.gettempofsizereference(exprasmlist,href,8);
-                        p.temp_offset:=href.offset;
-                        href.offset:=href.offset+4;
-                        exprasmList.concat(Taicpu.Op_reg(A_MOV,S_L,p.location.registerhigh,href));
-                        href.offset:=href.offset-4;
-{$else TEMPS_NOT_PUSH}
-                        exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.location.registerhigh));
-{$endif TEMPS_NOT_PUSH}
-                        rg.ungetregisterint(exprasmlist,p.location.registerhigh);
-                     end
-{$ifdef TEMPS_NOT_PUSH}
-                   else
-                     begin
-                        tg.gettempofsizereference(exprasmlist,href,4);
-                        p.temp_offset:=href.offset;
-                     end
-{$endif TEMPS_NOT_PUSH}
-                     ;
-                   pushed:=true;
-{$ifdef TEMPS_NOT_PUSH}
-                   exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,p.location.register,href));
-{$else TEMPS_NOT_PUSH}
-                   exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.location.register));
-{$endif TEMPS_NOT_PUSH}
-                   rg.ungetregisterint(exprasmlist,p.location.register);
-                end
-              else if (p.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
-                      ((p.location.reference.base<>R_NO) or
-                       (p.location.reference.index<>R_NO)
-                      ) then
-                  begin
-                     reference_release(exprasmlist,p.location.reference);
-                     rg.getexplicitregisterint(exprasmlist,R_EDI);
-                     emit_ref_reg(A_LEA,S_L,p.location.reference,R_EDI);
-{$ifdef TEMPS_NOT_PUSH}
-                     tg.gettempofsizereference(exprasmlist,href,4);
-                     exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
-                     p.temp_offset:=href.offset;
-{$else TEMPS_NOT_PUSH}
-                     exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,R_EDI));
-{$endif TEMPS_NOT_PUSH}
-                     rg.ungetregisterint(exprasmlist,R_EDI);
-                     pushed:=true;
-                  end
-              else pushed:=false;
-           end
-         else pushed:=false;
-         maybe_push:=pushed;
-      end;
-
-
-     function maybe_pushfpu(needed : byte;p : tnode) : boolean;
-       begin
-         if needed>=maxfpuregs then
-           begin
-             if p.location.loc = LOC_FPUREGISTER then
-               begin
-                 location_force_mem(exprasmlist,p.location);
-                 maybe_pushfpu:=true;
-               end
-             else
-               maybe_pushfpu:=false;
-           end
-         else
-           maybe_pushfpu:=false;
-       end;
-
-
-{$ifdef TEMPS_NOT_PUSH}
-    function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
-
-      var
-         pushed : boolean;
-         href : treference;
-
-      begin
-         if needed>rg.unusedregsint then
-           begin
-              if (p^.location.loc=LOC_REGISTER) then
-                begin
-                   if isint64(p^.resulttype.def) then
-                     begin
-                        tg.gettempofsizereference(exprasmlist,href,8);
-                        p^.temp_offset:=href.offset;
-                        href.offset:=href.offset+4;
-                        exprasmList.concat(Taicpu.Op_reg(A_MOV,S_L,p^.location.registerhigh,href));
-                        href.offset:=href.offset-4;
-                        rg.ungetregisterint(exprasmlist,p^.location.registerhigh);
-                     end
-                   else
-                     begin
-                        tg.gettempofsizereference(exprasmlist,href,4);
-                        p^.temp_offset:=href.offset;
-                     end;
-                   pushed:=true;
-                   exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,p^.location.register,href));
-                   rg.ungetregisterint(exprasmlist,p^.location.register);
-                end
-              else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
-                      ((p^.location.reference.base<>R_NO) or
-                       (p^.location.reference.index<>R_NO)
-                      ) then
-                  begin
-                     reference_release(p^.location.reference);
-                     rg.getexplicitregisterint(exprasmlist,R_EDI);
-                     emit_ref_reg(A_LEA,S_L,reference_copy(p^.location.reference),
-                       R_EDI);
-                     tg.gettempofsizereference(exprasmlist,href,4);
-                     exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
-                     rg.ungetregisterint(exprasmlist,R_EDI);
-                     p^.temp_offset:=href.offset;
-                     pushed:=true;
-                  end
-              else pushed:=false;
-           end
-         else pushed:=false;
-         maybe_push:=pushed;
-      end;
-{$endif TEMPS_NOT_PUSH}
-
-
-    procedure restore(p : tnode;isint64 : boolean);
-      var
-         hregister :  tregister;
-{$ifdef TEMPS_NOT_PUSH}
-         href : treference;
-{$endif TEMPS_NOT_PUSH}
-      begin
-         if p.location.loc = LOC_CREGISTER then
-           begin
-             load_regvar_reg(exprasmlist,p.location.register);
-             exit;
-           end;
-         hregister:=rg.getregisterint(exprasmlist);
-{$ifdef TEMPS_NOT_PUSH}
-         reset_reference(href);
-         href.base:=procinfo^.frame_pointer_reg;
-         href.offset:=p.temp_offset;
-         emit_ref_reg(A_MOV,S_L,href,hregister);
-{$else  TEMPS_NOT_PUSH}
-         exprasmList.concat(Taicpu.Op_reg(A_POP,S_L,hregister));
-{$endif TEMPS_NOT_PUSH}
-         if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
-           begin
-              p.location.register:=hregister;
-              if isint64 then
-                begin
-                   p.location.registerhigh:=rg.getregisterint(exprasmlist);
-{$ifdef TEMPS_NOT_PUSH}
-                   href.offset:=p.temp_offset+4;
-                   emit_ref_reg(A_MOV,S_L,p.location.registerhigh);
-                   { set correctly for release ! }
-                   href.offset:=p.temp_offset;
-{$else  TEMPS_NOT_PUSH}
-                   exprasmList.concat(Taicpu.Op_reg(A_POP,S_L,p.location.registerhigh));
-{$endif TEMPS_NOT_PUSH}
-                end;
-           end
-         else
-           begin
-              reference_reset(p.location.reference);
-              { any reasons why this was moved into the index register ? }
-              { normally usage of base register is much better (FK)      }
-              p.location.reference.base:=hregister;
-              { Why is this done? We can never be sure about p.left
-                because otherwise secondload fails !!!
-              set_location(p.left^.location,p.location);}
-           end;
-{$ifdef TEMPS_NOT_PUSH}
-         tg.ungetiftemp(exprasmlist,href);
-{$endif TEMPS_NOT_PUSH}
-      end;
-
-
-{$ifdef TEMPS_NOT_PUSH}
-    procedure restorefromtemp(p : tnode;isint64 : boolean);
-      var
-         hregister :  tregister;
-         href : treference;
-
-      begin
-         hregister:=rg.getregisterint(exprasmlist);
-         reset_reference(href);
-         href.base:=procinfo^.frame_pointer_reg;
-         href.offset:=p.temp_offset;
-         emit_ref_reg(A_MOV,S_L,href,hregister);
-         if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
-           begin
-              p.location.register:=hregister;
-              if isint64 then
-                begin
-                   p.location.registerhigh:=rg.getregisterint(exprasmlist);
-                   href.offset:=p.temp_offset+4;
-                   emit_ref_reg(A_MOV,S_L,p.location.registerhigh);
-                   { set correctly for release ! }
-                   href.offset:=p.temp_offset;
-                end;
-           end
-         else
-           begin
-              reset_reference(p.location.reference);
-              p.location.reference.base:=hregister;
-              { Why is this done? We can never be sure about p^.left
-                because otherwise secondload fails PM
-              set_location(p^.left^.location,p^.location);}
-           end;
-         tg.ungetiftemp(exprasmlist,href);
-      end;
-{$endif TEMPS_NOT_PUSH}
-
-    { only usefull in startup code }
-    procedure remove_non_regvars_from_loc(const t: tlocation; var regs: tregisterset);
-      begin
-        case t.loc of
-          LOC_REGISTER:
-            begin
-              { can't be a regvar, since it would be LOC_CREGISTER then }
-              exclude(regs,t.register);
-              if t.registerhigh <> R_NO then
-                exclude(regs,t.registerhigh);
-            end;
-          LOC_CREFERENCE,LOC_REFERENCE:
-            begin
-              if not(cs_regalloc in aktglobalswitches) or
-                 (t.reference.base in rg.usableregsint) then
-                exclude(regs,t.reference.base);
-              if not(cs_regalloc in aktglobalswitches) or
-                 (t.reference.index in rg.usableregsint) then
-              exclude(regs,t.reference.index);
-            end;
-        end;
-      end;
-
-
-    procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
-                                para_offset:longint;alignment : longint);
-      var
-        tempreference : treference;
-        href : treference;
-        hreg : tregister;
-        sizetopush,
-        size : longint;
-        cgsize : tcgsize;
-      begin
-        { 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);
-
-        { Handle Floating point types differently }
-        if p.resulttype.def.deftype=floatdef then
-         begin
-           case p.location.loc of
-             LOC_FPUREGISTER,
-             LOC_CFPUREGISTER:
-               begin
-                  size:=align(tfloatdef(p.resulttype.def).size,alignment);
-                  inc(pushedparasize,size);
-                  if not inlined then
-                   emit_const_reg(A_SUB,S_L,size,R_ESP);
-{$ifdef GDB}
-                  if (cs_debuginfo in aktmoduleswitches) and
-                     (exprasmList.first=exprasmList.last) then
-                    exprasmList.concat(Tai_force_line.Create);
-{$endif GDB}
-
-                  { this is the easiest case for inlined !! }
-                  if inlined then
-                   reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize)
-                  else
-                   reference_reset_base(href,R_ESP,0);
-
-                  cg.a_loadfpu_reg_ref(exprasmlist,
-                    def_cgsize(p.resulttype.def),p.location.register,href);
-               end;
-             LOC_REFERENCE,
-             LOC_CREFERENCE :
-               begin
-                 sizetopush:=align(p.resulttype.def.size,alignment);
-                 tempreference:=p.location.reference;
-                 inc(tempreference.offset,sizetopush);
-                 while (sizetopush>0) do
-                  begin
-                    if sizetopush>=4 then
-                     begin
-                       cgsize:=OS_32;
-                       inc(pushedparasize,4);
-                       dec(tempreference.offset,4);
-                       dec(sizetopush,4);
-                     end
-                    else
-                     begin
-                       cgsize:=OS_16;
-                       inc(pushedparasize,2);
-                       dec(tempreference.offset,2);
-                       dec(sizetopush,2);
-                     end;
-                    if inlined then
-                     begin
-                       reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
-                       cg.a_load_ref_ref(exprasmlist,cgsize,tempreference,href);
-                     end
-                    else
-                     cg.a_param_ref(exprasmlist,cgsize,tempreference,-1);
-                  end;
-               end;
-             else
-               internalerror(200204243);
-           end;
-         end
-        else
-         begin
-           { call by value open array ? }
-           if is_cdecl and
-              push_addr_param(p.resulttype.def) then
-            begin
-              if not (p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
-                internalerror(200204241);
-              { push on stack }
-              size:=align(p.resulttype.def.size,alignment);
-              inc(pushedparasize,size);
-              emit_const_reg(A_SUB,S_L,size,R_ESP);
-              reference_reset_base(href,R_ESP,0);
-              cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false);
-            end
-           else
-            begin
-              case p.location.loc of
-                LOC_CONSTANT,
-                LOC_REGISTER,
-                LOC_CREGISTER,
-                LOC_REFERENCE,
-                LOC_CREFERENCE :
-                  begin
-                    cgsize:=def_cgsize(p.resulttype.def);
-                    if cgsize in [OS_64,OS_S64] then
-                     begin
-                       inc(pushedparasize,8);
-                       if inlined then
-                        begin
-                          reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
-                          tcg64f32(cg).a_load64_loc_ref(exprasmlist,p.location,href);
-                        end
-                       else
-                        tcg64f32(cg).a_param64_loc(exprasmlist,p.location,-1);
-                     end
-                    else
-                     begin
-                       case cgsize of
-                         OS_8,OS_S8 :
-                           begin
-                             if alignment=4 then
-                              cgsize:=OS_32
-                             else
-                              cgsize:=OS_16;
-                           end;
-                         OS_16,OS_S16 :
-                           begin
-                             if alignment=4 then
-                              cgsize:=OS_32;
-                           end;
-                       end;
-                       { update register to use to match alignment }
-                       if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-                        begin
-                          hreg:=p.location.register;
-                          p.location.register:=rg.makeregsize(p.location.register,cgsize);
-                        end;
-                       inc(pushedparasize,alignment);
-                       if inlined then
-                        begin
-                          reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
-                          cg.a_load_loc_ref(exprasmlist,p.location,href);
-                        end
-                       else
-                        cg.a_param_loc(exprasmlist,p.location,-1);
-                       { restore old register }
-                       if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-                         p.location.register:=hreg;
-                     end;
-                    location_release(exprasmlist,p.location);
-                  end;
-{$ifdef SUPPORT_MMX}
-                LOC_MMXREGISTER,
-                LOC_CMMXREGISTER:
-                  begin
-                     inc(pushedparasize,8);
-                     if inlined then
-                       begin
-                          reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
-                          cg.a_loadmm_reg_ref(exprasmlist,p.location.register,href);
-                       end
-                     else
-                      cg.a_parammm_reg(exprasmlist,p.location.register);
-                  end;
-{$endif SUPPORT_MMX}
-                else
-                  internalerror(200204241);
-              end;
-           end;
-         end;
-      end;
-
-{*****************************************************************************
-                           Emit Functions
-*****************************************************************************}
-
-    { produces if necessary overflowcode }
-    procedure emitoverflowcheck(p:tnode);
-      var
-         hl : tasmlabel;
-      begin
-         if not(cs_check_overflow in aktlocalswitches) then
-          exit;
-         getlabel(hl);
-         if not ((p.resulttype.def.deftype=pointerdef) or
-                ((p.resulttype.def.deftype=orddef) and
-                 (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
-                                                  bool8bit,bool16bit,bool32bit]))) then
-           emitjmp(C_NO,hl)
-         else
-           emitjmp(C_NB,hl);
-         cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
-         cg.a_label(exprasmlist,hl);
-      end;
-
-   { DO NOT RELY on the fact that the tnode is not yet swaped
-     because of inlining code PM }
-    procedure firstcomplex(p : tbinarynode);
-      var
-         hp : tnode;
-      begin
-         { always calculate boolean AND and OR from left to right }
-         if (p.nodetype in [orn,andn]) and
-            (p.left.resulttype.def.deftype=orddef) and
-            (torddef(p.left.resulttype.def).typ in [bool8bit,bool16bit,bool32bit]) then
-           begin
-             { p.swaped:=false}
-             if nf_swaped in p.flags then
-               internalerror(234234);
-           end
-         else
-           if (((p.location.loc=LOC_FPUREGISTER) and
-                (p.right.registersfpu > p.left.registersfpu)) or
-               ((((p.left.registersfpu = 0) and
-                  (p.right.registersfpu = 0)) or
-                 (p.location.loc<>LOC_FPUREGISTER)) and
-                (p.left.registers32<p.right.registers32))) and
-           { the following check is appropriate, because all }
-           { 4 registers are rarely used and it is thereby   }
-           { achieved that the extra code is being dropped   }
-           { by exchanging not commutative operators     }
-               (p.right.registers32<=4) then
-            begin
-              hp:=p.left;
-              p.left:=p.right;
-              p.right:=hp;
-              if nf_swaped in p.flags then
-                exclude(p.flags,nf_swaped)
-              else
-                include(p.flags,nf_swaped);
-            end;
-         {else
-           p.swaped:=false; do not modify }
-      end;
-
-end.
-{
-  $Log$
-  Revision 1.36  2002-05-12 16:53:18  peter
-    * moved entry and exitcode to ncgutil and cgobj
-    * foreach gets extra argument for passing local data to the
-      iterator function
-    * -CR checks also class typecasts at runtime by changing them
-      into as
-    * fixed compiler to cycle with the -CR option
-    * fixed stabs with elf writer, finally the global variables can
-      be watched
-    * removed a lot of routines from cga unit and replaced them by
-      calls to cgobj
-    * u32bit-s32bit updates for and,or,xor nodes. When one element is
-      u32bit then the other is typecasted also to u32bit without giving
-      a rangecheck warning/error.
-    * fixed pascal calling method with reversing also the high tree in
-      the parast, detected by tcalcst3 test
-
-  Revision 1.35  2002/04/25 20:16:40  peter
-    * moved more routines from cga/n386util
-
-  Revision 1.34  2002/04/21 15:39:41  carl
-  * changeregsize -> rg.makeregsize
-
-  Revision 1.33  2002/04/20 21:37:07  carl
-  + generic FPC_CHECKPOINTER
-  + first parameter offset in stack now portable
-  * rename some constants
-  + move some cpu stuff to other units
-  - remove unused constents
-  * fix stacksize for some targets
-  * fix generic size problems which depend now on EXTEND_SIZE constant
-  * removing frame pointer in routines is only available for : i386,m68k and vis targets
-
-  Revision 1.32  2002/04/19 15:39:35  peter
-    * removed some more routines from cga
-    * moved location_force_reg/mem to ncgutil
-    * moved arrayconstructnode secondpass to ncgld
-
-  Revision 1.31  2002/04/15 19:44:21  peter
-    * fixed stackcheck that would be called recursively when a stack
-      error was found
-    * generic changeregsize(reg,size) for i386 register resizing
-    * removed some more routines from cga unit
-    * fixed returnvalue handling
-    * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
-
-  Revision 1.30  2002/04/04 19:06:12  peter
-    * removed unused units
-    * use tlocation.size in cg.a_*loc*() routines
-
-  Revision 1.29  2002/04/04 07:56:15  michael
-  * Patch from peter to fix go32v2 cycle
-
-  Revision 1.28  2002/04/02 17:11:37  peter
-    * tlocation,treference update
-    * LOC_CONSTANT added for better constant handling
-    * secondadd splitted in multiple routines
-    * location_force_reg added for loading a location to a register
-      of a specified size
-    * secondassignment parses now first the right and then the left node
-      (this is compatible with Kylix). This saves a lot of push/pop especially
-      with string operations
-    * adapted some routines to use the new cg methods
-
-  Revision 1.27  2002/03/31 20:26:40  jonas
-    + a_loadfpu_* and a_loadmm_* methods in tcg
-    * register allocation is now handled by a class and is mostly processor
-      independent (+rgobj.pas and i386/rgcpu.pas)
-    * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
-    * some small improvements and fixes to the optimizer
-    * some register allocation fixes
-    * some fpuvaroffset fixes in the unary minus node
-    * push/popusedregisters is now called rg.save/restoreusedregisters and
-      (for i386) uses temps instead of push/pop's when using -Op3 (that code is
-      also better optimizable)
-    * fixed and optimized register saving/restoring for new/dispose nodes
-    * LOC_FPU locations now also require their "register" field to be set to
-      R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
-    - list field removed of the tnode class because it's not used currently
-      and can cause hard-to-find bugs
-
-  Revision 1.26  2002/03/04 19:10:14  peter
-    * removed compiler warnings
-
-  Revision 1.25  2001/12/30 17:24:47  jonas
-    * range checking is now processor independent (part in cgobj,
-      part in cg64f32) and should work correctly again (it needed
-      some changes after the changes of the low and high of
-      tordef's to int64)
-    * maketojumpbool() is now processor independent (in ncgutil)
-    * getregister32 is now called getregisterint
-
-  Revision 1.24  2001/12/03 21:48:43  peter
-    * freemem change to value parameter
-    * torddef low/high range changed to int64
-
-  Revision 1.23  2001/12/02 16:19:17  jonas
-    * less unnecessary regvar loading with if-statements
-
-  Revision 1.22  2001/10/12 13:51:52  jonas
-    * fixed internalerror(10) due to previous fpu overflow fixes ("merged")
-    * fixed bug in n386add (introduced after compilerproc changes for string
-      operations) where calcregisters wasn't called for shortstring addnodes
-    * NOTE: from now on, the location of a binary node must now always be set
-       before you call calcregisters() for it
-
-  Revision 1.21  2001/09/17 21:29:14  peter
-    * merged netbsd, fpu-overflow from fixes branch
-
-  Revision 1.20  2001/08/26 13:37:01  florian
-    * some cg reorganisation
-    * some PPC updates
-
-  Revision 1.19  2001/08/24 12:22:14  jonas
-    * fixed memory leak with coping of array-of-consts as valuepara
-
-  Revision 1.18  2001/07/08 21:00:18  peter
-    * various widestring updates, it works now mostly without charset
-      mapping supported
-
-  Revision 1.17  2001/07/01 20:16:20  peter
-    * alignmentinfo record added
-    * -Oa argument supports more alignment settings that can be specified
-      per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
-      RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
-      required alignment and the maximum usefull alignment. The final
-      alignment will be choosen per variable size dependent on these
-      settings
-
-  Revision 1.16  2001/04/18 22:02:03  peter
-    * registration of targets and assemblers
-
-  Revision 1.15  2001/04/13 01:22:19  peter
-    * symtable change to classes
-    * range check generation and errors fixed, make cycle DEBUG=1 works
-    * memory leaks fixed
-
-  Revision 1.14  2001/04/02 21:20:39  peter
-    * resulttype rewrite
-
-  Revision 1.13  2001/03/11 22:58:52  peter
-    * getsym redesign, removed the globals srsym,srsymtable
-
-  Revision 1.12  2001/03/04 10:26:56  jonas
-    * new rangecheck code now handles conversion between signed and cardinal types correctly
-
-  Revision 1.11  2001/03/03 12:41:22  jonas
-    * simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary
-
-  Revision 1.10  2000/12/31 11:02:12  jonas
-    * optimized loadshortstring a bit
-
-  Revision 1.9  2000/12/25 00:07:33  peter
-    + new tlinkedlist class (merge of old tstringqueue,tcontainer and
-      tlinkedlist objects)
-
-  Revision 1.8  2000/12/11 19:10:19  jonas
-    * fixed web bug 1144
-    + implemented range checking for 64bit types
-
-  Revision 1.7  2000/12/07 17:19:46  jonas
-    * new constant handling: from now on, hex constants >$7fffffff are
-      parsed as unsigned constants (otherwise, $80000000 got sign extended
-      and became $ffffffff80000000), all constants in the longint range
-      become longints, all constants >$7fffffff and <=cardinal($ffffffff)
-      are cardinals and the rest are int64's.
-    * added lots of longint typecast to prevent range check errors in the
-      compiler and rtl
-    * type casts of symbolic ordinal constants are now preserved
-    * fixed bug where the original resulttype.def wasn't restored correctly
-      after doing a 64bit rangecheck
-
-  Revision 1.6  2000/12/05 11:44:34  jonas
-    + new integer regvar handling, should be much more efficient
-
-  Revision 1.5  2000/11/29 00:30:49  florian
-    * unused units removed from uses clause
-    * some changes for widestrings
-
-  Revision 1.4  2000/11/13 14:47:46  jonas
-    * support for range checking when converting from 64bit to something
-      smaller (32bit, 16bit, 8bit)
-    * fixed range checking between longint/cardinal and for array indexing
-      with cardinal (values > $7fffffff were considered negative)
-
-  Revision 1.3  2000/11/04 14:25:25  florian
-    + merged Attila's changes for interfaces, not tested yet
-
-  Revision 1.2  2000/10/31 22:02:57  peter
-    * symtable splitted, no real code changes
-
-  Revision 1.1  2000/10/15 09:33:32  peter
-    * moved n386*.pas to i386/ cpu_target dir
-
-  Revision 1.3  2000/10/14 21:52:54  peter
-    * fixed memory leaks
-
-  Revision 1.2  2000/10/14 10:14:50  peter
-    * moehrendorf oct 2000 rewrite
-
-  Revision 1.1  2000/10/01 19:58:40  peter
-    * new file
-
-}

+ 6 - 2
compiler/nadd.pas

@@ -60,7 +60,7 @@ implementation
       symconst,symtype,symdef,symsym,symtable,types,
       cgbase,
       htypechk,pass_1,
-      nmat,ncnv,nld,ncon,nset,nopt,ncal,ninl,
+      nmat,ncnv,ncon,nset,nopt,ncal,ninl,
       cpubase;
 
 
@@ -1617,7 +1617,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.47  2002-05-12 16:53:06  peter
+  Revision 1.48  2002-05-13 19:54:36  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.47  2002/05/12 16:53:06  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 9 - 1
compiler/ncgbas.pas

@@ -159,7 +159,11 @@ interface
                      begin
                        { remove cached insentry, because the new code can
                          require an other less optimized instruction }
+{$ifdef i386}
+{$ifndef NOAG386BIN}
                        taicpu(hp2).ResetPass1;
+{$endif}
+{$endif}
                        { fixup the references }
                        for i:=1 to taicpu(hp2).ops do
                         begin
@@ -290,7 +294,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.15  2002-05-12 16:53:07  peter
+  Revision 1.16  2002-05-13 19:54:37  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.15  2002/05/12 16:53:07  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 6 - 2
compiler/ncgflw.pas

@@ -67,7 +67,7 @@ implementation
 
     uses
       verbose,globals,systems,globtype,
-      symconst,symdef,symsym,aasm,types,
+      symconst,symsym,aasm,types,
       cginfo,cgbase,pass_2,
       cpubase,cpuasm,cpuinfo,
       nld,ncon,
@@ -611,7 +611,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.14  2002-05-12 16:53:07  peter
+  Revision 1.15  2002-05-13 19:54:37  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.14  2002/05/12 16:53:07  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 652 - 2
compiler/ncgld.pas

@@ -31,20 +31,663 @@ interface
       node,nld;
 
     type
+       tcgloadnode = class(tloadnode)
+          procedure pass_2;override;
+       end;
+
+       tcgassignmentnode = class(tassignmentnode)
+          procedure pass_2;override;
+       end;
+
+       tcgfuncretnode = class(tfuncretnode)
+          procedure pass_2;override;
+       end;
+
        tcgarrayconstructornode = class(tarrayconstructornode)
           procedure pass_2;override;
        end;
 
+
 implementation
 
     uses
       systems,
       verbose,globals,
-      symconst,symtype,symdef,aasm,types,
+      symconst,symtype,symdef,symsym,symtable,types,
+      ncnv,ncon,nmem,
+      aasm,cpuasm,regvars,
       cginfo,cgbase,pass_2,
       cpubase,
       tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
 
+{*****************************************************************************
+                             SecondLoad
+*****************************************************************************}
+
+    procedure tcgloadnode.pass_2;
+      var
+        intreg,
+        hregister : tregister;
+        symtabletype : tsymtabletype;
+        i : longint;
+        href : treference;
+        newsize : tcgsize;
+        pushed : tpushedsaved;
+      begin
+         { we don't know the size of all arrays }
+         newsize:=def_cgsize(resulttype.def);
+         location_reset(location,LOC_REFERENCE,newsize);
+         case symtableentry.typ of
+            absolutesym :
+               begin
+                  { this is only for toasm and toaddr }
+                  location.reference.symbol:=nil;
+                  if (tabsolutesym(symtableentry).abstyp=toaddr) then
+                   begin
+{$ifdef i386}
+                     if tabsolutesym(symtableentry).absseg then
+                      location.reference.segment:=R_FS;
+{$endif i386}
+                     location.reference.offset:=tabsolutesym(symtableentry).address;
+                   end
+                  else
+                   location.reference.symbol:=newasmsymbol(tabsolutesym(symtableentry).mangledname);
+               end;
+            constsym:
+              begin
+                 if tconstsym(symtableentry).consttyp=constresourcestring then
+                   begin
+                      location_reset(location,LOC_CREFERENCE,OS_ADDR);
+                      location.reference.symbol:=newasmsymbol(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
+                      location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
+                   end
+                 else
+                   internalerror(22798);
+              end;
+            varsym :
+               begin
+                  hregister:=R_NO;
+                  { C variable }
+                  if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
+                    begin
+                       location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
+                    end
+                  { DLL variable }
+                  else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
+                    begin
+                       hregister:=rg.getaddressregister(exprasmlist);
+                       location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
+                       cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hregister);
+                       location.reference.symbol:=nil;
+                       location.reference.base:=hregister;
+                    end
+                  { external variable }
+                  else if (vo_is_external in tvarsym(symtableentry).varoptions) then
+                    begin
+                       location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
+                    end
+                  { thread variable }
+                  else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
+                    begin
+                       rg.saveusedregisters(exprasmlist,pushed,[accumulator]);
+                       reference_reset_symbol(href,newasmsymbol(tvarsym(symtableentry).mangledname),0);
+                       cg.a_param_ref(exprasmlist,OS_ADDR,href,1);
+                       { the called procedure isn't allowed to change }
+                       { any register except EAX                    }
+                       cg.a_call_name(exprasmlist,'FPC_RELOCATE_THREADVAR');
+                       location.reference.base:=rg.getaddressregister(exprasmlist);
+                       cg.a_load_reg_reg(exprasmlist,OS_INT,accumulator,location.reference.base);
+                       rg.restoreusedregisters(exprasmlist,pushed);
+                    end
+                  { normal variable }
+                  else
+                    begin
+                       symtabletype:=symtable.symtabletype;
+                       { in case it is a register variable: }
+                       if tvarsym(symtableentry).reg<>R_NO then
+                         begin
+                            if tvarsym(symtableentry).reg in fpuregs then
+                              begin
+                                 location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
+                                 location.register:=tvarsym(symtableentry).reg;
+                              end
+                            else
+                             begin
+                               intreg:=rg.makeregsize(tvarsym(symtableentry).reg,OS_INT);
+                               if (intreg in general_registers) and
+                                  (not rg.regvar_loaded[intreg]) then
+                                 load_regvar(exprasmlist,tvarsym(symtableentry));
+                               location_reset(location,LOC_CREGISTER,cg.reg_cgsize(tvarsym(symtableentry).reg));
+                               location.register:=tvarsym(symtableentry).reg;
+                               exclude(rg.unusedregsint,intreg);
+                             end;
+                         end
+                       else
+                         begin
+                            { first handle local and temporary variables }
+                            if (symtabletype in [parasymtable,inlinelocalsymtable,
+                                                 inlineparasymtable,localsymtable]) then
+                              begin
+                                 location.reference.base:=procinfo^.framepointer;
+                                 if (symtabletype in [inlinelocalsymtable,
+                                                      localsymtable]) then
+                                   location.reference.offset:=
+                                     tvarsym(symtableentry).address-symtable.address_fixup
+                                 else
+                                   location.reference.offset:=
+                                     tvarsym(symtableentry).address+symtable.address_fixup;
+
+                                 if (symtabletype in [localsymtable,inlinelocalsymtable]) then
+                                   begin
+                                      if use_esp_stackframe then
+                                        dec(location.reference.offset,
+                                          tvarsym(symtableentry).getvaluesize)
+                                      else
+                                        location.reference.offset:=-location.reference.offset;
+                                   end;
+                                 if (lexlevel>symtable.symtablelevel) then
+                                   begin
+                                      hregister:=rg.getregisterint(exprasmlist);
+                                      { make a reference }
+                                      reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
+                                      cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
+                                      { walk parents }
+                                      i:=lexlevel-1;
+                                      while (i>symtable.symtablelevel) do
+                                        begin
+                                           { make a reference }
+                                           reference_reset_base(href,hregister,8);
+                                           cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
+                                           dec(i);
+                                        end;
+                                      location.reference.base:=hregister;
+                                   end;
+                              end
+                            else
+                              case symtabletype of
+                                 globalsymtable,
+                                 staticsymtable :
+                                   begin
+                                     location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname);
+                                   end;
+                                 stt_exceptsymtable:
+                                   begin
+                                      location.reference.base:=procinfo^.framepointer;
+                                      location.reference.offset:=tvarsym(symtableentry).address;
+                                   end;
+                                 objectsymtable:
+                                   begin
+                                      if (sp_static in tvarsym(symtableentry).symoptions) then
+                                        location.reference.symbol:=newasmsymbol(tvarsym(symtableentry).mangledname)
+                                      else
+                                        begin
+                                           rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
+                                           location.reference.base:=SELF_POINTER_REG;
+                                           location.reference.offset:=tvarsym(symtableentry).address;
+                                        end;
+                                   end;
+                                 withsymtable:
+                                   begin
+                                      if nf_islocal in tnode(twithsymtable(symtable).withnode).flags then
+                                        location.reference:=twithnode(twithsymtable(symtable).withnode).withreference
+                                      else
+                                        begin
+                                          location.reference.base:=rg.getaddressregister(exprasmlist);
+                                          cg.a_load_ref_reg(exprasmlist,OS_ADDR,
+                                             twithnode(twithsymtable(symtable).withnode).withreference,
+                                             location.reference.base);
+                                        end;
+                                      inc(location.reference.offset,tvarsym(symtableentry).address);
+                                   end;
+                              end;
+                         end;
+                       { in case call by reference, then calculate. Open array
+                         is always an reference! }
+                       if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
+                          is_open_array(tvarsym(symtableentry).vartype.def) or
+                          is_array_of_const(tvarsym(symtableentry).vartype.def) or
+                          ((tvarsym(symtableentry).varspez=vs_const) and
+                           push_addr_param(tvarsym(symtableentry).vartype.def)) then
+                         begin
+                            if hregister=R_NO then
+                              hregister:=rg.getaddressregister(exprasmlist);
+                            { we need to load only an address }
+                            location.size:=OS_ADDR;
+                            cg.a_load_loc_reg(exprasmlist,location,hregister);
+                            location_reset(location,LOC_REFERENCE,newsize);
+                            location.reference.base:=hregister;
+                        end;
+                    end;
+               end;
+            procsym:
+               begin
+                  if assigned(left) then
+                    begin
+                       location_reset(location,LOC_CREFERENCE,OS_64);
+                       tg.gettempofsizereference(exprasmlist,8,location.reference);
+
+                       { called as type.method, then we only need to return
+                         the address of the function, not the self pointer }
+                       if left.nodetype=typen then
+                        begin
+                          { there is no instance, we return 0 }
+                          cg.a_load_const_ref(exprasmlist,OS_ADDR,0,location.reference);
+                        end
+                       else
+                        begin
+                          secondpass(left);
+
+                          { load class instance address }
+                          case left.location.loc of
+                             LOC_CREGISTER,
+                             LOC_REGISTER:
+                               begin
+                                  hregister:=left.location.register;
+                                  if is_object(left.resulttype.def) then
+                                    CGMessage(cg_e_illegal_expression);
+                               end;
+                             LOC_CREFERENCE,
+                             LOC_REFERENCE:
+                               begin
+                                  hregister:=rg.getaddressregister(exprasmlist);
+                                  if is_class_or_interface(left.resulttype.def) then
+                                    cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister)
+                                  else
+                                    cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
+                                  location_release(exprasmlist,left.location);
+                                  location_freetemp(exprasmlist,left.location);
+                               end;
+                             else
+                               internalerror(26019);
+                          end;
+
+                          { store the class instance address }
+                          href:=location.reference;
+                          inc(href.offset,4);
+                          cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
+                          { hregister will be reused when loading a virtual method }
+                        end;
+
+                       { virtual method ? }
+                       if (po_virtualmethod in tprocdef(resulttype.def).procoptions) then
+                         begin
+                            { load vmt pointer }
+                            reference_reset_base(href,hregister,0);
+                            reference_release(exprasmlist,href);
+                            hregister:=rg.getaddressregister(exprasmlist);
+                            cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
+                            { load method address }
+                            reference_reset_base(href,hregister,tprocdef(resulttype.def)._class.vmtmethodoffset(
+                                                 tprocdef(resulttype.def).extnumber));
+                            reference_release(exprasmlist,href);
+                            hregister:=rg.getaddressregister(exprasmlist);
+                            cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
+                            { ... and store it }
+                            cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
+                            rg.ungetaddressregister(exprasmlist,hregister);
+                         end
+                       else
+                         begin
+                            { we don't use the hregister }
+                            rg.ungetregisterint(exprasmlist,hregister);
+                            { load address of the function }
+                            reference_reset_symbol(href,newasmsymbol(tprocdef(resulttype.def).mangledname),0);
+                            hregister:=cg.get_scratch_reg(exprasmlist);
+                            cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
+                            cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
+                            cg.free_scratch_reg(exprasmlist,hregister);
+                         end;
+                    end
+                  else
+                    begin
+                       {!!!!! Be aware, work on virtual methods too }
+                       location.reference.symbol:=newasmsymbol(tprocdef(resulttype.def).mangledname);
+                    end;
+               end;
+            typedconstsym :
+               begin
+                  location.reference.symbol:=newasmsymbol(ttypedconstsym(symtableentry).mangledname);
+               end;
+            else internalerror(4);
+         end;
+      end;
+
+
+{*****************************************************************************
+                             SecondAssignment
+*****************************************************************************}
+
+    procedure tcgassignmentnode.pass_2;
+      var
+         otlabel,hlabel,oflabel : tasmlabel;
+         fputyp : tfloattype;
+         href : treference;
+         ai : taicpu;
+         releaseright : boolean;
+         pushedregs : tmaybesave;
+         cgsize : tcgsize;
+
+      begin
+        otlabel:=truelabel;
+        oflabel:=falselabel;
+        getlabel(truelabel);
+        getlabel(falselabel);
+
+        {
+          in most cases we can process first the right node which contains
+          the most complex code. But not when the result is in the flags, then
+          loading the left node afterwards can destroy the flags.
+
+          when the right node returns as LOC_JUMP then we will generate
+          the following code:
+
+          rightnode
+          true:
+            leftnode
+            assign 1
+          false:
+            leftnode
+            assign 0
+        }
+
+        { Try to determine which side to calculate first,  }
+        if (right.location.loc<>LOC_FLAGS) and
+           ((right.location.loc=LOC_JUMP) or
+            (right.registers32>=left.registers32)) then
+         begin
+           secondpass(right);
+           { increment source reference counter, this is
+             useless for string constants}
+           if (right.resulttype.def.needs_inittable) and
+              (right.nodetype<>stringconstn) then
+            cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
+           if codegenerror then
+             exit;
+
+           { We skip the generation of the left node when it's a jump, see
+             explanation above }
+           if (right.location.loc<>LOC_JUMP) and
+              not(nf_concat_string in flags) then
+            begin
+              { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
+              { can be false                                             }
+              maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
+              secondpass(left);
+              { decrement destination reference counter }
+              if (left.resulttype.def.needs_inittable) then
+               cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
+              maybe_restore(exprasmlist,right.location,pushedregs);
+              if codegenerror then
+                exit;
+            end;
+         end
+        else
+         begin
+           { calculate left sides }
+           { don't do it yet if it's a crgister (JM) }
+           if not(nf_concat_string in flags) then
+            begin
+              secondpass(left);
+              { decrement destination reference counter }
+              if (left.resulttype.def.needs_inittable) then
+               cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
+              if codegenerror then
+               exit;
+            end;
+
+           { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
+           { can be false                                             }
+           maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
+           secondpass(right);
+           { increment source reference counter, this is
+             useless for string constants}
+           if (right.resulttype.def.needs_inittable) and
+              (right.nodetype<>stringconstn) then
+            cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
+           maybe_restore(exprasmlist,left.location,pushedregs);
+
+           if codegenerror then
+             exit;
+         end;
+
+        if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
+                                     {$ifdef SUPPORT_MMX}LOC_CMMXREGISTER,{$endif}
+                                     LOC_CREGISTER]) then
+          begin
+             CGMessage(cg_e_illegal_expression);
+             exit;
+          end;
+
+        releaseright:=true;
+
+        { shortstring assignments are handled separately }
+        if is_shortstring(left.resulttype.def) then
+          begin
+            {
+              we can get here only in the following situations
+              for the right node:
+               - empty constant string
+               - char
+            }
+
+            { empty constant string }
+            if (right.nodetype=stringconstn) and
+               (tstringconstnode(right).len=0) then
+              begin
+                cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
+              end
+            { char loading }
+            else if is_char(right.resulttype.def) then
+              begin
+                if right.nodetype=ordconstn then
+                  begin
+                    if (target_info.endian = endian_little) then
+                      cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
+                          left.location.reference)
+                    else
+                      cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
+                          left.location.reference);
+                  end
+                else
+                  begin
+                    href:=left.location.reference;
+                    cg.a_load_const_ref(exprasmlist,OS_8,1,href);
+                    inc(href.offset,1);
+                    case right.location.loc of
+                      LOC_REGISTER,
+                      LOC_CREGISTER :
+                        cg.a_load_reg_ref(exprasmlist,OS_8,rg.makeregsize(right.location.register,OS_8),href);
+                      LOC_REFERENCE,
+                      LOC_CREFERENCE :
+                        cg.a_load_ref_ref(exprasmlist,OS_8,right.location.reference,href);
+                      else
+                        internalerror(200205111);
+                    end;
+                  end;
+              end
+            else
+              internalerror(200204249);
+          end
+        else
+          begin
+            case right.location.loc of
+              LOC_CONSTANT :
+                begin
+                  if right.location.size in [OS_64,OS_S64] then
+                   tcg64f32(cg).a_load64_const_loc(exprasmlist,
+                       right.location.valuelow,right.location.valuehigh,left.location)
+                  else
+                   cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
+                end;
+              LOC_REFERENCE,
+              LOC_CREFERENCE :
+                begin
+                  case left.location.loc of
+                    LOC_CREGISTER :
+                      begin
+                        cgsize:=def_cgsize(left.resulttype.def);
+                        if cgsize in [OS_64,OS_S64] then
+                         tcg64f32(cg).a_load64_ref_reg(exprasmlist,
+                             right.location.reference,left.location.registerlow,left.location.registerhigh)
+                        else
+                         cg.a_load_ref_reg(exprasmlist,cgsize,
+                             right.location.reference,left.location.register);
+                        location_release(exprasmlist,right.location);
+                      end;
+                    LOC_CFPUREGISTER :
+                      begin
+                        cg.a_loadfpu_ref_reg(exprasmlist,
+                            def_cgsize(right.resulttype.def),
+                            right.location.reference,
+                            left.location.register);
+                      end;
+                    LOC_REFERENCE,
+                    LOC_CREFERENCE :
+                      begin
+                        cg.g_concatcopy(exprasmlist,right.location.reference,
+                                        left.location.reference,left.resulttype.def.size,true,false);
+                        { right.location is already released by concatcopy }
+                        releaseright:=false;
+                      end;
+                    else
+                      internalerror(200203284);
+                  end;
+                end;
+{$ifdef SUPPORT_MMX}
+              LOC_CMMXREGISTER,
+              LOC_MMXREGISTER:
+                begin
+                  if left.location.loc=LOC_CMMXREGISTER then
+                    cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
+                  else
+                    cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
+                end;
+{$endif SUPPORT_MMX}
+              LOC_REGISTER,
+              LOC_CREGISTER :
+                begin
+                  cgsize:=def_cgsize(left.resulttype.def);
+                  if cgsize in [OS_64,OS_S64] then
+                   tcg64f32(cg).a_load64_reg_loc(exprasmlist,
+                       right.location.registerlow,right.location.registerhigh,left.location)
+                  else
+                   cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
+                end;
+              LOC_FPUREGISTER,LOC_CFPUREGISTER :
+                begin
+                  if (left.resulttype.def.deftype=floatdef) then
+                   fputyp:=tfloatdef(left.resulttype.def).typ
+                  else
+                   if (right.resulttype.def.deftype=floatdef) then
+                    fputyp:=tfloatdef(right.resulttype.def).typ
+                  else
+                   if (right.nodetype=typeconvn) and
+                      (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
+                    fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
+                  else
+                    fputyp:=s32real;
+                  cg.a_loadfpu_reg_loc(exprasmlist,
+                      tfloat2tcgsize[fputyp],
+                      right.location.register,left.location);
+                end;
+              LOC_JUMP :
+                begin
+                  cgsize:=def_cgsize(left.resulttype.def);
+                  getlabel(hlabel);
+                  { generate the leftnode for the true case, and
+                    release the location }
+                  cg.a_label(exprasmlist,truelabel);
+                  maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
+                  secondpass(left);
+                  maybe_restore(exprasmlist,right.location,pushedregs);
+                  if codegenerror then
+                    exit;
+                  cg.a_load_const_loc(exprasmlist,1,left.location);
+                  location_release(exprasmlist,left.location);
+                  cg.a_jmp_always(exprasmlist,hlabel);
+                  { generate the leftnode for the false case }
+                  cg.a_label(exprasmlist,falselabel);
+                  maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
+                  secondpass(left);
+                  maybe_restore(exprasmlist,right.location,pushedregs);
+                  if codegenerror then
+                    exit;
+                  cg.a_load_const_loc(exprasmlist,0,left.location);
+                  cg.a_label(exprasmlist,hlabel);
+                end;
+              LOC_FLAGS :
+                begin
+                  if left.location.loc=LOC_CREGISTER then
+                    cg.g_flags2reg(exprasmlist,right.location.resflags,left.location.register)
+                  else
+                    begin
+                      if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+                       internalerror(200203273);
+                      cg.g_flags2ref(exprasmlist,right.location.resflags,left.location.reference);
+                    end;
+                end;
+            end;
+
+         end;
+
+        if releaseright then
+         location_release(exprasmlist,right.location);
+        location_release(exprasmlist,left.location);
+
+        truelabel:=otlabel;
+        falselabel:=oflabel;
+      end;
+
+
+{*****************************************************************************
+                             SecondFuncRet
+*****************************************************************************}
+
+    procedure tcgfuncretnode.pass_2;
+      var
+         hreg : tregister;
+         href : treference;
+         pp : pprocinfo;
+         hr_valid : boolean;
+         i : integer;
+      begin
+         location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
+         hr_valid:=false;
+         if (not inlining_procedure) and
+            (lexlevel<>funcretsym.owner.symtablelevel) then
+           begin
+              hreg:=rg.getregisterint(exprasmlist);
+              hr_valid:=true;
+              reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
+              cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
+
+              { walk up the stack frame }
+              pp:=procinfo^.parent;
+              i:=lexlevel-1;
+              while i>funcretsym.owner.symtablelevel do
+               begin
+                 reference_reset_base(href,hreg,pp^.framepointer_offset);
+                 cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
+                 pp:=pp^.parent;
+                 dec(i);
+               end;
+              location.reference.base:=hreg;
+              location.reference.offset:=pp^.return_offset;
+           end
+         else
+           begin
+             location.reference.base:=procinfo^.framepointer;
+             location.reference.offset:=procinfo^.return_offset;
+           end;
+         if ret_in_param(resulttype.def) then
+           begin
+              if not hr_valid then
+                hreg:=rg.getregisterint(exprasmlist);
+              cg.a_load_ref_reg(exprasmlist,OS_INT,location.reference,hreg);
+              location.reference.base:=hreg;
+              location.reference.offset:=0;
+           end;
+      end;
 {*****************************************************************************
                            SecondArrayConstruct
 *****************************************************************************}
@@ -256,11 +899,18 @@ implementation
       end;
 
 begin
+   cloadnode:=tcgloadnode;
+   cassignmentnode:=tcgassignmentnode;
+   cfuncretnode:=tcgfuncretnode;
    carrayconstructornode:=tcgarrayconstructornode;
 end.
 {
   $Log$
-  Revision 1.3  2002-05-12 16:53:07  peter
+  Revision 1.4  2002-05-13 19:54:37  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.3  2002/05/12 16:53:07  peter
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
       iterator function

+ 421 - 58
compiler/ncgutil.pas

@@ -28,16 +28,30 @@ interface
 
     uses
       node,
-      cginfo,cpubase,aasm;
+      cginfo,cpubase,aasm,
+      rgobj;
 
     type
       tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
 
+      tmaybesave = record
+        saved : boolean;
+        ref   : treference;
+      end;
+
+    procedure firstcomplex(p : tbinarynode);
+    procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
+    procedure remove_non_regvars_from_loc(const t: tlocation; var regs: tregisterset);
+
     procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
     procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
 
-    procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
+    procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
+    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;inlined,is_cdecl:boolean;
+                              para_offset:longint;alignment : longint);
 
     procedure genentrycode(list : TAAsmoutput;
                            make_global:boolean;
@@ -65,7 +79,130 @@ implementation
     gdb,
 {$endif GDB}
     ncon,
-    tgobj,cpuinfo,cgobj,cgcpu,rgobj,cg64f32;
+    tgobj,cpuinfo,cgobj,cgcpu,cg64f32;
+
+
+{*****************************************************************************
+                                  Misc Helpers
+*****************************************************************************}
+
+   { DO NOT RELY on the fact that the tnode is not yet swaped
+     because of inlining code PM }
+    procedure firstcomplex(p : tbinarynode);
+      var
+         hp : tnode;
+      begin
+         { always calculate boolean AND and OR from left to right }
+         if (p.nodetype in [orn,andn]) and
+            (p.left.resulttype.def.deftype=orddef) and
+            (torddef(p.left.resulttype.def).typ in [bool8bit,bool16bit,bool32bit]) then
+           begin
+             { p.swaped:=false}
+             if nf_swaped in p.flags then
+               internalerror(234234);
+           end
+         else
+           if (((p.location.loc=LOC_FPUREGISTER) and
+                (p.right.registersfpu > p.left.registersfpu)) or
+               ((((p.left.registersfpu = 0) and
+                  (p.right.registersfpu = 0)) or
+                 (p.location.loc<>LOC_FPUREGISTER)) and
+                (p.left.registers32<p.right.registers32))) and
+           { the following check is appropriate, because all }
+           { 4 registers are rarely used and it is thereby   }
+           { achieved that the extra code is being dropped   }
+           { by exchanging not commutative operators     }
+               (p.right.registers32<=c_countusableregsint) then
+            begin
+              hp:=p.left;
+              p.left:=p.right;
+              p.right:=hp;
+              if nf_swaped in p.flags then
+                exclude(p.flags,nf_swaped)
+              else
+                include(p.flags,nf_swaped);
+            end;
+      end;
+
+
+    procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
+    {
+      produces jumps to true respectively false labels using boolean expressions
+
+      depending on whether the loading of regvars is currently being
+      synchronized manually (such as in an if-node) or automatically (most of
+      the other cases where this procedure is called), loadregvars can be
+      "lr_load_regvars" or "lr_dont_load_regvars"
+    }
+      var
+        opsize : tcgsize;
+        storepos : tfileposinfo;
+      begin
+         if nf_error in p.flags then
+           exit;
+         storepos:=aktfilepos;
+         aktfilepos:=p.fileinfo;
+         if is_boolean(p.resulttype.def) then
+           begin
+              if loadregvars = lr_load_regvars then
+                load_all_regvars(list);
+              if is_constboolnode(p) then
+                begin
+                   if tordconstnode(p).value<>0 then
+                     cg.a_jmp_always(list,truelabel)
+                   else
+                     cg.a_jmp_always(list,falselabel)
+                end
+              else
+                begin
+                   opsize:=def_cgsize(p.resulttype.def);
+                   case p.location.loc of
+                     LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
+                       begin
+                         if (p.location.loc = LOC_CREGISTER) then
+                           load_regvar_reg(list,p.location.register);
+                         cg.a_cmp_const_loc_label(list,opsize,OC_NE,
+                           0,p.location,truelabel);
+                         { !!! should happen right after cmp (JM) }
+                         location_release(list,p.location);
+                         cg.a_jmp_always(list,falselabel);
+                       end;
+                     LOC_FLAGS :
+                       begin
+                         cg.a_jmp_flags(list,p.location.resflags,
+                           truelabel);
+                         cg.a_jmp_always(list,falselabel);
+                       end;
+                   end;
+                end;
+           end
+         else
+           internalerror(200112305);
+         aktfilepos:=storepos;
+      end;
+
+
+    procedure remove_non_regvars_from_loc(const t: tlocation; var regs: tregisterset);
+      begin
+        case t.loc of
+          LOC_REGISTER:
+            begin
+              { can't be a regvar, since it would be LOC_CREGISTER then }
+              exclude(regs,t.register);
+              if t.registerhigh <> R_NO then
+                exclude(regs,t.registerhigh);
+            end;
+          LOC_CREFERENCE,LOC_REFERENCE:
+            begin
+              if not(cs_regalloc in aktglobalswitches) or
+                 (t.reference.base in rg.usableregsint) then
+                exclude(regs,t.reference.base);
+              if not(cs_regalloc in aktglobalswitches) or
+                 (t.reference.index in rg.usableregsint) then
+              exclude(regs,t.reference.index);
+            end;
+        end;
+      end;
 
 
 {*****************************************************************************
@@ -341,60 +478,280 @@ implementation
       end;
 
 
-    procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
-    {
-      produces jumps to true respectively false labels using boolean expressions
+{*****************************************************************************
+                                  Maybe_Save
+*****************************************************************************}
 
-      depending on whether the loading of regvars is currently being
-      synchronized manually (such as in an if-node) or automatically (most of
-      the other cases where this procedure is called), loadregvars can be
-      "lr_load_regvars" or "lr_dont_load_regvars"
-    }
-      var
-        opsize : tcgsize;
-        storepos : tfileposinfo;
+    procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
       begin
-         if nf_error in p.flags then
+        s.saved:=false;
+        if l.loc=LOC_CREGISTER then
+         begin
+           s.saved:=true;
            exit;
-         storepos:=aktfilepos;
-         aktfilepos:=p.fileinfo;
-         if is_boolean(p.resulttype.def) then
-           begin
-              if loadregvars = lr_load_regvars then
-                load_all_regvars(list);
-              if is_constboolnode(p) then
-                begin
-                   if tordconstnode(p).value<>0 then
-                     cg.a_jmp_always(list,truelabel)
-                   else
-                     cg.a_jmp_always(list,falselabel)
-                end
+         end;
+        if needed>rg.countunusedregsint then
+         begin
+           case l.loc of
+             LOC_REGISTER :
+               begin
+                 if l.size in [OS_64,OS_S64] then
+                  begin
+                    tg.gettempofsizereference(exprasmlist,8,s.ref);
+                    tcg64f32(cg).a_load64_reg_ref(exprasmlist,l.registerlow,l.registerhigh,s.ref);
+                  end
+                 else
+                  begin
+                    tg.gettempofsizereference(exprasmlist,TCGSize2Size[l.size],s.ref);
+                    cg.a_load_reg_ref(exprasmlist,l.size,l.register,s.ref);
+                  end;
+                 location_release(exprasmlist,l);
+                 s.saved:=true;
+               end;
+             LOC_REFERENCE,
+             LOC_CREFERENCE :
+               begin
+                 if ((l.reference.base<>R_NO) or
+                     (l.reference.index<>R_NO)) then
+                  begin
+                    { load address into a single base register }
+                    cg.a_loadaddr_ref_reg(list,l.reference,l.reference.base);
+                    { save base register }
+                    tg.gettempofsizereference(exprasmlist,TCGSize2Size[OS_ADDR],s.ref);
+                    cg.a_load_reg_ref(exprasmlist,OS_ADDR,l.reference.base,s.ref);
+                    { release }
+                    location_release(exprasmlist,l);
+                    s.saved:=true;
+                  end;
+               end;
+           end;
+         end;
+      end;
+
+
+    procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
+      begin
+        if not s.saved then
+         exit;
+        if l.loc=LOC_CREGISTER then
+         begin
+           load_regvar_reg(list,l.register);
+           exit;
+         end;
+        case l.loc of
+          LOC_REGISTER :
+            begin
+              if l.size in [OS_64,OS_S64] then
+               begin
+                 l.registerlow:=rg.getregisterint(exprasmlist);
+                 l.registerhigh:=rg.getregisterint(exprasmlist);
+                 tcg64f32(cg).a_load64_ref_reg(exprasmlist,s.ref,l.registerlow,l.registerhigh);
+               end
               else
-                begin
-                   opsize:=def_cgsize(p.resulttype.def);
-                   case p.location.loc of
-                     LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
-                       begin
-                         if (p.location.loc = LOC_CREGISTER) then
-                           load_regvar_reg(list,p.location.register);
-                         cg.a_cmp_const_loc_label(list,opsize,OC_NE,
-                           0,p.location,truelabel);
-                         { !!! should happen right after cmp (JM) }
-                         location_release(list,p.location);
-                         cg.a_jmp_always(list,falselabel);
+               begin
+                 l.register:=rg.getregisterint(exprasmlist);
+                 cg.a_load_ref_reg(exprasmlist,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);
+            end;
+        end;
+        tg.ungetiftemp(exprasmlist,s.ref);
+      end;
+
+
+    function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
+      begin
+        if needed>=maxfpuregs then
+          begin
+            if l.loc = LOC_FPUREGISTER then
+              begin
+                location_force_mem(list,l);
+                maybe_pushfpu:=true;
+              end
+            else
+              maybe_pushfpu:=false;
+          end
+        else
+          maybe_pushfpu:=false;
+      end;
+
+
+{*****************************************************************************
+                                Push Value Para
+*****************************************************************************}
+
+    procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
+                              para_offset:longint;alignment : longint);
+      var
+        tempreference : treference;
+        href : treference;
+        hreg : tregister;
+        sizetopush,
+        size : longint;
+        cgsize : tcgsize;
+      begin
+        { 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);
+
+        { Handle Floating point types differently }
+        if p.resulttype.def.deftype=floatdef then
+         begin
+           case p.location.loc of
+             LOC_FPUREGISTER,
+             LOC_CFPUREGISTER:
+               begin
+                  size:=align(tfloatdef(p.resulttype.def).size,alignment);
+                  inc(pushedparasize,size);
+                  if not inlined then
+                   cg.a_op_const_reg(exprasmlist,OP_SUB,size,STACK_POINTER_REG);
+{$ifdef GDB}
+                  if (cs_debuginfo in aktmoduleswitches) and
+                     (exprasmList.first=exprasmList.last) then
+                    exprasmList.concat(Tai_force_line.Create);
+{$endif GDB}
+
+                  { this is the easiest case for inlined !! }
+                  if inlined then
+                   reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize)
+                  else
+                   reference_reset_base(href,stack_pointer_reg,0);
+
+                  cg.a_loadfpu_reg_ref(exprasmlist,
+                    def_cgsize(p.resulttype.def),p.location.register,href);
+               end;
+             LOC_REFERENCE,
+             LOC_CREFERENCE :
+               begin
+                 sizetopush:=align(p.resulttype.def.size,alignment);
+                 tempreference:=p.location.reference;
+                 inc(tempreference.offset,sizetopush);
+                 while (sizetopush>0) do
+                  begin
+                    if sizetopush>=4 then
+                     begin
+                       cgsize:=OS_32;
+                       inc(pushedparasize,4);
+                       dec(tempreference.offset,4);
+                       dec(sizetopush,4);
+                     end
+                    else
+                     begin
+                       cgsize:=OS_16;
+                       inc(pushedparasize,2);
+                       dec(tempreference.offset,2);
+                       dec(sizetopush,2);
+                     end;
+                    if inlined then
+                     begin
+                       reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
+                       cg.a_load_ref_ref(exprasmlist,cgsize,tempreference,href);
+                     end
+                    else
+                     cg.a_param_ref(exprasmlist,cgsize,tempreference,-1);
+                  end;
+               end;
+             else
+               internalerror(200204243);
+           end;
+         end
+        else
+         begin
+           { call by value open array ? }
+           if is_cdecl and
+              push_addr_param(p.resulttype.def) then
+            begin
+              if not (p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+                internalerror(200204241);
+              { push on stack }
+              size:=align(p.resulttype.def.size,alignment);
+              inc(pushedparasize,size);
+              cg.a_op_const_reg(exprasmlist,OP_SUB,size,STACK_POINTER_REG);
+              reference_reset_base(href,STACK_POINTER_REG,0);
+              cg.g_concatcopy(exprasmlist,p.location.reference,href,size,false,false);
+            end
+           else
+            begin
+              case p.location.loc of
+                LOC_CONSTANT,
+                LOC_REGISTER,
+                LOC_CREGISTER,
+                LOC_REFERENCE,
+                LOC_CREFERENCE :
+                  begin
+                    cgsize:=def_cgsize(p.resulttype.def);
+                    if cgsize in [OS_64,OS_S64] then
+                     begin
+                       inc(pushedparasize,8);
+                       if inlined then
+                        begin
+                          reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
+                          tcg64f32(cg).a_load64_loc_ref(exprasmlist,p.location,href);
+                        end
+                       else
+                        tcg64f32(cg).a_param64_loc(exprasmlist,p.location,-1);
+                     end
+                    else
+                     begin
+                       case cgsize of
+                         OS_8,OS_S8 :
+                           begin
+                             if alignment=4 then
+                              cgsize:=OS_32
+                             else
+                              cgsize:=OS_16;
+                           end;
+                         OS_16,OS_S16 :
+                           begin
+                             if alignment=4 then
+                              cgsize:=OS_32;
+                           end;
                        end;
-                     LOC_FLAGS :
+                       { update register to use to match alignment }
+                       if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+                        begin
+                          hreg:=p.location.register;
+                          p.location.register:=rg.makeregsize(p.location.register,cgsize);
+                        end;
+                       inc(pushedparasize,alignment);
+                       if inlined then
+                        begin
+                          reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
+                          cg.a_load_loc_ref(exprasmlist,p.location,href);
+                        end
+                       else
+                        cg.a_param_loc(exprasmlist,p.location,-1);
+                       { restore old register }
+                       if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+                         p.location.register:=hreg;
+                     end;
+                    location_release(exprasmlist,p.location);
+                  end;
+{$ifdef SUPPORT_MMX}
+                LOC_MMXREGISTER,
+                LOC_CMMXREGISTER:
+                  begin
+                     inc(pushedparasize,8);
+                     if inlined then
                        begin
-                         cg.a_jmp_flags(list,p.location.resflags,
-                           truelabel);
-                         cg.a_jmp_always(list,falselabel);
-                       end;
-                   end;
-                end;
-           end
-         else
-           internalerror(200112305);
-         aktfilepos:=storepos;
+                          reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
+                          cg.a_loadmm_reg_ref(exprasmlist,p.location.register,href);
+                       end
+                     else
+                      cg.a_parammm_reg(exprasmlist,p.location.register);
+                  end;
+{$endif SUPPORT_MMX}
+                else
+                  internalerror(200204241);
+              end;
+           end;
+         end;
       end;
 
 
@@ -703,6 +1060,7 @@ implementation
         href : treference;
         p : tsymtable;
         tempbuf : treference;
+        tmpreg : tregister;
       begin
         { Insert alignment and assembler names }
         if not inlined then
@@ -878,11 +1236,12 @@ implementation
               include(rg.usedinproc,accumulator);
 
               { allocate exception frame buffer }
-              list.concat(Taicpu.op_const_reg(A_SUB,S_L,36,R_ESP));
-              list.concat(Taicpu.op_reg_reg(A_MOV,S_L,R_ESP,R_EDI));
-              reference_reset_base(tempbuf,R_EDI,0);
-
+              cg.a_op_const_reg(list,OP_SUB,36,STACK_POINTER_REG);
+              tmpreg:=rg.getaddressregister(list);
+              cg.a_load_reg_reg(list,OS_ADDR,STACK_POINTER_REG,tmpreg);
+              reference_reset_base(tempbuf,tmpreg,0);
               cg.g_push_exception(list,tempbuf,1,aktexitlabel);
+              reference_release(list,tempbuf);
 
               { probably we've to reload self here }
               cg.g_maybe_loadself(list);
@@ -1097,7 +1456,7 @@ implementation
             cg.g_restore_frame_pointer(list)
            else
             if (tg.gettempsize<>0) then
-             cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,R_ESP);
+             cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,STACK_POINTER_REG);
          end;
 
         { at last, the return is generated }
@@ -1147,7 +1506,7 @@ implementation
                     st:='';
                   list.concat(Tai_stabs.Create(strpnew(
                    '"$t:r'+st+procinfo^._class.numberstring+'",'+
-                   tostr(N_RSYM)+',0,0,'+tostr(GDB_i386index[R_ESI]))));
+                   tostr(N_RSYM)+',0,0,'+tostr(GDB_i386index[SELF_POINTER_REG]))));
                 end;
 
             { define calling EBP as pseudo local var PM }
@@ -1248,7 +1607,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.12  2002-05-12 19:58:36  carl
+  Revision 1.13  2002-05-13 19:54:37  peter
+    * removed n386ld and n386util units
+    * maybe_save/maybe_restore added instead of the old maybe_push
+
+  Revision 1.12  2002/05/12 19:58:36  carl
   * some small portability fixes
 
   Revision 1.11  2002/05/12 16:53:07  peter