Jelajahi Sumber

* 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

peter 23 tahun lalu
induk
melakukan
5b242f7741
60 mengubah file dengan 5103 tambahan dan 5023 penghapusan
  1. 12 3
      compiler/assemble.pas
  2. 229 7
      compiler/cg64f32.pas
  3. 64 58
      compiler/cgbase.pas
  4. 119 27
      compiler/cgobj.pas
  5. 15 7
      compiler/cutils.pas
  6. 14 3
      compiler/globals.pas
  7. 15 4
      compiler/htypechk.pas
  8. 57 54
      compiler/i386/ag386att.pas
  9. 14 9
      compiler/i386/ag386int.pas
  10. 15 10
      compiler/i386/ag386nsm.pas
  11. 128 390
      compiler/i386/cga.pas
  12. 238 99
      compiler/i386/cgcpu.pas
  13. 43 32
      compiler/i386/cpuasm.pas
  14. 88 138
      compiler/i386/cpubase.pas
  15. 13 1
      compiler/i386/cpuinfo.pas
  16. 18 7
      compiler/i386/csopt386.pas
  17. 22 17
      compiler/i386/daopt386.pas
  18. 1261 1528
      compiler/i386/n386add.pas
  19. 192 215
      compiler/i386/n386cal.pas
  20. 182 196
      compiler/i386/n386cnv.pas
  21. 16 5
      compiler/i386/n386con.pas
  22. 13 3
      compiler/i386/n386flw.pas
  23. 113 234
      compiler/i386/n386inl.pas
  24. 370 431
      compiler/i386/n386ld.pas
  25. 257 402
      compiler/i386/n386mat.pas
  26. 104 162
      compiler/i386/n386mem.pas
  27. 36 8
      compiler/i386/n386obj.pas
  28. 37 32
      compiler/i386/n386opt.pas
  29. 93 87
      compiler/i386/n386set.pas
  30. 341 209
      compiler/i386/n386util.pas
  31. 16 5
      compiler/i386/ra386.pas
  32. 13 2
      compiler/i386/ra386att.pas
  33. 13 2
      compiler/i386/ra386int.pas
  34. 18 13
      compiler/i386/rgcpu.pas
  35. 18 7
      compiler/i386/rropt386.pas
  36. 40 39
      compiler/nadd.pas
  37. 16 5
      compiler/ncal.pas
  38. 126 101
      compiler/ncgcnv.pas
  39. 36 45
      compiler/ncgcon.pas
  40. 85 116
      compiler/ncgflw.pas
  41. 66 48
      compiler/ncgmem.pas
  42. 16 5
      compiler/ncgutil.pas
  43. 39 32
      compiler/ncnv.pas
  44. 25 8
      compiler/ncon.pas
  45. 22 11
      compiler/ninl.pas
  46. 26 11
      compiler/nld.pas
  47. 14 3
      compiler/nmat.pas
  48. 21 10
      compiler/nmem.pas
  49. 13 2
      compiler/nopt.pas
  50. 30 21
      compiler/nset.pas
  51. 26 2
      compiler/pass_2.pas
  52. 57 48
      compiler/pmodules.pas
  53. 13 2
      compiler/rautils.pas
  54. 15 4
      compiler/regvars.pas
  55. 116 42
      compiler/rgobj.pas
  56. 18 8
      compiler/symdef.pas
  57. 35 33
      compiler/tainst.pas
  58. 21 12
      compiler/targets/t_win32.pas
  59. 16 5
      compiler/tgobj.pas
  60. 14 3
      compiler/types.pas

+ 12 - 3
compiler/assemble.pas

@@ -1095,8 +1095,6 @@ Implementation
                            end;
                            end;
                          top_symbol :
                          top_symbol :
                            begin
                            begin
-                             if sym=nil then
-                              sym:=sym;
                              UsedAsmSymbolListInsert(sym);
                              UsedAsmSymbolListInsert(sym);
                            end;
                            end;
                        end;
                        end;
@@ -1553,7 +1551,18 @@ Implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.29  2001-11-06 14:53:48  jonas
+  Revision 1.30  2002-04-02 17:11:27  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.29  2001/11/06 14:53:48  jonas
     * compiles again with -dmemdebug
     * compiles again with -dmemdebug
 
 
   Revision 1.28  2001/09/18 11:30:47  michael
   Revision 1.28  2001/09/18 11:30:47  michael

+ 229 - 7
compiler/cg64f32.pas

@@ -30,18 +30,41 @@ unit cg64f32;
   interface
   interface
 
 
     uses
     uses
-       aasm, cgobj, cpubase,node,symtype;
+       aasm,
+       cpuinfo, cpubase,
+       cginfo, cgobj,
+       node,symtype;
 
 
     type
     type
       tcg64f32 = class(tcg)
       tcg64f32 = class(tcg)
+        procedure a_load64_const_ref(list : taasmoutput;valuelo, valuehi : AWord;const ref : treference);
         procedure a_load64_reg_ref(list : taasmoutput;reglo, reghi : tregister;const ref : treference);
         procedure a_load64_reg_ref(list : taasmoutput;reglo, reghi : tregister;const ref : treference);
         procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reglo,reghi : tregister);
         procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reglo,reghi : tregister);
         procedure a_load64_reg_reg(list : taasmoutput;reglosrc,reghisrc,reglodst,reghidst : tregister);
         procedure a_load64_reg_reg(list : taasmoutput;reglosrc,reghisrc,reglodst,reghidst : tregister);
+        procedure a_load64_const_reg(list : taasmoutput;valuelosrc,valuehisrc:AWord;reglodst,reghidst : tregister);
         procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reglo,reghi : tregister);
         procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reglo,reghi : tregister);
+        procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);
+        procedure a_load64_reg_loc(list : taasmoutput;reglo, reghi : tregister;const l : tlocation);
         procedure a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
         procedure a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
         procedure a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
         procedure a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
         procedure a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
         procedure a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
         procedure a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
         procedure a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
+        procedure a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
+        procedure a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
+
+        procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reglo,reghi : tregister);virtual;abstract;
+        procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;reglosrc,reghisrc,reglodst,reghidst : tregister);virtual;abstract;
+        procedure a_op64_reg_ref(list : taasmoutput;op:TOpCG;reglosrc,reghisrc : tregister;const ref : treference);virtual;abstract;
+        procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;reglodst,reghidst : tregister);virtual;abstract;
+        procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;const ref : treference);virtual;abstract;
+        procedure a_op64_const_loc(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:aword;const l: tlocation);
+        procedure a_op64_reg_loc(list : taasmoutput;op:TOpCG;reglo,reghi : tregister;const l : tlocation);
+        procedure a_op64_loc_reg(list : taasmoutput;op:TOpCG;const l : tlocation;reglo,reghi : tregister);
+
+        procedure a_param64_reg(list : taasmoutput;reglo,reghi : tregister;nr : longint);
+        procedure a_param64_const(list : taasmoutput;valuelo,valuehi : aword;nr : longint);
+        procedure a_param64_ref(list : taasmoutput;const r : treference;nr : longint);
+        procedure a_param64_loc(list : taasmoutput;const l : tlocation;nr : longint);
 
 
         { override to catch 64bit rangechecks }
         { override to catch 64bit rangechecks }
         procedure g_rangecheck(list: taasmoutput; const p: tnode;
         procedure g_rangecheck(list: taasmoutput; const p: tnode;
@@ -60,8 +83,7 @@ unit cg64f32;
        globtype,globals,systems,
        globtype,globals,systems,
        cgbase,
        cgbase,
        verbose,
        verbose,
-       symbase,symconst,symdef,types,
-       cpuinfo;
+       symbase,symconst,symdef,types;
 
 
     procedure tcg64f32.a_load64_reg_ref(list : taasmoutput;reglo, reghi : tregister;const ref : treference);
     procedure tcg64f32.a_load64_reg_ref(list : taasmoutput;reglo, reghi : tregister;const ref : treference);
       var
       var
@@ -80,10 +102,29 @@ unit cg64f32;
         a_load_reg_ref(list,OS_32,reghi,tmpref);
         a_load_reg_ref(list,OS_32,reghi,tmpref);
       end;
       end;
 
 
+    procedure tcg64f32.a_load64_const_ref(list : taasmoutput;valuelo, valuehi : AWord;const ref : treference);
+      var
+        tmpvalue: AWord;
+        tmpref: treference;
+      begin
+        if target_info.endian = endian_big then
+          begin
+            tmpvalue := valuelo;
+            valuelo := valuehi;
+            valuehi := tmpvalue;
+          end;
+        a_load_const_ref(list,OS_32,valuelo,ref);
+        tmpref := ref;
+        inc(tmpref.offset,4);
+        a_load_const_ref(list,OS_32,valuehi,tmpref);
+      end;
+
+
     procedure tcg64f32.a_load64_ref_reg(list : taasmoutput;const ref : treference;reglo,reghi : tregister);
     procedure tcg64f32.a_load64_ref_reg(list : taasmoutput;const ref : treference;reglo,reghi : tregister);
       var
       var
         tmpreg: tregister;
         tmpreg: tregister;
         tmpref: treference;
         tmpref: treference;
+        got_scratch: boolean;
       begin
       begin
         if target_info.endian = endian_big then
         if target_info.endian = endian_big then
           begin
           begin
@@ -91,12 +132,31 @@ unit cg64f32;
             reglo := reghi;
             reglo := reghi;
             reghi := tmpreg;
             reghi := tmpreg;
           end;
           end;
-        a_load_ref_reg(list,OS_32,ref,reglo);
+        got_scratch:=false;
         tmpref := ref;
         tmpref := ref;
+        if (tmpref.base=reglo) then
+         begin
+           tmpreg := get_scratch_reg(list);
+           got_scratch:=true;
+           a_load_reg_reg(list,OS_ADDR,tmpref.base,tmpreg);
+           tmpref.base:=tmpreg;
+         end
+        else
+         if (tmpref.index=reglo) then
+          begin
+            tmpreg := get_scratch_reg(list);
+            got_scratch:=true;
+            a_load_reg_reg(list,OS_ADDR,tmpref.index,tmpreg);
+            tmpref.index:=tmpreg;
+          end;
+        a_load_ref_reg(list,OS_32,tmpref,reglo);
         inc(tmpref.offset,4);
         inc(tmpref.offset,4);
         a_load_ref_reg(list,OS_32,tmpref,reghi);
         a_load_ref_reg(list,OS_32,tmpref,reghi);
+        if got_scratch then
+         free_scratch_reg(list,tmpreg);
       end;
       end;
 
 
+
     procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;reglosrc,reghisrc,reglodst,reghidst : tregister);
     procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;reglosrc,reghisrc,reglodst,reghidst : tregister);
 
 
       begin
       begin
@@ -104,21 +164,57 @@ unit cg64f32;
         a_load_reg_reg(list,OS_32,reghisrc,reghidst);
         a_load_reg_reg(list,OS_32,reghisrc,reghidst);
       end;
       end;
 
 
+    procedure tcg64f32.a_load64_const_reg(list : taasmoutput;valuelosrc,valuehisrc:AWord;reglodst,reghidst : tregister);
+
+      begin
+        a_load_const_reg(list,OS_32,valuelosrc,reglodst);
+        a_load_const_reg(list,OS_32,valuehisrc,reghidst);
+      end;
 
 
     procedure tcg64f32.a_load64_loc_reg(list : taasmoutput;const l : tlocation;reglo,reghi : tregister);
     procedure tcg64f32.a_load64_loc_reg(list : taasmoutput;const l : tlocation;reglo,reghi : tregister);
 
 
       begin
       begin
         case l.loc of
         case l.loc of
-          LOC_REFERENCE, LOC_MEM:
+          LOC_REFERENCE, LOC_CREFERENCE:
             a_load64_ref_reg(list,l.reference,reglo,reghi);
             a_load64_ref_reg(list,l.reference,reglo,reghi);
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
             a_load64_reg_reg(list,l.registerlow,l.registerhigh,reglo,reghi);
             a_load64_reg_reg(list,l.registerlow,l.registerhigh,reglo,reghi);
+          LOC_CONSTANT :
+            a_load64_const_reg(list,l.valuelow,l.valuehigh,reglo,reghi);
           else
           else
             internalerror(200112292);
             internalerror(200112292);
         end;
         end;
       end;
       end;
 
 
 
 
+    procedure tcg64f32.a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);
+      begin
+        case l.loc of
+          LOC_REGISTER,LOC_CREGISTER:
+            a_load64_reg_ref(list,l.registerlow,l.registerhigh,ref);
+          LOC_CONSTANT :
+            a_load64_const_ref(list,l.valuelow,l.valuehigh,ref);
+          else
+            internalerror(200203288);
+        end;
+      end;
+
+
+    procedure tcg64f32.a_load64_reg_loc(list : taasmoutput;reglo,reghi : tregister;const l : tlocation);
+
+      begin
+        case l.loc of
+          LOC_REFERENCE, LOC_CREFERENCE:
+            a_load64_reg_ref(list,reglo,reghi,l.reference);
+          LOC_REGISTER,LOC_CREGISTER:
+            a_load64_reg_reg(list,reglo,reghi,l.registerlow,l.registerhigh);
+          else
+            internalerror(200112293);
+        end;
+      end;
+
+
+
     procedure tcg64f32.a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
     procedure tcg64f32.a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
       var
       var
         tmpref: treference;
         tmpref: treference;
@@ -175,6 +271,121 @@ unit cg64f32;
           end;
           end;
       end;
       end;
 
 
+    procedure tcg64f32.a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
+      begin
+        case l.loc of
+          LOC_REFERENCE,
+          LOC_CREFERENCE :
+            a_load64low_ref_reg(list,l.reference,reg);
+          LOC_REGISTER :
+            a_load_reg_reg(list,OS_32,l.registerlow,reg);
+          LOC_CONSTANT :
+            a_load_const_reg(list,OS_32,l.valuelow,reg);
+          else
+            internalerror(200203244);
+        end;
+      end;
+
+    procedure tcg64f32.a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
+      begin
+        case l.loc of
+          LOC_REFERENCE,
+          LOC_CREFERENCE :
+            a_load64high_ref_reg(list,l.reference,reg);
+          LOC_REGISTER :
+            a_load_reg_reg(list,OS_32,l.registerhigh,reg);
+          LOC_CONSTANT :
+            a_load_const_reg(list,OS_32,l.valuehigh,reg);
+          else
+            internalerror(200203244);
+        end;
+      end;
+
+
+    procedure tcg64f32.a_op64_const_loc(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:aword;const l: tlocation);
+      begin
+        case l.loc of
+          LOC_REFERENCE, LOC_CREFERENCE:
+            a_op64_const_reg(list,op,valuelosrc,valuehisrc,l.registerlow,l.registerhigh);
+          LOC_REGISTER,LOC_CREGISTER:
+            a_op64_const_ref(list,op,valuelosrc,valuehisrc,l.reference);
+          else
+            internalerror(200203292);
+        end;
+      end;
+
+
+    procedure tcg64f32.a_op64_reg_loc(list : taasmoutput;op:TOpCG;reglo,reghi : tregister;const l : tlocation);
+      begin
+        case l.loc of
+          LOC_REFERENCE, LOC_CREFERENCE:
+            a_op64_reg_ref(list,op,reglo,reghi,l.reference);
+          LOC_REGISTER,LOC_CREGISTER:
+            a_op64_reg_reg(list,op,reglo,reghi,l.registerlow,l.registerhigh);
+          else
+            internalerror(2002032422);
+        end;
+      end;
+
+
+
+    procedure tcg64f32.a_op64_loc_reg(list : taasmoutput;op:TOpCG;const l : tlocation;reglo,reghi : tregister);
+      begin
+        case l.loc of
+          LOC_REFERENCE, LOC_CREFERENCE:
+            a_op64_ref_reg(list,op,l.reference,reglo,reghi);
+          LOC_REGISTER,LOC_CREGISTER:
+            a_op64_reg_reg(list,op,l.registerlow,l.registerhigh,reglo,reghi);
+          LOC_CONSTANT :
+            a_op64_const_reg(list,op,l.valuelow,l.valuehigh,reglo,reghi);
+          else
+            internalerror(200203242);
+        end;
+      end;
+
+
+    procedure tcg64f32.a_param64_reg(list : taasmoutput;reglo,reghi : tregister;nr : longint);
+      begin
+         a_param_reg(list,OS_32,reghi,nr);
+         a_param_reg(list,OS_32,reglo,nr+1);
+      end;
+
+
+    procedure tcg64f32.a_param64_const(list : taasmoutput;valuelo,valuehi : aword;nr : longint);
+      begin
+         a_param_const(list,OS_32,valuehi,nr);
+         a_param_const(list,OS_32,valuelo,nr+1);
+      end;
+
+
+    procedure tcg64f32.a_param64_ref(list : taasmoutput;const r : treference;nr : longint);
+      var
+        tmpref: treference;
+      begin
+        a_param_ref(list,OS_32,r,nr);
+        tmpref := r;
+        inc(tmpref.offset,4);
+        a_param_ref(list,OS_32,tmpref,nr+1);
+      end;
+
+
+    procedure tcg64f32.a_param64_loc(list : taasmoutput;const l:tlocation;nr : longint);
+      begin
+        case l.loc of
+          LOC_REGISTER,
+          LOC_CREGISTER :
+            a_param64_reg(list,l.registerlow,l.registerhigh,nr);
+          LOC_CONSTANT :
+            a_param64_const(list,l.valuelow,l.valuehigh,nr);
+          LOC_CREFERENCE,
+          LOC_REFERENCE :
+            a_param64_ref(list,l.reference,nr);
+        else
+          internalerror(200203287);
+        end;
+      end;
+
+
 
 
     procedure tcg64f32.g_rangecheck(list: taasmoutput; const p: tnode;
     procedure tcg64f32.g_rangecheck(list: taasmoutput; const p: tnode;
         const todef: tdef);
         const todef: tdef);
@@ -358,7 +569,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.4  2002-03-04 19:10:11  peter
+  Revision 1.5  2002-04-02 17:11:27  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.4  2002/03/04 19:10:11  peter
     * removed compiler warnings
     * removed compiler warnings
 
 
   Revision 1.3  2002/01/24 12:33:52  jonas
   Revision 1.3  2002/01/24 12:33:52  jonas
@@ -396,4 +618,4 @@ end.
   Revision 1.1  2000/03/01 15:36:13  florian
   Revision 1.1  2000/03/01 15:36:13  florian
     * some new stuff for the new cg
     * some new stuff for the new cg
 
 
-}
+}

+ 64 - 58
compiler/cgbase.pas

@@ -34,31 +34,24 @@ unit cgbase;
       { symtable }
       { symtable }
       symconst,symtype,symdef,symsym,
       symconst,symtype,symdef,symsym,
       { aasm }
       { aasm }
-      aasm,cpubase, cpuinfo
+      aasm,cpubase,cpuinfo,cginfo
       ;
       ;
 
 
-    type
-       TOpCg = (OP_ADD,OP_AND,OP_DIV,OP_IDIV,OP_IMUL,OP_MUL,OP_NEG,OP_NOT,
-                   OP_OR,OP_SAR,OP_SHL,OP_SHR,OP_SUB,OP_XOR);
 
 
-       TOpCmp = (OC_NONE,OC_EQ,OC_GT,OC_LT,OC_GTE,OC_LTE,OC_NE,OC_BE,OC_B,
-                 OC_AE,OC_A);
+    const
+       TCGSize2Size: Array[tcgsize] of longint = (0,
+          8,16,32,64,8,16,32,64,
+          32,64,80,64,
+          8,16,32,64,128,8,16,32,64,128);
 
 
-       TCgSize = (OS_NO,OS_8,OS_16,OS_32,OS_64,OS_S8,OS_S16,OS_S32,OS_S64,
-                { single,double,extended,comp }
-                  OS_F32,OS_F64,OS_F80,OS_C64,
-                { multi-media sizes: split in byte, word, dword, ... }
-                { entities, then the signed counterparts             }
-                  OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,OS_MS8,OS_MS16,OS_MS32,
-                  OS_MS64,OS_MS128);
+       tfloat2tcgsize: array[tfloattype] of tcgsize =
+         (OS_F32,OS_F64,OS_F80,OS_C64);
 
 
-    const
-      tfloat2tcgsize: array[tfloattype] of tcgsize =
-        (OS_F32,OS_F64,OS_F80,OS_C64);
+       tcgsize2tfloat: array[OS_F32..OS_C64] of tfloattype =
+         (s32real,s64real,s80real,s64comp);
 
 
-      tcgsize2tfloat: array[OS_F32..OS_C64] of tfloattype =
-        (s32real,s64real,s80real,s64comp);
 
 
+    const
        pi_uses_asm  = $1;       { set, if the procedure uses asm }
        pi_uses_asm  = $1;       { set, if the procedure uses asm }
        pi_is_global = $2;       { set, if the procedure is exported by an unit }
        pi_is_global = $2;       { set, if the procedure is exported by an unit }
        pi_do_call   = $4;       { set, if the procedure does a call }
        pi_do_call   = $4;       { set, if the procedure does a call }
@@ -71,41 +64,6 @@ unit cgbase;
        pi_needs_implicit_finally = $80; { set, if the procedure contains data which }
        pi_needs_implicit_finally = $80; { set, if the procedure contains data which }
                                         { needs to be finalized              }
                                         { needs to be finalized              }
 
 
-       { defines the default address size for a processor, }
-       { the natural int size for a processor,             }
-       { the maximum float size for a processor,           }
-       { the size of a vector register for a processor     }
-{$ifdef i386}
-       OS_ADDR = OS_32;
-       OS_INT = OS_32;
-       OS_FLOAT = OS_F80;
-       OS_VECTOR = OS_M64;
-{$endif i386}
-{$ifdef m68k}
-       OS_ADDR = OS_32;
-       OS_INT = OS_32;
-       OS_FLOAT = OS_F??; { processor supports 64bit, but does the compiler? }
-       OS_VECTOR = OS_NO;
-{$endif m68k}
-{$ifdef alpha}
-       OS_ADDR = OS_64;
-       OS_INT = OS_64;
-       OS_FLOAT = OS_F??;
-       OS_VECTOR = OS_NO;
-{$endif alpha}
-{$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}
-
     type
     type
        pprocinfo = ^tprocinfo;
        pprocinfo = ^tprocinfo;
        tprocinfo = object
        tprocinfo = object
@@ -211,7 +169,7 @@ unit cgbase;
     procedure codegen_newmodule;
     procedure codegen_newmodule;
     procedure codegen_newprocedure;
     procedure codegen_newprocedure;
 
 
-
+    function def_cgsize_ref(const p1: tdef): tcgsize;
     function def_cgsize(const p1: tdef): tcgsize;
     function def_cgsize(const p1: tdef): tcgsize;
     function int_cgsize(const l: aword): tcgsize;
     function int_cgsize(const l: aword): tcgsize;
 
 
@@ -471,19 +429,56 @@ implementation
          ResourceStrings.free;
          ResourceStrings.free;
       end;
       end;
 
 
+    function def_cgsize_ref(const p1: tdef): tcgsize;
+      begin
+        { return always SO_NO for arraydef, becuase for
+          some array types (open array) the size can not be determined }
+        if p1.deftype=arraydef then
+         result:=OS_NO
+        else
+         begin
+           case p1.size of
+             1    : result := OS_8;
+             2    : result := OS_16;
+             3,4  : result := OS_32;
+             5..8 : result := OS_64;
+             else   result := OS_NO;
+           end;
+           if is_signed(p1) then
+             result := tcgsize(ord(result)+(ord(OS_S8)-ord(OS_8)));
+         end;
+      end;
 
 
     function def_cgsize(const p1: tdef): tcgsize;
     function def_cgsize(const p1: tdef): tcgsize;
 
 
       begin
       begin
         case p1.deftype of
         case p1.deftype of
-          orddef, enumdef, setdef:
+          orddef,
+          enumdef,
+          setdef:
             begin
             begin
               result := int_cgsize(p1.size);
               result := int_cgsize(p1.size);
               if is_signed(p1) then
               if is_signed(p1) then
                 result := tcgsize(ord(result)+(ord(OS_S8)-ord(OS_8)));
                 result := tcgsize(ord(result)+(ord(OS_S8)-ord(OS_8)));
             end;
             end;
-          pointerdef, procvardef:
+          classrefdef,
+          pointerdef,
+          procvardef:
             result := OS_ADDR;
             result := OS_ADDR;
+          stringdef :
+            begin
+              if is_ansistring(p1) or is_widestring(p1) then
+                result := OS_ADDR
+              else
+                internalerror(200203314);
+            end;
+          objectdef :
+            begin
+              if is_class_or_interface(p1) then
+                result := OS_ADDR
+              else
+                internalerror(200203313);
+            end;
           floatdef:
           floatdef:
             result := tfloat2tcgsize[tfloatdef(p1).typ];
             result := tfloat2tcgsize[tfloatdef(p1).typ];
           else
           else
@@ -517,7 +512,7 @@ implementation
     function commutativeop(op: topcg): boolean;
     function commutativeop(op: topcg): boolean;
       const
       const
         list: array[topcg] of boolean =
         list: array[topcg] of boolean =
-          (true,true,false,false,true,true,false,false,
+          (true,true,true,false,false,true,true,false,false,
            true,false,false,false,false,true);
            true,false,false,false,false,true);
       begin
       begin
         commutativeop := list[op];
         commutativeop := list[op];
@@ -547,7 +542,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.7  2002-03-31 20:26:33  jonas
+  Revision 1.8  2002-04-02 17:11:27  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.7  2002/03/31 20:26:33  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 119 - 27
compiler/cgobj.pas

@@ -28,7 +28,9 @@ unit cgobj;
   interface
   interface
 
 
     uses
     uses
-       cclasses,aasm,symtable,cpuasm,cpubase,cgbase,cpuinfo,
+       cclasses,aasm,symtable,
+       cpuasm,cpubase,cpuinfo,
+       cginfo,
        symconst,symbase,symtype,node;
        symconst,symbase,symtype,node;
 
 
     type
     type
@@ -96,6 +98,7 @@ unit cgobj;
           procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;nr : longint);virtual; abstract;
           procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;nr : longint);virtual; abstract;
           procedure a_param_const(list : taasmoutput;size : tcgsize;a : aword;nr : longint);virtual;
           procedure a_param_const(list : taasmoutput;size : tcgsize;a : aword;nr : longint);virtual;
           procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;nr : longint);virtual;
           procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;nr : longint);virtual;
+          procedure a_param_loc(list : taasmoutput;size : tcgsize;const l : tlocation;nr : longint);
           procedure a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);virtual;
           procedure a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);virtual;
 
 
           {**********************************}
           {**********************************}
@@ -124,9 +127,11 @@ unit cgobj;
           { move instructions }
           { move instructions }
           procedure a_load_const_reg(list : taasmoutput;size : tcgsize;a : aword;register : tregister);virtual; abstract;
           procedure a_load_const_reg(list : taasmoutput;size : tcgsize;a : aword;register : tregister);virtual; abstract;
           procedure a_load_const_ref(list : taasmoutput;size : tcgsize;a : aword;const ref : treference);virtual;
           procedure a_load_const_ref(list : taasmoutput;size : tcgsize;a : aword;const ref : treference);virtual;
+          procedure a_load_const_loc(list : taasmoutput;size : tcgsize;a : aword;const loc : tlocation);
           procedure a_load_reg_ref(list : taasmoutput;size : tcgsize;register : tregister;const ref : treference);virtual; abstract;
           procedure a_load_reg_ref(list : taasmoutput;size : tcgsize;register : tregister;const ref : treference);virtual; abstract;
-          procedure a_load_ref_reg(list : taasmoutput;size : tcgsize;const ref : treference;register : tregister);virtual; abstract;
           procedure a_load_reg_reg(list : taasmoutput;size : tcgsize;reg1,reg2 : tregister);virtual; abstract;
           procedure a_load_reg_reg(list : taasmoutput;size : tcgsize;reg1,reg2 : tregister);virtual; abstract;
+          procedure a_load_reg_loc(list : taasmoutput;size : tcgsize;reg : tregister;const loc: tlocation);
+          procedure a_load_ref_reg(list : taasmoutput;size : tcgsize;const ref : treference;register : tregister);virtual; abstract;
           procedure a_load_loc_reg(list : taasmoutput;size : tcgsize;const loc: tlocation; reg : tregister);
           procedure a_load_loc_reg(list : taasmoutput;size : tcgsize;const loc: tlocation; reg : tregister);
           procedure a_load_loc_ref(list : taasmoutput;size : tcgsize;const loc: tlocation; const ref : treference);
           procedure a_load_loc_ref(list : taasmoutput;size : tcgsize;const loc: tlocation; const ref : treference);
           procedure a_load_sym_ofs_reg(list: taasmoutput; const sym: tasmsymbol; ofs: longint; reg: tregister);virtual; abstract;
           procedure a_load_sym_ofs_reg(list: taasmoutput; const sym: tasmsymbol; ofs: longint; reg: tregister);virtual; abstract;
@@ -174,6 +179,7 @@ unit cgobj;
             l : tasmlabel);
             l : tasmlabel);
           procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); virtual; abstract;
           procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); virtual; abstract;
           procedure a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const ref: treference; reg : tregister; l : tasmlabel); virtual;
           procedure a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const ref: treference; reg : tregister; l : tasmlabel); virtual;
+          procedure a_cmp_loc_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
           procedure a_cmp_ref_loc_label(list: taasmoutput; size: tcgsize;cmp_op: topcmp; const ref: treference; const loc: tlocation;
           procedure a_cmp_ref_loc_label(list: taasmoutput; size: tcgsize;cmp_op: topcmp; const ref: treference; const loc: tlocation;
             l : tasmlabel);
             l : tasmlabel);
 
 
@@ -182,7 +188,7 @@ unit cgobj;
 
 
           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 a_loadaddress_ref_reg(list : taasmoutput;const ref : treference;r : tregister);virtual; abstract;
+          procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);virtual; abstract;
           procedure g_stackframe_entry(list : taasmoutput;localsize : longint);virtual; abstract;
           procedure g_stackframe_entry(list : taasmoutput;localsize : longint);virtual; abstract;
           { restores the frame pointer at procedure exit, for the }
           { restores the frame pointer at procedure exit, for the }
           { i386 it generates a simple leave                      }
           { i386 it generates a simple leave                      }
@@ -235,7 +241,7 @@ unit cgobj;
   implementation
   implementation
 
 
     uses
     uses
-       strings,globals,globtype,options,gdb,systems,
+       strings,globals,globtype,options,gdb,systems,cgbase,
        ppu,verbose,types,tgobj,symdef,symsym,cga,tainst,rgobj;
        ppu,verbose,types,tgobj,symdef,symsym,cga,tainst,rgobj;
 
 
     const
     const
@@ -357,6 +363,25 @@ unit cgobj;
          free_scratch_reg(list,hr);
          free_scratch_reg(list,hr);
       end;
       end;
 
 
+
+    procedure tcg.a_param_loc(list : taasmoutput;size : tcgsize;const l:tlocation;nr : longint);
+
+      begin
+        case l.loc of
+          LOC_REGISTER,
+          LOC_CREGISTER :
+            a_param_reg(list,size,l.register,nr);
+          LOC_CONSTANT :
+            a_param_const(list,size,l.value,nr);
+          LOC_CREFERENCE,
+          LOC_REFERENCE :
+            a_param_ref(list,size,l.reference,nr);
+        else
+          internalerror(2002032211);
+        end;
+      end;
+
+
     procedure tcg.a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);
     procedure tcg.a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);
 
 
       var
       var
@@ -364,11 +389,12 @@ unit cgobj;
 
 
       begin
       begin
          hr:=get_scratch_reg(list);
          hr:=get_scratch_reg(list);
-         a_loadaddress_ref_reg(list,r,hr);
+         a_loadaddr_ref_reg(list,r,hr);
          a_param_reg(list,OS_ADDR,hr,nr);
          a_param_reg(list,OS_ADDR,hr,nr);
          free_scratch_reg(list,hr);
          free_scratch_reg(list,hr);
       end;
       end;
 
 
+
     procedure tcg.g_stackcheck(list : taasmoutput;stackframesize : longint);
     procedure tcg.g_stackcheck(list : taasmoutput;stackframesize : longint);
 
 
       begin
       begin
@@ -1077,15 +1103,44 @@ unit cgobj;
 
 
       begin
       begin
         case loc.loc of
         case loc.loc of
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             a_load_ref_reg(list,size,loc.reference,reg);
             a_load_ref_reg(list,size,loc.reference,reg);
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
             a_load_reg_reg(list,size,loc.register,reg);
             a_load_reg_reg(list,size,loc.register,reg);
+          LOC_CONSTANT:
+            a_load_const_reg(list,size,loc.value,reg);
           else
           else
             internalerror(200109092);
             internalerror(200109092);
         end;
         end;
       end;
       end;
 
 
+
+    procedure tcg.a_load_const_loc(list : taasmoutput;size : tcgsize;a : aword;const loc: tlocation);
+      begin
+        case loc.loc of
+          LOC_REFERENCE,LOC_CREFERENCE:
+            a_load_const_ref(list,size,a,loc.reference);
+          LOC_REGISTER,LOC_CREGISTER:
+            a_load_const_reg(list,size,a,loc.register);
+          else
+            internalerror(200203272);
+        end;
+      end;
+
+
+    procedure tcg.a_load_reg_loc(list : taasmoutput;size : tcgsize;reg : tregister;const loc: tlocation);
+      begin
+        case loc.loc of
+          LOC_REFERENCE,LOC_CREFERENCE:
+            a_load_reg_ref(list,size,reg,loc.reference);
+          LOC_REGISTER,LOC_CREGISTER:
+            a_load_reg_reg(list,size,reg,loc.register);
+          else
+            internalerror(200203271);
+        end;
+      end;
+
+
     procedure tcg.a_load_loc_ref(list : taasmoutput;size : tcgsize;const loc: tlocation; const ref : treference);
     procedure tcg.a_load_loc_ref(list : taasmoutput;size : tcgsize;const loc: tlocation; const ref : treference);
 
 
       var
       var
@@ -1093,7 +1148,7 @@ unit cgobj;
 
 
       begin
       begin
         case loc.loc of
         case loc.loc of
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             begin
             begin
 {$ifdef i386}
 {$ifdef i386}
               case size of
               case size of
@@ -1118,6 +1173,8 @@ unit cgobj;
             end;
             end;
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
             a_load_reg_ref(list,size,loc.register,ref);
             a_load_reg_ref(list,size,loc.register,ref);
+          LOC_CONSTANT:
+            a_load_const_ref(list,size,loc.value,ref);
           else
           else
             internalerror(200109302);
             internalerror(200109302);
         end;
         end;
@@ -1128,9 +1185,9 @@ unit cgobj;
 
 
       begin
       begin
         case loc.loc of
         case loc.loc of
-          LOC_REFERENCE, LOC_MEM:
+          LOC_REFERENCE, LOC_CREFERENCE:
             a_loadfpu_ref_reg(list,size,loc.reference,reg);
             a_loadfpu_ref_reg(list,size,loc.reference,reg);
-          LOC_FPU, LOC_CFPUREGISTER:
+          LOC_FPUREGISTER, LOC_CFPUREGISTER:
             a_loadfpu_reg_reg(list,loc.register,reg);
             a_loadfpu_reg_reg(list,loc.register,reg);
           else
           else
             internalerror(200203301);
             internalerror(200203301);
@@ -1142,9 +1199,9 @@ unit cgobj;
 
 
       begin
       begin
         case loc.loc of
         case loc.loc of
-          LOC_REFERENCE, LOC_MEM:
+          LOC_REFERENCE, LOC_CREFERENCE:
             a_loadfpu_reg_ref(list,size,reg,loc.reference);
             a_loadfpu_reg_ref(list,size,reg,loc.reference);
-          LOC_FPU, LOC_CFPUREGISTER:
+          LOC_FPUREGISTER, LOC_CFPUREGISTER:
             a_loadfpu_reg_reg(list,reg,loc.register);
             a_loadfpu_reg_reg(list,reg,loc.register);
           else
           else
             internalerror(48991);
             internalerror(48991);
@@ -1172,7 +1229,7 @@ unit cgobj;
         case loc.loc of
         case loc.loc of
           LOC_REGISTER, LOC_CREGISTER:
           LOC_REGISTER, LOC_CREGISTER:
             a_op_const_reg(list,op,a,loc.register);
             a_op_const_reg(list,op,a,loc.register);
-          LOC_REFERENCE, LOC_MEM:
+          LOC_REFERENCE, LOC_CREFERENCE:
             a_op_const_ref(list,op,size,a,loc.reference);
             a_op_const_ref(list,op,size,a,loc.reference);
           else
           else
             internalerror(200109061);
             internalerror(200109061);
@@ -1224,7 +1281,7 @@ unit cgobj;
         case loc.loc of
         case loc.loc of
           LOC_REGISTER, LOC_CREGISTER:
           LOC_REGISTER, LOC_CREGISTER:
             a_op_reg_reg(list,op,size,reg,loc.register);
             a_op_reg_reg(list,op,size,reg,loc.register);
-          LOC_REFERENCE, LOC_MEM:
+          LOC_REFERENCE, LOC_CREFERENCE:
             a_op_reg_ref(list,op,size,reg,loc.reference);
             a_op_reg_ref(list,op,size,reg,loc.reference);
           else
           else
             internalerror(200109061);
             internalerror(200109061);
@@ -1241,7 +1298,7 @@ unit cgobj;
         case loc.loc of
         case loc.loc of
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
             a_op_ref_reg(list,op,size,ref,loc.register);
             a_op_ref_reg(list,op,size,ref,loc.register);
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             begin
             begin
               tmpreg := get_scratch_reg(list);
               tmpreg := get_scratch_reg(list);
 {$ifdef i386}
 {$ifdef i386}
@@ -1292,7 +1349,7 @@ unit cgobj;
         case loc.loc of
         case loc.loc of
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
             a_cmp_const_reg_label(list,size,cmp_op,a,loc.register,l);
             a_cmp_const_reg_label(list,size,cmp_op,a,loc.register,l);
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             a_cmp_const_ref_label(list,size,cmp_op,a,loc.reference,l);
             a_cmp_const_ref_label(list,size,cmp_op,a,loc.reference,l);
           else
           else
             internalerror(200109061);
             internalerror(200109061);
@@ -1311,6 +1368,23 @@ unit cgobj;
         free_scratch_reg(list,tmpreg);
         free_scratch_reg(list,tmpreg);
       end;
       end;
 
 
+    procedure tcg.a_cmp_loc_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
+      begin
+        case loc.loc of
+          LOC_REGISTER,
+          LOC_CREGISTER:
+            a_cmp_reg_reg_label(list,size,cmp_op,loc.register,reg,l);
+          LOC_REFERENCE,
+          LOC_CREFERENCE :
+            a_cmp_ref_reg_label(list,size,cmp_op,loc.reference,reg,l);
+          LOC_CONSTANT:
+            a_cmp_const_reg_label(list,size,cmp_op,loc.value,reg,l);
+          else
+            internalerror(200203231);
+        end;
+      end;
+
+
     procedure tcg.a_cmp_ref_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference;const loc : tlocation;
     procedure tcg.a_cmp_ref_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference;const loc : tlocation;
       l : tasmlabel);
       l : tasmlabel);
 
 
@@ -1321,7 +1395,7 @@ unit cgobj;
         case loc.loc of
         case loc.loc of
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
             a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
             a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             begin
             begin
 {$ifdef i386}
 {$ifdef i386}
               { the following is done with defines to avoid a speed penalty,  }
               { the following is done with defines to avoid a speed penalty,  }
@@ -1356,6 +1430,12 @@ unit cgobj;
     { type used is checked against todefs ranges. fromdef (p.resulttype.def) }
     { type used is checked against todefs ranges. fromdef (p.resulttype.def) }
     { is the original type used at that location. When both defs are equal   }
     { is the original type used at that location. When both defs are equal   }
     { the check is also insert (needed for succ,pref,inc,dec)                }
     { the check is also insert (needed for succ,pref,inc,dec)                }
+      const
+{$ifdef ver1_0}
+        awordsignedmax=high(longint);
+{$else}
+        awordsignedmax=high(aword) div 2;
+{$endif}
       var
       var
         neglabel : tasmlabel;
         neglabel : tasmlabel;
         hreg : tregister;
         hreg : tregister;
@@ -1415,7 +1495,7 @@ unit cgobj;
               { if high(from) < 0 -> always range error }
               { if high(from) < 0 -> always range error }
               if (hfrom < 0) or
               if (hfrom < 0) or
                  { if low(to) > maxlongint also range error }
                  { if low(to) > maxlongint also range error }
-                 (lto > (high(aword) div 2)) then
+                 (lto > awordsignedmax) then
                 begin
                 begin
                   a_call_name(list,'FPC_RANGEERROR',0);
                   a_call_name(list,'FPC_RANGEERROR',0);
                   exit
                   exit
@@ -1423,13 +1503,13 @@ unit cgobj;
               { from is signed and to is unsigned -> when looking at from }
               { from is signed and to is unsigned -> when looking at from }
               { as an unsigned value, it must be < maxlongint (otherwise  }
               { as an unsigned value, it must be < maxlongint (otherwise  }
               { it's negative, which is invalid since "to" is unsigned)   }
               { it's negative, which is invalid since "to" is unsigned)   }
-              if hto > (high(aword) div 2) then
-                hto := (high(aword) div 2);
+              if hto > awordsignedmax then
+                hto := awordsignedmax;
             end
             end
           else
           else
             { from is unsigned, to is signed }
             { from is unsigned, to is signed }
             begin
             begin
-              if (lfrom > (high(aword) div 2)) or
+              if (lfrom > awordsignedmax) or
                  (hto < 0) then
                  (hto < 0) then
                 begin
                 begin
                   a_call_name(list,'FPC_RANGEERROR',0);
                   a_call_name(list,'FPC_RANGEERROR',0);
@@ -1445,15 +1525,15 @@ unit cgobj;
         hreg := get_scratch_reg(list);
         hreg := get_scratch_reg(list);
         if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
         if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
           a_op_const_reg_reg(list,OP_SUB,def_cgsize(p.resulttype.def),
           a_op_const_reg_reg(list,OP_SUB,def_cgsize(p.resulttype.def),
-           aword(lto),p.location.register,hreg)
+           aword(longint(lto and $ffffffff)),p.location.register,hreg)
         else
         else
           begin
           begin
             a_load_ref_reg(list,def_cgsize(p.resulttype.def),
             a_load_ref_reg(list,def_cgsize(p.resulttype.def),
               p.location.reference,hreg);
               p.location.reference,hreg);
-            a_op_const_reg(list,OP_SUB,aword(lto),hreg);
+            a_op_const_reg(list,OP_SUB,aword(longint(lto and $ffffffff)),hreg);
           end;
           end;
         getlabel(neglabel);
         getlabel(neglabel);
-        a_cmp_const_reg_label(list,OS_INT,OC_BE,aword(hto-lto),hreg,neglabel);
+        a_cmp_const_reg_label(list,OS_INT,OC_BE,aword(longint((hto-lto) and $ffffffff)),hreg,neglabel);
         { !!! should happen right after the compare (JM) }
         { !!! should happen right after the compare (JM) }
         free_scratch_reg(list,hreg);
         free_scratch_reg(list,hreg);
         a_call_name(list,'FPC_RANGEERROR',0);
         a_call_name(list,'FPC_RANGEERROR',0);
@@ -1473,7 +1553,18 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.8  2002-03-31 20:26:33  jonas
+  Revision 1.9  2002-04-02 17:11:27  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.8  2002/03/31 20:26:33  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)
@@ -1494,9 +1585,10 @@ end.
     * removed compiler warnings
     * removed compiler warnings
 
 
   Revision 1.6  2001/12/30 17:24:48  jonas
   Revision 1.6  2001/12/30 17:24:48  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)
+    * 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)
     * maketojumpbool() is now processor independent (in ncgutil)
     * getregister32 is now called getregisterint
     * getregister32 is now called getregisterint
 
 

+ 15 - 7
compiler/cutils.pas

@@ -26,9 +26,6 @@ unit cutils;
 
 
 interface
 interface
 
 
-uses
-  cpuinfo;
-
 {$ifdef delphi}
 {$ifdef delphi}
     type
     type
        dword = cardinal;
        dword = cardinal;
@@ -60,7 +57,7 @@ uses
     function tostr_with_plus(i : longint) : string;
     function tostr_with_plus(i : longint) : string;
     procedure valint(S : string;var V : longint;var code : integer);
     procedure valint(S : string;var V : longint;var code : integer);
     function is_number(const s : string) : boolean;
     function is_number(const s : string) : boolean;
-    function ispowerof2(value : TConstExprInt;var power : longint) : boolean;
+    function ispowerof2(value : int64;var power : longint) : boolean;
     function maybequoted(const s:string):string;
     function maybequoted(const s:string):string;
     function CompareText(S1, S2: string): longint;
     function CompareText(S1, S2: string): longint;
 
 
@@ -482,12 +479,12 @@ uses
       end;
       end;
 
 
 
 
-    function ispowerof2(value : TConstExprInt;var power : longint) : boolean;
+    function ispowerof2(value : int64;var power : longint) : boolean;
     {
     {
       return if value is a power of 2. And if correct return the power
       return if value is a power of 2. And if correct return the power
     }
     }
       var
       var
-         hl : TConstExprInt;
+         hl : int64;
          i : longint;
          i : longint;
       begin
       begin
          if value and (value - 1) <> 0 then
          if value and (value - 1) <> 0 then
@@ -750,7 +747,18 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.12  2001-11-18 18:43:13  peter
+  Revision 1.13  2002-04-02 17:11:28  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.12  2001/11/18 18:43:13  peter
     * overloading supported in child classes
     * overloading supported in child classes
     * fixed parsing of classes with private and virtual and overloaded
     * fixed parsing of classes with private and virtual and overloaded
       so it is compatible with delphi
       so it is compatible with delphi

+ 14 - 3
compiler/globals.pas

@@ -1443,8 +1443,8 @@ implementation
         not_unit_proc:=true;
         not_unit_proc:=true;
 
 
         apptype:=app_cui;
         apptype:=app_cui;
-	
-	have_local_threadvars := false;
+
+        have_local_threadvars := false;
      end;
      end;
 
 
 {$ifdef EXTDEBUG}
 {$ifdef EXTDEBUG}
@@ -1456,7 +1456,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.52  2002-03-28 16:07:52  armin
+  Revision 1.53  2002-04-02 17:11:28  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.52  2002/03/28 16:07:52  armin
   + initialize threadvars defined local in units
   + initialize threadvars defined local in units
 
 
   Revision 1.51  2002/01/24 18:25:48  peter
   Revision 1.51  2002/01/24 18:25:48  peter

+ 15 - 4
compiler/htypechk.pas

@@ -420,7 +420,7 @@ implementation
                 internalerror(200110101);
                 internalerror(200110101);
 
 
               if (abs(p.left.registers32-p.right.registers32)<r32) or
               if (abs(p.left.registers32-p.right.registers32)<r32) or
-                 ((p.location.loc = LOC_FPU) and
+                 ((p.location.loc = LOC_FPUREGISTER) and
                   (p.right.registersfpu <= p.left.registersfpu) and
                   (p.right.registersfpu <= p.left.registersfpu) and
                   ((p.right.registersfpu <> 0) or (p.left.registersfpu <> 0)) and
                   ((p.right.registersfpu <> 0) or (p.left.registersfpu <> 0)) and
                   (p.left.registers32   < p.right.registers32)) then
                   (p.left.registers32   < p.right.registers32)) then
@@ -440,8 +440,8 @@ implementation
               if (p.left.registers32=p.right.registers32) and
               if (p.left.registers32=p.right.registers32) and
                  (p.registers32=p.left.registers32) and
                  (p.registers32=p.left.registers32) and
                  (p.registers32>0) and
                  (p.registers32>0) and
-                (p.left.location.loc in [LOC_REFERENCE,LOC_MEM]) and
-                (p.right.location.loc in [LOC_REFERENCE,LOC_MEM]) then
+                (p.left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
+                (p.right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
                 inc(p.registers32);
                 inc(p.registers32);
             end
             end
            else
            else
@@ -938,7 +938,18 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.41  2002-01-16 09:33:46  jonas
+  Revision 1.42  2002-04-02 17:11:28  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.41  2002/01/16 09:33:46  jonas
     * no longer allow assignments to pointer expressions (unless there's a
     * no longer allow assignments to pointer expressions (unless there's a
       deref), reported by John Lee
       deref), reported by John Lee
 
 

+ 57 - 54
compiler/i386/ag386att.pas

@@ -132,60 +132,52 @@ interface
     var
     var
       s : string;
       s : string;
     begin
     begin
-      if ref.is_immediate then
+      with ref do
        begin
        begin
-         internalerror(1000101);
-         exit;
-       end
-      else
-       begin
-         with ref do
+         inc(offset,offsetfixup);
+         offsetfixup:=0;
+       { have we a segment prefix ? }
+       { These are probably not correctly handled under GAS }
+       { should be replaced by coding the segment override  }
+       { directly! - DJGPP FAQ                              }
+         if segment<>R_NO then
+          s:=att_reg2str[segment]+':'
+         else
+          s:='';
+         if assigned(symbol) then
+          s:=s+symbol.name;
+         if offset<0 then
+          s:=s+tostr(offset)
+         else
+          if (offset>0) then
+           begin
+             if assigned(symbol) then
+              s:=s+'+'+tostr(offset)
+             else
+              s:=s+tostr(offset);
+           end
+         else if (index=R_NO) and (base=R_NO) and not assigned(symbol) then
+           s:=s+'0';
+         if (index<>R_NO) and (base=R_NO) then
           begin
           begin
-            inc(offset,offsetfixup);
-            offsetfixup:=0;
-          { have we a segment prefix ? }
-          { These are probably not correctly handled under GAS }
-          { should be replaced by coding the segment override  }
-          { directly! - DJGPP FAQ                              }
-            if segment<>R_NO then
-             s:=att_reg2str[segment]+':'
+            s:=s+'(,'+att_reg2str[index];
+            if scalefactor<>0 then
+             s:=s+','+tostr(scalefactor)+')'
             else
             else
-             s:='';
-            if assigned(symbol) then
-             s:=s+symbol.name;
-            if offset<0 then
-             s:=s+tostr(offset)
-            else
-             if (offset>0) then
-              begin
-                if assigned(symbol) then
-                 s:=s+'+'+tostr(offset)
-                else
-                 s:=s+tostr(offset);
-              end
-            else if (index=R_NO) and (base=R_NO) and not assigned(symbol) then
-              s:=s+'0';
-            if (index<>R_NO) and (base=R_NO) then
-             begin
-               s:=s+'(,'+att_reg2str[index];
-               if scalefactor<>0 then
-                s:=s+','+tostr(scalefactor)+')'
-               else
-                s:=s+')';
-             end
-            else
-             if (index=R_NO) and (base<>R_NO) then
-              s:=s+'('+att_reg2str[base]+')'
-             else
-              if (index<>R_NO) and (base<>R_NO) then
-               begin
-                 s:=s+'('+att_reg2str[base]+','+att_reg2str[index];
-                 if scalefactor<>0 then
-                  s:=s+','+tostr(scalefactor)+')'
-                 else
-                  s := s+')';
-               end;
-          end;
+             s:=s+')';
+          end
+         else
+          if (index=R_NO) and (base<>R_NO) then
+           s:=s+'('+att_reg2str[base]+')'
+          else
+           if (index<>R_NO) and (base<>R_NO) then
+            begin
+              s:=s+'('+att_reg2str[base]+','+att_reg2str[index];
+              if scalefactor<>0 then
+               s:=s+','+tostr(scalefactor)+')'
+              else
+               s := s+')';
+            end;
        end;
        end;
       getreferencestring:=s;
       getreferencestring:=s;
     end;
     end;
@@ -200,7 +192,7 @@ interface
         top_ref :
         top_ref :
           getopstr:=getreferencestring(o.ref^);
           getopstr:=getreferencestring(o.ref^);
         top_const :
         top_const :
-          getopstr:='$'+tostr(o.val);
+          getopstr:='$'+tostr(longint(o.val));
         top_symbol :
         top_symbol :
           begin
           begin
             if assigned(o.sym) then
             if assigned(o.sym) then
@@ -232,7 +224,7 @@ interface
         top_ref :
         top_ref :
           getopstr_jmp:='*'+getreferencestring(o.ref^);
           getopstr_jmp:='*'+getreferencestring(o.ref^);
         top_const :
         top_const :
-          getopstr_jmp:=tostr(o.val);
+          getopstr_jmp:=tostr(longint(o.val));
         top_symbol :
         top_symbol :
           begin
           begin
             hs:=o.sym.name;
             hs:=o.sym.name;
@@ -949,7 +941,18 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.12  2001-12-29 15:29:58  jonas
+  Revision 1.13  2002-04-02 17:11:33  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.12  2001/12/29 15:29:58  jonas
     * powerpc/cgcpu.pas compiles :)
     * powerpc/cgcpu.pas compiles :)
     * several powerpc-related fixes
     * several powerpc-related fixes
     * cpuasm unit is now based on common tainst unit
     * cpuasm unit is now based on common tainst unit

+ 14 - 9
compiler/i386/ag386int.pas

@@ -119,12 +119,6 @@ interface
       s     : string;
       s     : string;
       first : boolean;
       first : boolean;
     begin
     begin
-      if ref.is_immediate then
-       begin
-         getreferencestring:=tostr(ref.offset);
-         exit;
-       end
-      else
       with ref do
       with ref do
         begin
         begin
           first:=true;
           first:=true;
@@ -179,7 +173,7 @@ interface
         top_reg :
         top_reg :
           getopstr:=int_reg2str[o.reg];
           getopstr:=int_reg2str[o.reg];
         top_const :
         top_const :
-          getopstr:=tostr(o.val);
+          getopstr:=tostr(longint(o.val));
         top_symbol :
         top_symbol :
           begin
           begin
             if assigned(o.sym) then
             if assigned(o.sym) then
@@ -242,7 +236,7 @@ interface
         top_reg :
         top_reg :
           getopstr_jmp:=int_reg2str[o.reg];
           getopstr_jmp:=int_reg2str[o.reg];
         top_const :
         top_const :
-          getopstr_jmp:=tostr(o.val);
+          getopstr_jmp:=tostr(longint(o.val));
         top_symbol :
         top_symbol :
           begin
           begin
             hs:=o.sym.name;
             hs:=o.sym.name;
@@ -828,7 +822,18 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.14  2001-06-18 20:36:25  peter
+  Revision 1.15  2002-04-02 17:11:33  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.14  2001/06/18 20:36:25  peter
     * -Ur switch (merged)
     * -Ur switch (merged)
     * masm fixes (merged)
     * masm fixes (merged)
     * quoted filenames for go32v2 and win32
     * quoted filenames for go32v2 and win32

+ 15 - 10
compiler/i386/ag386nsm.pas

@@ -144,12 +144,6 @@ interface
       s     : string;
       s     : string;
       first : boolean;
       first : boolean;
     begin
     begin
-      if ref.is_immediate then
-       begin
-         getreferencestring:=tostr(ref.offset);
-         exit;
-       end
-      else
       with ref do
       with ref do
         begin
         begin
           first:=true;
           first:=true;
@@ -233,9 +227,9 @@ interface
           top_const :
           top_const :
             begin
             begin
               if (ops=1) and (opcode<>A_RET) then
               if (ops=1) and (opcode<>A_RET) then
-               getopstr:=sizestr(s,dest)+tostr(o.val)
+               getopstr:=sizestr(s,dest)+tostr(longint(o.val))
               else
               else
-               getopstr:=tostr(o.val);
+               getopstr:=tostr(longint(o.val));
             end;
             end;
           top_symbol :
           top_symbol :
             begin
             begin
@@ -282,7 +276,7 @@ interface
           top_ref :
           top_ref :
             getopstr_jmp:=getreferencestring(o.ref^);
             getopstr_jmp:=getreferencestring(o.ref^);
           top_const :
           top_const :
-            getopstr_jmp:=tostr(o.val);
+            getopstr_jmp:=tostr(longint(o.val));
           top_symbol :
           top_symbol :
             begin
             begin
               hs:=o.sym.name;
               hs:=o.sym.name;
@@ -867,7 +861,18 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.12  2001-12-29 15:29:58  jonas
+  Revision 1.13  2002-04-02 17:11:33  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.12  2001/12/29 15:29:58  jonas
     * powerpc/cgcpu.pas compiles :)
     * powerpc/cgcpu.pas compiles :)
     * several powerpc-related fixes
     * several powerpc-related fixes
     * cpuasm unit is now based on common tainst unit
     * cpuasm unit is now based on common tainst unit

File diff ditekan karena terlalu besar
+ 128 - 390
compiler/i386/cga.pas


+ 238 - 99
compiler/i386/cgcpu.pas

@@ -27,7 +27,7 @@ unit cgcpu;
   interface
   interface
 
 
     uses
     uses
-       cgbase,cgobj,cg64f32,aasm,cpuasm,cpubase,cpuinfo,symconst;
+       cginfo,cgbase,cgobj,cg64f32,aasm,cpuasm,cpubase,cpuinfo,symconst;
 
 
     type
     type
       tcg386 = class(tcg64f32)
       tcg386 = class(tcg64f32)
@@ -97,7 +97,12 @@ unit cgcpu;
         procedure g_pop_exception_value_reg(list : taasmoutput;reg : tregister);override;
         procedure g_pop_exception_value_reg(list : taasmoutput;reg : tregister);override;
         procedure g_return_from_proc(list : taasmoutput;parasize : aword); override;
         procedure g_return_from_proc(list : taasmoutput;parasize : aword); override;
 
 
-        procedure a_loadaddress_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
+        procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : 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_const_reg(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;reglodst,reghidst : tregister);override;
+        procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;const ref : treference);override;
 
 
         procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
         procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
 
 
@@ -107,6 +112,7 @@ unit cgcpu;
 
 
        private
        private
 
 
+        procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
         procedure sizes2load(s1: tcgsize; s2: topsize; var op: tasmop; var s3: topsize);
         procedure sizes2load(s1: tcgsize; s2: topsize; var op: tasmop; var s3: topsize);
 
 
         procedure floatload(list: taasmoutput; t : tcgsize;const ref : treference);
         procedure floatload(list: taasmoutput; t : tcgsize;const ref : treference);
@@ -118,12 +124,12 @@ unit cgcpu;
 
 
     const
     const
 
 
-      TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_ADD,A_AND,A_DIV,
+      TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_ADD,A_AND,A_DIV,
                             A_IDIV,A_MUL, A_IMUL, A_NEG,A_NOT,A_OR,
                             A_IDIV,A_MUL, A_IMUL, A_NEG,A_NOT,A_OR,
                             A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
                             A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
 
 
-      TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,C_E,C_G,
-                           C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A);
+      TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
+          C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A);
 
 
       TCGSize2OpSize: Array[tcgsize] of topsize =
       TCGSize2OpSize: Array[tcgsize] of topsize =
         (S_NO,S_B,S_W,S_L,S_L,S_B,S_W,S_L,S_L,
         (S_NO,S_B,S_W,S_L,S_L,S_B,S_W,S_L,S_L,
@@ -141,16 +147,46 @@ unit cgcpu;
     { instantiate the class since it's abstract                      }
     { instantiate the class since it's abstract                      }
 
 
     procedure tcg386.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;nr : longint);
     procedure tcg386.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;nr : longint);
-
       begin
       begin
-        runerror(211);
+        case size of
+          OS_8,OS_S8 :
+            begin
+              if target_info.alignment.paraalign = 2 then
+                list.concat(taicpu.op_reg(A_PUSH,S_W,makereg16(r)))
+              else
+                list.concat(taicpu.op_reg(A_PUSH,S_L,makereg32(r)));
+            end;
+          OS_16,OS_S16:
+            begin
+              if target_info.alignment.paraalign = 2 then
+                list.concat(taicpu.op_reg(A_PUSH,S_W,r))
+              else
+                list.concat(taicpu.op_reg(A_PUSH,S_L,makereg32(r)));
+            end;
+          OS_32,OS_S32:
+            list.concat(taicpu.op_reg(A_PUSH,S_L,r));
+          else
+            internalerror(2002032212);
+        end;
       end;
       end;
 
 
 
 
     procedure tcg386.a_param_const(list : taasmoutput;size : tcgsize;a : aword;nr : longint);
     procedure tcg386.a_param_const(list : taasmoutput;size : tcgsize;a : aword;nr : longint);
 
 
       begin
       begin
-        runerror(211);
+        case size of
+          OS_8,OS_S8,OS_16,OS_S16:
+            begin
+              if target_info.alignment.paraalign = 2 then
+                list.concat(taicpu.op_const(A_PUSH,S_W,a))
+              else
+                list.concat(taicpu.op_const(A_PUSH,S_L,a));
+            end;
+          OS_32,OS_S32:
+            list.concat(taicpu.op_const(A_PUSH,S_L,a));
+          else
+            internalerror(2002032213);
+        end;
       end;
       end;
 
 
 
 
@@ -169,19 +205,39 @@ unit cgcpu;
                 list.concat(taicpu.op_reg(A_PUSH,S_W,makereg16(tmpreg)))
                 list.concat(taicpu.op_reg(A_PUSH,S_W,makereg16(tmpreg)))
               else
               else
                 list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
                 list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
+              free_scratch_reg(list,tmpreg);
             end;
             end;
           OS_32,OS_S32:
           OS_32,OS_S32:
-            list.concat(taicpu.op_ref(A_PUSH,S_L,newreference(r)));
+            list.concat(taicpu.op_ref(A_PUSH,S_L,r));
           else
           else
-            internalerror(200109301);
+            internalerror(2002032214);
         end;
         end;
       end;
       end;
 
 
 
 
     procedure tcg386.a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);
     procedure tcg386.a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);
 
 
+      var
+        tmpreg: tregister;
+
       begin
       begin
-        runerror(211);
+        if r.segment<>R_NO then
+          CGMessage(cg_e_cant_use_far_pointer_there);
+        if (r.base=R_NO) and (r.index=R_NO) then
+          list.concat(Taicpu.Op_sym_ofs(A_PUSH,S_L,r.symbol,r.offset))
+        else if (r.base=R_NO) and (r.index<>R_NO) and
+                (r.offset=0) and (r.scalefactor=0) and (r.symbol=nil) then
+          list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.index))
+        else if (r.base<>R_NO) and (r.index=R_NO) and
+                (r.offset=0) and (r.symbol=nil) then
+          list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.base))
+        else
+          begin
+            tmpreg := get_scratch_reg(list);
+            a_loadaddr_ref_reg(list,r,tmpreg);
+            list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
+            free_scratch_reg(list,tmpreg);
+          end;
       end;
       end;
 
 
     procedure tcg386.a_call_name(list : taasmoutput;const s : string;
     procedure tcg386.a_call_name(list : taasmoutput;const s : string;
@@ -201,13 +257,14 @@ unit cgcpu;
         { the optimizer will change it to "xor reg,reg" when loading zero, }
         { the optimizer will change it to "xor reg,reg" when loading zero, }
         { no need to do it here too (JM)                                   }
         { no need to do it here too (JM)                                   }
         list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[size],
         list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[size],
-          longint(a),reg))
+          a,reg))
       end;
       end;
 
 
 
 
     procedure tcg386.a_load_const_ref(list : taasmoutput; size: tcgsize; a : aword;const ref : treference);
     procedure tcg386.a_load_const_ref(list : taasmoutput; size: tcgsize; a : aword;const ref : treference);
 
 
       begin
       begin
+{$ifdef OPTLOAD0}
         { zero is often used several times in succession -> load it in a  }
         { zero is often used several times in succession -> load it in a  }
         { register and then store it to memory, so the optimizer can then }
         { register and then store it to memory, so the optimizer can then }
         { remove the unnecessary loads of registers and you get smaller   }
         { remove the unnecessary loads of registers and you get smaller   }
@@ -216,8 +273,9 @@ unit cgcpu;
            (size in [OS_32,OS_S32]) then
            (size in [OS_32,OS_S32]) then
           inherited a_load_const_ref(list,size,a,ref)
           inherited a_load_const_ref(list,size,a,ref)
         else
         else
+{$endif OPTLOAD0}
           list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[size],
           list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[size],
-            longint(a),newreference(ref)));
+            a,ref));
       end;
       end;
 
 
 
 
@@ -225,7 +283,7 @@ unit cgcpu;
 
 
       begin
       begin
         list.concat(taicpu.op_reg_ref(A_MOV,TCGSize2OpSize[size],reg,
         list.concat(taicpu.op_reg_ref(A_MOV,TCGSize2OpSize[size],reg,
-          newreference(ref)));
+          ref));
       End;
       End;
 
 
 
 
@@ -236,13 +294,8 @@ unit cgcpu;
         s: topsize;
         s: topsize;
 
 
       begin
       begin
-        if ref.is_immediate then
-          a_load_const_reg(list,size,aword(ref.offset),reg)
-        else
-          begin
-            sizes2load(size,regsize(reg),op,s);
-            list.concat(taicpu.op_ref_reg(op,s,newreference(ref),reg));
-          end;
+        sizes2load(size,regsize(reg),op,s);
+        list.concat(taicpu.op_ref_reg(op,s,ref,reg));
       end;
       end;
 
 
 
 
@@ -255,22 +308,27 @@ unit cgcpu;
       begin
       begin
         sizes2load(size,regsize(reg2),op,s);
         sizes2load(size,regsize(reg2),op,s);
         if (makereg32(reg1) = makereg32(reg2)) then
         if (makereg32(reg1) = makereg32(reg2)) then
-          { "mov reg1, reg1" doesn't make sense }
-          if op = A_MOV then
-            exit
-          else if (op = A_MOVZX) then
-            case size of
-              OS_8:
-                begin
-                  list.concat(taicpu.op_const_reg(A_AND,regsize(reg2),255,reg2));
-                  exit;
-                end;
-              OS_16:
-                begin
-                  list.concat(taicpu.op_const_reg(A_AND,S_L,65535,reg1));
-                  exit;
-                end;
+         begin
+           { "mov reg1, reg1" doesn't make sense }
+           if op = A_MOV then
+             exit;
+           { optimize movzx with "and ffff,<reg>" operation }
+           if (op = A_MOVZX) then
+            begin
+              case size of
+                OS_8:
+                  begin
+                    list.concat(taicpu.op_const_reg(A_AND,regsize(reg2),255,reg2));
+                    exit;
+                  end;
+                OS_16:
+                  begin
+                    list.concat(taicpu.op_const_reg(A_AND,regsize(reg2),65535,reg2));
+                    exit;
+                  end;
+              end;
             end;
             end;
+         end;
         list.concat(taicpu.op_reg_reg(op,s,reg1,reg2));
         list.concat(taicpu.op_reg_reg(op,s,reg1,reg2));
       end;
       end;
 
 
@@ -330,14 +388,14 @@ unit cgcpu;
     procedure tcg386.a_loadmm_ref_reg(list: taasmoutput; const ref: treference; reg: tregister);
     procedure tcg386.a_loadmm_ref_reg(list: taasmoutput; const ref: treference; reg: tregister);
 
 
        begin
        begin
-         list.concat(taicpu.op_ref_reg(A_MOVQ,S_NO,newreference(ref),reg));
+         list.concat(taicpu.op_ref_reg(A_MOVQ,S_NO,ref,reg));
        end;
        end;
 
 
 
 
     procedure tcg386.a_loadmm_reg_ref(list: taasmoutput; reg: tregister; const ref: treference);
     procedure tcg386.a_loadmm_reg_ref(list: taasmoutput; reg: tregister; const ref: treference);
 
 
        begin
        begin
-         list.concat(taicpu.op_reg_ref(A_MOVQ,S_NO,reg,newreference(ref)));
+         list.concat(taicpu.op_reg_ref(A_MOVQ,S_NO,reg,ref));
        end;
        end;
 
 
 
 
@@ -351,7 +409,7 @@ unit cgcpu;
         Case Op of
         Case Op of
           OP_DIV, OP_IDIV:
           OP_DIV, OP_IDIV:
             Begin
             Begin
-              if ispowerof2(longint(a),power) then
+              if ispowerof2(a,power) then
                 begin
                 begin
                   case op of
                   case op of
                     OP_DIV:
                     OP_DIV:
@@ -370,7 +428,7 @@ unit cgcpu;
           OP_MUL,OP_IMUL:
           OP_MUL,OP_IMUL:
             begin
             begin
               if not(cs_check_overflow in aktlocalswitches) and
               if not(cs_check_overflow in aktlocalswitches) and
-                 ispowerof2(longint(a),power) then
+                 ispowerof2(a,power) then
                 begin
                 begin
                   list.concat(taicpu.op_const_reg(A_SHL,regsize(reg),power,
                   list.concat(taicpu.op_const_reg(A_SHL,regsize(reg),power,
                     reg));
                     reg));
@@ -378,14 +436,15 @@ unit cgcpu;
                 end;
                 end;
               if op = OP_IMUL then
               if op = OP_IMUL then
                 list.concat(taicpu.op_const_reg(A_IMUL,regsize(reg),
                 list.concat(taicpu.op_const_reg(A_IMUL,regsize(reg),
-                  longint(a),reg))
+                  a,reg))
               else
               else
                 { OP_MUL should be handled specifically in the code        }
                 { OP_MUL should be handled specifically in the code        }
                 { generator because of the silly register usage restraints }
                 { generator because of the silly register usage restraints }
                 internalerror(200109225);
                 internalerror(200109225);
             end;
             end;
           OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
           OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
-            if (a = 1) and
+            if not(cs_check_overflow in aktlocalswitches) and
+               (a = 1) and
                (op in [OP_ADD,OP_SUB]) then
                (op in [OP_ADD,OP_SUB]) then
               if op = OP_ADD then
               if op = OP_ADD then
                 list.concat(taicpu.op_reg(A_INC,regsize(reg),reg))
                 list.concat(taicpu.op_reg(A_INC,regsize(reg),reg))
@@ -398,7 +457,7 @@ unit cgcpu;
                 list.concat(taicpu.op_const_reg(A_MOV,regsize(reg),0,reg))
                 list.concat(taicpu.op_const_reg(A_MOV,regsize(reg),0,reg))
             else
             else
               list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],regsize(reg),
               list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],regsize(reg),
-                longint(a),reg));
+                a,reg));
           OP_SHL,OP_SHR,OP_SAR:
           OP_SHL,OP_SHR,OP_SAR:
             begin
             begin
               if (a and 31) <> 0 Then
               if (a and 31) <> 0 Then
@@ -422,7 +481,7 @@ unit cgcpu;
         Case Op of
         Case Op of
           OP_DIV, OP_IDIV:
           OP_DIV, OP_IDIV:
             Begin
             Begin
-              if ispowerof2(longint(a),power) then
+              if ispowerof2(a,power) then
                 begin
                 begin
                   case op of
                   case op of
                     OP_DIV:
                     OP_DIV:
@@ -431,7 +490,7 @@ unit cgcpu;
                       opcode := A_SAR;
                       opcode := A_SAR;
                   end;
                   end;
                   list.concat(taicpu.op_const_ref(opcode,
                   list.concat(taicpu.op_const_ref(opcode,
-                    TCgSize2OpSize[size],power,newreference(ref)));
+                    TCgSize2OpSize[size],power,ref));
                   exit;
                   exit;
                 end;
                 end;
               { the rest should be handled specifically in the code      }
               { the rest should be handled specifically in the code      }
@@ -441,10 +500,10 @@ unit cgcpu;
           OP_MUL,OP_IMUL:
           OP_MUL,OP_IMUL:
             begin
             begin
               if not(cs_check_overflow in aktlocalswitches) and
               if not(cs_check_overflow in aktlocalswitches) and
-                 ispowerof2(longint(a),power) then
+                 ispowerof2(a,power) then
                 begin
                 begin
                   list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
                   list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
-                    power,newreference(ref)));
+                    power,ref));
                   exit;
                   exit;
                 end;
                 end;
               { can't multiply a memory location directly with a constant }
               { can't multiply a memory location directly with a constant }
@@ -456,14 +515,13 @@ unit cgcpu;
                 internalerror(200109232);
                 internalerror(200109232);
             end;
             end;
           OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
           OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
-            if (a = 1) and
+            if not(cs_check_overflow in aktlocalswitches) and
+               (a = 1) and
                (op in [OP_ADD,OP_SUB]) then
                (op in [OP_ADD,OP_SUB]) then
               if op = OP_ADD then
               if op = OP_ADD then
-                list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],
-                  newreference(ref)))
+                list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],ref))
               else
               else
-                list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],
-                  newreference(ref)))
+                list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],ref))
             else if (a = 0) then
             else if (a = 0) then
               if (op <> OP_AND) then
               if (op <> OP_AND) then
                 exit
                 exit
@@ -471,12 +529,12 @@ unit cgcpu;
                 a_load_const_ref(list,size,0,ref)
                 a_load_const_ref(list,size,0,ref)
             else
             else
               list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
               list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
-                TCgSize2OpSize[size],longint(a),newreference(ref)));
+                TCgSize2OpSize[size],a,ref));
           OP_SHL,OP_SHR,OP_SAR:
           OP_SHL,OP_SHR,OP_SAR:
             begin
             begin
               if (a and 31) <> 0 Then
               if (a and 31) <> 0 Then
                 list.concat(taicpu.op_const_ref(
                 list.concat(taicpu.op_const_ref(
-                  TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,newreference(ref)));
+                  TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,ref));
               if (a shr 5) <> 0 Then
               if (a shr 5) <> 0 Then
                 internalerror(68991);
                 internalerror(68991);
             end
             end
@@ -572,28 +630,22 @@ unit cgcpu;
          opsize: topsize;
          opsize: topsize;
 
 
        begin
        begin
-          if ref.is_immediate then
-            a_op_const_reg(list,op,aword(ref.offset),reg)
-          else
-            begin
-              case op of
-                OP_NEG,OP_NOT,OP_IMUL:
-                  begin
-                    inherited a_op_ref_reg(list,op,size,ref,reg);
-                  end;
-                OP_MUL,OP_DIV,OP_IDIV:
-                  { special stuff, needs separate handling inside code }
-                  { generator                                          }
-                  internalerror(200109239);
-                else
-                  begin
-                    opsize := makeregsize(reg,size);
-                    list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],opsize,
-                      newreference(ref),reg));
-                  end;
+          case op of
+            OP_NEG,OP_NOT,OP_IMUL:
+              begin
+                inherited a_op_ref_reg(list,op,size,ref,reg);
               end;
               end;
-            end;
-        end;
+            OP_MUL,OP_DIV,OP_IDIV:
+              { special stuff, needs separate handling inside code }
+              { generator                                          }
+              internalerror(200109239);
+            else
+              begin
+                opsize := makeregsize(reg,size);
+                list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],opsize,ref,reg));
+              end;
+          end;
+       end;
 
 
 
 
      procedure tcg386.a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
      procedure tcg386.a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
@@ -607,8 +659,7 @@ unit cgcpu;
              begin
              begin
                if reg <> R_NO then
                if reg <> R_NO then
                  internalerror(200109237);
                  internalerror(200109237);
-               list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],
-                 newreference(ref)));
+               list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref));
              end;
              end;
            OP_IMUL:
            OP_IMUL:
              begin
              begin
@@ -622,8 +673,7 @@ unit cgcpu;
            else
            else
              begin
              begin
                opsize := tcgsize2opsize[size];
                opsize := tcgsize2opsize[size];
-               list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],opsize,reg,
-                 newreference(ref)));
+               list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],opsize,reg,ref));
              end;
              end;
          end;
          end;
        end;
        end;
@@ -652,23 +702,22 @@ unit cgcpu;
           OP_IMUL:
           OP_IMUL:
             begin
             begin
               if not(cs_check_overflow in aktlocalswitches) and
               if not(cs_check_overflow in aktlocalswitches) and
-                 ispowerof2(longint(a),power) then
+                 ispowerof2(a,power) then
                 { can be done with a shift }
                 { can be done with a shift }
                 inherited a_op_const_reg_reg(list,op,size,a,src,dst);
                 inherited a_op_const_reg_reg(list,op,size,a,src,dst);
-              list.concat(taicpu.op_const_reg_reg(A_IMUL,S_L,longint(a),src,dst));
+              list.concat(taicpu.op_const_reg_reg(A_IMUL,S_L,a,src,dst));
             end;
             end;
           OP_ADD, OP_SUB:
           OP_ADD, OP_SUB:
             if (a = 0) then
             if (a = 0) then
               a_load_reg_reg(list,size,src,dst)
               a_load_reg_reg(list,size,src,dst)
             else
             else
               begin
               begin
-                reset_reference(tmpref);
+                reference_reset(tmpref);
                 tmpref.base := src;
                 tmpref.base := src;
                 tmpref.offset := longint(a);
                 tmpref.offset := longint(a);
                 if op = OP_SUB then
                 if op = OP_SUB then
                   tmpref.offset := -tmpref.offset;
                   tmpref.offset := -tmpref.offset;
-                list.concat(taicpu.op_ref_reg(A_LEA,S_L,newreference(tmpref),
-                  dst));
+                list.concat(taicpu.op_ref_reg(A_LEA,S_L,tmpref,dst));
               end
               end
           else internalerror(200112302);
           else internalerror(200112302);
         end;
         end;
@@ -698,12 +747,11 @@ unit cgcpu;
             list.concat(taicpu.op_reg_reg_reg(A_IMUL,S_L,src1,src2,dst));
             list.concat(taicpu.op_reg_reg_reg(A_IMUL,S_L,src1,src2,dst));
           OP_ADD:
           OP_ADD:
             begin
             begin
-              reset_reference(tmpref);
+              reference_reset(tmpref);
               tmpref.base := src1;
               tmpref.base := src1;
               tmpref.index := src2;
               tmpref.index := src2;
               tmpref.scalefactor := 1;
               tmpref.scalefactor := 1;
-              list.concat(taicpu.op_ref_reg(A_LEA,S_L,newreference(tmpref),
-                dst));
+              list.concat(taicpu.op_ref_reg(A_LEA,S_L,tmpref,dst));
             end
             end
           else internalerror(200112303);
           else internalerror(200112303);
         end;
         end;
@@ -715,11 +763,11 @@ unit cgcpu;
         l : tasmlabel);
         l : tasmlabel);
 
 
         begin
         begin
-          if a <> 0 then
-            list.concat(taicpu.op_const_reg(A_CMP,regsize(reg),longint(a),
-              reg))
+          if (a = 0) and
+             (cmp_op in [OC_EQ,OC_NE]) then
+            list.concat(taicpu.op_reg_reg(A_TEST,regsize(reg),reg,reg))
           else
           else
-            list.concat(taicpu.op_reg_reg(A_TEST,regsize(reg),reg,reg));
+            list.concat(taicpu.op_const_reg(A_CMP,regsize(reg),a,reg));
           a_jmp_cond(list,cmp_op,l);
           a_jmp_cond(list,cmp_op,l);
         end;
         end;
 
 
@@ -727,8 +775,7 @@ unit cgcpu;
         l : tasmlabel);
         l : tasmlabel);
 
 
         begin
         begin
-          list.concat(taicpu.op_const_ref(A_CMP,TCgSize2OpSize[size],
-            longint(a),newreference(ref)));
+          list.concat(taicpu.op_const_ref(A_CMP,TCgSize2OpSize[size],a,ref));
           a_jmp_cond(list,cmp_op,l);
           a_jmp_cond(list,cmp_op,l);
         end;
         end;
 
 
@@ -749,7 +796,7 @@ unit cgcpu;
 
 
         begin
         begin
           opsize := makeregsize(reg,size);
           opsize := makeregsize(reg,size);
-          list.concat(taicpu.op_ref_reg(A_CMP,opsize,newreference(ref),reg));
+          list.concat(taicpu.op_ref_reg(A_CMP,opsize,ref,reg));
           a_jmp_cond(list,cmp_op,l);
           a_jmp_cond(list,cmp_op,l);
         end;
         end;
 
 
@@ -843,10 +890,10 @@ unit cgcpu;
         runerror(211);
         runerror(211);
       end;
       end;
 
 
-     procedure tcg386.a_loadaddress_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
+     procedure tcg386.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
 
 
        begin
        begin
-         list.concat(taicpu.op_ref_reg(A_LEA,S_L,newreference(ref),r));
+         list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,r));
        end;
        end;
 
 
     function tcg386.makeregsize(var reg: tregister; size: tcgsize): topsize;
     function tcg386.makeregsize(var reg: tregister; size: tcgsize): topsize;
@@ -879,6 +926,87 @@ unit cgcpu;
       end;
       end;
 
 
 
 
+{ ************* 64bit operations ************ }
+
+    procedure tcg386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
+      begin
+        case op of
+          OP_ADD :
+            begin
+              op1:=A_ADD;
+              op2:=A_ADC;
+            end;
+          OP_SUB :
+            begin
+              op1:=A_SUB;
+              op2:=A_SBB;
+            end;
+          OP_XOR :
+            begin
+              op1:=A_XOR;
+              op2:=A_XOR;
+            end;
+          OP_OR :
+            begin
+              op1:=A_OR;
+              op2:=A_OR;
+            end;
+          OP_AND :
+            begin
+              op1:=A_AND;
+              op2:=A_AND;
+            end;
+          else
+            internalerror(200203241);
+        end;
+      end;
+
+
+    procedure tcg386.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reglo,reghi : tregister);
+      var
+        op1,op2 : TAsmOp;
+        tempref : treference;
+      begin
+        get_64bit_ops(op,op1,op2);
+        list.concat(taicpu.op_ref_reg(op1,S_L,ref,reglo));
+        tempref:=ref;
+        inc(tempref.offset,4);
+        list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reghi));
+      end;
+
+
+    procedure tcg386.a_op64_reg_reg(list : taasmoutput;op:TOpCG;reglosrc,reghisrc,reglodst,reghidst : tregister);
+      var
+        op1,op2 : TAsmOp;
+      begin
+        get_64bit_ops(op,op1,op2);
+        list.concat(taicpu.op_reg_reg(op1,S_L,reglosrc,reglodst));
+        list.concat(taicpu.op_reg_reg(op2,S_L,reghisrc,reghidst));
+      end;
+
+
+    procedure tcg386.a_op64_const_reg(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;reglodst,reghidst : tregister);
+      var
+        op1,op2 : TAsmOp;
+      begin
+        get_64bit_ops(op,op1,op2);
+        list.concat(taicpu.op_const_reg(op1,S_L,valuelosrc,reglodst));
+        list.concat(taicpu.op_const_reg(op2,S_L,valuehisrc,reghidst));
+      end;
+
+
+    procedure tcg386.a_op64_const_ref(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;const ref : treference);
+      var
+        op1,op2 : TAsmOp;
+        tempref : treference;
+      begin
+        get_64bit_ops(op,op1,op2);
+        list.concat(taicpu.op_const_ref(op1,S_L,valuelosrc,ref));
+        tempref:=ref;
+        inc(tempref.offset,4);
+        list.concat(taicpu.op_const_ref(op2,S_L,valuehisrc,tempref));
+      end;
+
 
 
 { ************* concatcopy ************ }
 { ************* concatcopy ************ }
 
 
@@ -982,7 +1110,7 @@ unit cgcpu;
 
 
       begin
       begin
          floatloadops(t,op,s);
          floatloadops(t,op,s);
-         list.concat(Taicpu.Op_ref(op,s,newreference(ref)));
+         list.concat(Taicpu.Op_ref(op,s,ref));
          inc(trgcpu(rg).fpuvaroffset);
          inc(trgcpu(rg).fpuvaroffset);
       end;
       end;
 
 
@@ -1021,7 +1149,7 @@ unit cgcpu;
 
 
       begin
       begin
          floatstoreops(t,op,s);
          floatstoreops(t,op,s);
-         list.concat(Taicpu.Op_ref(op,s,newreference(ref)));
+         list.concat(Taicpu.Op_ref(op,s,ref));
          dec(trgcpu(rg).fpuvaroffset);
          dec(trgcpu(rg).fpuvaroffset);
       end;
       end;
 
 
@@ -1031,7 +1159,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.8  2002-03-31 20:26:37  jonas
+  Revision 1.9  2002-04-02 17:11:33  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.8  2002/03/31 20:26:37  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 43 - 32
compiler/i386/cpuasm.pas

@@ -42,7 +42,7 @@ interface
 uses
 uses
   cclasses,tainst,
   cclasses,tainst,
   aasm,globals,verbose,
   aasm,globals,verbose,
-  cpubase;
+  cpuinfo,cpubase;
 
 
 const
 const
   MaxPrefixes=4;
   MaxPrefixes=4;
@@ -63,26 +63,26 @@ type
      constructor op_none(op : tasmop;_size : topsize);
      constructor op_none(op : tasmop;_size : topsize);
 
 
      constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
      constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
-     constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
-     constructor op_ref(op : tasmop;_size : topsize;_op1 : preference);
+     constructor op_const(op : tasmop;_size : topsize;_op1 : aword);
+     constructor op_ref(op : tasmop;_size : topsize;const _op1 : treference);
 
 
      constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
      constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
-     constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : preference);
-     constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
+     constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
+     constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aword);
 
 
-     constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
-     constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
-     constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference);
+     constructor op_const_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister);
+     constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aword);
+     constructor op_const_ref(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference);
 
 
-     constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : preference;_op2 : tregister);
+     constructor op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
      { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
      { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
-     constructor op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : preference);
+     constructor op_ref_ref(op : tasmop;_size : topsize;const _op1,_op2 : treference);
 
 
      constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
      constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
-     constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
-     constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference;_op3 : tregister);
-     constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : preference);
-     constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : preference);
+     constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;_op3 : tregister);
+     constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference;_op3 : tregister);
+     constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; const _op3 : treference);
+     constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;const _op3 : treference);
 
 
      { this is for Jmp instructions }
      { this is for Jmp instructions }
      constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
      constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
@@ -90,7 +90,7 @@ type
      constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
      constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
      constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
      constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
      constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
      constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
-     constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
+     constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
 
 
      procedure changeopsize(siz:topsize);
      procedure changeopsize(siz:topsize);
 
 
@@ -222,7 +222,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
+    constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aword);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -231,7 +231,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : preference);
+    constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -250,7 +250,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
+    constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aword);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -260,7 +260,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : preference);
+    constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -270,7 +270,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+    constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -280,7 +280,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
+    constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aword);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -290,7 +290,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference);
+    constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -300,7 +300,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : preference;_op2 : tregister);
+    constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -310,7 +310,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : preference);
+    constructor taicpu.op_ref_ref(op : tasmop;_size : topsize;const _op1,_op2 : treference);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -330,7 +330,7 @@ uses
          loadreg(2,_op3);
          loadreg(2,_op3);
       end;
       end;
 
 
-    constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
+    constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;_op3 : tregister);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -340,7 +340,7 @@ uses
          loadreg(2,_op3);
          loadreg(2,_op3);
       end;
       end;
 
 
-    constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;_op3 : preference);
+    constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -351,7 +351,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference;_op3 : tregister);
+    constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aword;const _op2 : treference;_op3 : tregister);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -362,7 +362,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : preference);
+    constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aword;_op2 : tregister;const _op3 : treference);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -411,7 +411,7 @@ uses
       end;
       end;
 
 
 
 
-    constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
+    constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
       begin
       begin
          inherited create(op);
          inherited create(op);
          init(_size);
          init(_size);
@@ -611,7 +611,7 @@ begin
           end;
           end;
         top_const :
         top_const :
           begin
           begin
-            if (opsize<>S_W) and (val>=-128) and (val<=127) then
+            if (opsize<>S_W) and (longint(val)>=-128) and (val<=127) then
               ot:=OT_IMM8 or OT_SIGNED
               ot:=OT_IMM8 or OT_SIGNED
             else
             else
               ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
               ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
@@ -1289,7 +1289,7 @@ var
         end;
         end;
       top_const :
       top_const :
         begin
         begin
-          currval:=oper[opidx].val;
+          currval:=longint(oper[opidx].val);
           currsym:=nil;
           currsym:=nil;
         end;
         end;
       top_symbol :
       top_symbol :
@@ -1593,7 +1593,18 @@ end;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.17  2001-12-31 16:59:43  peter
+  Revision 1.18  2002-04-02 17:11:33  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.17  2001/12/31 16:59:43  peter
     * protected/private symbols parsing fixed
     * protected/private symbols parsing fixed
 
 
   Revision 1.16  2001/12/29 15:29:59  jonas
   Revision 1.16  2001/12/29 15:29:59  jonas

+ 88 - 138
compiler/i386/cpubase.pas

@@ -31,7 +31,7 @@ unit cpubase;
 interface
 interface
 
 
 uses
 uses
-  globals,cutils,cclasses,aasm;
+  globals,cutils,cclasses,aasm,cpuinfo,cginfo;
 
 
 const
 const
 { Size of the instruction table converted by nasmconv.pas }
 { Size of the instruction table converted by nasmconv.pas }
@@ -429,9 +429,8 @@ type
   trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
   trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
 
 
   { immediate/reference record }
   { immediate/reference record }
-  preference = ^treference;
+  poperreference = ^treference;
   treference = packed record
   treference = packed record
-     is_immediate : boolean; { is this used as reference or immediate }
      segment,
      segment,
      base,
      base,
      index       : tregister;
      index       : tregister;
@@ -457,8 +456,8 @@ type
           case typ : toptype of
           case typ : toptype of
            top_none   : ();
            top_none   : ();
            top_reg    : (reg:tregister);
            top_reg    : (reg:tregister);
-           top_ref    : (ref:preference);
-           top_const  : (val:longint);
+           top_ref    : (ref:poperreference);
+           top_const  : (val:aword);
            top_symbol : (sym:tasmsymbol;symofs:longint);
            top_symbol : (sym:tasmsymbol;symofs:longint);
         end;
         end;
 
 
@@ -487,38 +486,43 @@ type
 type
 type
   TLoc=(
   TLoc=(
     LOC_INVALID,      { added for tracking problems}
     LOC_INVALID,      { added for tracking problems}
-    LOC_FPU,          { FPU stack }
-    LOC_REGISTER,     { in a processor register }
-    LOC_MEM,          { in memory }
-    LOC_REFERENCE,    { like LOC_MEM, but lvalue }
+    LOC_CONSTANT,     { constant value }
     LOC_JUMP,         { boolean results only, jump to false or true label }
     LOC_JUMP,         { boolean results only, jump to false or true label }
     LOC_FLAGS,        { boolean results only, flags are set }
     LOC_FLAGS,        { boolean results only, flags are set }
+    LOC_CREFERENCE,   { in memory constant value }
+    LOC_REFERENCE,    { in memory value }
+    LOC_REGISTER,     { in a processor register }
     LOC_CREGISTER,    { Constant register which shouldn't be modified }
     LOC_CREGISTER,    { Constant register which shouldn't be modified }
+    LOC_FPUREGISTER,  { FPU stack }
+    LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
     LOC_MMXREGISTER,  { MMX register }
     LOC_MMXREGISTER,  { MMX register }
     LOC_CMMXREGISTER, { MMX register variable }
     LOC_CMMXREGISTER, { MMX register variable }
-    LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
     LOC_SSEREGISTER,
     LOC_SSEREGISTER,
     LOC_CSSEREGISTER
     LOC_CSSEREGISTER
   );
   );
 
 
   plocation = ^tlocation;
   plocation = ^tlocation;
   tlocation = packed record
   tlocation = packed record
-     case loc : tloc of
-        LOC_MEM,LOC_REFERENCE : (reference : treference);
-        LOC_FPU : ();
-        LOC_JUMP : ();
+     loc  : TLoc;
+     size : TCGSize;
+     case TLoc of
         LOC_FLAGS : (resflags : tresflags);
         LOC_FLAGS : (resflags : tresflags);
-        LOC_INVALID : ();
-
-        { it's only for better handling }
-        LOC_MMXREGISTER : (mmxreg : tregister);
+        LOC_CONSTANT : (
+          case longint of
+            1 : (value : AWord);
+            2 : (valuelow, valuehigh:AWord);
+          );
+        LOC_CREFERENCE,
+        LOC_REFERENCE : (reference : treference);
         { segment in reference at the same place as in loc_register }
         { segment in reference at the same place as in loc_register }
         LOC_REGISTER,LOC_CREGISTER : (
         LOC_REGISTER,LOC_CREGISTER : (
-        case longint of
-          1 : (register,segment,registerhigh : tregister);
-          { overlay a registerlow }
-          2 : (registerlow : tregister);
-        );
+          case longint of
+            1 : (register,segment,registerhigh : tregister);
+            { overlay a registerlow }
+            2 : (registerlow : tregister);
+          );
+        { it's only for better handling }
+        LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
   end;
   end;
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -718,31 +722,21 @@ const
     { returns the operand prefix for a given register }
     { returns the operand prefix for a given register }
     function regsize(reg : tregister) : topsize;
     function regsize(reg : tregister) : topsize;
 
 
-    { resets all values of ref to defaults }
-    procedure reset_reference(var ref : treference);
-    { set mostly used values of a new reference }
-    function new_reference(base : tregister;offset : longint) : preference;
-
-    function newreference(const r : treference) : preference;
-    procedure disposereference(var r : preference);
-
     function reg2str(r : tregister) : string;
     function reg2str(r : tregister) : string;
 
 
     function is_calljmp(o:tasmop):boolean;
     function is_calljmp(o:tasmop):boolean;
 
 
-    procedure clear_location(var loc : tlocation);
-    procedure set_location(var destloc,sourceloc : tlocation);
-    procedure swap_location(var destloc,sourceloc : tlocation);
-
     procedure inverse_flags(var f: TResFlags);
     procedure inverse_flags(var f: TResFlags);
     function flags_to_cond(const f: TResFlags) : TAsmCond;
     function flags_to_cond(const f: TResFlags) : TAsmCond;
 
 
+
 implementation
 implementation
 
 
-{$ifdef heaptrc}
   uses
   uses
-      ppheap;
+{$ifdef heaptrc}
+      ppheap,
 {$endif heaptrc}
 {$endif heaptrc}
+      verbose;
 
 
 {*****************************************************************************
 {*****************************************************************************
                                   Helpers
                                   Helpers
@@ -799,23 +793,6 @@ implementation
       end;
       end;
 
 
 
 
-    procedure disposereference(var r : preference);
-      begin
-         dispose(r);
-         r:=nil;
-      end;
-
-
-    function newreference(const r : treference) : preference;
-      var
-         p : preference;
-      begin
-         new(p);
-         p^:=r;
-         newreference:=p;
-      end;
-
-
     function reg8toreg16(reg : tregister) : tregister;
     function reg8toreg16(reg : tregister) : tregister;
 
 
       begin
       begin
@@ -877,56 +854,35 @@ implementation
         regtoreg64:=R_NO;
         regtoreg64:=R_NO;
      end;
      end;
 
 
-function regsize(reg : tregister) : topsize;
-begin
-   if reg in regset8bit then
-     regsize:=S_B
-   else if reg in regset16bit then
-     regsize:=S_W
-   else if reg in regset32bit then
-     regsize:=S_L;
-end;
-
-
-procedure reset_reference(var ref : treference);
-begin
-  FillChar(ref,sizeof(treference),0);
-end;
-
-
-function new_reference(base : tregister;offset : longint) : preference;
-var
-  r : preference;
-begin
-  new(r);
-  FillChar(r^,sizeof(treference),0);
-  r^.base:=base;
-  r^.offset:=offset;
-  new_reference:=r;
-end;
-
-    procedure clear_location(var loc : tlocation);
-
+    function regsize(reg : tregister) : topsize;
       begin
       begin
-        loc.loc:=LOC_INVALID;
+         if reg in regset8bit then
+           regsize:=S_B
+         else if reg in regset16bit then
+           regsize:=S_W
+         else if reg in regset32bit then
+           regsize:=S_L
+         else
+           internalerror(200203261);
       end;
       end;
 
 
-    {This is needed if you want to be able to delete the string with the nodes !!}
-    procedure set_location(var destloc,sourceloc : tlocation);
 
 
+    procedure inverse_flags(var f: TResFlags);
+      const
+         flagsinvers : array[F_E..F_BE] of tresflags =
+            (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_NC,F_C,
+             F_BE,F_B,F_AE,F_A);
       begin
       begin
-        destloc:= sourceloc;
+        f := flagsinvers[f];
       end;
       end;
 
 
-    procedure swap_location(var destloc,sourceloc : tlocation);
-
-      var
-         swapl : tlocation;
 
 
+    function flags_to_cond(const f: TResFlags) : TAsmCond;
+      const
+        flags_2_cond : array[TResFlags] of TAsmCond =
+          (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
       begin
       begin
-         swapl := destloc;
-         destloc := sourceloc;
-         sourceloc := swapl;
+        result := flags_2_cond[f];
       end;
       end;
 
 
 
 
@@ -934,64 +890,58 @@ end;
                               Instruction table
                               Instruction table
 *****************************************************************************}
 *****************************************************************************}
 
 
-procedure DoneCpu;
-begin
-  {exitproc:=saveexit; }
+    procedure BuildInsTabCache;
 {$ifndef NOAG386BIN}
 {$ifndef NOAG386BIN}
-  if assigned(instabcache) then
-    dispose(instabcache);
-{$endif NOAG386BIN}
-end;
-
-
-procedure BuildInsTabCache;
-{$ifndef NOAG386BIN}
-var
-  i : longint;
+      var
+        i : longint;
 {$endif}
 {$endif}
-begin
+      begin
 {$ifndef NOAG386BIN}
 {$ifndef NOAG386BIN}
-  new(instabcache);
-  FillChar(instabcache^,sizeof(tinstabcache),$ff);
-  i:=0;
-  while (i<InsTabEntries) do
-   begin
-     if InsTabCache^[InsTab[i].OPcode]=-1 then
-      InsTabCache^[InsTab[i].OPcode]:=i;
-     inc(i);
-   end;
+        new(instabcache);
+        FillChar(instabcache^,sizeof(tinstabcache),$ff);
+        i:=0;
+        while (i<InsTabEntries) do
+         begin
+           if InsTabCache^[InsTab[i].OPcode]=-1 then
+            InsTabCache^[InsTab[i].OPcode]:=i;
+           inc(i);
+         end;
 {$endif NOAG386BIN}
 {$endif NOAG386BIN}
-end;
-
-    procedure inverse_flags(var f: TResFlags);
-      const
-         flagsinvers : array[F_E..F_BE] of tresflags =
-            (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_NC,F_C,
-             F_BE,F_B,F_AE,F_A);
-      begin
-        f := flagsinvers[f];
       end;
       end;
 
 
-    function flags_to_cond(const f: TResFlags) : TAsmCond;
-      const
-        flags_2_cond : array[TResFlags] of TAsmCond =
-          (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
+
+    procedure InitCpu;
       begin
       begin
-        result := flags_2_cond[f];
+{$ifndef NOAG386BIN}
+        if not assigned(instabcache) then
+          BuildInsTabCache;
+{$endif NOAG386BIN}
       end;
       end;
 
 
-procedure InitCpu;
-begin
+
+    procedure DoneCpu;
+      begin
 {$ifndef NOAG386BIN}
 {$ifndef NOAG386BIN}
-  if not assigned(instabcache) then
-    BuildInsTabCache;
+        if assigned(instabcache) then
+         dispose(instabcache);
 {$endif NOAG386BIN}
 {$endif NOAG386BIN}
-end;
+      end;
 
 
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.11  2002-03-31 20:26:37  jonas
+  Revision 1.12  2002-04-02 17:11:34  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.11  2002/03/31 20:26:37  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 13 - 1
compiler/i386/cpuinfo.pas

@@ -28,6 +28,7 @@ Interface
 
 
 Type
 Type
    AWord = Cardinal;
    AWord = Cardinal;
+   PAWord = ^AWord;
 
 
    { the ordinal type used when evaluating constant integer expressions }
    { the ordinal type used when evaluating constant integer expressions }
    TConstExprInt = int64;
    TConstExprInt = int64;
@@ -50,7 +51,18 @@ Implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.4  2001-09-02 21:18:29  peter
+  Revision 1.5  2002-04-02 17:11:34  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.4  2001/09/02 21:18:29  peter
     * split constsym.value in valueord,valueordptr,valueptr. The valueordptr
     * split constsym.value in valueord,valueordptr,valueptr. The valueordptr
       is used for holding target platform pointer values. As those can be
       is used for holding target platform pointer values. As those can be
       bigger than the source platform.
       bigger than the source platform.

+ 18 - 7
compiler/i386/csopt386.pas

@@ -27,7 +27,7 @@ Unit CSOpt386;
 
 
 Interface
 Interface
 
 
-Uses aasm, cpubase, cpuasm;
+Uses aasm, cpuinfo, cpubase, cpuasm;
 
 
 function CSE(asmL: TAAsmoutput; first, last: Tai; pass: longint): boolean;
 function CSE(asmL: TAAsmoutput; first, last: Tai; pass: longint): boolean;
 
 
@@ -1263,7 +1263,7 @@ begin
 {$endif replaceregdebug}
 {$endif replaceregdebug}
 End;
 End;
 
 
-Function FindRegWithConst(p: Tai; size: topsize; l: longint; Var Res: TRegister): Boolean;
+Function FindRegWithConst(p: Tai; size: topsize; l: aword; Var Res: TRegister): Boolean;
 {Finds a register which contains the constant l}
 {Finds a register which contains the constant l}
 Var Counter: TRegister;
 Var Counter: TRegister;
 {$ifdef testing}
 {$ifdef testing}
@@ -1394,9 +1394,9 @@ begin
 end;
 end;
 
 
 procedure removeLocalStores(const t1: tai);
 procedure removeLocalStores(const t1: tai);
-var
+{var
   p: tai;
   p: tai;
-  regcount: tregister;
+  regcount: tregister; }
 begin
 begin
 {
 {
   for regcount := LoGPReg to HiGPReg do
   for regcount := LoGPReg to HiGPReg do
@@ -1812,7 +1812,7 @@ Begin
                                   insertllitem(asml,p,p.next,hp1);
                                   insertllitem(asml,p,p.next,hp1);
                                   hp1 := taicpu.op_reg_ref(A_MOV,
                                   hp1 := taicpu.op_reg_ref(A_MOV,
                                     regsize(regcounter),regcounter,
                                     regsize(regcounter),regcounter,
-                                    newreference(taicpu(p).oper[0].ref^));
+                                    taicpu(p).oper[0].ref^);
                                   new(pTaiprop(hp1.optinfo));
                                   new(pTaiprop(hp1.optinfo));
                                   pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
                                   pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
                                   insertllitem(asml,p,p.next,hp1);
                                   insertllitem(asml,p,p.next,hp1);
@@ -1865,7 +1865,7 @@ Begin
                                   insertllitem(asml,p,p.next,hp1);
                                   insertllitem(asml,p,p.next,hp1);
                                   hp1 := taicpu.op_reg_ref(A_MOV,
                                   hp1 := taicpu.op_reg_ref(A_MOV,
                                     regsize(regcounter),regcounter,
                                     regsize(regcounter),regcounter,
-                                    newreference(taicpu(p).oper[1].ref^));
+                                    taicpu(p).oper[1].ref^);
                                   new(pTaiprop(hp1.optinfo));
                                   new(pTaiprop(hp1.optinfo));
                                   pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
                                   pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
                                   insertllitem(asml,p,p.next,hp1);
                                   insertllitem(asml,p,p.next,hp1);
@@ -1981,7 +1981,18 @@ End.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.25  2002-03-31 20:26:38  jonas
+  Revision 1.26  2002-04-02 17:11:34  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.25  2002/03/31 20:26:38  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 22 - 17
compiler/i386/daopt386.pas

@@ -739,26 +739,20 @@ End;
 
 
 Function RefsEquivalent(Const R1, R2: TReference; var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
 Function RefsEquivalent(Const R1, R2: TReference; var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
 Begin
 Begin
-  If R1.is_immediate Then
-    RefsEquivalent := R2.is_immediate and (R1.Offset = R2.Offset)
-  Else
-    RefsEquivalent := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
-                      RegsEquivalent(R1.Base, R2.Base, RegInfo, OpAct) And
-                      RegsEquivalent(R1.Index, R2.Index, RegInfo, OpAct) And
-                      (R1.Segment = R2.Segment) And (R1.ScaleFactor = R2.ScaleFactor) And
-                      (R1.Symbol = R2.Symbol);
+  RefsEquivalent := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
+                    RegsEquivalent(R1.Base, R2.Base, RegInfo, OpAct) And
+                    RegsEquivalent(R1.Index, R2.Index, RegInfo, OpAct) And
+                    (R1.Segment = R2.Segment) And (R1.ScaleFactor = R2.ScaleFactor) And
+                    (R1.Symbol = R2.Symbol);
 End;
 End;
 
 
 
 
 Function RefsEqual(Const R1, R2: TReference): Boolean;
 Function RefsEqual(Const R1, R2: TReference): Boolean;
 Begin
 Begin
-  If R1.is_immediate Then
-    RefsEqual := R2.is_immediate and (R1.Offset = R2.Offset)
-  Else
-    RefsEqual := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
-                 (R1.Segment = R2.Segment) And (R1.Base = R2.Base) And
-                 (R1.Index = R2.Index) And (R1.ScaleFactor = R2.ScaleFactor) And
-                 (R1.Symbol=R2.Symbol);
+  RefsEqual := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
+               (R1.Segment = R2.Segment) And (R1.Base = R2.Base) And
+               (R1.Index = R2.Index) And (R1.ScaleFactor = R2.ScaleFactor) And
+               (R1.Symbol=R2.Symbol);
 End;
 End;
 
 
 Function IsGP32Reg(Reg: TRegister): Boolean;
 Function IsGP32Reg(Reg: TRegister): Boolean;
@@ -1617,7 +1611,7 @@ Begin
 End;
 End;
 
 
 
 
-Procedure ReadRef(p: PTaiProp; Ref: PReference);
+Procedure ReadRef(p: PTaiProp; Const Ref: POperReference);
 Begin
 Begin
   If Ref^.Base <> R_NO Then
   If Ref^.Base <> R_NO Then
     ReadReg(p, Ref^.Base);
     ReadReg(p, Ref^.Base);
@@ -2592,7 +2586,18 @@ End.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.27  2002-03-31 20:26:38  jonas
+  Revision 1.28  2002-04-02 17:11:34  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:38  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

File diff ditekan karena terlalu besar
+ 1261 - 1528
compiler/i386/n386add.pas


+ 192 - 215
compiler/i386/n386cal.pas

@@ -60,10 +60,10 @@ implementation
 {$ifdef GDB}
 {$ifdef GDB}
       gdb,
       gdb,
 {$endif GDB}
 {$endif GDB}
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       cpubase,cpuasm,
       cpubase,cpuasm,
-      nmem,nld,
-      tainst,cga,cgobj,tgobj,n386ld,n386util,regvars,rgobj,rgcpu;
+      nmem,nld,ncnv,
+      tainst,cga,cgobj,tgobj,n386ld,n386util,regvars,rgobj,rgcpu,cg64f32;
 
 
 {*****************************************************************************
 {*****************************************************************************
                              TI386CALLPARANODE
                              TI386CALLPARANODE
@@ -89,7 +89,8 @@ implementation
          otlabel,oflabel : tasmlabel;
          otlabel,oflabel : tasmlabel;
          { temporary variables: }
          { temporary variables: }
          tempdeftype : tdeftype;
          tempdeftype : tdeftype;
-         r : preference;
+         href   : treference;
+         cgsize : tcgsize;
 
 
       begin
       begin
          { set default para_alignment to target_info.stackalignment }
          { set default para_alignment to target_info.stackalignment }
@@ -119,7 +120,7 @@ implementation
                begin
                begin
                  inc(pushedparasize,4);
                  inc(pushedparasize,4);
                  emitpushreferenceaddr(left.location.reference);
                  emitpushreferenceaddr(left.location.reference);
-                 rg.del_reference(exprasmlist,left.location.reference);
+                 location_release(exprasmlist,left.location);
                end
                end
              else
              else
                push_value_para(left,inlined,is_cdecl,para_offset,para_alignment);
                push_value_para(left,inlined,is_cdecl,para_offset,para_alignment);
@@ -131,7 +132,7 @@ implementation
            end
            end
          { in codegen.handleread.. defcoll.data is set to nil }
          { in codegen.handleread.. defcoll.data is set to nil }
          else if assigned(defcoll.paratype.def) and
          else if assigned(defcoll.paratype.def) and
-           (defcoll.paratype.def.deftype=formaldef) then
+                 (defcoll.paratype.def.deftype=formaldef) then
            begin
            begin
               { allow @var }
               { allow @var }
               inc(pushedparasize,4);
               inc(pushedparasize,4);
@@ -141,9 +142,8 @@ implementation
                 { always a register }
                 { always a register }
                   if inlined then
                   if inlined then
                     begin
                     begin
-                       r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                       emit_reg_ref(A_MOV,S_L,
-                         left.location.register,r);
+                       reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
+                       emit_reg_ref(A_MOV,S_L,left.location.register,href);
                     end
                     end
                   else
                   else
                     emit_reg(A_PUSH,S_L,left.location.register);
                     emit_reg(A_PUSH,S_L,left.location.register);
@@ -151,30 +151,55 @@ implementation
                 end
                 end
               else
               else
                 begin
                 begin
-                   if not(left.location.loc in [LOC_MEM,LOC_REFERENCE]) then
+                   { get temp for constants }
+                   if left.location.loc=LOC_CONSTANT then
+                    begin
+                      cgsize:=def_cgsize(left.resulttype.def);
+                      tg.gettempofsizereference(exprasmlist,left.resulttype.def.size,href);
+                      cg.a_load_loc_ref(exprasmlist,cgsize,left.location,href);
+                      location_reset(left.location,LOC_REFERENCE,cgsize);
+                      left.location.reference:=href;
+                    end;
+
+                   if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
                      CGMessage(type_e_mismatch)
                      CGMessage(type_e_mismatch)
                    else
                    else
                      begin
                      begin
                        if inlined then
                        if inlined then
                          begin
                          begin
                            rg.getexplicitregisterint(exprasmlist,R_EDI);
                            rg.getexplicitregisterint(exprasmlist,R_EDI);
-                           emit_ref_reg(A_LEA,S_L,
-                             newreference(left.location.reference),R_EDI);
-                           r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                           emit_reg_ref(A_MOV,S_L,R_EDI,r);
+                           emit_ref_reg(A_LEA,S_L,left.location.reference,R_EDI);
+                           reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
+                           emit_reg_ref(A_MOV,S_L,R_EDI,href);
                            rg.ungetregisterint(exprasmlist,R_EDI);
                            rg.ungetregisterint(exprasmlist,R_EDI);
                          end
                          end
-                      else
-                        emitpushreferenceaddr(left.location.reference);
-                        rg.del_reference(exprasmlist,left.location.reference);
+                       else
+                         cg.a_paramaddr_ref(exprasmlist,left.location.reference,-1);
+                       location_release(exprasmlist,left.location);
                      end;
                      end;
                 end;
                 end;
            end
            end
          { handle call by reference parameter }
          { handle call by reference parameter }
          else if (defcoll.paratyp in [vs_var,vs_out]) then
          else if (defcoll.paratyp in [vs_var,vs_out]) then
            begin
            begin
+              { get temp for constants }
+              if left.location.loc=LOC_CONSTANT then
+               begin
+                 cgsize:=def_cgsize(left.resulttype.def);
+                 tg.gettempofsizereference(exprasmlist,left.resulttype.def.size,href);
+                 cg.a_load_loc_ref(exprasmlist,cgsize,left.location,href);
+                 location_reset(left.location,LOC_REFERENCE,cgsize);
+                 left.location.reference:=href;
+               end;
+
               if (left.location.loc<>LOC_REFERENCE) then
               if (left.location.loc<>LOC_REFERENCE) then
-                internalerror(200106041);
+               begin
+                 { passing self to a var parameter is allowed in
+                   TP and delphi }
+                 if not((left.location.loc=LOC_CREFERENCE) and
+                        (left.nodetype=selfn)) then
+                  internalerror(200106041);
+               end;
               maybe_push_high;
               maybe_push_high;
               if (defcoll.paratyp=vs_out) and
               if (defcoll.paratyp=vs_out) and
                  assigned(defcoll.paratype.def) and
                  assigned(defcoll.paratype.def) and
@@ -185,15 +210,14 @@ implementation
               if inlined then
               if inlined then
                 begin
                 begin
                    rg.getexplicitregisterint(exprasmlist,R_EDI);
                    rg.getexplicitregisterint(exprasmlist,R_EDI);
-                   emit_ref_reg(A_LEA,S_L,
-                     newreference(left.location.reference),R_EDI);
-                   r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                   emit_reg_ref(A_MOV,S_L,R_EDI,r);
+                   emit_ref_reg(A_LEA,S_L,left.location.reference,R_EDI);
+                   reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
+                   emit_reg_ref(A_MOV,S_L,R_EDI,href);
                    rg.ungetregisterint(exprasmlist,R_EDI);
                    rg.ungetregisterint(exprasmlist,R_EDI);
                 end
                 end
               else
               else
-                emitpushreferenceaddr(left.location.reference);
-              rg.del_reference(exprasmlist,left.location.reference);
+                cg.a_paramaddr_ref(exprasmlist,left.location.reference,-1);
+              location_release(exprasmlist,left.location);
            end
            end
          else
          else
            begin
            begin
@@ -212,20 +236,35 @@ implementation
                   not is_cdecl
                   not is_cdecl
                  ) then
                  ) then
                 begin
                 begin
+                   if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+                    begin
+                      { allow passing nil to a procvardef (methodpointer) }
+                      if (left.nodetype=typeconvn) and
+                         (left.resulttype.def.deftype=procvardef) and
+                         (ttypeconvnode(left).left.nodetype=niln) then
+                       begin
+                         tg.gettempofsizereference(exprasmlist,tcgsize2size[left.location.size],href);
+                         cg.a_load_loc_ref(exprasmlist,left.location.size,left.location,href);
+                         location_reset(left.location,LOC_REFERENCE,left.location.size);
+                         left.location.reference:=href;
+                       end
+                      else
+                       internalerror(200204011);
+                    end;
+
                    maybe_push_high;
                    maybe_push_high;
                    inc(pushedparasize,4);
                    inc(pushedparasize,4);
                    if inlined then
                    if inlined then
                      begin
                      begin
                         rg.getexplicitregisterint(exprasmlist,R_EDI);
                         rg.getexplicitregisterint(exprasmlist,R_EDI);
-                        emit_ref_reg(A_LEA,S_L,
-                          newreference(left.location.reference),R_EDI);
-                        r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                        emit_reg_ref(A_MOV,S_L,R_EDI,r);
+                        emit_ref_reg(A_LEA,S_L,left.location.reference,R_EDI);
+                        reference_reset_base(href,procinfo^.framepointer,para_offset-pushedparasize);
+                        emit_reg_ref(A_MOV,S_L,R_EDI,href);
                         rg.ungetregisterint(exprasmlist,R_EDI);
                         rg.ungetregisterint(exprasmlist,R_EDI);
                      end
                      end
                    else
                    else
-                     emitpushreferenceaddr(left.location.reference);
-                   rg.del_reference(exprasmlist,left.location.reference);
+                     cg.a_paramaddr_ref(exprasmlist,left.location.reference,-1);
+                   location_release(exprasmlist,left.location);
                 end
                 end
               else
               else
                 begin
                 begin
@@ -258,7 +297,7 @@ implementation
          unusedstate: pointer;
          unusedstate: pointer;
          pushed : tpushedsaved;
          pushed : tpushedsaved;
          funcretref,refcountedtemp : treference;
          funcretref,refcountedtemp : treference;
-         hregister,hregister2 : tregister;
+         hregister : tregister;
          oldpushedparasize : longint;
          oldpushedparasize : longint;
          { true if ESI must be loaded again after the subroutine }
          { true if ESI must be loaded again after the subroutine }
          loadesi : boolean;
          loadesi : boolean;
@@ -273,7 +312,7 @@ implementation
          { lexlevel count }
          { lexlevel count }
          i : longint;
          i : longint;
          { help reference pointer }
          { help reference pointer }
-         r : preference;
+         href : treference;
          hp : tnode;
          hp : tnode;
          pp : tbinarynode;
          pp : tbinarynode;
          params : tnode;
          params : tnode;
@@ -292,13 +331,14 @@ implementation
          push_size : longint;
          push_size : longint;
 {$endif OPTALIGN}
 {$endif OPTALIGN}
          pop_allowed : boolean;
          pop_allowed : boolean;
+         cgsize : tcgsize;
          constructorfailed : tasmlabel;
          constructorfailed : tasmlabel;
 
 
       label
       label
          dont_call;
          dont_call;
 
 
       begin
       begin
-         reset_reference(location.reference);
+         location_reset(location,LOC_REFERENCE,def_cgsize_ref(resulttype.def));
          extended_new:=false;
          extended_new:=false;
          iolabel:=nil;
          iolabel:=nil;
          inlinecode:=nil;
          inlinecode:=nil;
@@ -467,7 +507,7 @@ implementation
 {$endif test_dest_loc}
 {$endif test_dest_loc}
                 if inlined then
                 if inlined then
                   begin
                   begin
-                     reset_reference(funcretref);
+                     reference_reset(funcretref);
                      funcretref.offset:=tg.gettempofsizepersistant(exprasmlist,resulttype.def.size);
                      funcretref.offset:=tg.gettempofsizepersistant(exprasmlist,resulttype.def.size);
                      funcretref.base:=procinfo^.framepointer;
                      funcretref.base:=procinfo^.framepointer;
 {$ifdef extdebug}
 {$ifdef extdebug}
@@ -514,10 +554,9 @@ implementation
               if inlined then
               if inlined then
                 begin
                 begin
                    rg.getexplicitregisterint(exprasmlist,R_EDI);
                    rg.getexplicitregisterint(exprasmlist,R_EDI);
-                   emit_ref_reg(A_LEA,S_L,
-                     newreference(funcretref),R_EDI);
-                   r:=new_reference(procinfo^.framepointer,inlinecode.retoffset);
-                   emit_reg_ref(A_MOV,S_L,R_EDI,r);
+                   emit_ref_reg(A_LEA,S_L,funcretref,R_EDI);
+                   reference_reset_base(href,procinfo^.framepointer,inlinecode.retoffset);
+                   emit_reg_ref(A_MOV,S_L,R_EDI,href);
                    rg.ungetregisterint(exprasmlist,R_EDI);
                    rg.ungetregisterint(exprasmlist,R_EDI);
                 end
                 end
               else
               else
@@ -544,24 +583,13 @@ implementation
                    methodpointer.resulttype:=
                    methodpointer.resulttype:=
                      twithnode(twithsymtable(symtableproc).withnode).left.resulttype;
                      twithnode(twithsymtable(symtableproc).withnode).left.resulttype;
                    { make a reference }
                    { make a reference }
-                   new(r);
-                   reset_reference(r^);
-                   { if assigned(ptree(twithsymtable(symtable).withnode)^.pref) then
-                     begin
-                        r^:=ptree(twithsymtable(symtable).withnode)^.pref^;
-                     end
-                   else
-                     begin
-                        r^.offset:=symtable.datasize;
-                        r^.base:=procinfo^.framepointer;
-                     end; }
-                   r^:=twithnode(twithsymtable(symtableproc).withnode).withreference^;
+                   href:=twithnode(twithsymtable(symtableproc).withnode).withreference;
                    if ((not(nf_islocal in twithnode(twithsymtable(symtableproc).withnode).flags)) and
                    if ((not(nf_islocal in twithnode(twithsymtable(symtableproc).withnode).flags)) and
                        (not twithsymtable(symtableproc).direct_with)) or
                        (not twithsymtable(symtableproc).direct_with)) or
                       is_class_or_interface(methodpointer.resulttype.def) then
                       is_class_or_interface(methodpointer.resulttype.def) then
-                     emit_ref_reg(A_MOV,S_L,r,R_ESI)
+                     emit_ref_reg(A_MOV,S_L,href,R_ESI)
                    else
                    else
-                     emit_ref_reg(A_LEA,S_L,r,R_ESI);
+                     emit_ref_reg(A_LEA,S_L,href,R_ESI);
                 end;
                 end;
 
 
               { push self }
               { push self }
@@ -674,9 +702,8 @@ implementation
                                     { destructor with extended syntax called from dispose }
                                     { destructor with extended syntax called from dispose }
                                     { hdisposen always deliver LOC_REFERENCE          }
                                     { hdisposen always deliver LOC_REFERENCE          }
                                     rg.getexplicitregisterint(exprasmlist,R_ESI);
                                     rg.getexplicitregisterint(exprasmlist,R_ESI);
-                                    emit_ref_reg(A_LEA,S_L,
-                                      newreference(methodpointer.location.reference),R_ESI);
-                                    rg.del_reference(exprasmlist,methodpointer.location.reference);
+                                    emit_ref_reg(A_LEA,S_L,methodpointer.location.reference,R_ESI);
+                                    reference_release(exprasmlist,methodpointer.location.reference);
                                     emit_reg(A_PUSH,S_L,R_ESI);
                                     emit_reg(A_PUSH,S_L,R_ESI);
                                     emit_sym(A_PUSH,S_L,
                                     emit_sym(A_PUSH,S_L,
                                       newasmsymbol(tobjectdef(methodpointer.resulttype.def).vmt_mangledname));
                                       newasmsymbol(tobjectdef(methodpointer.resulttype.def).vmt_mangledname));
@@ -699,12 +726,10 @@ implementation
                                               begin
                                               begin
                                                  if (methodpointer.resulttype.def.deftype=classrefdef) or
                                                  if (methodpointer.resulttype.def.deftype=classrefdef) or
                                                     is_class_or_interface(methodpointer.resulttype.def) then
                                                     is_class_or_interface(methodpointer.resulttype.def) then
-                                                   emit_ref_reg(A_MOV,S_L,
-                                                     newreference(methodpointer.location.reference),R_ESI)
+                                                   emit_ref_reg(A_MOV,S_L,methodpointer.location.reference,R_ESI)
                                                  else
                                                  else
-                                                   emit_ref_reg(A_LEA,S_L,
-                                                     newreference(methodpointer.location.reference),R_ESI);
-                                                 rg.del_reference(exprasmlist,methodpointer.location.reference);
+                                                   emit_ref_reg(A_LEA,S_L,methodpointer.location.reference,R_ESI);
+                                                 reference_release(exprasmlist,methodpointer.location.reference);
                                               end;
                                               end;
                                          end;
                                          end;
                                       end;
                                       end;
@@ -717,11 +742,8 @@ implementation
                                           begin
                                           begin
                                              { class method needs current VMT }
                                              { class method needs current VMT }
                                              rg.getexplicitregisterint(exprasmlist,R_ESI);
                                              rg.getexplicitregisterint(exprasmlist,R_ESI);
-                                             new(r);
-                                             reset_reference(r^);
-                                             r^.base:=R_ESI;
-                                             r^.offset:= tprocdef(procdefinition)._class.vmt_offset;
-                                             emit_ref_reg(A_MOV,S_L,r,R_ESI);
+                                             reference_reset_base(href,R_ESI,tprocdef(procdefinition)._class.vmt_offset);
+                                             emit_ref_reg(A_MOV,S_L,href,R_ESI);
                                           end;
                                           end;
 
 
                                         { direct call to destructor: remove data }
                                         { direct call to destructor: remove data }
@@ -778,11 +800,8 @@ implementation
                           begin
                           begin
                              { class method needs current VMT }
                              { class method needs current VMT }
                              rg.getexplicitregisterint(exprasmlist,R_ESI);
                              rg.getexplicitregisterint(exprasmlist,R_ESI);
-                             new(r);
-                             reset_reference(r^);
-                             r^.base:=R_ESI;
-                             r^.offset:= tprocdef(procdefinition)._class.vmt_offset;
-                             emit_ref_reg(A_MOV,S_L,r,R_ESI);
+                             reference_reset_base(href,R_ESI,tprocdef(procdefinition)._class.vmt_offset);
+                             emit_ref_reg(A_MOV,S_L,href,R_ESI);
                           end
                           end
                         else
                         else
                           begin
                           begin
@@ -836,16 +855,11 @@ implementation
                    (right=nil)) then
                    (right=nil)) then
                   begin
                   begin
                      emit_reg(A_PUSH,S_L,R_ESI);
                      emit_reg(A_PUSH,S_L,R_ESI);
-                     new(r);
-                     reset_reference(r^);
-                     r^.base:=R_ESI;
+                     reference_reset_base(href,R_ESI,0);
                      rg.getexplicitregisterint(exprasmlist,R_EDI);
                      rg.getexplicitregisterint(exprasmlist,R_EDI);
-                     emit_ref_reg(A_MOV,S_L,r,R_EDI);
-                     new(r);
-                     reset_reference(r^);
-                     r^.offset:=72;
-                     r^.base:=R_EDI;
-                     emit_ref(A_CALL,S_NO,r);
+                     emit_ref_reg(A_MOV,S_L,href,R_EDI);
+                     reference_reset_base(href,R_EDI,72);
+                     emit_ref(A_CALL,S_NO,href);
                      rg.ungetregisterint(exprasmlist,R_EDI);
                      rg.ungetregisterint(exprasmlist,R_EDI);
                   end;
                   end;
 
 
@@ -869,11 +883,8 @@ implementation
                      }
                      }
                      if lexlevel=(tprocdef(procdefinition).parast.symtablelevel) then
                      if lexlevel=(tprocdef(procdefinition).parast.symtablelevel) then
                        begin
                        begin
-                          new(r);
-                          reset_reference(r^);
-                          r^.offset:=procinfo^.framepointer_offset;
-                          r^.base:=procinfo^.framepointer;
-                          emit_ref(A_PUSH,S_L,r)
+                          reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
+                          emit_ref(A_PUSH,S_L,href)
                        end
                        end
                        { this is only true if the difference is one !!
                        { this is only true if the difference is one !!
                          but it cannot be more !! }
                          but it cannot be more !! }
@@ -884,20 +895,14 @@ implementation
                      else if (lexlevel>(tprocdef(procdefinition).parast.symtablelevel)) then
                      else if (lexlevel>(tprocdef(procdefinition).parast.symtablelevel)) then
                        begin
                        begin
                           hregister:=rg.getregisterint(exprasmlist);
                           hregister:=rg.getregisterint(exprasmlist);
-                          new(r);
-                          reset_reference(r^);
-                          r^.offset:=procinfo^.framepointer_offset;
-                          r^.base:=procinfo^.framepointer;
-                          emit_ref_reg(A_MOV,S_L,r,hregister);
+                          reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
+                          emit_ref_reg(A_MOV,S_L,href,hregister);
                           for i:=(tprocdef(procdefinition).parast.symtablelevel) to lexlevel-1 do
                           for i:=(tprocdef(procdefinition).parast.symtablelevel) to lexlevel-1 do
                             begin
                             begin
-                               new(r);
-                               reset_reference(r^);
                                {we should get the correct frame_pointer_offset at each level
                                {we should get the correct frame_pointer_offset at each level
                                how can we do this !!! }
                                how can we do this !!! }
-                               r^.offset:=procinfo^.framepointer_offset;
-                               r^.base:=hregister;
-                               emit_ref_reg(A_MOV,S_L,r,hregister);
+                               reference_reset_base(href,hregister,procinfo^.framepointer_offset);
+                               emit_ref_reg(A_MOV,S_L,href,hregister);
                             end;
                             end;
                           emit_reg(A_PUSH,S_L,hregister);
                           emit_reg(A_PUSH,S_L,hregister);
                           rg.ungetregisterint(exprasmlist,hregister);
                           rg.ungetregisterint(exprasmlist,hregister);
@@ -932,22 +937,15 @@ implementation
                         { ESI is loaded earlier }
                         { ESI is loaded earlier }
                         (po_classmethod in procdefinition.procoptions) then
                         (po_classmethod in procdefinition.procoptions) then
                          begin
                          begin
-                            new(r);
-                            reset_reference(r^);
-                            r^.base:=R_ESI;
+                            reference_reset_base(href,R_ESI,0);
                          end
                          end
                        else
                        else
                          begin
                          begin
-                            new(r);
-                            reset_reference(r^);
-                            r^.base:=R_ESI;
                             { this is one point where we need vmt_offset (PM) }
                             { this is one point where we need vmt_offset (PM) }
-                            r^.offset:= tprocdef(procdefinition)._class.vmt_offset;
+                            reference_reset_base(href,R_ESI,tprocdef(procdefinition)._class.vmt_offset);
                             rg.getexplicitregisterint(exprasmlist,R_EDI);
                             rg.getexplicitregisterint(exprasmlist,R_EDI);
-                            emit_ref_reg(A_MOV,S_L,r,R_EDI);
-                            new(r);
-                            reset_reference(r^);
-                            r^.base:=R_EDI;
+                            emit_ref_reg(A_MOV,S_L,href,R_EDI);
+                            reference_reset_base(href,R_EDI,0);
                          end;
                          end;
                      end
                      end
                    else
                    else
@@ -966,7 +964,7 @@ implementation
                    }
                    }
                    if tprocdef(procdefinition).extnumber=-1 then
                    if tprocdef(procdefinition).extnumber=-1 then
                      internalerror(44584);
                      internalerror(44584);
-                   r^.offset:=tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber);
+                   href.offset:=tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber);
                    if not(is_interface(tprocdef(procdefinition)._class)) and
                    if not(is_interface(tprocdef(procdefinition)._class)) and
                      not(is_cppclass(tprocdef(procdefinition)._class)) then
                      not(is_cppclass(tprocdef(procdefinition)._class)) then
                      begin
                      begin
@@ -974,16 +972,16 @@ implementation
                           begin
                           begin
                              emit_sym(A_PUSH,S_L,
                              emit_sym(A_PUSH,S_L,
                                newasmsymbol(tprocdef(procdefinition)._class.vmt_mangledname));
                                newasmsymbol(tprocdef(procdefinition)._class.vmt_mangledname));
-                             emit_reg(A_PUSH,S_L,r^.base);
+                             emit_reg(A_PUSH,S_L,href.base);
                              emitcall('FPC_CHECK_OBJECT_EXT');
                              emitcall('FPC_CHECK_OBJECT_EXT');
                           end
                           end
                         else if (cs_check_range in aktlocalswitches) then
                         else if (cs_check_range in aktlocalswitches) then
                           begin
                           begin
-                             emit_reg(A_PUSH,S_L,r^.base);
+                             emit_reg(A_PUSH,S_L,href.base);
                              emitcall('FPC_CHECK_OBJECT');
                              emitcall('FPC_CHECK_OBJECT');
                           end;
                           end;
                      end;
                      end;
-                   emit_ref(A_CALL,S_NO,r);
+                   emit_ref(A_CALL,S_NO,href);
                    rg.ungetregisterint(exprasmlist,R_EDI);
                    rg.ungetregisterint(exprasmlist,R_EDI);
                 end
                 end
               else if not inlined then
               else if not inlined then
@@ -1028,10 +1026,9 @@ implementation
                    if (right.location.reference.base=R_ESI) or
                    if (right.location.reference.base=R_ESI) or
                       (right.location.reference.index=R_ESI) then
                       (right.location.reference.index=R_ESI) then
                      begin
                      begin
-                        rg.del_reference(exprasmlist,right.location.reference);
+                        reference_release(exprasmlist,right.location.reference);
                         rg.getexplicitregisterint(exprasmlist,R_EDI);
                         rg.getexplicitregisterint(exprasmlist,R_EDI);
-                        emit_ref_reg(A_MOV,S_L,
-                          newreference(right.location.reference),R_EDI);
+                        emit_ref_reg(A_MOV,S_L,right.location.reference,R_EDI);
                         hregister:=R_EDI;
                         hregister:=R_EDI;
                      end;
                      end;
 
 
@@ -1041,8 +1038,7 @@ implementation
                        { load ESI }
                        { load ESI }
                        inc(right.location.reference.offset,4);
                        inc(right.location.reference.offset,4);
                        rg.getexplicitregisterint(exprasmlist,R_ESI);
                        rg.getexplicitregisterint(exprasmlist,R_ESI);
-                       emit_ref_reg(A_MOV,S_L,
-                         newreference(right.location.reference),R_ESI);
+                       emit_ref_reg(A_MOV,S_L,right.location.reference,R_ESI);
                        dec(right.location.reference.offset,4);
                        dec(right.location.reference.offset,4);
                        { push self pointer }
                        { push self pointer }
                        emit_reg(A_PUSH,S_L,R_ESI);
                        emit_reg(A_PUSH,S_L,R_ESI);
@@ -1050,30 +1046,27 @@ implementation
 
 
                    rg.saveregvars(exprasmlist,ALL_REGISTERS);
                    rg.saveregvars(exprasmlist,ALL_REGISTERS);
                    if hregister=R_NO then
                    if hregister=R_NO then
-                     emit_ref(A_CALL,S_NO,newreference(right.location.reference))
+                     emit_ref(A_CALL,S_NO,right.location.reference)
                    else
                    else
                      begin
                      begin
                        emit_reg(A_CALL,S_NO,hregister);
                        emit_reg(A_CALL,S_NO,hregister);
                        rg.ungetregisterint(exprasmlist,hregister);
                        rg.ungetregisterint(exprasmlist,hregister);
                      end;
                      end;
 
 
-                   rg.del_reference(exprasmlist,right.location.reference);
+                   reference_release(exprasmlist,right.location.reference);
                 end
                 end
               else
               else
                 begin
                 begin
                    rg.saveregvars(exprasmlist,ALL_REGISTERS);
                    rg.saveregvars(exprasmlist,ALL_REGISTERS);
                    case right.location.loc of
                    case right.location.loc of
                       LOC_REGISTER,LOC_CREGISTER:
                       LOC_REGISTER,LOC_CREGISTER:
-                         begin
-                             emit_reg(A_CALL,S_NO,right.location.register);
-                             rg.ungetregisterint(exprasmlist,right.location.register);
-                         end
+                        emit_reg(A_CALL,S_NO,right.location.register);
+                      LOC_REFERENCE,LOC_CREFERENCE :
+                        emit_ref(A_CALL,S_NO,right.location.reference);
                       else
                       else
-                         begin
-                           emit_ref(A_CALL,S_NO,newreference(right.location.reference));
-                           rg.del_reference(exprasmlist,right.location.reference);
-                         end;
+                        internalerror(200203311);
                    end;
                    end;
+                   location_release(exprasmlist,right.location);
                 end;
                 end;
            end;
            end;
 
 
@@ -1144,16 +1137,11 @@ implementation
               getlabel(constructorfailed);
               getlabel(constructorfailed);
               emitjmp(C_Z,constructorfailed);
               emitjmp(C_Z,constructorfailed);
               emit_reg(A_PUSH,S_L,R_ESI);
               emit_reg(A_PUSH,S_L,R_ESI);
-              new(r);
-              reset_reference(r^);
-              r^.base:=R_ESI;
+              reference_reset_base(href,R_ESI,0);
               rg.getexplicitregisterint(exprasmlist,R_EDI);
               rg.getexplicitregisterint(exprasmlist,R_EDI);
-              emit_ref_reg(A_MOV,S_L,r,R_EDI);
-              new(r);
-              reset_reference(r^);
-              r^.offset:=68;
-              r^.base:=R_EDI;
-              emit_ref(A_CALL,S_NO,r);
+              emit_ref_reg(A_MOV,S_L,href,R_EDI);
+              reference_reset_base(href,R_EDI,68);
+              emit_ref(A_CALL,S_NO,href);
               rg.ungetregisterint(exprasmlist,R_EDI);
               rg.ungetregisterint(exprasmlist,R_EDI);
               exprasmList.concat(Tairegalloc.Alloc(R_EAX));
               exprasmList.concat(Tairegalloc.Alloc(R_EAX));
               emitlab(constructorfailed);
               emitlab(constructorfailed);
@@ -1165,7 +1153,7 @@ implementation
          { needed also when result_no_used !! }
          { needed also when result_no_used !! }
          if (not is_void(resulttype.def)) and ret_in_param(resulttype.def) then
          if (not is_void(resulttype.def)) and ret_in_param(resulttype.def) then
            begin
            begin
-              location.loc:=LOC_MEM;
+              location.loc:=LOC_CREFERENCE;
               location.reference.symbol:=nil;
               location.reference.symbol:=nil;
               location.reference:=funcretref;
               location.reference:=funcretref;
            end;
            end;
@@ -1181,11 +1169,6 @@ implementation
                  { quick'n'dirty check if it is a class or an object }
                  { quick'n'dirty check if it is a class or an object }
                  (resulttype.def.deftype=orddef) then
                  (resulttype.def.deftype=orddef) then
                 begin
                 begin
-                   { this fails if popsize > 0 PM }
-                   location.loc:=LOC_FLAGS;
-                   location.resflags:=F_NE;
-
-
                    if extended_new then
                    if extended_new then
                      begin
                      begin
 {$ifdef test_dest_loc}
 {$ifdef test_dest_loc}
@@ -1197,8 +1180,15 @@ implementation
                              cg.a_reg_alloc(exprasmlist,R_EAX);
                              cg.a_reg_alloc(exprasmlist,R_EAX);
                              hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
                              hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
                              emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
                              emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
+                             location_reset(location,LOC_REGISTER,OS_NO);
                              location.register:=hregister;
                              location.register:=hregister;
                           end;
                           end;
+                     end
+                   else
+                     begin
+                       { this fails if popsize > 0 PM }
+                       location_reset(location,LOC_FLAGS,OS_NO);
+                       location.resflags:=F_NE;
                      end;
                      end;
                 end
                 end
                { structed results are easy to handle.... }
                { structed results are easy to handle.... }
@@ -1213,92 +1203,69 @@ implementation
                 begin
                 begin
                    if (resulttype.def.deftype in [orddef,enumdef]) then
                    if (resulttype.def.deftype in [orddef,enumdef]) then
                      begin
                      begin
-                        location.loc:=LOC_REGISTER;
                         cg.a_reg_alloc(exprasmlist,R_EAX);
                         cg.a_reg_alloc(exprasmlist,R_EAX);
-                        case resulttype.def.size of
-                          4 :
-                            begin
-{$ifdef test_dest_loc}
-                               if dest_loc_known and (dest_loc_tree=p) then
-                                 mov_reg_to_dest(p,S_L,R_EAX)
-                               else
-{$endif test_dest_loc}
-                                 begin
-                                    hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
-                                    emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
-                                    location.register:=hregister;
-                                 end;
-                            end;
-                          1 :
-                            begin
-{$ifdef test_dest_loc}
-                                 if dest_loc_known and (dest_loc_tree=p) then
-                                   mov_reg_to_dest(p,S_B,R_AL)
-                                 else
-{$endif test_dest_loc}
-                                   begin
-                                      hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
-                                      emit_reg_reg(A_MOV,S_B,R_AL,reg32toreg8(hregister));
-                                      location.register:=reg32toreg8(hregister);
-                                   end;
-                              end;
-                          2 :
-                            begin
-{$ifdef test_dest_loc}
-                               if dest_loc_known and (dest_loc_tree=p) then
-                                 mov_reg_to_dest(p,S_W,R_AX)
-                               else
-{$endif test_dest_loc}
-                                 begin
-                                    hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
-                                    emit_reg_reg(A_MOV,S_W,R_AX,reg32toreg16(hregister));
-                                    location.register:=reg32toreg16(hregister);
-                                 end;
-                            end;
-                           8 :
+                        cgsize:=def_cgsize(resulttype.def);
+                        location_reset(location,LOC_REGISTER,cgsize);
+                        if cgsize in [OS_64,OS_S64] then
+                         begin
+                           cg.a_reg_alloc(exprasmlist,R_EDX);
+                           if R_EDX in rg.unusedregsint then
+                             begin
+                                location.registerhigh:=rg.getexplicitregisterint(exprasmlist,R_EDX);
+                                location.registerlow:=rg.getexplicitregisterint(exprasmlist,R_EAX);
+                             end
+                           else
                              begin
                              begin
+                                location.registerhigh:=rg.getexplicitregisterint(exprasmlist,R_EDX);
+                                location.registerlow:=rg.getexplicitregisterint(exprasmlist,R_EAX);
+                             end;
+                           tcg64f32(cg).a_load64_reg_reg(exprasmlist,R_EAX,R_EDX,location.registerlow,location.registerhigh);
+                         end
+                        else
+                         begin
+                           location.register:=rg.getexplicitregisterint(exprasmlist,R_EAX);
+                           case cgsize of
+                             OS_8,OS_S8 :
+                               begin
+                                 hregister:=R_AL;
+                                 location.register:=makereg8(location.register);
+                               end;
+                             OS_16,OS_S16 :
+                               begin
+                                 hregister:=R_AX;
+                                 location.register:=makereg16(location.register);
+                               end;
+                             OS_32,OS_S32 :
+                               hregister:=R_EAX;
+                             else
+                               internalerror(200203281);
+                           end;
 {$ifdef test_dest_loc}
 {$ifdef test_dest_loc}
 {$error Don't know what to do here}
 {$error Don't know what to do here}
+                               if dest_loc_known and (dest_loc_tree=p) then
+                                 mov_reg_to_dest(p,S_L,R_EAX)
 {$endif test_dest_loc}
 {$endif test_dest_loc}
-                                cg.a_reg_alloc(exprasmlist,R_EDX);
-                                if R_EDX in rg.unusedregsint then
-                                  begin
-                                     hregister2:=rg.getexplicitregisterint(exprasmlist,R_EDX);
-                                     hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
-                                  end
-                                else
-                                  begin
-                                     hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
-                                     hregister2:=rg.getexplicitregisterint(exprasmlist,R_EDX);
-                                  end;
-                                emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
-                                emit_reg_reg(A_MOV,S_L,R_EDX,hregister2);
-                                location.registerlow:=hregister;
-                                location.registerhigh:=hregister2;
-                             end;
-                        else internalerror(7);
+                           cg.a_load_reg_reg(exprasmlist,cgsize,hregister,location.register);
+                         end
                      end
                      end
-
-                end
               else if (resulttype.def.deftype=floatdef) then
               else if (resulttype.def.deftype=floatdef) then
                 begin
                 begin
-                  location.loc:=LOC_FPU;
+                  location_reset(location,LOC_FPUREGISTER,OS_NO);
                   location.register:=R_ST;
                   location.register:=R_ST;
                   inc(trgcpu(rg).fpuvaroffset);
                   inc(trgcpu(rg).fpuvaroffset);
                 end
                 end
               else if is_ansistring(resulttype.def) or
               else if is_ansistring(resulttype.def) or
-                is_widestring(resulttype.def) then
+                      is_widestring(resulttype.def) then
                 begin
                 begin
+                   location_reset(location,LOC_CREFERENCE,OS_ADDR);
+                   location.reference:=refcountedtemp;
                    cg.a_reg_alloc(exprasmlist,R_EAX);
                    cg.a_reg_alloc(exprasmlist,R_EAX);
-                   emit_reg_ref(A_MOV,S_L,R_EAX,
-                     newreference(refcountedtemp));
+                   cg.a_load_reg_ref(exprasmlist,OS_ADDR,R_EAX,location.reference);
                    cg.a_reg_dealloc(exprasmlist,R_EAX);
                    cg.a_reg_dealloc(exprasmlist,R_EAX);
-                   location.loc:=LOC_MEM;
-                   location.reference:=refcountedtemp;
                 end
                 end
               else
               else
                 begin
                 begin
-                   location.loc:=LOC_REGISTER;
+                   location_reset(location,LOC_REGISTER,OS_INT);
 {$ifdef test_dest_loc}
 {$ifdef test_dest_loc}
                    if dest_loc_known and (dest_loc_tree=p) then
                    if dest_loc_known and (dest_loc_tree=p) then
                      mov_reg_to_dest(p,S_L,R_EAX)
                      mov_reg_to_dest(p,S_L,R_EAX)
@@ -1306,9 +1273,8 @@ implementation
 {$endif test_dest_loc}
 {$endif test_dest_loc}
                     begin
                     begin
                        cg.a_reg_alloc(exprasmlist,R_EAX);
                        cg.a_reg_alloc(exprasmlist,R_EAX);
-                       hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
-                       emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
-                       location.register:=hregister;
+                       location.register:=rg.getexplicitregisterint(exprasmlist,R_EAX);
+                       cg.a_load_reg_reg(exprasmlist,OS_INT,R_EAX,location.register);
                     end;
                     end;
                 end;
                 end;
              end;
              end;
@@ -1334,7 +1300,7 @@ implementation
            begin
            begin
               if assigned(pp.left) then
               if assigned(pp.left) then
                 begin
                 begin
-                  if (pp.left.location.loc in [LOC_REFERENCE,LOC_MEM]) then
+                  if (pp.left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
                     tg.ungetiftemp(exprasmlist,pp.left.location.reference);
                     tg.ungetiftemp(exprasmlist,pp.left.location.reference);
                 { process also all nodes of an array of const }
                 { process also all nodes of an array of const }
                   if pp.left.nodetype=arrayconstructorn then
                   if pp.left.nodetype=arrayconstructorn then
@@ -1344,7 +1310,7 @@ implementation
                          hp:=pp.left;
                          hp:=pp.left;
                          while assigned(hp) do
                          while assigned(hp) do
                           begin
                           begin
-                            if (tarrayconstructornode(tunarynode(hp).left).location.loc in [LOC_REFERENCE,LOC_MEM]) then
+                            if (tarrayconstructornode(tunarynode(hp).left).location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
                               tg.ungetiftemp(exprasmlist,tarrayconstructornode(hp).left.location.reference);
                               tg.ungetiftemp(exprasmlist,tarrayconstructornode(hp).left.location.reference);
                             hp:=tbinarynode(hp).right;
                             hp:=tbinarynode(hp).right;
                           end;
                           end;
@@ -1369,7 +1335,7 @@ implementation
          { if return value is not used }
          { if return value is not used }
          if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
          if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
            begin
            begin
-              if location.loc in [LOC_MEM,LOC_REFERENCE] then
+              if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
                 begin
                 begin
                    { data which must be finalized ? }
                    { data which must be finalized ? }
                    if (resulttype.def.needs_inittable) then
                    if (resulttype.def.needs_inittable) then
@@ -1377,7 +1343,7 @@ implementation
                    { release unused temp }
                    { release unused temp }
                    tg.ungetiftemp(exprasmlist,location.reference)
                    tg.ungetiftemp(exprasmlist,location.reference)
                 end
                 end
-              else if location.loc=LOC_FPU then
+              else if location.loc=LOC_FPUREGISTER then
                 begin
                 begin
                   { release FPU stack }
                   { release FPU stack }
                   emit_reg(A_FSTP,S_NO,R_ST);
                   emit_reg(A_FSTP,S_NO,R_ST);
@@ -1569,7 +1535,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.42  2002-03-31 20:26:38  jonas
+  Revision 1.43  2002-04-02 17:11:35  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.42  2002/03/31 20:26:38  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 182 - 196
compiler/i386/n386cnv.pas

@@ -60,7 +60,7 @@ implementation
    uses
    uses
       verbose,systems,
       verbose,systems,
       symconst,symdef,aasm,
       symconst,symdef,aasm,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       ncon,ncal,
       ncon,ncal,
       cpubase,
       cpubase,
       cgobj,cga,tgobj,rgobj,rgcpu,n386util;
       cgobj,cga,tgobj,rgobj,rgcpu,n386util;
@@ -72,12 +72,12 @@ implementation
 
 
     procedure ti386typeconvnode.second_int_to_int;
     procedure ti386typeconvnode.second_int_to_int;
       var
       var
-        op      : tasmop;
-        opsize    : topsize;
-        hregister,
-        hregister2 : tregister;
-
+        newsize,
+        oldsize    : tcgsize;
       begin
       begin
+        newsize:=def_cgsize(resulttype.def);
+        oldsize:=def_cgsize(left.resulttype.def);
+
         { insert range check if not explicit conversion }
         { insert range check if not explicit conversion }
         if not(nf_explizit in flags) then
         if not(nf_explizit in flags) then
           cg.g_rangecheck(exprasmlist,left,resulttype.def);
           cg.g_rangecheck(exprasmlist,left,resulttype.def);
@@ -85,105 +85,42 @@ implementation
         { is the result size smaller ? }
         { is the result size smaller ? }
         if resulttype.def.size<left.resulttype.def.size then
         if resulttype.def.size<left.resulttype.def.size then
           begin
           begin
-            { only need to set the new size of a register }
-            if (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+            { reuse the left location by default }
+            location_copy(location,left.location);
+            location.size:=newsize;
+
+            { update the register to use }
+            if (location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
              begin
              begin
-               case resulttype.def.size of
-                1 : location.register:=makereg8(left.location.register);
-                2 : location.register:=makereg16(left.location.register);
-                4 : location.register:=makereg32(left.location.register);
+               if oldsize in [OS_64,OS_S64] then
+                begin
+                  { we can release the upper register }
+                  rg.ungetregisterint(exprasmlist,location.registerhigh);
+                  location.registerhigh:=R_NO;
+                end;
+               case newsize of
+                 OS_8,OS_S8 :
+                   location.register:=makereg8(location.register);
+                 OS_16,OS_S16 :
+                   location.register:=makereg16(location.register);
+                 OS_32,OS_S32 :
+                   location.register:=makereg32(location.register);
                end;
                end;
-               { we can release the upper register }
-               if is_64bitint(left.resulttype.def) then
-                 rg.ungetregisterint(exprasmlist,left.location.registerhigh);
              end;
              end;
           end
           end
 
 
         { is the result size bigger ? }
         { is the result size bigger ? }
         else if resulttype.def.size>left.resulttype.def.size then
         else if resulttype.def.size>left.resulttype.def.size then
           begin
           begin
-            { remove reference }
-            if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
-              begin
-                rg.del_reference(exprasmlist,left.location.reference);
-                { we can do this here as we need no temp inside }
-                tg.ungetiftemp(exprasmlist,left.location.reference);
-              end;
-
-            { get op and opsize, handle separate for constants, because
-              movz doesn't support constant values }
-            if (left.location.loc=LOC_MEM) and (left.location.reference.is_immediate) then
-             begin
-               if is_64bitint(resulttype.def) then
-                 opsize:=S_L
-               else
-                 opsize:=def_opsize(resulttype.def);
-               op:=A_MOV;
-             end
-            else
-             begin
-               opsize:=def2def_opsize(left.resulttype.def,resulttype.def);
-               if opsize in [S_B,S_W,S_L] then
-                op:=A_MOV
-               else
-                if is_signed(left.resulttype.def) then
-                 op:=A_MOVSX
-                else
-                 op:=A_MOVZX;
-             end;
-            { load the register we need }
-            if left.location.loc<>LOC_REGISTER then
-              hregister:=rg.getregisterint(exprasmlist)
-            else
-              hregister:=left.location.register;
-
-            { set the correct register size and location }
-            clear_location(location);
-            location.loc:=LOC_REGISTER;
-
-            { do we need a second register for a 64 bit type ? }
-            if is_64bitint(resulttype.def) then
-              begin
-                 hregister2:=rg.getregisterint(exprasmlist);
-                 location.registerhigh:=hregister2;
-              end;
-            case resulttype.def.size of
-             1:
-               location.register:=makereg8(hregister);
-             2:
-               location.register:=makereg16(hregister);
-             4,8:
-               location.register:=makereg32(hregister);
-            end;
-            { insert the assembler code }
-            if left.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
-              emit_reg_reg(op,opsize,left.location.register,location.register)
-            else
-              emit_ref_reg(op,opsize,
-                newreference(left.location.reference),location.register);
-
-            { do we need a sign extension for int64? }
-            if is_64bitint(resulttype.def) then
-              { special case for constants (JM) }
-              if is_constintnode(left) then
-                begin
-                  if tordconstnode(left).value >= 0 then
-                    emit_reg_reg(A_XOR,S_L,
-                      hregister2,hregister2)
-                  else
-                    emit_const_reg(A_MOV,S_L,longint($ffffffff),hregister2);
-                end
-              else
-                begin
-                  if (torddef(resulttype.def).typ=s64bit) and
-                     is_signed(left.resulttype.def) then
-                    begin
-                      emit_reg_reg(A_MOV,S_L,location.register,hregister2);
-                      emit_const_reg(A_SAR,S_L,31,hregister2);
-                    end
-                   else
-                     emit_reg_reg(A_XOR,S_L,hregister2,hregister2);
-                end;
+            { we need to load the value in a register }
+            location_copy(location,left.location);
+            location_force_reg(location,newsize,false);
+          end
+        else
+          begin
+            { no special loading is required, reuse current location }
+            location_copy(location,left.location);
+            location.size:=newsize;
           end;
           end;
       end;
       end;
 
 
@@ -191,68 +128,75 @@ implementation
     procedure ti386typeconvnode.second_int_to_real;
     procedure ti386typeconvnode.second_int_to_real;
 
 
       var
       var
-         r : preference;
+         r : treference;
          hregister : tregister;
          hregister : tregister;
          l1,l2 : tasmlabel;
          l1,l2 : tasmlabel;
 
 
       begin
       begin
+         location_reset(location,LOC_FPUREGISTER,OS_NO);
          { for u32bit a solution is to push $0 and to load a comp }
          { for u32bit a solution is to push $0 and to load a comp }
          { does this first, it destroys maybe EDI }
          { does this first, it destroys maybe EDI }
          hregister:=R_EDI;
          hregister:=R_EDI;
          if torddef(left.resulttype.def).typ=u32bit then
          if torddef(left.resulttype.def).typ=u32bit then
             push_int(0);
             push_int(0);
-         if (left.location.loc=LOC_REGISTER) or
-            (left.location.loc=LOC_CREGISTER) then
-           begin
-              if not (torddef(left.resulttype.def).typ in [u32bit,s32bit,u64bit,s64bit]) then
-                rg.getexplicitregisterint(exprasmlist,R_EDI);
-              case torddef(left.resulttype.def).typ of
-                 s8bit : emit_reg_reg(A_MOVSX,S_BL,left.location.register,R_EDI);
-                 u8bit : emit_reg_reg(A_MOVZX,S_BL,left.location.register,R_EDI);
-                 s16bit : emit_reg_reg(A_MOVSX,S_WL,left.location.register,R_EDI);
-                 u16bit : emit_reg_reg(A_MOVZX,S_WL,left.location.register,R_EDI);
-                 u32bit,s32bit:
-                   hregister:=left.location.register;
-                 u64bit,s64bit:
-                   begin
-                      emit_reg(A_PUSH,S_L,left.location.registerhigh);
-                      hregister:=left.location.registerlow;
-                   end;
-              end;
-              rg.ungetregister(exprasmlist,left.location.register);
-           end
-         else
-           begin
-              r:=newreference(left.location.reference);
-              rg.getexplicitregisterint(exprasmlist,R_EDI);
-              case torddef(left.resulttype.def).typ of
-                 s8bit:
-                   emit_ref_reg(A_MOVSX,S_BL,r,R_EDI);
-                 u8bit:
-                   emit_ref_reg(A_MOVZX,S_BL,r,R_EDI);
-                 s16bit:
-                   emit_ref_reg(A_MOVSX,S_WL,r,R_EDI);
-                 u16bit:
-                   emit_ref_reg(A_MOVZX,S_WL,r,R_EDI);
-                 u32bit,s32bit:
-                   emit_ref_reg(A_MOV,S_L,r,R_EDI);
-                 u64bit,s64bit:
-                   begin
-                      inc(r^.offset,4);
-                      emit_ref_reg(A_MOV,S_L,r,R_EDI);
-                      emit_reg(A_PUSH,S_L,R_EDI);
-                      r:=newreference(left.location.reference);
-                      emit_ref_reg(A_MOV,S_L,r,R_EDI);
-                   end;
+
+         case left.location.loc of
+           LOC_REGISTER,
+           LOC_CREGISTER :
+             begin
+                if not (torddef(left.resulttype.def).typ in [u32bit,s32bit,u64bit,s64bit]) then
+                  rg.getexplicitregisterint(exprasmlist,R_EDI);
+                case torddef(left.resulttype.def).typ of
+                   s8bit : emit_reg_reg(A_MOVSX,S_BL,left.location.register,R_EDI);
+                   u8bit : emit_reg_reg(A_MOVZX,S_BL,left.location.register,R_EDI);
+                   s16bit : emit_reg_reg(A_MOVSX,S_WL,left.location.register,R_EDI);
+                   u16bit : emit_reg_reg(A_MOVZX,S_WL,left.location.register,R_EDI);
+                   u32bit,s32bit:
+                     hregister:=left.location.register;
+                   u64bit,s64bit:
+                     begin
+                        emit_reg(A_PUSH,S_L,left.location.registerhigh);
+                        hregister:=left.location.registerlow;
+                     end;
+                end;
               end;
               end;
-              rg.del_reference(exprasmlist,left.location.reference);
-              tg.ungetiftemp(exprasmlist,left.location.reference);
-           end;
+            LOC_REFERENCE,
+            LOC_CREFERENCE :
+              begin
+                r:=left.location.reference;
+                rg.getexplicitregisterint(exprasmlist,R_EDI);
+                case torddef(left.resulttype.def).typ of
+                   s8bit:
+                     emit_ref_reg(A_MOVSX,S_BL,r,R_EDI);
+                   u8bit:
+                     emit_ref_reg(A_MOVZX,S_BL,r,R_EDI);
+                   s16bit:
+                     emit_ref_reg(A_MOVSX,S_WL,r,R_EDI);
+                   u16bit:
+                     emit_ref_reg(A_MOVZX,S_WL,r,R_EDI);
+                   u32bit,s32bit:
+                     emit_ref_reg(A_MOV,S_L,r,R_EDI);
+                   u64bit,s64bit:
+                     begin
+                        inc(r.offset,4);
+                        emit_ref_reg(A_MOV,S_L,r,R_EDI);
+                        emit_reg(A_PUSH,S_L,R_EDI);
+                        r:=left.location.reference;
+                        emit_ref_reg(A_MOV,S_L,r,R_EDI);
+                     end;
+                end;
+             end;
+           else
+             internalerror(2002032218);
+         end;
+         location_release(exprasmlist,left.location);
+         location_freetemp(exprasmlist,left.location);
+
          { for 64 bit integers, the high dword is already pushed }
          { for 64 bit integers, the high dword is already pushed }
          emit_reg(A_PUSH,S_L,hregister);
          emit_reg(A_PUSH,S_L,hregister);
          if hregister = R_EDI then
          if hregister = R_EDI then
            rg.ungetregisterint(exprasmlist,R_EDI);
            rg.ungetregisterint(exprasmlist,R_EDI);
-         r:=new_reference(R_ESP,0);
+         reference_reset_base(r,R_ESP,0);
          case torddef(left.resulttype.def).typ of
          case torddef(left.resulttype.def).typ of
            u32bit:
            u32bit:
              begin
              begin
@@ -270,14 +214,14 @@ implementation
                 { we load bits 0..62 and then check bit 63:  }
                 { we load bits 0..62 and then check bit 63:  }
                 { if it is 1 then we add $80000000 000000000 }
                 { if it is 1 then we add $80000000 000000000 }
                 { as double                                  }
                 { as double                                  }
-                inc(r^.offset,4);
+                inc(r.offset,4);
                 rg.getexplicitregisterint(exprasmlist,R_EDI);
                 rg.getexplicitregisterint(exprasmlist,R_EDI);
                 emit_ref_reg(A_MOV,S_L,r,R_EDI);
                 emit_ref_reg(A_MOV,S_L,r,R_EDI);
-                r:=new_reference(R_ESP,4);
+                reference_reset_base(r,R_ESP,4);
                 emit_const_ref(A_AND,S_L,$7fffffff,r);
                 emit_const_ref(A_AND,S_L,$7fffffff,r);
                 emit_const_reg(A_TEST,S_L,longint($80000000),R_EDI);
                 emit_const_reg(A_TEST,S_L,longint($80000000),R_EDI);
                 rg.ungetregisterint(exprasmlist,R_EDI);
                 rg.ungetregisterint(exprasmlist,R_EDI);
-                r:=new_reference(R_ESP,0);
+                reference_reset_base(r,R_ESP,0);
                 emit_ref(A_FILD,S_IQ,r);
                 emit_ref(A_FILD,S_IQ,r);
                 getdatalabel(l1);
                 getdatalabel(l1);
                 getlabel(l2);
                 getlabel(l2);
@@ -286,8 +230,7 @@ implementation
                 { I got this constant from a test progtram (FK) }
                 { I got this constant from a test progtram (FK) }
                 Consts.concat(Tai_const.Create_32bit(0));
                 Consts.concat(Tai_const.Create_32bit(0));
                 Consts.concat(Tai_const.Create_32bit(1138753536));
                 Consts.concat(Tai_const.Create_32bit(1138753536));
-                r:=new_reference(R_NO,0);
-                r^.symbol:=l1;
+                reference_reset_symbol(r,l1,0);
                 emit_ref(A_FADD,S_FL,r);
                 emit_ref(A_FADD,S_FL,r);
                 emitlab(l2);
                 emitlab(l2);
                 emit_const_reg(A_ADD,S_L,8,R_ESP);
                 emit_const_reg(A_ADD,S_L,8,R_ESP);
@@ -301,8 +244,6 @@ implementation
              end;
              end;
          end;
          end;
          inc(trgcpu(rg).fpuvaroffset);
          inc(trgcpu(rg).fpuvaroffset);
-         clear_location(location);
-         location.loc:=LOC_FPU;
          location.register:=R_ST;
          location.register:=R_ST;
       end;
       end;
 
 
@@ -310,68 +251,104 @@ implementation
     procedure ti386typeconvnode.second_int_to_bool;
     procedure ti386typeconvnode.second_int_to_bool;
       var
       var
         hregister : tregister;
         hregister : tregister;
-        resflags  : tresflags;
+        leftopsize,
         opsize    : topsize;
         opsize    : topsize;
-        pref      : preference;
+        pref      : treference;
+        hlabel,oldtruelabel,oldfalselabel : tasmlabel;
       begin
       begin
-         clear_location(location);
+         oldtruelabel:=truelabel;
+         oldfalselabel:=falselabel;
+         getlabel(truelabel);
+         getlabel(falselabel);
+         secondpass(left);
+         if codegenerror then
+          exit;
          { byte(boolean) or word(wordbool) or longint(longbool) must }
          { byte(boolean) or word(wordbool) or longint(longbool) must }
          { be accepted for var parameters                            }
          { be accepted for var parameters                            }
          if (nf_explizit in flags) and
          if (nf_explizit in flags) and
             (left.resulttype.def.size=resulttype.def.size) and
             (left.resulttype.def.size=resulttype.def.size) and
-            (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
+            (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
            begin
            begin
-              set_location(location,left.location);
+              location_copy(location,left.location);
+              truelabel:=oldtruelabel;
+              falselabel:=oldfalselabel;
               exit;
               exit;
            end;
            end;
-         location.loc:=LOC_REGISTER;
-         rg.del_location(exprasmlist,left.location);
-         opsize:=def_opsize(left.resulttype.def);
+         location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
+         location_release(exprasmlist,left.location);
+
+         opsize:=def_opsize(resulttype.def);
+         leftopsize:=def_opsize(left.resulttype.def);
          case left.location.loc of
          case left.location.loc of
-            LOC_MEM,LOC_REFERENCE :
+            LOC_CREFERENCE,LOC_REFERENCE :
               begin
               begin
                 if is_64bitint(left.resulttype.def) then
                 if is_64bitint(left.resulttype.def) then
                  begin
                  begin
                    hregister:=rg.getregisterint(exprasmlist);
                    hregister:=rg.getregisterint(exprasmlist);
-                   emit_ref_reg(A_MOV,opsize,
-                     newreference(left.location.reference),hregister);
-                   pref:=newreference(left.location.reference);
-                   inc(pref^.offset,4);
-                   emit_reg_ref(A_OR,opsize,
-                     hregister,pref);
+                   emit_ref_reg(A_MOV,S_L,left.location.reference,hregister);
+                   pref:=left.location.reference;
+                   inc(pref.offset,4);
+                   emit_ref_reg(A_OR,S_L,pref,hregister);
+                 end
+                else
+                 begin
+                   hregister:=def_getreg(left.resulttype.def);
+                   emit_ref_reg(A_MOV,leftopsize,left.location.reference,hregister);
+                 end;
+              end;
+            LOC_CONSTANT :
+              begin
+                if is_64bitint(left.resulttype.def) then
+                 begin
+                   hregister:=def_getreg(left.resulttype.def);
+                   emit_const_reg(A_MOV,S_L,left.location.valuelow,hregister);
+                   emit_const_reg(A_OR,S_L,left.location.valuehigh,hregister);
                  end
                  end
                 else
                 else
                  begin
                  begin
                    hregister:=def_getreg(left.resulttype.def);
                    hregister:=def_getreg(left.resulttype.def);
-                   emit_ref_reg(A_MOV,opsize,
-                     newreference(left.location.reference),hregister);
-                   emit_reg_reg(A_OR,opsize,hregister,hregister);
+                   emit_const_reg(A_MOV,leftopsize,left.location.value,hregister);
                  end;
                  end;
-                resflags:=F_NE;
               end;
               end;
             LOC_FLAGS :
             LOC_FLAGS :
               begin
               begin
-                hregister:=rg.getregisterint(exprasmlist);
-                resflags:=left.location.resflags;
+                hregister:=def_getreg(left.resulttype.def);
+                emit_flag2reg(left.location.resflags,hregister);
               end;
               end;
             LOC_REGISTER,LOC_CREGISTER :
             LOC_REGISTER,LOC_CREGISTER :
               begin
               begin
                 hregister:=left.location.register;
                 hregister:=left.location.register;
-                emit_reg_reg(A_OR,opsize,hregister,hregister);
-                resflags:=F_NE;
+              end;
+            LOC_JUMP :
+              begin
+                hregister:=def_getreg(left.resulttype.def);
+                getlabel(hlabel);
+                cg.a_label(exprasmlist,truelabel);
+                cg.a_load_const_reg(exprasmlist,def_cgsize(left.resulttype.def),1,hregister);
+                cg.a_jmp_cond(exprasmlist,OC_NONE,hlabel);
+                cg.a_label(exprasmlist,falselabel);
+                cg.a_load_const_reg(exprasmlist,def_cgsize(left.resulttype.def),0,hregister);
+                cg.a_label(exprasmlist,hlabel);
               end;
               end;
             else
             else
               internalerror(10062);
               internalerror(10062);
          end;
          end;
-         case resulttype.def.size of
-          1 : location.register:=makereg8(hregister);
-          2 : location.register:=makereg16(hregister);
-          4 : location.register:=makereg32(hregister);
-         else
-          internalerror(10064);
+         emit_reg(A_NEG,leftopsize,hregister);
+         case opsize of
+           S_B :
+             location.register:=makereg8(hregister);
+           S_W :
+             location.register:=makereg16(hregister);
+           S_L :
+             location.register:=makereg32(hregister);
+           else
+            internalerror(10064);
          end;
          end;
-         emit_flag2reg(resflags,location.register);
-      end;
+         emit_reg_reg(A_SBB,opsize,location.register,location.register);
+         emit_reg(A_NEG,opsize,location.register);
+         truelabel:=oldtruelabel;
+         falselabel:=oldfalselabel;
+       end;
 
 
 
 
 {****************************************************************************
 {****************************************************************************
@@ -397,7 +374,7 @@ implementation
            @second_pointer_to_array,
            @second_pointer_to_array,
            @second_int_to_int,
            @second_int_to_int,
            @second_int_to_bool,
            @second_int_to_bool,
-           @second_bool_to_int, { bool_to_bool }
+           @second_bool_to_bool,
            @second_bool_to_int,
            @second_bool_to_int,
            @second_real_to_real,
            @second_real_to_real,
            @second_int_to_real,
            @second_int_to_real,
@@ -436,18 +413,16 @@ implementation
          nillabel : plabel;
          nillabel : plabel;
 {$endif TESTOBJEXT2}
 {$endif TESTOBJEXT2}
       begin
       begin
+        { the boolean routines can be called with LOC_JUMP and
+          call secondpass themselves in the helper }
+        if not(convtype in [tc_bool_2_int,tc_bool_2_bool,tc_int_2_bool]) then
+         begin
+           secondpass(left);
+           if codegenerror then
+            exit;
+         end;
 
 
-         { this isn't good coding, I think tc_bool_2_int, shouldn't be }
-         { type conversion (FK)                                 }
-
-         if not(convtype in [tc_bool_2_int,tc_bool_2_bool]) then
-           begin
-              secondpass(left);
-              set_location(location,left.location);
-              if codegenerror then
-               exit;
-           end;
-         second_call_helper(convtype);
+        second_call_helper(convtype);
 
 
 {$ifdef TESTOBJEXT2}
 {$ifdef TESTOBJEXT2}
                   { Check explicit conversions to objects pointers !! }
                   { Check explicit conversions to objects pointers !! }
@@ -493,7 +468,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.31  2002-03-31 20:26:38  jonas
+  Revision 1.32  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.31  2002/03/31 20:26:38  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 16 - 5
compiler/i386/n386con.pas

@@ -51,11 +51,11 @@ implementation
          result:=nil;
          result:=nil;
          if (value_real=1.0) or (value_real=0.0) then
          if (value_real=1.0) or (value_real=0.0) then
            begin
            begin
-              location.loc:=LOC_FPU;
+              location.loc:=LOC_FPUREGISTER;
               registersfpu:=1;
               registersfpu:=1;
            end
            end
          else
          else
-           location.loc:=LOC_MEM;
+           location.loc:=LOC_CREFERENCE;
       end;
       end;
 
 
     procedure ti386realconstnode.pass_2;
     procedure ti386realconstnode.pass_2;
@@ -64,14 +64,14 @@ implementation
          if (value_real=1.0) then
          if (value_real=1.0) then
            begin
            begin
               emit_none(A_FLD1,S_NO);
               emit_none(A_FLD1,S_NO);
-              location.loc:=LOC_FPU;
+              location.loc:=LOC_FPUREGISTER;
               location.register:=R_ST;
               location.register:=R_ST;
               inc(trgcpu(rg).fpuvaroffset);
               inc(trgcpu(rg).fpuvaroffset);
            end
            end
          else if (value_real=0.0) then
          else if (value_real=0.0) then
            begin
            begin
               emit_none(A_FLDZ,S_NO);
               emit_none(A_FLDZ,S_NO);
-              location.loc:=LOC_FPU;
+              location.loc:=LOC_FPUREGISTER;
               location.register:=R_ST;
               location.register:=R_ST;
               inc(trgcpu(rg).fpuvaroffset);
               inc(trgcpu(rg).fpuvaroffset);
            end
            end
@@ -85,7 +85,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.12  2002-03-31 20:26:38  jonas
+  Revision 1.13  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.12  2002/03/31 20:26:38  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 13 - 3
compiler/i386/n386flw.pas

@@ -440,8 +440,7 @@ implementation
          if assigned(exceptsymtable) then
          if assigned(exceptsymtable) then
            tvarsym(exceptsymtable.symindex.first).address:=ref.offset;
            tvarsym(exceptsymtable.symindex.first).address:=ref.offset;
 
 
-         emit_reg_ref(A_MOV,S_L,
-           R_EAX,newreference(ref));
+         emit_reg_ref(A_MOV,S_L,R_EAX,ref);
          { deallocate eax }
          { deallocate eax }
          exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
          exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
 
 
@@ -737,7 +736,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.20  2002-03-31 20:26:38  jonas
+  Revision 1.21  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.20  2002/03/31 20:26:38  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 113 - 234
compiler/i386/n386inl.pas

@@ -40,10 +40,10 @@ implementation
       globtype,systems,
       globtype,systems,
       cutils,verbose,globals,fmodule,
       cutils,verbose,globals,fmodule,
       symconst,symtype,symdef,aasm,types,
       symconst,symtype,symdef,aasm,types,
-      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,rgobj,rgcpu;
+      cga,tgobj,n386util,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
 
 
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -56,8 +56,7 @@ implementation
          {tfloattype = (s32real,s64real,s80real,s64bit,f16bit,f32bit);}
          {tfloattype = (s32real,s64real,s80real,s64bit,f16bit,f32bit);}
 {        float_name: array[tfloattype] of string[8]=
 {        float_name: array[tfloattype] of string[8]=
            ('S32REAL','S64REAL','S80REAL','S64BIT','F16BIT','F32BIT'); }
            ('S32REAL','S64REAL','S80REAL','S64BIT','F16BIT','F32BIT'); }
-         incdecop:array[in_inc_x..in_dec_x] of tasmop=(A_INC,A_DEC);
-         addsubop:array[in_inc_x..in_dec_x] of tasmop=(A_ADD,A_SUB);
+         addsubop:array[in_inc_x..in_dec_x] of TOpCG=(OP_ADD,OP_SUB);
        var
        var
          opsize : topsize;
          opsize : topsize;
          op,
          op,
@@ -69,19 +68,19 @@ implementation
          hp : tnode;
          hp : tnode;
 
 
       var
       var
-         r : preference;
-         //hp : tcallparanode;
+         href,href2 : treference;
          hp2 : tstringconstnode;
          hp2 : tstringconstnode;
          dummycoll  : tparaitem;
          dummycoll  : tparaitem;
          l : longint;
          l : longint;
          ispushed : boolean;
          ispushed : boolean;
+         hregisterhi,
          hregister : tregister;
          hregister : tregister;
          lengthlab,
          lengthlab,
          otlabel,oflabel{,l1}   : tasmlabel;
          otlabel,oflabel{,l1}   : tasmlabel;
          oldpushedparasize : longint;
          oldpushedparasize : longint;
          def : tdef;
          def : tdef;
-         hr,hr2 : treference;
-
+         cgop : TOpCG;
+         cgsize : TCGSize;
       begin
       begin
       { save & reset pushedparasize }
       { save & reset pushedparasize }
          oldpushedparasize:=pushedparasize;
          oldpushedparasize:=pushedparasize;
@@ -123,6 +122,7 @@ implementation
             in_sizeof_x,
             in_sizeof_x,
             in_typeof_x :
             in_typeof_x :
               begin
               begin
+                 location_reset(location,LOC_REGISTER,OS_ADDR);
                  { for both cases load vmt }
                  { for both cases load vmt }
                  if left.nodetype=typen then
                  if left.nodetype=typen then
                    begin
                    begin
@@ -134,186 +134,97 @@ implementation
                  else
                  else
                    begin
                    begin
                       secondpass(left);
                       secondpass(left);
-                      rg.del_reference(exprasmlist,left.location.reference);
-                      location.loc:=LOC_REGISTER;
+                      location_release(exprasmlist,left.location);
                       location.register:=rg.getregisterint(exprasmlist);
                       location.register:=rg.getregisterint(exprasmlist);
                       { load VMT pointer }
                       { load VMT pointer }
                       inc(left.location.reference.offset,
                       inc(left.location.reference.offset,
                         tobjectdef(left.resulttype.def).vmt_offset);
                         tobjectdef(left.resulttype.def).vmt_offset);
-                      emit_ref_reg(A_MOV,S_L,
-                      newreference(left.location.reference),
-                        location.register);
+                      emit_ref_reg(A_MOV,S_L,left.location.reference,location.register);
                    end;
                    end;
                  { in sizeof load size }
                  { in sizeof load size }
                  if inlinenumber=in_sizeof_x then
                  if inlinenumber=in_sizeof_x then
                    begin
                    begin
-                      new(r);
-                      reset_reference(r^);
-                      r^.base:=location.register;
-                      emit_ref_reg(A_MOV,S_L,r,
-                        location.register);
+                      reference_reset_base(href,location.register,0);
+                      emit_ref_reg(A_MOV,S_L,href,location.register);
                    end;
                    end;
               end;
               end;
             in_length_x :
             in_length_x :
               begin
               begin
                  secondpass(left);
                  secondpass(left);
-                 set_location(location,left.location);
                  { length in ansi strings is at offset -8 }
                  { length in ansi strings is at offset -8 }
                  if is_ansistring(left.resulttype.def) or
                  if is_ansistring(left.resulttype.def) or
                     is_widestring(left.resulttype.def) then
                     is_widestring(left.resulttype.def) then
                   begin
                   begin
                     if left.location.loc<>LOC_REGISTER then
                     if left.location.loc<>LOC_REGISTER then
                      begin
                      begin
-                       rg.del_location(exprasmlist,left.location);
+                       location_release(exprasmlist,left.location);
                        hregister:=rg.getregisterint(exprasmlist);
                        hregister:=rg.getregisterint(exprasmlist);
-                       emit_mov_loc_reg(left.location,hregister);
+                       cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,hregister);
                      end
                      end
                     else
                     else
                      hregister:=left.location.register;
                      hregister:=left.location.register;
-                    reset_reference(hr);
-                    hr.base:=hregister;
-                    hr.offset:=-8;
+                    reference_reset_base(href,hregister,-8);
                     getlabel(lengthlab);
                     getlabel(lengthlab);
                     emit_reg_reg(A_OR,S_L,hregister,hregister);
                     emit_reg_reg(A_OR,S_L,hregister,hregister);
                     emitjmp(C_Z,lengthlab);
                     emitjmp(C_Z,lengthlab);
-                    emit_ref_reg(A_MOV,S_L,newreference(hr),hregister);
+                    emit_ref_reg(A_MOV,S_L,href,hregister);
                     emitlab(lengthlab);
                     emitlab(lengthlab);
-                    location.loc:=LOC_REGISTER;
+                    location_reset(location,LOC_REGISTER,OS_INT);
                     location.register:=hregister;
                     location.register:=hregister;
+                  end
+                 else
+                  begin
+                    location_copy(location,left.location);
+                    location.size:=OS_8;
                   end;
                   end;
               end;
               end;
             in_pred_x,
             in_pred_x,
             in_succ_x:
             in_succ_x:
               begin
               begin
                  secondpass(left);
                  secondpass(left);
-                 if not (cs_check_overflow in aktlocalswitches) then
-                   if inlinenumber=in_pred_x then
-                     asmop:=A_DEC
-                   else
-                     asmop:=A_INC
+                 if inlinenumber=in_pred_x then
+                  cgop:=OP_SUB
                  else
                  else
-                   if inlinenumber=in_pred_x then
-                     asmop:=A_SUB
-                   else
-                     asmop:=A_ADD;
-                 case resulttype.def.size of
-                   8 : opsize:=S_L;
-                   4 : opsize:=S_L;
-                   2 : opsize:=S_W;
-                   1 : opsize:=S_B;
-                 else
-                   internalerror(10080);
-                 end;
-                 location.loc:=LOC_REGISTER;
-                 if resulttype.def.size=8 then
-                   begin
-                      if left.location.loc<>LOC_REGISTER then
-                        begin
-                           if left.location.loc=LOC_CREGISTER then
-                             begin
-                                location.registerlow:=rg.getregisterint(exprasmlist);
-                                location.registerhigh:=rg.getregisterint(exprasmlist);
-                                emit_reg_reg(A_MOV,opsize,left.location.registerlow,
-                                  location.registerlow);
-                                emit_reg_reg(A_MOV,opsize,left.location.registerhigh,
-                                  location.registerhigh);
-                             end
-                           else
-                             begin
-                                rg.del_reference(exprasmlist,left.location.reference);
-                                location.registerlow:=rg.getregisterint(exprasmlist);
-                                location.registerhigh:=rg.getregisterint(exprasmlist);
-                                emit_ref_reg(A_MOV,opsize,newreference(left.location.reference),
-                                  location.registerlow);
-                                r:=newreference(left.location.reference);
-                                inc(r^.offset,4);
-                                emit_ref_reg(A_MOV,opsize,r,
-                                  location.registerhigh);
-                             end;
-                        end
-                      else
-                        begin
-                           location.registerhigh:=left.location.registerhigh;
-                           location.registerlow:=left.location.registerlow;
-                        end;
-                      if inlinenumber=in_succ_x then
-                        begin
-                           emit_const_reg(A_ADD,opsize,1,
-                             location.registerlow);
-                           emit_const_reg(A_ADC,opsize,0,
-                             location.registerhigh);
-                        end
-                      else
-                        begin
-                           emit_const_reg(A_SUB,opsize,1,
-                             location.registerlow);
-                           emit_const_reg(A_SBB,opsize,0,
-                             location.registerhigh);
-                        end;
-                   end
+                  cgop:=OP_ADD;
+                 cgsize:=def_cgsize(resulttype.def);
+
+                 { we need a value in a register }
+                 location_copy(location,left.location);
+                 location_force_reg(location,cgsize,false);
+
+                 if cgsize in [OS_64,OS_S64] then
+                  tcg64f32(cg).a_op64_const_reg(exprasmlist,cgop,1,0,
+                      location.registerlow,location.registerhigh)
                  else
                  else
-                   begin
-                      if left.location.loc<>LOC_REGISTER then
-                        begin
-                           { first, we've to release the source location ... }
-                           if left.location.loc in [LOC_MEM,LOC_REFERENCE] then
-                             rg.del_reference(exprasmlist,left.location.reference);
-
-                           location.register:=rg.getregisterint(exprasmlist);
-                           if (resulttype.def.size=2) then
-                             location.register:=reg32toreg16(location.register);
-                           if (resulttype.def.size=1) then
-                             location.register:=reg32toreg8(location.register);
-                           if left.location.loc=LOC_CREGISTER then
-                             emit_reg_reg(A_MOV,opsize,left.location.register,
-                               location.register)
-                           else
-                           if left.location.loc=LOC_FLAGS then
-                             emit_flag2reg(left.location.resflags,location.register)
-                           else
-                             emit_ref_reg(A_MOV,opsize,newreference(left.location.reference),
-                               location.register);
-                        end
-                      else location.register:=left.location.register;
-                      if not (cs_check_overflow in aktlocalswitches) then
-                        emit_reg(asmop,opsize,
-                        location.register)
-                      else
-                        emit_const_reg(asmop,opsize,1,
-                        location.register);
-                   end;
+                  cg.a_op_const_reg(exprasmlist,cgop,1,location.register);
+
                  emitoverflowcheck(self);
                  emitoverflowcheck(self);
                  cg.g_rangecheck(exprasmlist,self,resulttype.def);
                  cg.g_rangecheck(exprasmlist,self,resulttype.def);
               end;
               end;
             in_dec_x,
             in_dec_x,
             in_inc_x :
             in_inc_x :
               begin
               begin
-              { set defaults }
-                addvalue:=1;
+                { set defaults }
                 addconstant:=true;
                 addconstant:=true;
-              { load first parameter, must be a reference }
+                { load first parameter, must be a reference }
                 secondpass(tcallparanode(left).left);
                 secondpass(tcallparanode(left).left);
+                cgsize:=def_cgsize(tcallparanode(left).left.resulttype.def);
+                { get addvalue }
                 case tcallparanode(left).left.resulttype.def.deftype of
                 case tcallparanode(left).left.resulttype.def.deftype of
                   orddef,
                   orddef,
-                 enumdef : begin
-                             case tcallparanode(left).left.resulttype.def.size of
-                              1 : opsize:=S_B;
-                              2 : opsize:=S_W;
-                              4 : opsize:=S_L;
-                              8 : opsize:=S_L;
-                             end;
-                           end;
-              pointerdef : begin
-                             opsize:=S_L;
-                             if is_void(tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def) then
-                              addvalue:=1
-                             else
-                              addvalue:=tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def.size;
-                           end;
-                else
-                 internalerror(10081);
+                  enumdef :
+                    addvalue:=1;
+                  pointerdef :
+                    begin
+                      if is_void(tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def) then
+                       addvalue:=1
+                      else
+                       addvalue:=tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def.size;
+                    end;
+                  else
+                    internalerror(10081);
                 end;
                 end;
-              { 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,
                    ispushed:=maybe_push(tcallparanode(tcallparanode(left).right).left.registers32,
@@ -321,76 +232,39 @@ implementation
                    secondpass(tcallparanode(tcallparanode(left).right).left);
                    secondpass(tcallparanode(tcallparanode(left).right).left);
                    if ispushed then
                    if ispushed then
                      restore(tcallparanode(left).left,false);
                      restore(tcallparanode(left).left,false);
-                 { 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)
                    else
                    else
                     begin
                     begin
-                      case tcallparanode(tcallparanode(left).right).left.location.loc of
-                   LOC_REGISTER,
-                  LOC_CREGISTER : hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
-                        LOC_MEM,
-                  LOC_REFERENCE : begin
-                                    rg.del_reference(exprasmlist,tcallparanode(tcallparanode(left).right).left.location.reference);
-                                    hregister:=rg.getregisterint(exprasmlist);
-                                    emit_ref_reg(A_MOV,S_L,
-                                      newreference(tcallparanode(tcallparanode(left).right).left.location.reference),hregister);
-                                  end;
-                       else
-                        internalerror(10082);
-                       end;
-                    { insert multiply with addvalue if its >1 }
+                      location_force_reg(tcallparanode(tcallparanode(left).right).left.location,cgsize,false);
+                      hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
+                      hregisterhi:=tcallparanode(tcallparanode(left).right).left.location.registerhigh;
+                      { insert multiply with addvalue if its >1 }
                       if addvalue>1 then
                       if addvalue>1 then
-                       emit_const_reg(A_IMUL,opsize,
-                         addvalue,hregister);
+                        cg.a_op_const_reg(exprasmlist,OP_IMUL,addvalue,hregister);
                       addconstant:=false;
                       addconstant:=false;
                     end;
                     end;
                  end;
                  end;
               { write the add instruction }
               { write the add instruction }
                 if addconstant then
                 if addconstant then
                  begin
                  begin
-                   if (addvalue=1) and not(cs_check_overflow in aktlocalswitches) then
-                     begin
-                        if tcallparanode(left).left.location.loc=LOC_CREGISTER then
-                          emit_reg(incdecop[inlinenumber],opsize,
-                            tcallparanode(left).left.location.register)
-                        else
-                          emit_ref(incdecop[inlinenumber],opsize,
-                            newreference(tcallparanode(left).left.location.reference))
-                     end
+                   if cgsize in [OS_64,OS_S64] then
+                    tcg64f32(cg).a_op64_const_loc(exprasmlist,addsubop[inlinenumber],
+                       addvalue,0,tcallparanode(left).left.location)
                    else
                    else
-                     begin
-                        if tcallparanode(left).left.location.loc=LOC_CREGISTER then
-                          emit_const_reg(addsubop[inlinenumber],opsize,
-                            addvalue,tcallparanode(left).left.location.register)
-                        else
-                          emit_const_ref(addsubop[inlinenumber],opsize,
-                            addvalue,newreference(tcallparanode(left).left.location.reference));
-                     end
+                    cg.a_op_const_loc(exprasmlist,addsubop[inlinenumber],cgsize,
+                       addvalue,tcallparanode(left).left.location);
                  end
                  end
                 else
                 else
                  begin
                  begin
-                    { BUG HERE : detected with nasm :
-                      hregister is allways 32 bit
-                      it should be converted to 16 or 8 bit depending on op_size  PM }
-                    { still not perfect :
-                      if hregister is already a 16 bit reg ?? PM }
-                    { makeregXX is the solution (FK) }
-                    case opsize of
-                      S_B : hregister:=makereg8(hregister);
-                      S_W : hregister:=makereg16(hregister);
-                    end;
-                    if tcallparanode(left).left.location.loc=LOC_CREGISTER then
-                      emit_reg_reg(addsubop[inlinenumber],opsize,
-                        hregister,tcallparanode(left).left.location.register)
-                    else
-                      emit_reg_ref(addsubop[inlinenumber],opsize,
-                        hregister,newreference(tcallparanode(left).left.location.reference));
-                    case opsize of
-                      S_B : hregister:=reg8toreg32(hregister);
-                      S_W : hregister:=reg16toreg32(hregister);
-                    end;
-                   rg.ungetregisterint(exprasmlist,hregister);
+                   if cgsize in [OS_64,OS_S64] then
+                    tcg64f32(cg).a_op64_reg_loc(exprasmlist,addsubop[inlinenumber],
+                       hregister,hregisterhi,tcallparanode(left).left.location)
+                   else
+                    cg.a_op_reg_loc(exprasmlist,addsubop[inlinenumber],cgsize,
+                       hregister,tcallparanode(left).left.location);
+                   location_release(exprasmlist,tcallparanode(tcallparanode(left).right).left.location);
                  end;
                  end;
                 emitoverflowcheck(tcallparanode(left).left);
                 emitoverflowcheck(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);
@@ -398,11 +272,10 @@ implementation
 
 
             in_typeinfo_x:
             in_typeinfo_x:
                begin
                begin
+                  location_reset(location,LOC_REGISTER,OS_ADDR);
                   location.register:=rg.getregisterint(exprasmlist);
                   location.register:=rg.getregisterint(exprasmlist);
-                  new(r);
-                  reset_reference(r^);
-                  r^.symbol:=tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(fullrtti);
-                  emit_ref_reg(A_LEA,S_L,r,location.register);
+                  reference_reset_symbol(href,tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(fullrtti),0);
+                  emit_ref_reg(A_LEA,S_L,href,location.register);
                end;
                end;
 
 
              in_finalize_x:
              in_finalize_x:
@@ -419,9 +292,8 @@ implementation
                     end;
                     end;
 
 
                   { generate a reference }
                   { generate a reference }
-                  reset_reference(hr);
-                  hr.symbol:=tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(initrtti);
-                  emitpushreferenceaddr(hr);
+                  reference_reset_symbol(href,tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(initrtti),0);
+                  emitpushreferenceaddr(href);
 
 
                   { data to finalize }
                   { data to finalize }
                   secondpass(tcallparanode(left).left);
                   secondpass(tcallparanode(left).left);
@@ -439,20 +311,18 @@ implementation
             in_assigned_x :
             in_assigned_x :
               begin
               begin
                  secondpass(tcallparanode(left).left);
                  secondpass(tcallparanode(left).left);
-                 location.loc:=LOC_FLAGS;
+                 location_release(exprasmlist,tcallparanode(left).left.location);
                  if (tcallparanode(left).left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
                  if (tcallparanode(left).left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
                    begin
                    begin
                       emit_reg_reg(A_OR,S_L,
                       emit_reg_reg(A_OR,S_L,
                         tcallparanode(left).left.location.register,
                         tcallparanode(left).left.location.register,
                         tcallparanode(left).left.location.register);
                         tcallparanode(left).left.location.register);
-                      rg.ungetregisterint(exprasmlist,tcallparanode(left).left.location.register);
                    end
                    end
                  else
                  else
                    begin
                    begin
-                      emit_const_ref(A_CMP,S_L,0,
-                        newreference(tcallparanode(left).left.location.reference));
-                      rg.del_reference(exprasmlist,tcallparanode(left).left.location.reference);
+                      emit_const_ref(A_CMP,S_L,0,tcallparanode(left).left.location.reference);
                    end;
                    end;
+                 location_reset(location,LOC_FLAGS,OS_NO);
                  location.resflags:=F_NE;
                  location.resflags:=F_NE;
               end;
               end;
             in_setlength_x:
             in_setlength_x:
@@ -471,17 +341,17 @@ implementation
                   if is_dynamic_array(def) then
                   if is_dynamic_array(def) then
                     begin
                     begin
                        { get temp. space }
                        { get temp. space }
-                       tg.gettempofsizereference(exprasmlist,l*4,hr);
+                       tg.gettempofsizereference(exprasmlist,l*4,href);
                        { keep data start }
                        { keep data start }
-                       hr2:=hr;
+                       href2:=href;
                        { copy dimensions }
                        { copy dimensions }
                        hp:=left;
                        hp:=left;
                        while assigned(tcallparanode(hp).right) do
                        while assigned(tcallparanode(hp).right) do
                          begin
                          begin
                             secondpass(tcallparanode(hp).left);
                             secondpass(tcallparanode(hp).left);
-                            emit_mov_loc_ref(tcallparanode(hp).left.location,hr,
-                              S_L,true);
-                            inc(hr.offset,4);
+                            location_release(exprasmlist,tcallparanode(hp).left.location);
+                            cg.a_load_loc_ref(exprasmlist,OS_INT,tcallparanode(hp).left.location,href);
+                            inc(href.offset,4);
                             hp:=tcallparanode(hp).right;
                             hp:=tcallparanode(hp).right;
                          end;
                          end;
                     end
                     end
@@ -507,15 +377,14 @@ implementation
                   else secondpass(tcallparanode(hp).left);
                   else secondpass(tcallparanode(hp).left);
                   if is_dynamic_array(def) then
                   if is_dynamic_array(def) then
                     begin
                     begin
-                       emitpushreferenceaddr(hr2);
+                       emitpushreferenceaddr(href2);
                        push_int(l);
                        push_int(l);
-                       reset_reference(hr2);
-                       hr2.symbol:=tstoreddef(def).get_rtti_label(initrtti);
-                       emitpushreferenceaddr(hr2);
+                       reference_reset_symbol(href2,tstoreddef(def).get_rtti_label(initrtti),0);
+                       emitpushreferenceaddr(href2);
                        emitpushreferenceaddr(tcallparanode(hp).left.location.reference);
                        emitpushreferenceaddr(tcallparanode(hp).left.location.reference);
                        rg.saveregvars(exprasmlist,all_registers);
                        rg.saveregvars(exprasmlist,all_registers);
                        emitcall('FPC_DYNARR_SETLENGTH');
                        emitcall('FPC_DYNARR_SETLENGTH');
-                       tg.ungetiftemp(exprasmlist,hr);
+                       tg.ungetiftemp(exprasmlist,href);
                     end
                     end
                   else
                   else
                     { must be string }
                     { must be string }
@@ -546,6 +415,7 @@ implementation
             in_include_x_y,
             in_include_x_y,
             in_exclude_x_y:
             in_exclude_x_y:
               begin
               begin
+                 location_copy(location,left.location);
                  secondpass(tcallparanode(left).left);
                  secondpass(tcallparanode(left).left);
                  if tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn then
                  if tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn then
                    begin
                    begin
@@ -564,9 +434,8 @@ implementation
                         begin
                         begin
                            inc(tcallparanode(left).left.location.reference.offset,
                            inc(tcallparanode(left).left.location.reference.offset,
                              (tordconstnode(tcallparanode(tcallparanode(left).right).left).value div 32)*4);
                              (tordconstnode(tcallparanode(tcallparanode(left).right).left).value div 32)*4);
-                           emit_const_ref(asmop,S_L,
-                             l,newreference(tcallparanode(left).left.location.reference));
-                           rg.del_reference(exprasmlist,tcallparanode(left).left.location.reference);
+                           emit_const_ref(asmop,S_L,l,tcallparanode(left).left.location.reference);
+                           location_release(exprasmlist,tcallparanode(left).left.location);
                         end
                         end
                       else
                       else
                         { LOC_CREGISTER }
                         { LOC_CREGISTER }
@@ -613,25 +482,22 @@ implementation
                             op:=A_MOV
                             op:=A_MOV
                            else
                            else
                             op:=A_MOVZX;
                             op:=A_MOVZX;
-                           emit_ref_reg(op,opsize,
-                             newreference(
-                               tcallparanode(tcallparanode(left).right).left.location.reference),R_EDI);
+                           emit_ref_reg(op,opsize,tcallparanode(tcallparanode(left).right).left.location.reference,R_EDI);
                         end;
                         end;
                       if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
                       if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
-                        emit_reg_ref(asmop,S_L,hregister,
-                          newreference(tcallparanode(left).left.location.reference))
+                        emit_reg_ref(asmop,S_L,hregister,tcallparanode(left).left.location.reference)
                       else
                       else
-                        emit_reg_reg(asmop,S_L,hregister,
-                          tcallparanode(left).left.location.register);
+                        emit_reg_reg(asmop,S_L,hregister,tcallparanode(left).left.location.register);
                       if hregister = R_EDI then
                       if hregister = R_EDI then
                         rg.ungetregisterint(exprasmlist,R_EDI);
                         rg.ungetregisterint(exprasmlist,R_EDI);
                    end;
                    end;
               end;
               end;
             in_pi:
             in_pi:
               begin
               begin
+                location_reset(location,LOC_FPUREGISTER,OS_NO);
                 emit_none(A_FLDPI,S_NO);
                 emit_none(A_FLDPI,S_NO);
                 inc(trgcpu(rg).fpuvaroffset);
                 inc(trgcpu(rg).fpuvaroffset);
-                location.register := R_ST;
+                location.register:=R_ST;
               end;
               end;
             in_sin_extended,
             in_sin_extended,
             in_arctan_extended,
             in_arctan_extended,
@@ -641,22 +507,23 @@ implementation
             in_ln_extended,
             in_ln_extended,
             in_cos_extended:
             in_cos_extended:
               begin
               begin
-                 secondpass(left);
+                 location_reset(location,LOC_FPUREGISTER,OS_NO);
                  location.register := R_ST;
                  location.register := R_ST;
+                 secondpass(left);
                  case left.location.loc of
                  case left.location.loc of
-                    LOC_FPU:
+                    LOC_FPUREGISTER:
                       ;
                       ;
                     LOC_CFPUREGISTER:
                     LOC_CFPUREGISTER:
                       begin
                       begin
                          cg.a_loadfpu_reg_reg(exprasmlist,
                          cg.a_loadfpu_reg_reg(exprasmlist,
                            left.location.register,location.register);
                            left.location.register,location.register);
                       end;
                       end;
-                    LOC_REFERENCE,LOC_MEM:
+                    LOC_REFERENCE,LOC_CREFERENCE:
                       begin
                       begin
                          cg.a_loadfpu_ref_reg(exprasmlist,
                          cg.a_loadfpu_ref_reg(exprasmlist,
                            def_cgsize(left.resulttype.def),
                            def_cgsize(left.resulttype.def),
                            left.location.reference,location.register);
                            left.location.reference,location.register);
-                         rg.del_reference(exprasmlist,left.location.reference);
+                         location_release(exprasmlist,left.location);
                       end
                       end
                     else
                     else
                       internalerror(309991);
                       internalerror(309991);
@@ -707,6 +574,7 @@ implementation
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
             in_mmx_pcmpeqb..in_mmx_pcmpgtw:
             in_mmx_pcmpeqb..in_mmx_pcmpgtw:
               begin
               begin
+                 location_reset(location,LOC_MMXREGISTER,OS_NO);
                  if left.location.loc=LOC_REGISTER then
                  if left.location.loc=LOC_REGISTER then
                    begin
                    begin
                       {!!!!!!!}
                       {!!!!!!!}
@@ -732,7 +600,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.33  2002-03-31 20:26:39  jonas
+  Revision 1.34  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.33  2002/03/31 20:26:39  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

File diff ditekan karena terlalu besar
+ 370 - 431
compiler/i386/n386ld.pas


+ 257 - 402
compiler/i386/n386mat.pas

@@ -53,10 +53,10 @@ implementation
       globtype,systems,
       globtype,systems,
       cutils,verbose,globals,
       cutils,verbose,globals,
       symconst,symdef,aasm,types,
       symconst,symdef,aasm,types,
-      cgbase,pass_1,pass_2,
+      cginfo,cgbase,pass_1,pass_2,
       ncon,
       ncon,
       cpubase,
       cpubase,
-      cga,tgobj,n386util,ncgutil,cgobj,rgobj,rgcpu;
+      cga,tgobj,n386util,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
 
 
 {*****************************************************************************
 {*****************************************************************************
                              TI386MODDIVNODE
                              TI386MODDIVNODE
@@ -72,11 +72,15 @@ implementation
       begin
       begin
          shrdiv := false;
          shrdiv := false;
          secondpass(left);
          secondpass(left);
+         if codegenerror then
+          exit;
          pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
          pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
          secondpass(right);
          secondpass(right);
          if pushed then
          if pushed then
            restore(left,is_64bitint(left.resulttype.def));
            restore(left,is_64bitint(left.resulttype.def));
-         set_location(location,left.location);
+         if codegenerror then
+          exit;
+         location_copy(location,left.location);
 
 
          if is_64bitint(resulttype.def) then
          if is_64bitint(resulttype.def) then
            begin
            begin
@@ -86,189 +90,164 @@ implementation
          else
          else
            begin
            begin
               { put numerator in register }
               { put numerator in register }
-              if left.location.loc<>LOC_REGISTER then
-                begin
-                   if left.location.loc=LOC_CREGISTER then
-                     begin
-                       hreg1:=rg.getregisterint(exprasmlist);
-                       emit_reg_reg(A_MOV,S_L,left.location.register,hreg1);
-                     end
-                   else
-                     begin
-                       rg.del_reference(exprasmlist,left.location.reference);
-                       hreg1:=rg.getregisterint(exprasmlist);
-                       emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
-                         hreg1);
-                     end;
-                   clear_location(left.location);
-                   left.location.loc:=LOC_REGISTER;
-                   left.location.register:=hreg1;
-                end
-              else hreg1:=left.location.register;
-
-                if (nodetype=divn) and (right.nodetype=ordconstn) and
-                    ispowerof2(tordconstnode(right).value,power) then
-                  Begin
-                    shrdiv := true;
-                    {for signed numbers, the numerator must be adjusted before the
-                     shift instruction, but not wih unsigned numbers! Otherwise,
-                     "Cardinal($ffffffff) div 16" overflows! (JM)}
-                    If is_signed(left.resulttype.def) Then
-                      Begin
-                        If (aktOptProcessor <> class386) and
-                           not(CS_LittleSize in aktglobalswitches) then
-                        { use a sequence without jumps, saw this in
-                          comp.compilers (JM) }
-                          begin
+              location_force_reg(left.location,OS_INT,false);
+              hreg1:=left.location.register;
+
+              if (nodetype=divn) and
+                 (right.nodetype=ordconstn) and
+                 ispowerof2(tordconstnode(right).value,power) then
+                Begin
+                  shrdiv := true;
+                  { for signed numbers, the numerator must be adjusted before the
+                    shift instruction, but not wih unsigned numbers! Otherwise,
+                    "Cardinal($ffffffff) div 16" overflows! (JM) }
+                  If is_signed(left.resulttype.def) Then
+                    Begin
+                      If (aktOptProcessor <> class386) and
+                         not(CS_LittleSize in aktglobalswitches) then
+                         { use a sequence without jumps, saw this in
+                           comp.compilers (JM) }
+                        begin
                           { no jumps, but more operations }
                           { no jumps, but more operations }
-                            if (hreg1 = R_EAX) and
-                               (R_EDX in rg.unusedregsint) then
-                              begin
-                                hreg2 := rg.getexplicitregisterint(exprasmlist,R_EDX);
-                                emit_none(A_CDQ,S_NO);
-                              end
-                            else
-                              begin
-                                rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                hreg2 := R_EDI;
-                                emit_reg_reg(A_MOV,S_L,hreg1,R_EDI);
+                          if (hreg1 = R_EAX) and
+                             (R_EDX in rg.unusedregsint) then
+                            begin
+                              hreg2 := rg.getexplicitregisterint(exprasmlist,R_EDX);
+                              emit_none(A_CDQ,S_NO);
+                            end
+                          else
+                            begin
+                              rg.getexplicitregisterint(exprasmlist,R_EDI);
+                              hreg2 := R_EDI;
+                              emit_reg_reg(A_MOV,S_L,hreg1,R_EDI);
                               { if the left value is signed, R_EDI := $ffffffff,
                               { if the left value is signed, R_EDI := $ffffffff,
                                 otherwise 0 }
                                 otherwise 0 }
-                                emit_const_reg(A_SAR,S_L,31,R_EDI);
-                            { if signed, R_EDI := right value-1, otherwise 0 }
-                              end;
-                            emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
+                              emit_const_reg(A_SAR,S_L,31,R_EDI);
+                              { if signed, R_EDI := right value-1, otherwise 0 }
+                            end;
+                          emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
                           { add to the left value }
                           { add to the left value }
-                            emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
+                          emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
                           { release EDX if we used it }
                           { release EDX if we used it }
                           { also releas EDI }
                           { also releas EDI }
                           rg.ungetregisterint(exprasmlist,hreg2);
                           rg.ungetregisterint(exprasmlist,hreg2);
                           { do the shift }
                           { do the shift }
-                            emit_const_reg(A_SAR,S_L,power,hreg1);
-                          end
-                        else
-                          begin
+                          emit_const_reg(A_SAR,S_L,power,hreg1);
+                        end
+                      else
+                        begin
                           { a jump, but less operations }
                           { a jump, but less operations }
-                            emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
-                            getlabel(hl);
-                            emitjmp(C_NS,hl);
-                            if power=1 then
-                              emit_reg(A_INC,S_L,hreg1)
+                          emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
+                          getlabel(hl);
+                          emitjmp(C_NS,hl);
+                          if power=1 then
+                            emit_reg(A_INC,S_L,hreg1)
+                          else
+                            emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
+                          emitlab(hl);
+                          emit_const_reg(A_SAR,S_L,power,hreg1);
+                        end
+                    End
+                  Else
+                    emit_const_reg(A_SHR,S_L,power,hreg1);
+                End
+              else
+                begin
+                  { bring denominator to EDI }
+                  { EDI is always free, it's }
+                  { only used for temporary  }
+                  { purposes              }
+                  rg.getexplicitregisterint(exprasmlist,R_EDI);
+                  if right.location.loc<>LOC_CREGISTER then
+                   location_release(exprasmlist,right.location);
+                  cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,R_EDI);
+                  popedx:=false;
+                  popeax:=false;
+                  if hreg1=R_EDX then
+                    begin
+                      if not(R_EAX in rg.unusedregsint) then
+                         begin
+                            emit_reg(A_PUSH,S_L,R_EAX);
+                            popeax:=true;
+                         end
+                       else
+                         rg.getexplicitregisterint(exprasmlist,R_EAX);
+                      emit_reg_reg(A_MOV,S_L,R_EDX,R_EAX);
+                    end
+                  else
+                    begin
+                       if not(R_EDX in rg.unusedregsint) then
+                         begin
+                            emit_reg(A_PUSH,S_L,R_EDX);
+                            popedx:=true;
+                         end
+                       else
+                         rg.getexplicitregisterint(exprasmlist,R_EDX);
+                       if hreg1<>R_EAX then
+                         begin
+                            if not(R_EAX in rg.unusedregsint) then
+                              begin
+                                 emit_reg(A_PUSH,S_L,R_EAX);
+                                 popeax:=true;
+                              end
                             else
                             else
-                              emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
-                            emitlab(hl);
-                            emit_const_reg(A_SAR,S_L,power,hreg1);
-                          end
-                      End
-                    Else
-                      emit_const_reg(A_SHR,S_L,power,hreg1);
-                  End
-                else
-                  begin
-                      { bring denominator to EDI }
-                      { EDI is always free, it's }
-                      { only used for temporary  }
-                      { purposes              }
-                   rg.getexplicitregisterint(exprasmlist,R_EDI);
-                   if (right.location.loc<>LOC_REGISTER) and
-                      (right.location.loc<>LOC_CREGISTER) then
-                     begin
-                       rg.del_reference(exprasmlist,right.location.reference);
-                       left.location.loc:=LOC_REGISTER;
-                       emit_ref_reg(A_MOV,S_L,newreference(right.location.reference),R_EDI);
-                     end
-                   else
-                     begin
-                        emit_reg_reg(A_MOV,S_L,right.location.register,R_EDI);
-                        rg.ungetregisterint(exprasmlist,right.location.register);
-                     end;
-                   popedx:=false;
-                   popeax:=false;
-                   if hreg1=R_EDX then
-                     begin
-                       if not(R_EAX in rg.unusedregsint) then
-                          begin
-                             emit_reg(A_PUSH,S_L,R_EAX);
-                             popeax:=true;
-                          end
-                        else
-                          rg.getexplicitregisterint(exprasmlist,R_EAX);
-                       emit_reg_reg(A_MOV,S_L,R_EDX,R_EAX);
-                     end
-                   else
-                     begin
-                        if not(R_EDX in rg.unusedregsint) then
-                          begin
-                             emit_reg(A_PUSH,S_L,R_EDX);
-                             popedx:=true;
-                          end
-                        else
-                          rg.getexplicitregisterint(exprasmlist,R_EDX);
-                        if hreg1<>R_EAX then
-                          begin
-                             if not(R_EAX in rg.unusedregsint) then
-                               begin
-                                  emit_reg(A_PUSH,S_L,R_EAX);
-                                  popeax:=true;
-                               end
-                             else
-                               rg.getexplicitregisterint(exprasmlist,R_EAX);
-                             emit_reg_reg(A_MOV,S_L,hreg1,R_EAX);
-                          end;
-                     end;
-                   { sign extension depends on the left type }
-                   if torddef(left.resulttype.def).typ=u32bit then
-                      emit_reg_reg(A_XOR,S_L,R_EDX,R_EDX)
-                   else
-                      emit_none(A_CDQ,S_NO);
-
-                   { division depends on the right type }
-                   if torddef(right.resulttype.def).typ=u32bit then
-                     emit_reg(A_DIV,S_L,R_EDI)
-                   else
-                     emit_reg(A_IDIV,S_L,R_EDI);
-                   rg.ungetregisterint(exprasmlist,R_EDI);
-                   if nodetype=divn then
-                     begin
-                        if not popedx and (hreg1 <> R_EDX) then
-                          rg.ungetregister(exprasmlist,R_EDX);
-                        { if result register is busy then copy }
-                        if popeax then
-                          begin
-                             if hreg1=R_EAX then
-                               internalerror(112);
-                             emit_reg_reg(A_MOV,S_L,R_EAX,hreg1)
-                          end
-                        else
-                          if hreg1<>R_EAX then
-                            Begin
-                              rg.ungetregisterint(exprasmlist,hreg1);
-                              { no need to allocate eax, that's already done before }
-                              { the div (JM)                                        }
-                              hreg1 := R_EAX;
-                            end;
-                     end
-                   else
-                     begin
-                       if not popeax and (hreg1 <> R_EAX)then
-                         rg.ungetregister(exprasmlist,R_EAX);
-                       if popedx then
-                        {the mod was done by an (i)div (so the result is now in
-                         edx), but edx was occupied prior to the division, so
-                         move the result into a safe place (JM)}
-                         emit_reg_reg(A_MOV,S_L,R_EDX,hreg1)
+                              rg.getexplicitregisterint(exprasmlist,R_EAX);
+                            emit_reg_reg(A_MOV,S_L,hreg1,R_EAX);
+                         end;
+                    end;
+                  { sign extension depends on the left type }
+                  if torddef(left.resulttype.def).typ=u32bit then
+                     emit_reg_reg(A_XOR,S_L,R_EDX,R_EDX)
+                  else
+                     emit_none(A_CDQ,S_NO);
+
+                  { division depends on the right type }
+                  if torddef(right.resulttype.def).typ=u32bit then
+                    emit_reg(A_DIV,S_L,R_EDI)
+                  else
+                    emit_reg(A_IDIV,S_L,R_EDI);
+                  rg.ungetregisterint(exprasmlist,R_EDI);
+                  if nodetype=divn then
+                    begin
+                       if not popedx and (hreg1 <> R_EDX) then
+                         rg.ungetregister(exprasmlist,R_EDX);
+                       { if result register is busy then copy }
+                       if popeax then
+                         begin
+                            if hreg1=R_EAX then
+                              internalerror(112);
+                            emit_reg_reg(A_MOV,S_L,R_EAX,hreg1)
+                         end
                        else
                        else
-                         Begin
-                           if hreg1 <> R_EDX then
+                         if hreg1<>R_EAX then
+                           Begin
                              rg.ungetregisterint(exprasmlist,hreg1);
                              rg.ungetregisterint(exprasmlist,hreg1);
-                           hreg1 := R_EDX
-                         End;
-                     end;
-                   if popeax then
-                     emit_reg(A_POP,S_L,R_EAX);
-                   if popedx then
-                     emit_reg(A_POP,S_L,R_EDX);
-                  end;
+                             { no need to allocate eax, that's already done before }
+                             { the div (JM)                                        }
+                             hreg1 := R_EAX;
+                           end;
+                    end
+                  else
+                    begin
+                      if not popeax and (hreg1 <> R_EAX)then
+                        rg.ungetregister(exprasmlist,R_EAX);
+                      if popedx then
+                       {the mod was done by an (i)div (so the result is now in
+                        edx), but edx was occupied prior to the division, so
+                        move the result into a safe place (JM)}
+                        emit_reg_reg(A_MOV,S_L,R_EDX,hreg1)
+                      else
+                        Begin
+                          if hreg1 <> R_EDX then
+                            rg.ungetregisterint(exprasmlist,hreg1);
+                          hreg1 := R_EDX
+                        End;
+                    end;
+                  if popeax then
+                    emit_reg(A_POP,S_L,R_EAX);
+                  if popedx then
+                    emit_reg(A_POP,S_L,R_EDX);
+                end;
               If not(shrdiv) then
               If not(shrdiv) then
                { shrdiv only use hreg1 (which is already in usedinproc,   }
                { shrdiv only use hreg1 (which is already in usedinproc,   }
                { since it was acquired with getregister), the others also }
                { since it was acquired with getregister), the others also }
@@ -277,8 +256,7 @@ implementation
                   include(rg.usedinproc,R_EAX);
                   include(rg.usedinproc,R_EAX);
                   include(rg.usedinproc,R_EDX);
                   include(rg.usedinproc,R_EDX);
                 End;
                 End;
-              clear_location(location);
-              location.loc:=LOC_REGISTER;
+              location_reset(location,LOC_REGISTER,OS_32);
               location.register:=hreg1;
               location.register:=hreg1;
            end;
            end;
       end;
       end;
@@ -290,7 +268,7 @@ implementation
 
 
     procedure ti386shlshrnode.pass_2;
     procedure ti386shlshrnode.pass_2;
       var
       var
-         hregister1,hregister2,hregister3,
+         hregister2,hregister3,
          hregisterhigh,hregisterlow : tregister;
          hregisterhigh,hregisterlow : tregister;
          pushed,popecx : boolean;
          pushed,popecx : boolean;
          op : tasmop;
          op : tasmop;
@@ -313,33 +291,12 @@ implementation
 
 
          if is_64bitint(left.resulttype.def) then
          if is_64bitint(left.resulttype.def) then
            begin
            begin
+              location_reset(location,LOC_REGISTER,OS_64);
+
               { load left operator in a register }
               { load left operator in a register }
-              if left.location.loc<>LOC_REGISTER then
-                begin
-                   if left.location.loc=LOC_CREGISTER then
-                     begin
-                        hregisterlow:=rg.getregisterint(exprasmlist);
-                        hregisterhigh:=rg.getregisterint(exprasmlist);
-                        emit_reg_reg(A_MOV,S_L,left.location.registerlow,
-                          hregisterlow);
-                        emit_reg_reg(A_MOV,S_L,left.location.registerhigh,
-                          hregisterlow);
-                     end
-                   else
-                     begin
-                        rg.del_reference(exprasmlist,left.location.reference);
-                        hregisterlow:=rg.getregisterint(exprasmlist);
-                        hregisterhigh:=rg.getregisterint(exprasmlist);
-                        emit_mov_ref_reg64(left.location.reference,
-                          hregisterlow,
-                          hregisterhigh);
-                     end;
-                end
-              else
-                begin
-                   hregisterlow:=left.location.registerlow;
-                   hregisterhigh:=left.location.registerhigh;
-                end;
+              location_force_reg(left.location,OS_64,false);
+              hregisterhigh:=left.location.registerhigh;
+              hregisterlow:=left.location.registerlow;
 
 
               { shifting by a constant directly coded: }
               { shifting by a constant directly coded: }
               if (right.nodetype=ordconstn) then
               if (right.nodetype=ordconstn) then
@@ -385,26 +342,16 @@ implementation
                         location.registerlow:=hregisterlow;
                         location.registerlow:=hregisterlow;
                         location.registerhigh:=hregisterhigh;
                         location.registerhigh:=hregisterhigh;
                      end;
                      end;
-                   location.loc:=LOC_REGISTER;
                 end
                 end
               else
               else
                 begin
                 begin
                    { load right operators in a register }
                    { load right operators in a register }
                    if right.location.loc<>LOC_REGISTER then
                    if right.location.loc<>LOC_REGISTER then
                      begin
                      begin
-                       if right.location.loc=LOC_CREGISTER then
-                          begin
-                             hregister2:=rg.getexplicitregisterint(exprasmlist,R_ECX);
-                             emit_reg_reg(A_MOV,S_L,right.location.register,
-                               hregister2);
-                          end
-                        else
-                          begin
-                             rg.del_reference(exprasmlist,right.location.reference);
-                             hregister2:=rg.getexplicitregisterint(exprasmlist,R_ECX);
-                             emit_ref_reg(A_MOV,S_L,newreference(right.location.reference),
-                               hregister2);
-                          end;
+                       if right.location.loc<>LOC_CREGISTER then
+                        location_release(exprasmlist,right.location);
+                       hregister2:=rg.getexplicitregisterint(exprasmlist,R_ECX);
+                       cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,hregister2);
                      end
                      end
                    else
                    else
                      hregister2:=right.location.register;
                      hregister2:=right.location.register;
@@ -505,7 +452,8 @@ implementation
                    { maybe put ECX back }
                    { maybe put ECX back }
                    if popecx then
                    if popecx then
                      emit_reg(A_POP,S_L,R_ECX)
                      emit_reg(A_POP,S_L,R_ECX)
-                   else rg.ungetregisterint(exprasmlist,R_ECX);
+                   else
+                     rg.ungetregisterint(exprasmlist,R_ECX);
 
 
                    location.registerlow:=hregisterlow;
                    location.registerlow:=hregisterlow;
                    location.registerhigh:=hregisterhigh;
                    location.registerhigh:=hregisterhigh;
@@ -514,24 +462,8 @@ implementation
          else
          else
            begin
            begin
               { load left operators in a register }
               { load left operators in a register }
-              if left.location.loc<>LOC_REGISTER then
-                begin
-                   if left.location.loc=LOC_CREGISTER then
-                     begin
-                        hregister1:=rg.getregisterint(exprasmlist);
-                        emit_reg_reg(A_MOV,S_L,left.location.register,
-                          hregister1);
-                     end
-                   else
-                     begin
-                        rg.del_reference(exprasmlist,left.location.reference);
-                        hregister1:=rg.getregisterint(exprasmlist);
-                        emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
-                          hregister1);
-                     end;
-                end
-              else
-                hregister1:=left.location.register;
+              location_copy(location,left.location);
+              location_force_reg(location,OS_INT,false);
 
 
               { shifting by a constant directly coded: }
               { shifting by a constant directly coded: }
               if (right.nodetype=ordconstn) then
               if (right.nodetype=ordconstn) then
@@ -539,34 +471,23 @@ implementation
                    { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)
                    { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)
                    if right.value<=31 then
                    if right.value<=31 then
                    }
                    }
-                     emit_const_reg(op,S_L,tordconstnode(right).value and 31,
-                       hregister1);
+                   emit_const_reg(op,S_L,tordconstnode(right).value and 31,
+                     location.register);
                    {
                    {
                    else
                    else
                      emit_reg_reg(A_XOR,S_L,hregister1,
                      emit_reg_reg(A_XOR,S_L,hregister1,
                        hregister1);
                        hregister1);
                    }
                    }
-                   location.loc:=LOC_REGISTER;
-                   location.register:=hregister1;
                 end
                 end
               else
               else
                 begin
                 begin
                    { load right operators in a register }
                    { load right operators in a register }
                    if right.location.loc<>LOC_REGISTER then
                    if right.location.loc<>LOC_REGISTER then
                      begin
                      begin
-                       if right.location.loc=LOC_CREGISTER then
-                          begin
-                             hregister2:=rg.getexplicitregisterint(exprasmlist,R_ECX);
-                             emit_reg_reg(A_MOV,S_L,right.location.register,
-                               hregister2);
-                          end
-                        else
-                          begin
-                             rg.del_reference(exprasmlist,right.location.reference);
-                             hregister2:=rg.getexplicitregisterint(exprasmlist,R_ECX);
-                             emit_ref_reg(A_MOV,S_L,newreference(right.location.reference),
-                               hregister2);
-                          end;
+                       if right.location.loc<>LOC_CREGISTER then
+                        location_release(exprasmlist,right.location);
+                       hregister2:=rg.getexplicitregisterint(exprasmlist,R_ECX);
+                       cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,hregister2);
                      end
                      end
                    else
                    else
                      hregister2:=right.location.register;
                      hregister2:=right.location.register;
@@ -574,12 +495,12 @@ implementation
                    { left operator is already in a register }
                    { left operator is already in a register }
                    { hence are both in a register }
                    { hence are both in a register }
                    { is it in the case ECX ? }
                    { is it in the case ECX ? }
-                   if (hregister1=R_ECX) then
+                   if (location.register=R_ECX) then
                      begin
                      begin
                         { then only swap }
                         { then only swap }
-                        emit_reg_reg(A_XCHG,S_L,hregister1,hregister2);
-                        hregister3:=hregister1;
-                        hregister1:=hregister2;
+                        emit_reg_reg(A_XCHG,S_L,location.register,hregister2);
+                        hregister3:=location.register;
+                        location.register:=hregister2;
                         hregister2:=hregister3;
                         hregister2:=hregister3;
                      end
                      end
                    { if second operator not in ECX ? }
                    { if second operator not in ECX ? }
@@ -597,13 +518,12 @@ implementation
                      end;
                      end;
                    rg.ungetregisterint(exprasmlist,hregister2);
                    rg.ungetregisterint(exprasmlist,hregister2);
                    { right operand is in ECX }
                    { right operand is in ECX }
-                   emit_reg_reg(op,S_L,R_CL,hregister1);
+                   emit_reg_reg(op,S_L,R_CL,location.register);
                    { maybe ECX back }
                    { maybe ECX back }
                    if popecx then
                    if popecx then
                      emit_reg(A_POP,S_L,R_ECX)
                      emit_reg(A_POP,S_L,R_ECX)
                    else
                    else
                      rg.ungetregisterint(exprasmlist,R_ECX);
                      rg.ungetregisterint(exprasmlist,R_ECX);
-                   location.register:=hregister1;
                 end;
                 end;
            end;
            end;
       end;
       end;
@@ -630,7 +550,7 @@ implementation
            begin
            begin
              if (registersfpu < 1) then
              if (registersfpu < 1) then
                registersfpu := 1;
                registersfpu := 1;
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
            end
            end
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
          else if (cs_mmx in aktlocalswitches) and
          else if (cs_mmx in aktlocalswitches) and
@@ -659,12 +579,13 @@ implementation
 
 
 
 
     procedure ti386unaryminusnode.pass_2;
     procedure ti386unaryminusnode.pass_2;
+
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
       procedure do_mmx_neg;
       procedure do_mmx_neg;
         var
         var
            op : tasmop;
            op : tasmop;
         begin
         begin
-           location.loc:=LOC_MMXREGISTER;
+           location_reset(location,LOC_MMXREGISTER,OS_NO);
            if cs_mmx_saturation in aktlocalswitches then
            if cs_mmx_saturation in aktlocalswitches then
              case mmx_type(resulttype.def) of
              case mmx_type(resulttype.def) of
                 mmxs8bit:
                 mmxs8bit:
@@ -694,44 +615,19 @@ implementation
          if is_64bitint(left.resulttype.def) then
          if is_64bitint(left.resulttype.def) then
            begin
            begin
               secondpass(left);
               secondpass(left);
-              clear_location(location);
-              location.loc:=LOC_REGISTER;
-              case left.location.loc of
-                LOC_REGISTER :
-                  begin
-                     location.registerlow:=left.location.registerlow;
-                     location.registerhigh:=left.location.registerhigh;
-                  end;
-                LOC_CREGISTER :
-                  begin
-                     location.registerlow:=rg.getregisterint(exprasmlist);
-                     location.registerhigh:=rg.getregisterint(exprasmlist);
-                     emit_reg_reg(A_MOV,S_L,left.location.registerlow,location.registerlow);
-                     emit_reg_reg(A_MOV,S_L,left.location.registerhigh,location.registerhigh);
-                  end;
-                LOC_REFERENCE,LOC_MEM :
-                  begin
-                     rg.del_reference(exprasmlist,left.location.reference);
-                     location.registerlow:=rg.getregisterint(exprasmlist);
-                     location.registerhigh:=rg.getregisterint(exprasmlist);
-                     emit_mov_ref_reg64(left.location.reference,
-                       location.registerlow,
-                       location.registerhigh);
-                  end;
-              end;
-            {
-            emit_reg(A_NEG,S_L,location.registerlow);
-            emit_const_reg(A_ADC,S_L,0,location.registerhigh);
-            emit_reg(A_NEG,S_L,location.registerhigh);
-            }
-            emit_reg(A_NOT,S_L,location.registerhigh);
-            emit_reg(A_NEG,S_L,location.registerlow);
-            emit_const_reg(A_SBB,S_L,-1,location.registerhigh);
+
+              { load left operator in a register }
+              location_copy(location,left.location);
+              location_force_reg(location,OS_64,false);
+
+              emit_reg(A_NOT,S_L,location.registerhigh);
+              emit_reg(A_NEG,S_L,location.registerlow);
+              emit_const_reg(A_SBB,S_L,-1,location.registerhigh);
            end
            end
          else
          else
            begin
            begin
               secondpass(left);
               secondpass(left);
-              location.loc:=LOC_REGISTER;
+              location_reset(location,LOC_REGISTER,OS_INT);
               case left.location.loc of
               case left.location.loc of
                  LOC_REGISTER:
                  LOC_REGISTER:
                    begin
                    begin
@@ -748,7 +644,7 @@ implementation
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
                  LOC_MMXREGISTER:
                  LOC_MMXREGISTER:
                    begin
                    begin
-                      set_location(location,left.location);
+                      location_copy(location,left.location);
                       emit_reg_reg(A_PXOR,S_NO,R_MM7,R_MM7);
                       emit_reg_reg(A_PXOR,S_NO,R_MM7,R_MM7);
                       do_mmx_neg;
                       do_mmx_neg;
                    end;
                    end;
@@ -761,17 +657,17 @@ implementation
                       do_mmx_neg;
                       do_mmx_neg;
                    end;
                    end;
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
-                 LOC_REFERENCE,LOC_MEM:
+                 LOC_REFERENCE,
+                 LOC_CREFERENCE:
                    begin
                    begin
-                      rg.del_reference(exprasmlist,left.location.reference);
+                      reference_release(exprasmlist,left.location.reference);
                       if (left.resulttype.def.deftype=floatdef) then
                       if (left.resulttype.def.deftype=floatdef) then
                         begin
                         begin
-                           location.loc:=LOC_FPU;
+                           location_reset(location,LOC_FPUREGISTER,OS_NO);
                            location.register := R_ST;
                            location.register := R_ST;
                            cg.a_loadfpu_ref_reg(exprasmlist,
                            cg.a_loadfpu_ref_reg(exprasmlist,
-                             def_cgsize(left.resulttype.def),
-                             left.location.reference,
-                             R_ST);
+                              def_cgsize(left.resulttype.def),
+                              left.location.reference,R_ST);
                            emit_none(A_FCHS,S_NO);
                            emit_none(A_FCHS,S_NO);
                         end
                         end
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -779,39 +675,36 @@ implementation
                         begin
                         begin
                            location.register:=rg.getregistermm(exprasmlist);
                            location.register:=rg.getregistermm(exprasmlist);
                            emit_reg_reg(A_PXOR,S_NO,R_MM7,R_MM7);
                            emit_reg_reg(A_PXOR,S_NO,R_MM7,R_MM7);
-                           emit_ref_reg(A_MOVQ,S_NO,
-                             newreference(left.location.reference),
-                             location.register);
+                           emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
                            do_mmx_neg;
                            do_mmx_neg;
                         end
                         end
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
                       else
                       else
                         begin
                         begin
                            location.register:=rg.getregisterint(exprasmlist);
                            location.register:=rg.getregisterint(exprasmlist);
-                           emit_ref_reg(A_MOV,S_L,
-                             newreference(left.location.reference),
-                             location.register);
+                           emit_ref_reg(A_MOV,S_L,left.location.reference,location.register);
                            emit_reg(A_NEG,S_L,location.register);
                            emit_reg(A_NEG,S_L,location.register);
                         end;
                         end;
                    end;
                    end;
-                 LOC_FPU,LOC_CFPUREGISTER:
+                 LOC_FPUREGISTER,LOC_CFPUREGISTER:
                    begin
                    begin
                       { "load st,st" is ignored by the code generator }
                       { "load st,st" is ignored by the code generator }
-                      cg.a_loadfpu_reg_reg(exprasmlist,
-                        left.location.register,R_ST);
-                      location.loc:=LOC_FPU;
-                      location.register := R_ST;
+                      cg.a_loadfpu_reg_reg(exprasmlist,left.location.register,R_ST);
+                      location_reset(location,LOC_FPUREGISTER,OS_NO);
+                      location.register:=R_ST;
                       emit_none(A_FCHS,S_NO);
                       emit_none(A_FCHS,S_NO);
                    end;
                    end;
+                 else
+                    internalerror(200203225);
               end;
               end;
            end;
            end;
-{ Here was a problem...     }
-{ Operand to be negated always     }
-{ seems to be converted to signed  }
-{ 32-bit before doing neg!!     }
-{ So this is useless...     }
-{ that's not true: -2^31 gives an overflow error if it is negaded (FK) }
-{        emitoverflowcheck(p);}
+         { Here was a problem...     }
+         { Operand to be negated always     }
+         { seems to be converted to signed  }
+         { 32-bit before doing neg!!     }
+         { So this is useless...     }
+         { that's not true: -2^31 gives an overflow error if it is negaded (FK) }
+         { emitoverflowcheck(p);}
       end;
       end;
 
 
 
 
@@ -834,12 +727,13 @@ implementation
             { the second pass could change the location of left }
             { the second pass could change the location of left }
             { if it is a register variable, so we've to do      }
             { if it is a register variable, so we've to do      }
             { this before the case statement                    }
             { this before the case statement                    }
-            if left.location.loc in [LOC_REFERENCE,LOC_MEM,
-              LOC_FLAGS,LOC_REGISTER,LOC_CREGISTER] then
-              secondpass(left);
+            if left.location.loc<>LOC_JUMP then
+             secondpass(left);
+
             case left.location.loc of
             case left.location.loc of
               LOC_JUMP :
               LOC_JUMP :
                 begin
                 begin
+                  location_reset(location,LOC_JUMP,OS_NO);
                   hl:=truelabel;
                   hl:=truelabel;
                   truelabel:=falselabel;
                   truelabel:=falselabel;
                   falselabel:=hl;
                   falselabel:=hl;
@@ -850,30 +744,25 @@ implementation
                   falselabel:=hl;
                   falselabel:=hl;
                 end;
                 end;
               LOC_FLAGS :
               LOC_FLAGS :
-                location.resflags:=flagsinvers[left.location.resflags];
-              LOC_REGISTER, LOC_CREGISTER :
                 begin
                 begin
-                  location.loc:=LOC_FLAGS;
-                  location.resflags:=F_E;
-                  emit_reg_reg(A_TEST,opsize,
-                    left.location.register,left.location.register);
-                  rg.ungetregister(exprasmlist,left.location.register);
+                  location_release(exprasmlist,left.location);
+                  location_reset(location,LOC_FLAGS,OS_NO);
+                  location.resflags:=flagsinvers[left.location.resflags];
                 end;
                 end;
+              LOC_CONSTANT,
+              LOC_REGISTER,
+              LOC_CREGISTER,
               LOC_REFERENCE,
               LOC_REFERENCE,
-              LOC_MEM :
+              LOC_CREFERENCE :
                 begin
                 begin
-                  clear_location(location);
-                  location.loc:=LOC_REGISTER;
-                  rg.del_reference(exprasmlist,left.location.reference);
-                  { this was placed before del_ref => internaalerror(10) }
-                  location.register:=def_getreg(resulttype.def);
-                  emit_ref_reg(A_MOV,opsize,
-                    newreference(left.location.reference),location.register);
-                  emit_reg_reg(A_TEST,opsize,location.register,location.register);
-                  rg.ungetregister(exprasmlist,location.register);
-                  location.loc:=LOC_FLAGS;
+                  location_force_reg(left.location,def_cgsize(resulttype.def),true);
+                  location_release(exprasmlist,left.location);
+                  emit_reg_reg(A_TEST,opsize,left.location.register,left.location.register);
+                  location_reset(location,LOC_FLAGS,OS_NO);
                   location.resflags:=F_E;
                   location.resflags:=F_E;
                 end;
                 end;
+             else
+                internalerror(200203224);
             end;
             end;
           end
           end
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -881,25 +770,25 @@ implementation
           if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
           if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
            begin
            begin
              secondpass(left);
              secondpass(left);
-             location.loc:=LOC_MMXREGISTER;
+             location_reset(location,LOC_MMXREGISTER,OS_NO);
              { prepare EDI }
              { prepare EDI }
              rg.getexplicitregisterint(exprasmlist,R_EDI);
              rg.getexplicitregisterint(exprasmlist,R_EDI);
              emit_const_reg(A_MOV,S_L,longint($ffffffff),R_EDI);
              emit_const_reg(A_MOV,S_L,longint($ffffffff),R_EDI);
              { load operand }
              { load operand }
              case left.location.loc of
              case left.location.loc of
                LOC_MMXREGISTER:
                LOC_MMXREGISTER:
-                 set_location(location,left.location);
+                 location_copy(location,left.location);
                LOC_CMMXREGISTER:
                LOC_CMMXREGISTER:
                  begin
                  begin
                    location.register:=rg.getregistermm(exprasmlist);
                    location.register:=rg.getregistermm(exprasmlist);
                    emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
                    emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
                  end;
                  end;
-               LOC_REFERENCE,LOC_MEM:
+               LOC_REFERENCE,
+               LOC_CREFERENCE:
                  begin
                  begin
-                   rg.del_reference(exprasmlist,left.location.reference);
+                   location_release(exprasmlist,left.location);
                    location.register:=rg.getregistermm(exprasmlist);
                    location.register:=rg.getregistermm(exprasmlist);
-                   emit_ref_reg(A_MOVQ,S_NO,
-                     newreference(left.location.reference),location.register);
+                   emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
                  end;
                  end;
              end;
              end;
              { load mask }
              { load mask }
@@ -916,65 +805,20 @@ implementation
          else if is_64bitint(left.resulttype.def) then
          else if is_64bitint(left.resulttype.def) then
            begin
            begin
               secondpass(left);
               secondpass(left);
-              clear_location(location);
-              location.loc:=LOC_REGISTER;
-              case left.location.loc of
-                LOC_REGISTER :
-                  begin
-                     location.registerlow:=left.location.registerlow;
-                     location.registerhigh:=left.location.registerhigh;
-                     emit_reg(A_NOT,S_L,location.registerlow);
-                     emit_reg(A_NOT,S_L,location.registerhigh);
-                  end;
-                LOC_CREGISTER :
-                  begin
-                     location.registerlow:=rg.getregisterint(exprasmlist);
-                     location.registerhigh:=rg.getregisterint(exprasmlist);
-                     emit_reg_reg(A_MOV,S_L,left.location.registerlow,location.registerlow);
-                     emit_reg_reg(A_MOV,S_L,left.location.registerhigh,location.registerhigh);
-                     emit_reg(A_NOT,S_L,location.registerlow);
-                     emit_reg(A_NOT,S_L,location.registerhigh);
-                  end;
-                LOC_REFERENCE,LOC_MEM :
-                  begin
-                     rg.del_reference(exprasmlist,left.location.reference);
-                     location.registerlow:=rg.getregisterint(exprasmlist);
-                     location.registerhigh:=rg.getregisterint(exprasmlist);
-                     emit_mov_ref_reg64(left.location.reference,
-                       location.registerlow,
-                       location.registerhigh);
-                     emit_reg(A_NOT,S_L,location.registerlow);
-                     emit_reg(A_NOT,S_L,location.registerhigh);
-                  end;
-              end;
+              location_copy(location,left.location);
+              location_force_reg(location,OS_64,false);
+
+              emit_reg(A_NOT,S_L,location.registerlow);
+              emit_reg(A_NOT,S_L,location.registerhigh);
            end
            end
          else
          else
           begin
           begin
             secondpass(left);
             secondpass(left);
-            clear_location(location);
+            location_copy(location,left.location);
+            location_force_reg(location,def_cgsize(resulttype.def),false);
+
             opsize:=def_opsize(resulttype.def);
             opsize:=def_opsize(resulttype.def);
-            location.loc:=LOC_REGISTER;
-            case left.location.loc of
-              LOC_REGISTER :
-                begin
-                  location.register:=left.location.register;
-                  emit_reg(A_NOT,opsize,location.register);
-                end;
-              LOC_CREGISTER :
-                begin
-                  location.register:=def_getreg(resulttype.def);
-                  emit_reg_reg(A_MOV,opsize,left.location.register,location.register);
-                  emit_reg(A_NOT,opsize,location.register);
-                end;
-              LOC_REFERENCE,LOC_MEM :
-                begin
-                  rg.del_reference(exprasmlist,left.location.reference);
-                  location.register:=def_getreg(resulttype.def);
-                  emit_ref_reg(A_MOV,opsize,
-                    newreference(left.location.reference),location.register);
-                  emit_reg(A_NOT,opsize,location.register);
-                end;
-            end;
+            emit_reg(A_NOT,opsize,location.register);
           end;
           end;
       end;
       end;
 
 
@@ -987,7 +831,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.24  2002-03-31 20:26:39  jonas
+  Revision 1.25  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.24  2002/03/31 20:26:39  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 104 - 162
compiler/i386/n386mem.pas

@@ -59,7 +59,7 @@ implementation
       globtype,systems,
       globtype,systems,
       cutils,verbose,globals,
       cutils,verbose,globals,
       symconst,symtype,symdef,symsym,symtable,aasm,types,
       symconst,symtype,symdef,symsym,symtable,aasm,types,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       pass_1,nld,ncon,nadd,
       pass_1,nld,ncon,nadd,
       cpubase,cpuasm,
       cpubase,cpuasm,
       cgobj,cga,tgobj,n386util,rgobj;
       cgobj,cga,tgobj,n386util,rgobj;
@@ -72,15 +72,17 @@ implementation
       var
       var
          pushed : tpushedsaved;
          pushed : tpushedsaved;
          regstopush: tregisterset;
          regstopush: tregisterset;
-         r : preference;
+         href : treference;
       begin
       begin
          if assigned(left) then
          if assigned(left) then
            begin
            begin
               secondpass(left);
               secondpass(left);
-              location.register:=left.location.register;
+              location_copy(location,left.location);
            end
            end
          else
          else
            begin
            begin
+              location_reset(location,LOC_REFERENCE,OS_ADDR);
+
               regstopush := all_registers;
               regstopush := all_registers;
               remove_non_regvars_from_loc(location,regstopush);
               remove_non_regvars_from_loc(location,regstopush);
               rg.saveusedregisters(exprasmlist,pushed,regstopush);
               rg.saveusedregisters(exprasmlist,pushed,regstopush);
@@ -95,11 +97,9 @@ implementation
 
 
               if tpointerdef(resulttype.def).pointertype.def.needs_inittable then
               if tpointerdef(resulttype.def).pointertype.def.needs_inittable then
                 begin
                 begin
-                   new(r);
-                   reset_reference(r^);
-                   r^.symbol:=tstoreddef(tpointerdef(resulttype.def).pointertype.def).get_rtti_label(initrtti);
-                   emitpushreferenceaddr(r^);
-                   dispose(r);
+                   reference_reset_symbol(href,tstoreddef(tpointerdef(resulttype.def).pointertype.def).get_rtti_label(initrtti),0);
+                   emitpushreferenceaddr(href);
+
                    { push pointer we just allocated, we need to initialize the
                    { push pointer we just allocated, we need to initialize the
                      data located at that pointer not the pointer self (PFV) }
                      data located at that pointer not the pointer self (PFV) }
                    emit_push_loc(location);
                    emit_push_loc(location);
@@ -109,8 +109,6 @@ implementation
               { may be load ESI }
               { may be load ESI }
               maybe_loadself;
               maybe_loadself;
            end;
            end;
-         if codegenerror then
-           exit;
       end;
       end;
 
 
 
 
@@ -136,26 +134,23 @@ implementation
       var
       var
          regstopush: tregisterset;
          regstopush: tregisterset;
          pushed : tpushedsaved;
          pushed : tpushedsaved;
+         href : treference;
          lefttemp: treference;
          lefttemp: treference;
-         r : preference;
          left_needs_initfinal: boolean;
          left_needs_initfinal: boolean;
 
 
-        procedure saveleft;
-          begin
-            tg.gettempofsizereference(exprasmlist,target_info.size_of_pointer,
-              lefttemp);
-            cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,lefttemp);
-            rg.del_location(exprasmlist,left.location);
-          end;
-
+         procedure saveleft;
+         begin
+           tg.gettempofsizereference(exprasmlist,target_info.size_of_pointer,lefttemp);
+           cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,lefttemp);
+           location_release(exprasmlist,left.location);
+         end;
 
 
       begin
       begin
          secondpass(left);
          secondpass(left);
          if codegenerror then
          if codegenerror then
            exit;
            exit;
 
 
-         left_needs_initfinal :=
-           tpointerdef(left.resulttype.def).pointertype.def.needs_inittable;
+         left_needs_initfinal:=tpointerdef(left.resulttype.def).pointertype.def.needs_inittable;
 
 
          regstopush := all_registers;
          regstopush := all_registers;
          remove_non_regvars_from_loc(left.location,regstopush);
          remove_non_regvars_from_loc(left.location,regstopush);
@@ -168,11 +163,8 @@ implementation
              begin
              begin
                 if left_needs_initfinal then
                 if left_needs_initfinal then
                   begin
                   begin
-                     new(r);
-                     reset_reference(r^);
-                     r^.symbol:=tstoreddef(tpointerdef(left.resulttype.def).pointertype.def).get_rtti_label(initrtti);
-                     emitpushreferenceaddr(r^);
-                     dispose(r);
+                     reference_reset_symbol(href,tstoreddef(tpointerdef(left.resulttype.def).pointertype.def).get_rtti_label(initrtti),0);
+                     emitpushreferenceaddr(href);
                      { push pointer adress }
                      { push pointer adress }
                      emit_push_loc(left.location);
                      emit_push_loc(left.location);
                      { save left and free its registers }
                      { save left and free its registers }
@@ -185,7 +177,7 @@ implementation
                 else
                 else
                   begin
                   begin
                     emit_push_loc(left.location);
                     emit_push_loc(left.location);
-                    rg.del_location(exprasmlist,left.location);
+                    location_release(exprasmlist,left.location);
                   end;
                   end;
                 emitcall('FPC_FREEMEM');
                 emitcall('FPC_FREEMEM');
              end;
              end;
@@ -200,11 +192,8 @@ implementation
                 emitcall('FPC_GETMEM');
                 emitcall('FPC_GETMEM');
                 if left_needs_initfinal then
                 if left_needs_initfinal then
                   begin
                   begin
-                     new(r);
-                     reset_reference(r^);
-                     r^.symbol:=tstoreddef(tpointerdef(left.resulttype.def).pointertype.def).get_rtti_label(initrtti);
-                     emitpushreferenceaddr(r^);
-                     dispose(r);
+                     reference_reset_symbol(href,tstoreddef(tpointerdef(left.resulttype.def).pointertype.def).get_rtti_label(initrtti),0);
+                     emitpushreferenceaddr(href);
                      emit_push_mem(lefttemp);
                      emit_push_mem(lefttemp);
                      tg.ungetiftemp(exprasmlist,lefttemp);
                      tg.ungetiftemp(exprasmlist,lefttemp);
                      emitcall('FPC_INITIALIZE');
                      emitcall('FPC_INITIALIZE');
@@ -245,8 +234,6 @@ implementation
     procedure ti386vecnode.pass_2;
     procedure ti386vecnode.pass_2;
       var
       var
         is_pushed : boolean;
         is_pushed : boolean;
-        ind,hr : tregister;
-        //_p : tnode;
 
 
           function get_mul_size:longint;
           function get_mul_size:longint;
           begin
           begin
@@ -271,9 +258,9 @@ implementation
             else
             else
               begin
               begin
                  if ispowerof2(l1,l2) then
                  if ispowerof2(l1,l2) then
-                   emit_const_reg(A_SHL,S_L,l2,ind)
+                   emit_const_reg(A_SHL,S_L,l2,right.location.register)
                  else
                  else
-                   emit_const_reg(A_IMUL,S_L,l1,ind);
+                   emit_const_reg(A_IMUL,S_L,l1,right.location.register);
               end;
               end;
             end;
             end;
           end;
           end;
@@ -285,22 +272,24 @@ implementation
          { because in constant nodes which constant index              }
          { because in constant nodes which constant index              }
          { the left tree is removed                                  }
          { the left tree is removed                                  }
          t   : tnode;
          t   : tnode;
-         hp  : preference;
          href : treference;
          href : treference;
-         tai : Taicpu;
          srsym : tsym;
          srsym : tsym;
          pushed : tpushedsaved;
          pushed : tpushedsaved;
          hightree : tnode;
          hightree : tnode;
-         hl,otl,ofl : tasmlabel;
+         isjump  : boolean;
+         otl,ofl : tasmlabel;
+         newsize : tcgsize;
       begin
       begin
+         newsize:=def_cgsize_ref(resulttype.def);
+         location_reset(location,LOC_REFERENCE,newsize);
+
          secondpass(left);
          secondpass(left);
          { we load the array reference to location }
          { we load the array reference to location }
 
 
          { an ansistring needs to be dereferenced }
          { an ansistring needs to be dereferenced }
          if is_ansistring(left.resulttype.def) or
          if is_ansistring(left.resulttype.def) or
-           is_widestring(left.resulttype.def) then
+            is_widestring(left.resulttype.def) then
            begin
            begin
-              reset_reference(location.reference);
               if nf_callunique in flags then
               if nf_callunique in flags then
                 begin
                 begin
                    if left.location.loc<>LOC_REFERENCE then
                    if left.location.loc<>LOC_REFERENCE then
@@ -319,18 +308,21 @@ implementation
                    rg.restoreusedregisters(exprasmlist,pushed);
                    rg.restoreusedregisters(exprasmlist,pushed);
                 end;
                 end;
 
 
-              if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-                begin
-                   location.reference.base:=left.location.register;
-                end
-              else
-                begin
-                   rg.del_reference(exprasmlist,left.location.reference);
-                   location.reference.base:=rg.getregisterint(exprasmlist);
-                   emit_ref_reg(A_MOV,S_L,
-                     newreference(left.location.reference),
-                     location.reference.base);
-                end;
+              case left.location.loc of
+                LOC_REGISTER,
+                LOC_CREGISTER :
+                  location.reference.base:=left.location.register;
+                LOC_CREFERENCE,
+                LOC_REFERENCE :
+                  begin
+                    location_release(exprasmlist,left.location);
+                    location.reference.base:=rg.getregisterint(exprasmlist);
+                    emit_ref_reg(A_MOV,S_L,
+                      left.location.reference,location.reference.base);
+                  end;
+                else
+                  internalerror(2002032218);
+              end;
 
 
               { check for a zero length string,
               { check for a zero length string,
                 we can use the ansistring routine here }
                 we can use the ansistring routine here }
@@ -344,38 +336,35 @@ implementation
                    rg.restoreusedregisters(exprasmlist,pushed);
                    rg.restoreusedregisters(exprasmlist,pushed);
                 end;
                 end;
 
 
+              { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
               if is_ansistring(left.resulttype.def) then
               if is_ansistring(left.resulttype.def) then
-                { in ansistrings S[1] is pchar(S)[0] !! }
                 dec(location.reference.offset)
                 dec(location.reference.offset)
               else
               else
-                begin
-                   { in widestrings S[1] is pwchar(S)[0] !! }
-                   dec(location.reference.offset,2);
-//                   emit_const_reg(A_SHL,S_L,
-//                     1,location.reference.base);
-                end;
+                dec(location.reference.offset,2);
 
 
               { we've also to keep left up-to-date, because it is used   }
               { we've also to keep left up-to-date, because it is used   }
               { if a constant array index occurs, subject to change (FK) }
               { if a constant array index occurs, subject to change (FK) }
-              set_location(left.location,location);
+              location_copy(left.location,location);
            end
            end
          else if is_dynamic_array(left.resulttype.def) then
          else if is_dynamic_array(left.resulttype.def) then
          { ... also a dynamic string }
          { ... also a dynamic string }
            begin
            begin
-              reset_reference(location.reference);
+              case left.location.loc of
+                LOC_REGISTER,
+                LOC_CREGISTER :
+                  location.reference.base:=left.location.register;
+                LOC_REFERENCE,
+                LOC_CREFERENCE :
+                  begin
+                     location_release(exprasmlist,left.location);
+                     location.reference.base:=rg.getregisterint(exprasmlist);
+                     emit_ref_reg(A_MOV,S_L,
+                       left.location.reference,location.reference.base);
+                  end;
+                else
+                  internalerror(2002032219);
+              end;
 
 
-              if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-                begin
-                   location.reference.base:=left.location.register;
-                end
-              else
-                begin
-                   rg.del_reference(exprasmlist,left.location.reference);
-                   location.reference.base:=rg.getregisterint(exprasmlist);
-                   emit_ref_reg(A_MOV,S_L,
-                     newreference(left.location.reference),
-                     location.reference.base);
-                end;
 {$warning FIXME}
 {$warning FIXME}
               { check for a zero length string,
               { check for a zero length string,
                 we can use the ansistring routine here }
                 we can use the ansistring routine here }
@@ -391,10 +380,10 @@ implementation
 
 
               { we've also to keep left up-to-date, because it is used   }
               { we've also to keep left up-to-date, because it is used   }
               { if a constant array index occurs, subject to change (FK) }
               { if a constant array index occurs, subject to change (FK) }
-              set_location(left.location,location);
+              location_copy(left.location,location);
            end
            end
          else
          else
-           set_location(location,left.location);
+           location_copy(location,left.location);
 
 
          { offset can only differ from 0 if arraydef }
          { offset can only differ from 0 if arraydef }
          if (left.resulttype.def.deftype=arraydef) and
          if (left.resulttype.def.deftype=arraydef) and
@@ -441,9 +430,9 @@ implementation
                           begin
                           begin
                              rg.saveusedregisters(exprasmlist,pushed,all_registers);
                              rg.saveusedregisters(exprasmlist,pushed,all_registers);
                              push_int(tordconstnode(right).value);
                              push_int(tordconstnode(right).value);
-                             hp:=newreference(location.reference);
-                             dec(hp^.offset,7);
-                             emit_ref(A_PUSH,S_L,hp);
+                             href:=location.reference;
+                             dec(href.offset,7);
+                             emit_ref(A_PUSH,S_L,href);
                              rg.saveregvars(exprasmlist,all_registers);
                              rg.saveregvars(exprasmlist,all_registers);
                              emitcall('FPC_ANSISTR_RANGECHECK');
                              emitcall('FPC_ANSISTR_RANGECHECK');
                              rg.restoreusedregisters(exprasmlist,pushed);
                              rg.restoreusedregisters(exprasmlist,pushed);
@@ -472,7 +461,7 @@ implementation
               putnode(p);
               putnode(p);
               p:=_p;
               p:=_p;
               }
               }
-              set_location(location,left.location);
+              location_copy(location,left.location);
            end
            end
          else
          else
          { not nodetype=ordconstn }
          { not nodetype=ordconstn }
@@ -538,10 +527,10 @@ implementation
                        get_mul_size*extraoffset);
                        get_mul_size*extraoffset);
                 end;
                 end;
               { calculate from left to right }
               { calculate from left to right }
-              if (location.loc<>LOC_REFERENCE) and
-                 (location.loc<>LOC_MEM) then
+              if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
                 CGMessage(cg_e_illegal_expression);
                 CGMessage(cg_e_illegal_expression);
-              if (right.location.loc=LOC_JUMP) then
+              isjump:=(right.location.loc=LOC_JUMP);
+              if isjump then
                begin
                begin
                  otl:=truelabel;
                  otl:=truelabel;
                  getlabel(truelabel);
                  getlabel(truelabel);
@@ -564,8 +553,8 @@ implementation
                      if is_open_array(left.resulttype.def) or
                      if is_open_array(left.resulttype.def) or
                         is_array_of_const(left.resulttype.def) then
                         is_array_of_const(left.resulttype.def) then
                       begin
                       begin
-                        reset_reference(href);
                         tarraydef(left.resulttype.def).genrangecheck;
                         tarraydef(left.resulttype.def).genrangecheck;
+                        reference_reset(href);
                         href.symbol:=newasmsymbol(tarraydef(left.resulttype.def).getrangecheckstring);
                         href.symbol:=newasmsymbol(tarraydef(left.resulttype.def).getrangecheckstring);
                         href.offset:=4;
                         href.offset:=4;
                         srsym:=searchsymonlyin(tloadnode(left).symtable,
                         srsym:=searchsymonlyin(tloadnode(left).symtable,
@@ -573,7 +562,8 @@ implementation
                         hightree:=cloadnode.create(tvarsym(srsym),tloadnode(left).symtable);
                         hightree:=cloadnode.create(tvarsym(srsym),tloadnode(left).symtable);
                         firstpass(hightree);
                         firstpass(hightree);
                         secondpass(hightree);
                         secondpass(hightree);
-                        emit_mov_loc_ref(hightree.location,href,S_L,true);
+                        location_release(exprasmlist,hightree.location);
+                        cg.a_load_loc_ref(exprasmlist,OS_INT,hightree.location,href);
                         hightree.free;
                         hightree.free;
                         hightree:=nil;
                         hightree:=nil;
                       end;
                       end;
@@ -581,72 +571,13 @@ implementation
                    end;
                    end;
                end;
                end;
 
 
-              case right.location.loc of
-                 LOC_REGISTER:
-                   begin
-                      ind:=right.location.register;
-                      case right.resulttype.def.size of
-                         1:
-                           begin
-                              hr:=reg8toreg32(ind);
-                              emit_reg_reg(A_MOVZX,S_BL,ind,hr);
-                              ind:=hr;
-                           end;
-                         2:
-                           begin
-                              hr:=reg16toreg32(ind);
-                              emit_reg_reg(A_MOVZX,S_WL,ind,hr);
-                              ind:=hr;
-                           end;
-                      end;
-                   end;
-                 LOC_CREGISTER:
-                   begin
-                      ind:=rg.getregisterint(exprasmlist);
-                      case right.resulttype.def.size of
-                         1:
-                           emit_reg_reg(A_MOVZX,S_BL,right.location.register,ind);
-                         2:
-                           emit_reg_reg(A_MOVZX,S_WL,right.location.register,ind);
-                         4:
-                           emit_reg_reg(A_MOV,S_L,right.location.register,ind);
-                      end;
-                   end;
-                 LOC_FLAGS:
-                   begin
-                      ind:=rg.getregisterint(exprasmlist);
-                      emit_flag2reg(right.location.resflags,reg32toreg8(ind));
-                      emit_reg_reg(A_MOVZX,S_BL,reg32toreg8(ind),ind);
-                   end;
-                 LOC_JUMP :
-                   begin
-                     ind:=rg.getregisterint(exprasmlist);
-                     emitlab(truelabel);
-                     truelabel:=otl;
-                     emit_const_reg(A_MOV,S_L,1,ind);
-                     getlabel(hl);
-                     emitjmp(C_None,hl);
-                     emitlab(falselabel);
-                     falselabel:=ofl;
-                     emit_reg_reg(A_XOR,S_L,ind,ind);
-                     emitlab(hl);
-                   end;
-                 LOC_REFERENCE,LOC_MEM :
-                   begin
-                      rg.del_reference(exprasmlist,right.location.reference);
-                      ind:=rg.getregisterint(exprasmlist);
-                      { Booleans are stored in an 8 bit memory location, so
-                        the use of MOVL is not correct }
-                      case right.resulttype.def.size of
-                       1 : tai:=Taicpu.Op_ref_reg(A_MOVZX,S_BL,newreference(right.location.reference),ind);
-                       2 : tai:=Taicpu.Op_ref_reg(A_MOVZX,S_WL,newreference(right.location.reference),ind);
-                       4 : tai:=Taicpu.Op_ref_reg(A_MOV,S_L,newreference(right.location.reference),ind);
-                      end;
-                      exprasmList.concat(tai);
-                   end;
-                 else
-                   internalerror(5913428);
-                end;
+              location_force_reg(right.location,OS_32,false);
+
+              if isjump then
+               begin
+                 truelabel:=otl;
+                 falselabel:=ofl;
+               end;
 
 
             { produce possible range check code: }
             { produce possible range check code: }
               if cs_check_range in aktlocalswitches then
               if cs_check_range in aktlocalswitches then
@@ -663,10 +594,10 @@ implementation
                          st_ansistring:
                          st_ansistring:
                            begin
                            begin
                               rg.saveusedregisters(exprasmlist,pushed,all_registers);
                               rg.saveusedregisters(exprasmlist,pushed,all_registers);
-                              emit_reg(A_PUSH,S_L,ind);
-                              hp:=newreference(location.reference);
-                              dec(hp^.offset,7);
-                              emit_ref(A_PUSH,S_L,hp);
+                              emit_reg(A_PUSH,S_L,right.location.register);
+                              href:=location.reference;
+                              dec(href.offset,7);
+                              emit_ref(A_PUSH,S_L,href);
                               rg.saveregvars(exprasmlist,all_registers);
                               rg.saveregvars(exprasmlist,all_registers);
                               emitcall('FPC_ANSISTR_RANGECHECK');
                               emitcall('FPC_ANSISTR_RANGECHECK');
                               rg.restoreusedregisters(exprasmlist,pushed);
                               rg.restoreusedregisters(exprasmlist,pushed);
@@ -686,7 +617,7 @@ implementation
 
 
               if location.reference.index=R_NO then
               if location.reference.index=R_NO then
                begin
                begin
-                 location.reference.index:=ind;
+                 location.reference.index:=right.location.register;
                  calc_emit_mul;
                  calc_emit_mul;
                end
                end
               else
               else
@@ -700,13 +631,11 @@ implementation
                     end;
                     end;
                     calc_emit_mul;
                     calc_emit_mul;
                     location.reference.base:=location.reference.index;
                     location.reference.base:=location.reference.index;
-                    location.reference.index:=ind;
+                    location.reference.index:=right.location.register;
                   end
                   end
                  else
                  else
                   begin
                   begin
-                    emit_ref_reg(
-                      A_LEA,S_L,newreference(location.reference),
-                      location.reference.index);
+                    emit_ref_reg(A_LEA,S_L,location.reference,location.reference.index);
                     rg.ungetregisterint(exprasmlist,location.reference.base);
                     rg.ungetregisterint(exprasmlist,location.reference.base);
                     { the symbol offset is loaded,             }
                     { the symbol offset is loaded,             }
                     { so release the symbol name and set symbol  }
                     { so release the symbol name and set symbol  }
@@ -715,13 +644,15 @@ implementation
                     location.reference.offset:=0;
                     location.reference.offset:=0;
                     calc_emit_mul;
                     calc_emit_mul;
                     location.reference.base:=location.reference.index;
                     location.reference.base:=location.reference.index;
-                    location.reference.index:=ind;
+                    location.reference.index:=right.location.register;
                   end;
                   end;
                end;
                end;
 
 
               if nf_memseg in flags then
               if nf_memseg in flags then
                 location.reference.segment:=R_FS;
                 location.reference.segment:=R_FS;
            end;
            end;
+
+        location.size:=newsize;
       end;
       end;
 
 
 
 
@@ -734,7 +665,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.22  2002-04-01 09:44:04  jonas
+  Revision 1.23  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.22  2002/04/01 09:44:04  jonas
     * better fix for new/dispose bug with init/final data
     * better fix for new/dispose bug with init/final data
 
 
   Revision 1.21  2002/03/31 20:26:39  jonas
   Revision 1.21  2002/03/31 20:26:39  jonas

+ 36 - 8
compiler/i386/n386obj.pas

@@ -37,7 +37,7 @@ uses
   fmodule,
   fmodule,
   nobj,
   nobj,
   cpubase,
   cpubase,
-  cga, tgobj;
+  cga,tgobj,rgobj;
 
 
    type
    type
      ti386classheader=class(tclassheader)
      ti386classheader=class(tclassheader)
@@ -108,40 +108,56 @@ procedure ti386classheader.cgintfwrapper(asmlist: TAAsmoutput; procdef: tprocdef
   end;
   end;
 
 
   procedure adjustselfvalue(ioffset: longint);
   procedure adjustselfvalue(ioffset: longint);
+  var
+    href : treference;
   begin
   begin
     { sub $ioffset,offset(%esp) }
     { sub $ioffset,offset(%esp) }
-    emit_const_ref(A_SUB,S_L,ioffset,new_reference(R_ESP,getselfoffsetfromsp(procdef)));
+    reference_reset_base(href,R_ESP,getselfoffsetfromsp(procdef));
+    emit_const_ref(A_SUB,S_L,ioffset,href);
   end;
   end;
 
 
   procedure getselftoeax(offs: longint);
   procedure getselftoeax(offs: longint);
+  var
+    href : treference;
   begin
   begin
     { mov offset(%esp),%eax }
     { mov offset(%esp),%eax }
-    emit_ref_reg(A_MOV,S_L,new_reference(R_ESP,getselfoffsetfromsp(procdef)),R_EAX);
+    reference_reset_base(href,R_ESP,getselfoffsetfromsp(procdef));
+    emit_ref_reg(A_MOV,S_L,href,R_EAX);
   end;
   end;
 
 
   procedure loadvmttoeax;
   procedure loadvmttoeax;
+  var
+    href : treference;
   begin
   begin
     checkvirtual;
     checkvirtual;
     { mov  0(%eax),%eax ; load vmt}
     { mov  0(%eax),%eax ; load vmt}
-    emit_ref_reg(A_MOV,S_L,new_reference(R_EAX,0),R_EAX);
+    reference_reset_base(href,R_EAX,0);
+    emit_ref_reg(A_MOV,S_L,href,R_EAX);
   end;
   end;
 
 
   procedure op_oneaxmethodaddr(op: TAsmOp);
   procedure op_oneaxmethodaddr(op: TAsmOp);
+  var
+    href : treference;
   begin
   begin
     { call/jmp  vmtoffs(%eax) ; method offs }
     { call/jmp  vmtoffs(%eax) ; method offs }
-    emit_ref(op,S_L,new_reference(R_EAX,procdef._class.vmtmethodoffset(procdef.extnumber)));
+    reference_reset_base(href,R_EAX,procdef._class.vmtmethodoffset(procdef.extnumber));
+    emit_ref(op,S_L,href);
   end;
   end;
 
 
   procedure loadmethodoffstoeax;
   procedure loadmethodoffstoeax;
+  var
+    href : treference;
   begin
   begin
     { mov  vmtoffs(%eax),%eax ; method offs }
     { mov  vmtoffs(%eax),%eax ; method offs }
-    emit_ref_reg(A_MOV,S_L,new_reference(R_EAX,procdef._class.vmtmethodoffset(procdef.extnumber)),R_EAX);
+    reference_reset_base(href,R_EAX,procdef._class.vmtmethodoffset(procdef.extnumber));
+    emit_ref_reg(A_MOV,S_L,href,R_EAX);
   end;
   end;
 
 
 var
 var
   oldexprasmlist: TAAsmoutput;
   oldexprasmlist: TAAsmoutput;
   lab : tasmsymbol;
   lab : tasmsymbol;
   make_global : boolean;
   make_global : boolean;
+  href : treference;
 begin
 begin
   if procdef.proctypeoption<>potype_none then
   if procdef.proctypeoption<>potype_none then
     Internalerror(200006137);
     Internalerror(200006137);
@@ -194,7 +210,8 @@ begin
       loadvmttoeax;
       loadvmttoeax;
       loadmethodoffstoeax;
       loadmethodoffstoeax;
       { mov %eax,4(%esp) }
       { mov %eax,4(%esp) }
-      emit_reg_ref(A_MOV,S_L,R_EAX,new_reference(R_ESP,4));
+      reference_reset_base(href,R_ESP,4);
+      emit_reg_ref(A_MOV,S_L,R_EAX,href);
       { pop  %eax }
       { pop  %eax }
       emit_reg(A_POP,S_L,R_EAX);
       emit_reg(A_POP,S_L,R_EAX);
       { ret  ; jump to the address }
       { ret  ; jump to the address }
@@ -222,7 +239,18 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2002-03-31 20:26:39  jonas
+  Revision 1.6  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.5  2002/03/31 20:26:39  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 37 - 32
compiler/i386/n386opt.pas

@@ -41,7 +41,7 @@ type
 
 
 implementation
 implementation
 
 
-uses pass_1, types, htypechk, cgbase, cpubase, cga,
+uses pass_1, types, htypechk, cginfo, cgbase, cpubase, cga,
      tgobj, aasm, ncnv, ncon, pass_2, symdef, rgobj;
      tgobj, aasm, ncnv, ncon, pass_2, symdef, rgobj;
 
 
 
 
@@ -71,7 +71,7 @@ begin
   firstpass(right);
   firstpass(right);
   if codegenerror then
   if codegenerror then
     exit;
     exit;
-  location.loc := LOC_MEM;
+  location.loc := LOC_CREFERENCE;
   if not is_constcharnode(right) then
   if not is_constcharnode(right) then
     { it's not sure we need the register, but we can't know it here yet }
     { it's not sure we need the register, but we can't know it here yet }
     calcregisters(self,2,0,0)
     calcregisters(self,2,0,0)
@@ -83,8 +83,7 @@ end;
 procedure ti386addsstringcharoptnode.pass_2;
 procedure ti386addsstringcharoptnode.pass_2;
 var
 var
   l: tasmlabel;
   l: tasmlabel;
-  href2: preference;
-  href:  treference;
+  href,href2 :  treference;
   hreg, lengthreg: tregister;
   hreg, lengthreg: tregister;
   checklength: boolean;
   checklength: boolean;
 begin
 begin
@@ -100,8 +99,7 @@ begin
        { release the registers }
        { release the registers }
        tg.ungetiftemp(exprasmlist,left.location.reference);
        tg.ungetiftemp(exprasmlist,left.location.reference);
        { does not hurt: }
        { does not hurt: }
-       clear_location(left.location);
-       left.location.loc:=LOC_MEM;
+       location_reset(left.location,LOC_CREFERENCE,def_cgsize_ref(resulttype.def));
        left.location.reference:=href;
        left.location.reference:=href;
     end;
     end;
   secondpass(right);
   secondpass(right);
@@ -114,14 +112,13 @@ begin
   { is it a constant char? }
   { is it a constant char? }
   if not is_constcharnode(right) then
   if not is_constcharnode(right) then
     { no, make sure it is in a register }
     { no, make sure it is in a register }
-    if right.location.loc in [LOC_REFERENCE,LOC_MEM] then
+    if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
       begin
       begin
         { free the registers of right }
         { free the registers of right }
-        rg.del_reference(exprasmlist,right.location.reference);
+        reference_release(exprasmlist,right.location.reference);
         { get register for the char }
         { get register for the char }
         hreg := reg32toreg8(rg.getregisterint(exprasmlist));
         hreg := reg32toreg8(rg.getregisterint(exprasmlist));
-        emit_ref_reg(A_MOV,S_B,
-          newreference(right.location.reference),hreg);
+        emit_ref_reg(A_MOV,S_B,right.location.reference,hreg);
        { I don't think a temp char exists, but it won't hurt (JM) }
        { I don't think a temp char exists, but it won't hurt (JM) }
        tg.ungetiftemp(exprasmlist,right.location.reference);
        tg.ungetiftemp(exprasmlist,right.location.reference);
       end
       end
@@ -129,7 +126,7 @@ begin
 
 
   { load the current string length }
   { load the current string length }
   lengthreg := rg.getregisterint(exprasmlist);
   lengthreg := rg.getregisterint(exprasmlist);
-  emit_ref_reg(A_MOVZX,S_BL,newreference(left.location.reference),lengthreg);
+  emit_ref_reg(A_MOVZX,S_BL,left.location.reference,lengthreg);
 
 
   { do we have to check the length ? }
   { do we have to check the length ? }
   if tg.istemp(left.location.reference) then
   if tg.istemp(left.location.reference) then
@@ -148,31 +145,31 @@ begin
     end;
     end;
 
 
   { no, so increase the length and add the new character }
   { no, so increase the length and add the new character }
-  href2 := newreference(left.location.reference);
+  href2 := left.location.reference;
 
 
   { we need a new reference to store the character }
   { we need a new reference to store the character }
   { at the end of the string. Check if the base or }
   { at the end of the string. Check if the base or }
   { index register is still free                   }
   { index register is still free                   }
-  if (href2^.base <> R_NO) and
-     (href2^.index <> R_NO) then
+  if (href2.base <> R_NO) and
+     (href2.index <> R_NO) then
     begin
     begin
       { they're not free, so add the base reg to       }
       { they're not free, so add the base reg to       }
       { the string length (since the index can         }
       { the string length (since the index can         }
       { have a scalefactor) and use lengthreg as base  }
       { have a scalefactor) and use lengthreg as base  }
-      emit_reg_reg(A_ADD,S_L,href2^.base,lengthreg);
-      href2^.base := lengthreg;
+      emit_reg_reg(A_ADD,S_L,href2.base,lengthreg);
+      href2.base := lengthreg;
     end
     end
   else
   else
     { at least one is still free, so put EDI there }
     { at least one is still free, so put EDI there }
-    if href2^.base = R_NO then
-      href2^.base := lengthreg
+    if href2.base = R_NO then
+      href2.base := lengthreg
     else
     else
       begin
       begin
-        href2^.index := lengthreg;
-        href2^.scalefactor := 1;
+        href2.index := lengthreg;
+        href2.scalefactor := 1;
       end;
       end;
   { we need to be one position after the last char }
   { we need to be one position after the last char }
-  inc(href2^.offset);
+  inc(href2.offset);
   { store the character at the end of the string }
   { store the character at the end of the string }
   if (right.nodetype <> ordconstn) then
   if (right.nodetype <> ordconstn) then
     begin
     begin
@@ -185,12 +182,11 @@ begin
     emit_const_ref(A_MOV,S_B,tordconstnode(right).value,href2);
     emit_const_ref(A_MOV,S_B,tordconstnode(right).value,href2);
   { increase the string length }
   { increase the string length }
   emit_reg(A_INC,S_B,reg32toreg8(lengthreg));
   emit_reg(A_INC,S_B,reg32toreg8(lengthreg));
-  emit_reg_ref(A_MOV,S_B,reg32toreg8(lengthreg),
-                 newreference(left.location.reference));
+  emit_reg_ref(A_MOV,S_B,reg32toreg8(lengthreg),left.location.reference);
   rg.ungetregisterint(exprasmlist,lengthreg);
   rg.ungetregisterint(exprasmlist,lengthreg);
   if checklength then
   if checklength then
     emitlab(l);
     emitlab(l);
-  set_location(location,left.location);
+  location_copy(location,left.location);
 end;
 end;
 
 
 procedure ti386addsstringcsstringoptnode.pass_2;
 procedure ti386addsstringcsstringoptnode.pass_2;
@@ -211,8 +207,7 @@ begin
        { release the registers }
        { release the registers }
        tg.ungetiftemp(exprasmlist,left.location.reference);
        tg.ungetiftemp(exprasmlist,left.location.reference);
        { does not hurt: }
        { does not hurt: }
-       clear_location(left.location);
-       left.location.loc:=LOC_MEM;
+       location_reset(left.location,LOC_CREFERENCE,def_cgsize_ref(resulttype.def));
        left.location.reference:=href;
        left.location.reference:=href;
     end;
     end;
   secondpass(right);
   secondpass(right);
@@ -222,8 +217,7 @@ begin
   { because emitpushreferenceaddr doesn't need extra }
   { because emitpushreferenceaddr doesn't need extra }
   { 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,pushedregs,regstopush);
   { push the maximum possible length of the result }
   { push the maximum possible length of the result }
   emitpushreferenceaddr(left.location.reference);
   emitpushreferenceaddr(left.location.reference);
@@ -231,14 +225,14 @@ begin
   { deallocations in the right place if it happens }
   { deallocations in the right place if it happens }
   { too early than when it happens too late (if    }
   { too early than when it happens too late (if    }
   { the pushref needs a "lea (..),edi; push edi")  }
   { the pushref needs a "lea (..),edi; push edi")  }
-  rg.del_reference(exprasmlist,right.location.reference);
+  reference_release(exprasmlist,right.location.reference);
   emitpushreferenceaddr(right.location.reference);
   emitpushreferenceaddr(right.location.reference);
   rg.saveregvars(exprasmlist,regstopush);
   rg.saveregvars(exprasmlist,regstopush);
   emitcall('FPC_SHORTSTR_CONCAT');
   emitcall('FPC_SHORTSTR_CONCAT');
   tg.ungetiftemp(exprasmlist,right.location.reference);
   tg.ungetiftemp(exprasmlist,right.location.reference);
   maybe_loadself;
   maybe_loadself;
   rg.restoreusedregisters(exprasmlist,pushedregs);
   rg.restoreusedregisters(exprasmlist,pushedregs);
-  set_location(location,left.location);
+  location_copy(location,left.location);
 end;
 end;
 
 
 begin
 begin
@@ -248,7 +242,18 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.7  2002-03-31 20:26:39  jonas
+  Revision 1.8  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.7  2002/03/31 20:26:39  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)
@@ -266,7 +271,7 @@ end.
       and can cause hard-to-find bugs
       and can cause hard-to-find bugs
 
 
   Revision 1.6  2001/12/31 09:53:15  jonas
   Revision 1.6  2001/12/31 09:53:15  jonas
-    * changed remaining "getregister32" calls to "getregisterint"
+    * changed remaining "getregister32" calls to ":=rg.getregisterint(exprasmlist);"
 
 
   Revision 1.5  2001/08/26 13:37:00  florian
   Revision 1.5  2001/08/26 13:37:00  florian
     * some cg reorganisation
     * some cg reorganisation

+ 93 - 87
compiler/i386/n386set.pas

@@ -47,7 +47,7 @@ implementation
       globtype,systems,cpuinfo,
       globtype,systems,cpuinfo,
       verbose,globals,
       verbose,globals,
       symconst,symdef,aasm,types,
       symconst,symdef,aasm,types,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       ncon,
       ncon,
       cpubase,
       cpubase,
       cga,tgobj,n386util,regvars,rgobj;
       cga,tgobj,n386util,regvars,rgobj;
@@ -82,7 +82,7 @@ implementation
            end;
            end;
 
 
          { we doesn't modify the left side, we check only the type }
          { we doesn't modify the left side, we check only the type }
-         set_location(location,left.location);
+         location_copy(location,left.location);
        end;
        end;
 
 
 
 
@@ -103,6 +103,7 @@ implementation
          ranges     : boolean;
          ranges     : boolean;
          hr,hr2,
          hr,hr2,
          pleftreg   : tregister;
          pleftreg   : tregister;
+         href       : treference;
          opsize     : topsize;
          opsize     : topsize;
          setparts   : array[1..8] of Tsetpart;
          setparts   : array[1..8] of Tsetpart;
          i,numparts : byte;
          i,numparts : byte;
@@ -238,12 +239,11 @@ implementation
                { load the value in a register }
                { load the value in a register }
                pleftreg := rg.getexplicitregisterint(exprasmlist,R_EDI);
                pleftreg := rg.getexplicitregisterint(exprasmlist,R_EDI);
                opsize := S_L;
                opsize := S_L;
-               emit_ref_reg(A_MOVZX,S_BL,newreference(left.location.reference),
-                            pleftreg);
+               emit_ref_reg(A_MOVZX,S_BL,left.location.reference,pleftreg);
              end;
              end;
 
 
             { Get a label to jump to the end }
             { Get a label to jump to the end }
-            location.loc:=LOC_FLAGS;
+            location_reset(location,LOC_FLAGS,OS_NO);
 
 
             { It's better to use the zero flag when there are
             { It's better to use the zero flag when there are
               no ranges }
               no ranges }
@@ -276,8 +276,8 @@ implementation
                         begin
                         begin
                           rg.ungetregister(exprasmlist,pleftreg);
                           rg.ungetregister(exprasmlist,pleftreg);
                           rg.getexplicitregisterint(exprasmlist,R_EDI);
                           rg.getexplicitregisterint(exprasmlist,R_EDI);
-                          emit_ref_reg(A_LEA,S_L,
-                            new_reference(pleftreg,-setparts[i].start),R_EDI);
+                          reference_reset_base(href,pleftreg,-setparts[i].start);
+                          emit_ref_reg(A_LEA,S_L,href,R_EDI);
                           { only now change pleftreg since previous value is }
                           { only now change pleftreg since previous value is }
                           { still used in previous instruction               }
                           { still used in previous instruction               }
                           pleftreg := R_EDI;
                           pleftreg := R_EDI;
@@ -337,39 +337,44 @@ implementation
              { Now place the end label }
              { Now place the end label }
              emitlab(l);
              emitlab(l);
              case left.location.loc of
              case left.location.loc of
-            LOC_REGISTER,
-           LOC_CREGISTER : rg.ungetregister(exprasmlist,pleftreg);
-             else
-               begin
-                rg.del_reference(exprasmlist,left.location.reference);
-                rg.ungetregister(exprasmlist,R_EDI);
-               end
-             end
+               LOC_REGISTER,
+               LOC_CREGISTER :
+                 rg.ungetregister(exprasmlist,pleftreg);
+               else
+                 begin
+                   reference_release(exprasmlist,left.location.reference);
+                   rg.ungetregister(exprasmlist,R_EDI);
+                 end;
+             end;
           end
           end
          else
          else
           begin
           begin
-          { We will now generated code to check the set itself, no jmps,
-            handle smallsets separate, because it allows faster checks }
+            location_reset(location,LOC_FLAGS,OS_NO);
+
+            { We will now generated code to check the set itself, no jmps,
+              handle smallsets separate, because it allows faster checks }
             if use_small then
             if use_small then
              begin
              begin
                if left.nodetype=ordconstn then
                if left.nodetype=ordconstn then
                 begin
                 begin
                   location.resflags:=F_NE;
                   location.resflags:=F_NE;
                   case right.location.loc of
                   case right.location.loc of
-                     LOC_REGISTER,
-                     LOC_CREGISTER:
+                    LOC_REGISTER,
+                    LOC_CREGISTER:
                       begin
                       begin
                          emit_const_reg(A_TEST,S_L,
                          emit_const_reg(A_TEST,S_L,
                            1 shl (tordconstnode(left).value and 31),right.location.register);
                            1 shl (tordconstnode(left).value and 31),right.location.register);
-                         rg.ungetregisterint(exprasmlist,right.location.register);
-                       end
-                  else
-                   begin
-                     emit_const_ref(A_TEST,S_L,1 shl (tordconstnode(left).value and 31),
-                       newreference(right.location.reference));
-                     rg.del_reference(exprasmlist,right.location.reference);
-                   end;
+                      end;
+                    LOC_REFERENCE,
+                    LOC_CREFERENCE :
+                      begin
+                        emit_const_ref(A_TEST,S_L,1 shl (tordconstnode(left).value and 31),
+                           right.location.reference);
+                      end;
+                    else
+                      internalerror(200203312);
                   end;
                   end;
+                  location_release(exprasmlist,right.location);
                 end
                 end
                else
                else
                 begin
                 begin
@@ -386,10 +391,9 @@ implementation
                       { and because it's a small set we need only 5 bits }
                       { and because it's a small set we need only 5 bits }
                       { but 8 bits are easier to load               }
                       { but 8 bits are easier to load               }
                       rg.getexplicitregisterint(exprasmlist,R_EDI);
                       rg.getexplicitregisterint(exprasmlist,R_EDI);
-                      emit_ref_reg(A_MOVZX,S_BL,
-                        newreference(left.location.reference),R_EDI);
+                      emit_ref_reg(A_MOVZX,S_BL,left.location.reference,R_EDI);
                       hr:=R_EDI;
                       hr:=R_EDI;
-                      rg.del_reference(exprasmlist,left.location.reference);
+                      location_release(exprasmlist,left.location);
                     end;
                     end;
                   end;
                   end;
 
 
@@ -400,24 +404,25 @@ implementation
                             emit_reg_reg(A_BT,S_L,hr,
                             emit_reg_reg(A_BT,S_L,hr,
                               right.location.register);
                               right.location.register);
                             rg.ungetregisterint(exprasmlist,right.location.register);
                             rg.ungetregisterint(exprasmlist,right.location.register);
-                          end
-                  else
-                    begin
-                      rg.del_reference(exprasmlist,right.location.reference);
-                      if right.location.reference.is_immediate then
+                          end;
+                   LOC_CONSTANT :
                        begin
                        begin
                        { We have to load the value into a register because
                        { We have to load the value into a register because
                          btl does not accept values only refs or regs (PFV) }
                          btl does not accept values only refs or regs (PFV) }
                          hr2:=rg.getregisterint(exprasmlist);
                          hr2:=rg.getregisterint(exprasmlist);
                          emit_const_reg(A_MOV,S_L,
                          emit_const_reg(A_MOV,S_L,
-                           right.location.reference.offset,hr2);
+                           right.location.value,hr2);
                          emit_reg_reg(A_BT,S_L,hr,hr2);
                          emit_reg_reg(A_BT,S_L,hr,hr2);
                          rg.ungetregisterint(exprasmlist,hr2);
                          rg.ungetregisterint(exprasmlist,hr2);
-                       end
-                      else
-                        emit_reg_ref(A_BT,S_L,hr,
-                          newreference(right.location.reference));
-                    end;
+                       end;
+                   LOC_CREFERENCE,
+                   LOC_REFERENCE :
+                       begin
+                         location_release(exprasmlist,right.location);
+                         emit_reg_ref(A_BT,S_L,hr,right.location.reference);
+                       end;
+                     else
+                       internalerror(2002032210);
                   end;
                   end;
                   { simply to indicate EDI is deallocated here too (JM) }
                   { simply to indicate EDI is deallocated here too (JM) }
                   rg.ungetregisterint(exprasmlist,hr);
                   rg.ungetregisterint(exprasmlist,hr);
@@ -427,7 +432,7 @@ implementation
              end
              end
             else
             else
              begin
              begin
-               if right.location.reference.is_immediate then
+               if right.location.loc=LOC_CONSTANT then
                 begin
                 begin
                   location.resflags:=F_C;
                   location.resflags:=F_C;
                   getlabel(l);
                   getlabel(l);
@@ -457,7 +462,7 @@ implementation
                         { We have to load the value into a register because
                         { We have to load the value into a register because
                           btl does not accept values only refs or regs (PFV) }
                           btl does not accept values only refs or regs (PFV) }
                           hr2:=rg.getregisterint(exprasmlist);
                           hr2:=rg.getregisterint(exprasmlist);
-                          emit_const_reg(A_MOV,S_L,right.location.reference.offset,hr2);
+                          emit_const_reg(A_MOV,S_L,right.location.value,hr2);
                           emit_reg_reg(A_BT,S_L,hr,hr2);
                           emit_reg_reg(A_BT,S_L,hr,hr2);
                           rg.ungetregisterint(exprasmlist,hr2);
                           rg.ungetregisterint(exprasmlist,hr2);
                        end;
                        end;
@@ -466,46 +471,42 @@ implementation
 {$ifdef CORRECT_SET_IN_FPC}
 {$ifdef CORRECT_SET_IN_FPC}
                           if m_tp in aktmodeswitches then
                           if m_tp in aktmodeswitches then
                             begin
                             begin
-                            {***WARNING only correct if
-                              reference is 32 bits (PM) *****}
-                               emit_const_ref(A_CMP,S_L,
-                                 31,newreference(left.location.reference));
+                              {***WARNING only correct if
+                                reference is 32 bits (PM) *****}
+                               emit_const_ref(A_CMP,S_L,31,reference_copy(left.location.reference));
                             end
                             end
                           else
                           else
 {$endif CORRECT_SET_IN_FPC}
 {$endif CORRECT_SET_IN_FPC}
                             begin
                             begin
-                               emit_const_ref(A_CMP,S_B,
-                                 31,newreference(left.location.reference));
+                               emit_const_ref(A_CMP,S_B,31,left.location.reference);
                             end;
                             end;
                        emitjmp(C_NA,l);
                        emitjmp(C_NA,l);
                      { reset carry flag }
                      { reset carry flag }
                        emit_none(A_CLC,S_NO);
                        emit_none(A_CLC,S_NO);
                        emitjmp(C_NONE,l2);
                        emitjmp(C_NONE,l2);
                        emitlab(l);
                        emitlab(l);
-                       rg.del_reference(exprasmlist,left.location.reference);
+                       location_release(exprasmlist,left.location);
                        hr:=rg.getregisterint(exprasmlist);
                        hr:=rg.getregisterint(exprasmlist);
-                       emit_ref_reg(A_MOV,S_L,
-                         newreference(left.location.reference),hr);
+                       emit_ref_reg(A_MOV,S_L,left.location.reference,hr);
                      { We have to load the value into a register because
                      { We have to load the value into a register because
                        btl does not accept values only refs or regs (PFV) }
                        btl does not accept values only refs or regs (PFV) }
                        hr2:=rg.getregisterint(exprasmlist);
                        hr2:=rg.getregisterint(exprasmlist);
                        emit_const_reg(A_MOV,S_L,
                        emit_const_reg(A_MOV,S_L,
-                         right.location.reference.offset,hr2);
+                         right.location.value,hr2);
                        emit_reg_reg(A_BT,S_L,hr,hr2);
                        emit_reg_reg(A_BT,S_L,hr,hr2);
                        rg.ungetregisterint(exprasmlist,hr2);
                        rg.ungetregisterint(exprasmlist,hr2);
                     end;
                     end;
                   end;
                   end;
                   emitlab(l2);
                   emitlab(l2);
-                end { of right.location.reference.is_immediate }
+                end { of right.location.loc=LOC_CONSTANT }
                { do search in a normal set which could have >32 elementsm
                { do search in a normal set which could have >32 elementsm
                  but also used if the left side contains higher values > 32 }
                  but also used if the left side contains higher values > 32 }
                else if left.nodetype=ordconstn then
                else if left.nodetype=ordconstn then
                 begin
                 begin
                   location.resflags:=F_NE;
                   location.resflags:=F_NE;
                   inc(right.location.reference.offset,tordconstnode(left).value shr 3);
                   inc(right.location.reference.offset,tordconstnode(left).value shr 3);
-                  emit_const_ref(A_TEST,S_B,1 shl (tordconstnode(left).value and 7),
-                    newreference(right.location.reference));
-                  rg.del_reference(exprasmlist,right.location.reference);
+                  emit_const_ref(A_TEST,S_B,1 shl (tordconstnode(left).value and 7),right.location.reference);
+                  location_release(exprasmlist,right.location);
                 end
                 end
                else
                else
                 begin
                 begin
@@ -514,11 +515,11 @@ implementation
                       pleftreg := rg.getexplicitregisterint(exprasmlist,R_EDI);
                       pleftreg := rg.getexplicitregisterint(exprasmlist,R_EDI);
                       opsize := def2def_opsize(left.resulttype.def,u32bittype.def);
                       opsize := def2def_opsize(left.resulttype.def,u32bittype.def);
                       if opsize = S_L then
                       if opsize = S_L then
-                        emit_ref_reg(A_MOV,opsize,newreference(left.location.reference),pleftreg)
+                        emit_ref_reg(A_MOV,opsize,left.location.reference,pleftreg)
                       else
                       else
-                        emit_ref_reg(A_MOVZX,opsize,newreference(left.location.reference),pleftreg);
-                      tg.ungetiftemp(exprasmlist,left.location.reference);
-                      rg.del_reference(exprasmlist,left.location.reference);
+                        emit_ref_reg(A_MOVZX,opsize,left.location.reference,pleftreg);
+                      location_freetemp(exprasmlist,left.location);
+                      location_release(exprasmlist,left.location);
                     end
                     end
                   else
                   else
                     begin
                     begin
@@ -531,17 +532,15 @@ implementation
                          { any problem (JM)                                         }
                          { any problem (JM)                                         }
                          emit_to_reg32(pleftreg)
                          emit_to_reg32(pleftreg)
                     end;
                     end;
-                  emit_reg_ref(A_BT,S_L,pleftreg,newreference(right.location.reference));
+                  emit_reg_ref(A_BT,S_L,pleftreg,right.location.reference);
                   rg.ungetregister(exprasmlist,pleftreg);
                   rg.ungetregister(exprasmlist,pleftreg);
-                  rg.del_reference(exprasmlist,right.location.reference);
+                  location_release(exprasmlist,right.location);
                   { tg.ungetiftemp(exprasmlist,right.location.reference) happens below }
                   { tg.ungetiftemp(exprasmlist,right.location.reference) happens below }
-                  location.loc:=LOC_FLAGS;
                   location.resflags:=F_C;
                   location.resflags:=F_C;
                 end;
                 end;
              end;
              end;
           end;
           end;
-          if (right.location.loc in [LOC_MEM,LOC_REFERENCE]) then
-            tg.ungetiftemp(exprasmlist,right.location.reference);
+          location_freetemp(exprasmlist,right.location);
        end;
        end;
 
 
 
 
@@ -781,7 +780,7 @@ implementation
         var
         var
            table : tasmlabel;
            table : tasmlabel;
            last : TConstExprInt;
            last : TConstExprInt;
-           hr : preference;
+           href : treference;
 
 
         procedure genitem(t : pcaserecord);
         procedure genitem(t : pcaserecord);
 
 
@@ -832,13 +831,11 @@ implementation
                     reg8toreg32(hregister));
                     reg8toreg32(hregister));
                 hregister:=reg8toreg32(hregister);
                 hregister:=reg8toreg32(hregister);
              end;
              end;
-           new(hr);
-           reset_reference(hr^);
-           hr^.symbol:=table;
-           hr^.offset:=(-longint(min_))*4;
-           hr^.index:=hregister;
-           hr^.scalefactor:=4;
-           emit_ref(A_JMP,S_NO,hr);
+           reference_reset_symbol(href,table,0);
+           href.offset:=(-longint(min_))*4;
+           href.index:=hregister;
+           href.scalefactor:=4;
+           emit_ref(A_JMP,S_NO,href);
            { !!!!! generate tables
            { !!!!! generate tables
              if not(cs_littlesize in aktlocalswitches) then
              if not(cs_littlesize in aktlocalswitches) then
              jumpSegment.concat(Taicpu.Op_const(A_ALIGN,S_NO,4));
              jumpSegment.concat(Taicpu.Op_const(A_ALIGN,S_NO,4));
@@ -863,7 +860,7 @@ implementation
 {$else Delphi}
 {$else Delphi}
          dist : dword;
          dist : dword;
 {$endif Delphi}
 {$endif Delphi}
-         hr : preference;
+         href : treference;
 
 
       begin
       begin
          getlabel(endlabel);
          getlabel(endlabel);
@@ -934,17 +931,17 @@ implementation
                  if opsize=S_Q then
                  if opsize=S_Q then
                    begin
                    begin
                       emit_reg_reg(A_MOV,S_L,left.location.registerlow,hregister);
                       emit_reg_reg(A_MOV,S_L,left.location.registerlow,hregister);
-                      hr:=newreference(left.location.reference);
-                      inc(hr^.offset,4);
+                      href:=left.location.reference;
+                      inc(href.offset,4);
                       emit_reg_reg(A_MOV,S_L,left.location.registerhigh,hregister2);
                       emit_reg_reg(A_MOV,S_L,left.location.registerhigh,hregister2);
                    end
                    end
                  else
                  else
                    emit_reg_reg(A_MOV,opsize,
                    emit_reg_reg(A_MOV,opsize,
                      left.location.register,hregister);
                      left.location.register,hregister);
               end;
               end;
-            LOC_MEM,LOC_REFERENCE:
+            LOC_CREFERENCE,LOC_REFERENCE:
               begin
               begin
-                 rg.del_reference(exprasmlist,left.location.reference);
+                 location_release(exprasmlist,left.location);
                  hregister:=rg.getregisterint(exprasmlist);
                  hregister:=rg.getregisterint(exprasmlist);
                  case opsize of
                  case opsize of
                     S_B:
                     S_B:
@@ -956,15 +953,13 @@ implementation
                  end;
                  end;
                  if opsize=S_Q then
                  if opsize=S_Q then
                    begin
                    begin
-                      emit_ref_reg(A_MOV,S_L,newreference(
-                        left.location.reference),hregister);
-                      hr:=newreference(left.location.reference);
-                      inc(hr^.offset,4);
-                      emit_ref_reg(A_MOV,S_L,hr,hregister2);
+                      emit_ref_reg(A_MOV,S_L,left.location.reference,hregister);
+                      href:=left.location.reference;
+                      inc(href.offset,4);
+                      emit_ref_reg(A_MOV,S_L,href,hregister2);
                    end
                    end
                  else
                  else
-                   emit_ref_reg(A_MOV,opsize,newreference(
-                     left.location.reference),hregister);
+                   emit_ref_reg(A_MOV,opsize,left.location.reference,hregister);
               end;
               end;
             else internalerror(2002);
             else internalerror(2002);
          end;
          end;
@@ -1092,7 +1087,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.20  2002-03-31 20:26:39  jonas
+  Revision 1.21  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.20  2002/03/31 20:26:39  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 341 - 209
compiler/i386/n386util.pas

@@ -27,7 +27,9 @@ unit n386util;
 interface
 interface
 
 
     uses
     uses
-      symtype,node;
+      symtype,node,cpubase,cginfo;
+
+    procedure location_force_reg(var l:tlocation;size:TCGSize;maybeconst:boolean);
 
 
     function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
     function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
     function maybe_pushfpu(needed : byte;p : tnode) : boolean;
     function maybe_pushfpu(needed : byte;p : tnode) : boolean;
@@ -55,7 +57,7 @@ implementation
     uses
     uses
        globtype,globals,systems,verbose,
        globtype,globals,systems,verbose,
        cutils,
        cutils,
-       aasm,cpubase,cpuasm,cpuinfo,
+       aasm,cpuasm,cpuinfo,
        symconst,symbase,symdef,symsym,symtable,
        symconst,symbase,symdef,symsym,symtable,
 {$ifdef GDB}
 {$ifdef GDB}
        gdb,
        gdb,
@@ -64,7 +66,174 @@ implementation
        ncon,nld,
        ncon,nld,
        pass_1,pass_2,
        pass_1,pass_2,
        cgbase,tgobj,
        cgbase,tgobj,
-       cga,regvars,cgobj,rgobj,rgcpu;
+       cga,regvars,cgobj,cg64f32,rgobj,rgcpu;
+
+
+    procedure location_force_reg(var l:tlocation;size:TCGSize;maybeconst:boolean);
+      var
+        hregister,
+        hregisterhi : tregister;
+        hl : tasmlabel;
+      begin
+        { release previous location before demanding a new register }
+        if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+         begin
+           location_freetemp(exprasmlist,l);
+           location_release(exprasmlist,l);
+         end;
+        { handle transformations to 64bit separate }
+        if size in [OS_64,OS_S64] then
+         begin
+           if not (l.size in [OS_64,OS_S64]) then
+            begin
+              { load a smaller size to OS_64 }
+              if l.loc=LOC_REGISTER then
+               hregister:=makereg32(l.registerlow)
+              else
+               hregister:=rg.getregisterint(exprasmlist);
+              { load value in low register }
+              case l.loc of
+                LOC_FLAGS :
+                  cg.g_flags2reg(exprasmlist,l.resflags,hregister);
+                LOC_JUMP :
+                  begin
+                    cg.a_label(exprasmlist,truelabel);
+                    cg.a_load_const_reg(exprasmlist,OS_32,1,hregister);
+                    getlabel(hl);
+                    cg.a_jmp_cond(exprasmlist,OC_NONE,hl);
+                    cg.a_label(exprasmlist,falselabel);
+                    cg.a_load_const_reg(exprasmlist,OS_32,0,hregister);
+                    cg.a_label(exprasmlist,hl);
+                  end;
+                else
+                  cg.a_load_loc_reg(exprasmlist,l.size,l,hregister);
+              end;
+              { reset hi part, take care of the signed bit of the current value }
+              hregisterhi:=rg.getregisterint(exprasmlist);
+              if (size=OS_S64) and
+                 (l.size in [OS_S8,OS_S16,OS_S32]) then
+               begin
+                 if l.loc=LOC_CONSTANT then
+                  begin
+                    if (longint(l.value)<0) then
+                     cg.a_load_const_reg(exprasmlist,OS_32,$ffffffff,hregisterhi)
+                    else
+                     cg.a_load_const_reg(exprasmlist,OS_32,0,hregisterhi);
+                  end
+                 else
+                  begin
+                    cg.a_load_reg_reg(exprasmlist,OS_32,hregister,hregisterhi);
+                    cg.a_op_const_reg(exprasmlist,OP_SAR,31,hregisterhi);
+                  end;
+               end
+              else
+               cg.a_load_const_reg(exprasmlist,OS_32,0,hregisterhi);
+              location_reset(l,LOC_REGISTER,size);
+              l.registerlow:=hregister;
+              l.registerhigh:=hregisterhi;
+            end
+           else
+            begin
+              { 64bit to 64bit }
+              if (l.loc=LOC_REGISTER) or
+                 ((l.loc=LOC_CREGISTER) and maybeconst) then
+               begin
+                 hregister:=l.registerlow;
+                 hregisterhi:=l.registerhigh;
+               end
+              else
+               begin
+                 hregister:=rg.getregisterint(exprasmlist);
+                 hregisterhi:=rg.getregisterint(exprasmlist);
+               end;
+              { load value in new register }
+              tcg64f32(cg).a_load64_loc_reg(exprasmlist,l,hregister,hregisterhi);
+              location_reset(l,LOC_REGISTER,size);
+              l.registerlow:=hregister;
+              l.registerhigh:=hregisterhi;
+            end;
+         end
+        else
+         begin
+           { transformations to 32bit or smaller }
+           if l.loc=LOC_REGISTER then
+            begin
+              { if the previous was 64bit release the high register }
+              if l.size in [OS_64,OS_S64] then
+               begin
+                 rg.ungetregisterint(exprasmlist,l.registerhigh);
+                 l.registerhigh:=R_NO;
+               end;
+              case size of
+                OS_8,OS_S8 :
+                  hregister:=makereg8(l.register);
+                OS_16,OS_S16 :
+                  hregister:=makereg16(l.register);
+                OS_32,OS_S32 :
+                  hregister:=makereg32(l.register);
+              end;
+            end
+           else
+            begin
+              { get new register }
+              if (l.loc=LOC_CREGISTER) and
+                 maybeconst and
+                 (TCGSize2Size[size]=TCGSize2Size[l.size]) then
+               hregister:=l.register
+              else
+               begin
+                 hregister:=rg.getregisterint(exprasmlist);
+                 case size of
+                   OS_8,OS_S8 :
+                     hregister:=makereg8(hregister);
+                   OS_16,OS_S16 :
+                     hregister:=makereg16(hregister);
+                 end;
+               end;
+            end;
+           { load value in new register }
+           case l.loc of
+             LOC_FLAGS :
+               cg.g_flags2reg(exprasmlist,l.resflags,hregister);
+             LOC_JUMP :
+               begin
+                 cg.a_label(exprasmlist,truelabel);
+                 cg.a_load_const_reg(exprasmlist,size,1,hregister);
+                 getlabel(hl);
+                 cg.a_jmp_cond(exprasmlist,OC_NONE,hl);
+                 cg.a_label(exprasmlist,falselabel);
+                 cg.a_load_const_reg(exprasmlist,size,0,hregister);
+                 cg.a_label(exprasmlist,hl);
+               end;
+             else
+               begin
+                 { load_loc_reg can only handle size >= l.size, when the
+                   new size is smaller then we need to adjust the size
+                   of the orignal and maybe recalculate l.register }
+                 if (TCGSize2Size[size]<TCGSize2Size[l.size]) then
+                  begin
+                    if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+                     begin
+                       case size of
+                         OS_8,OS_S8 :
+                           l.register:=makereg8(l.register);
+                         OS_16,OS_S16 :
+                           l.register:=makereg16(l.register);
+                         OS_32,OS_S32 :
+                           l.register:=makereg32(l.register);
+                         else
+                           internalerror(200203295);
+                       end;
+                     end;
+                    l.size:=size;
+                  end;
+                 cg.a_load_loc_reg(exprasmlist,l.size,l,hregister);
+               end;
+           end;
+           location_reset(l,LOC_REGISTER,size);
+           l.register:=hregister;
+         end;
+      end;
 
 
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -117,14 +286,14 @@ implementation
 {$endif TEMPS_NOT_PUSH}
 {$endif TEMPS_NOT_PUSH}
                    rg.ungetregisterint(exprasmlist,p.location.register);
                    rg.ungetregisterint(exprasmlist,p.location.register);
                 end
                 end
-              else if (p.location.loc in [LOC_MEM,LOC_REFERENCE]) and
+              else if (p.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
                       ((p.location.reference.base<>R_NO) or
                       ((p.location.reference.base<>R_NO) or
                        (p.location.reference.index<>R_NO)
                        (p.location.reference.index<>R_NO)
                       ) then
                       ) then
                   begin
                   begin
-                     rg.del_reference(exprasmlist,p.location.reference);
+                     reference_release(exprasmlist,p.location.reference);
                      rg.getexplicitregisterint(exprasmlist,R_EDI);
                      rg.getexplicitregisterint(exprasmlist,R_EDI);
-                     emit_ref_reg(A_LEA,S_L,newreference(p.location.reference),R_EDI);
+                     emit_ref_reg(A_LEA,S_L,p.location.reference,R_EDI);
 {$ifdef TEMPS_NOT_PUSH}
 {$ifdef TEMPS_NOT_PUSH}
                      tg.gettempofsizereference(exprasmlist,href,4);
                      tg.gettempofsizereference(exprasmlist,href,4);
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
@@ -146,7 +315,7 @@ implementation
        begin
        begin
          if needed>=maxfpuregs then
          if needed>=maxfpuregs then
            begin
            begin
-             if p.location.loc = LOC_FPU then
+             if p.location.loc = LOC_FPUREGISTER then
                begin
                begin
                  emit_to_mem(p.location,p.resulttype.def);
                  emit_to_mem(p.location,p.resulttype.def);
                  maybe_pushfpu:=true;
                  maybe_pushfpu:=true;
@@ -194,9 +363,9 @@ implementation
                        (p^.location.reference.index<>R_NO)
                        (p^.location.reference.index<>R_NO)
                       ) then
                       ) then
                   begin
                   begin
-                     rg.del_reference(exprasmlist,p^.location.reference);
+                     reference_release(p^.location.reference);
                      rg.getexplicitregisterint(exprasmlist,R_EDI);
                      rg.getexplicitregisterint(exprasmlist,R_EDI);
-                     emit_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
+                     emit_ref_reg(A_LEA,S_L,reference_copy(p^.location.reference),
                        R_EDI);
                        R_EDI);
                      tg.gettempofsizereference(exprasmlist,href,4);
                      tg.gettempofsizereference(exprasmlist,href,4);
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
@@ -251,7 +420,7 @@ implementation
            end
            end
          else
          else
            begin
            begin
-              reset_reference(p.location.reference);
+              reference_reset(p.location.reference);
               { any reasons why this was moved into the index register ? }
               { any reasons why this was moved into the index register ? }
               { normally usage of base register is much better (FK)      }
               { normally usage of base register is much better (FK)      }
               p.location.reference.base:=hregister;
               p.location.reference.base:=hregister;
@@ -350,7 +519,7 @@ implementation
                { because this may cross a page boundary and you'll get a }
                { because this may cross a page boundary and you'll get a }
                { sigsegv (JM)                                            }
                { sigsegv (JM)                                            }
                emit_push_mem_size(p.location.reference,1);
                emit_push_mem_size(p.location.reference,1);
-               rg.del_reference(exprasmlist,p.location.reference);
+               reference_release(exprasmlist,p.location.reference);
              end;
              end;
            end;
            end;
          end;
          end;
@@ -360,100 +529,103 @@ implementation
                                 para_offset:longint;alignment : longint);
                                 para_offset:longint;alignment : longint);
       var
       var
         tempreference : treference;
         tempreference : treference;
-        r : preference;
+        r : treference;
         opsize : topsize;
         opsize : topsize;
-        op : tasmop;
         hreg : tregister;
         hreg : tregister;
         size : longint;
         size : longint;
         hlabel : tasmlabel;
         hlabel : tasmlabel;
+        cgsize : tcgsize;
       begin
       begin
         case p.location.loc of
         case p.location.loc of
            LOC_REGISTER,
            LOC_REGISTER,
            LOC_CREGISTER:
            LOC_CREGISTER:
              begin
              begin
-                  if p.resulttype.def.size=8 then
-                    begin
-                       inc(pushedparasize,8);
-                       if inlined then
-                         begin
-                            r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                            exprasmlist.concat(taicpu.op_reg_ref(A_MOV,S_L,p.location.registerlow,r));
-                            r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
-                            exprasmlist.concat(taicpu.op_reg_ref(A_MOV,S_L,p.location.registerhigh,r));
-                         end
-                       else
-                         begin
-                           exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,p.location.registerhigh));
-                           exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,p.location.registerlow));
-                         end;
-                       rg.ungetregisterint(exprasmlist,p.location.registerhigh);
-                       rg.ungetregisterint(exprasmlist,p.location.registerlow);
-                    end
-                  else case p.location.register of
-                   R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,
-                   R_EDI,R_ESP,R_EBP :
+               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(r,procinfo^.framepointer,para_offset-pushedparasize);
+                     tcg64f32(cg).a_load64_loc_ref(exprasmlist,p.location,r);
+                   end
+                  else
+                   tcg64f32(cg).a_param64_loc(exprasmlist,p.location,-1);
+                end
+               else
+                begin
+                  { save old register }
+                  hreg:=p.location.register;
+                  { update register to use to match alignment }
+                  case cgsize of
+                    OS_8,OS_S8 :
                       begin
                       begin
-                        inc(pushedparasize,4);
-                        if inlined then
+                        if alignment=4 then
                          begin
                          begin
-                           r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                           exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,p.location.register,r));
+                           p.location.register:=makereg32(p.location.register);
+                           cgsize:=OS_32;
                          end
                          end
                         else
                         else
-                         exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.location.register));
-                        rg.ungetregisterint(exprasmlist,p.location.register);
-                      end;
-                   R_AX,R_BX,R_CX,R_DX,R_SI,R_DI:
-                      begin
-                        if alignment=4 then
-                          begin
-                            opsize:=S_L;
-                            hreg:=reg16toreg32(p.location.register);
-                            inc(pushedparasize,4);
-                          end
-                        else
-                          begin
-                            opsize:=S_W;
-                            hreg:=p.location.register;
-                            inc(pushedparasize,2);
-                          end;
-                        if inlined then
-                          begin
-                            r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                            exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
-                          end
-                        else
-                          exprasmList.concat(Taicpu.Op_reg(A_PUSH,opsize,hreg));
-                        rg.ungetregisterint(exprasmlist,reg16toreg32(p.location.register));
+                         begin
+                           p.location.register:=makereg16(p.location.register);
+                           cgsize:=OS_16;
+                         end;
                       end;
                       end;
-                   R_AL,R_BL,R_CL,R_DL:
+                    OS_16,OS_S16 :
                       begin
                       begin
                         if alignment=4 then
                         if alignment=4 then
-                          begin
-                            opsize:=S_L;
-                            hreg:=reg8toreg32(p.location.register);
-                            inc(pushedparasize,4);
-                          end
-                        else
-                          begin
-                            opsize:=S_W;
-                            hreg:=reg8toreg16(p.location.register);
-                            inc(pushedparasize,2);
-                          end;
-                        { we must push always 16 bit }
-                        if inlined then
-                          begin
-                            r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                            exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
-                          end
-                        else
-                          exprasmList.concat(Taicpu.Op_reg(A_PUSH,opsize,hreg));
-                        rg.ungetregisterint(exprasmlist,reg8toreg32(p.location.register));
+                         begin
+                           p.location.register:=makereg32(p.location.register);
+                           cgsize:=OS_32;
+                         end;
                       end;
                       end;
-                   else internalerror(1899);
+                  end;
+                  inc(pushedparasize,alignment);
+                  if inlined then
+                   begin
+                     reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
+                     cg.a_load_loc_ref(exprasmlist,cgsize,p.location,r);
+                   end
+                  else
+                   cg.a_param_loc(exprasmlist,cgsize,p.location,-1);
+                  { restore old register }
+                  p.location.register:=hreg;
                 end;
                 end;
+               location_release(exprasmlist,p.location);
              end;
              end;
-           LOC_FPU, LOC_CFPUREGISTER:
+           LOC_CONSTANT :
+             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(r,procinfo^.framepointer,para_offset-pushedparasize);
+                     tcg64f32(cg).a_load64_loc_ref(exprasmlist,p.location,r);
+                   end
+                  else
+                   tcg64f32(cg).a_param64_loc(exprasmlist,p.location,-1);
+                end
+               else
+                begin
+                  if alignment=4 then
+                   cgsize:=OS_32
+                  else
+                   cgsize:=OS_16;
+                  inc(pushedparasize,alignment);
+                  if inlined then
+                   begin
+                     reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
+                     cg.a_load_loc_ref(exprasmlist,cgsize,p.location,r);
+                   end
+                  else
+                   cg.a_param_loc(exprasmlist,cgsize,p.location,-1);
+                end;
+               location_release(exprasmlist,p.location);
+             end;
+           LOC_FPUREGISTER,
+           LOC_CFPUREGISTER:
              begin
              begin
                 size:=align(tfloatdef(p.resulttype.def).size,alignment);
                 size:=align(tfloatdef(p.resulttype.def).size,alignment);
                 inc(pushedparasize,size);
                 inc(pushedparasize,size);
@@ -464,22 +636,20 @@ implementation
                    (exprasmList.first=exprasmList.last) then
                    (exprasmList.first=exprasmList.last) then
                   exprasmList.concat(Tai_force_line.Create);
                   exprasmList.concat(Tai_force_line.Create);
 {$endif GDB}
 {$endif GDB}
-                r:=new_reference(R_ESP,0);
+
                 { this is the easiest case for inlined !! }
                 { this is the easiest case for inlined !! }
                 if inlined then
                 if inlined then
-                  begin
-                     r^.base:=procinfo^.framepointer;
-                     r^.offset:=para_offset-pushedparasize;
-                  end;
+                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize)
+                else
+                 reference_reset_base(r,R_ESP,0);
 
 
                 cg.a_loadfpu_reg_ref(exprasmlist,
                 cg.a_loadfpu_reg_ref(exprasmlist,
-                  def_cgsize(p.resulttype.def),p.location.register,r^);
-                dispose(r);
+                  def_cgsize(p.resulttype.def),p.location.register,r);
              end;
              end;
-           LOC_REFERENCE,LOC_MEM:
+           LOC_REFERENCE,LOC_CREFERENCE:
              begin
              begin
                 tempreference:=p.location.reference;
                 tempreference:=p.location.reference;
-                rg.del_reference(exprasmlist,p.location.reference);
+                reference_release(exprasmlist,p.location.reference);
                 case p.resulttype.def.deftype of
                 case p.resulttype.def.deftype of
                   enumdef,
                   enumdef,
                   orddef :
                   orddef :
@@ -490,16 +660,12 @@ implementation
                              if inlined then
                              if inlined then
                                begin
                                begin
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                 emit_ref_reg(A_MOV,S_L,
-                                   newreference(tempreference),R_EDI);
-                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
-                                 rg.ungetregisterint(exprasmlist,R_EDI);
-                                 rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  inc(tempreference.offset,4);
                                  inc(tempreference.offset,4);
-                                 emit_ref_reg(A_MOV,S_L,
-                                   newreference(tempreference),R_EDI);
-                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
+                                 emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize+4);
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                end
                                end
@@ -516,9 +682,8 @@ implementation
                              if inlined then
                              if inlined then
                                begin
                                begin
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                 emit_ref_reg(A_MOV,S_L,
-                                   newreference(tempreference),R_EDI);
-                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                end
                                end
@@ -541,9 +706,8 @@ implementation
                              if inlined then
                              if inlined then
                               begin
                               begin
                                 rg.getexplicitregisterint(exprasmlist,R_EDI);
                                 rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                emit_ref_reg(A_MOV,opsize,
-                                  newreference(tempreference),hreg);
-                                r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                emit_ref_reg(A_MOV,opsize,tempreference,hreg);
+                                reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                 exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
                                 exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
                                 rg.ungetregisterint(exprasmlist,R_EDI);
                                 rg.ungetregisterint(exprasmlist,R_EDI);
                               end
                               end
@@ -563,9 +727,8 @@ implementation
                              if inlined then
                              if inlined then
                                begin
                                begin
                                   rg.getexplicitregisterint(exprasmlist,R_EDI);
                                   rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                  emit_ref_reg(A_MOV,S_L,
-                                    newreference(tempreference),R_EDI);
-                                  r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                  emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                                  reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                   exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                   exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                   rg.ungetregisterint(exprasmlist,R_EDI);
                                   rg.ungetregisterint(exprasmlist,R_EDI);
                                end
                                end
@@ -580,9 +743,8 @@ implementation
                             if inlined then
                             if inlined then
                               begin
                               begin
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                 emit_ref_reg(A_MOV,S_L,
-                                   newreference(tempreference),R_EDI);
-                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
                               end
@@ -593,9 +755,8 @@ implementation
                             if inlined then
                             if inlined then
                               begin
                               begin
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                 emit_ref_reg(A_MOV,S_L,
-                                   newreference(tempreference),R_EDI);
-                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
                               end
@@ -612,9 +773,8 @@ implementation
                             if inlined then
                             if inlined then
                               begin
                               begin
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                 emit_ref_reg(A_MOV,S_L,
-                                   newreference(tempreference),R_EDI);
-                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
                               end
@@ -625,9 +785,8 @@ implementation
                             if inlined then
                             if inlined then
                               begin
                               begin
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                 emit_ref_reg(A_MOV,S_L,
-                                   newreference(tempreference),R_EDI);
-                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
                               end
@@ -650,15 +809,13 @@ implementation
                             if inlined then
                             if inlined then
                               begin
                               begin
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  rg.getexplicitregisterint(exprasmlist,R_EDI);
-                                 emit_ref_reg(A_MOV,opsize,
-                                   newreference(tempreference),hreg);
-                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 emit_ref_reg(A_MOV,opsize,tempreference,hreg);
+                                 reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
                                  exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
                               end
                             else
                             else
-                              exprasmList.concat(Taicpu.Op_ref(A_PUSH,opsize,
-                                newreference(tempreference)));
+                              exprasmList.concat(Taicpu.Op_ref(A_PUSH,opsize,tempreference));
                         end;
                         end;
                       end;
                       end;
                     end;
                     end;
@@ -670,9 +827,8 @@ implementation
                        if inlined then
                        if inlined then
                          begin
                          begin
                             rg.getexplicitregisterint(exprasmlist,R_EDI);
                             rg.getexplicitregisterint(exprasmlist,R_EDI);
-                            emit_ref_reg(A_MOV,S_L,
-                              newreference(tempreference),R_EDI);
-                            r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                            emit_ref_reg(A_MOV,S_L,tempreference,R_EDI);
+                            reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                             exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                             exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,r));
                             rg.ungetregisterint(exprasmlist,R_EDI);
                             rg.ungetregisterint(exprasmlist,R_EDI);
                          end
                          end
@@ -707,8 +863,8 @@ implementation
                                 inc(pushedparasize,4);
                                 inc(pushedparasize,4);
                                 if inlined then
                                 if inlined then
                                   begin
                                   begin
-                                    r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                                    concatcopy(tempreference,r^,4,false,false);
+                                    reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
+                                    concatcopy(tempreference,r,4,false,false);
                                   end
                                   end
                                 else
                                 else
                                   emit_push_mem(tempreference);
                                   emit_push_mem(tempreference);
@@ -720,11 +876,11 @@ implementation
                                     inc(pushedparasize,2);
                                     inc(pushedparasize,2);
                                     if inlined then
                                     if inlined then
                                       begin
                                       begin
-                                        r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
-                                        concatcopy(tempreference,r^,2,false,false);
+                                        reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
+                                        concatcopy(tempreference,r,2,false,false);
                                       end
                                       end
                                     else
                                     else
-                                      exprasmList.concat(Taicpu.Op_ref(A_PUSH,S_W,newreference(tempreference)));
+                                      exprasmList.concat(Taicpu.Op_ref(A_PUSH,S_W,tempreference));
                                   end;
                                   end;
                               end;
                               end;
                          end
                          end
@@ -735,9 +891,8 @@ implementation
                            size:=align(p.resulttype.def.size,alignment);
                            size:=align(p.resulttype.def.size,alignment);
                            inc(pushedparasize,size);
                            inc(pushedparasize,size);
                            emit_const_reg(A_SUB,S_L,size,R_ESP);
                            emit_const_reg(A_SUB,S_L,size,R_ESP);
-                           r:=new_reference(R_ESP,0);
-                           concatcopy(tempreference,r^,size,false,false);
-                           dispose(r);
+                           reference_reset_base(r,R_ESP,0);
+                           concatcopy(tempreference,r,size,false,false);
                          end
                          end
                        else
                        else
                          internalerror(8954);
                          internalerror(8954);
@@ -762,7 +917,7 @@ implementation
                 emitlab(truelabel);
                 emitlab(truelabel);
                 if inlined then
                 if inlined then
                   begin
                   begin
-                     r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                     reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                      emit_const_ref(A_MOV,opsize,1,r);
                      emit_const_ref(A_MOV,opsize,1,r);
                   end
                   end
                 else
                 else
@@ -771,7 +926,7 @@ implementation
                 emitlab(falselabel);
                 emitlab(falselabel);
                 if inlined then
                 if inlined then
                   begin
                   begin
-                     r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                     reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                      emit_const_ref(A_MOV,opsize,0,r);
                      emit_const_ref(A_MOV,opsize,0,r);
                   end
                   end
                 else
                 else
@@ -801,7 +956,7 @@ implementation
                  end;
                  end;
                 if inlined then
                 if inlined then
                   begin
                   begin
-                     r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                     reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,opsize,hreg,r));
                   end
                   end
                 else
                 else
@@ -826,13 +981,13 @@ implementation
 {$endif GDB}
 {$endif GDB}
                 if inlined then
                 if inlined then
                   begin
                   begin
-                     r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                     reference_reset_base(r,procinfo^.framepointer,para_offset-pushedparasize);
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,
                        p.location.register,r));
                        p.location.register,r));
                   end
                   end
                 else
                 else
                    begin
                    begin
-                      r:=new_reference(R_ESP,0);
+                      reference_reset_base(r,R_ESP,0);
                       exprasmList.concat(Taicpu.Op_reg_ref(
                       exprasmList.concat(Taicpu.Op_reg_ref(
                         A_MOVQ,S_NO,p.location.register,r));
                         A_MOVQ,S_NO,p.location.register,r));
                    end;
                    end;
@@ -880,11 +1035,11 @@ implementation
                internalerror(234234);
                internalerror(234234);
            end
            end
          else
          else
-           if (((p.location.loc=LOC_FPU) and
+           if (((p.location.loc=LOC_FPUREGISTER) and
                 (p.right.registersfpu > p.left.registersfpu)) or
                 (p.right.registersfpu > p.left.registersfpu)) or
                ((((p.left.registersfpu = 0) and
                ((((p.left.registersfpu = 0) and
                   (p.right.registersfpu = 0)) or
                   (p.right.registersfpu = 0)) or
-                 (p.location.loc<>LOC_FPU)) and
+                 (p.location.loc<>LOC_FPUREGISTER)) and
                 (p.left.registers32<p.right.registers32))) and
                 (p.left.registers32<p.right.registers32))) and
            { the following check is appropriate, because all }
            { the following check is appropriate, because all }
            { 4 registers are rarely used and it is thereby   }
            { 4 registers are rarely used and it is thereby   }
@@ -945,8 +1100,7 @@ implementation
               begin
               begin
                  if (source.nodetype=stringconstn) and
                  if (source.nodetype=stringconstn) and
                    (str_length(source)=0) then
                    (str_length(source)=0) then
-                   emit_const_ref(
-                      A_MOV,S_B,0,newreference(dest.location.reference))
+                   emit_const_ref(A_MOV,S_B,0,dest.location.reference)
                  else
                  else
                    begin
                    begin
                      emitpushreferenceaddr(dest.location.reference);
                      emitpushreferenceaddr(dest.location.reference);
@@ -960,17 +1114,15 @@ implementation
               begin
               begin
                  if source.nodetype=ordconstn then
                  if source.nodetype=ordconstn then
                    emit_const_ref(
                    emit_const_ref(
-                      A_MOV,S_W,tordconstnode(source).value*256+1,newreference(dest.location.reference))
+                      A_MOV,S_W,tordconstnode(source).value*256+1,dest.location.reference)
                  else
                  else
                    begin
                    begin
                       if (source.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
                       if (source.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
                         begin
                         begin
                            href := dest.location.reference;
                            href := dest.location.reference;
-                           emit_const_ref(A_MOV,S_B,1,newreference(href));
+                           emit_const_ref(A_MOV,S_B,1,href);
                            inc(href.offset,1);
                            inc(href.offset,1);
-                           emit_reg_ref(A_MOV,S_B,makereg8(source.location.register),
-                                        newreference(href));
-                           rg.ungetregister(exprasmlist,source.location.register);
+                           emit_reg_ref(A_MOV,S_B,makereg8(source.location.register),href);
                         end
                         end
                       else
                       else
                       { not so elegant (goes better with extra register    }
                       { not so elegant (goes better with extra register    }
@@ -979,13 +1131,13 @@ implementation
                            { end of the heap! "movw" would be ok too, but  }
                            { end of the heap! "movw" would be ok too, but  }
                            { I don't think that would be faster (JM)       }
                            { I don't think that would be faster (JM)       }
                            rg.getexplicitregisterint(exprasmlist,R_EDI);
                            rg.getexplicitregisterint(exprasmlist,R_EDI);
-                           emit_ref_reg(A_MOVZX,S_BL,newreference(source.location.reference),R_EDI);
-                           rg.del_reference(exprasmlist,source.location.reference);
+                           emit_ref_reg(A_MOVZX,S_BL,source.location.reference,R_EDI);
                            emit_const_reg(A_SHL,S_L,8,R_EDI);
                            emit_const_reg(A_SHL,S_L,8,R_EDI);
                            emit_const_reg(A_OR,S_L,1,R_EDI);
                            emit_const_reg(A_OR,S_L,1,R_EDI);
-                           emit_reg_ref(A_MOV,S_W,R_DI,newreference(dest.location.reference));
+                           emit_reg_ref(A_MOV,S_W,R_DI,dest.location.reference);
                            rg.ungetregisterint(exprasmlist,R_EDI);
                            rg.ungetregisterint(exprasmlist,R_EDI);
                         end;
                         end;
+                      location_release(exprasmlist,source.location);
                    end;
                    end;
               end;
               end;
          else
          else
@@ -998,7 +1150,7 @@ implementation
       Load a string, handles stringdef and orddef (char) types
       Load a string, handles stringdef and orddef (char) types
     }
     }
       var
       var
-         r : preference;
+         r : treference;
 
 
       begin
       begin
          case p.right.resulttype.def.deftype of
          case p.right.resulttype.def.deftype of
@@ -1006,7 +1158,7 @@ implementation
               begin
               begin
                  if (p.right.nodetype=stringconstn) and
                  if (p.right.nodetype=stringconstn) and
                    (str_length(p.right)=0) then
                    (str_length(p.right)=0) then
-                   emit_const_ref(A_MOV,S_L,0,newreference(p.left.location.reference))
+                   emit_const_ref(A_MOV,S_L,0,p.left.location.reference)
                  else
                  else
                    begin
                    begin
                      emitpushreferenceaddr(p.left.location.reference);
                      emitpushreferenceaddr(p.left.location.reference);
@@ -1018,10 +1170,10 @@ implementation
               end;
               end;
             orddef:
             orddef:
               begin
               begin
-                 emit_const_ref(A_MOV,S_L,1,newreference(p.left.location.reference));
+                 emit_const_ref(A_MOV,S_L,1,p.left.location.reference);
 
 
-                 r:=newreference(p.left.location.reference);
-                 inc(r^.offset,4);
+                 r:=p.left.location.reference;
+                 inc(r.offset,4);
 
 
                  if p.right.nodetype=ordconstn then
                  if p.right.nodetype=ordconstn then
                    emit_const_ref(A_MOV,S_B,tordconstnode(p.right).value,r)
                    emit_const_ref(A_MOV,S_B,tordconstnode(p.right).value,r)
@@ -1029,24 +1181,20 @@ implementation
                    begin
                    begin
                       case p.right.location.loc of
                       case p.right.location.loc of
                          LOC_REGISTER,LOC_CREGISTER:
                          LOC_REGISTER,LOC_CREGISTER:
-                           begin
-                              emit_reg_ref(A_MOV,S_B,p.right.location.register,r);
-                              rg.ungetregister(exprasmlist,p.right.location.register);
-                           end;
-                         LOC_MEM,LOC_REFERENCE:
+                           emit_reg_ref(A_MOV,S_B,p.right.location.register,r);
+                         LOC_CREFERENCE,LOC_REFERENCE:
                            begin
                            begin
                               if not(R_EAX in rg.unusedregsint) then
                               if not(R_EAX in rg.unusedregsint) then
                                 emit_reg(A_PUSH,S_L,R_EAX);
                                 emit_reg(A_PUSH,S_L,R_EAX);
-                              emit_ref_reg(A_MOV,S_B,newreference(p.right.location.reference),R_AL);
+                              emit_ref_reg(A_MOV,S_B,p.right.location.reference,R_AL);
                               emit_reg_ref(A_MOV,S_B,R_AL,r);
                               emit_reg_ref(A_MOV,S_B,R_AL,r);
-
                               if not(R_EAX in rg.unusedregsint) then
                               if not(R_EAX in rg.unusedregsint) then
                                 emit_reg(A_POP,S_L,R_EAX);
                                 emit_reg(A_POP,S_L,R_EAX);
-                              rg.del_reference(exprasmlist,p.right.location.reference);
                            end
                            end
                          else
                          else
                            internalerror(20799);
                            internalerror(20799);
                         end;
                         end;
+                        location_release(exprasmlist,p.right.location);
                    end;
                    end;
               end;
               end;
          else
          else
@@ -1065,22 +1213,9 @@ implementation
          remove_non_regvars_from_loc(source.location,regs_to_push);
          remove_non_regvars_from_loc(source.location,regs_to_push);
          { Push them (JM) }
          { Push them (JM) }
          rg.saveusedregisters(exprasmlist,pushed,regs_to_push);
          rg.saveusedregisters(exprasmlist,pushed,regs_to_push);
-         case source.location.loc of
-           LOC_REFERENCE,LOC_MEM:
-             begin
-                { Now release the location and registers (see cgai386.pas: }
-                { loadansistring for more info on the order) (JM)          }
-                tg.ungetiftemp(exprasmlist,source.location.reference);
-                rg.del_reference(exprasmlist,source.location.reference);
-                emit_push_mem(source.location.reference);
-             end;
-           LOC_REGISTER,LOC_CREGISTER:
-             begin
-                emit_reg(A_PUSH,S_L,source.location.register);
-                { Now release the register (JM) }
-                rg.ungetregisterint(exprasmlist,source.location.register);
-             end;
-         end;
+         location_freetemp(exprasmlist,source.location);
+         location_release(exprasmlist,source.location);
+         cg.a_param_loc(exprasmlist,OS_ADDR,source.location,1);
          push_shortstring_length(dest);
          push_shortstring_length(dest);
          emitpushreferenceaddr(dest.location.reference);
          emitpushreferenceaddr(dest.location.reference);
          rg.saveregvars(exprasmlist,all_registers);
          rg.saveregvars(exprasmlist,all_registers);
@@ -1100,22 +1235,9 @@ implementation
          remove_non_regvars_from_loc(source.location,regs_to_push);
          remove_non_regvars_from_loc(source.location,regs_to_push);
          { Push them (JM) }
          { Push them (JM) }
          rg.saveusedregisters(exprasmlist,pushed,regs_to_push);
          rg.saveusedregisters(exprasmlist,pushed,regs_to_push);
-         case source.location.loc of
-           LOC_REFERENCE,LOC_MEM:
-             begin
-                { Now release the location and registers (see cgai386.pas: }
-                { loadansistring for more info on the order) (JM)          }
-                tg.ungetiftemp(exprasmlist,source.location.reference);
-                rg.del_reference(exprasmlist,source.location.reference);
-                emit_push_mem(source.location.reference);
-             end;
-           LOC_REGISTER,LOC_CREGISTER:
-             begin
-                emit_reg(A_PUSH,S_L,source.location.register);
-                { Now release the register (JM) }
-                rg.ungetregisterint(exprasmlist,source.location.register);
-             end;
-         end;
+         location_freetemp(exprasmlist,source.location);
+         location_release(exprasmlist,source.location);
+         cg.a_param_loc(exprasmlist,OS_ADDR,source.location,1);
          push_shortstring_length(dest);
          push_shortstring_length(dest);
          emitpushreferenceaddr(dest.location.reference);
          emitpushreferenceaddr(dest.location.reference);
          rg.saveregvars(exprasmlist,all_registers);
          rg.saveregvars(exprasmlist,all_registers);
@@ -1143,33 +1265,32 @@ implementation
          { nevertheless, this has to be changed, because otherwise the }
          { nevertheless, this has to be changed, because otherwise the }
          { register is released before it's contents are pushed ->     }
          { register is released before it's contents are pushed ->     }
          { problems with the optimizer (JM)                         }
          { problems with the optimizer (JM)                         }
-         rg.del_reference(exprasmlist,p.left.location.reference);
+         reference_release(exprasmlist,p.left.location.reference);
          ungettemp:=false;
          ungettemp:=false;
          case p.right.location.loc of
          case p.right.location.loc of
             LOC_REGISTER,LOC_CREGISTER:
             LOC_REGISTER,LOC_CREGISTER:
               begin
               begin
                  rg.saveusedregisters(exprasmlist,pushed, all_registers - [p.right.location.register]);
                  rg.saveusedregisters(exprasmlist,pushed, all_registers - [p.right.location.register]);
                  exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.right.location.register));
                  exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,p.right.location.register));
-                 rg.ungetregisterint(exprasmlist,p.right.location.register);
               end;
               end;
-            LOC_REFERENCE,LOC_MEM:
+            LOC_REFERENCE,LOC_CREFERENCE:
               begin
               begin
                  rg.saveusedregisters(exprasmlist,pushed, all_registers
                  rg.saveusedregisters(exprasmlist,pushed, all_registers
                    - [p.right.location.reference.base]
                    - [p.right.location.reference.base]
                    - [p.right.location.reference.index]);
                    - [p.right.location.reference.index]);
                  emit_push_mem(p.right.location.reference);
                  emit_push_mem(p.right.location.reference);
-                 rg.del_reference(exprasmlist,p.right.location.reference);
                  ungettemp:=true;
                  ungettemp:=true;
               end;
               end;
          end;
          end;
+         location_release(exprasmlist,p.right.location);
          emitpushreferenceaddr(p.left.location.reference);
          emitpushreferenceaddr(p.left.location.reference);
-         rg.del_reference(exprasmlist,p.left.location.reference);
+         location_release(exprasmlist,p.left.location);
          rg.saveregvars(exprasmlist,all_registers);
          rg.saveregvars(exprasmlist,all_registers);
          emitcall('FPC_INTF_ASSIGN');
          emitcall('FPC_INTF_ASSIGN');
          maybe_loadself;
          maybe_loadself;
          rg.restoreusedregisters(exprasmlist,pushed);
          rg.restoreusedregisters(exprasmlist,pushed);
          if ungettemp then
          if ungettemp then
-           tg.ungetiftemp(exprasmlist,p.right.location.reference);
+           location_release(exprasmlist,p.right.location);
       end;
       end;
 
 
 
 
@@ -1177,7 +1298,18 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.27  2002-03-31 20:26:40  jonas
+  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
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 16 - 5
compiler/i386/ra386.pas

@@ -57,7 +57,7 @@ implementation
 uses
 uses
   globtype,globals,systems,verbose,
   globtype,globals,systems,verbose,
   symconst,symdef,symsym,
   symconst,symdef,symsym,
-  cgbase,
+  cpuinfo,cgbase,
   types,cpuasm;
   types,cpuasm;
 
 
 {$define ATTOP}
 {$define ATTOP}
@@ -247,7 +247,7 @@ begin
                s:=operands[i].opr.symbol;
                s:=operands[i].opr.symbol;
                so:=operands[i].opr.symofs;
                so:=operands[i].opr.symofs;
                operands[i].opr.typ:=OPR_REFERENCE;
                operands[i].opr.typ:=OPR_REFERENCE;
-               reset_reference(operands[i].opr.ref);
+               Fillchar(operands[i].opr.ref,sizeof(treference),0);
                operands[i].opr.ref.symbol:=s;
                operands[i].opr.ref.symbol:=s;
                operands[i].opr.ref.offset:=so;
                operands[i].opr.ref.offset:=so;
              end;
              end;
@@ -575,14 +575,14 @@ begin
    begin
    begin
      case operands[i].opr.typ of
      case operands[i].opr.typ of
        OPR_CONSTANT :
        OPR_CONSTANT :
-         ai.loadconst(i-1,operands[i].opr.val);
+         ai.loadconst(i-1,aword(operands[i].opr.val));
        OPR_REGISTER:
        OPR_REGISTER:
          ai.loadreg(i-1,operands[i].opr.reg);
          ai.loadreg(i-1,operands[i].opr.reg);
        OPR_SYMBOL:
        OPR_SYMBOL:
          ai.loadsymbol(i-1,operands[i].opr.symbol,operands[i].opr.symofs);
          ai.loadsymbol(i-1,operands[i].opr.symbol,operands[i].opr.symofs);
        OPR_REFERENCE:
        OPR_REFERENCE:
          begin
          begin
-           ai.loadref(i-1,newreference(operands[i].opr.ref));
+           ai.loadref(i-1,operands[i].opr.ref);
            if operands[i].size<>S_NO then
            if operands[i].size<>S_NO then
              begin
              begin
                asize:=0;
                asize:=0;
@@ -631,7 +631,18 @@ end;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.14  2002-01-24 18:25:53  peter
+  Revision 1.15  2002-04-02 17:11:39  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.14  2002/01/24 18:25:53  peter
    * implicit result variable generation for assembler routines
    * implicit result variable generation for assembler routines
    * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
    * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
 
 

+ 13 - 2
compiler/i386/ra386att.pas

@@ -1565,7 +1565,7 @@ Begin
             begin
             begin
               l:=opr.val;
               l:=opr.val;
               opr.typ:=OPR_REFERENCE;
               opr.typ:=OPR_REFERENCE;
-              reset_reference(opr.Ref);
+              Fillchar(opr.ref,sizeof(treference),0);
               opr.Ref.Offset:=l;
               opr.Ref.Offset:=l;
             end;
             end;
            BuildReference;
            BuildReference;
@@ -2135,7 +2135,18 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.17  2002-03-28 20:48:25  carl
+  Revision 1.18  2002-04-02 17:11:39  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.17  2002/03/28 20:48:25  carl
   - remove go32v1 support
   - remove go32v1 support
 
 
   Revision 1.16  2002/01/24 18:25:53  peter
   Revision 1.16  2002/01/24 18:25:53  peter

+ 13 - 2
compiler/i386/ra386int.pas

@@ -1541,7 +1541,7 @@ Begin
                begin
                begin
                  l:=opr.val;
                  l:=opr.val;
                  opr.typ:=OPR_REFERENCE;
                  opr.typ:=OPR_REFERENCE;
-                 reset_reference(opr.Ref);
+                 Fillchar(opr.ref,sizeof(treference),0);
                  opr.Ref.Offset:=l;
                  opr.Ref.Offset:=l;
                end;
                end;
               BuildReference;
               BuildReference;
@@ -1964,7 +1964,18 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.20  2002-01-24 18:25:53  peter
+  Revision 1.21  2002-04-02 17:11:39  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.20  2002/01/24 18:25:53  peter
    * implicit result variable generation for assembler routines
    * implicit result variable generation for assembler routines
    * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
    * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
 
 

+ 18 - 13
compiler/i386/rgcpu.pas

@@ -46,7 +46,7 @@ unit rgcpu;
           function getregisterfpu(list: taasmoutput) : tregister; override;
           function getregisterfpu(list: taasmoutput) : tregister; override;
           procedure ungetregisterfpu(list: taasmoutput; r : tregister); override;
           procedure ungetregisterfpu(list: taasmoutput; r : tregister); override;
 
 
-          procedure del_reference(list: taasmoutput; const ref : treference); override;
+          procedure ungetreference(list: taasmoutput; const ref : treference); override;
 
 
           { pushes and restores registers }
           { pushes and restores registers }
           procedure pushusedregisters(list: taasmoutput;
           procedure pushusedregisters(list: taasmoutput;
@@ -179,11 +179,9 @@ unit rgcpu;
       end;
       end;
 
 
 
 
-    procedure trgcpu.del_reference(list: taasmoutput; const ref : treference);
+    procedure trgcpu.ungetreference(list: taasmoutput; const ref : treference);
 
 
       begin
       begin
-         if ref.is_immediate then
-           exit;
          ungetregisterint(list,ref.base);
          ungetregisterint(list,ref.base);
          ungetregisterint(list,ref.index);
          ungetregisterint(list,ref.index);
       end;
       end;
@@ -194,7 +192,7 @@ unit rgcpu;
 
 
       var
       var
         r: tregister;
         r: tregister;
-        hr: preference;
+        hr: treference;
       begin
       begin
         usedinproc:=usedinproc + s;
         usedinproc:=usedinproc + s;
         for r:=R_EAX to R_EBX do
         for r:=R_EAX to R_EBX do
@@ -224,9 +222,7 @@ unit rgcpu;
                not(r in unusedregsmm) then
                not(r in unusedregsmm) then
               begin
               begin
                 list.concat(Taicpu.Op_const_reg(A_SUB,S_L,8,R_ESP));
                 list.concat(Taicpu.Op_const_reg(A_SUB,S_L,8,R_ESP));
-                new(hr);
-                reset_reference(hr^);
-                hr^.base:=R_ESP;
+                reference_reset_base(hr,R_ESP,0);
                 list.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,r,hr));
                 list.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,r,hr));
                 include(unusedregsmm,r);
                 include(unusedregsmm,r);
                 inc(countunusedregsmm);
                 inc(countunusedregsmm);
@@ -246,7 +242,7 @@ unit rgcpu;
       var
       var
         r : tregister;
         r : tregister;
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
-        hr : preference;
+        hr : treference;
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
       begin
       begin
         { restore in reverse order: }
         { restore in reverse order: }
@@ -254,9 +250,7 @@ unit rgcpu;
         for r:=R_MM6 downto R_MM0 do
         for r:=R_MM6 downto R_MM0 do
           if pushed[r].pushed then
           if pushed[r].pushed then
             begin
             begin
-              new(hr);
-              reset_reference(hr^);
-              hr^.base:=R_ESP;
+              reference_reset_base(hr,R_ESP,0);
               list.concat(Taicpu.Op_ref_reg(
               list.concat(Taicpu.Op_ref_reg(
                 A_MOVQ,S_NO,hr,r));
                 A_MOVQ,S_NO,hr,r));
               list.concat(Taicpu.Op_const_reg(
               list.concat(Taicpu.Op_const_reg(
@@ -334,7 +328,18 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.1  2002-03-31 20:26:40  jonas
+  Revision 1.2  2002-04-02 17:11:39  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.1  2002/03/31 20:26:40  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 18 - 7
compiler/i386/rropt386.pas

@@ -130,7 +130,7 @@ begin
       end;
       end;
     A_INC,A_DEC:
     A_INC,A_DEC:
       begin
       begin
-        reset_reference(tmpref);
+        reference_reset(tmpref);
         tmpref.base := reg1;
         tmpref.base := reg1;
         case p.opcode of
         case p.opcode of
           A_INC:
           A_INC:
@@ -141,11 +141,11 @@ begin
         p.ops := 2;
         p.ops := 2;
         p.opcode := A_LEA;
         p.opcode := A_LEA;
         p.loadreg(1,reg2);
         p.loadreg(1,reg2);
-        p.loadref(0,newreference(tmpref));
+        p.loadref(0,tmpref);
       end;
       end;
     A_SUB,A_ADD:
     A_SUB,A_ADD:
       begin
       begin
-        reset_reference(tmpref);
+        reference_reset(tmpref);
         tmpref.base := reg1;
         tmpref.base := reg1;
         case p.oper[0].typ of
         case p.oper[0].typ of
           top_const:
           top_const:
@@ -164,16 +164,16 @@ begin
           else internalerror(200010031);
           else internalerror(200010031);
         end;
         end;
         p.opcode := A_LEA;
         p.opcode := A_LEA;
-        p.loadref(0,newreference(tmpref));
+        p.loadref(0,tmpref);
         p.loadreg(1,reg2);
         p.loadreg(1,reg2);
       end;
       end;
     A_SHL:
     A_SHL:
       begin
       begin
-        reset_reference(tmpref);
+        reference_reset(tmpref);
         tmpref.index := reg1;
         tmpref.index := reg1;
         tmpref.scalefactor := 1 shl p.oper[0].val;
         tmpref.scalefactor := 1 shl p.oper[0].val;
         p.opcode := A_LEA;
         p.opcode := A_LEA;
-        p.loadref(0,newreference(tmpref));
+        p.loadref(0,tmpref);
         p.loadreg(1,reg2);
         p.loadreg(1,reg2);
       end;
       end;
     else internalerror(200010032);
     else internalerror(200010032);
@@ -344,7 +344,18 @@ End.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.9  2002-03-31 20:26:41  jonas
+  Revision 1.10  2002-04-02 17:11:39  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.9  2002/03/31 20:26:41  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 40 - 39
compiler/nadd.pas

@@ -140,7 +140,7 @@ implementation
              begin
              begin
                { insert explicit typecast to s32bit }
                { insert explicit typecast to s32bit }
                left:=ctypeconvnode.create(left,s32bittype);
                left:=ctypeconvnode.create(left,s32bittype);
-               include(left.flags,nf_explizit);
+               left.toggleflag(nf_explizit);
                resulttypepass(left);
                resulttypepass(left);
              end
              end
             else
             else
@@ -167,9 +167,9 @@ implementation
          { are converted to widestring. This must be done before constant }
          { are converted to widestring. This must be done before constant }
          { folding to allow char+widechar etc.                            }
          { folding to allow char+widechar etc.                            }
          if is_widestring(right.resulttype.def) or
          if is_widestring(right.resulttype.def) or
-           is_widestring(left.resulttype.def) or
-           is_widechar(right.resulttype.def) or
-           is_widechar(left.resulttype.def) then
+            is_widestring(left.resulttype.def) or
+            is_widechar(right.resulttype.def) or
+            is_widechar(left.resulttype.def) then
            begin
            begin
               inserttypeconv(right,cwidestringtype);
               inserttypeconv(right,cwidestringtype);
               inserttypeconv(left,cwidestringtype);
               inserttypeconv(left,cwidestringtype);
@@ -554,15 +554,17 @@ implementation
               begin
               begin
                 if torddef(left.resulttype.def).size>torddef(right.resulttype.def).size then
                 if torddef(left.resulttype.def).size>torddef(right.resulttype.def).size then
                  begin
                  begin
-                   inserttypeconv(right,left.resulttype);
+                   right:=ctypeconvnode.create(right,left.resulttype);
                    ttypeconvnode(right).convtype:=tc_bool_2_int;
                    ttypeconvnode(right).convtype:=tc_bool_2_int;
-                   include(right.flags,nf_explizit);
+                   right.toggleflag(nf_explizit);
+                   resulttypepass(right);
                  end
                  end
                 else if torddef(left.resulttype.def).size<torddef(right.resulttype.def).size then
                 else if torddef(left.resulttype.def).size<torddef(right.resulttype.def).size then
                  begin
                  begin
-                   inserttypeconv(left,right.resulttype);
+                   left:=ctypeconvnode.create(left,right.resulttype);
                    ttypeconvnode(left).convtype:=tc_bool_2_int;
                    ttypeconvnode(left).convtype:=tc_bool_2_int;
-                   include(left.flags,nf_explizit);
+                   left.toggleflag(nf_explizit);
+                   resulttypepass(left);
                  end;
                  end;
                 case nodetype of
                 case nodetype of
                   xorn,
                   xorn,
@@ -749,23 +751,11 @@ implementation
                inserttypeconv(left,htype);
                inserttypeconv(left,htype);
              end;
              end;
 
 
-            { if the destination is not a smallset then insert a typeconv
-              which loads a smallset into a normal set }
-            if (tsetdef(ld).settype<>smallset) and
-               (tsetdef(rd).settype=smallset) then
-             begin
-               if (right.nodetype=setconstn) then
-                 begin
-                    t:=csetconstnode.create(tsetconstnode(right).value_set,left.resulttype);
-                    tsetconstnode(t).left:=tsetconstnode(right).left;
-                    tsetconstnode(right).left := nil;
-                    right.free;
-                    right:=t;
-                 end
-               else
-                 inserttypeconv(right,left.resulttype);
-               resulttypepass(right);
-             end;
+            { if the right side is also a setdef then the settype must
+              be the same as the left setdef }
+            if (rd.deftype=setdef) and
+               (tsetdef(ld).settype<>tsetdef(rd).settype) then
+              inserttypeconv(right,left.resulttype);
           end
           end
 
 
          { compare pchar to char arrays by addresses like BP/Delphi }
          { compare pchar to char arrays by addresses like BP/Delphi }
@@ -805,7 +795,7 @@ implementation
                    inserttypeconv(right,clongstringtype);
                    inserttypeconv(right,clongstringtype);
                  if not(is_longstring(ld)) then
                  if not(is_longstring(ld)) then
                    inserttypeconv(left,clongstringtype);
                    inserttypeconv(left,clongstringtype);
-                 location.loc:=LOC_MEM;
+                 location.loc:=LOC_CREFERENCE;
               end
               end
             else
             else
               begin
               begin
@@ -1342,11 +1332,11 @@ implementation
          { int/int gives real/real! }
          { int/int gives real/real! }
          if nodetype=slashn then
          if nodetype=slashn then
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              { maybe we need an integer register to save }
              { maybe we need an integer register to save }
              { a reference                               }
              { a reference                               }
-             if ((left.location.loc<>LOC_FPU) or
-                 (right.location.loc<>LOC_FPU)) and
+             if ((left.location.loc<>LOC_FPUREGISTER) or
+                 (right.location.loc<>LOC_FPUREGISTER)) and
                 (left.registers32=right.registers32) then
                 (left.registers32=right.registers32) then
                calcregisters(self,1,1,0)
                calcregisters(self,1,1,0)
              else
              else
@@ -1356,10 +1346,10 @@ implementation
               { calcregisters(0,2,0) will overestimate the number of    }
               { calcregisters(0,2,0) will overestimate the number of    }
               { necessary registers (it will make it 3 in case one of   }
               { necessary registers (it will make it 3 in case one of   }
               { the operands is already in the fpu) (JM)                }
               { the operands is already in the fpu) (JM)                }
-              if ((left.location.loc <> LOC_FPU) or
-                  (right.location.loc <> LOC_FPU)) and
+              if ((left.location.loc <> LOC_FPUREGISTER) or
+                  (right.location.loc <> LOC_FPUREGISTER)) and
                  (registersfpu < 2) then
                  (registersfpu < 2) then
-                inc(registersfpu);  
+                inc(registersfpu);
            end
            end
 
 
          { if both are orddefs then check sub types }
          { if both are orddefs then check sub types }
@@ -1446,7 +1436,7 @@ implementation
                  result := first_addset;
                  result := first_addset;
                  if assigned(result) then
                  if assigned(result) then
                    exit;
                    exit;
-                 location.loc:=LOC_MEM;
+                 location.loc:=LOC_CREFERENCE;
                  calcregisters(self,0,0,0);
                  calcregisters(self,0,0,0);
                  { here we call SET... }
                  { here we call SET... }
                  if assigned(procinfo) then
                  if assigned(procinfo) then
@@ -1483,7 +1473,7 @@ implementation
               else if is_longstring(ld) then
               else if is_longstring(ld) then
                 begin
                 begin
                    { this is only for add, the comparisaion is handled later }
                    { this is only for add, the comparisaion is handled later }
-                   location.loc:=LOC_MEM;
+                   location.loc:=LOC_CREFERENCE;
                 end
                 end
               else
               else
                 begin
                 begin
@@ -1519,17 +1509,17 @@ implementation
          { is one a real float ? }
          { is one a real float ? }
          else if (rd.deftype=floatdef) or (ld.deftype=floatdef) then
          else if (rd.deftype=floatdef) or (ld.deftype=floatdef) then
             begin
             begin
-              location.loc:=LOC_FPU;
+              location.loc:=LOC_FPUREGISTER;
               calcregisters(self,0,1,0);
               calcregisters(self,0,1,0);
               { an add node always first loads both the left and the    }
               { an add node always first loads both the left and the    }
               { right in the fpu before doing the calculation. However, }
               { right in the fpu before doing the calculation. However, }
               { calcregisters(0,2,0) will overestimate the number of    }
               { calcregisters(0,2,0) will overestimate the number of    }
               { necessary registers (it will make it 3 in case one of   }
               { necessary registers (it will make it 3 in case one of   }
               { the operands is already in the fpu) (JM)                }
               { the operands is already in the fpu) (JM)                }
-              if ((left.location.loc <> LOC_FPU) or
-                  (right.location.loc <> LOC_FPU)) and
+              if ((left.location.loc <> LOC_FPUREGISTER) or
+                  (right.location.loc <> LOC_FPUREGISTER)) and
                  (registersfpu < 2) then
                  (registersfpu < 2) then
-                inc(registersfpu);  
+                inc(registersfpu);
             end
             end
 
 
          { pointer comperation and subtraction }
          { pointer comperation and subtraction }
@@ -1611,7 +1601,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.43  2002-03-30 23:12:09  carl
+  Revision 1.44  2002-04-02 17:11:28  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.43  2002/03/30 23:12:09  carl
   * avoid crash with procinfo ('merged')
   * avoid crash with procinfo ('merged')
 
 
   Revision 1.42  2001/12/27 15:33:58  jonas
   Revision 1.42  2001/12/27 15:33:58  jonas

+ 16 - 5
compiler/ncal.pas

@@ -1560,7 +1560,7 @@ implementation
          else
          else
          { not a procedure variable }
          { not a procedure variable }
            begin
            begin
-              location.loc:=LOC_MEM;
+              location.loc:=LOC_CREFERENCE;
 
 
               { calc the correture value for the register }
               { calc the correture value for the register }
               { handle predefined procedures }
               { handle predefined procedures }
@@ -1640,13 +1640,13 @@ implementation
                         if is_widestring(resulttype.def) or
                         if is_widestring(resulttype.def) or
                            is_ansistring(resulttype.def) then
                            is_ansistring(resulttype.def) then
                           begin
                           begin
-                             location.loc:=LOC_MEM;
+                             location.loc:=LOC_CREFERENCE;
                              registers32:=1;
                              registers32:=1;
                           end;
                           end;
                      end
                      end
                    else if (resulttype.def.deftype=floatdef) then
                    else if (resulttype.def.deftype=floatdef) then
                      begin
                      begin
-                       location.loc:=LOC_FPU;
+                       location.loc:=LOC_FPUREGISTER;
 {$ifdef m68k}
 {$ifdef m68k}
                        if (cs_fp_emulation in aktmoduleswitches) or
                        if (cs_fp_emulation in aktmoduleswitches) or
                           (tfloatdef(resulttype.def).typ=s32real) then
                           (tfloatdef(resulttype.def).typ=s32real) then
@@ -1658,7 +1658,7 @@ implementation
 {$endif not m68k}
 {$endif not m68k}
                      end
                      end
                    else
                    else
-                     location.loc:=LOC_MEM;
+                     location.loc:=LOC_CREFERENCE;
                 end;
                 end;
            end;
            end;
          { a fpu can be used in any procedure !! }
          { a fpu can be used in any procedure !! }
@@ -1827,7 +1827,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.66  2002-03-31 20:26:33  jonas
+  Revision 1.67  2002-04-02 17:11:28  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.66  2002/03/31 20:26:33  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 126 - 101
compiler/ncgcnv.pas

@@ -41,9 +41,11 @@ interface
          procedure second_cord_to_pointer;override;
          procedure second_cord_to_pointer;override;
          procedure second_proc_to_procvar;override;
          procedure second_proc_to_procvar;override;
          procedure second_bool_to_int;override;
          procedure second_bool_to_int;override;
+         procedure second_bool_to_bool;override;
          procedure second_ansistring_to_pchar;override;
          procedure second_ansistring_to_pchar;override;
          procedure second_class_to_intf;override;
          procedure second_class_to_intf;override;
          procedure second_char_to_char;override;
          procedure second_char_to_char;override;
+         procedure second_nothing;override;
        end;
        end;
 
 
   implementation
   implementation
@@ -54,7 +56,7 @@ interface
       ncon,ncal,
       ncon,ncal,
       cpubase,cpuinfo,
       cpubase,cpuinfo,
       pass_2,
       pass_2,
-      cgbase,
+      cginfo,cgbase,
       cga,cgobj,cgcpu,
       cga,cgobj,cgcpu,
 {$ifdef i386}
 {$ifdef i386}
       n386util,
       n386util,
@@ -69,33 +71,29 @@ interface
         hr : treference;
         hr : treference;
 
 
       begin
       begin
-         clear_location(location);
-         location.loc:=LOC_REGISTER;
+         location_release(exprasmlist,left.location);
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          case tstringdef(left.resulttype.def).string_typ of
          case tstringdef(left.resulttype.def).string_typ of
            st_shortstring :
            st_shortstring :
              begin
              begin
                inc(left.location.reference.offset);
                inc(left.location.reference.offset);
-               rg.del_reference(exprasmlist,left.location.reference);
                location.register:=rg.getregisterint(exprasmlist);
                location.register:=rg.getregisterint(exprasmlist);
-               cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
-                 location.register);
+               cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
              end;
              end;
            st_ansistring :
            st_ansistring :
              begin
              begin
                if (left.nodetype=stringconstn) and
                if (left.nodetype=stringconstn) and
                   (str_length(left)=0) then
                   (str_length(left)=0) then
                 begin
                 begin
-                  reset_reference(hr);
+                  reference_reset(hr);
                   hr.symbol:=newasmsymbol('FPC_EMPTYCHAR');
                   hr.symbol:=newasmsymbol('FPC_EMPTYCHAR');
                   location.register:=rg.getregisterint(exprasmlist);
                   location.register:=rg.getregisterint(exprasmlist);
-                  cg.a_loadaddress_ref_reg(exprasmlist,hr,location.register);
+                  cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
                 end
                 end
                else
                else
                 begin
                 begin
-                  rg.del_reference(exprasmlist,left.location.reference);
                   location.register:=rg.getregisterint(exprasmlist);
                   location.register:=rg.getregisterint(exprasmlist);
-                  cg.a_load_ref_reg(exprasmlist,OS_32,left.location.reference,
-                    location.register);
+                  cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,location.register);
                 end;
                 end;
              end;
              end;
            st_longstring:
            st_longstring:
@@ -108,17 +106,16 @@ interface
                if (left.nodetype=stringconstn) and
                if (left.nodetype=stringconstn) and
                   (str_length(left)=0) then
                   (str_length(left)=0) then
                 begin
                 begin
-                  reset_reference(hr);
+                  reference_reset(hr);
                   hr.symbol:=newasmsymbol('FPC_EMPTYCHAR');
                   hr.symbol:=newasmsymbol('FPC_EMPTYCHAR');
                   location.register:=rg.getregisterint(exprasmlist);
                   location.register:=rg.getregisterint(exprasmlist);
-                  cg.a_loadaddress_ref_reg(exprasmlist,hr,location.register);
+                  cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
                 end
                 end
                else
                else
                 begin
                 begin
-                  rg.del_reference(exprasmlist,left.location.reference);
                   location.register:=rg.getregisterint(exprasmlist);
                   location.register:=rg.getregisterint(exprasmlist);
 {$warning Todo: convert widestrings to ascii when typecasting them to pchars}
 {$warning Todo: convert widestrings to ascii when typecasting them to pchars}
-                  cg.a_load_ref_reg(exprasmlist,OS_32,left.location.reference,
+                  cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
                     location.register);
                     location.register);
                 end;
                 end;
              end;
              end;
@@ -139,6 +136,7 @@ interface
             (tstringconstnode(left).len+1 >= arrsize) and
             (tstringconstnode(left).len+1 >= arrsize) and
             (tstringdef(left.resulttype.def).string_typ=st_shortstring) then
             (tstringdef(left.resulttype.def).string_typ=st_shortstring) then
            begin
            begin
+             location_copy(location,left.location);
              inc(location.reference.offset);
              inc(location.reference.offset);
              exit;
              exit;
            end
            end
@@ -151,46 +149,43 @@ interface
     procedure tcgtypeconvnode.second_array_to_pointer;
     procedure tcgtypeconvnode.second_array_to_pointer;
 
 
       begin
       begin
-         rg.del_reference(exprasmlist,left.location.reference);
-         clear_location(location);
-         location.loc:=LOC_REGISTER;
+         location_release(exprasmlist,left.location);
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          location.register:=rg.getregisterint(exprasmlist);
          location.register:=rg.getregisterint(exprasmlist);
-         cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
-           location.register);
+         cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
       end;
       end;
 
 
 
 
     procedure tcgtypeconvnode.second_pointer_to_array;
     procedure tcgtypeconvnode.second_pointer_to_array;
 
 
       begin
       begin
-        clear_location(location);
-        location.loc:=LOC_REFERENCE;
-        reset_reference(location.reference);
+        location_reset(location,LOC_REFERENCE,OS_NO);
         case left.location.loc of
         case left.location.loc of
           LOC_REGISTER :
           LOC_REGISTER :
             location.reference.base:=left.location.register;
             location.reference.base:=left.location.register;
           LOC_CREGISTER :
           LOC_CREGISTER :
             begin
             begin
               location.reference.base:=rg.getregisterint(exprasmlist);
               location.reference.base:=rg.getregisterint(exprasmlist);
-              cg.a_load_reg_reg(exprasmlist,OS_32,left.location.register,
+              cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
                 location.reference.base);
                 location.reference.base);
-            end
-         else
+            end;
+          LOC_REFERENCE,
+          LOC_CREFERENCE :
             begin
             begin
-              rg.del_reference(exprasmlist,left.location.reference);
+              location_release(exprasmlist,left.location);
               location.reference.base:=rg.getregisterint(exprasmlist);
               location.reference.base:=rg.getregisterint(exprasmlist);
-              cg.a_load_ref_reg(exprasmlist,OS_32,left.location.reference,
+              cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
                 location.reference.base);
                 location.reference.base);
             end;
             end;
+          else
+            internalerror(2002032216);
         end;
         end;
       end;
       end;
 
 
 
 
     procedure tcgtypeconvnode.second_char_to_string;
     procedure tcgtypeconvnode.second_char_to_string;
-
       begin
       begin
-         clear_location(location);
-         location.loc:=LOC_MEM;
+         location_reset(location,LOC_REFERENCE,OS_NO);
          case tstringdef(resulttype.def).string_typ of
          case tstringdef(resulttype.def).string_typ of
            st_shortstring :
            st_shortstring :
              begin
              begin
@@ -206,25 +201,25 @@ interface
 
 
     procedure tcgtypeconvnode.second_real_to_real;
     procedure tcgtypeconvnode.second_real_to_real;
       begin
       begin
-         clear_location(location);
-         location.loc:=LOC_FPU;
+         location_reset(location,LOC_FPUREGISTER,OS_NO);
          case left.location.loc of
          case left.location.loc of
-            LOC_FPU : ;
+            LOC_FPUREGISTER,
             LOC_CFPUREGISTER:
             LOC_CFPUREGISTER:
               begin
               begin
-                 location:=left.location;
-                 exit;
+                location_copy(location,left.location);
+                exit;
               end;
               end;
-            LOC_MEM,
+            LOC_CREFERENCE,
             LOC_REFERENCE:
             LOC_REFERENCE:
               begin
               begin
+                 location_release(exprasmlist,left.location);
                  location.register := rg.getregisterfpu(exprasmlist);
                  location.register := rg.getregisterfpu(exprasmlist);
                  cg.a_loadfpu_ref_reg(exprasmlist,
                  cg.a_loadfpu_ref_reg(exprasmlist,
                    def_cgsize(left.resulttype.def),
                    def_cgsize(left.resulttype.def),
                    left.location.reference,location.register);
                    left.location.reference,location.register);
-                 { we have to free the reference }
-                 rg.del_reference(exprasmlist,left.location.reference);
               end;
               end;
+            else
+              internalerror(2002032215);
          end;
          end;
       end;
       end;
 
 
@@ -243,16 +238,14 @@ interface
         { method pointer ? }
         { method pointer ? }
         if assigned(tcallnode(left).left) then
         if assigned(tcallnode(left).left) then
           begin
           begin
-             set_location(location,left.location);
+             location_copy(location,left.location);
           end
           end
         else
         else
           begin
           begin
-             clear_location(location);
-             location.loc:=LOC_REGISTER;
-             rg.del_reference(exprasmlist,left.location.reference);
+             location_release(exprasmlist,left.location);
+             location_reset(location,LOC_REGISTER,OS_ADDR);
              location.register:=rg.getregisterint(exprasmlist);
              location.register:=rg.getregisterint(exprasmlist);
-             cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
-               location.register);
+             cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
           end;
           end;
       end;
       end;
 
 
@@ -274,22 +267,21 @@ interface
          { be accepted for var parameters                            }
          { be accepted for var parameters                            }
          if (nf_explizit in flags) and
          if (nf_explizit in flags) and
             (left.resulttype.def.size=resulttype.def.size) and
             (left.resulttype.def.size=resulttype.def.size) and
-            (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
+            (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
            begin
            begin
-              set_location(location,left.location);
+              location_copy(location,left.location);
               truelabel:=oldtruelabel;
               truelabel:=oldtruelabel;
               falselabel:=oldfalselabel;
               falselabel:=oldfalselabel;
               exit;
               exit;
            end;
            end;
-         clear_location(location);
-         location.loc:=LOC_REGISTER;
-         rg.del_location(exprasmlist,left.location);
-         location.register:=rg.getregisterint(exprasmlist);
          { size of the boolean we're converting }
          { size of the boolean we're converting }
          opsize := def_cgsize(left.resulttype.def);
          opsize := def_cgsize(left.resulttype.def);
          { size of the destination }
          { size of the destination }
          newsize := def_cgsize(resulttype.def);
          newsize := def_cgsize(resulttype.def);
-         { the the source size is bigger than the destination, we can }
+         { reset location for destination }
+         location_reset(location,LOC_REGISTER,newsize);
+         location.register:=rg.getregisterint(exprasmlist);
+         { if the source size is bigger than the destination, we can }
          { simply decrease the sources size (since wordbool(true) =   }
          { simply decrease the sources size (since wordbool(true) =   }
          { boolean(true) etc... (JM)                                  }
          { boolean(true) etc... (JM)                                  }
          case newsize of
          case newsize of
@@ -318,96 +310,108 @@ interface
              end;
              end;
          end;
          end;
          case left.location.loc of
          case left.location.loc of
-            LOC_MEM,
-      LOC_REFERENCE :
-           cg.a_load_ref_reg(exprasmlist,opsize,left.location.reference,
-             location.register);
-       LOC_REGISTER,
-      LOC_CREGISTER :
-           if left.location.register<>location.register then
-             cg.a_load_reg_reg(exprasmlist,opsize,left.location.register,
-               location.register);
-          LOC_FLAGS :
-            cg.g_flags2reg(exprasmlist,left.location.resflags,location.register);
-           LOC_JUMP :
-             begin
-               getlabel(hlabel);
-               cg.a_label(exprasmlist,truelabel);
-               cg.a_load_const_reg(exprasmlist,newsize,1,location.register);
-               cg.a_jmp_cond(exprasmlist,OC_NONE,hlabel);
-               cg.a_label(exprasmlist,falselabel);
-               cg.a_load_const_reg(exprasmlist,newsize,0,location.register);
-               cg.a_label(exprasmlist,hlabel);
-             end;
-         else
-           internalerror(10061);
+            LOC_CREFERENCE,
+            LOC_REFERENCE :
+              cg.a_load_ref_reg(exprasmlist,opsize,left.location.reference,
+                location.register);
+            LOC_REGISTER,
+            LOC_CREGISTER :
+              if left.location.register<>location.register then
+                cg.a_load_reg_reg(exprasmlist,opsize,left.location.register,
+                  location.register);
+            LOC_FLAGS :
+              cg.g_flags2reg(exprasmlist,left.location.resflags,location.register);
+            LOC_JUMP :
+              begin
+                getlabel(hlabel);
+                cg.a_label(exprasmlist,truelabel);
+                cg.a_load_const_reg(exprasmlist,newsize,1,location.register);
+                cg.a_jmp_cond(exprasmlist,OC_NONE,hlabel);
+                cg.a_label(exprasmlist,falselabel);
+                cg.a_load_const_reg(exprasmlist,newsize,0,location.register);
+                cg.a_label(exprasmlist,hlabel);
+              end;
+            else
+              internalerror(10061);
          end;
          end;
          truelabel:=oldtruelabel;
          truelabel:=oldtruelabel;
          falselabel:=oldfalselabel;
          falselabel:=oldfalselabel;
       end;
       end;
 
 
 
 
+    procedure tcgtypeconvnode.second_bool_to_bool;
+      begin
+        { we can reuse the conversion already available
+          in bool_to_int to resize the value. But when the
+          size of the new boolean is smaller we need to calculate
+          the value as is done in int_to_bool. This is needed because
+          the bits that define the true status can be outside the limits
+          of the new size and truncating the register can result in a 0
+          value }
+        if resulttype.def.size<left.resulttype.def.size then
+          second_int_to_bool
+        else
+          second_bool_to_int;
+      end;
+
+
     procedure tcgtypeconvnode.second_ansistring_to_pchar;
     procedure tcgtypeconvnode.second_ansistring_to_pchar;
       var
       var
          l1 : tasmlabel;
          l1 : tasmlabel;
          hr : treference;
          hr : treference;
       begin
       begin
-         clear_location(location);
-         location.loc:=LOC_REGISTER;
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          getlabel(l1);
          getlabel(l1);
          case left.location.loc of
          case left.location.loc of
             LOC_CREGISTER,LOC_REGISTER:
             LOC_CREGISTER,LOC_REGISTER:
               location.register:=left.location.register;
               location.register:=left.location.register;
-            LOC_MEM,LOC_REFERENCE:
+            LOC_CREFERENCE,LOC_REFERENCE:
               begin
               begin
-                rg.del_reference(exprasmlist,left.location.reference);
+                location_release(exprasmlist,left.location);
                 location.register:=rg.getregisterint(exprasmlist);
                 location.register:=rg.getregisterint(exprasmlist);
-                cg.a_load_ref_reg(exprasmlist,OS_32,left.location.reference,
-                  location.register);
+                cg.a_load_ref_reg(exprasmlist,OS_32,left.location.reference,location.register);
               end;
               end;
+            else
+              internalerror(2002032214);
          end;
          end;
-         cg.a_cmp_const_reg_label(exprasmlist,OS_32,OC_NE,0,location.register,
-           l1);
-         reset_reference(hr);
+         cg.a_cmp_const_reg_label(exprasmlist,OS_32,OC_NE,0,location.register,l1);
+         reference_reset(hr);
          hr.symbol:=newasmsymbol('FPC_EMPTYCHAR');
          hr.symbol:=newasmsymbol('FPC_EMPTYCHAR');
-         cg.a_loadaddress_ref_reg(exprasmlist,hr,location.register);
+         cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
          cg.a_label(exprasmlist,l1);
          cg.a_label(exprasmlist,l1);
       end;
       end;
 
 
 
 
     procedure tcgtypeconvnode.second_class_to_intf;
     procedure tcgtypeconvnode.second_class_to_intf;
       var
       var
-         hreg : tregister;
          l1 : tasmlabel;
          l1 : tasmlabel;
       begin
       begin
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          case left.location.loc of
          case left.location.loc of
-            LOC_MEM,
+            LOC_CREFERENCE,
             LOC_REFERENCE:
             LOC_REFERENCE:
               begin
               begin
-                 rg.del_reference(exprasmlist,left.location.reference);
-                 hreg:=rg.getregisterint(exprasmlist);
-                 cg.a_load_ref_reg(exprasmlist,OS_32,left.location.reference,
-                   hreg);
+                 location_release(exprasmlist,left.location);
+                 location.register:=rg.getregisterint(exprasmlist);
+                 cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,location.register);
               end;
               end;
             LOC_CREGISTER:
             LOC_CREGISTER:
               begin
               begin
-                 hreg:=rg.getregisterint(exprasmlist);
-                 cg.a_load_reg_reg(exprasmlist,OS_32,left.location.register,
-                   hreg);
+                 location.register:=rg.getregisterint(exprasmlist);
+                 cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,location.register);
               end;
               end;
             LOC_REGISTER:
             LOC_REGISTER:
-              hreg:=left.location.register;
-            else internalerror(121120001);
+              location.register:=left.location.register;
+            else
+              internalerror(121120001);
          end;
          end;
          getlabel(l1);
          getlabel(l1);
-         cg.a_cmp_const_reg_label(exprasmlist,OS_32,OC_EQ,0,hreg,l1);
+         cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,location.register,l1);
          cg.a_op_const_reg(exprasmlist,OP_ADD,aword(
          cg.a_op_const_reg(exprasmlist,OP_ADD,aword(
            tobjectdef(left.resulttype.def).implementedinterfaces.ioffsets(
            tobjectdef(left.resulttype.def).implementedinterfaces.ioffsets(
            tobjectdef(left.resulttype.def).implementedinterfaces.searchintf(
            tobjectdef(left.resulttype.def).implementedinterfaces.searchintf(
-           resulttype.def))^),hreg);
+           resulttype.def))^),location.register);
          cg.a_label(exprasmlist,l1);
          cg.a_label(exprasmlist,l1);
-         location.loc:=LOC_REGISTER;
-         location.register:=hreg;
       end;
       end;
 
 
 
 
@@ -418,13 +422,34 @@ interface
         second_int_to_int;
         second_int_to_int;
       end;
       end;
 
 
+
+    procedure tcgtypeconvnode.second_nothing;
+      begin
+        { we reuse the old value }
+        location_copy(location,left.location);
+        { but use the new size, but we don't know the size of all arrays }
+        location.size:=def_cgsize_ref(resulttype.def)
+      end;
+
+
 begin
 begin
   ctypeconvnode := tcgtypeconvnode;
   ctypeconvnode := tcgtypeconvnode;
 end.
 end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2002-03-31 20:26:34  jonas
+  Revision 1.6  2002-04-02 17:11:28  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.5  2002/03/31 20:26:34  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 36 - 45
compiler/ncgcon.pas

@@ -66,8 +66,8 @@ implementation
       globtype,widestr,systems,
       globtype,widestr,systems,
       verbose,globals,
       verbose,globals,
       symconst,symdef,aasm,types,
       symconst,symdef,aasm,types,
-      cpubase,
-      tgobj;
+      cpuinfo,cpubase,
+      cginfo,cgbase,tgobj,rgobj;
 
 
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -88,6 +88,7 @@ implementation
          realait : tait;
          realait : tait;
 
 
       begin
       begin
+        location_reset(location,LOC_CREFERENCE,def_cgsize_ref(resulttype.def));
         lastlabel:=nil;
         lastlabel:=nil;
         realait:=floattype2ait[tfloatdef(resulttype.def).typ];
         realait:=floattype2ait[tfloatdef(resulttype.def).typ];
         { const already used ? }
         { const already used ? }
@@ -141,9 +142,7 @@ implementation
                   end;
                   end;
                end;
                end;
           end;
           end;
-        reset_reference(location.reference);
         location.reference.symbol:=lab_real;
         location.reference.symbol:=lab_real;
-        location.loc:=LOC_MEM;
       end;
       end;
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -155,26 +154,9 @@ implementation
          l : tasmlabel;
          l : tasmlabel;
 
 
       begin
       begin
-         location.loc:=LOC_MEM;
-         { still needs to be made more generic (and optimal), this is for }
-         { when Peter implements LOC_ORDCONST (JM)                        }
-         if is_64bitint(resulttype.def) then
-           begin
-              getdatalabel(l);
-              if (cs_create_smart in aktmoduleswitches) then
-                Consts.concat(Tai_cut.Create);
-              Consts.concat(Tai_label.Create(l));
-              Consts.concat(Tai_const.Create_32bit(longint(value)));
-              Consts.concat(Tai_const.Create_32bit(longint(value shr 32)));
-              reset_reference(location.reference);
-              location.reference.symbol:=l;
-           end
-         else
-           begin
-              { non int64 const. behaves as a memory reference }
-              location.reference.is_immediate:=true;
-              location.reference.offset:=longint(value);
-           end;
+         location_reset(location,LOC_CONSTANT,def_cgsize(resulttype.def));
+         location.valuelow:=AWord(value);
+         location.valuehigh:=AWord(value shr 32);
       end;
       end;
 
 
 
 
@@ -185,9 +167,8 @@ implementation
     procedure tcgpointerconstnode.pass_2;
     procedure tcgpointerconstnode.pass_2;
       begin
       begin
          { an integer const. behaves as a memory reference }
          { an integer const. behaves as a memory reference }
-         location.loc:=LOC_MEM;
-         location.reference.is_immediate:=true;
-         location.reference.offset:=longint(value);
+         location_reset(location,LOC_CONSTANT,OS_ADDR);
+         location.value:=AWord(value);
       end;
       end;
 
 
 
 
@@ -202,19 +183,24 @@ implementation
          lastlabel   : tasmlabel;
          lastlabel   : tasmlabel;
          pc       : pchar;
          pc       : pchar;
          same_string : boolean;
          same_string : boolean;
+         size : tcgsize;
          l,j,
          l,j,
          i,mylength  : longint;
          i,mylength  : longint;
       begin
       begin
          { for empty ansistrings we could return a constant 0 }
          { for empty ansistrings we could return a constant 0 }
-         if (is_ansistring(resulttype.def) or
-             is_widestring(resulttype.def)) and
+         if (st_type in [st_ansistring,st_widestring]) and
             (len=0) then
             (len=0) then
           begin
           begin
-            location.loc:=LOC_MEM;
-            location.reference.is_immediate:=true;
-            location.reference.offset:=0;
+            location_reset(location,LOC_CONSTANT,OS_ADDR);
+            location.value:=0;
             exit;
             exit;
           end;
           end;
+         { return a constant reference in memory }
+         if (st_type in [st_ansistring,st_widestring]) then
+          size:=OS_ADDR
+         else
+          size:=def_cgsize_ref(resulttype.def);
+         location_reset(location,LOC_CREFERENCE,size);
          { const already used ? }
          { const already used ? }
          lastlabel:=nil;
          lastlabel:=nil;
          if not assigned(lab_str) then
          if not assigned(lab_str) then
@@ -367,9 +353,7 @@ implementation
                    end;
                    end;
                 end;
                 end;
            end;
            end;
-         reset_reference(location.reference);
          location.reference.symbol:=lab_str;
          location.reference.symbol:=lab_str;
-         location.loc:=LOC_MEM;
       end;
       end;
 
 
 
 
@@ -387,11 +371,11 @@ implementation
         { small sets are loaded as constants }
         { small sets are loaded as constants }
         if tsetdef(resulttype.def).settype=smallset then
         if tsetdef(resulttype.def).settype=smallset then
          begin
          begin
-           location.loc:=LOC_MEM;
-           location.reference.is_immediate:=true;
-           location.reference.offset:=plongint(value_set)^;
+           location_reset(location,LOC_CONSTANT,OS_32);
+           location.value:=PAWord(value_set)^;
            exit;
            exit;
          end;
          end;
+        location_reset(location,LOC_CREFERENCE,OS_NO);
         neededtyp:=ait_const_8bit;
         neededtyp:=ait_const_8bit;
         lastlabel:=nil;
         lastlabel:=nil;
         { const already used ? }
         { const already used ? }
@@ -464,9 +448,7 @@ implementation
                   end;
                   end;
                end;
                end;
           end;
           end;
-        reset_reference(location.reference);
         location.reference.symbol:=lab_set;
         location.reference.symbol:=lab_set;
-        location.loc:=LOC_MEM;
       end;
       end;
 
 
 
 
@@ -476,9 +458,8 @@ implementation
 
 
     procedure tcgnilnode.pass_2;
     procedure tcgnilnode.pass_2;
       begin
       begin
-         location.loc:=LOC_MEM;
-         location.reference.is_immediate:=true;
-         location.reference.offset:=0;
+         location_reset(location,LOC_CONSTANT,OS_ADDR);
+         location.value:=0;
       end;
       end;
 
 
 
 
@@ -491,7 +472,7 @@ implementation
         tmplabel : TAsmLabel;
         tmplabel : TAsmLabel;
         i : integer;
         i : integer;
       begin
       begin
-        location.loc:=LOC_MEM;
+        location_reset(location,LOC_CREFERENCE,OS_NO);
         { label for GUID }
         { label for GUID }
         getdatalabel(tmplabel);
         getdatalabel(tmplabel);
         consts.concat(Tai_label.Create(tmplabel));
         consts.concat(Tai_label.Create(tmplabel));
@@ -500,7 +481,6 @@ implementation
         consts.concat(Tai_const.Create_16bit(value.D3));
         consts.concat(Tai_const.Create_16bit(value.D3));
         for i:=Low(value.D4) to High(value.D4) do
         for i:=Low(value.D4) to High(value.D4) do
           consts.concat(Tai_const.Create_8bit(value.D4[i]));
           consts.concat(Tai_const.Create_8bit(value.D4[i]));
-        reset_reference(location.reference);
         location.reference.symbol:=tmplabel;
         location.reference.symbol:=tmplabel;
       end;
       end;
 
 
@@ -516,7 +496,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2002-03-31 20:26:34  jonas
+  Revision 1.6  2002-04-02 17:11:28  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.5  2002/03/31 20:26:34  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 85 - 116
compiler/ncgflw.pas

@@ -68,12 +68,12 @@ implementation
     uses
     uses
       verbose,globals,systems,globtype,
       verbose,globals,systems,globtype,
       symconst,symdef,symsym,aasm,types,
       symconst,symdef,symsym,aasm,types,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       cpubase,cpuasm,cpuinfo,
       cpubase,cpuasm,cpuinfo,
       nld,ncon,
       nld,ncon,
       cga,tgobj,rgobj,
       cga,tgobj,rgobj,
       ncgutil,
       ncgutil,
-      tainst,regvars,cgobj,cgcpu;
+      tainst,regvars,cgobj,cgcpu,cg64f32;
 
 
 {*****************************************************************************
 {*****************************************************************************
                          Second_While_RepeatN
                          Second_While_RepeatN
@@ -433,26 +433,10 @@ implementation
          {op : tasmop;
          {op : tasmop;
          s : topsize;}
          s : topsize;}
          otlabel,oflabel : tasmlabel;
          otlabel,oflabel : tasmlabel;
-         r : treference;
-         is_mem,
+         cgsize : tcgsize;
+         hreg : tregister;
          allocated_acc,
          allocated_acc,
          allocated_acchigh: boolean;
          allocated_acchigh: boolean;
-
-      procedure cleanleft;
-        begin
-          if is_mem then
-            begin
-              rg.del_reference(exprasmlist,left.location.reference);
-              tg.ungetiftemp(exprasmlist,left.location.reference);
-            end
-          else
-            begin
-              rg.ungetregister(exprasmlist,left.location.register);
-              if left.location.registerhigh <> R_NO then
-                rg.ungetregister(exprasmlist,left.location.registerhigh);
-            end;
-        end;
-
       label
       label
          do_jmp;
          do_jmp;
       begin
       begin
@@ -474,110 +458,84 @@ implementation
               getlabel(truelabel);
               getlabel(truelabel);
               getlabel(falselabel);
               getlabel(falselabel);
               secondpass(left);
               secondpass(left);
+              { the result of left is not needed anymore after this
+                node }
+              location_freetemp(exprasmlist,left.location);
+              location_release(exprasmlist,left.location);
               case left.location.loc of
               case left.location.loc of
-                 LOC_FPU : goto do_jmp;
-                 LOC_MEM,
-           LOC_REFERENCE : is_mem:=true;
-           LOC_CREGISTER,
-            LOC_REGISTER : is_mem:=false;
-               LOC_FLAGS : begin
-                             cg.a_reg_alloc(exprasmlist,accumulator);
-                             allocated_acc := true;
-                             cg.g_flags2reg(exprasmlist,left.location.resflags,accumulator);
-                             goto do_jmp;
-                           end;
-                LOC_JUMP : begin
-                             cg.a_reg_alloc(exprasmlist,accumulator);
-                             allocated_acc := true;
-                             cg.a_label(exprasmlist,truelabel);
-{$ifdef i386}
-                             cg.a_load_const_reg(exprasmlist,OS_8,1,
-                               makereg8(accumulator));
-{$else i386}
-                             cg.a_load_const_reg(exprasmlist,OS_8,1,
-                               accumulator);
-{$endif i386}
-                             cg.a_jmp_cond(exprasmlist,OC_NONE,aktexit2label);
-                             cg.a_label(exprasmlist,falselabel);
+                LOC_FPUREGISTER :
+                  goto do_jmp;
+                LOC_FLAGS :
+                  begin
+                    cg.a_reg_alloc(exprasmlist,accumulator);
+                    allocated_acc := true;
+                    cg.g_flags2reg(exprasmlist,left.location.resflags,accumulator);
+                    goto do_jmp;
+                  end;
+                LOC_JUMP :
+                  begin
+                    cg.a_reg_alloc(exprasmlist,accumulator);
 {$ifdef i386}
 {$ifdef i386}
-                             cg.a_load_const_reg(exprasmlist,OS_8,0,
-                               makereg8(accumulator));
+                    hreg:=makereg8(accumulator);
 {$else i386}
 {$else i386}
-                             cg.a_load_const_reg(exprasmlist,OS_8,0,
-                               accumulator);
+                    hreg:=accumulator;
 {$endif i386}
 {$endif i386}
-                             goto do_jmp;
-                           end;
-              else
-                internalerror(2001);
+                    allocated_acc := true;
+                    cg.a_label(exprasmlist,truelabel);
+                    cg.a_load_const_reg(exprasmlist,OS_8,1,hreg);
+                    cg.a_jmp_cond(exprasmlist,OC_NONE,aktexit2label);
+                    cg.a_label(exprasmlist,falselabel);
+                    cg.a_load_const_reg(exprasmlist,OS_8,0,hreg);
+                    goto do_jmp;
+                  end;
               end;
               end;
               case aktprocdef.rettype.def.deftype of
               case aktprocdef.rettype.def.deftype of
-           pointerdef,
-           procvardef : begin
-                          cleanleft;
-                          cg.a_reg_alloc(exprasmlist,accumulator);
-                          allocated_acc := true;
-                          cg.a_load_loc_reg(exprasmlist,OS_ADDR,
-                            left.location,accumulator);
-                        end;
-             floatdef : begin
+                pointerdef,
+                procvardef :
+                  begin
+                    cg.a_reg_alloc(exprasmlist,accumulator);
+                    allocated_acc := true;
+                    cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,accumulator);
+                  end;
+                floatdef :
+                  begin
 {$ifndef i386}
 {$ifndef i386}
-                          cg.a_reg_alloc(exprasmlist,fpuresultreg);
+                    cg.a_reg_alloc(exprasmlist,fpuresultreg);
 {$endif not i386}
 {$endif not i386}
-                          cg.a_loadfpu_loc_reg(exprasmlist,
-                            def_cgsize(aktprocdef.rettype.def),
-                            left.location,fpuresultreg);
-                          cleanleft;
-                        end;
-              { orddef,
-              enumdef : }
-              else
-              { it can be anything shorter than 4 bytes PM
-              this caused form bug 711 }
-                begin
-                   cleanleft;
-                   cg.a_reg_alloc(exprasmlist,accumulator);
-                   allocated_acc := true;
-                   case aktprocdef.rettype.def.size of
-                    { it can be a qword/int64 too ... }
-                    8 :
-                      if is_mem then
+                    cg.a_loadfpu_loc_reg(exprasmlist,
+                        def_cgsize(aktprocdef.rettype.def),
+                        left.location,fpuresultreg);
+                  end;
+                else
+                  begin
+                    cgsize:=def_cgsize(aktprocdef.rettype.def);
+                    cg.a_reg_alloc(exprasmlist,accumulator);
+                    allocated_acc := true;
+                    case cgsize of
+                      OS_64,OS_S64 :
                         begin
                         begin
-                           cg.a_load_ref_reg(exprasmlist,OS_32,
-                             left.location.reference,accumulator);
-                           r:=left.location.reference;
-                           inc(r.offset,4);
-                           cg.a_reg_alloc(exprasmlist,accumulatorhigh);
-                           allocated_acchigh := true;
-                           cg.a_load_ref_reg(exprasmlist,OS_32,r,accumulatorhigh);
+                          cg.a_reg_alloc(exprasmlist,accumulatorhigh);
+                          allocated_acchigh := true;
+                          tcg64f32(cg).a_load64_loc_reg(exprasmlist,left.location,
+                              accumulator,accumulatorhigh);
                         end
                         end
                       else
                       else
                         begin
                         begin
-                           cg.a_load_reg_reg(exprasmlist,OS_32,left.location.registerlow,accumulator);
-                           cg.a_reg_alloc(exprasmlist,accumulatorhigh);
-                           allocated_acchigh := true;
-                           cg.a_load_reg_reg(exprasmlist,OS_32,left.location.registerhigh,accumulatorhigh);
-                        end;
-                   { if its 3 bytes only we can still
-                     copy one of garbage ! PM }
 {$ifdef i386}
 {$ifdef i386}
-                    4,3 :
-                      cg.a_load_loc_reg(exprasmlist,OS_32,left.location,
-                        accumulator);
-                    2 :
-                      cg.a_load_loc_reg(exprasmlist,OS_16,left.location,
-                        makereg16(accumulator));
-                    1 :
-                      cg.a_load_loc_reg(exprasmlist,OS_8,left.location,
-                        makereg8(accumulator));
-{$else i386}
-                    4,3,2,1:
-                      cg.a_load_loc_reg(exprasmlist,
-                        def_cgsize(aktprocdef.rettype.def.size),left.location,
-                        accumulator));
-{$endif i386}
-                    else internalerror(605001);
-                   end;
+                          case cgsize of
+                            OS_8,OS_S8 :
+                              hreg:=makereg8(accumulator);
+                            OS_16,OS_S16 :
+                              hreg:=makereg16(accumulator);
+                            else
+                              hreg:=accumulator;
+                          end;
+{$else}
+                          hreg:=accumulator;
+{$endif}
+                          cg.a_load_loc_reg(exprasmlist,cgsize,left.location,hreg);
+                        end;
+                    end;
                  end;
                  end;
               end;
               end;
 do_jmp:
 do_jmp:
@@ -587,14 +545,14 @@ do_jmp:
               if allocated_acc then
               if allocated_acc then
                 cg.a_reg_dealloc(exprasmlist,accumulator);
                 cg.a_reg_dealloc(exprasmlist,accumulator);
               if allocated_acchigh then
               if allocated_acchigh then
-                cg.a_reg_dealloc(exprasmlist,accumulator);
+                cg.a_reg_dealloc(exprasmlist,accumulatorhigh);
 {$ifndef i386}
 {$ifndef i386}
-             if (aktprocdef.rettype.def.deftype = floatdef) then
-               cg.a_reg_dealloc(exprasmlist,fpuresultreg);
+              if (aktprocdef.rettype.def.deftype = floatdef) then
+                cg.a_reg_dealloc(exprasmlist,fpuresultreg);
 {$endif not i386}
 {$endif not i386}
            end
            end
          else
          else
-            cg.a_jmp_cond(exprasmlist,OC_None,aktexitlabel);
+           cg.a_jmp_cond(exprasmlist,OC_None,aktexitlabel);
        end;
        end;
 
 
 
 
@@ -669,7 +627,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.9  2002-03-31 20:26:34  jonas
+  Revision 1.10  2002-04-02 17:11:28  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.9  2002/03/31 20:26:34  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 66 - 48
compiler/ncgmem.pas

@@ -81,7 +81,7 @@ implementation
       globtype,systems,
       globtype,systems,
       cutils,verbose,globals,
       cutils,verbose,globals,
       symconst,symbase,symdef,symsym,aasm,
       symconst,symbase,symdef,symsym,aasm,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       nld,ncon,nadd,
       nld,ncon,nadd,
       cpubase,cgobj,cgcpu,
       cpubase,cgobj,cgcpu,
       cga,tgobj,rgobj;
       cga,tgobj,rgobj;
@@ -93,6 +93,7 @@ implementation
     procedure tcgloadvmtnode.pass_2;
     procedure tcgloadvmtnode.pass_2;
 
 
       begin
       begin
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          location.register:=rg.getregisterint(exprasmlist);
          location.register:=rg.getregisterint(exprasmlist);
          cg.a_load_sym_ofs_reg(exprasmlist,
          cg.a_load_sym_ofs_reg(exprasmlist,
            newasmsymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),
            newasmsymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),
@@ -115,19 +116,18 @@ implementation
 
 
     procedure tcghdisposenode.pass_2;
     procedure tcghdisposenode.pass_2;
       begin
       begin
+         location_reset(location,LOC_REFERENCE,def_cgsize_ref(resulttype.def));
+
          secondpass(left);
          secondpass(left);
          if codegenerror then
          if codegenerror then
            exit;
            exit;
-        { is this already set somewhere else? It wasn't present in the }
-        { original i386 code either (JM)                               }
-        { location.loc := LOC_REFERENCE;                               }
-         reset_reference(location.reference);
+
          case left.location.loc of
          case left.location.loc of
             LOC_REGISTER:
             LOC_REGISTER:
               begin
               begin
                 if not rg.isaddressregister(left.location.register) then
                 if not rg.isaddressregister(left.location.register) then
                   begin
                   begin
-                    rg.ungetregister(exprasmlist,left.location.register);
+                    location_release(exprasmlist,left.location);
                     location.reference.index := rg.getaddressregister(exprasmlist);
                     location.reference.index := rg.getaddressregister(exprasmlist);
                     cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
                     cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
                       location.reference.index);
                       location.reference.index);
@@ -135,13 +135,17 @@ implementation
                 else
                 else
                   location.reference.index := left.location.register;
                   location.reference.index := left.location.register;
               end;
               end;
-            LOC_CREGISTER,LOC_MEM,LOC_REFERENCE:
+            LOC_CREGISTER,
+            LOC_CREFERENCE,
+            LOC_REFERENCE:
               begin
               begin
-                 rg.del_location(exprasmlist,left.location);
+                 location_release(exprasmlist,left.location);
                  location.reference.index:=rg.getaddressregister(exprasmlist);
                  location.reference.index:=rg.getaddressregister(exprasmlist);
                  cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
                  cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
                    location.reference.index);
                    location.reference.index);
               end;
               end;
+            else
+              internalerror(2002032217);
          end;
          end;
       end;
       end;
 
 
@@ -158,12 +162,12 @@ implementation
            location of left }
            location of left }
          if nf_procvarload in flags then
          if nf_procvarload in flags then
           begin
           begin
-            set_location(location,left.location);
+            location_copy(location,left.location);
             exit;
             exit;
           end;
           end;
 
 
-         location.loc:=LOC_REGISTER;
-         rg.del_reference(exprasmlist,left.location.reference);
+         location_release(exprasmlist,left.location);
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          location.register:=rg.getaddressregister(exprasmlist);
          location.register:=rg.getaddressregister(exprasmlist);
          {@ on a procvar means returning an address to the procedure that
          {@ on a procvar means returning an address to the procedure that
            is stored in it.}
            is stored in it.}
@@ -178,7 +182,7 @@ implementation
            cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
            cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
              location.register)
              location.register)
          else
          else
-           cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
+           cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,
              location.register);
              location.register);
       end;
       end;
 
 
@@ -190,10 +194,12 @@ implementation
     procedure tcgdoubleaddrnode.pass_2;
     procedure tcgdoubleaddrnode.pass_2;
       begin
       begin
          secondpass(left);
          secondpass(left);
-         location.loc:=LOC_REGISTER;
-         rg.del_reference(exprasmlist,left.location.reference);
+
+         location_release(exprasmlist,left.location);
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          location.register:=rg.getaddressregister(exprasmlist);
          location.register:=rg.getaddressregister(exprasmlist);
-         cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
+
+         cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,
            location.register);
            location.register);
       end;
       end;
 
 
@@ -206,13 +212,13 @@ implementation
 
 
       begin
       begin
          secondpass(left);
          secondpass(left);
-         reset_reference(location.reference);
+         location_reset(location,LOC_REFERENCE,def_cgsize_ref(resulttype.def));
          case left.location.loc of
          case left.location.loc of
             LOC_REGISTER:
             LOC_REGISTER:
               begin
               begin
                 if not rg.isaddressregister(left.location.register) then
                 if not rg.isaddressregister(left.location.register) then
                   begin
                   begin
-                    rg.ungetregister(exprasmlist,left.location.register);
+                    location_release(exprasmlist,left.location);
                     location.reference.base := rg.getaddressregister(exprasmlist);
                     location.reference.base := rg.getaddressregister(exprasmlist);
                     cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
                     cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
                       location.reference.base);
                       location.reference.base);
@@ -220,9 +226,11 @@ implementation
                 else
                 else
                   location.reference.base := left.location.register;
                   location.reference.base := left.location.register;
               end;
               end;
-            LOC_CREGISTER,LOC_MEM,LOC_REFERENCE:
+            LOC_CREGISTER,
+            LOC_CREFERENCE,
+            LOC_REFERENCE:
               begin
               begin
-                 rg.del_location(exprasmlist,left.location);
+                 location_release(exprasmlist,left.location);
                  location.reference.base:=rg.getaddressregister(exprasmlist);
                  location.reference.base:=rg.getaddressregister(exprasmlist);
                  cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
                  cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
                    location.reference.base);
                    location.reference.base);
@@ -245,23 +253,25 @@ implementation
          { classes and interfaces must be dereferenced implicit }
          { classes and interfaces must be dereferenced implicit }
          if is_class_or_interface(left.resulttype.def) then
          if is_class_or_interface(left.resulttype.def) then
            begin
            begin
-             reset_reference(location.reference);
+             location_reset(location,LOC_REFERENCE,def_cgsize_ref(resulttype.def));
              case left.location.loc of
              case left.location.loc of
                 LOC_REGISTER:
                 LOC_REGISTER:
                   begin
                   begin
                     if not rg.isaddressregister(left.location.register) then
                     if not rg.isaddressregister(left.location.register) then
                       begin
                       begin
-                        rg.ungetregister(exprasmlist,left.location.register);
-                        location.reference.base := rg.getaddressregister(exprasmlist);
+                        location_release(exprasmlist,left.location);
+                        location.reference.base:=rg.getaddressregister(exprasmlist);
                         cg.a_load_reg_reg(exprasmlist,OS_ADDR,
                         cg.a_load_reg_reg(exprasmlist,OS_ADDR,
                           left.location.register,location.reference.base);
                           left.location.register,location.reference.base);
                       end
                       end
                     else
                     else
                       location.reference.base := left.location.register;
                       location.reference.base := left.location.register;
                   end;
                   end;
-                LOC_CREGISTER,LOC_MEM,LOC_REFERENCE:
+                LOC_CREGISTER,
+                LOC_CREFERENCE,
+                LOC_REFERENCE:
                   begin
                   begin
-                     rg.del_location(exprasmlist,left.location);
+                     location_release(exprasmlist,left.location);
                      location.reference.base:=rg.getaddressregister(exprasmlist);
                      location.reference.base:=rg.getaddressregister(exprasmlist);
                      cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
                      cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
                        location.reference.base);
                        location.reference.base);
@@ -275,12 +285,11 @@ implementation
                 location.reference);
                 location.reference);
            end
            end
          else
          else
-           set_location(location,left.location);
+           location_copy(location,left.location);
 
 
-        { is this already set somewhere else? It wasn't present in the }
-        { original i386 code either (JM)                               }
-        { location.loc := LOC_REFERENCE;                               }
          inc(location.reference.offset,vs.address);
          inc(location.reference.offset,vs.address);
+         { also update the size of the location }
+         location.size:=def_cgsize_ref(resulttype.def);
       end;
       end;
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -289,17 +298,16 @@ implementation
 
 
     procedure tcgselfnode.pass_2;
     procedure tcgselfnode.pass_2;
       begin
       begin
-         reset_reference(location.reference);
          rg.getexplicitregisterint(exprasmlist,SELF_POINTER);
          rg.getexplicitregisterint(exprasmlist,SELF_POINTER);
          if (resulttype.def.deftype=classrefdef) or
          if (resulttype.def.deftype=classrefdef) or
-           is_class(resulttype.def) then
+            is_class(resulttype.def) then
           begin
           begin
-            location.loc := LOC_CREGISTER;
+            location_reset(location,LOC_CREGISTER,OS_ADDR);
             location.register:=SELF_POINTER;
             location.register:=SELF_POINTER;
           end
           end
          else
          else
            begin
            begin
-             location.loc := LOC_REFERENCE;
+             location_reset(location,LOC_CREFERENCE,OS_ADDR);
              location.reference.base:=SELF_POINTER;
              location.reference.base:=SELF_POINTER;
            end;
            end;
       end;
       end;
@@ -326,18 +334,19 @@ implementation
             begin
             begin
                secondpass(left);
                secondpass(left);
 {$ifdef i386}
 {$ifdef i386}
-               if left.location.reference.segment<>R_NO then
+               if (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
+                  (left.location.reference.segment<>R_NO) then
                  message(parser_e_no_with_for_variable_in_other_segments);
                  message(parser_e_no_with_for_variable_in_other_segments);
 {$endif i386}
 {$endif i386}
 
 
-               new(withreference);
+               reference_reset(withreference);
 
 
                usetemp:=false;
                usetemp:=false;
                if (left.nodetype=loadn) and
                if (left.nodetype=loadn) and
                   (tloadnode(left).symtable=aktprocdef.localst) then
                   (tloadnode(left).symtable=aktprocdef.localst) then
                  begin
                  begin
                     { for locals use the local storage }
                     { for locals use the local storage }
-                    withreference^:=left.location.reference;
+                    withreference:=left.location.reference;
                     include(flags,nf_islocal);
                     include(flags,nf_islocal);
                  end
                  end
                else
                else
@@ -348,17 +357,17 @@ implementation
                   if is_class_or_interface(left.resulttype.def) then
                   if is_class_or_interface(left.resulttype.def) then
                     cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,tmpreg)
                     cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,tmpreg)
                   else
                   else
-                    cg.a_loadaddress_ref_reg(exprasmlist,
+                    cg.a_loadaddr_ref_reg(exprasmlist,
                       left.location.reference,tmpreg);
                       left.location.reference,tmpreg);
                 end;
                 end;
 
 
-               rg.del_location(exprasmlist,left.location);
+               location_release(exprasmlist,left.location);
 
 
                { if the with expression is stored in a temp    }
                { if the with expression is stored in a temp    }
                { area we must make it persistent and shouldn't }
                { area we must make it persistent and shouldn't }
                { release it (FK)                               }
                { release it (FK)                               }
-               if (left.location.loc in [LOC_MEM,LOC_REFERENCE]) and
-                 tg.istemp(left.location.reference) then
+               if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
+                  tg.istemp(left.location.reference) then
                  begin
                  begin
                     tg.normaltemptopersistant(left.location.reference.offset);
                     tg.normaltemptopersistant(left.location.reference.offset);
                     with_expr_in_temp:=true;
                     with_expr_in_temp:=true;
@@ -369,11 +378,10 @@ implementation
                { if usetemp is set the value must be in tmpreg }
                { if usetemp is set the value must be in tmpreg }
                if usetemp then
                if usetemp then
                 begin
                 begin
-                  tg.gettempofsizereference(exprasmlist,target_info.size_of_pointer,
-                    withreference^);
-                  tg.normaltemptopersistant(withreference^.offset);
+                  tg.gettempofsizereference(exprasmlist,target_info.size_of_pointer,withreference);
+                  tg.normaltemptopersistant(withreference.offset);
                   { move to temp reference }
                   { move to temp reference }
-                  cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference^);
+                  cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
                   cg.free_scratch_reg(exprasmlist,tmpreg);
                   cg.free_scratch_reg(exprasmlist,tmpreg);
 {$ifdef GDB}
 {$ifdef GDB}
                   if (cs_debuginfo in aktmoduleswitches) then
                   if (cs_debuginfo in aktmoduleswitches) then
@@ -385,7 +393,7 @@ implementation
                       withdebugList.concat(Tai_stabs.Create(strpnew(
                       withdebugList.concat(Tai_stabs.Create(strpnew(
                          '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
                          '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
                          '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
                          '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
-                         tostr(N_LSYM)+',0,0,'+tostr(withreference^.offset))));
+                         tostr(N_LSYM)+',0,0,'+tostr(withreference.offset))));
                       mangled_length:=length(aktprocdef.mangledname);
                       mangled_length:=length(aktprocdef.mangledname);
                       getmem(pp,mangled_length+50);
                       getmem(pp,mangled_length+50);
                       strpcopy(pp,'192,0,0,'+withstartlabel.name);
                       strpcopy(pp,'192,0,0,'+withstartlabel.name);
@@ -405,7 +413,7 @@ implementation
 
 
                if usetemp then
                if usetemp then
                  begin
                  begin
-                   tg.ungetpersistanttemp(exprasmlist,withreference^.offset);
+                   tg.ungetpersistanttemp(exprasmlist,withreference.offset);
 {$ifdef GDB}
 {$ifdef GDB}
                    if (cs_debuginfo in aktmoduleswitches) then
                    if (cs_debuginfo in aktmoduleswitches) then
                      begin
                      begin
@@ -426,8 +434,7 @@ implementation
                if with_expr_in_temp then
                if with_expr_in_temp then
                  tg.ungetpersistanttemp(exprasmlist,left.location.reference.offset);
                  tg.ungetpersistanttemp(exprasmlist,left.location.reference.offset);
 
 
-               dispose(withreference);
-               withreference:=nil;
+               reference_reset(withreference);
             end;
             end;
        end;
        end;
 
 
@@ -444,7 +451,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.4  2002-03-31 20:26:34  jonas
+  Revision 1.5  2002-04-02 17:11:28  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.4  2002/03/31 20:26:34  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 16 - 5
compiler/ncgutil.pas

@@ -46,7 +46,7 @@ implementation
     types,
     types,
     aasm,cgbase,regvars,
     aasm,cgbase,regvars,
     ncon,
     ncon,
-    cpubase,cpuinfo,tgobj,cgobj,cgcpu,cg64f32,rgobj;
+    cpubase,cpuinfo,tgobj,cginfo,cgobj,cgcpu,cg64f32,rgobj;
 
 
 
 
 {$ifdef TEMPS_NOT_PUSH}
 {$ifdef TEMPS_NOT_PUSH}
@@ -185,14 +185,14 @@ implementation
                 begin
                 begin
                    opsize:=def_cgsize(p.resulttype.def);
                    opsize:=def_cgsize(p.resulttype.def);
                    case p.location.loc of
                    case p.location.loc of
-                     LOC_CREGISTER,LOC_REGISTER,LOC_MEM,LOC_REFERENCE :
+                     LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
                        begin
                        begin
                          if (p.location.loc = LOC_CREGISTER) then
                          if (p.location.loc = LOC_CREGISTER) then
                            load_regvar_reg(exprasmlist,p.location.register);
                            load_regvar_reg(exprasmlist,p.location.register);
                          cg.a_cmp_const_loc_label(exprasmlist,opsize,OC_NE,
                          cg.a_cmp_const_loc_label(exprasmlist,opsize,OC_NE,
                            0,p.location,truelabel);
                            0,p.location,truelabel);
                          { !!! should happen right after cmp (JM) }
                          { !!! should happen right after cmp (JM) }
-                         rg.del_location(exprasmlist,p.location);
+                         location_release(exprasmlist,p.location);
                          cg.a_jmp_cond(exprasmlist,OC_NONE,falselabel);
                          cg.a_jmp_cond(exprasmlist,OC_NONE,falselabel);
                        end;
                        end;
                      LOC_FLAGS :
                      LOC_FLAGS :
@@ -213,7 +213,18 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.3  2002-03-31 20:26:34  jonas
+  Revision 1.4  2002-04-02 17:11:28  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.3  2002/03/31 20:26:34  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)
@@ -240,4 +251,4 @@ end.
       tordef's to int64)
       tordef's to int64)
     * maketojumpbool() is now processor independent (in ncgutil)
     * maketojumpbool() is now processor independent (in ncgutil)
     * getregister32 is now called getregisterint
     * getregister32 is now called getregisterint
-}
+}

+ 39 - 32
compiler/ncnv.pas

@@ -94,12 +94,13 @@ interface
           procedure second_proc_to_procvar;virtual;abstract;
           procedure second_proc_to_procvar;virtual;abstract;
           procedure second_bool_to_int;virtual;abstract;
           procedure second_bool_to_int;virtual;abstract;
           procedure second_int_to_bool;virtual;abstract;
           procedure second_int_to_bool;virtual;abstract;
+          procedure second_bool_to_bool;virtual;abstract;
           procedure second_load_smallset;virtual;abstract;
           procedure second_load_smallset;virtual;abstract;
           procedure second_ansistring_to_pchar;virtual;abstract;
           procedure second_ansistring_to_pchar;virtual;abstract;
           procedure second_pchar_to_string;virtual;abstract;
           procedure second_pchar_to_string;virtual;abstract;
           procedure second_class_to_intf;virtual;abstract;
           procedure second_class_to_intf;virtual;abstract;
           procedure second_char_to_char;virtual;abstract;
           procedure second_char_to_char;virtual;abstract;
-          procedure second_nothing; virtual;
+          procedure second_nothing; virtual;abstract;
 
 
        end;
        end;
        ttypeconvnodeclass = class of ttypeconvnode;
        ttypeconvnodeclass = class of ttypeconvnode;
@@ -135,7 +136,7 @@ implementation
       cutils,verbose,globals,widestr,
       cutils,verbose,globals,widestr,
       symconst,symdef,symsym,symtable,
       symconst,symdef,symsym,symtable,
       ncon,ncal,nset,nadd,ninl,nmem,
       ncon,ncal,nset,nadd,ninl,nmem,
-      cgbase,
+      cginfo,cgbase,
       htypechk,pass_1,cpubase,cpuinfo;
       htypechk,pass_1,cpubase,cpuinfo;
 
 
 
 
@@ -606,8 +607,6 @@ implementation
             exit;
             exit;
           end;
           end;
         result := nil;
         result := nil;
-        { a chararray with 1 element is the same as a char }
-        set_location(location,left.location);
       end;
       end;
 
 
 
 
@@ -823,21 +822,19 @@ implementation
                ((tsetdef(resulttype.def).settype = smallset) xor
                ((tsetdef(resulttype.def).settype = smallset) xor
                 (tsetdef(left.resulttype.def).settype = smallset)) then
                 (tsetdef(left.resulttype.def).settype = smallset)) then
               begin
               begin
-              { try to define the set as a normalset if it's a constant set }
+                { constant sets can be converted by changing the type only }
+                if (left.nodetype=setconstn) then
+                 begin
+                   tsetdef(left.resulttype.def).changesettype(tsetdef(resulttype.def).settype);
+                   result:=left;
+                   left:=nil;
+                   exit;
+                 end;
+
                 if (tsetdef(resulttype.def).settype <> smallset) then
                 if (tsetdef(resulttype.def).settype <> smallset) then
-                  begin
-                    if (left.nodetype=setconstn) then
-                      begin
-                        tsetdef(left.resulttype.def).changesettype(normset);
-                        result:=left;
-                        left:=nil;
-                        exit;
-                      end
-                     else
-                      convtype:=tc_load_smallset;
-                  end
+                 convtype:=tc_load_smallset
                 else
                 else
-                  convtype := tc_normal_2_smallset;
+                 convtype := tc_normal_2_smallset;
                 exit;
                 exit;
               end
               end
             else
             else
@@ -1098,8 +1095,12 @@ implementation
             left:=hp;
             left:=hp;
           end;
           end;
 
 
-        { remove typeconv after niln }
-        if (left.nodetype=niln) then
+        { remove typeconv after niln, but not when the result is a
+          methodpointer. The typeconv of the methodpointer will then
+          take care of updateing size of niln to OS_64 }
+        if (left.nodetype=niln) and
+           not((resulttype.def.deftype=procvardef) and
+               (po_methodpointer in tprocvardef(resulttype.def).procoptions)) then
           begin
           begin
             left.resulttype:=resulttype;
             left.resulttype:=resulttype;
             result:=left;
             result:=left;
@@ -1185,14 +1186,14 @@ implementation
 
 
       begin
       begin
          first_char_to_string:=nil;
          first_char_to_string:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CREFERENCE;
       end;
       end;
 
 
 
 
     function ttypeconvnode.first_nothing : tnode;
     function ttypeconvnode.first_nothing : tnode;
       begin
       begin
          first_nothing:=nil;
          first_nothing:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CREFERENCE;
       end;
       end;
 
 
 
 
@@ -1224,7 +1225,7 @@ implementation
          if registersfpu<1 then
          if registersfpu<1 then
           registersfpu:=1;
           registersfpu:=1;
 {$endif not m68k}
 {$endif not m68k}
-        location.loc:=LOC_FPU;
+        location.loc:=LOC_FPUREGISTER;
       end;
       end;
 
 
 
 
@@ -1240,7 +1241,7 @@ implementation
 {$endif}
 {$endif}
          if registersfpu<1 then
          if registersfpu<1 then
            registersfpu:=1;
            registersfpu:=1;
-         location.loc:=LOC_FPU;
+         location.loc:=LOC_FPUREGISTER;
       end;
       end;
 
 
 
 
@@ -1270,7 +1271,7 @@ implementation
          be accepted for var parameters }
          be accepted for var parameters }
          if (nf_explizit in flags) and
          if (nf_explizit in flags) and
             (left.resulttype.def.size=resulttype.def.size) and
             (left.resulttype.def.size=resulttype.def.size) and
-            (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
+            (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
            exit;
            exit;
          { when converting to 64bit, first convert to a 32bit int and then   }
          { when converting to 64bit, first convert to a 32bit int and then   }
          { convert to a 64bit int (only necessary for 32bit processors) (JM) }
          { convert to a 64bit int (only necessary for 32bit processors) (JM) }
@@ -1297,7 +1298,7 @@ implementation
          be accepted for var parameters }
          be accepted for var parameters }
          if (nf_explizit in flags) and
          if (nf_explizit in flags) and
             (left.resulttype.def.size=resulttype.def.size) and
             (left.resulttype.def.size=resulttype.def.size) and
-            (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
+            (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
            exit;
            exit;
          location.loc:=LOC_REGISTER;
          location.loc:=LOC_REGISTER;
          { need if bool to bool !!
          { need if bool to bool !!
@@ -1454,7 +1455,7 @@ implementation
  {$ifdef SUPPORT_MMX}
  {$ifdef SUPPORT_MMX}
         registersmmx:=left.registersmmx;
         registersmmx:=left.registersmmx;
  {$endif}
  {$endif}
-        set_location(location,left.location);
+        location.loc:=left.location.loc;
 
 
         if nf_explizit in flags then
         if nf_explizit in flags then
          begin
          begin
@@ -1490,11 +1491,6 @@ implementation
       end;
       end;
 
 
 
 
-    procedure ttypeconvnode.second_nothing;
-      begin
-      end;
-
-
 {*****************************************************************************
 {*****************************************************************************
                                 TISNODE
                                 TISNODE
 *****************************************************************************}
 *****************************************************************************}
@@ -1688,7 +1684,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.48  2002-02-03 09:30:03  peter
+  Revision 1.49  2002-04-02 17:11:28  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.48  2002/02/03 09:30:03  peter
     * more fixes for protected handling
     * more fixes for protected handling
 
 
   Revision 1.47  2001/12/10 14:34:04  jonas
   Revision 1.47  2001/12/10 14:34:04  jonas

+ 25 - 8
compiler/ncon.pas

@@ -342,7 +342,7 @@ implementation
     function trealconstnode.pass_1 : tnode;
     function trealconstnode.pass_1 : tnode;
       begin
       begin
          result:=nil;
          result:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CREFERENCE;
          { needs to be loaded into an FPU register }
          { needs to be loaded into an FPU register }
          registersfpu:=1;
          registersfpu:=1;
       end;
       end;
@@ -388,7 +388,10 @@ implementation
     function tordconstnode.pass_1 : tnode;
     function tordconstnode.pass_1 : tnode;
       begin
       begin
          result:=nil;
          result:=nil;
-         location.loc:=LOC_MEM;
+         if is_64bitint(resulttype.def) then
+          location.loc:=LOC_CREFERENCE
+         else
+          location.loc:=LOC_CONSTANT;
       end;
       end;
 
 
     function tordconstnode.docompare(p: tnode): boolean;
     function tordconstnode.docompare(p: tnode): boolean;
@@ -431,7 +434,7 @@ implementation
     function tpointerconstnode.pass_1 : tnode;
     function tpointerconstnode.pass_1 : tnode;
       begin
       begin
          result:=nil;
          result:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CONSTANT;
       end;
       end;
 
 
     function tpointerconstnode.docompare(p: tnode): boolean;
     function tpointerconstnode.docompare(p: tnode): boolean;
@@ -543,7 +546,7 @@ implementation
     function tstringconstnode.pass_1 : tnode;
     function tstringconstnode.pass_1 : tnode;
       begin
       begin
         result:=nil;
         result:=nil;
-        location.loc:=LOC_MEM;
+        location.loc:=LOC_CREFERENCE;
       end;
       end;
 
 
     function tstringconstnode.getpcharcopy : pchar;
     function tstringconstnode.getpcharcopy : pchar;
@@ -622,7 +625,10 @@ implementation
     function tsetconstnode.pass_1 : tnode;
     function tsetconstnode.pass_1 : tnode;
       begin
       begin
          result:=nil;
          result:=nil;
-         location.loc:=LOC_MEM;
+         if tsetdef(resulttype.def).settype=smallset then
+          location.loc:=LOC_CONSTANT
+         else
+          location.loc:=LOC_CREFERENCE;
       end;
       end;
 
 
     function tsetconstnode.docompare(p: tnode): boolean;
     function tsetconstnode.docompare(p: tnode): boolean;
@@ -662,7 +668,7 @@ implementation
     function tnilnode.pass_1 : tnode;
     function tnilnode.pass_1 : tnode;
       begin
       begin
         result:=nil;
         result:=nil;
-        location.loc:=LOC_MEM;
+        location.loc:=LOC_CONSTANT;
       end;
       end;
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -696,7 +702,7 @@ implementation
     function tguidconstnode.pass_1 : tnode;
     function tguidconstnode.pass_1 : tnode;
       begin
       begin
          result:=nil;
          result:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CREFERENCE;
       end;
       end;
 
 
     function tguidconstnode.docompare(p: tnode): boolean;
     function tguidconstnode.docompare(p: tnode): boolean;
@@ -718,7 +724,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.25  2002-03-04 19:10:11  peter
+  Revision 1.26  2002-04-02 17:11:29  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.25  2002/03/04 19:10:11  peter
     * removed compiler warnings
     * removed compiler warnings
 
 
   Revision 1.24  2001/10/20 19:28:38  peter
   Revision 1.24  2001/10/20 19:28:38  peter

+ 22 - 11
compiler/ninl.pas

@@ -1993,7 +1993,7 @@ implementation
               else
               else
                 firstpass(left);
                 firstpass(left);
               left_max;
               left_max;
-              set_location(location,left.location);
+              location.loc:=left.location.loc;
            end;
            end;
          inc(parsing_para_level);
          inc(parsing_para_level);
          { intern const should already be handled }
          { intern const should already be handled }
@@ -2162,7 +2162,7 @@ implementation
                       begin
                       begin
                          { need we an additional register ? }
                          { need we an additional register ? }
                          if not(is_constintnode(tcallparanode(tcallparanode(left).right).left)) and
                          if not(is_constintnode(tcallparanode(tcallparanode(left).right).left)) and
-                           (tcallparanode(tcallparanode(left).right).left.location.loc in [LOC_MEM,LOC_REFERENCE]) and
+                           (tcallparanode(tcallparanode(left).right).left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
                            (tcallparanode(tcallparanode(left).right).left.registers32<=1) then
                            (tcallparanode(tcallparanode(left).right).left.registers32<=1) then
                            inc(registers32);
                            inc(registers32);
 
 
@@ -2219,7 +2219,7 @@ implementation
 
 
          in_cos_extended:
          in_cos_extended:
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -2229,7 +2229,7 @@ implementation
 
 
          in_sin_extended:
          in_sin_extended:
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -2239,7 +2239,7 @@ implementation
 
 
          in_arctan_extended:
          in_arctan_extended:
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,2);
              registersfpu:=max(left.registersfpu,2);
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -2249,13 +2249,13 @@ implementation
 
 
          in_pi:
          in_pi:
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registersfpu:=1;
              registersfpu:=1;
            end;
            end;
 
 
          in_abs_extended:
          in_abs_extended:
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -2265,7 +2265,7 @@ implementation
 
 
          in_sqr_extended:
          in_sqr_extended:
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -2275,7 +2275,7 @@ implementation
 
 
          in_sqrt_extended:
          in_sqrt_extended:
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -2285,7 +2285,7 @@ implementation
 
 
          in_ln_extended:
          in_ln_extended:
            begin
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,2);
              registersfpu:=max(left.registersfpu,2);
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
@@ -2341,7 +2341,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.70  2002-03-31 20:26:34  jonas
+  Revision 1.71  2002-04-02 17:11:29  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.70  2002/03/31 20:26:34  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 26 - 11
compiler/nld.pas

@@ -124,7 +124,7 @@ implementation
       cutils,verbose,globtype,globals,systems,
       cutils,verbose,globtype,globals,systems,
       symtable,types,
       symtable,types,
       htypechk,pass_1,
       htypechk,pass_1,
-      ncnv,nmem,ncal,cpubase,rgobj,cgbase
+      ncnv,nmem,ncal,cpubase,rgobj,cginfo,cgbase
       ;
       ;
 
 
 
 
@@ -312,7 +312,7 @@ implementation
                       { we use ansistrings so no fast exit here }
                       { we use ansistrings so no fast exit here }
                       if assigned(procinfo) then
                       if assigned(procinfo) then
                         procinfo^.no_fast_exit:=true;
                         procinfo^.no_fast_exit:=true;
-                      location.loc:=LOC_MEM;
+                      location.loc:=LOC_CREFERENCE;
                    end;
                    end;
               end;
               end;
             varsym :
             varsym :
@@ -331,7 +331,7 @@ implementation
                         end;
                         end;
                      end;
                      end;
                    if (tvarsym(symtableentry).varspez=vs_const) then
                    if (tvarsym(symtableentry).varspez=vs_const) then
-                     location.loc:=LOC_MEM;
+                     location.loc:=LOC_CREFERENCE;
                    { we need a register for call by reference parameters }
                    { we need a register for call by reference parameters }
                    if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
                    if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
                       ((tvarsym(symtableentry).varspez=vs_const) and
                       ((tvarsym(symtableentry).varspez=vs_const) and
@@ -604,7 +604,7 @@ implementation
       begin
       begin
         firstpass(left);
         firstpass(left);
         firstpass(right);
         firstpass(right);
-        location.loc := LOC_MEM;
+        location.loc := LOC_CREFERENCE;
         calcregisters(self,0,0,0);
         calcregisters(self,0,0,0);
         result:=nil;
         result:=nil;
       end;
       end;
@@ -711,7 +711,7 @@ implementation
       begin
       begin
         dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
         dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
         result:=nil;
         result:=nil;
-      { only pass left tree, right tree contains next construct if any }
+        { only pass left tree, right tree contains next construct if any }
         if assigned(left) then
         if assigned(left) then
          begin
          begin
            hp:=self;
            hp:=self;
@@ -784,14 +784,19 @@ implementation
                end;
                end;
               chp.flags := chp.flags+orgflags;
               chp.flags := chp.flags+orgflags;
               include(chp.flags,nf_cargswap);
               include(chp.flags,nf_cargswap);
-              chp.location.loc:=LOC_MEM;
+              chp.location.loc:=LOC_CREFERENCE;
               calcregisters(chp,0,0,0);
               calcregisters(chp,0,0,0);
               chp.resulttype:=htype;
               chp.resulttype:=htype;
               result:=chp;
               result:=chp;
               exit;
               exit;
             end;
             end;
          end;
          end;
-        location.loc:=LOC_MEM;
+        { C Arguments are pushed on the stack and
+          are not accesible after the push }
+        if not(nf_cargs in flags) then
+         location.loc:=LOC_CREFERENCE
+        else
+         location.loc:=LOC_INVALID;
         calcregisters(self,0,0,0);
         calcregisters(self,0,0,0);
       end;
       end;
 
 
@@ -879,7 +884,7 @@ implementation
     function trttinode.pass_1 : tnode;
     function trttinode.pass_1 : tnode;
       begin
       begin
         result:=nil;
         result:=nil;
-        location.loc:=LOC_MEM;
+        location.loc:=LOC_CREFERENCE;
       end;
       end;
 
 
 
 
@@ -894,8 +899,7 @@ implementation
 
 
     procedure trttinode.pass_2;
     procedure trttinode.pass_2;
       begin
       begin
-        reset_reference(location.reference);
-        location.loc:=LOC_MEM;
+        location_reset(location,LOC_CREFERENCE,OS_NO);
         location.reference.symbol:=rttidef.get_rtti_label(rttitype);
         location.reference.symbol:=rttidef.get_rtti_label(rttitype);
       end;
       end;
 
 
@@ -911,7 +915,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.33  2002-03-31 20:26:34  jonas
+  Revision 1.34  2002-04-02 17:11:29  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.33  2002/03/31 20:26:34  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 14 - 3
compiler/nmat.pas

@@ -628,7 +628,7 @@ implementation
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
          if is_boolean(resulttype.def) then
          if is_boolean(resulttype.def) then
            begin
            begin
-             if (location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
+             if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
               begin
               begin
                 location.loc:=LOC_REGISTER;
                 location.loc:=LOC_REGISTER;
                 if (registers32<1) then
                 if (registers32<1) then
@@ -654,7 +654,7 @@ implementation
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
            if is_64bitint(left.resulttype.def) then
            if is_64bitint(left.resulttype.def) then
              begin
              begin
-                if (location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
+                if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
                  begin
                  begin
                    location.loc:=LOC_REGISTER;
                    location.loc:=LOC_REGISTER;
                    if (registers32<2) then
                    if (registers32<2) then
@@ -678,7 +678,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.29  2002-03-04 19:10:11  peter
+  Revision 1.30  2002-04-02 17:11:29  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.29  2002/03/04 19:10:11  peter
     * removed compiler warnings
     * removed compiler warnings
 
 
   Revision 1.28  2002/02/11 11:45:51  michael
   Revision 1.28  2002/02/11 11:45:51  michael

+ 21 - 10
compiler/nmem.pas

@@ -115,9 +115,9 @@ interface
        tselfnodeclass = class of tselfnode;
        tselfnodeclass = class of tselfnode;
 
 
        twithnode = class(tbinarynode)
        twithnode = class(tbinarynode)
-          withsymtable : twithsymtable;
-          tablecount : longint;
-          withreference : preference;
+          withsymtable  : twithsymtable;
+          tablecount    : longint;
+          withreference : treference;
           constructor create(symtable : twithsymtable;l,r : tnode;count : longint);virtual;
           constructor create(symtable : twithsymtable;l,r : tnode;count : longint);virtual;
           destructor destroy;override;
           destructor destroy;override;
           function getcopy : tnode;override;
           function getcopy : tnode;override;
@@ -551,7 +551,7 @@ implementation
           end;
           end;
 
 
          { we should allow loc_mem for @string }
          { we should allow loc_mem for @string }
-         if not(left.location.loc in [LOC_MEM,LOC_REFERENCE]) then
+         if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
            begin
            begin
              aktfilepos:=left.fileinfo;
              aktfilepos:=left.fileinfo;
              CGMessage(cg_e_illegal_expression);
              CGMessage(cg_e_illegal_expression);
@@ -714,10 +714,10 @@ implementation
            end
            end
          else
          else
            begin
            begin
-              if (left.location.loc<>LOC_MEM) and
-                (left.location.loc<>LOC_REFERENCE) then
+              if (left.location.loc<>LOC_CREFERENCE) and
+                 (left.location.loc<>LOC_REFERENCE) then
                 CGMessage(cg_e_illegal_expression);
                 CGMessage(cg_e_illegal_expression);
-              set_location(location,left.location);
+              location.loc:=left.location.loc;
            end;
            end;
       end;
       end;
 
 
@@ -885,7 +885,7 @@ implementation
          if left.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
          if left.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
            location.loc:=LOC_REFERENCE
            location.loc:=LOC_REFERENCE
          else
          else
-           location.loc:=LOC_MEM;
+           location.loc:=LOC_CREFERENCE;
       end;
       end;
 
 
 
 
@@ -927,7 +927,7 @@ implementation
          inherited create(withn,l,r);
          inherited create(withn,l,r);
          withsymtable:=symtable;
          withsymtable:=symtable;
          tablecount:=count;
          tablecount:=count;
-         withreference:=nil;
+         FillChar(withreference,sizeof(withreference),0);
          set_file_line(l);
          set_file_line(l);
       end;
       end;
 
 
@@ -1040,7 +1040,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.26  2002-04-01 20:57:13  jonas
+  Revision 1.27  2002-04-02 17:11:29  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.26  2002/04/01 20:57:13  jonas
     * fixed web bug 1907
     * fixed web bug 1907
     * fixed some other procvar related bugs (all related to accepting procvar
     * fixed some other procvar related bugs (all related to accepting procvar
         constructs with either too many or too little parameters)
         constructs with either too many or too little parameters)

+ 13 - 2
compiler/nopt.pas

@@ -137,7 +137,7 @@ end;
 function taddsstringoptnode.pass_1: tnode;
 function taddsstringoptnode.pass_1: tnode;
 begin
 begin
   pass_1 := nil;
   pass_1 := nil;
-  location.loc := LOC_MEM;
+  location.loc := LOC_CREFERENCE;
   calcregisters(self,0,0,0);
   calcregisters(self,0,0,0);
   { here we call STRCONCAT or STRCMP or STRCOPY }
   { here we call STRCONCAT or STRCMP or STRCOPY }
   procinfo^.flags:=procinfo^.flags or pi_do_call;
   procinfo^.flags:=procinfo^.flags or pi_do_call;
@@ -278,7 +278,18 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2001-09-02 21:12:07  peter
+  Revision 1.6  2002-04-02 17:11:29  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.5  2001/09/02 21:12:07  peter
     * move class of definitions into type section for delphi
     * move class of definitions into type section for delphi
 
 
   Revision 1.4  2001/08/26 13:36:43  florian
   Revision 1.4  2001/08/26 13:36:43  florian

+ 30 - 21
compiler/nset.pas

@@ -160,7 +160,7 @@ implementation
          if codegenerror then
          if codegenerror then
           exit;
           exit;
 
 
-         set_location(location,left.location);
+         location_copy(location,left.location);
          calcregisters(self,0,0,0);
          calcregisters(self,0,0,0);
       end;
       end;
 
 
@@ -176,6 +176,8 @@ implementation
 
 
 
 
     function tinnode.det_resulttype:tnode;
     function tinnode.det_resulttype:tnode;
+      type
+        byteset = set of byte;
       var
       var
         t : tnode;
         t : tnode;
         pst : pconstset;
         pst : pconstset;
@@ -246,28 +248,12 @@ implementation
          { type conversion/check }
          { type conversion/check }
          if assigned(tsetdef(right.resulttype.def).elementtype.def) then
          if assigned(tsetdef(right.resulttype.def).elementtype.def) then
           inserttypeconv(left,tsetdef(right.resulttype.def).elementtype);
           inserttypeconv(left,tsetdef(right.resulttype.def).elementtype);
-      end;
-
-
-    function tinnode.pass_1 : tnode;
-      type
-        byteset = set of byte;
-      var
-        t : tnode;
-      begin
-         result:=nil;
-         location.loc:=LOC_FLAGS;
-
-         firstpass(right);
-         firstpass(left);
-         if codegenerror then
-           exit;
 
 
          { empty set then return false }
          { empty set then return false }
          if not assigned(tsetdef(right.resulttype.def).elementtype.def) then
          if not assigned(tsetdef(right.resulttype.def).elementtype.def) then
           begin
           begin
             t:=cordconstnode.create(0,booltype);
             t:=cordconstnode.create(0,booltype);
-            firstpass(t);
+            resulttypepass(t);
             result:=t;
             result:=t;
             exit;
             exit;
           end;
           end;
@@ -276,10 +262,22 @@ implementation
          if (left.nodetype=ordconstn) and (right.nodetype=setconstn) then
          if (left.nodetype=ordconstn) and (right.nodetype=setconstn) then
           begin
           begin
             t:=cordconstnode.create(byte(tordconstnode(left).value in byteset(tsetconstnode(right).value_set^)),booltype);
             t:=cordconstnode.create(byte(tordconstnode(left).value in byteset(tsetconstnode(right).value_set^)),booltype);
-            firstpass(t);
+            resulttypepass(t);
             result:=t;
             result:=t;
             exit;
             exit;
           end;
           end;
+      end;
+
+
+    function tinnode.pass_1 : tnode;
+      begin
+         result:=nil;
+         location.loc:=LOC_FLAGS;
+
+         firstpass(right);
+         firstpass(left);
+         if codegenerror then
+           exit;
 
 
          left_right_max;
          left_right_max;
          { this is not allways true due to optimization }
          { this is not allways true due to optimization }
@@ -343,7 +341,7 @@ implementation
          if codegenerror then
          if codegenerror then
            exit;
            exit;
         left_right_max;
         left_right_max;
-        set_location(location,left.location);
+        location_copy(location,left.location);
       end;
       end;
 
 
 
 
@@ -576,7 +574,18 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.18  2002-03-31 20:26:35  jonas
+  Revision 1.19  2002-04-02 17:11:29  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.18  2002/03/31 20:26:35  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 26 - 2
compiler/pass_2.pas

@@ -53,7 +53,7 @@ implementation
      globtype,systems,verbose,
      globtype,systems,verbose,
      cclasses,globals,
      cclasses,globals,
      symconst,symbase,symtype,symsym,aasm,
      symconst,symbase,symtype,symsym,aasm,
-     pass_1,cgbase,regvars,nflw,rgobj;
+     pass_1,cpubase,cgbase,regvars,nflw,rgobj;
 
 
 {*****************************************************************************
 {*****************************************************************************
                               SecondPass
                               SecondPass
@@ -163,6 +163,9 @@ implementation
 {$ifdef TEMPREGDEBUG}
 {$ifdef TEMPREGDEBUG}
          prevp : pptree;
          prevp : pptree;
 {$endif TEMPREGDEBUG}
 {$endif TEMPREGDEBUG}
+{$ifdef EXTDEBUG}
+         oldloc : tloc;
+{$endif EXTDEBUG}
       begin
       begin
          if not(nf_error in p.flags) then
          if not(nf_error in p.flags) then
           begin
           begin
@@ -178,6 +181,10 @@ implementation
             aktfilepos:=p.fileinfo;
             aktfilepos:=p.fileinfo;
             aktlocalswitches:=p.localswitches;
             aktlocalswitches:=p.localswitches;
             codegenerror:=false;
             codegenerror:=false;
+{$ifdef EXTDEBUG}
+            oldloc:=p.location.loc;
+            p.location.loc:=LOC_INVALID;
+{$endif EXTDEBUG}
 {$ifdef logsecondpass}
 {$ifdef logsecondpass}
             logsecond(p.nodetype,true);
             logsecond(p.nodetype,true);
 {$endif logsecondpass}
 {$endif logsecondpass}
@@ -185,6 +192,12 @@ implementation
 {$ifdef logsecondpass}
 {$ifdef logsecondpass}
             logsecond(p.nodetype,false);
             logsecond(p.nodetype,false);
 {$endif logsecondpass}
 {$endif logsecondpass}
+{$ifdef EXTDEBUG}
+            if (not codegenerror) and
+               (oldloc<>LOC_INVALID) and
+               (p.location.loc=LOC_INVALID) then
+             Comment(V_Fatal,'Location not set in secondpass: '+nodetype2str[p.nodetype]);
+{$endif EXTDEBUG}
             if codegenerror then
             if codegenerror then
               include(p.flags,nf_error);
               include(p.flags,nf_error);
 
 
@@ -311,7 +324,18 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.22  2002-03-31 20:26:35  jonas
+  Revision 1.23  2002-04-02 17:11:29  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.22  2002/03/31 20:26:35  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 57 - 48
compiler/pmodules.pas

@@ -214,10 +214,10 @@ implementation
         dataSegment.concatlist(ResourceStringTables);
         dataSegment.concatlist(ResourceStringTables);
         ResourceStringTables.free;
         ResourceStringTables.free;
       end;
       end;
-      
-      
-      
-      
+
+
+
+
 
 
     procedure InsertInitFinalTable;
     procedure InsertInitFinalTable;
       var
       var
@@ -675,7 +675,7 @@ implementation
            procdef:=aktprocdef;
            procdef:=aktprocdef;
          end;
          end;
       end;
       end;
-      
+
     procedure insertLocalThreadvarsTablesTable;
     procedure insertLocalThreadvarsTablesTable;
       var
       var
         hp : tused_unit;
         hp : tused_unit;
@@ -703,39 +703,37 @@ implementation
           dataSegment.concat(Tai_cut.Create);
           dataSegment.concat(Tai_cut.Create);
         dataSegment.concatlist(ltvTables);
         dataSegment.concatlist(ltvTables);
         ltvTables.free;
         ltvTables.free;
-	if count > 0 then
-  	  have_local_threadvars := true;
+        if count > 0 then
+          have_local_threadvars := true;
       end;
       end;
-      
-      
-      
+
+
+
     var ltvTable : taasmoutput;
     var ltvTable : taasmoutput;
-      
+
     procedure addToLocalThreadvarTab(p:tnamedindexitem);
     procedure addToLocalThreadvarTab(p:tnamedindexitem);
       var
       var
-        vs   : tvarsym;
-        s    : string;
-	asym : tasmsymbol;
+        asym : tasmsymbol;
       begin
       begin
         with tvarsym(p) do
         with tvarsym(p) do
          begin
          begin
-	   if (typ=varsym) and (vo_is_thread_var IN varoptions) then
-	   begin
-	     if ltvTable = nil then
-	     begin   { first threadvar }
-	       ltvTable := TAAsmOutput.Create;
-	       ltvTable.insert(tai_symbol.createdataname_global(current_module.modulename^+'_$LOCALTHREADVARLIST',0));
-	     end;
-	     asym := getasmsymbol(mangledname);
-	     if asym <> nil then
-	     begin
-	       ltvTable.concat(tai_const_symbol.create(asym));    { address of threadvar }
-	       ltvTable.concat(tai_const.create_32bit(getsize));  { size of threadvar }
-	     end;
-	   end;
+           if (typ=varsym) and (vo_is_thread_var IN varoptions) then
+           begin
+             if ltvTable = nil then
+             begin   { first threadvar }
+               ltvTable := TAAsmOutput.Create;
+               ltvTable.insert(tai_symbol.createdataname_global(current_module.modulename^+'_$LOCALTHREADVARLIST',0));
+             end;
+                 asym := getasmsymbol(mangledname);
+             if asym <> nil then
+             begin
+               ltvTable.concat(tai_const_symbol.create(asym));    { address of threadvar }
+               ltvTable.concat(tai_const.create_32bit(getsize));  { size of threadvar }
+             end;
+           end;
          end;
          end;
       end;
       end;
-      
+
 
 
 
 
     procedure proc_unit;
     procedure proc_unit;
@@ -752,7 +750,7 @@ implementation
           ((resourcestringlist=nil) or resourcestringList.empty)
           ((resourcestringlist=nil) or resourcestringList.empty)
         );
         );
       end;
       end;
-      
+
       var
       var
          main_file: tinputfile;
          main_file: tinputfile;
          st     : tsymtable;
          st     : tsymtable;
@@ -1013,20 +1011,20 @@ implementation
                 codeSegment.concat(Tai_cut.Create);
                 codeSegment.concat(Tai_cut.Create);
               genimplicitunitfinal(codesegment);
               genimplicitunitfinal(codesegment);
            end;
            end;
-	 
-	 { generate a list of local threadvars }  
-	 ltvTable := nil;
-	 st.foreach_static (@addToLocalThreadvarTab);
-	 if ltvTable <> nil then
-	 begin
-	   ltvTable.concat(tai_const.create_32bit(0));  { end of list marker }
-	   ltvTable.concat(tai_symbol_end.createname(current_module.modulename^+'_$LOCALTHREADVARLIST'));
-	   if (cs_create_smart in aktmoduleswitches) then
-             dataSegment.concat(Tai_cut.Create);
-	   dataSegment.concatlist(ltvTable);
-	   ltvTable.Free;
-	   current_module.flags:=current_module.flags or uf_local_threadvars;
-	 end;
+
+         { generate a list of local threadvars }
+         ltvTable := nil;
+         st.foreach_static (@addToLocalThreadvarTab);
+         if ltvTable <> nil then
+         begin
+           ltvTable.concat(tai_const.create_32bit(0));  { end of list marker }
+           ltvTable.concat(tai_symbol_end.createname(current_module.modulename^+'_$LOCALTHREADVARLIST'));
+           if (cs_create_smart in aktmoduleswitches) then
+            dataSegment.concat(Tai_cut.Create);
+           dataSegment.concatlist(ltvTable);
+           ltvTable.Free;
+           current_module.flags:=current_module.flags or uf_local_threadvars;
+         end;
 
 
          { the last char should always be a point }
          { the last char should always be a point }
          consume(_POINT);
          consume(_POINT);
@@ -1301,7 +1299,7 @@ implementation
             aktprocdef.aliasnames.insert('PASCALMAIN');
             aktprocdef.aliasnames.insert('PASCALMAIN');
             aktprocdef.aliasnames.insert(target_info.cprefix+'main');
             aktprocdef.aliasnames.insert(target_info.cprefix+'main');
           end;
           end;
-	 insertLocalThreadvarsTablesTable;
+         insertLocalThreadvarsTablesTable;
          compile_proc_body(true,false);
          compile_proc_body(true,false);
 
 
          { Add symbol to the exports section for win32 so smartlinking a
          { Add symbol to the exports section for win32 so smartlinking a
@@ -1373,13 +1371,13 @@ implementation
 
 
          if islibrary or
          if islibrary or
             (target_info.target=target_i386_WIN32) or
             (target_info.target=target_i386_WIN32) or
-	    (target_info.target=target_i386_NETWARE) then
+            (target_info.target=target_i386_NETWARE) then
            exportlib.generatelib;
            exportlib.generatelib;
 
 
 
 
          { insert heap }
          { insert heap }
          insertResourceTablesTable;
          insertResourceTablesTable;
-	 
+
          insertinitfinaltable;
          insertinitfinaltable;
          insertheap;
          insertheap;
          inserttargetspecific;
          inserttargetspecific;
@@ -1430,7 +1428,18 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.55  2002-04-01 13:43:32  armin
+  Revision 1.56  2002-04-02 17:11:29  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.55  2002/04/01 13:43:32  armin
   addToLocalThreadvarList used '_'+name instead of mangledname to find asm symbol
   addToLocalThreadvarList used '_'+name instead of mangledname to find asm symbol
 
 
   Revision 1.54  2002/03/29 17:19:50  armin
   Revision 1.54  2002/03/29 17:19:50  armin

+ 13 - 2
compiler/rautils.pas

@@ -1030,7 +1030,7 @@ Begin
       Message(asmr_e_invalid_operand_type);
       Message(asmr_e_invalid_operand_type);
   end;
   end;
   opr.typ := OPR_REFERENCE;
   opr.typ := OPR_REFERENCE;
-  reset_reference(opr.ref);
+  Fillchar(opr.ref,sizeof(treference),0);
 end;
 end;
 
 
 
 
@@ -1585,7 +1585,18 @@ end;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.27  2002-01-29 21:32:03  peter
+  Revision 1.28  2002-04-02 17:11:29  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/01/29 21:32:03  peter
     * allow accessing locals in other lexlevel when the current assembler
     * allow accessing locals in other lexlevel when the current assembler
       routine doesn't have locals.
       routine doesn't have locals.
 
 

+ 15 - 4
compiler/regvars.pas

@@ -30,7 +30,7 @@ interface
        aasm,
        aasm,
        node,
        node,
        symsym,
        symsym,
-       cpubase, tgobj, rgobj;
+       cpubase, cginfo, tgobj, rgobj;
 
 
     procedure assign_regvars(p: tnode);
     procedure assign_regvars(p: tnode);
     procedure load_regvars(asml: TAAsmoutput; p: tnode);
     procedure load_regvars(asml: TAAsmoutput; p: tnode);
@@ -284,7 +284,7 @@ implementation
                 { possible that it's been modified  (JM)                  }
                 { possible that it's been modified  (JM)                  }
                 if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
                 if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
                   begin
                   begin
-                    reset_reference(hr);
+                    reference_reset(hr);
                     if vsym.owner.symtabletype in [inlinelocalsymtable,localsymtable] then
                     if vsym.owner.symtabletype in [inlinelocalsymtable,localsymtable] then
                       hr.offset:=-vsym.address+vsym.owner.address_fixup
                       hr.offset:=-vsym.address+vsym.owner.address_fixup
                     else hr.offset:=vsym.address+vsym.owner.address_fixup;
                     else hr.offset:=vsym.address+vsym.owner.address_fixup;
@@ -306,7 +306,7 @@ implementation
       if not rg.regvar_loaded[makereg32(vsym.reg)] then
       if not rg.regvar_loaded[makereg32(vsym.reg)] then
         begin
         begin
           asml.concat(Tairegalloc.alloc(makereg32(vsym.reg)));
           asml.concat(Tairegalloc.alloc(makereg32(vsym.reg)));
-          reset_reference(hr);
+          reference_reset(hr);
           if vsym.owner.symtabletype in [inlinelocalsymtable,localsymtable] then
           if vsym.owner.symtabletype in [inlinelocalsymtable,localsymtable] then
             hr.offset:=-vsym.address+vsym.owner.address_fixup
             hr.offset:=-vsym.address+vsym.owner.address_fixup
           else hr.offset:=vsym.address+vsym.owner.address_fixup;
           else hr.offset:=vsym.address+vsym.owner.address_fixup;
@@ -459,7 +459,18 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.23  2002-03-31 20:26:36  jonas
+  Revision 1.24  2002-04-02 17:11:29  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.23  2002/03/31 20:26:36  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 116 - 42
compiler/rgobj.pas

@@ -32,7 +32,7 @@ unit rgobj;
       cpuinfo,
       cpuinfo,
       cpuasm,
       cpuasm,
       tainst,
       tainst,
-      cclasses,globtype,cgbase,aasm,node;
+      cclasses,globtype,cginfo,cgbase,aasm,node;
 
 
     type
     type
        regvar_longintarray = array[firstreg..lastreg] of longint;
        regvar_longintarray = array[firstreg..lastreg] of longint;
@@ -97,18 +97,12 @@ unit rgobj;
           { deallocate any kind of register }
           { deallocate any kind of register }
           procedure ungetregister(list: taasmoutput; r : tregister); virtual;
           procedure ungetregister(list: taasmoutput; r : tregister); virtual;
 
 
+          { deallocate any kind of register }
+          procedure ungetreference(list: taasmoutput; const ref : treference); virtual;
+
           { reset the register allocator information (usable registers etc) }
           { reset the register allocator information (usable registers etc) }
           procedure cleartempgen;virtual;
           procedure cleartempgen;virtual;
 
 
-          { deallocate the registers of a reference }
-          procedure del_reference(list: taasmoutput; const ref : treference);virtual;
-
-          { deallocate the registers of a location if it's a reference }
-          procedure del_locref(list: taasmoutput; const location : tlocation);
-
-          { deallocate the registers of a location }
-          procedure del_location(list: taasmoutput; const l : tlocation);
-
           { saves register variables (restoring happens automatically) }
           { saves register variables (restoring happens automatically) }
           procedure saveregvars(list: taasmoutput; const s: tregisterset);
           procedure saveregvars(list: taasmoutput; const s: tregisterset);
 
 
@@ -154,6 +148,19 @@ unit rgobj;
      var
      var
        rg: trgobj;
        rg: trgobj;
 
 
+     { trerefence handling }
+     procedure reference_reset(var ref : treference);
+     procedure reference_reset_base(var ref : treference;base : tregister;offset : longint);
+     procedure reference_reset_symbol(var ref : treference;sym : tasmsymbol;offset : longint);
+     procedure reference_release(list: taasmoutput; const ref : treference);
+
+     { tlocation handling }
+     procedure location_reset(var l : tlocation;lt:TLoc;lsize:TCGSize);
+     procedure location_release(list: taasmoutput; const l : tlocation);
+     procedure location_freetemp(list: taasmoutput; const l : tlocation);
+     procedure location_copy(var destloc,sourceloc : tlocation);
+     procedure location_swap(var destloc,sourceloc : tlocation);
+
 
 
   implementation
   implementation
 
 
@@ -390,7 +397,7 @@ unit rgobj;
       end;
       end;
 
 
 
 
-    procedure trgobj.del_reference(list : taasmoutput; const ref : treference);
+    procedure trgobj.ungetreference(list : taasmoutput; const ref : treference);
 
 
       begin
       begin
          ungetregister(list,ref.base);
          ungetregister(list,ref.base);
@@ -398,27 +405,6 @@ unit rgobj;
       end;
       end;
 
 
 
 
-    procedure trgobj.del_locref(list : taasmoutput; const location : tlocation);
-
-      begin
-         if (location.loc<>LOC_MEM) and (location.loc<>LOC_REFERENCE) then
-           exit;
-         del_reference(list,location.reference);
-      end;
-
-
-    procedure trgobj.del_location(list : taasmoutput; const l : tlocation);
-
-      begin
-         case l.loc of
-           LOC_REGISTER :
-             ungetregister(list,l.register);
-           LOC_MEM,LOC_REFERENCE :
-             del_reference(list,l.reference);
-         end;
-      end;
-
-
     procedure trgobj.saveregvars(list: taasmoutput; const s: tregisterset);
     procedure trgobj.saveregvars(list: taasmoutput; const s: tregisterset);
       var
       var
         r: tregister;
         r: tregister;
@@ -534,9 +520,7 @@ unit rgobj;
             begin
             begin
               if saved[r].ofs <> reg_not_saved then
               if saved[r].ofs <> reg_not_saved then
                 begin
                 begin
-                  reset_reference(hr);
-                  hr.base:=frame_pointer;
-                  hr.offset:=saved[r].ofs;
+                  reference_reset_base(hr,frame_pointer,saved[r].ofs);
                   cg.a_reg_alloc(list,r);
                   cg.a_reg_alloc(list,r);
                   cg.a_loadmm_ref_reg(list,hr,r);
                   cg.a_loadmm_ref_reg(list,hr,r);
                   if not (r in unusedregsmm) then
                   if not (r in unusedregsmm) then
@@ -558,9 +542,7 @@ unit rgobj;
             begin
             begin
               if saved[r].ofs <> reg_not_saved then
               if saved[r].ofs <> reg_not_saved then
                 begin
                 begin
-                  reset_reference(hr);
-                  hr.base:=frame_pointer;
-                  hr.offset:=saved[r].ofs;
+                  reference_reset_base(hr,frame_pointer,saved[r].ofs);
                   cg.a_reg_alloc(list,r);
                   cg.a_reg_alloc(list,r);
                   cg.a_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
                   cg.a_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
                   if not (r in unusedregsfpu) then
                   if not (r in unusedregsfpu) then
@@ -581,9 +563,7 @@ unit rgobj;
           begin
           begin
             if saved[r].ofs <> reg_not_saved then
             if saved[r].ofs <> reg_not_saved then
               begin
               begin
-                reset_reference(hr);
-                hr.base:=frame_pointer;
-                hr.offset:=saved[r].ofs;
+                reference_reset_base(hr,frame_pointer,saved[r].ofs);
                 cg.a_reg_alloc(list,r);
                 cg.a_reg_alloc(list,r);
                 cg.a_load_ref_reg(list,OS_INT,hr,r);
                 cg.a_load_ref_reg(list,OS_INT,hr,r);
                 if not (r in unusedregsint) then
                 if not (r in unusedregsint) then
@@ -773,13 +753,107 @@ unit rgobj;
         state := nil;
         state := nil;
       end;
       end;
 
 
+
+{****************************************************************************
+                                  TReference
+****************************************************************************}
+
+    procedure reference_reset(var ref : treference);
+      begin
+        FillChar(ref,sizeof(treference),0);
+      end;
+
+
+    procedure reference_reset_base(var ref : treference;base : tregister;offset : longint);
+      begin
+        FillChar(ref,sizeof(treference),0);
+        ref.base:=base;
+        ref.offset:=offset;
+      end;
+
+
+    procedure reference_reset_symbol(var ref : treference;sym : tasmsymbol;offset : longint);
+      begin
+        FillChar(ref,sizeof(treference),0);
+        ref.symbol:=sym;
+        ref.offset:=offset;
+      end;
+
+
+    procedure reference_release(list: taasmoutput; const ref : treference);
+      begin
+        rg.ungetreference(list,ref);
+      end;
+
+
+{****************************************************************************
+                                  TLocation
+****************************************************************************}
+
+    procedure location_reset(var l : tlocation;lt:TLoc;lsize:TCGSize);
+      begin
+        FillChar(l,sizeof(tlocation),0);
+        l.loc:=lt;
+        l.size:=lsize;
+      end;
+
+
+    procedure location_release(list: taasmoutput; const l : tlocation);
+      begin
+        case l.loc of
+          LOC_REGISTER,LOC_CREGISTER :
+            begin
+              rg.ungetregisterint(list,l.register);
+              if l.size in [OS_64,OS_S64] then
+               rg.ungetregisterint(list,l.registerhigh);
+            end;
+          LOC_CREFERENCE,LOC_REFERENCE :
+            rg.ungetreference(list, l.reference);
+        end;
+      end;
+
+
+    procedure location_freetemp(list:taasmoutput; const l : tlocation);
+      begin
+        if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+         tg.ungetiftemp(list,l.reference);
+      end;
+
+
+    procedure location_copy(var destloc,sourceloc : tlocation);
+      begin
+        destloc:=sourceloc;
+      end;
+
+
+    procedure location_swap(var destloc,sourceloc : tlocation);
+      var
+        swapl : tlocation;
+      begin
+        swapl := destloc;
+        destloc := sourceloc;
+        sourceloc := swapl;
+      end;
+
+
 finalization
 finalization
   rg.free;
   rg.free;
 end.
 end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.2  2002-04-01 19:24:25  jonas
+  Revision 1.3  2002-04-02 17:11:29  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.2  2002/04/01 19:24:25  jonas
     * fixed different parameter name in interface and implementation
     * fixed different parameter name in interface and implementation
       declaration of a method (only 1.0.x detected this)
       declaration of a method (only 1.0.x detected this)
 
 

+ 18 - 8
compiler/symdef.pas

@@ -1753,10 +1753,9 @@ implementation
         u64bit    : stabstring := strpnew('-32;');
         u64bit    : stabstring := strpnew('-32;');
         s64bit    : stabstring := strpnew('-31;');
         s64bit    : stabstring := strpnew('-31;');
 {$endif not Use_integer_types_for_boolean}
 {$endif not Use_integer_types_for_boolean}
-         { u32bit : stabstring := strpnew('r'+
-              s32bittype^.numberstring+';0;-1;'); }
+         {u32bit : stabstring := tstoreddef(s32bittype.def).numberstring+';0;-1;'); }
         else
         else
-          stabstring := strpnew('r'+tstoreddef(s32bittype.def).numberstring+';'+tostr(low)+';'+tostr(high)+';');
+          stabstring := strpnew('r'+tstoreddef(s32bittype.def).numberstring+';'+tostr(longint(low))+';'+tostr(longint(high))+';');
         end;
         end;
       end;
       end;
 {$endif GDB}
 {$endif GDB}
@@ -1775,8 +1774,8 @@ implementation
         begin
         begin
           write_rtti_name;
           write_rtti_name;
           rttiList.concat(Tai_const.Create_8bit(byte(trans[typ])));
           rttiList.concat(Tai_const.Create_8bit(byte(trans[typ])));
-          rttiList.concat(Tai_const.Create_32bit(low));
-          rttiList.concat(Tai_const.Create_32bit(high));
+          rttiList.concat(Tai_const.Create_32bit(longint(low)));
+          rttiList.concat(Tai_const.Create_32bit(longint(high)));
         end;
         end;
 
 
       begin
       begin
@@ -2643,7 +2642,7 @@ implementation
         cachedsize := elesize;
         cachedsize := elesize;
         If (cachedsize>0) and
         If (cachedsize>0) and
            (
            (
-            (TConstExprInt(highrange)-TConstExprInt(lowrange) >= $7fffffff) or
+            (TConstExprInt(highrange)-TConstExprInt(lowrange) > $7fffffff) or
             { () are needed around elesize-1 to avoid a possible
             { () are needed around elesize-1 to avoid a possible
               integer overflow for elesize=1 !! PM }
               integer overflow for elesize=1 !! PM }
             (($7fffffff div cachedsize + (cachedsize -1)) < (int64(highrange) - int64(lowrange)))
             (($7fffffff div cachedsize + (cachedsize -1)) < (int64(highrange) - int64(lowrange)))
@@ -2652,7 +2651,7 @@ implementation
             Message(sym_e_segment_too_large);
             Message(sym_e_segment_too_large);
             size := 4
             size := 4
           End
           End
-        Else size:=(highrange-lowrange+1)*cachedsize;
+        Else size:=longint((highrange-lowrange+1)*cachedsize);
       end;
       end;
 
 
 
 
@@ -5420,7 +5419,18 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.67  2002-03-31 20:26:36  jonas
+  Revision 1.68  2002-04-02 17:11:29  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.67  2002/03/31 20:26:36  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 35 - 33
compiler/tainst.pas

@@ -49,9 +49,9 @@ Type
     Constructor Create(op : tasmop);
     Constructor Create(op : tasmop);
     Destructor Destroy;override;
     Destructor Destroy;override;
     function getcopy:tlinkedlistitem;override;
     function getcopy:tlinkedlistitem;override;
-    procedure loadconst(opidx:longint;l:longint);
+    procedure loadconst(opidx:longint;l:aword);
     procedure loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
     procedure loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
-    procedure loadref(opidx:longint;p:preference);
+    procedure loadref(opidx:longint;const r:treference);
     procedure loadreg(opidx:longint;r:tregister);
     procedure loadreg(opidx:longint;r:tregister);
     procedure loadoper(opidx:longint;o:toper);
     procedure loadoper(opidx:longint;o:toper);
     procedure SetCondition(const c:TAsmCond);
     procedure SetCondition(const c:TAsmCond);
@@ -123,14 +123,14 @@ implementation
 
 
 
 
 
 
-    procedure tainstruction.loadconst(opidx:longint;l:longint);
+    procedure tainstruction.loadconst(opidx:longint;l:aword);
       begin
       begin
         if opidx>=ops then
         if opidx>=ops then
          ops:=opidx+1;
          ops:=opidx+1;
         with oper[opidx] do
         with oper[opidx] do
          begin
          begin
            if typ=top_ref then
            if typ=top_ref then
-            disposereference(ref);
+            dispose(ref);
            val:=l;
            val:=l;
            typ:=top_const;
            typ:=top_const;
          end;
          end;
@@ -145,7 +145,7 @@ implementation
         with oper[opidx] do
         with oper[opidx] do
          begin
          begin
            if typ=top_ref then
            if typ=top_ref then
-            disposereference(ref);
+            dispose(ref);
            sym:=s;
            sym:=s;
            symofs:=sofs;
            symofs:=sofs;
            typ:=top_symbol;
            typ:=top_symbol;
@@ -157,37 +157,25 @@ implementation
 
 
 
 
 
 
-    procedure tainstruction.loadref(opidx:longint;p:preference);
+    procedure tainstruction.loadref(opidx:longint;const r:treference);
       begin
       begin
         if opidx>=ops then
         if opidx>=ops then
          ops:=opidx+1;
          ops:=opidx+1;
         with oper[opidx] do
         with oper[opidx] do
          begin
          begin
-           if typ=top_ref then
-            disposereference(ref);
-           if p^.is_immediate then
-             begin
-{$ifdef REF_IMMEDIATE_WARN}
-               Comment(V_Warning,'Reference immediate');
-{$endif}
-               val:=p^.offset;
-               disposereference(p);
-               typ:=top_const;
-             end
-           else
-             begin
-               ref:=p;
-      { We allow this exception for i386, since overloading this would be
-        too much of a a speed penalty}
+           if typ<>top_ref then
+            new(ref);
+           ref^:=r;
 {$ifdef i386}
 {$ifdef i386}
-               if not(ref^.segment in [R_DS,R_NO]) then
-                 segprefix:=ref^.segment;
+           { We allow this exception for i386, since overloading this would be
+             too much of a a speed penalty}
+           if not(ref^.segment in [R_DS,R_NO]) then
+            segprefix:=ref^.segment;
 {$endif}
 {$endif}
-               typ:=top_ref;
-               { mark symbol as used }
-               if assigned(ref^.symbol) then
-                 inc(ref^.symbol.refs);
-             end;
+           typ:=top_ref;
+           { mark symbol as used }
+           if assigned(ref^.symbol) then
+             inc(ref^.symbol.refs);
          end;
          end;
       end;
       end;
 
 
@@ -200,7 +188,7 @@ implementation
         with oper[opidx] do
         with oper[opidx] do
          begin
          begin
            if typ=top_ref then
            if typ=top_ref then
-            disposereference(ref);
+            dispose(ref);
            reg:=r;
            reg:=r;
            typ:=top_reg;
            typ:=top_reg;
          end;
          end;
@@ -213,11 +201,14 @@ implementation
         if opidx>=ops then
         if opidx>=ops then
          ops:=opidx+1;
          ops:=opidx+1;
         if oper[opidx].typ=top_ref then
         if oper[opidx].typ=top_ref then
-          disposereference(oper[opidx].ref);
+         dispose(oper[opidx].ref);
         oper[opidx]:=o;
         oper[opidx]:=o;
         { copy also the reference }
         { copy also the reference }
         if oper[opidx].typ=top_ref then
         if oper[opidx].typ=top_ref then
-         oper[opidx].ref:=newreference(o.ref^);
+         begin
+           new(oper[opidx].ref);
+           oper[opidx].ref^:=o.ref^;
+         end;
       end;
       end;
 
 
 
 
@@ -251,7 +242,18 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.3  2001-12-29 16:29:08  jonas
+  Revision 1.4  2002-04-02 17:11:32  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.3  2001/12/29 16:29:08  jonas
     * fixed stupid copy-paste bug
     * fixed stupid copy-paste bug
 
 
   Revision 1.2  2001/12/29 15:28:57  jonas
   Revision 1.2  2001/12/29 15:28:57  jonas

+ 21 - 12
compiler/targets/t_win32.pas

@@ -43,7 +43,7 @@ implementation
 {$ifdef GDB}
 {$ifdef GDB}
        gdb,
        gdb,
 {$endif}
 {$endif}
-       import,export,link;
+       import,export,link,rgobj;
 
 
   type
   type
     timportlibwin32=class(timportlib)
     timportlibwin32=class(timportlib)
@@ -207,12 +207,14 @@ implementation
     procedure timportlibwin32.generatesmartlib;
     procedure timportlibwin32.generatesmartlib;
       var
       var
          hp1 : timportlist;
          hp1 : timportlist;
+{$ifdef GDB}
          importname : string;
          importname : string;
          suffix : integer;
          suffix : integer;
+{$endif GDB}
          hp2 : timported_item;
          hp2 : timported_item;
          lhead,lname,lcode,
          lhead,lname,lcode,
          lidata4,lidata5 : tasmlabel;
          lidata4,lidata5 : tasmlabel;
-         r : preference;
+         href : treference;
       begin
       begin
          if (aktoutputformat<>as_i386_asw) and
          if (aktoutputformat<>as_i386_asw) and
             (aktoutputformat<>as_i386_pecoff) then
             (aktoutputformat<>as_i386_pecoff) then
@@ -260,9 +262,7 @@ implementation
                  if not hp2.is_var then
                  if not hp2.is_var then
                   begin
                   begin
                     getlabel(lcode);
                     getlabel(lcode);
-                    new(r);
-                    reset_reference(r^);
-                    r^.symbol:=lcode;
+                    reference_reset_symbol(href,lcode,0);
                     { place jump in codesegment, insert a code section in the
                     { place jump in codesegment, insert a code section in the
                       importsection to reduce the amount of .s files (PFV) }
                       importsection to reduce the amount of .s files (PFV) }
                     importsSection.concat(Tai_section.Create(sec_code));
                     importsSection.concat(Tai_section.Create(sec_code));
@@ -271,7 +271,7 @@ implementation
                      importsSection.concat(Tai_stab_function_name.Create(nil));
                      importsSection.concat(Tai_stab_function_name.Create(nil));
 {$EndIf GDB}
 {$EndIf GDB}
                     importsSection.concat(Tai_symbol.Createname_global(hp2.func^,0));
                     importsSection.concat(Tai_symbol.Createname_global(hp2.func^,0));
-                    importsSection.concat(Taicpu.Op_ref(A_JMP,S_NO,r));
+                    importsSection.concat(Taicpu.Op_ref(A_JMP,S_NO,href));
                     importsSection.concat(Tai_align.Create_op(4,$90));
                     importsSection.concat(Tai_align.Create_op(4,$90));
                   end;
                   end;
                  { create head link }
                  { create head link }
@@ -352,7 +352,7 @@ implementation
          l1,l2,l3,l4 : tasmlabel;
          l1,l2,l3,l4 : tasmlabel;
          importname : string;
          importname : string;
          suffix : integer;
          suffix : integer;
-         r : preference;
+         href : treference;
       begin
       begin
          if (aktoutputformat<>as_i386_asw) and
          if (aktoutputformat<>as_i386_asw) and
             (aktoutputformat<>as_i386_pecoff) then
             (aktoutputformat<>as_i386_pecoff) then
@@ -411,13 +411,11 @@ implementation
                     begin
                     begin
                       getlabel(l4);
                       getlabel(l4);
                       { create indirect jump }
                       { create indirect jump }
-                      new(r);
-                      reset_reference(r^);
-                      r^.symbol:=l4;
+                      reference_reset_symbol(href,l4,0);
                       { place jump in codesegment }
                       { place jump in codesegment }
                       importsSection.concat(Tai_section.Create(sec_code));
                       importsSection.concat(Tai_section.Create(sec_code));
                       importsSection.concat(Tai_symbol.Createname_global(hp2.func^,0));
                       importsSection.concat(Tai_symbol.Createname_global(hp2.func^,0));
-                      importsSection.concat(Taicpu.Op_ref(A_JMP,S_NO,r));
+                      importsSection.concat(Taicpu.Op_ref(A_JMP,S_NO,href));
                       importsSection.concat(Tai_align.Create_op(4,$90));
                       importsSection.concat(Tai_align.Create_op(4,$90));
                       { add jump field to importsection }
                       { add jump field to importsection }
                       importsSection.concat(Tai_section.Create(sec_idata5));
                       importsSection.concat(Tai_section.Create(sec_idata5));
@@ -1606,7 +1604,18 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.23  2002-01-29 21:27:34  peter
+  Revision 1.24  2002-04-02 17:11:39  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.23  2002/01/29 21:27:34  peter
     * default alignment changed to 4 bytes for locals and static const,var
     * default alignment changed to 4 bytes for locals and static const,var
 
 
   Revision 1.22  2002/01/19 11:53:07  peter
   Revision 1.22  2002/01/19 11:53:07  peter

+ 16 - 5
compiler/tgobj.pas

@@ -340,7 +340,7 @@ unit tgobj;
     procedure ttgobj.gettempofsizereference(list: taasmoutput; l : longint;var ref : treference);
     procedure ttgobj.gettempofsizereference(list: taasmoutput; l : longint;var ref : treference);
       begin
       begin
          { do a reset, because the reference isn't used }
          { do a reset, because the reference isn't used }
-         reset_reference(ref);
+         FillChar(ref,sizeof(treference),0);
          ref.offset:=gettempofsize(list,l);
          ref.offset:=gettempofsize(list,l);
          ref.base:=procinfo^.framepointer;
          ref.base:=procinfo^.framepointer;
       end;
       end;
@@ -348,7 +348,7 @@ unit tgobj;
     procedure ttgobj.gettempofsizereferencepersistant(list: taasmoutput; l : longint;var ref : treference);
     procedure ttgobj.gettempofsizereferencepersistant(list: taasmoutput; l : longint;var ref : treference);
       begin
       begin
          { do a reset, because the reference isn't used }
          { do a reset, because the reference isn't used }
-         reset_reference(ref);
+         FillChar(ref,sizeof(treference),0);
          ref.offset:=gettempofsizepersistant(list,l);
          ref.offset:=gettempofsizepersistant(list,l);
          ref.base:=procinfo^.framepointer;
          ref.base:=procinfo^.framepointer;
       end;
       end;
@@ -359,7 +359,7 @@ unit tgobj;
          foundslot,tl : ptemprecord;
          foundslot,tl : ptemprecord;
       begin
       begin
          { do a reset, because the reference isn't used }
          { do a reset, because the reference isn't used }
-         reset_reference(ref);
+         FillChar(ref,sizeof(treference),0);
          ref.base:=procinfo^.framepointer;
          ref.base:=procinfo^.framepointer;
          { Reuse old slot ? }
          { Reuse old slot ? }
          foundslot:=nil;
          foundslot:=nil;
@@ -642,7 +642,18 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.1  2002-03-31 20:26:37  jonas
+  Revision 1.2  2002-04-02 17:11:32  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.1  2002/03/31 20:26:37  jonas
     + a_loadfpu_* and a_loadmm_* methods in tcg
     + a_loadfpu_* and a_loadmm_* methods in tcg
     * register allocation is now handled by a class and is mostly processor
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
       independent (+rgobj.pas and i386/rgcpu.pas)
@@ -693,4 +704,4 @@ end.
   Revision 1.1  1999/08/02 17:14:12  florian
   Revision 1.1  1999/08/02 17:14:12  florian
     + changed the temp. generator to an object
     + changed the temp. generator to an object
 
 
-}
+}

+ 14 - 3
compiler/types.pas

@@ -48,7 +48,7 @@ interface
     function is_ordinal(def : tdef) : boolean;
     function is_ordinal(def : tdef) : boolean;
 
 
     { returns the min. value of the type }
     { returns the min. value of the type }
-    function get_min_value(def : tdef) : longint;
+    function get_min_value(def : tdef) : TConstExprInt;
 
 
     { returns basetype of the specified range }
     { returns basetype of the specified range }
     function range_to_basetype(low,high:TConstExprInt):tbasetype;
     function range_to_basetype(low,high:TConstExprInt):tbasetype;
@@ -560,7 +560,7 @@ implementation
 
 
 
 
     { returns the min. value of the type }
     { returns the min. value of the type }
-    function get_min_value(def : tdef) : longint;
+    function get_min_value(def : tdef) : TConstExprInt;
       begin
       begin
          case def.deftype of
          case def.deftype of
            orddef:
            orddef:
@@ -1955,7 +1955,18 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.65  2002-04-01 20:57:14  jonas
+  Revision 1.66  2002-04-02 17:11:32  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.65  2002/04/01 20:57:14  jonas
     * fixed web bug 1907
     * fixed web bug 1907
     * fixed some other procvar related bugs (all related to accepting procvar
     * fixed some other procvar related bugs (all related to accepting procvar
         constructs with either too many or too little parameters)
         constructs with either too many or too little parameters)

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini