Преглед изворни кода

* 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 година
родитељ
комит
5b242f7741
60 измењених фајлова са 5103 додато и 5023 уклоњено
  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;
                          top_symbol :
                            begin
-                             if sym=nil then
-                              sym:=sym;
                              UsedAsmSymbolListInsert(sym);
                            end;
                        end;
@@ -1553,7 +1551,18 @@ Implementation
 end.
 {
   $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
 
   Revision 1.28  2001/09/18 11:30:47  michael

+ 229 - 7
compiler/cg64f32.pas

@@ -30,18 +30,41 @@ unit cg64f32;
   interface
 
     uses
-       aasm, cgobj, cpubase,node,symtype;
+       aasm,
+       cpuinfo, cpubase,
+       cginfo, cgobj,
+       node,symtype;
 
     type
       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_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_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_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_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
         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_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 }
         procedure g_rangecheck(list: taasmoutput; const p: tnode;
@@ -60,8 +83,7 @@ unit cg64f32;
        globtype,globals,systems,
        cgbase,
        verbose,
-       symbase,symconst,symdef,types,
-       cpuinfo;
+       symbase,symconst,symdef,types;
 
     procedure tcg64f32.a_load64_reg_ref(list : taasmoutput;reglo, reghi : tregister;const ref : treference);
       var
@@ -80,10 +102,29 @@ unit cg64f32;
         a_load_reg_ref(list,OS_32,reghi,tmpref);
       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);
       var
         tmpreg: tregister;
         tmpref: treference;
+        got_scratch: boolean;
       begin
         if target_info.endian = endian_big then
           begin
@@ -91,12 +132,31 @@ unit cg64f32;
             reglo := reghi;
             reghi := tmpreg;
           end;
-        a_load_ref_reg(list,OS_32,ref,reglo);
+        got_scratch:=false;
         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);
         a_load_ref_reg(list,OS_32,tmpref,reghi);
+        if got_scratch then
+         free_scratch_reg(list,tmpreg);
       end;
 
+
     procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;reglosrc,reghisrc,reglodst,reghidst : tregister);
 
       begin
@@ -104,21 +164,57 @@ unit cg64f32;
         a_load_reg_reg(list,OS_32,reghisrc,reghidst);
       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);
 
       begin
         case l.loc of
-          LOC_REFERENCE, LOC_MEM:
+          LOC_REFERENCE, LOC_CREFERENCE:
             a_load64_ref_reg(list,l.reference,reglo,reghi);
           LOC_REGISTER,LOC_CREGISTER:
             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
             internalerror(200112292);
         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);
       var
         tmpref: treference;
@@ -175,6 +271,121 @@ unit cg64f32;
           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;
         const todef: tdef);
@@ -358,7 +569,18 @@ begin
 end.
 {
   $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
 
   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
     * some new stuff for the new cg
 
-}
+}

+ 64 - 58
compiler/cgbase.pas

@@ -34,31 +34,24 @@ unit cgbase;
       { symtable }
       symconst,symtype,symdef,symsym,
       { 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_is_global = $2;       { set, if the procedure is exported by an unit }
        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 }
                                         { 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
        pprocinfo = ^tprocinfo;
        tprocinfo = object
@@ -211,7 +169,7 @@ unit cgbase;
     procedure codegen_newmodule;
     procedure codegen_newprocedure;
 
-
+    function def_cgsize_ref(const p1: tdef): tcgsize;
     function def_cgsize(const p1: tdef): tcgsize;
     function int_cgsize(const l: aword): tcgsize;
 
@@ -471,19 +429,56 @@ implementation
          ResourceStrings.free;
       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;
 
       begin
         case p1.deftype of
-          orddef, enumdef, setdef:
+          orddef,
+          enumdef,
+          setdef:
             begin
               result := int_cgsize(p1.size);
               if is_signed(p1) then
                 result := tcgsize(ord(result)+(ord(OS_S8)-ord(OS_8)));
             end;
-          pointerdef, procvardef:
+          classrefdef,
+          pointerdef,
+          procvardef:
             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:
             result := tfloat2tcgsize[tfloatdef(p1).typ];
           else
@@ -517,7 +512,7 @@ implementation
     function commutativeop(op: topcg): boolean;
       const
         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);
       begin
         commutativeop := list[op];
@@ -547,7 +542,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 119 - 27
compiler/cgobj.pas

@@ -28,7 +28,9 @@ unit cgobj;
   interface
 
     uses
-       cclasses,aasm,symtable,cpuasm,cpubase,cgbase,cpuinfo,
+       cclasses,aasm,symtable,
+       cpuasm,cpubase,cpuinfo,
+       cginfo,
        symconst,symbase,symtype,node;
 
     type
@@ -96,6 +98,7 @@ unit cgobj;
           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_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;
 
           {**********************************}
@@ -124,9 +127,11 @@ unit cgobj;
           { move instructions }
           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_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_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_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_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;
@@ -174,6 +179,7 @@ unit cgobj;
             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_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;
             l : tasmlabel);
 
@@ -182,7 +188,7 @@ unit cgobj;
 
           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;
           { restores the frame pointer at procedure exit, for the }
           { i386 it generates a simple leave                      }
@@ -235,7 +241,7 @@ unit cgobj;
   implementation
 
     uses
-       strings,globals,globtype,options,gdb,systems,
+       strings,globals,globtype,options,gdb,systems,cgbase,
        ppu,verbose,types,tgobj,symdef,symsym,cga,tainst,rgobj;
 
     const
@@ -357,6 +363,25 @@ unit cgobj;
          free_scratch_reg(list,hr);
       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);
 
       var
@@ -364,11 +389,12 @@ unit cgobj;
 
       begin
          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);
          free_scratch_reg(list,hr);
       end;
 
+
     procedure tcg.g_stackcheck(list : taasmoutput;stackframesize : longint);
 
       begin
@@ -1077,15 +1103,44 @@ unit cgobj;
 
       begin
         case loc.loc of
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             a_load_ref_reg(list,size,loc.reference,reg);
           LOC_REGISTER,LOC_CREGISTER:
             a_load_reg_reg(list,size,loc.register,reg);
+          LOC_CONSTANT:
+            a_load_const_reg(list,size,loc.value,reg);
           else
             internalerror(200109092);
         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);
 
       var
@@ -1093,7 +1148,7 @@ unit cgobj;
 
       begin
         case loc.loc of
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             begin
 {$ifdef i386}
               case size of
@@ -1118,6 +1173,8 @@ unit cgobj;
             end;
           LOC_REGISTER,LOC_CREGISTER:
             a_load_reg_ref(list,size,loc.register,ref);
+          LOC_CONSTANT:
+            a_load_const_ref(list,size,loc.value,ref);
           else
             internalerror(200109302);
         end;
@@ -1128,9 +1185,9 @@ unit cgobj;
 
       begin
         case loc.loc of
-          LOC_REFERENCE, LOC_MEM:
+          LOC_REFERENCE, LOC_CREFERENCE:
             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);
           else
             internalerror(200203301);
@@ -1142,9 +1199,9 @@ unit cgobj;
 
       begin
         case loc.loc of
-          LOC_REFERENCE, LOC_MEM:
+          LOC_REFERENCE, LOC_CREFERENCE:
             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);
           else
             internalerror(48991);
@@ -1172,7 +1229,7 @@ unit cgobj;
         case loc.loc of
           LOC_REGISTER, LOC_CREGISTER:
             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);
           else
             internalerror(200109061);
@@ -1224,7 +1281,7 @@ unit cgobj;
         case loc.loc of
           LOC_REGISTER, LOC_CREGISTER:
             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);
           else
             internalerror(200109061);
@@ -1241,7 +1298,7 @@ unit cgobj;
         case loc.loc of
           LOC_REGISTER,LOC_CREGISTER:
             a_op_ref_reg(list,op,size,ref,loc.register);
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             begin
               tmpreg := get_scratch_reg(list);
 {$ifdef i386}
@@ -1292,7 +1349,7 @@ unit cgobj;
         case loc.loc of
           LOC_REGISTER,LOC_CREGISTER:
             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);
           else
             internalerror(200109061);
@@ -1311,6 +1368,23 @@ unit cgobj;
         free_scratch_reg(list,tmpreg);
       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;
       l : tasmlabel);
 
@@ -1321,7 +1395,7 @@ unit cgobj;
         case loc.loc of
           LOC_REGISTER,LOC_CREGISTER:
             a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
-          LOC_REFERENCE,LOC_MEM:
+          LOC_REFERENCE,LOC_CREFERENCE:
             begin
 {$ifdef i386}
               { 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) }
     { is the original type used at that location. When both defs are equal   }
     { 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
         neglabel : tasmlabel;
         hreg : tregister;
@@ -1415,7 +1495,7 @@ unit cgobj;
               { if high(from) < 0 -> always range error }
               if (hfrom < 0) or
                  { if low(to) > maxlongint also range error }
-                 (lto > (high(aword) div 2)) then
+                 (lto > awordsignedmax) then
                 begin
                   a_call_name(list,'FPC_RANGEERROR',0);
                   exit
@@ -1423,13 +1503,13 @@ unit cgobj;
               { from is signed and to is unsigned -> when looking at from }
               { as an unsigned value, it must be < maxlongint (otherwise  }
               { 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
           else
             { from is unsigned, to is signed }
             begin
-              if (lfrom > (high(aword) div 2)) or
+              if (lfrom > awordsignedmax) or
                  (hto < 0) then
                 begin
                   a_call_name(list,'FPC_RANGEERROR',0);
@@ -1445,15 +1525,15 @@ unit cgobj;
         hreg := get_scratch_reg(list);
         if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
           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
           begin
             a_load_ref_reg(list,def_cgsize(p.resulttype.def),
               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;
         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) }
         free_scratch_reg(list,hreg);
         a_call_name(list,'FPC_RANGEERROR',0);
@@ -1473,7 +1553,18 @@ finalization
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
@@ -1494,9 +1585,10 @@ end.
     * removed compiler warnings
 
   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)
     * getregister32 is now called getregisterint
 

+ 15 - 7
compiler/cutils.pas

@@ -26,9 +26,6 @@ unit cutils;
 
 interface
 
-uses
-  cpuinfo;
-
 {$ifdef delphi}
     type
        dword = cardinal;
@@ -60,7 +57,7 @@ uses
     function tostr_with_plus(i : longint) : string;
     procedure valint(S : string;var V : longint;var code : integer);
     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 CompareText(S1, S2: string): longint;
 
@@ -482,12 +479,12 @@ uses
       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
     }
       var
-         hl : TConstExprInt;
+         hl : int64;
          i : longint;
       begin
          if value and (value - 1) <> 0 then
@@ -750,7 +747,18 @@ initialization
 end.
 {
   $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
     * fixed parsing of classes with private and virtual and overloaded
       so it is compatible with delphi

+ 14 - 3
compiler/globals.pas

@@ -1443,8 +1443,8 @@ implementation
         not_unit_proc:=true;
 
         apptype:=app_cui;
-	
-	have_local_threadvars := false;
+
+        have_local_threadvars := false;
      end;
 
 {$ifdef EXTDEBUG}
@@ -1456,7 +1456,18 @@ begin
 end.
 {
   $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
 
   Revision 1.51  2002/01/24 18:25:48  peter

+ 15 - 4
compiler/htypechk.pas

@@ -420,7 +420,7 @@ implementation
                 internalerror(200110101);
 
               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 <> 0) or (p.left.registersfpu <> 0)) and
                   (p.left.registers32   < p.right.registers32)) then
@@ -440,8 +440,8 @@ implementation
               if (p.left.registers32=p.right.registers32) and
                  (p.registers32=p.left.registers32) 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);
             end
            else
@@ -938,7 +938,18 @@ implementation
 end.
 {
   $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
       deref), reported by John Lee
 

+ 57 - 54
compiler/i386/ag386att.pas

@@ -132,60 +132,52 @@ interface
     var
       s : string;
     begin
-      if ref.is_immediate then
+      with ref do
        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
-            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
-             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;
       getreferencestring:=s;
     end;
@@ -200,7 +192,7 @@ interface
         top_ref :
           getopstr:=getreferencestring(o.ref^);
         top_const :
-          getopstr:='$'+tostr(o.val);
+          getopstr:='$'+tostr(longint(o.val));
         top_symbol :
           begin
             if assigned(o.sym) then
@@ -232,7 +224,7 @@ interface
         top_ref :
           getopstr_jmp:='*'+getreferencestring(o.ref^);
         top_const :
-          getopstr_jmp:=tostr(o.val);
+          getopstr_jmp:=tostr(longint(o.val));
         top_symbol :
           begin
             hs:=o.sym.name;
@@ -949,7 +941,18 @@ initialization
 end.
 {
   $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 :)
     * several powerpc-related fixes
     * cpuasm unit is now based on common tainst unit

+ 14 - 9
compiler/i386/ag386int.pas

@@ -119,12 +119,6 @@ interface
       s     : string;
       first : boolean;
     begin
-      if ref.is_immediate then
-       begin
-         getreferencestring:=tostr(ref.offset);
-         exit;
-       end
-      else
       with ref do
         begin
           first:=true;
@@ -179,7 +173,7 @@ interface
         top_reg :
           getopstr:=int_reg2str[o.reg];
         top_const :
-          getopstr:=tostr(o.val);
+          getopstr:=tostr(longint(o.val));
         top_symbol :
           begin
             if assigned(o.sym) then
@@ -242,7 +236,7 @@ interface
         top_reg :
           getopstr_jmp:=int_reg2str[o.reg];
         top_const :
-          getopstr_jmp:=tostr(o.val);
+          getopstr_jmp:=tostr(longint(o.val));
         top_symbol :
           begin
             hs:=o.sym.name;
@@ -828,7 +822,18 @@ initialization
 end.
 {
   $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)
     * masm fixes (merged)
     * quoted filenames for go32v2 and win32

+ 15 - 10
compiler/i386/ag386nsm.pas

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

Разлика између датотеке није приказан због своје велике величине
+ 128 - 390
compiler/i386/cga.pas


+ 238 - 99
compiler/i386/cgcpu.pas

@@ -27,7 +27,7 @@ unit cgcpu;
   interface
 
     uses
-       cgbase,cgobj,cg64f32,aasm,cpuasm,cpubase,cpuinfo,symconst;
+       cginfo,cgbase,cgobj,cg64f32,aasm,cpuasm,cpubase,cpuinfo,symconst;
 
     type
       tcg386 = class(tcg64f32)
@@ -97,7 +97,12 @@ unit cgcpu;
         procedure g_pop_exception_value_reg(list : taasmoutput;reg : tregister);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;
 
@@ -107,6 +112,7 @@ unit cgcpu;
 
        private
 
+        procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
         procedure sizes2load(s1: tcgsize; s2: topsize; var op: tasmop; var s3: topsize);
 
         procedure floatload(list: taasmoutput; t : tcgsize;const ref : treference);
@@ -118,12 +124,12 @@ unit cgcpu;
 
     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_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 =
         (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                      }
 
     procedure tcg386.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;nr : longint);
-
       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;
 
 
     procedure tcg386.a_param_const(list : taasmoutput;size : tcgsize;a : aword;nr : longint);
 
       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;
 
 
@@ -169,19 +205,39 @@ unit cgcpu;
                 list.concat(taicpu.op_reg(A_PUSH,S_W,makereg16(tmpreg)))
               else
                 list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
+              free_scratch_reg(list,tmpreg);
             end;
           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
-            internalerror(200109301);
+            internalerror(2002032214);
         end;
       end;
 
 
     procedure tcg386.a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);
 
+      var
+        tmpreg: tregister;
+
       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;
 
     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, }
         { no need to do it here too (JM)                                   }
         list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[size],
-          longint(a),reg))
+          a,reg))
       end;
 
 
     procedure tcg386.a_load_const_ref(list : taasmoutput; size: tcgsize; a : aword;const ref : treference);
 
       begin
+{$ifdef OPTLOAD0}
         { zero is often used several times in succession -> load it in a  }
         { register and then store it to memory, so the optimizer can then }
         { remove the unnecessary loads of registers and you get smaller   }
@@ -216,8 +273,9 @@ unit cgcpu;
            (size in [OS_32,OS_S32]) then
           inherited a_load_const_ref(list,size,a,ref)
         else
+{$endif OPTLOAD0}
           list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[size],
-            longint(a),newreference(ref)));
+            a,ref));
       end;
 
 
@@ -225,7 +283,7 @@ unit cgcpu;
 
       begin
         list.concat(taicpu.op_reg_ref(A_MOV,TCGSize2OpSize[size],reg,
-          newreference(ref)));
+          ref));
       End;
 
 
@@ -236,13 +294,8 @@ unit cgcpu;
         s: topsize;
 
       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;
 
 
@@ -255,22 +308,27 @@ unit cgcpu;
       begin
         sizes2load(size,regsize(reg2),op,s);
         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;
         list.concat(taicpu.op_reg_reg(op,s,reg1,reg2));
       end;
 
@@ -330,14 +388,14 @@ unit cgcpu;
     procedure tcg386.a_loadmm_ref_reg(list: taasmoutput; const ref: treference; reg: tregister);
 
        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;
 
 
     procedure tcg386.a_loadmm_reg_ref(list: taasmoutput; reg: tregister; const ref: treference);
 
        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;
 
 
@@ -351,7 +409,7 @@ unit cgcpu;
         Case Op of
           OP_DIV, OP_IDIV:
             Begin
-              if ispowerof2(longint(a),power) then
+              if ispowerof2(a,power) then
                 begin
                   case op of
                     OP_DIV:
@@ -370,7 +428,7 @@ unit cgcpu;
           OP_MUL,OP_IMUL:
             begin
               if not(cs_check_overflow in aktlocalswitches) and
-                 ispowerof2(longint(a),power) then
+                 ispowerof2(a,power) then
                 begin
                   list.concat(taicpu.op_const_reg(A_SHL,regsize(reg),power,
                     reg));
@@ -378,14 +436,15 @@ unit cgcpu;
                 end;
               if op = OP_IMUL then
                 list.concat(taicpu.op_const_reg(A_IMUL,regsize(reg),
-                  longint(a),reg))
+                  a,reg))
               else
                 { OP_MUL should be handled specifically in the code        }
                 { generator because of the silly register usage restraints }
                 internalerror(200109225);
             end;
           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
               if op = OP_ADD then
                 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))
             else
               list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],regsize(reg),
-                longint(a),reg));
+                a,reg));
           OP_SHL,OP_SHR,OP_SAR:
             begin
               if (a and 31) <> 0 Then
@@ -422,7 +481,7 @@ unit cgcpu;
         Case Op of
           OP_DIV, OP_IDIV:
             Begin
-              if ispowerof2(longint(a),power) then
+              if ispowerof2(a,power) then
                 begin
                   case op of
                     OP_DIV:
@@ -431,7 +490,7 @@ unit cgcpu;
                       opcode := A_SAR;
                   end;
                   list.concat(taicpu.op_const_ref(opcode,
-                    TCgSize2OpSize[size],power,newreference(ref)));
+                    TCgSize2OpSize[size],power,ref));
                   exit;
                 end;
               { the rest should be handled specifically in the code      }
@@ -441,10 +500,10 @@ unit cgcpu;
           OP_MUL,OP_IMUL:
             begin
               if not(cs_check_overflow in aktlocalswitches) and
-                 ispowerof2(longint(a),power) then
+                 ispowerof2(a,power) then
                 begin
                   list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
-                    power,newreference(ref)));
+                    power,ref));
                   exit;
                 end;
               { can't multiply a memory location directly with a constant }
@@ -456,14 +515,13 @@ unit cgcpu;
                 internalerror(200109232);
             end;
           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
               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
-                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
               if (op <> OP_AND) then
                 exit
@@ -471,12 +529,12 @@ unit cgcpu;
                 a_load_const_ref(list,size,0,ref)
             else
               list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
-                TCgSize2OpSize[size],longint(a),newreference(ref)));
+                TCgSize2OpSize[size],a,ref));
           OP_SHL,OP_SHR,OP_SAR:
             begin
               if (a and 31) <> 0 Then
                 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
                 internalerror(68991);
             end
@@ -572,28 +630,22 @@ unit cgcpu;
          opsize: topsize;
 
        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;
+            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);
@@ -607,8 +659,7 @@ unit cgcpu;
              begin
                if reg <> R_NO then
                  internalerror(200109237);
-               list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],
-                 newreference(ref)));
+               list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref));
              end;
            OP_IMUL:
              begin
@@ -622,8 +673,7 @@ unit cgcpu;
            else
              begin
                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;
@@ -652,23 +702,22 @@ unit cgcpu;
           OP_IMUL:
             begin
               if not(cs_check_overflow in aktlocalswitches) and
-                 ispowerof2(longint(a),power) then
+                 ispowerof2(a,power) then
                 { can be done with a shift }
                 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;
           OP_ADD, OP_SUB:
             if (a = 0) then
               a_load_reg_reg(list,size,src,dst)
             else
               begin
-                reset_reference(tmpref);
+                reference_reset(tmpref);
                 tmpref.base := src;
                 tmpref.offset := longint(a);
                 if op = OP_SUB then
                   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
           else internalerror(200112302);
         end;
@@ -698,12 +747,11 @@ unit cgcpu;
             list.concat(taicpu.op_reg_reg_reg(A_IMUL,S_L,src1,src2,dst));
           OP_ADD:
             begin
-              reset_reference(tmpref);
+              reference_reset(tmpref);
               tmpref.base := src1;
               tmpref.index := src2;
               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
           else internalerror(200112303);
         end;
@@ -715,11 +763,11 @@ unit cgcpu;
         l : tasmlabel);
 
         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
-            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);
         end;
 
@@ -727,8 +775,7 @@ unit cgcpu;
         l : tasmlabel);
 
         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);
         end;
 
@@ -749,7 +796,7 @@ unit cgcpu;
 
         begin
           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);
         end;
 
@@ -843,10 +890,10 @@ unit cgcpu;
         runerror(211);
       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
-         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;
 
     function tcg386.makeregsize(var reg: tregister; size: tcgsize): topsize;
@@ -879,6 +926,87 @@ unit cgcpu;
       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 ************ }
 
@@ -982,7 +1110,7 @@ unit cgcpu;
 
       begin
          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);
       end;
 
@@ -1021,7 +1149,7 @@ unit cgcpu;
 
       begin
          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);
       end;
 
@@ -1031,7 +1159,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 43 - 32
compiler/i386/cpuasm.pas

@@ -42,7 +42,7 @@ interface
 uses
   cclasses,tainst,
   aasm,globals,verbose,
-  cpubase;
+  cpuinfo,cpubase;
 
 const
   MaxPrefixes=4;
@@ -63,26 +63,26 @@ type
      constructor op_none(op : tasmop;_size : topsize);
 
      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_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) }
-     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_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 }
      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_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_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);
 
@@ -222,7 +222,7 @@ uses
       end;
 
 
-    constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
+    constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aword);
       begin
          inherited create(op);
          init(_size);
@@ -231,7 +231,7 @@ uses
       end;
 
 
-    constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : preference);
+    constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
       begin
          inherited create(op);
          init(_size);
@@ -250,7 +250,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -260,7 +260,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -270,7 +270,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -280,7 +280,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -290,7 +290,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -300,7 +300,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -310,7 +310,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -330,7 +330,7 @@ uses
          loadreg(2,_op3);
       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
          inherited create(op);
          init(_size);
@@ -340,7 +340,7 @@ uses
          loadreg(2,_op3);
       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
          inherited create(op);
          init(_size);
@@ -351,7 +351,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -362,7 +362,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -411,7 +411,7 @@ uses
       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
          inherited create(op);
          init(_size);
@@ -611,7 +611,7 @@ begin
           end;
         top_const :
           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
             else
               ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
@@ -1289,7 +1289,7 @@ var
         end;
       top_const :
         begin
-          currval:=oper[opidx].val;
+          currval:=longint(oper[opidx].val);
           currsym:=nil;
         end;
       top_symbol :
@@ -1593,7 +1593,18 @@ end;
 end.
 {
   $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
 
   Revision 1.16  2001/12/29 15:29:59  jonas

+ 88 - 138
compiler/i386/cpubase.pas

@@ -31,7 +31,7 @@ unit cpubase;
 interface
 
 uses
-  globals,cutils,cclasses,aasm;
+  globals,cutils,cclasses,aasm,cpuinfo,cginfo;
 
 const
 { Size of the instruction table converted by nasmconv.pas }
@@ -429,9 +429,8 @@ type
   trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
 
   { immediate/reference record }
-  preference = ^treference;
+  poperreference = ^treference;
   treference = packed record
-     is_immediate : boolean; { is this used as reference or immediate }
      segment,
      base,
      index       : tregister;
@@ -457,8 +456,8 @@ type
           case typ : toptype of
            top_none   : ();
            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);
         end;
 
@@ -487,38 +486,43 @@ type
 type
   TLoc=(
     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_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_FPUREGISTER,  { FPU stack }
+    LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
     LOC_MMXREGISTER,  { MMX register }
     LOC_CMMXREGISTER, { MMX register variable }
-    LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
     LOC_SSEREGISTER,
     LOC_CSSEREGISTER
   );
 
   plocation = ^tlocation;
   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_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 }
         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;
 
 {*****************************************************************************
@@ -718,31 +722,21 @@ const
     { returns the operand prefix for a given register }
     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 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);
     function flags_to_cond(const f: TResFlags) : TAsmCond;
 
+
 implementation
 
-{$ifdef heaptrc}
   uses
-      ppheap;
+{$ifdef heaptrc}
+      ppheap,
 {$endif heaptrc}
+      verbose;
 
 {*****************************************************************************
                                   Helpers
@@ -799,23 +793,6 @@ implementation
       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;
 
       begin
@@ -877,56 +854,35 @@ implementation
         regtoreg64:=R_NO;
      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
-        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;
 
-    {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
-        destloc:= sourceloc;
+        f := flagsinvers[f];
       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
-         swapl := destloc;
-         destloc := sourceloc;
-         sourceloc := swapl;
+        result := flags_2_cond[f];
       end;
 
 
@@ -934,64 +890,58 @@ end;
                               Instruction table
 *****************************************************************************}
 
-procedure DoneCpu;
-begin
-  {exitproc:=saveexit; }
+    procedure BuildInsTabCache;
 {$ifndef NOAG386BIN}
-  if assigned(instabcache) then
-    dispose(instabcache);
-{$endif NOAG386BIN}
-end;
-
-
-procedure BuildInsTabCache;
-{$ifndef NOAG386BIN}
-var
-  i : longint;
+      var
+        i : longint;
 {$endif}
-begin
+      begin
 {$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}
-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;
 
-    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
-        result := flags_2_cond[f];
+{$ifndef NOAG386BIN}
+        if not assigned(instabcache) then
+          BuildInsTabCache;
+{$endif NOAG386BIN}
       end;
 
-procedure InitCpu;
-begin
+
+    procedure DoneCpu;
+      begin
 {$ifndef NOAG386BIN}
-  if not assigned(instabcache) then
-    BuildInsTabCache;
+        if assigned(instabcache) then
+         dispose(instabcache);
 {$endif NOAG386BIN}
-end;
+      end;
 
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 13 - 1
compiler/i386/cpuinfo.pas

@@ -28,6 +28,7 @@ Interface
 
 Type
    AWord = Cardinal;
+   PAWord = ^AWord;
 
    { the ordinal type used when evaluating constant integer expressions }
    TConstExprInt = int64;
@@ -50,7 +51,18 @@ Implementation
 end.
 {
   $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
       is used for holding target platform pointer values. As those can be
       bigger than the source platform.

+ 18 - 7
compiler/i386/csopt386.pas

@@ -27,7 +27,7 @@ Unit CSOpt386;
 
 Interface
 
-Uses aasm, cpubase, cpuasm;
+Uses aasm, cpuinfo, cpubase, cpuasm;
 
 function CSE(asmL: TAAsmoutput; first, last: Tai; pass: longint): boolean;
 
@@ -1263,7 +1263,7 @@ begin
 {$endif replaceregdebug}
 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}
 Var Counter: TRegister;
 {$ifdef testing}
@@ -1394,9 +1394,9 @@ begin
 end;
 
 procedure removeLocalStores(const t1: tai);
-var
+{var
   p: tai;
-  regcount: tregister;
+  regcount: tregister; }
 begin
 {
   for regcount := LoGPReg to HiGPReg do
@@ -1812,7 +1812,7 @@ Begin
                                   insertllitem(asml,p,p.next,hp1);
                                   hp1 := taicpu.op_reg_ref(A_MOV,
                                     regsize(regcounter),regcounter,
-                                    newreference(taicpu(p).oper[0].ref^));
+                                    taicpu(p).oper[0].ref^);
                                   new(pTaiprop(hp1.optinfo));
                                   pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
                                   insertllitem(asml,p,p.next,hp1);
@@ -1865,7 +1865,7 @@ Begin
                                   insertllitem(asml,p,p.next,hp1);
                                   hp1 := taicpu.op_reg_ref(A_MOV,
                                     regsize(regcounter),regcounter,
-                                    newreference(taicpu(p).oper[1].ref^));
+                                    taicpu(p).oper[1].ref^);
                                   new(pTaiprop(hp1.optinfo));
                                   pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
                                   insertllitem(asml,p,p.next,hp1);
@@ -1981,7 +1981,18 @@ End.
 
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       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;
 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;
 
 
 Function RefsEqual(Const R1, R2: TReference): Boolean;
 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;
 
 Function IsGP32Reg(Reg: TRegister): Boolean;
@@ -1617,7 +1611,7 @@ Begin
 End;
 
 
-Procedure ReadRef(p: PTaiProp; Ref: PReference);
+Procedure ReadRef(p: PTaiProp; Const Ref: POperReference);
 Begin
   If Ref^.Base <> R_NO Then
     ReadReg(p, Ref^.Base);
@@ -2592,7 +2586,18 @@ End.
 
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

Разлика између датотеке није приказан због своје велике величине
+ 1261 - 1528
compiler/i386/n386add.pas


+ 192 - 215
compiler/i386/n386cal.pas

@@ -60,10 +60,10 @@ implementation
 {$ifdef GDB}
       gdb,
 {$endif GDB}
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       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
@@ -89,7 +89,8 @@ implementation
          otlabel,oflabel : tasmlabel;
          { temporary variables: }
          tempdeftype : tdeftype;
-         r : preference;
+         href   : treference;
+         cgsize : tcgsize;
 
       begin
          { set default para_alignment to target_info.stackalignment }
@@ -119,7 +120,7 @@ implementation
                begin
                  inc(pushedparasize,4);
                  emitpushreferenceaddr(left.location.reference);
-                 rg.del_reference(exprasmlist,left.location.reference);
+                 location_release(exprasmlist,left.location);
                end
              else
                push_value_para(left,inlined,is_cdecl,para_offset,para_alignment);
@@ -131,7 +132,7 @@ implementation
            end
          { in codegen.handleread.. defcoll.data is set to nil }
          else if assigned(defcoll.paratype.def) and
-           (defcoll.paratype.def.deftype=formaldef) then
+                 (defcoll.paratype.def.deftype=formaldef) then
            begin
               { allow @var }
               inc(pushedparasize,4);
@@ -141,9 +142,8 @@ implementation
                 { always a register }
                   if inlined then
                     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
                   else
                     emit_reg(A_PUSH,S_L,left.location.register);
@@ -151,30 +151,55 @@ implementation
                 end
               else
                 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)
                    else
                      begin
                        if inlined then
                          begin
                            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);
                          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
          { handle call by reference parameter }
          else if (defcoll.paratyp in [vs_var,vs_out]) then
            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
-                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;
               if (defcoll.paratyp=vs_out) and
                  assigned(defcoll.paratype.def) and
@@ -185,15 +210,14 @@ implementation
               if inlined then
                 begin
                    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);
                 end
               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
          else
            begin
@@ -212,20 +236,35 @@ implementation
                   not is_cdecl
                  ) then
                 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;
                    inc(pushedparasize,4);
                    if inlined then
                      begin
                         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);
                      end
                    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
               else
                 begin
@@ -258,7 +297,7 @@ implementation
          unusedstate: pointer;
          pushed : tpushedsaved;
          funcretref,refcountedtemp : treference;
-         hregister,hregister2 : tregister;
+         hregister : tregister;
          oldpushedparasize : longint;
          { true if ESI must be loaded again after the subroutine }
          loadesi : boolean;
@@ -273,7 +312,7 @@ implementation
          { lexlevel count }
          i : longint;
          { help reference pointer }
-         r : preference;
+         href : treference;
          hp : tnode;
          pp : tbinarynode;
          params : tnode;
@@ -292,13 +331,14 @@ implementation
          push_size : longint;
 {$endif OPTALIGN}
          pop_allowed : boolean;
+         cgsize : tcgsize;
          constructorfailed : tasmlabel;
 
       label
          dont_call;
 
       begin
-         reset_reference(location.reference);
+         location_reset(location,LOC_REFERENCE,def_cgsize_ref(resulttype.def));
          extended_new:=false;
          iolabel:=nil;
          inlinecode:=nil;
@@ -467,7 +507,7 @@ implementation
 {$endif test_dest_loc}
                 if inlined then
                   begin
-                     reset_reference(funcretref);
+                     reference_reset(funcretref);
                      funcretref.offset:=tg.gettempofsizepersistant(exprasmlist,resulttype.def.size);
                      funcretref.base:=procinfo^.framepointer;
 {$ifdef extdebug}
@@ -514,10 +554,9 @@ implementation
               if inlined then
                 begin
                    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);
                 end
               else
@@ -544,24 +583,13 @@ implementation
                    methodpointer.resulttype:=
                      twithnode(twithsymtable(symtableproc).withnode).left.resulttype;
                    { 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
                        (not twithsymtable(symtableproc).direct_with)) or
                       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
-                     emit_ref_reg(A_LEA,S_L,r,R_ESI);
+                     emit_ref_reg(A_LEA,S_L,href,R_ESI);
                 end;
 
               { push self }
@@ -674,9 +702,8 @@ implementation
                                     { destructor with extended syntax called from dispose }
                                     { hdisposen always deliver LOC_REFERENCE          }
                                     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_sym(A_PUSH,S_L,
                                       newasmsymbol(tobjectdef(methodpointer.resulttype.def).vmt_mangledname));
@@ -699,12 +726,10 @@ implementation
                                               begin
                                                  if (methodpointer.resulttype.def.deftype=classrefdef) or
                                                     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
-                                                   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;
@@ -717,11 +742,8 @@ implementation
                                           begin
                                              { class method needs current VMT }
                                              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;
 
                                         { direct call to destructor: remove data }
@@ -778,11 +800,8 @@ implementation
                           begin
                              { class method needs current VMT }
                              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
                         else
                           begin
@@ -836,16 +855,11 @@ implementation
                    (right=nil)) then
                   begin
                      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);
-                     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);
                   end;
 
@@ -869,11 +883,8 @@ implementation
                      }
                      if lexlevel=(tprocdef(procdefinition).parast.symtablelevel) then
                        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
                        { this is only true if the difference is one !!
                          but it cannot be more !! }
@@ -884,20 +895,14 @@ implementation
                      else if (lexlevel>(tprocdef(procdefinition).parast.symtablelevel)) then
                        begin
                           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
                             begin
-                               new(r);
-                               reset_reference(r^);
                                {we should get the correct frame_pointer_offset at each level
                                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;
                           emit_reg(A_PUSH,S_L,hregister);
                           rg.ungetregisterint(exprasmlist,hregister);
@@ -932,22 +937,15 @@ implementation
                         { ESI is loaded earlier }
                         (po_classmethod in procdefinition.procoptions) then
                          begin
-                            new(r);
-                            reset_reference(r^);
-                            r^.base:=R_ESI;
+                            reference_reset_base(href,R_ESI,0);
                          end
                        else
                          begin
-                            new(r);
-                            reset_reference(r^);
-                            r^.base:=R_ESI;
                             { 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);
-                            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
                    else
@@ -966,7 +964,7 @@ implementation
                    }
                    if tprocdef(procdefinition).extnumber=-1 then
                      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
                      not(is_cppclass(tprocdef(procdefinition)._class)) then
                      begin
@@ -974,16 +972,16 @@ implementation
                           begin
                              emit_sym(A_PUSH,S_L,
                                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');
                           end
                         else if (cs_check_range in aktlocalswitches) then
                           begin
-                             emit_reg(A_PUSH,S_L,r^.base);
+                             emit_reg(A_PUSH,S_L,href.base);
                              emitcall('FPC_CHECK_OBJECT');
                           end;
                      end;
-                   emit_ref(A_CALL,S_NO,r);
+                   emit_ref(A_CALL,S_NO,href);
                    rg.ungetregisterint(exprasmlist,R_EDI);
                 end
               else if not inlined then
@@ -1028,10 +1026,9 @@ implementation
                    if (right.location.reference.base=R_ESI) or
                       (right.location.reference.index=R_ESI) then
                      begin
-                        rg.del_reference(exprasmlist,right.location.reference);
+                        reference_release(exprasmlist,right.location.reference);
                         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;
                      end;
 
@@ -1041,8 +1038,7 @@ implementation
                        { load ESI }
                        inc(right.location.reference.offset,4);
                        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);
                        { push self pointer }
                        emit_reg(A_PUSH,S_L,R_ESI);
@@ -1050,30 +1046,27 @@ implementation
 
                    rg.saveregvars(exprasmlist,ALL_REGISTERS);
                    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
                      begin
                        emit_reg(A_CALL,S_NO,hregister);
                        rg.ungetregisterint(exprasmlist,hregister);
                      end;
 
-                   rg.del_reference(exprasmlist,right.location.reference);
+                   reference_release(exprasmlist,right.location.reference);
                 end
               else
                 begin
                    rg.saveregvars(exprasmlist,ALL_REGISTERS);
                    case right.location.loc of
                       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
-                         begin
-                           emit_ref(A_CALL,S_NO,newreference(right.location.reference));
-                           rg.del_reference(exprasmlist,right.location.reference);
-                         end;
+                        internalerror(200203311);
                    end;
+                   location_release(exprasmlist,right.location);
                 end;
            end;
 
@@ -1144,16 +1137,11 @@ implementation
               getlabel(constructorfailed);
               emitjmp(C_Z,constructorfailed);
               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);
-              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);
               exprasmList.concat(Tairegalloc.Alloc(R_EAX));
               emitlab(constructorfailed);
@@ -1165,7 +1153,7 @@ implementation
          { needed also when result_no_used !! }
          if (not is_void(resulttype.def)) and ret_in_param(resulttype.def) then
            begin
-              location.loc:=LOC_MEM;
+              location.loc:=LOC_CREFERENCE;
               location.reference.symbol:=nil;
               location.reference:=funcretref;
            end;
@@ -1181,11 +1169,6 @@ implementation
                  { quick'n'dirty check if it is a class or an object }
                  (resulttype.def.deftype=orddef) then
                 begin
-                   { this fails if popsize > 0 PM }
-                   location.loc:=LOC_FLAGS;
-                   location.resflags:=F_NE;
-
-
                    if extended_new then
                      begin
 {$ifdef test_dest_loc}
@@ -1197,8 +1180,15 @@ implementation
                              cg.a_reg_alloc(exprasmlist,R_EAX);
                              hregister:=rg.getexplicitregisterint(exprasmlist,R_EAX);
                              emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
+                             location_reset(location,LOC_REGISTER,OS_NO);
                              location.register:=hregister;
                           end;
+                     end
+                   else
+                     begin
+                       { this fails if popsize > 0 PM }
+                       location_reset(location,LOC_FLAGS,OS_NO);
+                       location.resflags:=F_NE;
                      end;
                 end
                { structed results are easy to handle.... }
@@ -1213,92 +1203,69 @@ implementation
                 begin
                    if (resulttype.def.deftype in [orddef,enumdef]) then
                      begin
-                        location.loc:=LOC_REGISTER;
                         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
+                                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}
 {$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}
-                                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
               else if (resulttype.def.deftype=floatdef) then
                 begin
-                  location.loc:=LOC_FPU;
+                  location_reset(location,LOC_FPUREGISTER,OS_NO);
                   location.register:=R_ST;
                   inc(trgcpu(rg).fpuvaroffset);
                 end
               else if is_ansistring(resulttype.def) or
-                is_widestring(resulttype.def) then
+                      is_widestring(resulttype.def) then
                 begin
+                   location_reset(location,LOC_CREFERENCE,OS_ADDR);
+                   location.reference:=refcountedtemp;
                    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);
-                   location.loc:=LOC_MEM;
-                   location.reference:=refcountedtemp;
                 end
               else
                 begin
-                   location.loc:=LOC_REGISTER;
+                   location_reset(location,LOC_REGISTER,OS_INT);
 {$ifdef test_dest_loc}
                    if dest_loc_known and (dest_loc_tree=p) then
                      mov_reg_to_dest(p,S_L,R_EAX)
@@ -1306,9 +1273,8 @@ implementation
 {$endif test_dest_loc}
                     begin
                        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;
@@ -1334,7 +1300,7 @@ implementation
            begin
               if assigned(pp.left) then
                 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);
                 { process also all nodes of an array of const }
                   if pp.left.nodetype=arrayconstructorn then
@@ -1344,7 +1310,7 @@ implementation
                          hp:=pp.left;
                          while assigned(hp) do
                           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);
                             hp:=tbinarynode(hp).right;
                           end;
@@ -1369,7 +1335,7 @@ implementation
          { if return value is not used }
          if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
            begin
-              if location.loc in [LOC_MEM,LOC_REFERENCE] then
+              if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
                 begin
                    { data which must be finalized ? }
                    if (resulttype.def.needs_inittable) then
@@ -1377,7 +1343,7 @@ implementation
                    { release unused temp }
                    tg.ungetiftemp(exprasmlist,location.reference)
                 end
-              else if location.loc=LOC_FPU then
+              else if location.loc=LOC_FPUREGISTER then
                 begin
                   { release FPU stack }
                   emit_reg(A_FSTP,S_NO,R_ST);
@@ -1569,7 +1535,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 182 - 196
compiler/i386/n386cnv.pas

@@ -60,7 +60,7 @@ implementation
    uses
       verbose,systems,
       symconst,symdef,aasm,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       ncon,ncal,
       cpubase,
       cgobj,cga,tgobj,rgobj,rgcpu,n386util;
@@ -72,12 +72,12 @@ implementation
 
     procedure ti386typeconvnode.second_int_to_int;
       var
-        op      : tasmop;
-        opsize    : topsize;
-        hregister,
-        hregister2 : tregister;
-
+        newsize,
+        oldsize    : tcgsize;
       begin
+        newsize:=def_cgsize(resulttype.def);
+        oldsize:=def_cgsize(left.resulttype.def);
+
         { insert range check if not explicit conversion }
         if not(nf_explizit in flags) then
           cg.g_rangecheck(exprasmlist,left,resulttype.def);
@@ -85,105 +85,42 @@ implementation
         { is the result size smaller ? }
         if resulttype.def.size<left.resulttype.def.size then
           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
-               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;
-               { we can release the upper register }
-               if is_64bitint(left.resulttype.def) then
-                 rg.ungetregisterint(exprasmlist,left.location.registerhigh);
              end;
           end
 
         { is the result size bigger ? }
         else if resulttype.def.size>left.resulttype.def.size then
           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;
 
@@ -191,68 +128,75 @@ implementation
     procedure ti386typeconvnode.second_int_to_real;
 
       var
-         r : preference;
+         r : treference;
          hregister : tregister;
          l1,l2 : tasmlabel;
 
       begin
+         location_reset(location,LOC_FPUREGISTER,OS_NO);
          { for u32bit a solution is to push $0 and to load a comp }
          { does this first, it destroys maybe EDI }
          hregister:=R_EDI;
          if torddef(left.resulttype.def).typ=u32bit then
             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;
-              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 }
          emit_reg(A_PUSH,S_L,hregister);
          if hregister = R_EDI then
            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
            u32bit:
              begin
@@ -270,14 +214,14 @@ implementation
                 { we load bits 0..62 and then check bit 63:  }
                 { if it is 1 then we add $80000000 000000000 }
                 { as double                                  }
-                inc(r^.offset,4);
+                inc(r.offset,4);
                 rg.getexplicitregisterint(exprasmlist,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_reg(A_TEST,S_L,longint($80000000),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);
                 getdatalabel(l1);
                 getlabel(l2);
@@ -286,8 +230,7 @@ implementation
                 { I got this constant from a test progtram (FK) }
                 Consts.concat(Tai_const.Create_32bit(0));
                 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);
                 emitlab(l2);
                 emit_const_reg(A_ADD,S_L,8,R_ESP);
@@ -301,8 +244,6 @@ implementation
              end;
          end;
          inc(trgcpu(rg).fpuvaroffset);
-         clear_location(location);
-         location.loc:=LOC_FPU;
          location.register:=R_ST;
       end;
 
@@ -310,68 +251,104 @@ implementation
     procedure ti386typeconvnode.second_int_to_bool;
       var
         hregister : tregister;
-        resflags  : tresflags;
+        leftopsize,
         opsize    : topsize;
-        pref      : preference;
+        pref      : treference;
+        hlabel,oldtruelabel,oldfalselabel : tasmlabel;
       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 }
          { be accepted for var parameters                            }
          if (nf_explizit in flags) 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
-              set_location(location,left.location);
+              location_copy(location,left.location);
+              truelabel:=oldtruelabel;
+              falselabel:=oldfalselabel;
               exit;
            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
-            LOC_MEM,LOC_REFERENCE :
+            LOC_CREFERENCE,LOC_REFERENCE :
               begin
                 if is_64bitint(left.resulttype.def) then
                  begin
                    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
                 else
                  begin
                    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;
-                resflags:=F_NE;
               end;
             LOC_FLAGS :
               begin
-                hregister:=rg.getregisterint(exprasmlist);
-                resflags:=left.location.resflags;
+                hregister:=def_getreg(left.resulttype.def);
+                emit_flag2reg(left.location.resflags,hregister);
               end;
             LOC_REGISTER,LOC_CREGISTER :
               begin
                 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;
             else
               internalerror(10062);
          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;
-         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_int_to_int,
            @second_int_to_bool,
-           @second_bool_to_int, { bool_to_bool }
+           @second_bool_to_bool,
            @second_bool_to_int,
            @second_real_to_real,
            @second_int_to_real,
@@ -436,18 +413,16 @@ implementation
          nillabel : plabel;
 {$endif TESTOBJEXT2}
       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}
                   { Check explicit conversions to objects pointers !! }
@@ -493,7 +468,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 16 - 5
compiler/i386/n386con.pas

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

+ 13 - 3
compiler/i386/n386flw.pas

@@ -440,8 +440,7 @@ implementation
          if assigned(exceptsymtable) then
            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 }
          exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
 
@@ -737,7 +736,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 113 - 234
compiler/i386/n386inl.pas

@@ -40,10 +40,10 @@ implementation
       globtype,systems,
       cutils,verbose,globals,fmodule,
       symconst,symtype,symdef,aasm,types,
-      cgbase,pass_1,pass_2,
+      cginfo,cgbase,pass_1,pass_2,
       cpubase,
       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);}
 {        float_name: array[tfloattype] of string[8]=
            ('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
          opsize : topsize;
          op,
@@ -69,19 +68,19 @@ implementation
          hp : tnode;
 
       var
-         r : preference;
-         //hp : tcallparanode;
+         href,href2 : treference;
          hp2 : tstringconstnode;
          dummycoll  : tparaitem;
          l : longint;
          ispushed : boolean;
+         hregisterhi,
          hregister : tregister;
          lengthlab,
          otlabel,oflabel{,l1}   : tasmlabel;
          oldpushedparasize : longint;
          def : tdef;
-         hr,hr2 : treference;
-
+         cgop : TOpCG;
+         cgsize : TCGSize;
       begin
       { save & reset pushedparasize }
          oldpushedparasize:=pushedparasize;
@@ -123,6 +122,7 @@ implementation
             in_sizeof_x,
             in_typeof_x :
               begin
+                 location_reset(location,LOC_REGISTER,OS_ADDR);
                  { for both cases load vmt }
                  if left.nodetype=typen then
                    begin
@@ -134,186 +134,97 @@ implementation
                  else
                    begin
                       secondpass(left);
-                      rg.del_reference(exprasmlist,left.location.reference);
-                      location.loc:=LOC_REGISTER;
+                      location_release(exprasmlist,left.location);
                       location.register:=rg.getregisterint(exprasmlist);
                       { load VMT pointer }
                       inc(left.location.reference.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;
                  { in sizeof load size }
                  if inlinenumber=in_sizeof_x then
                    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;
             in_length_x :
               begin
                  secondpass(left);
-                 set_location(location,left.location);
                  { length in ansi strings is at offset -8 }
                  if is_ansistring(left.resulttype.def) or
                     is_widestring(left.resulttype.def) then
                   begin
                     if left.location.loc<>LOC_REGISTER then
                      begin
-                       rg.del_location(exprasmlist,left.location);
+                       location_release(exprasmlist,left.location);
                        hregister:=rg.getregisterint(exprasmlist);
-                       emit_mov_loc_reg(left.location,hregister);
+                       cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,hregister);
                      end
                     else
                      hregister:=left.location.register;
-                    reset_reference(hr);
-                    hr.base:=hregister;
-                    hr.offset:=-8;
+                    reference_reset_base(href,hregister,-8);
                     getlabel(lengthlab);
                     emit_reg_reg(A_OR,S_L,hregister,hregister);
                     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);
-                    location.loc:=LOC_REGISTER;
+                    location_reset(location,LOC_REGISTER,OS_INT);
                     location.register:=hregister;
+                  end
+                 else
+                  begin
+                    location_copy(location,left.location);
+                    location.size:=OS_8;
                   end;
               end;
             in_pred_x,
             in_succ_x:
               begin
                  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
-                   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
-                   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);
                  cg.g_rangecheck(exprasmlist,self,resulttype.def);
               end;
             in_dec_x,
             in_inc_x :
               begin
-              { set defaults }
-                addvalue:=1;
+                { set defaults }
                 addconstant:=true;
-              { load first parameter, must be a reference }
+                { load first parameter, must be a reference }
                 secondpass(tcallparanode(left).left);
+                cgsize:=def_cgsize(tcallparanode(left).left.resulttype.def);
+                { get addvalue }
                 case tcallparanode(left).left.resulttype.def.deftype of
                   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;
-              { second argument specified?, must be a s32bit in register }
+                { second argument specified?, must be a s32bit in register }
                 if assigned(tcallparanode(left).right) then
                  begin
                    ispushed:=maybe_push(tcallparanode(tcallparanode(left).right).left.registers32,
@@ -321,76 +232,39 @@ implementation
                    secondpass(tcallparanode(tcallparanode(left).right).left);
                    if ispushed then
                      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
                     addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
                    else
                     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
-                       emit_const_reg(A_IMUL,opsize,
-                         addvalue,hregister);
+                        cg.a_op_const_reg(exprasmlist,OP_IMUL,addvalue,hregister);
                       addconstant:=false;
                     end;
                  end;
               { write the add instruction }
                 if addconstant then
                  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
-                     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
                 else
                  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;
                 emitoverflowcheck(tcallparanode(left).left);
                 cg.g_rangecheck(exprasmlist,tcallparanode(left).left,tcallparanode(left).left.resulttype.def);
@@ -398,11 +272,10 @@ implementation
 
             in_typeinfo_x:
                begin
+                  location_reset(location,LOC_REGISTER,OS_ADDR);
                   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;
 
              in_finalize_x:
@@ -419,9 +292,8 @@ implementation
                     end;
 
                   { 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 }
                   secondpass(tcallparanode(left).left);
@@ -439,20 +311,18 @@ implementation
             in_assigned_x :
               begin
                  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
                    begin
                       emit_reg_reg(A_OR,S_L,
                         tcallparanode(left).left.location.register,
                         tcallparanode(left).left.location.register);
-                      rg.ungetregisterint(exprasmlist,tcallparanode(left).left.location.register);
                    end
                  else
                    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;
+                 location_reset(location,LOC_FLAGS,OS_NO);
                  location.resflags:=F_NE;
               end;
             in_setlength_x:
@@ -471,17 +341,17 @@ implementation
                   if is_dynamic_array(def) then
                     begin
                        { get temp. space }
-                       tg.gettempofsizereference(exprasmlist,l*4,hr);
+                       tg.gettempofsizereference(exprasmlist,l*4,href);
                        { keep data start }
-                       hr2:=hr;
+                       href2:=href;
                        { copy dimensions }
                        hp:=left;
                        while assigned(tcallparanode(hp).right) do
                          begin
                             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;
                          end;
                     end
@@ -507,15 +377,14 @@ implementation
                   else secondpass(tcallparanode(hp).left);
                   if is_dynamic_array(def) then
                     begin
-                       emitpushreferenceaddr(hr2);
+                       emitpushreferenceaddr(href2);
                        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);
                        rg.saveregvars(exprasmlist,all_registers);
                        emitcall('FPC_DYNARR_SETLENGTH');
-                       tg.ungetiftemp(exprasmlist,hr);
+                       tg.ungetiftemp(exprasmlist,href);
                     end
                   else
                     { must be string }
@@ -546,6 +415,7 @@ implementation
             in_include_x_y,
             in_exclude_x_y:
               begin
+                 location_copy(location,left.location);
                  secondpass(tcallparanode(left).left);
                  if tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn then
                    begin
@@ -564,9 +434,8 @@ implementation
                         begin
                            inc(tcallparanode(left).left.location.reference.offset,
                              (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
                       else
                         { LOC_CREGISTER }
@@ -613,25 +482,22 @@ implementation
                             op:=A_MOV
                            else
                             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;
                       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
-                        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
                         rg.ungetregisterint(exprasmlist,R_EDI);
                    end;
               end;
             in_pi:
               begin
+                location_reset(location,LOC_FPUREGISTER,OS_NO);
                 emit_none(A_FLDPI,S_NO);
                 inc(trgcpu(rg).fpuvaroffset);
-                location.register := R_ST;
+                location.register:=R_ST;
               end;
             in_sin_extended,
             in_arctan_extended,
@@ -641,22 +507,23 @@ implementation
             in_ln_extended,
             in_cos_extended:
               begin
-                 secondpass(left);
+                 location_reset(location,LOC_FPUREGISTER,OS_NO);
                  location.register := R_ST;
+                 secondpass(left);
                  case left.location.loc of
-                    LOC_FPU:
+                    LOC_FPUREGISTER:
                       ;
                     LOC_CFPUREGISTER:
                       begin
                          cg.a_loadfpu_reg_reg(exprasmlist,
                            left.location.register,location.register);
                       end;
-                    LOC_REFERENCE,LOC_MEM:
+                    LOC_REFERENCE,LOC_CREFERENCE:
                       begin
                          cg.a_loadfpu_ref_reg(exprasmlist,
                            def_cgsize(left.resulttype.def),
                            left.location.reference,location.register);
-                         rg.del_reference(exprasmlist,left.location.reference);
+                         location_release(exprasmlist,left.location);
                       end
                     else
                       internalerror(309991);
@@ -707,6 +574,7 @@ implementation
 {$ifdef SUPPORT_MMX}
             in_mmx_pcmpeqb..in_mmx_pcmpgtw:
               begin
+                 location_reset(location,LOC_MMXREGISTER,OS_NO);
                  if left.location.loc=LOC_REGISTER then
                    begin
                       {!!!!!!!}
@@ -732,7 +600,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

Разлика између датотеке није приказан због своје велике величине
+ 370 - 431
compiler/i386/n386ld.pas


+ 257 - 402
compiler/i386/n386mat.pas

@@ -53,10 +53,10 @@ implementation
       globtype,systems,
       cutils,verbose,globals,
       symconst,symdef,aasm,types,
-      cgbase,pass_1,pass_2,
+      cginfo,cgbase,pass_1,pass_2,
       ncon,
       cpubase,
-      cga,tgobj,n386util,ncgutil,cgobj,rgobj,rgcpu;
+      cga,tgobj,n386util,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
 
 {*****************************************************************************
                              TI386MODDIVNODE
@@ -72,11 +72,15 @@ implementation
       begin
          shrdiv := false;
          secondpass(left);
+         if codegenerror then
+          exit;
          pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
          secondpass(right);
          if pushed then
            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
            begin
@@ -86,189 +90,164 @@ implementation
          else
            begin
               { 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 }
-                            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,
                                 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 }
-                            emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
+                          emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
                           { release EDX if we used it }
                           { also releas EDI }
                           rg.ungetregisterint(exprasmlist,hreg2);
                           { 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 }
-                            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
-                              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
-                         Begin
-                           if hreg1 <> R_EDX then
+                         if hreg1<>R_EAX then
+                           Begin
                              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
                { shrdiv only use hreg1 (which is already in usedinproc,   }
                { since it was acquired with getregister), the others also }
@@ -277,8 +256,7 @@ implementation
                   include(rg.usedinproc,R_EAX);
                   include(rg.usedinproc,R_EDX);
                 End;
-              clear_location(location);
-              location.loc:=LOC_REGISTER;
+              location_reset(location,LOC_REGISTER,OS_32);
               location.register:=hreg1;
            end;
       end;
@@ -290,7 +268,7 @@ implementation
 
     procedure ti386shlshrnode.pass_2;
       var
-         hregister1,hregister2,hregister3,
+         hregister2,hregister3,
          hregisterhigh,hregisterlow : tregister;
          pushed,popecx : boolean;
          op : tasmop;
@@ -313,33 +291,12 @@ implementation
 
          if is_64bitint(left.resulttype.def) then
            begin
+              location_reset(location,LOC_REGISTER,OS_64);
+
               { 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: }
               if (right.nodetype=ordconstn) then
@@ -385,26 +342,16 @@ implementation
                         location.registerlow:=hregisterlow;
                         location.registerhigh:=hregisterhigh;
                      end;
-                   location.loc:=LOC_REGISTER;
                 end
               else
                 begin
                    { load right operators in a register }
                    if right.location.loc<>LOC_REGISTER then
                      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
                    else
                      hregister2:=right.location.register;
@@ -505,7 +452,8 @@ implementation
                    { maybe put ECX back }
                    if popecx then
                      emit_reg(A_POP,S_L,R_ECX)
-                   else rg.ungetregisterint(exprasmlist,R_ECX);
+                   else
+                     rg.ungetregisterint(exprasmlist,R_ECX);
 
                    location.registerlow:=hregisterlow;
                    location.registerhigh:=hregisterhigh;
@@ -514,24 +462,8 @@ implementation
          else
            begin
               { 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: }
               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)
                    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
                      emit_reg_reg(A_XOR,S_L,hregister1,
                        hregister1);
                    }
-                   location.loc:=LOC_REGISTER;
-                   location.register:=hregister1;
                 end
               else
                 begin
                    { load right operators in a register }
                    if right.location.loc<>LOC_REGISTER then
                      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
                    else
                      hregister2:=right.location.register;
@@ -574,12 +495,12 @@ implementation
                    { left operator is already in a register }
                    { hence are both in a register }
                    { is it in the case ECX ? }
-                   if (hregister1=R_ECX) then
+                   if (location.register=R_ECX) then
                      begin
                         { 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;
                      end
                    { if second operator not in ECX ? }
@@ -597,13 +518,12 @@ implementation
                      end;
                    rg.ungetregisterint(exprasmlist,hregister2);
                    { 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 }
                    if popecx then
                      emit_reg(A_POP,S_L,R_ECX)
                    else
                      rg.ungetregisterint(exprasmlist,R_ECX);
-                   location.register:=hregister1;
                 end;
            end;
       end;
@@ -630,7 +550,7 @@ implementation
            begin
              if (registersfpu < 1) then
                registersfpu := 1;
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
            end
 {$ifdef SUPPORT_MMX}
          else if (cs_mmx in aktlocalswitches) and
@@ -659,12 +579,13 @@ implementation
 
 
     procedure ti386unaryminusnode.pass_2;
+
 {$ifdef SUPPORT_MMX}
       procedure do_mmx_neg;
         var
            op : tasmop;
         begin
-           location.loc:=LOC_MMXREGISTER;
+           location_reset(location,LOC_MMXREGISTER,OS_NO);
            if cs_mmx_saturation in aktlocalswitches then
              case mmx_type(resulttype.def) of
                 mmxs8bit:
@@ -694,44 +615,19 @@ implementation
          if is_64bitint(left.resulttype.def) then
            begin
               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
          else
            begin
               secondpass(left);
-              location.loc:=LOC_REGISTER;
+              location_reset(location,LOC_REGISTER,OS_INT);
               case left.location.loc of
                  LOC_REGISTER:
                    begin
@@ -748,7 +644,7 @@ implementation
 {$ifdef SUPPORT_MMX}
                  LOC_MMXREGISTER:
                    begin
-                      set_location(location,left.location);
+                      location_copy(location,left.location);
                       emit_reg_reg(A_PXOR,S_NO,R_MM7,R_MM7);
                       do_mmx_neg;
                    end;
@@ -761,17 +657,17 @@ implementation
                       do_mmx_neg;
                    end;
 {$endif SUPPORT_MMX}
-                 LOC_REFERENCE,LOC_MEM:
+                 LOC_REFERENCE,
+                 LOC_CREFERENCE:
                    begin
-                      rg.del_reference(exprasmlist,left.location.reference);
+                      reference_release(exprasmlist,left.location.reference);
                       if (left.resulttype.def.deftype=floatdef) then
                         begin
-                           location.loc:=LOC_FPU;
+                           location_reset(location,LOC_FPUREGISTER,OS_NO);
                            location.register := R_ST;
                            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);
                         end
 {$ifdef SUPPORT_MMX}
@@ -779,39 +675,36 @@ implementation
                         begin
                            location.register:=rg.getregistermm(exprasmlist);
                            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;
                         end
 {$endif SUPPORT_MMX}
                       else
                         begin
                            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);
                         end;
                    end;
-                 LOC_FPU,LOC_CFPUREGISTER:
+                 LOC_FPUREGISTER,LOC_CFPUREGISTER:
                    begin
                       { "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);
                    end;
+                 else
+                    internalerror(200203225);
               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;
 
 
@@ -834,12 +727,13 @@ implementation
             { the second pass could change the location of left }
             { if it is a register variable, so we've to do      }
             { 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
               LOC_JUMP :
                 begin
+                  location_reset(location,LOC_JUMP,OS_NO);
                   hl:=truelabel;
                   truelabel:=falselabel;
                   falselabel:=hl;
@@ -850,30 +744,25 @@ implementation
                   falselabel:=hl;
                 end;
               LOC_FLAGS :
-                location.resflags:=flagsinvers[left.location.resflags];
-              LOC_REGISTER, LOC_CREGISTER :
                 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;
+              LOC_CONSTANT,
+              LOC_REGISTER,
+              LOC_CREGISTER,
               LOC_REFERENCE,
-              LOC_MEM :
+              LOC_CREFERENCE :
                 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;
                 end;
+             else
+                internalerror(200203224);
             end;
           end
 {$ifdef SUPPORT_MMX}
@@ -881,25 +770,25 @@ implementation
           if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
            begin
              secondpass(left);
-             location.loc:=LOC_MMXREGISTER;
+             location_reset(location,LOC_MMXREGISTER,OS_NO);
              { prepare EDI }
              rg.getexplicitregisterint(exprasmlist,R_EDI);
              emit_const_reg(A_MOV,S_L,longint($ffffffff),R_EDI);
              { load operand }
              case left.location.loc of
                LOC_MMXREGISTER:
-                 set_location(location,left.location);
+                 location_copy(location,left.location);
                LOC_CMMXREGISTER:
                  begin
                    location.register:=rg.getregistermm(exprasmlist);
                    emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
                  end;
-               LOC_REFERENCE,LOC_MEM:
+               LOC_REFERENCE,
+               LOC_CREFERENCE:
                  begin
-                   rg.del_reference(exprasmlist,left.location.reference);
+                   location_release(exprasmlist,left.location);
                    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;
              { load mask }
@@ -916,65 +805,20 @@ implementation
          else if is_64bitint(left.resulttype.def) then
            begin
               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
          else
           begin
             secondpass(left);
-            clear_location(location);
+            location_copy(location,left.location);
+            location_force_reg(location,def_cgsize(resulttype.def),false);
+
             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;
 
@@ -987,7 +831,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 104 - 162
compiler/i386/n386mem.pas

@@ -59,7 +59,7 @@ implementation
       globtype,systems,
       cutils,verbose,globals,
       symconst,symtype,symdef,symsym,symtable,aasm,types,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       pass_1,nld,ncon,nadd,
       cpubase,cpuasm,
       cgobj,cga,tgobj,n386util,rgobj;
@@ -72,15 +72,17 @@ implementation
       var
          pushed : tpushedsaved;
          regstopush: tregisterset;
-         r : preference;
+         href : treference;
       begin
          if assigned(left) then
            begin
               secondpass(left);
-              location.register:=left.location.register;
+              location_copy(location,left.location);
            end
          else
            begin
+              location_reset(location,LOC_REFERENCE,OS_ADDR);
+
               regstopush := all_registers;
               remove_non_regvars_from_loc(location,regstopush);
               rg.saveusedregisters(exprasmlist,pushed,regstopush);
@@ -95,11 +97,9 @@ implementation
 
               if tpointerdef(resulttype.def).pointertype.def.needs_inittable then
                 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
                      data located at that pointer not the pointer self (PFV) }
                    emit_push_loc(location);
@@ -109,8 +109,6 @@ implementation
               { may be load ESI }
               maybe_loadself;
            end;
-         if codegenerror then
-           exit;
       end;
 
 
@@ -136,26 +134,23 @@ implementation
       var
          regstopush: tregisterset;
          pushed : tpushedsaved;
+         href : treference;
          lefttemp: treference;
-         r : preference;
          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
          secondpass(left);
          if codegenerror then
            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;
          remove_non_regvars_from_loc(left.location,regstopush);
@@ -168,11 +163,8 @@ implementation
              begin
                 if left_needs_initfinal then
                   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 }
                      emit_push_loc(left.location);
                      { save left and free its registers }
@@ -185,7 +177,7 @@ implementation
                 else
                   begin
                     emit_push_loc(left.location);
-                    rg.del_location(exprasmlist,left.location);
+                    location_release(exprasmlist,left.location);
                   end;
                 emitcall('FPC_FREEMEM');
              end;
@@ -200,11 +192,8 @@ implementation
                 emitcall('FPC_GETMEM');
                 if left_needs_initfinal then
                   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);
                      tg.ungetiftemp(exprasmlist,lefttemp);
                      emitcall('FPC_INITIALIZE');
@@ -245,8 +234,6 @@ implementation
     procedure ti386vecnode.pass_2;
       var
         is_pushed : boolean;
-        ind,hr : tregister;
-        //_p : tnode;
 
           function get_mul_size:longint;
           begin
@@ -271,9 +258,9 @@ implementation
             else
               begin
                  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
-                   emit_const_reg(A_IMUL,S_L,l1,ind);
+                   emit_const_reg(A_IMUL,S_L,l1,right.location.register);
               end;
             end;
           end;
@@ -285,22 +272,24 @@ implementation
          { because in constant nodes which constant index              }
          { the left tree is removed                                  }
          t   : tnode;
-         hp  : preference;
          href : treference;
-         tai : Taicpu;
          srsym : tsym;
          pushed : tpushedsaved;
          hightree : tnode;
-         hl,otl,ofl : tasmlabel;
+         isjump  : boolean;
+         otl,ofl : tasmlabel;
+         newsize : tcgsize;
       begin
+         newsize:=def_cgsize_ref(resulttype.def);
+         location_reset(location,LOC_REFERENCE,newsize);
+
          secondpass(left);
          { we load the array reference to location }
 
          { an ansistring needs to be dereferenced }
          if is_ansistring(left.resulttype.def) or
-           is_widestring(left.resulttype.def) then
+            is_widestring(left.resulttype.def) then
            begin
-              reset_reference(location.reference);
               if nf_callunique in flags then
                 begin
                    if left.location.loc<>LOC_REFERENCE then
@@ -319,18 +308,21 @@ implementation
                    rg.restoreusedregisters(exprasmlist,pushed);
                 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,
                 we can use the ansistring routine here }
@@ -344,38 +336,35 @@ implementation
                    rg.restoreusedregisters(exprasmlist,pushed);
                 end;
 
+              { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
               if is_ansistring(left.resulttype.def) then
-                { in ansistrings S[1] is pchar(S)[0] !! }
                 dec(location.reference.offset)
               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   }
               { if a constant array index occurs, subject to change (FK) }
-              set_location(left.location,location);
+              location_copy(left.location,location);
            end
          else if is_dynamic_array(left.resulttype.def) then
          { ... also a dynamic string }
            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}
               { check for a zero length string,
                 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   }
               { if a constant array index occurs, subject to change (FK) }
-              set_location(left.location,location);
+              location_copy(left.location,location);
            end
          else
-           set_location(location,left.location);
+           location_copy(location,left.location);
 
          { offset can only differ from 0 if arraydef }
          if (left.resulttype.def.deftype=arraydef) and
@@ -441,9 +430,9 @@ implementation
                           begin
                              rg.saveusedregisters(exprasmlist,pushed,all_registers);
                              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);
                              emitcall('FPC_ANSISTR_RANGECHECK');
                              rg.restoreusedregisters(exprasmlist,pushed);
@@ -472,7 +461,7 @@ implementation
               putnode(p);
               p:=_p;
               }
-              set_location(location,left.location);
+              location_copy(location,left.location);
            end
          else
          { not nodetype=ordconstn }
@@ -538,10 +527,10 @@ implementation
                        get_mul_size*extraoffset);
                 end;
               { 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);
-              if (right.location.loc=LOC_JUMP) then
+              isjump:=(right.location.loc=LOC_JUMP);
+              if isjump then
                begin
                  otl:=truelabel;
                  getlabel(truelabel);
@@ -564,8 +553,8 @@ implementation
                      if is_open_array(left.resulttype.def) or
                         is_array_of_const(left.resulttype.def) then
                       begin
-                        reset_reference(href);
                         tarraydef(left.resulttype.def).genrangecheck;
+                        reference_reset(href);
                         href.symbol:=newasmsymbol(tarraydef(left.resulttype.def).getrangecheckstring);
                         href.offset:=4;
                         srsym:=searchsymonlyin(tloadnode(left).symtable,
@@ -573,7 +562,8 @@ implementation
                         hightree:=cloadnode.create(tvarsym(srsym),tloadnode(left).symtable);
                         firstpass(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:=nil;
                       end;
@@ -581,72 +571,13 @@ implementation
                    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: }
               if cs_check_range in aktlocalswitches then
@@ -663,10 +594,10 @@ implementation
                          st_ansistring:
                            begin
                               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);
                               emitcall('FPC_ANSISTR_RANGECHECK');
                               rg.restoreusedregisters(exprasmlist,pushed);
@@ -686,7 +617,7 @@ implementation
 
               if location.reference.index=R_NO then
                begin
-                 location.reference.index:=ind;
+                 location.reference.index:=right.location.register;
                  calc_emit_mul;
                end
               else
@@ -700,13 +631,11 @@ implementation
                     end;
                     calc_emit_mul;
                     location.reference.base:=location.reference.index;
-                    location.reference.index:=ind;
+                    location.reference.index:=right.location.register;
                   end
                  else
                   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);
                     { the symbol offset is loaded,             }
                     { so release the symbol name and set symbol  }
@@ -715,13 +644,15 @@ implementation
                     location.reference.offset:=0;
                     calc_emit_mul;
                     location.reference.base:=location.reference.index;
-                    location.reference.index:=ind;
+                    location.reference.index:=right.location.register;
                   end;
                end;
 
               if nf_memseg in flags then
                 location.reference.segment:=R_FS;
            end;
+
+        location.size:=newsize;
       end;
 
 
@@ -734,7 +665,18 @@ begin
 end.
 {
   $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
 
   Revision 1.21  2002/03/31 20:26:39  jonas

+ 36 - 8
compiler/i386/n386obj.pas

@@ -37,7 +37,7 @@ uses
   fmodule,
   nobj,
   cpubase,
-  cga, tgobj;
+  cga,tgobj,rgobj;
 
    type
      ti386classheader=class(tclassheader)
@@ -108,40 +108,56 @@ procedure ti386classheader.cgintfwrapper(asmlist: TAAsmoutput; procdef: tprocdef
   end;
 
   procedure adjustselfvalue(ioffset: longint);
+  var
+    href : treference;
   begin
     { 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;
 
   procedure getselftoeax(offs: longint);
+  var
+    href : treference;
   begin
     { 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;
 
   procedure loadvmttoeax;
+  var
+    href : treference;
   begin
     checkvirtual;
     { 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;
 
   procedure op_oneaxmethodaddr(op: TAsmOp);
+  var
+    href : treference;
   begin
     { 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;
 
   procedure loadmethodoffstoeax;
+  var
+    href : treference;
   begin
     { 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;
 
 var
   oldexprasmlist: TAAsmoutput;
   lab : tasmsymbol;
   make_global : boolean;
+  href : treference;
 begin
   if procdef.proctypeoption<>potype_none then
     Internalerror(200006137);
@@ -194,7 +210,8 @@ begin
       loadvmttoeax;
       loadmethodoffstoeax;
       { 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 }
       emit_reg(A_POP,S_L,R_EAX);
       { ret  ; jump to the address }
@@ -222,7 +239,18 @@ initialization
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 37 - 32
compiler/i386/n386opt.pas

@@ -41,7 +41,7 @@ type
 
 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;
 
 
@@ -71,7 +71,7 @@ begin
   firstpass(right);
   if codegenerror then
     exit;
-  location.loc := LOC_MEM;
+  location.loc := LOC_CREFERENCE;
   if not is_constcharnode(right) then
     { it's not sure we need the register, but we can't know it here yet }
     calcregisters(self,2,0,0)
@@ -83,8 +83,7 @@ end;
 procedure ti386addsstringcharoptnode.pass_2;
 var
   l: tasmlabel;
-  href2: preference;
-  href:  treference;
+  href,href2 :  treference;
   hreg, lengthreg: tregister;
   checklength: boolean;
 begin
@@ -100,8 +99,7 @@ begin
        { release the registers }
        tg.ungetiftemp(exprasmlist,left.location.reference);
        { 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;
     end;
   secondpass(right);
@@ -114,14 +112,13 @@ begin
   { is it a constant char? }
   if not is_constcharnode(right) then
     { 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
         { free the registers of right }
-        rg.del_reference(exprasmlist,right.location.reference);
+        reference_release(exprasmlist,right.location.reference);
         { get register for the char }
         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) }
        tg.ungetiftemp(exprasmlist,right.location.reference);
       end
@@ -129,7 +126,7 @@ begin
 
   { load the current string length }
   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 ? }
   if tg.istemp(left.location.reference) then
@@ -148,31 +145,31 @@ begin
     end;
 
   { 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 }
   { at the end of the string. Check if the base or }
   { 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
       { they're not free, so add the base reg to       }
       { the string length (since the index can         }
       { 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
   else
     { 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
       begin
-        href2^.index := lengthreg;
-        href2^.scalefactor := 1;
+        href2.index := lengthreg;
+        href2.scalefactor := 1;
       end;
   { 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 }
   if (right.nodetype <> ordconstn) then
     begin
@@ -185,12 +182,11 @@ begin
     emit_const_ref(A_MOV,S_B,tordconstnode(right).value,href2);
   { increase the string length }
   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);
   if checklength then
     emitlab(l);
-  set_location(location,left.location);
+  location_copy(location,left.location);
 end;
 
 procedure ti386addsstringcsstringoptnode.pass_2;
@@ -211,8 +207,7 @@ begin
        { release the registers }
        tg.ungetiftemp(exprasmlist,left.location.reference);
        { 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;
     end;
   secondpass(right);
@@ -222,8 +217,7 @@ begin
   { because emitpushreferenceaddr doesn't need extra }
   { registers) (JM)                                  }
   regstopush := all_registers;
-  remove_non_regvars_from_loc(right.location,
-    regstopush);
+  remove_non_regvars_from_loc(right.location,regstopush);
   rg.saveusedregisters(exprasmlist,pushedregs,regstopush);
   { push the maximum possible length of the result }
   emitpushreferenceaddr(left.location.reference);
@@ -231,14 +225,14 @@ begin
   { deallocations in the right place if it happens }
   { too early than when it happens too late (if    }
   { 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);
   rg.saveregvars(exprasmlist,regstopush);
   emitcall('FPC_SHORTSTR_CONCAT');
   tg.ungetiftemp(exprasmlist,right.location.reference);
   maybe_loadself;
   rg.restoreusedregisters(exprasmlist,pushedregs);
-  set_location(location,left.location);
+  location_copy(location,left.location);
 end;
 
 begin
@@ -248,7 +242,18 @@ end.
 
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
@@ -266,7 +271,7 @@ end.
       and can cause hard-to-find bugs
 
   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
     * some cg reorganisation

+ 93 - 87
compiler/i386/n386set.pas

@@ -47,7 +47,7 @@ implementation
       globtype,systems,cpuinfo,
       verbose,globals,
       symconst,symdef,aasm,types,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       ncon,
       cpubase,
       cga,tgobj,n386util,regvars,rgobj;
@@ -82,7 +82,7 @@ implementation
            end;
 
          { we doesn't modify the left side, we check only the type }
-         set_location(location,left.location);
+         location_copy(location,left.location);
        end;
 
 
@@ -103,6 +103,7 @@ implementation
          ranges     : boolean;
          hr,hr2,
          pleftreg   : tregister;
+         href       : treference;
          opsize     : topsize;
          setparts   : array[1..8] of Tsetpart;
          i,numparts : byte;
@@ -238,12 +239,11 @@ implementation
                { load the value in a register }
                pleftreg := rg.getexplicitregisterint(exprasmlist,R_EDI);
                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;
 
             { 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
               no ranges }
@@ -276,8 +276,8 @@ implementation
                         begin
                           rg.ungetregister(exprasmlist,pleftreg);
                           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 }
                           { still used in previous instruction               }
                           pleftreg := R_EDI;
@@ -337,39 +337,44 @@ implementation
              { Now place the end label }
              emitlab(l);
              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
          else
           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
              begin
                if left.nodetype=ordconstn then
                 begin
                   location.resflags:=F_NE;
                   case right.location.loc of
-                     LOC_REGISTER,
-                     LOC_CREGISTER:
+                    LOC_REGISTER,
+                    LOC_CREGISTER:
                       begin
                          emit_const_reg(A_TEST,S_L,
                            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;
+                  location_release(exprasmlist,right.location);
                 end
                else
                 begin
@@ -386,10 +391,9 @@ implementation
                       { and because it's a small set we need only 5 bits }
                       { but 8 bits are easier to load               }
                       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;
-                      rg.del_reference(exprasmlist,left.location.reference);
+                      location_release(exprasmlist,left.location);
                     end;
                   end;
 
@@ -400,24 +404,25 @@ implementation
                             emit_reg_reg(A_BT,S_L,hr,
                               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
                        { We have to load the value into a register because
                          btl does not accept values only refs or regs (PFV) }
                          hr2:=rg.getregisterint(exprasmlist);
                          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);
                          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;
                   { simply to indicate EDI is deallocated here too (JM) }
                   rg.ungetregisterint(exprasmlist,hr);
@@ -427,7 +432,7 @@ implementation
              end
             else
              begin
-               if right.location.reference.is_immediate then
+               if right.location.loc=LOC_CONSTANT then
                 begin
                   location.resflags:=F_C;
                   getlabel(l);
@@ -457,7 +462,7 @@ implementation
                         { We have to load the value into a register because
                           btl does not accept values only refs or regs (PFV) }
                           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);
                           rg.ungetregisterint(exprasmlist,hr2);
                        end;
@@ -466,46 +471,42 @@ implementation
 {$ifdef CORRECT_SET_IN_FPC}
                           if m_tp in aktmodeswitches then
                             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
                           else
 {$endif CORRECT_SET_IN_FPC}
                             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;
                        emitjmp(C_NA,l);
                      { reset carry flag }
                        emit_none(A_CLC,S_NO);
                        emitjmp(C_NONE,l2);
                        emitlab(l);
-                       rg.del_reference(exprasmlist,left.location.reference);
+                       location_release(exprasmlist,left.location);
                        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
                        btl does not accept values only refs or regs (PFV) }
                        hr2:=rg.getregisterint(exprasmlist);
                        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);
                        rg.ungetregisterint(exprasmlist,hr2);
                     end;
                   end;
                   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
                  but also used if the left side contains higher values > 32 }
                else if left.nodetype=ordconstn then
                 begin
                   location.resflags:=F_NE;
                   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
                else
                 begin
@@ -514,11 +515,11 @@ implementation
                       pleftreg := rg.getexplicitregisterint(exprasmlist,R_EDI);
                       opsize := def2def_opsize(left.resulttype.def,u32bittype.def);
                       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
-                        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
                   else
                     begin
@@ -531,17 +532,15 @@ implementation
                          { any problem (JM)                                         }
                          emit_to_reg32(pleftreg)
                     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.del_reference(exprasmlist,right.location.reference);
+                  location_release(exprasmlist,right.location);
                   { tg.ungetiftemp(exprasmlist,right.location.reference) happens below }
-                  location.loc:=LOC_FLAGS;
                   location.resflags:=F_C;
                 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;
 
 
@@ -781,7 +780,7 @@ implementation
         var
            table : tasmlabel;
            last : TConstExprInt;
-           hr : preference;
+           href : treference;
 
         procedure genitem(t : pcaserecord);
 
@@ -832,13 +831,11 @@ implementation
                     reg8toreg32(hregister));
                 hregister:=reg8toreg32(hregister);
              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
              if not(cs_littlesize in aktlocalswitches) then
              jumpSegment.concat(Taicpu.Op_const(A_ALIGN,S_NO,4));
@@ -863,7 +860,7 @@ implementation
 {$else Delphi}
          dist : dword;
 {$endif Delphi}
-         hr : preference;
+         href : treference;
 
       begin
          getlabel(endlabel);
@@ -934,17 +931,17 @@ implementation
                  if opsize=S_Q then
                    begin
                       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);
                    end
                  else
                    emit_reg_reg(A_MOV,opsize,
                      left.location.register,hregister);
               end;
-            LOC_MEM,LOC_REFERENCE:
+            LOC_CREFERENCE,LOC_REFERENCE:
               begin
-                 rg.del_reference(exprasmlist,left.location.reference);
+                 location_release(exprasmlist,left.location);
                  hregister:=rg.getregisterint(exprasmlist);
                  case opsize of
                     S_B:
@@ -956,15 +953,13 @@ implementation
                  end;
                  if opsize=S_Q then
                    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
                  else
-                   emit_ref_reg(A_MOV,opsize,newreference(
-                     left.location.reference),hregister);
+                   emit_ref_reg(A_MOV,opsize,left.location.reference,hregister);
               end;
             else internalerror(2002);
          end;
@@ -1092,7 +1087,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 341 - 209
compiler/i386/n386util.pas

@@ -27,7 +27,9 @@ unit n386util;
 interface
 
     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_pushfpu(needed : byte;p : tnode) : boolean;
@@ -55,7 +57,7 @@ implementation
     uses
        globtype,globals,systems,verbose,
        cutils,
-       aasm,cpubase,cpuasm,cpuinfo,
+       aasm,cpuasm,cpuinfo,
        symconst,symbase,symdef,symsym,symtable,
 {$ifdef GDB}
        gdb,
@@ -64,7 +66,174 @@ implementation
        ncon,nld,
        pass_1,pass_2,
        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}
                    rg.ungetregisterint(exprasmlist,p.location.register);
                 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.index<>R_NO)
                       ) then
                   begin
-                     rg.del_reference(exprasmlist,p.location.reference);
+                     reference_release(exprasmlist,p.location.reference);
                      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}
                      tg.gettempofsizereference(exprasmlist,href,4);
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
@@ -146,7 +315,7 @@ implementation
        begin
          if needed>=maxfpuregs then
            begin
-             if p.location.loc = LOC_FPU then
+             if p.location.loc = LOC_FPUREGISTER then
                begin
                  emit_to_mem(p.location,p.resulttype.def);
                  maybe_pushfpu:=true;
@@ -194,9 +363,9 @@ implementation
                        (p^.location.reference.index<>R_NO)
                       ) then
                   begin
-                     rg.del_reference(exprasmlist,p^.location.reference);
+                     reference_release(p^.location.reference);
                      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);
                      tg.gettempofsizereference(exprasmlist,href,4);
                      exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,R_EDI,href));
@@ -251,7 +420,7 @@ implementation
            end
          else
            begin
-              reset_reference(p.location.reference);
+              reference_reset(p.location.reference);
               { any reasons why this was moved into the index register ? }
               { normally usage of base register is much better (FK)      }
               p.location.reference.base:=hregister;
@@ -350,7 +519,7 @@ implementation
                { because this may cross a page boundary and you'll get a }
                { sigsegv (JM)                                            }
                emit_push_mem_size(p.location.reference,1);
-               rg.del_reference(exprasmlist,p.location.reference);
+               reference_release(exprasmlist,p.location.reference);
              end;
            end;
          end;
@@ -360,100 +529,103 @@ implementation
                                 para_offset:longint;alignment : longint);
       var
         tempreference : treference;
-        r : preference;
+        r : treference;
         opsize : topsize;
-        op : tasmop;
         hreg : tregister;
         size : longint;
         hlabel : tasmlabel;
+        cgsize : tcgsize;
       begin
         case p.location.loc of
            LOC_REGISTER,
            LOC_CREGISTER:
              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
-                        inc(pushedparasize,4);
-                        if inlined then
+                        if alignment=4 then
                          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
                         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;
-                   R_AL,R_BL,R_CL,R_DL:
+                    OS_16,OS_S16 :
                       begin
                         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;
-                   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;
+               location_release(exprasmlist,p.location);
              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
                 size:=align(tfloatdef(p.resulttype.def).size,alignment);
                 inc(pushedparasize,size);
@@ -464,22 +636,20 @@ implementation
                    (exprasmList.first=exprasmList.last) then
                   exprasmList.concat(Tai_force_line.Create);
 {$endif GDB}
-                r:=new_reference(R_ESP,0);
+
                 { this is the easiest case for inlined !! }
                 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,
-                  def_cgsize(p.resulttype.def),p.location.register,r^);
-                dispose(r);
+                  def_cgsize(p.resulttype.def),p.location.register,r);
              end;
-           LOC_REFERENCE,LOC_MEM:
+           LOC_REFERENCE,LOC_CREFERENCE:
              begin
                 tempreference:=p.location.reference;
-                rg.del_reference(exprasmlist,p.location.reference);
+                reference_release(exprasmlist,p.location.reference);
                 case p.resulttype.def.deftype of
                   enumdef,
                   orddef :
@@ -490,16 +660,12 @@ implementation
                              if inlined then
                                begin
                                  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));
-                                 rg.ungetregisterint(exprasmlist,R_EDI);
-                                 rg.getexplicitregisterint(exprasmlist,R_EDI);
                                  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));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                end
@@ -516,9 +682,8 @@ implementation
                              if inlined then
                                begin
                                  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));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                                end
@@ -541,9 +706,8 @@ implementation
                              if inlined then
                               begin
                                 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));
                                 rg.ungetregisterint(exprasmlist,R_EDI);
                               end
@@ -563,9 +727,8 @@ implementation
                              if inlined then
                                begin
                                   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));
                                   rg.ungetregisterint(exprasmlist,R_EDI);
                                end
@@ -580,9 +743,8 @@ implementation
                             if inlined then
                               begin
                                  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));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
@@ -593,9 +755,8 @@ implementation
                             if inlined then
                               begin
                                  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));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
@@ -612,9 +773,8 @@ implementation
                             if inlined then
                               begin
                                  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));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
@@ -625,9 +785,8 @@ implementation
                             if inlined then
                               begin
                                  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));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
@@ -650,15 +809,13 @@ implementation
                             if inlined then
                               begin
                                  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));
                                  rg.ungetregisterint(exprasmlist,R_EDI);
                               end
                             else
-                              exprasmList.concat(Taicpu.Op_ref(A_PUSH,opsize,
-                                newreference(tempreference)));
+                              exprasmList.concat(Taicpu.Op_ref(A_PUSH,opsize,tempreference));
                         end;
                       end;
                     end;
@@ -670,9 +827,8 @@ implementation
                        if inlined then
                          begin
                             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));
                             rg.ungetregisterint(exprasmlist,R_EDI);
                          end
@@ -707,8 +863,8 @@ implementation
                                 inc(pushedparasize,4);
                                 if inlined then
                                   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
                                 else
                                   emit_push_mem(tempreference);
@@ -720,11 +876,11 @@ implementation
                                     inc(pushedparasize,2);
                                     if inlined then
                                       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
                                     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
@@ -735,9 +891,8 @@ implementation
                            size:=align(p.resulttype.def.size,alignment);
                            inc(pushedparasize,size);
                            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
                        else
                          internalerror(8954);
@@ -762,7 +917,7 @@ implementation
                 emitlab(truelabel);
                 if inlined then
                   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);
                   end
                 else
@@ -771,7 +926,7 @@ implementation
                 emitlab(falselabel);
                 if inlined then
                   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);
                   end
                 else
@@ -801,7 +956,7 @@ implementation
                  end;
                 if inlined then
                   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));
                   end
                 else
@@ -826,13 +981,13 @@ implementation
 {$endif GDB}
                 if inlined then
                   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,
                        p.location.register,r));
                   end
                 else
                    begin
-                      r:=new_reference(R_ESP,0);
+                      reference_reset_base(r,R_ESP,0);
                       exprasmList.concat(Taicpu.Op_reg_ref(
                         A_MOVQ,S_NO,p.location.register,r));
                    end;
@@ -880,11 +1035,11 @@ implementation
                internalerror(234234);
            end
          else
-           if (((p.location.loc=LOC_FPU) and
+           if (((p.location.loc=LOC_FPUREGISTER) and
                 (p.right.registersfpu > p.left.registersfpu)) or
                ((((p.left.registersfpu = 0) and
                   (p.right.registersfpu = 0)) or
-                 (p.location.loc<>LOC_FPU)) and
+                 (p.location.loc<>LOC_FPUREGISTER)) and
                 (p.left.registers32<p.right.registers32))) and
            { the following check is appropriate, because all }
            { 4 registers are rarely used and it is thereby   }
@@ -945,8 +1100,7 @@ implementation
               begin
                  if (source.nodetype=stringconstn) and
                    (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
                    begin
                      emitpushreferenceaddr(dest.location.reference);
@@ -960,17 +1114,15 @@ implementation
               begin
                  if source.nodetype=ordconstn then
                    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
                    begin
                       if (source.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
                         begin
                            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);
-                           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
                       else
                       { not so elegant (goes better with extra register    }
@@ -979,13 +1131,13 @@ implementation
                            { end of the heap! "movw" would be ok too, but  }
                            { I don't think that would be faster (JM)       }
                            rg.getexplicitregisterint(exprasmlist,R_EDI);
-                           emit_ref_reg(A_MOVZX,S_BL,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_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);
                         end;
+                      location_release(exprasmlist,source.location);
                    end;
               end;
          else
@@ -998,7 +1150,7 @@ implementation
       Load a string, handles stringdef and orddef (char) types
     }
       var
-         r : preference;
+         r : treference;
 
       begin
          case p.right.resulttype.def.deftype of
@@ -1006,7 +1158,7 @@ implementation
               begin
                  if (p.right.nodetype=stringconstn) and
                    (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
                    begin
                      emitpushreferenceaddr(p.left.location.reference);
@@ -1018,10 +1170,10 @@ implementation
               end;
             orddef:
               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
                    emit_const_ref(A_MOV,S_B,tordconstnode(p.right).value,r)
@@ -1029,24 +1181,20 @@ implementation
                    begin
                       case p.right.location.loc of
                          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
                               if not(R_EAX in rg.unusedregsint) then
                                 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);
-
                               if not(R_EAX in rg.unusedregsint) then
                                 emit_reg(A_POP,S_L,R_EAX);
-                              rg.del_reference(exprasmlist,p.right.location.reference);
                            end
                          else
                            internalerror(20799);
                         end;
+                        location_release(exprasmlist,p.right.location);
                    end;
               end;
          else
@@ -1065,22 +1213,9 @@ implementation
          remove_non_regvars_from_loc(source.location,regs_to_push);
          { Push them (JM) }
          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);
          emitpushreferenceaddr(dest.location.reference);
          rg.saveregvars(exprasmlist,all_registers);
@@ -1100,22 +1235,9 @@ implementation
          remove_non_regvars_from_loc(source.location,regs_to_push);
          { Push them (JM) }
          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);
          emitpushreferenceaddr(dest.location.reference);
          rg.saveregvars(exprasmlist,all_registers);
@@ -1143,33 +1265,32 @@ implementation
          { nevertheless, this has to be changed, because otherwise the }
          { register is released before it's contents are pushed ->     }
          { problems with the optimizer (JM)                         }
-         rg.del_reference(exprasmlist,p.left.location.reference);
+         reference_release(exprasmlist,p.left.location.reference);
          ungettemp:=false;
          case p.right.location.loc of
             LOC_REGISTER,LOC_CREGISTER:
               begin
                  rg.saveusedregisters(exprasmlist,pushed, all_registers - [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;
-            LOC_REFERENCE,LOC_MEM:
+            LOC_REFERENCE,LOC_CREFERENCE:
               begin
                  rg.saveusedregisters(exprasmlist,pushed, all_registers
                    - [p.right.location.reference.base]
                    - [p.right.location.reference.index]);
                  emit_push_mem(p.right.location.reference);
-                 rg.del_reference(exprasmlist,p.right.location.reference);
                  ungettemp:=true;
               end;
          end;
+         location_release(exprasmlist,p.right.location);
          emitpushreferenceaddr(p.left.location.reference);
-         rg.del_reference(exprasmlist,p.left.location.reference);
+         location_release(exprasmlist,p.left.location);
          rg.saveregvars(exprasmlist,all_registers);
          emitcall('FPC_INTF_ASSIGN');
          maybe_loadself;
          rg.restoreusedregisters(exprasmlist,pushed);
          if ungettemp then
-           tg.ungetiftemp(exprasmlist,p.right.location.reference);
+           location_release(exprasmlist,p.right.location);
       end;
 
 
@@ -1177,7 +1298,18 @@ implementation
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 16 - 5
compiler/i386/ra386.pas

@@ -57,7 +57,7 @@ implementation
 uses
   globtype,globals,systems,verbose,
   symconst,symdef,symsym,
-  cgbase,
+  cpuinfo,cgbase,
   types,cpuasm;
 
 {$define ATTOP}
@@ -247,7 +247,7 @@ begin
                s:=operands[i].opr.symbol;
                so:=operands[i].opr.symofs;
                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.offset:=so;
              end;
@@ -575,14 +575,14 @@ begin
    begin
      case operands[i].opr.typ of
        OPR_CONSTANT :
-         ai.loadconst(i-1,operands[i].opr.val);
+         ai.loadconst(i-1,aword(operands[i].opr.val));
        OPR_REGISTER:
          ai.loadreg(i-1,operands[i].opr.reg);
        OPR_SYMBOL:
          ai.loadsymbol(i-1,operands[i].opr.symbol,operands[i].opr.symofs);
        OPR_REFERENCE:
          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
              begin
                asize:=0;
@@ -631,7 +631,18 @@ end;
 end.
 {
   $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
    * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
 

+ 13 - 2
compiler/i386/ra386att.pas

@@ -1565,7 +1565,7 @@ Begin
             begin
               l:=opr.val;
               opr.typ:=OPR_REFERENCE;
-              reset_reference(opr.Ref);
+              Fillchar(opr.ref,sizeof(treference),0);
               opr.Ref.Offset:=l;
             end;
            BuildReference;
@@ -2135,7 +2135,18 @@ finalization
 end.
 {
   $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
 
   Revision 1.16  2002/01/24 18:25:53  peter

+ 13 - 2
compiler/i386/ra386int.pas

@@ -1541,7 +1541,7 @@ Begin
                begin
                  l:=opr.val;
                  opr.typ:=OPR_REFERENCE;
-                 reset_reference(opr.Ref);
+                 Fillchar(opr.ref,sizeof(treference),0);
                  opr.Ref.Offset:=l;
                end;
               BuildReference;
@@ -1964,7 +1964,18 @@ finalization
 end.
 {
   $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
    * 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;
           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 }
           procedure pushusedregisters(list: taasmoutput;
@@ -179,11 +179,9 @@ unit rgcpu;
       end;
 
 
-    procedure trgcpu.del_reference(list: taasmoutput; const ref : treference);
+    procedure trgcpu.ungetreference(list: taasmoutput; const ref : treference);
 
       begin
-         if ref.is_immediate then
-           exit;
          ungetregisterint(list,ref.base);
          ungetregisterint(list,ref.index);
       end;
@@ -194,7 +192,7 @@ unit rgcpu;
 
       var
         r: tregister;
-        hr: preference;
+        hr: treference;
       begin
         usedinproc:=usedinproc + s;
         for r:=R_EAX to R_EBX do
@@ -224,9 +222,7 @@ unit rgcpu;
                not(r in unusedregsmm) then
               begin
                 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));
                 include(unusedregsmm,r);
                 inc(countunusedregsmm);
@@ -246,7 +242,7 @@ unit rgcpu;
       var
         r : tregister;
 {$ifdef SUPPORT_MMX}
-        hr : preference;
+        hr : treference;
 {$endif SUPPORT_MMX}
       begin
         { restore in reverse order: }
@@ -254,9 +250,7 @@ unit rgcpu;
         for r:=R_MM6 downto R_MM0 do
           if pushed[r].pushed then
             begin
-              new(hr);
-              reset_reference(hr^);
-              hr^.base:=R_ESP;
+              reference_reset_base(hr,R_ESP,0);
               list.concat(Taicpu.Op_ref_reg(
                 A_MOVQ,S_NO,hr,r));
               list.concat(Taicpu.Op_const_reg(
@@ -334,7 +328,18 @@ end.
 
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 18 - 7
compiler/i386/rropt386.pas

@@ -130,7 +130,7 @@ begin
       end;
     A_INC,A_DEC:
       begin
-        reset_reference(tmpref);
+        reference_reset(tmpref);
         tmpref.base := reg1;
         case p.opcode of
           A_INC:
@@ -141,11 +141,11 @@ begin
         p.ops := 2;
         p.opcode := A_LEA;
         p.loadreg(1,reg2);
-        p.loadref(0,newreference(tmpref));
+        p.loadref(0,tmpref);
       end;
     A_SUB,A_ADD:
       begin
-        reset_reference(tmpref);
+        reference_reset(tmpref);
         tmpref.base := reg1;
         case p.oper[0].typ of
           top_const:
@@ -164,16 +164,16 @@ begin
           else internalerror(200010031);
         end;
         p.opcode := A_LEA;
-        p.loadref(0,newreference(tmpref));
+        p.loadref(0,tmpref);
         p.loadreg(1,reg2);
       end;
     A_SHL:
       begin
-        reset_reference(tmpref);
+        reference_reset(tmpref);
         tmpref.index := reg1;
         tmpref.scalefactor := 1 shl p.oper[0].val;
         p.opcode := A_LEA;
-        p.loadref(0,newreference(tmpref));
+        p.loadref(0,tmpref);
         p.loadreg(1,reg2);
       end;
     else internalerror(200010032);
@@ -344,7 +344,18 @@ End.
 
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 40 - 39
compiler/nadd.pas

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

+ 16 - 5
compiler/ncal.pas

@@ -1560,7 +1560,7 @@ implementation
          else
          { not a procedure variable }
            begin
-              location.loc:=LOC_MEM;
+              location.loc:=LOC_CREFERENCE;
 
               { calc the correture value for the register }
               { handle predefined procedures }
@@ -1640,13 +1640,13 @@ implementation
                         if is_widestring(resulttype.def) or
                            is_ansistring(resulttype.def) then
                           begin
-                             location.loc:=LOC_MEM;
+                             location.loc:=LOC_CREFERENCE;
                              registers32:=1;
                           end;
                      end
                    else if (resulttype.def.deftype=floatdef) then
                      begin
-                       location.loc:=LOC_FPU;
+                       location.loc:=LOC_FPUREGISTER;
 {$ifdef m68k}
                        if (cs_fp_emulation in aktmoduleswitches) or
                           (tfloatdef(resulttype.def).typ=s32real) then
@@ -1658,7 +1658,7 @@ implementation
 {$endif not m68k}
                      end
                    else
-                     location.loc:=LOC_MEM;
+                     location.loc:=LOC_CREFERENCE;
                 end;
            end;
          { a fpu can be used in any procedure !! }
@@ -1827,7 +1827,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       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_proc_to_procvar;override;
          procedure second_bool_to_int;override;
+         procedure second_bool_to_bool;override;
          procedure second_ansistring_to_pchar;override;
          procedure second_class_to_intf;override;
          procedure second_char_to_char;override;
+         procedure second_nothing;override;
        end;
 
   implementation
@@ -54,7 +56,7 @@ interface
       ncon,ncal,
       cpubase,cpuinfo,
       pass_2,
-      cgbase,
+      cginfo,cgbase,
       cga,cgobj,cgcpu,
 {$ifdef i386}
       n386util,
@@ -69,33 +71,29 @@ interface
         hr : treference;
 
       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
            st_shortstring :
              begin
                inc(left.location.reference.offset);
-               rg.del_reference(exprasmlist,left.location.reference);
                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;
            st_ansistring :
              begin
                if (left.nodetype=stringconstn) and
                   (str_length(left)=0) then
                 begin
-                  reset_reference(hr);
+                  reference_reset(hr);
                   hr.symbol:=newasmsymbol('FPC_EMPTYCHAR');
                   location.register:=rg.getregisterint(exprasmlist);
-                  cg.a_loadaddress_ref_reg(exprasmlist,hr,location.register);
+                  cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
                 end
                else
                 begin
-                  rg.del_reference(exprasmlist,left.location.reference);
                   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;
            st_longstring:
@@ -108,17 +106,16 @@ interface
                if (left.nodetype=stringconstn) and
                   (str_length(left)=0) then
                 begin
-                  reset_reference(hr);
+                  reference_reset(hr);
                   hr.symbol:=newasmsymbol('FPC_EMPTYCHAR');
                   location.register:=rg.getregisterint(exprasmlist);
-                  cg.a_loadaddress_ref_reg(exprasmlist,hr,location.register);
+                  cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
                 end
                else
                 begin
-                  rg.del_reference(exprasmlist,left.location.reference);
                   location.register:=rg.getregisterint(exprasmlist);
 {$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);
                 end;
              end;
@@ -139,6 +136,7 @@ interface
             (tstringconstnode(left).len+1 >= arrsize) and
             (tstringdef(left.resulttype.def).string_typ=st_shortstring) then
            begin
+             location_copy(location,left.location);
              inc(location.reference.offset);
              exit;
            end
@@ -151,46 +149,43 @@ interface
     procedure tcgtypeconvnode.second_array_to_pointer;
 
       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);
-         cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
-           location.register);
+         cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
       end;
 
 
     procedure tcgtypeconvnode.second_pointer_to_array;
 
       begin
-        clear_location(location);
-        location.loc:=LOC_REFERENCE;
-        reset_reference(location.reference);
+        location_reset(location,LOC_REFERENCE,OS_NO);
         case left.location.loc of
           LOC_REGISTER :
             location.reference.base:=left.location.register;
           LOC_CREGISTER :
             begin
               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);
-            end
-         else
+            end;
+          LOC_REFERENCE,
+          LOC_CREFERENCE :
             begin
-              rg.del_reference(exprasmlist,left.location.reference);
+              location_release(exprasmlist,left.location);
               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);
             end;
+          else
+            internalerror(2002032216);
         end;
       end;
 
 
     procedure tcgtypeconvnode.second_char_to_string;
-
       begin
-         clear_location(location);
-         location.loc:=LOC_MEM;
+         location_reset(location,LOC_REFERENCE,OS_NO);
          case tstringdef(resulttype.def).string_typ of
            st_shortstring :
              begin
@@ -206,25 +201,25 @@ interface
 
     procedure tcgtypeconvnode.second_real_to_real;
       begin
-         clear_location(location);
-         location.loc:=LOC_FPU;
+         location_reset(location,LOC_FPUREGISTER,OS_NO);
          case left.location.loc of
-            LOC_FPU : ;
+            LOC_FPUREGISTER,
             LOC_CFPUREGISTER:
               begin
-                 location:=left.location;
-                 exit;
+                location_copy(location,left.location);
+                exit;
               end;
-            LOC_MEM,
+            LOC_CREFERENCE,
             LOC_REFERENCE:
               begin
+                 location_release(exprasmlist,left.location);
                  location.register := rg.getregisterfpu(exprasmlist);
                  cg.a_loadfpu_ref_reg(exprasmlist,
                    def_cgsize(left.resulttype.def),
                    left.location.reference,location.register);
-                 { we have to free the reference }
-                 rg.del_reference(exprasmlist,left.location.reference);
               end;
+            else
+              internalerror(2002032215);
          end;
       end;
 
@@ -243,16 +238,14 @@ interface
         { method pointer ? }
         if assigned(tcallnode(left).left) then
           begin
-             set_location(location,left.location);
+             location_copy(location,left.location);
           end
         else
           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);
-             cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
-               location.register);
+             cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
           end;
       end;
 
@@ -274,22 +267,21 @@ interface
          { be accepted for var parameters                            }
          if (nf_explizit in flags) 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
-              set_location(location,left.location);
+              location_copy(location,left.location);
               truelabel:=oldtruelabel;
               falselabel:=oldfalselabel;
               exit;
            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 }
          opsize := def_cgsize(left.resulttype.def);
          { size of the destination }
          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) =   }
          { boolean(true) etc... (JM)                                  }
          case newsize of
@@ -318,96 +310,108 @@ interface
              end;
          end;
          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;
          truelabel:=oldtruelabel;
          falselabel:=oldfalselabel;
       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;
       var
          l1 : tasmlabel;
          hr : treference;
       begin
-         clear_location(location);
-         location.loc:=LOC_REGISTER;
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          getlabel(l1);
          case left.location.loc of
             LOC_CREGISTER,LOC_REGISTER:
               location.register:=left.location.register;
-            LOC_MEM,LOC_REFERENCE:
+            LOC_CREFERENCE,LOC_REFERENCE:
               begin
-                rg.del_reference(exprasmlist,left.location.reference);
+                location_release(exprasmlist,left.location);
                 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;
+            else
+              internalerror(2002032214);
          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');
-         cg.a_loadaddress_ref_reg(exprasmlist,hr,location.register);
+         cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
          cg.a_label(exprasmlist,l1);
       end;
 
 
     procedure tcgtypeconvnode.second_class_to_intf;
       var
-         hreg : tregister;
          l1 : tasmlabel;
       begin
+         location_reset(location,LOC_REGISTER,OS_ADDR);
          case left.location.loc of
-            LOC_MEM,
+            LOC_CREFERENCE,
             LOC_REFERENCE:
               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;
             LOC_CREGISTER:
               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;
             LOC_REGISTER:
-              hreg:=left.location.register;
-            else internalerror(121120001);
+              location.register:=left.location.register;
+            else
+              internalerror(121120001);
          end;
          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(
            tobjectdef(left.resulttype.def).implementedinterfaces.ioffsets(
            tobjectdef(left.resulttype.def).implementedinterfaces.searchintf(
-           resulttype.def))^),hreg);
+           resulttype.def))^),location.register);
          cg.a_label(exprasmlist,l1);
-         location.loc:=LOC_REGISTER;
-         location.register:=hreg;
       end;
 
 
@@ -418,13 +422,34 @@ interface
         second_int_to_int;
       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
   ctypeconvnode := tcgtypeconvnode;
 end.
 
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 36 - 45
compiler/ncgcon.pas

@@ -66,8 +66,8 @@ implementation
       globtype,widestr,systems,
       verbose,globals,
       symconst,symdef,aasm,types,
-      cpubase,
-      tgobj;
+      cpuinfo,cpubase,
+      cginfo,cgbase,tgobj,rgobj;
 
 
 {*****************************************************************************
@@ -88,6 +88,7 @@ implementation
          realait : tait;
 
       begin
+        location_reset(location,LOC_CREFERENCE,def_cgsize_ref(resulttype.def));
         lastlabel:=nil;
         realait:=floattype2ait[tfloatdef(resulttype.def).typ];
         { const already used ? }
@@ -141,9 +142,7 @@ implementation
                   end;
                end;
           end;
-        reset_reference(location.reference);
         location.reference.symbol:=lab_real;
-        location.loc:=LOC_MEM;
       end;
 
 {*****************************************************************************
@@ -155,26 +154,9 @@ implementation
          l : tasmlabel;
 
       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;
 
 
@@ -185,9 +167,8 @@ implementation
     procedure tcgpointerconstnode.pass_2;
       begin
          { 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;
 
 
@@ -202,19 +183,24 @@ implementation
          lastlabel   : tasmlabel;
          pc       : pchar;
          same_string : boolean;
+         size : tcgsize;
          l,j,
          i,mylength  : longint;
       begin
          { 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
           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;
           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 ? }
          lastlabel:=nil;
          if not assigned(lab_str) then
@@ -367,9 +353,7 @@ implementation
                    end;
                 end;
            end;
-         reset_reference(location.reference);
          location.reference.symbol:=lab_str;
-         location.loc:=LOC_MEM;
       end;
 
 
@@ -387,11 +371,11 @@ implementation
         { small sets are loaded as constants }
         if tsetdef(resulttype.def).settype=smallset then
          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;
          end;
+        location_reset(location,LOC_CREFERENCE,OS_NO);
         neededtyp:=ait_const_8bit;
         lastlabel:=nil;
         { const already used ? }
@@ -464,9 +448,7 @@ implementation
                   end;
                end;
           end;
-        reset_reference(location.reference);
         location.reference.symbol:=lab_set;
-        location.loc:=LOC_MEM;
       end;
 
 
@@ -476,9 +458,8 @@ implementation
 
     procedure tcgnilnode.pass_2;
       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;
 
 
@@ -491,7 +472,7 @@ implementation
         tmplabel : TAsmLabel;
         i : integer;
       begin
-        location.loc:=LOC_MEM;
+        location_reset(location,LOC_CREFERENCE,OS_NO);
         { label for GUID }
         getdatalabel(tmplabel);
         consts.concat(Tai_label.Create(tmplabel));
@@ -500,7 +481,6 @@ implementation
         consts.concat(Tai_const.Create_16bit(value.D3));
         for i:=Low(value.D4) to High(value.D4) do
           consts.concat(Tai_const.Create_8bit(value.D4[i]));
-        reset_reference(location.reference);
         location.reference.symbol:=tmplabel;
       end;
 
@@ -516,7 +496,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 85 - 116
compiler/ncgflw.pas

@@ -68,12 +68,12 @@ implementation
     uses
       verbose,globals,systems,globtype,
       symconst,symdef,symsym,aasm,types,
-      cgbase,pass_2,
+      cginfo,cgbase,pass_2,
       cpubase,cpuasm,cpuinfo,
       nld,ncon,
       cga,tgobj,rgobj,
       ncgutil,
-      tainst,regvars,cgobj,cgcpu;
+      tainst,regvars,cgobj,cgcpu,cg64f32;
 
 {*****************************************************************************
                          Second_While_RepeatN
@@ -433,26 +433,10 @@ implementation
          {op : tasmop;
          s : topsize;}
          otlabel,oflabel : tasmlabel;
-         r : treference;
-         is_mem,
+         cgsize : tcgsize;
+         hreg : tregister;
          allocated_acc,
          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
          do_jmp;
       begin
@@ -474,110 +458,84 @@ implementation
               getlabel(truelabel);
               getlabel(falselabel);
               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
-                 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}
-                             cg.a_load_const_reg(exprasmlist,OS_8,0,
-                               makereg8(accumulator));
+                    hreg:=makereg8(accumulator);
 {$else i386}
-                             cg.a_load_const_reg(exprasmlist,OS_8,0,
-                               accumulator);
+                    hreg:=accumulator;
 {$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;
               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}
-                          cg.a_reg_alloc(exprasmlist,fpuresultreg);
+                    cg.a_reg_alloc(exprasmlist,fpuresultreg);
 {$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
-                           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
                       else
                         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}
-                    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;
 do_jmp:
@@ -587,14 +545,14 @@ do_jmp:
               if allocated_acc then
                 cg.a_reg_dealloc(exprasmlist,accumulator);
               if allocated_acchigh then
-                cg.a_reg_dealloc(exprasmlist,accumulator);
+                cg.a_reg_dealloc(exprasmlist,accumulatorhigh);
 {$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}
            end
          else
-            cg.a_jmp_cond(exprasmlist,OC_None,aktexitlabel);
+           cg.a_jmp_cond(exprasmlist,OC_None,aktexitlabel);
        end;
 
 
@@ -669,7 +627,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 66 - 48
compiler/ncgmem.pas

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

+ 16 - 5
compiler/ncgutil.pas

@@ -46,7 +46,7 @@ implementation
     types,
     aasm,cgbase,regvars,
     ncon,
-    cpubase,cpuinfo,tgobj,cgobj,cgcpu,cg64f32,rgobj;
+    cpubase,cpuinfo,tgobj,cginfo,cgobj,cgcpu,cg64f32,rgobj;
 
 
 {$ifdef TEMPS_NOT_PUSH}
@@ -185,14 +185,14 @@ implementation
                 begin
                    opsize:=def_cgsize(p.resulttype.def);
                    case p.location.loc of
-                     LOC_CREGISTER,LOC_REGISTER,LOC_MEM,LOC_REFERENCE :
+                     LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
                        begin
                          if (p.location.loc = LOC_CREGISTER) then
                            load_regvar_reg(exprasmlist,p.location.register);
                          cg.a_cmp_const_loc_label(exprasmlist,opsize,OC_NE,
                            0,p.location,truelabel);
                          { !!! 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);
                        end;
                      LOC_FLAGS :
@@ -213,7 +213,18 @@ end.
 
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
@@ -240,4 +251,4 @@ end.
       tordef's to int64)
     * maketojumpbool() is now processor independent (in ncgutil)
     * getregister32 is now called getregisterint
-}
+}

+ 39 - 32
compiler/ncnv.pas

@@ -94,12 +94,13 @@ interface
           procedure second_proc_to_procvar;virtual;abstract;
           procedure second_bool_to_int;virtual;abstract;
           procedure second_int_to_bool;virtual;abstract;
+          procedure second_bool_to_bool;virtual;abstract;
           procedure second_load_smallset;virtual;abstract;
           procedure second_ansistring_to_pchar;virtual;abstract;
           procedure second_pchar_to_string;virtual;abstract;
           procedure second_class_to_intf;virtual;abstract;
           procedure second_char_to_char;virtual;abstract;
-          procedure second_nothing; virtual;
+          procedure second_nothing; virtual;abstract;
 
        end;
        ttypeconvnodeclass = class of ttypeconvnode;
@@ -135,7 +136,7 @@ implementation
       cutils,verbose,globals,widestr,
       symconst,symdef,symsym,symtable,
       ncon,ncal,nset,nadd,ninl,nmem,
-      cgbase,
+      cginfo,cgbase,
       htypechk,pass_1,cpubase,cpuinfo;
 
 
@@ -606,8 +607,6 @@ implementation
             exit;
           end;
         result := nil;
-        { a chararray with 1 element is the same as a char }
-        set_location(location,left.location);
       end;
 
 
@@ -823,21 +822,19 @@ implementation
                ((tsetdef(resulttype.def).settype = smallset) xor
                 (tsetdef(left.resulttype.def).settype = smallset)) then
               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
-                  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
-                  convtype := tc_normal_2_smallset;
+                 convtype := tc_normal_2_smallset;
                 exit;
               end
             else
@@ -1098,8 +1095,12 @@ implementation
             left:=hp;
           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
             left.resulttype:=resulttype;
             result:=left;
@@ -1185,14 +1186,14 @@ implementation
 
       begin
          first_char_to_string:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CREFERENCE;
       end;
 
 
     function ttypeconvnode.first_nothing : tnode;
       begin
          first_nothing:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CREFERENCE;
       end;
 
 
@@ -1224,7 +1225,7 @@ implementation
          if registersfpu<1 then
           registersfpu:=1;
 {$endif not m68k}
-        location.loc:=LOC_FPU;
+        location.loc:=LOC_FPUREGISTER;
       end;
 
 
@@ -1240,7 +1241,7 @@ implementation
 {$endif}
          if registersfpu<1 then
            registersfpu:=1;
-         location.loc:=LOC_FPU;
+         location.loc:=LOC_FPUREGISTER;
       end;
 
 
@@ -1270,7 +1271,7 @@ implementation
          be accepted for var parameters }
          if (nf_explizit in flags) 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;
          { when converting to 64bit, first convert to a 32bit int and then   }
          { convert to a 64bit int (only necessary for 32bit processors) (JM) }
@@ -1297,7 +1298,7 @@ implementation
          be accepted for var parameters }
          if (nf_explizit in flags) 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;
          location.loc:=LOC_REGISTER;
          { need if bool to bool !!
@@ -1454,7 +1455,7 @@ implementation
  {$ifdef SUPPORT_MMX}
         registersmmx:=left.registersmmx;
  {$endif}
-        set_location(location,left.location);
+        location.loc:=left.location.loc;
 
         if nf_explizit in flags then
          begin
@@ -1490,11 +1491,6 @@ implementation
       end;
 
 
-    procedure ttypeconvnode.second_nothing;
-      begin
-      end;
-
-
 {*****************************************************************************
                                 TISNODE
 *****************************************************************************}
@@ -1688,7 +1684,18 @@ begin
 end.
 {
   $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
 
   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;
       begin
          result:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CREFERENCE;
          { needs to be loaded into an FPU register }
          registersfpu:=1;
       end;
@@ -388,7 +388,10 @@ implementation
     function tordconstnode.pass_1 : tnode;
       begin
          result:=nil;
-         location.loc:=LOC_MEM;
+         if is_64bitint(resulttype.def) then
+          location.loc:=LOC_CREFERENCE
+         else
+          location.loc:=LOC_CONSTANT;
       end;
 
     function tordconstnode.docompare(p: tnode): boolean;
@@ -431,7 +434,7 @@ implementation
     function tpointerconstnode.pass_1 : tnode;
       begin
          result:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CONSTANT;
       end;
 
     function tpointerconstnode.docompare(p: tnode): boolean;
@@ -543,7 +546,7 @@ implementation
     function tstringconstnode.pass_1 : tnode;
       begin
         result:=nil;
-        location.loc:=LOC_MEM;
+        location.loc:=LOC_CREFERENCE;
       end;
 
     function tstringconstnode.getpcharcopy : pchar;
@@ -622,7 +625,10 @@ implementation
     function tsetconstnode.pass_1 : tnode;
       begin
          result:=nil;
-         location.loc:=LOC_MEM;
+         if tsetdef(resulttype.def).settype=smallset then
+          location.loc:=LOC_CONSTANT
+         else
+          location.loc:=LOC_CREFERENCE;
       end;
 
     function tsetconstnode.docompare(p: tnode): boolean;
@@ -662,7 +668,7 @@ implementation
     function tnilnode.pass_1 : tnode;
       begin
         result:=nil;
-        location.loc:=LOC_MEM;
+        location.loc:=LOC_CONSTANT;
       end;
 
 {*****************************************************************************
@@ -696,7 +702,7 @@ implementation
     function tguidconstnode.pass_1 : tnode;
       begin
          result:=nil;
-         location.loc:=LOC_MEM;
+         location.loc:=LOC_CREFERENCE;
       end;
 
     function tguidconstnode.docompare(p: tnode): boolean;
@@ -718,7 +724,18 @@ begin
 end.
 {
   $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
 
   Revision 1.24  2001/10/20 19:28:38  peter

+ 22 - 11
compiler/ninl.pas

@@ -1993,7 +1993,7 @@ implementation
               else
                 firstpass(left);
               left_max;
-              set_location(location,left.location);
+              location.loc:=left.location.loc;
            end;
          inc(parsing_para_level);
          { intern const should already be handled }
@@ -2162,7 +2162,7 @@ implementation
                       begin
                          { need we an additional register ? }
                          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
                            inc(registers32);
 
@@ -2219,7 +2219,7 @@ implementation
 
          in_cos_extended:
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
@@ -2229,7 +2229,7 @@ implementation
 
          in_sin_extended:
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
@@ -2239,7 +2239,7 @@ implementation
 
          in_arctan_extended:
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,2);
 {$ifdef SUPPORT_MMX}
@@ -2249,13 +2249,13 @@ implementation
 
          in_pi:
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registersfpu:=1;
            end;
 
          in_abs_extended:
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
@@ -2265,7 +2265,7 @@ implementation
 
          in_sqr_extended:
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
@@ -2275,7 +2275,7 @@ implementation
 
          in_sqrt_extended:
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,1);
 {$ifdef SUPPORT_MMX}
@@ -2285,7 +2285,7 @@ implementation
 
          in_ln_extended:
            begin
-             location.loc:=LOC_FPU;
+             location.loc:=LOC_FPUREGISTER;
              registers32:=left.registers32;
              registersfpu:=max(left.registersfpu,2);
 {$ifdef SUPPORT_MMX}
@@ -2341,7 +2341,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 26 - 11
compiler/nld.pas

@@ -124,7 +124,7 @@ implementation
       cutils,verbose,globtype,globals,systems,
       symtable,types,
       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 }
                       if assigned(procinfo) then
                         procinfo^.no_fast_exit:=true;
-                      location.loc:=LOC_MEM;
+                      location.loc:=LOC_CREFERENCE;
                    end;
               end;
             varsym :
@@ -331,7 +331,7 @@ implementation
                         end;
                      end;
                    if (tvarsym(symtableentry).varspez=vs_const) then
-                     location.loc:=LOC_MEM;
+                     location.loc:=LOC_CREFERENCE;
                    { we need a register for call by reference parameters }
                    if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
                       ((tvarsym(symtableentry).varspez=vs_const) and
@@ -604,7 +604,7 @@ implementation
       begin
         firstpass(left);
         firstpass(right);
-        location.loc := LOC_MEM;
+        location.loc := LOC_CREFERENCE;
         calcregisters(self,0,0,0);
         result:=nil;
       end;
@@ -711,7 +711,7 @@ implementation
       begin
         dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
         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
          begin
            hp:=self;
@@ -784,14 +784,19 @@ implementation
                end;
               chp.flags := chp.flags+orgflags;
               include(chp.flags,nf_cargswap);
-              chp.location.loc:=LOC_MEM;
+              chp.location.loc:=LOC_CREFERENCE;
               calcregisters(chp,0,0,0);
               chp.resulttype:=htype;
               result:=chp;
               exit;
             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);
       end;
 
@@ -879,7 +884,7 @@ implementation
     function trttinode.pass_1 : tnode;
       begin
         result:=nil;
-        location.loc:=LOC_MEM;
+        location.loc:=LOC_CREFERENCE;
       end;
 
 
@@ -894,8 +899,7 @@ implementation
 
     procedure trttinode.pass_2;
       begin
-        reset_reference(location.reference);
-        location.loc:=LOC_MEM;
+        location_reset(location,LOC_CREFERENCE,OS_NO);
         location.reference.symbol:=rttidef.get_rtti_label(rttitype);
       end;
 
@@ -911,7 +915,18 @@ begin
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 14 - 3
compiler/nmat.pas

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

+ 21 - 10
compiler/nmem.pas

@@ -115,9 +115,9 @@ interface
        tselfnodeclass = class of tselfnode;
 
        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;
           destructor destroy;override;
           function getcopy : tnode;override;
@@ -551,7 +551,7 @@ implementation
           end;
 
          { 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
              aktfilepos:=left.fileinfo;
              CGMessage(cg_e_illegal_expression);
@@ -714,10 +714,10 @@ implementation
            end
          else
            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);
-              set_location(location,left.location);
+              location.loc:=left.location.loc;
            end;
       end;
 
@@ -885,7 +885,7 @@ implementation
          if left.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
            location.loc:=LOC_REFERENCE
          else
-           location.loc:=LOC_MEM;
+           location.loc:=LOC_CREFERENCE;
       end;
 
 
@@ -927,7 +927,7 @@ implementation
          inherited create(withn,l,r);
          withsymtable:=symtable;
          tablecount:=count;
-         withreference:=nil;
+         FillChar(withreference,sizeof(withreference),0);
          set_file_line(l);
       end;
 
@@ -1040,7 +1040,18 @@ begin
 end.
 {
   $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 some other procvar related bugs (all related to accepting procvar
         constructs with either too many or too little parameters)

+ 13 - 2
compiler/nopt.pas

@@ -137,7 +137,7 @@ end;
 function taddsstringoptnode.pass_1: tnode;
 begin
   pass_1 := nil;
-  location.loc := LOC_MEM;
+  location.loc := LOC_CREFERENCE;
   calcregisters(self,0,0,0);
   { here we call STRCONCAT or STRCMP or STRCOPY }
   procinfo^.flags:=procinfo^.flags or pi_do_call;
@@ -278,7 +278,18 @@ end.
 
 {
   $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
 
   Revision 1.4  2001/08/26 13:36:43  florian

+ 30 - 21
compiler/nset.pas

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

+ 26 - 2
compiler/pass_2.pas

@@ -53,7 +53,7 @@ implementation
      globtype,systems,verbose,
      cclasses,globals,
      symconst,symbase,symtype,symsym,aasm,
-     pass_1,cgbase,regvars,nflw,rgobj;
+     pass_1,cpubase,cgbase,regvars,nflw,rgobj;
 
 {*****************************************************************************
                               SecondPass
@@ -163,6 +163,9 @@ implementation
 {$ifdef TEMPREGDEBUG}
          prevp : pptree;
 {$endif TEMPREGDEBUG}
+{$ifdef EXTDEBUG}
+         oldloc : tloc;
+{$endif EXTDEBUG}
       begin
          if not(nf_error in p.flags) then
           begin
@@ -178,6 +181,10 @@ implementation
             aktfilepos:=p.fileinfo;
             aktlocalswitches:=p.localswitches;
             codegenerror:=false;
+{$ifdef EXTDEBUG}
+            oldloc:=p.location.loc;
+            p.location.loc:=LOC_INVALID;
+{$endif EXTDEBUG}
 {$ifdef logsecondpass}
             logsecond(p.nodetype,true);
 {$endif logsecondpass}
@@ -185,6 +192,12 @@ implementation
 {$ifdef logsecondpass}
             logsecond(p.nodetype,false);
 {$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
               include(p.flags,nf_error);
 
@@ -311,7 +324,18 @@ implementation
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 57 - 48
compiler/pmodules.pas

@@ -214,10 +214,10 @@ implementation
         dataSegment.concatlist(ResourceStringTables);
         ResourceStringTables.free;
       end;
-      
-      
-      
-      
+
+
+
+
 
     procedure InsertInitFinalTable;
       var
@@ -675,7 +675,7 @@ implementation
            procdef:=aktprocdef;
          end;
       end;
-      
+
     procedure insertLocalThreadvarsTablesTable;
       var
         hp : tused_unit;
@@ -703,39 +703,37 @@ implementation
           dataSegment.concat(Tai_cut.Create);
         dataSegment.concatlist(ltvTables);
         ltvTables.free;
-	if count > 0 then
-  	  have_local_threadvars := true;
+        if count > 0 then
+          have_local_threadvars := true;
       end;
-      
-      
-      
+
+
+
     var ltvTable : taasmoutput;
-      
+
     procedure addToLocalThreadvarTab(p:tnamedindexitem);
       var
-        vs   : tvarsym;
-        s    : string;
-	asym : tasmsymbol;
+        asym : tasmsymbol;
       begin
         with tvarsym(p) do
          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;
-      
+
 
 
     procedure proc_unit;
@@ -752,7 +750,7 @@ implementation
           ((resourcestringlist=nil) or resourcestringList.empty)
         );
       end;
-      
+
       var
          main_file: tinputfile;
          st     : tsymtable;
@@ -1013,20 +1011,20 @@ implementation
                 codeSegment.concat(Tai_cut.Create);
               genimplicitunitfinal(codesegment);
            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 }
          consume(_POINT);
@@ -1301,7 +1299,7 @@ implementation
             aktprocdef.aliasnames.insert('PASCALMAIN');
             aktprocdef.aliasnames.insert(target_info.cprefix+'main');
           end;
-	 insertLocalThreadvarsTablesTable;
+         insertLocalThreadvarsTablesTable;
          compile_proc_body(true,false);
 
          { Add symbol to the exports section for win32 so smartlinking a
@@ -1373,13 +1371,13 @@ implementation
 
          if islibrary or
             (target_info.target=target_i386_WIN32) or
-	    (target_info.target=target_i386_NETWARE) then
+            (target_info.target=target_i386_NETWARE) then
            exportlib.generatelib;
 
 
          { insert heap }
          insertResourceTablesTable;
-	 
+
          insertinitfinaltable;
          insertheap;
          inserttargetspecific;
@@ -1430,7 +1428,18 @@ implementation
 end.
 {
   $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
 
   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);
   end;
   opr.typ := OPR_REFERENCE;
-  reset_reference(opr.ref);
+  Fillchar(opr.ref,sizeof(treference),0);
 end;
 
 
@@ -1585,7 +1585,18 @@ end;
 end.
 {
   $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
       routine doesn't have locals.
 

+ 15 - 4
compiler/regvars.pas

@@ -30,7 +30,7 @@ interface
        aasm,
        node,
        symsym,
-       cpubase, tgobj, rgobj;
+       cpubase, cginfo, tgobj, rgobj;
 
     procedure assign_regvars(p: tnode);
     procedure load_regvars(asml: TAAsmoutput; p: tnode);
@@ -284,7 +284,7 @@ implementation
                 { possible that it's been modified  (JM)                  }
                 if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
                   begin
-                    reset_reference(hr);
+                    reference_reset(hr);
                     if vsym.owner.symtabletype in [inlinelocalsymtable,localsymtable] then
                       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
         begin
           asml.concat(Tairegalloc.alloc(makereg32(vsym.reg)));
-          reset_reference(hr);
+          reference_reset(hr);
           if vsym.owner.symtabletype in [inlinelocalsymtable,localsymtable] then
             hr.offset:=-vsym.address+vsym.owner.address_fixup
           else hr.offset:=vsym.address+vsym.owner.address_fixup;
@@ -459,7 +459,18 @@ end.
 
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 116 - 42
compiler/rgobj.pas

@@ -32,7 +32,7 @@ unit rgobj;
       cpuinfo,
       cpuasm,
       tainst,
-      cclasses,globtype,cgbase,aasm,node;
+      cclasses,globtype,cginfo,cgbase,aasm,node;
 
     type
        regvar_longintarray = array[firstreg..lastreg] of longint;
@@ -97,18 +97,12 @@ unit rgobj;
           { deallocate any kind of register }
           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) }
           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) }
           procedure saveregvars(list: taasmoutput; const s: tregisterset);
 
@@ -154,6 +148,19 @@ unit rgobj;
      var
        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
 
@@ -390,7 +397,7 @@ unit rgobj;
       end;
 
 
-    procedure trgobj.del_reference(list : taasmoutput; const ref : treference);
+    procedure trgobj.ungetreference(list : taasmoutput; const ref : treference);
 
       begin
          ungetregister(list,ref.base);
@@ -398,27 +405,6 @@ unit rgobj;
       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);
       var
         r: tregister;
@@ -534,9 +520,7 @@ unit rgobj;
             begin
               if saved[r].ofs <> reg_not_saved then
                 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_loadmm_ref_reg(list,hr,r);
                   if not (r in unusedregsmm) then
@@ -558,9 +542,7 @@ unit rgobj;
             begin
               if saved[r].ofs <> reg_not_saved then
                 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_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
                   if not (r in unusedregsfpu) then
@@ -581,9 +563,7 @@ unit rgobj;
           begin
             if saved[r].ofs <> reg_not_saved then
               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_load_ref_reg(list,OS_INT,hr,r);
                 if not (r in unusedregsint) then
@@ -773,13 +753,107 @@ unit rgobj;
         state := nil;
       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
   rg.free;
 end.
 
 {
   $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
       declaration of a method (only 1.0.x detected this)
 

+ 18 - 8
compiler/symdef.pas

@@ -1753,10 +1753,9 @@ implementation
         u64bit    : stabstring := strpnew('-32;');
         s64bit    : stabstring := strpnew('-31;');
 {$endif not Use_integer_types_for_boolean}
-         { u32bit : stabstring := strpnew('r'+
-              s32bittype^.numberstring+';0;-1;'); }
+         {u32bit : stabstring := tstoreddef(s32bittype.def).numberstring+';0;-1;'); }
         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;
 {$endif GDB}
@@ -1775,8 +1774,8 @@ implementation
         begin
           write_rtti_name;
           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;
 
       begin
@@ -2643,7 +2642,7 @@ implementation
         cachedsize := elesize;
         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
               integer overflow for elesize=1 !! PM }
             (($7fffffff div cachedsize + (cachedsize -1)) < (int64(highrange) - int64(lowrange)))
@@ -2652,7 +2651,7 @@ implementation
             Message(sym_e_segment_too_large);
             size := 4
           End
-        Else size:=(highrange-lowrange+1)*cachedsize;
+        Else size:=longint((highrange-lowrange+1)*cachedsize);
       end;
 
 
@@ -5420,7 +5419,18 @@ implementation
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)

+ 35 - 33
compiler/tainst.pas

@@ -49,9 +49,9 @@ Type
     Constructor Create(op : tasmop);
     Destructor Destroy;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 loadref(opidx:longint;p:preference);
+    procedure loadref(opidx:longint;const r:treference);
     procedure loadreg(opidx:longint;r:tregister);
     procedure loadoper(opidx:longint;o:toper);
     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
         if opidx>=ops then
          ops:=opidx+1;
         with oper[opidx] do
          begin
            if typ=top_ref then
-            disposereference(ref);
+            dispose(ref);
            val:=l;
            typ:=top_const;
          end;
@@ -145,7 +145,7 @@ implementation
         with oper[opidx] do
          begin
            if typ=top_ref then
-            disposereference(ref);
+            dispose(ref);
            sym:=s;
            symofs:=sofs;
            typ:=top_symbol;
@@ -157,37 +157,25 @@ implementation
 
 
 
-    procedure tainstruction.loadref(opidx:longint;p:preference);
+    procedure tainstruction.loadref(opidx:longint;const r:treference);
       begin
         if opidx>=ops then
          ops:=opidx+1;
         with oper[opidx] do
          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}
-               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}
-               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;
 
@@ -200,7 +188,7 @@ implementation
         with oper[opidx] do
          begin
            if typ=top_ref then
-            disposereference(ref);
+            dispose(ref);
            reg:=r;
            typ:=top_reg;
          end;
@@ -213,11 +201,14 @@ implementation
         if opidx>=ops then
          ops:=opidx+1;
         if oper[opidx].typ=top_ref then
-          disposereference(oper[opidx].ref);
+         dispose(oper[opidx].ref);
         oper[opidx]:=o;
         { copy also the reference }
         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;
 
 
@@ -251,7 +242,18 @@ end.
 
 {
   $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
 
   Revision 1.2  2001/12/29 15:28:57  jonas

+ 21 - 12
compiler/targets/t_win32.pas

@@ -43,7 +43,7 @@ implementation
 {$ifdef GDB}
        gdb,
 {$endif}
-       import,export,link;
+       import,export,link,rgobj;
 
   type
     timportlibwin32=class(timportlib)
@@ -207,12 +207,14 @@ implementation
     procedure timportlibwin32.generatesmartlib;
       var
          hp1 : timportlist;
+{$ifdef GDB}
          importname : string;
          suffix : integer;
+{$endif GDB}
          hp2 : timported_item;
          lhead,lname,lcode,
          lidata4,lidata5 : tasmlabel;
-         r : preference;
+         href : treference;
       begin
          if (aktoutputformat<>as_i386_asw) and
             (aktoutputformat<>as_i386_pecoff) then
@@ -260,9 +262,7 @@ implementation
                  if not hp2.is_var then
                   begin
                     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
                       importsection to reduce the amount of .s files (PFV) }
                     importsSection.concat(Tai_section.Create(sec_code));
@@ -271,7 +271,7 @@ implementation
                      importsSection.concat(Tai_stab_function_name.Create(nil));
 {$EndIf GDB}
                     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));
                   end;
                  { create head link }
@@ -352,7 +352,7 @@ implementation
          l1,l2,l3,l4 : tasmlabel;
          importname : string;
          suffix : integer;
-         r : preference;
+         href : treference;
       begin
          if (aktoutputformat<>as_i386_asw) and
             (aktoutputformat<>as_i386_pecoff) then
@@ -411,13 +411,11 @@ implementation
                     begin
                       getlabel(l4);
                       { create indirect jump }
-                      new(r);
-                      reset_reference(r^);
-                      r^.symbol:=l4;
+                      reference_reset_symbol(href,l4,0);
                       { place jump in codesegment }
                       importsSection.concat(Tai_section.Create(sec_code));
                       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));
                       { add jump field to importsection }
                       importsSection.concat(Tai_section.Create(sec_idata5));
@@ -1606,7 +1604,18 @@ initialization
 end.
 {
   $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
 
   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);
       begin
          { do a reset, because the reference isn't used }
-         reset_reference(ref);
+         FillChar(ref,sizeof(treference),0);
          ref.offset:=gettempofsize(list,l);
          ref.base:=procinfo^.framepointer;
       end;
@@ -348,7 +348,7 @@ unit tgobj;
     procedure ttgobj.gettempofsizereferencepersistant(list: taasmoutput; l : longint;var ref : treference);
       begin
          { do a reset, because the reference isn't used }
-         reset_reference(ref);
+         FillChar(ref,sizeof(treference),0);
          ref.offset:=gettempofsizepersistant(list,l);
          ref.base:=procinfo^.framepointer;
       end;
@@ -359,7 +359,7 @@ unit tgobj;
          foundslot,tl : ptemprecord;
       begin
          { do a reset, because the reference isn't used }
-         reset_reference(ref);
+         FillChar(ref,sizeof(treference),0);
          ref.base:=procinfo^.framepointer;
          { Reuse old slot ? }
          foundslot:=nil;
@@ -642,7 +642,18 @@ finalization
 end.
 {
   $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
     * register allocation is now handled by a class and is mostly processor
       independent (+rgobj.pas and i386/rgcpu.pas)
@@ -693,4 +704,4 @@ end.
   Revision 1.1  1999/08/02 17:14:12  florian
     + changed the temp. generator to an object
 
-}
+}

+ 14 - 3
compiler/types.pas

@@ -48,7 +48,7 @@ interface
     function is_ordinal(def : tdef) : boolean;
 
     { 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 }
     function range_to_basetype(low,high:TConstExprInt):tbasetype;
@@ -560,7 +560,7 @@ implementation
 
 
     { returns the min. value of the type }
-    function get_min_value(def : tdef) : longint;
+    function get_min_value(def : tdef) : TConstExprInt;
       begin
          case def.deftype of
            orddef:
@@ -1955,7 +1955,18 @@ implementation
 end.
 {
   $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 some other procvar related bugs (all related to accepting procvar
         constructs with either too many or too little parameters)

Неке датотеке нису приказане због велике количине промена