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
     type
        {# Generic opcodes, which must be supporrted by all processors }
        {# Generic opcodes, which must be supporrted by all processors }
-       TOpCg = 
+       TOpCg =
        (
        (
           OP_NONE,
           OP_NONE,
           OP_ADD,       { simple addition          }
           OP_ADD,       { simple addition          }
@@ -51,9 +51,9 @@ interface
         );
         );
 
 
        {# Generic flag values - used for jump locations }
        {# Generic flag values - used for jump locations }
-       TOpCmp = 
+       TOpCmp =
        (
        (
-          OC_NONE,          
+          OC_NONE,
           OC_EQ,           { equality comparison }
           OC_EQ,           { equality comparison }
           OC_GT,
           OC_GT,
           OC_LT,
           OC_LT,
@@ -78,35 +78,22 @@ interface
                   OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,OS_MS8,OS_MS16,OS_MS32,
                   OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,OS_MS8,OS_MS16,OS_MS32,
                   OS_MS64,OS_MS128);
                   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
     const
        tcgsize2size : Array[tcgsize] of integer =
        tcgsize2size : Array[tcgsize] of integer =
          { integer values }
          { integer values }
         (0,1,2,4,8,1,2,4,8,
         (0,1,2,4,8,1,2,4,8,
-         { floating point values } 
+         { floating point values }
          4,8,EXTENDED_SIZE,8,
          4,8,EXTENDED_SIZE,8,
          { multimedia values }
          { multimedia values }
          1,2,4,8,16,1,2,4,8,16);
          1,2,4,8,16,1,2,4,8,16);
-         
+
        tfloat2tcgsize: array[tfloattype] of tcgsize =
        tfloat2tcgsize: array[tfloattype] of tcgsize =
          (OS_F32,OS_F64,OS_F80,OS_C64);
          (OS_F32,OS_F64,OS_F80,OS_C64);
 
 
        tcgsize2tfloat: array[OS_F32..OS_C64] of tfloattype =
        tcgsize2tfloat: array[OS_F32..OS_C64] of tfloattype =
          (s32real,s64real,s80real,s64comp);
          (s32real,s64real,s80real,s64comp);
 
 
-         
+
 
 
 
 
 implementation
 implementation
@@ -114,7 +101,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $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
   + added more patches from Mazen for SPARC port
 
 
   Revision 1.5  2002/04/21 19:46:52  carl
   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 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_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 }
           { 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        }
           { 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_param_const(list,OS_32,stackframesize,1);
          a_call_name(list,'FPC_STACKCHECK');
          a_call_name(list,'FPC_STACKCHECK');
       end;
       end;
-      
-      
+
+
     procedure tcg.g_maybe_loadself(list : taasmoutput);
     procedure tcg.g_maybe_loadself(list : taasmoutput);
       var
       var
          hp : treference;
          hp : treference;
@@ -1085,7 +1086,7 @@ unit cgobj;
                 end;
                 end;
            end;
            end;
       end;
       end;
-      
+
 
 
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -1112,7 +1113,11 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $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
   * maybe_loadself portable
 
 
   Revision 1.20  2002/05/12 16:53:04  peter
   Revision 1.20  2002/05/12 16:53:04  peter

+ 8 - 24
compiler/i386/cga.pas

@@ -61,29 +61,9 @@ interface
 implementation
 implementation
 
 
     uses
     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.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       iterator function

+ 50 - 4
compiler/i386/cgcpu.pas

@@ -28,7 +28,9 @@ unit cgcpu;
   interface
   interface
 
 
     uses
     uses
-       cginfo,cgbase,cgobj,cg64f32,aasm,cpuasm,cpubase,cpuinfo,symconst;
+       cginfo,cgbase,cgobj,cg64f32,
+       aasm,cpuasm,cpubase,cpuinfo,
+       node,symconst;
 
 
     type
     type
       tcg386 = class(tcg64f32)
       tcg386 = class(tcg64f32)
@@ -91,6 +93,7 @@ unit cgcpu;
         procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
         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_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_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;
         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_save_all_registers(list : taasmoutput);override;
         procedure g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);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 a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
         procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
         procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
@@ -152,7 +157,7 @@ unit cgcpu;
 
 
     uses
     uses
        globtype,globals,verbose,systems,cutils,
        globtype,globals,verbose,systems,cutils,
-       symtable,symdef,symsym,types,
+       symdef,symsym,types,
        rgobj,tgobj,rgcpu,tainst;
        rgobj,tgobj,rgcpu,tainst;
 
 
 {$ifndef NOTARGETWIN32}
 {$ifndef NOTARGETWIN32}
@@ -1047,6 +1052,17 @@ unit cgcpu;
        end;
        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 ************ }
 { ************* 64bit operations ************ }
 
 
     procedure tcg386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
     procedure tcg386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
@@ -1732,13 +1748,43 @@ unit cgcpu;
       end;
       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
 begin
   cg := tcg386.create;
   cg := tcg386.create;
 end.
 end.
 {
 {
   $Log$
   $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
   * some small portability fixes
 
 
   Revision 1.15  2002/05/12 16:53:16  peter
   Revision 1.15  2002/05/12 16:53:16  peter

+ 6 - 2
compiler/i386/cpunode.pas

@@ -30,7 +30,7 @@ unit cpunode;
 
 
     uses
     uses
        ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,
        ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,
-       n386ld,n386add,n386cal,n386con,n386cnv,n386flw,n386mat,n386mem,
+       n386add,n386cal,n386con,n386cnv,n386flw,n386mat,n386mem,
        n386set,n386inl,n386opt,
        n386set,n386inl,n386opt,
        { this not really a node }
        { this not really a node }
        n386obj, rgcpu;
        n386obj, rgcpu;
@@ -38,7 +38,11 @@ unit cpunode;
 end.
 end.
 {
 {
   $Log$
   $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
     * removed some more routines from cga
     * moved location_force_reg/mem to ncgutil
     * moved location_force_reg/mem to ncgutil
     * moved arrayconstructnode secondpass to ncgld
     * moved arrayconstructnode secondpass to ncgld

+ 18 - 16
compiler/i386/n386add.pas

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

+ 8 - 4
compiler/i386/n386cal.pas

@@ -51,7 +51,7 @@ implementation
     uses
     uses
       globtype,systems,
       globtype,systems,
       cutils,verbose,globals,
       cutils,verbose,globals,
-      symconst,symbase,symsym,symtable,aasm,types,
+      symconst,symbase,symsym,symtable,types,
 {$ifdef GDB}
 {$ifdef GDB}
   {$ifdef delphi}
   {$ifdef delphi}
       sysutils,
       sysutils,
@@ -61,9 +61,9 @@ implementation
       gdb,
       gdb,
 {$endif GDB}
 {$endif GDB}
       cginfo,cgbase,pass_2,
       cginfo,cgbase,pass_2,
-      cpubase,
+      cpubase,aasm,tainst,
       nmem,nld,ncnv,
       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
                              TI386CALLPARANODE
@@ -1484,7 +1484,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       iterator function

+ 15 - 13
compiler/i386/n386inl.pas

@@ -43,7 +43,7 @@ implementation
       cginfo,cgbase,pass_1,pass_2,
       cginfo,cgbase,pass_1,pass_2,
       cpubase,
       cpubase,
       nbas,ncon,ncal,ncnv,nld,
       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;
          href : treference;
          hp2 : tstringconstnode;
          hp2 : tstringconstnode;
          l : longint;
          l : longint;
-         ispushed : boolean;
+         pushedregs : tmaybesave;
          hregisterhi,
          hregisterhi,
          hregister : tregister;
          hregister : tregister;
          lengthlab,
          lengthlab,
@@ -190,7 +190,7 @@ implementation
                  else
                  else
                   cg.a_op_const_reg(exprasmlist,cgop,1,location.register);
                   cg.a_op_const_reg(exprasmlist,cgop,1,location.register);
 
 
-                 emitoverflowcheck(self);
+                 cg.g_overflowcheck(exprasmlist,self);
                  cg.g_rangecheck(exprasmlist,self,resulttype.def);
                  cg.g_rangecheck(exprasmlist,self,resulttype.def);
               end;
               end;
             in_dec_x,
             in_dec_x,
@@ -219,11 +219,10 @@ implementation
                 { second argument specified?, must be a s32bit in register }
                 { second argument specified?, must be a s32bit in register }
                 if assigned(tcallparanode(left).right) then
                 if assigned(tcallparanode(left).right) then
                  begin
                  begin
-                   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);
                    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 }
                    { when constant, just multiply the addvalue }
                    if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
                    if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
                     addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
                     addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
@@ -258,7 +257,7 @@ implementation
                        hregister,tcallparanode(left).left.location);
                        hregister,tcallparanode(left).left.location);
                    location_release(exprasmlist,tcallparanode(tcallparanode(left).right).left.location);
                    location_release(exprasmlist,tcallparanode(tcallparanode(left).right).left.location);
                  end;
                  end;
-                emitoverflowcheck(tcallparanode(left).left);
+                cg.g_overflowcheck(exprasmlist,tcallparanode(left).left);
                 cg.g_rangecheck(exprasmlist,tcallparanode(left).left,tcallparanode(left).left.resulttype.def);
                 cg.g_rangecheck(exprasmlist,tcallparanode(left).left,tcallparanode(left).left.resulttype.def);
               end;
               end;
 
 
@@ -323,11 +322,10 @@ implementation
                  else
                  else
                    begin
                    begin
                       { generate code for the element to set }
                       { 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);
                       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 }
                       { determine asm operator }
                       if inlinenumber=in_include_x_y then
                       if inlinenumber=in_include_x_y then
                         asmop:=A_BTS
                         asmop:=A_BTS
@@ -468,7 +466,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       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,
       cginfo,cgbase,pass_1,pass_2,
       ncon,
       ncon,
       cpubase,
       cpubase,
-      cga,tgobj,n386util,ncgutil,cgobj,rgobj,rgcpu;
+      cga,tgobj,ncgutil,cgobj,rgobj,rgcpu;
 
 
 {*****************************************************************************
 {*****************************************************************************
                              TI386MODDIVNODE
                              TI386MODDIVNODE
@@ -66,18 +66,18 @@ implementation
       var
       var
          hreg1 : tregister;
          hreg1 : tregister;
          hreg2 : tregister;
          hreg2 : tregister;
-         shrdiv, pushed,popeax,popedx : boolean;
+         shrdiv,popeax,popedx : boolean;
          power : longint;
          power : longint;
          hl : tasmlabel;
          hl : tasmlabel;
+         pushedregs : tmaybesave;
       begin
       begin
          shrdiv := false;
          shrdiv := false;
          secondpass(left);
          secondpass(left);
          if codegenerror then
          if codegenerror then
           exit;
           exit;
-         pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
+         maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
          secondpass(right);
          secondpass(right);
-         if pushed then
-           restore(left,is_64bitint(left.resulttype.def));
+         maybe_restore(exprasmlist,left.location,pushedregs);
          if codegenerror then
          if codegenerror then
           exit;
           exit;
          location_copy(location,left.location);
          location_copy(location,left.location);
@@ -270,18 +270,17 @@ implementation
       var
       var
          hregister2,hregister3,
          hregister2,hregister3,
          hregisterhigh,hregisterlow : tregister;
          hregisterhigh,hregisterlow : tregister;
-         pushed,popecx : boolean;
+         popecx : boolean;
          op : tasmop;
          op : tasmop;
          l1,l2,l3 : tasmlabel;
          l1,l2,l3 : tasmlabel;
-
+         pushedregs : tmaybesave;
       begin
       begin
          popecx:=false;
          popecx:=false;
 
 
          secondpass(left);
          secondpass(left);
-         pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
+         maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
          secondpass(right);
          secondpass(right);
-         if pushed then
-           restore(left,is_64bitint(left.resulttype.def));
+         maybe_restore(exprasmlist,left.location,pushedregs);
 
 
          { determine operator }
          { determine operator }
          case nodetype of
          case nodetype of
@@ -831,7 +830,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       iterator function

+ 9 - 7
compiler/i386/n386mem.pas

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

+ 6 - 2
compiler/i386/n386opt.pas

@@ -47,7 +47,7 @@ uses
   aasm,
   aasm,
   ncnv, ncon, pass_2,
   ncnv, ncon, pass_2,
   cginfo, cgbase, cpubase,
   cginfo, cgbase, cpubase,
-  tgobj, rgobj, cgobj, n386util;
+  tgobj, rgobj, cgobj, ncgutil;
 
 
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -248,7 +248,11 @@ end.
 
 
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       iterator function

+ 12 - 11
compiler/i386/n386set.pas

@@ -50,7 +50,7 @@ implementation
       cginfo,cgbase,pass_2,
       cginfo,cgbase,pass_2,
       ncon,
       ncon,
       cpubase,
       cpubase,
-      cga,cgobj,tgobj,ncgutil,n386util,regvars,rgobj;
+      cga,cgobj,tgobj,ncgutil,regvars,rgobj;
 
 
      const
      const
        bytes2Sxx:array[1..8] of Topsize=(S_B,S_W,S_NO,S_L,S_NO,S_NO,S_NO,S_Q);
        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;
     procedure ti386setelementnode.pass_2;
        var
        var
-         pushed: boolean;
+         pushedregs : tmaybesave;
        begin
        begin
        { load first value in 32bit register }
        { load first value in 32bit register }
          secondpass(left);
          secondpass(left);
@@ -71,12 +71,11 @@ implementation
        { also a second value ? }
        { also a second value ? }
          if assigned(right) then
          if assigned(right) then
            begin
            begin
-             pushed:=maybe_push(right.registers32,left,false);
+             maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
              secondpass(right);
              secondpass(right);
              if codegenerror then
              if codegenerror then
                exit;
                exit;
-             if pushed then
-               restore(left,false);
+             maybe_restore(exprasmlist,left.location,pushedregs);
              if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
              if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
               location_force_reg(exprasmlist,right.location,OS_32,false);
               location_force_reg(exprasmlist,right.location,OS_32,false);
            end;
            end;
@@ -99,7 +98,6 @@ implementation
        var
        var
          genjumps,
          genjumps,
          use_small,
          use_small,
-         pushed,
          ranges     : boolean;
          ranges     : boolean;
          hr,hr2,
          hr,hr2,
          pleftreg   : tregister;
          pleftreg   : tregister;
@@ -108,7 +106,7 @@ implementation
          setparts   : array[1..8] of Tsetpart;
          setparts   : array[1..8] of Tsetpart;
          i,numparts : byte;
          i,numparts : byte;
          adjustment : longint;
          adjustment : longint;
-         {href,href2 : Treference;}
+         pushedregs : tmaybesave;
          l,l2       : tasmlabel;
          l,l2       : tasmlabel;
 {$ifdef CORRECT_SET_IN_FPC}
 {$ifdef CORRECT_SET_IN_FPC}
          AM         : tasmop;
          AM         : tasmop;
@@ -194,10 +192,9 @@ implementation
          { Only process the right if we are not generating jumps }
          { Only process the right if we are not generating jumps }
          if not genjumps then
          if not genjumps then
           begin
           begin
-            pushed:=maybe_push(right.registers32,left,false);
+            maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
             secondpass(right);
             secondpass(right);
-            if pushed then
-             restore(left,false);
+            maybe_restore(exprasmlist,left.location,pushedregs);
           end;
           end;
          if codegenerror then
          if codegenerror then
           exit;
           exit;
@@ -1019,7 +1016,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       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,
       symconst,symtype,symdef,symsym,symtable,types,
       cgbase,
       cgbase,
       htypechk,pass_1,
       htypechk,pass_1,
-      nmat,ncnv,nld,ncon,nset,nopt,ncal,ninl,
+      nmat,ncnv,ncon,nset,nopt,ncal,ninl,
       cpubase;
       cpubase;
 
 
 
 
@@ -1617,7 +1617,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       iterator function

+ 9 - 1
compiler/ncgbas.pas

@@ -159,7 +159,11 @@ interface
                      begin
                      begin
                        { remove cached insentry, because the new code can
                        { remove cached insentry, because the new code can
                          require an other less optimized instruction }
                          require an other less optimized instruction }
+{$ifdef i386}
+{$ifndef NOAG386BIN}
                        taicpu(hp2).ResetPass1;
                        taicpu(hp2).ResetPass1;
+{$endif}
+{$endif}
                        { fixup the references }
                        { fixup the references }
                        for i:=1 to taicpu(hp2).ops do
                        for i:=1 to taicpu(hp2).ops do
                         begin
                         begin
@@ -290,7 +294,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       iterator function

+ 6 - 2
compiler/ncgflw.pas

@@ -67,7 +67,7 @@ implementation
 
 
     uses
     uses
       verbose,globals,systems,globtype,
       verbose,globals,systems,globtype,
-      symconst,symdef,symsym,aasm,types,
+      symconst,symsym,aasm,types,
       cginfo,cgbase,pass_2,
       cginfo,cgbase,pass_2,
       cpubase,cpuasm,cpuinfo,
       cpubase,cpuasm,cpuinfo,
       nld,ncon,
       nld,ncon,
@@ -611,7 +611,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       iterator function

+ 652 - 2
compiler/ncgld.pas

@@ -31,20 +31,663 @@ interface
       node,nld;
       node,nld;
 
 
     type
     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)
        tcgarrayconstructornode = class(tarrayconstructornode)
           procedure pass_2;override;
           procedure pass_2;override;
        end;
        end;
 
 
+
 implementation
 implementation
 
 
     uses
     uses
       systems,
       systems,
       verbose,globals,
       verbose,globals,
-      symconst,symtype,symdef,aasm,types,
+      symconst,symtype,symdef,symsym,symtable,types,
+      ncnv,ncon,nmem,
+      aasm,cpuasm,regvars,
       cginfo,cgbase,pass_2,
       cginfo,cgbase,pass_2,
       cpubase,
       cpubase,
       tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
       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
                            SecondArrayConstruct
 *****************************************************************************}
 *****************************************************************************}
@@ -256,11 +899,18 @@ implementation
       end;
       end;
 
 
 begin
 begin
+   cloadnode:=tcgloadnode;
+   cassignmentnode:=tcgassignmentnode;
+   cfuncretnode:=tcgfuncretnode;
    carrayconstructornode:=tcgarrayconstructornode;
    carrayconstructornode:=tcgarrayconstructornode;
 end.
 end.
 {
 {
   $Log$
   $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
     * moved entry and exitcode to ncgutil and cgobj
     * foreach gets extra argument for passing local data to the
     * foreach gets extra argument for passing local data to the
       iterator function
       iterator function

+ 421 - 58
compiler/ncgutil.pas

@@ -28,16 +28,30 @@ interface
 
 
     uses
     uses
       node,
       node,
-      cginfo,cpubase,aasm;
+      cginfo,cpubase,aasm,
+      rgobj;
 
 
     type
     type
       tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
       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_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
     procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
     procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
 
 
-    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;
     procedure genentrycode(list : TAAsmoutput;
                            make_global:boolean;
                            make_global:boolean;
@@ -65,7 +79,130 @@ implementation
     gdb,
     gdb,
 {$endif GDB}
 {$endif GDB}
     ncon,
     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;
       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
       begin
-         if nf_error in p.flags then
+        s.saved:=false;
+        if l.loc=LOC_CREGISTER then
+         begin
+           s.saved:=true;
            exit;
            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
               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;
                        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
                        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;
       end;
 
 
 
 
@@ -703,6 +1060,7 @@ implementation
         href : treference;
         href : treference;
         p : tsymtable;
         p : tsymtable;
         tempbuf : treference;
         tempbuf : treference;
+        tmpreg : tregister;
       begin
       begin
         { Insert alignment and assembler names }
         { Insert alignment and assembler names }
         if not inlined then
         if not inlined then
@@ -878,11 +1236,12 @@ implementation
               include(rg.usedinproc,accumulator);
               include(rg.usedinproc,accumulator);
 
 
               { allocate exception frame buffer }
               { 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);
               cg.g_push_exception(list,tempbuf,1,aktexitlabel);
+              reference_release(list,tempbuf);
 
 
               { probably we've to reload self here }
               { probably we've to reload self here }
               cg.g_maybe_loadself(list);
               cg.g_maybe_loadself(list);
@@ -1097,7 +1456,7 @@ implementation
             cg.g_restore_frame_pointer(list)
             cg.g_restore_frame_pointer(list)
            else
            else
             if (tg.gettempsize<>0) then
             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;
          end;
 
 
         { at last, the return is generated }
         { at last, the return is generated }
@@ -1147,7 +1506,7 @@ implementation
                     st:='';
                     st:='';
                   list.concat(Tai_stabs.Create(strpnew(
                   list.concat(Tai_stabs.Create(strpnew(
                    '"$t:r'+st+procinfo^._class.numberstring+'",'+
                    '"$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;
                 end;
 
 
             { define calling EBP as pseudo local var PM }
             { define calling EBP as pseudo local var PM }
@@ -1248,7 +1607,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $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
   * some small portability fixes
 
 
   Revision 1.11  2002/05/12 16:53:07  peter
   Revision 1.11  2002/05/12 16:53:07  peter