Explorar o código

* 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 %!s(int64=23) %!d(string=hai) anos
pai
achega
5b242f7741
Modificáronse 60 ficheiros con 5103 adicións e 5023 borrados
  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

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 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)

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 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)

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 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)

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio