Pārlūkot izejas kodu

+ support for handling OS_128/OS_S128 on 64 Bit CPUs as far as needed for method pointers in registers

git-svn-id: trunk@22344 -
florian 13 gadi atpakaļ
vecāks
revīzija
7361e19799

+ 16 - 1
compiler/aasmtai.pas

@@ -738,6 +738,9 @@ interface
            varsym : tsym;
            varsym : tsym;
            constructor create(sym : tsym;loc : tregister);
            constructor create(sym : tsym;loc : tregister);
            constructor create64(sym : tsym;loc,lochi : tregister);
            constructor create64(sym : tsym;loc,lochi : tregister);
+{$ifdef cpu64bitalu}
+           constructor create128(sym : tsym;loc,lochi : tregister);
+{$endif cpu64bitalu}
            constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
            constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
            procedure ppuwrite(ppufile:tcompilerppufile);override;
            procedure ppuwrite(ppufile:tcompilerppufile);override;
            procedure buildderefimpl;override;
            procedure buildderefimpl;override;
@@ -917,7 +920,18 @@ implementation
       end;
       end;
 
 
 
 
-    constructor tai_varloc.create64(sym: tsym; loc: tregister;lochi : tregister);
+    constructor tai_varloc.create64(sym: tsym; loc, lochi: tregister);
+      begin
+        inherited Create;
+        typ:=ait_varloc;
+        newlocation:=loc;
+        newlocationhi:=lochi;
+        varsym:=sym;
+      end;
+
+
+{$ifdef cpu64bitalu}
+    constructor tai_varloc.create128(sym: tsym; loc, lochi: tregister);
       begin
       begin
         inherited Create;
         inherited Create;
         typ:=ait_varloc;
         typ:=ait_varloc;
@@ -925,6 +939,7 @@ implementation
         newlocationhi:=lochi;
         newlocationhi:=lochi;
         varsym:=sym;
         varsym:=sym;
       end;
       end;
+{$endif cpu64bitalu}
 
 
 
 
     constructor tai_varloc.ppuload(t: taitype; ppufile: tcompilerppufile);
     constructor tai_varloc.ppuload(t: taitype; ppufile: tcompilerppufile);

+ 1 - 0
compiler/alpha/cgcpu.pas

@@ -162,6 +162,7 @@ end;
 procedure create_codegen;
 procedure create_codegen;
   begin
   begin
     cg:=tcgalpha.create;
     cg:=tcgalpha.create;
+    cg128:=tcg128.create;
   end;
   end;
 
 
 end.
 end.

+ 0 - 3
compiler/cg64f32.pas

@@ -61,7 +61,6 @@ unit cg64f32;
         procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);override;
         procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);override;
 
 
 
 
-
         procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
         procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
         procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
         procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
         procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
         procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
@@ -366,8 +365,6 @@ unit cg64f32;
       end;
       end;
 
 
 
 
-
-
     procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
     procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
 
 
       var
       var

+ 8 - 0
compiler/cgbase.pas

@@ -209,6 +209,9 @@ interface
       { A type to store register locations for 64 Bit values. }
       { A type to store register locations for 64 Bit values. }
 {$ifdef cpu64bitalu}
 {$ifdef cpu64bitalu}
       tregister64 = tregister;
       tregister64 = tregister;
+      tregister128 = record
+         reglo,reghi : tregister;
+      end;
 {$else cpu64bitalu}
 {$else cpu64bitalu}
       tregister64 = record
       tregister64 = record
          reglo,reghi : tregister;
          reglo,reghi : tregister;
@@ -594,6 +597,11 @@ implementation
           OS_NO,OS_8,OS_16,OS_NO,OS_32,OS_NO,OS_NO,OS_NO,OS_64
           OS_NO,OS_8,OS_16,OS_NO,OS_32,OS_NO,OS_NO,OS_NO,OS_64
         );
         );
       begin
       begin
+{$ifdef cpu64bitalu}
+        if a=16 then
+          result:=OS_128
+        else
+{$endif cpu64bitalu}
         if a>8 then
         if a>8 then
           result:=OS_NO
           result:=OS_NO
         else
         else

+ 227 - 7
compiler/cgobj.pas

@@ -458,7 +458,25 @@ unit cgobj;
           function g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister;virtual;
           function g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister;virtual;
        end;
        end;
 
 
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+    {  This class implements an abstract code generator class
+       for 128 Bit operations, it applies currently only to 64 Bit CPUs and supports only simple operations
+    }
+    tcg128 = class
+        procedure a_load128_reg_reg(list : TAsmList;regsrc,regdst : tregister128);virtual;
+        procedure a_load128_reg_ref(list : TAsmList;reg : tregister128;const ref : treference);virtual;
+        procedure a_load128_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);virtual;
+        procedure a_load128_reg_loc(list : TAsmList;reg : tregister128;const l : tlocation);virtual;
+
+        procedure a_load128_loc_cgpara(list : TAsmList;const l : tlocation;const paraloc : TCGPara);virtual;
+        procedure a_load128_ref_cgpara(list: TAsmList; const r: treference;const paraloc: tcgpara);
+        procedure a_load128_reg_cgpara(list: TAsmList; reg: tregister128;const paraloc: tcgpara);
+    end;
+
+    { Creates a tregister128 record from 2 64 Bit registers. }
+    function joinreg128(reglo,reghi : tregister) : tregister128;
+
+{$else cpu64bitalu}
     {# @abstract(Abstract code generator for 64 Bit operations)
     {# @abstract(Abstract code generator for 64 Bit operations)
        This class implements an abstract code generator class
        This class implements an abstract code generator class
        for 64 Bit operations.
        for 64 Bit operations.
@@ -474,7 +492,6 @@ unit cgobj;
         procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);virtual;abstract;
         procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);virtual;abstract;
         procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);virtual;abstract;
         procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);virtual;abstract;
 
 
-
         procedure a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);virtual;abstract;
         procedure a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);virtual;abstract;
         procedure a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);virtual;abstract;
         procedure a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);virtual;abstract;
         procedure a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);virtual;abstract;
         procedure a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);virtual;abstract;
@@ -537,10 +554,13 @@ unit cgobj;
 {$endif cpu64bitalu}
 {$endif cpu64bitalu}
 
 
     var
     var
-       {# Main code generator class }
+       { Main code generator class }
        cg : tcg;
        cg : tcg;
-{$ifndef cpu64bitalu}
-       {# Code generator class for all operations working with 64-Bit operands }
+{$ifdef cpu64bitalu}
+       { Code generator class for all operations working with 128-Bit operands }
+       cg128 : tcg128;
+{$else cpu64bitalu}
+       { Code generator class for all operations working with 64-Bit operands }
        cg64 : tcg64;
        cg64 : tcg64;
 {$endif cpu64bitalu}
 {$endif cpu64bitalu}
 
 
@@ -556,7 +576,6 @@ implementation
        tgobj,cutils,procinfo,
        tgobj,cutils,procinfo,
        ncgrtti;
        ncgrtti;
 
 
-
 {*****************************************************************************
 {*****************************************************************************
                             basic functionallity
                             basic functionallity
 ******************************************************************************}
 ******************************************************************************}
@@ -2508,6 +2527,204 @@ implementation
             internalerror(2006082211);
             internalerror(2006082211);
         end;
         end;
       end;
       end;
+{$else cpu64bitalu}
+
+    function joinreg128(reglo, reghi: tregister): tregister128;
+      begin
+        result.reglo:=reglo;
+        result.reghi:=reghi;
+      end;
+
+
+    procedure splitparaloc128(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
+      var
+        paraloclo,
+        paralochi : pcgparalocation;
+      begin
+        if not(cgpara.size in [OS_128,OS_S128]) then
+          internalerror(2012090604);
+        if not assigned(cgpara.location) then
+          internalerror(2012090605);
+        { init lo/hi para }
+        cgparahi.reset;
+        if cgpara.size=OS_S128 then
+          cgparahi.size:=OS_S64
+        else
+          cgparahi.size:=OS_64;
+        cgparahi.intsize:=8;
+        cgparahi.alignment:=cgpara.alignment;
+        paralochi:=cgparahi.add_location;
+        cgparalo.reset;
+        cgparalo.size:=OS_64;
+        cgparalo.intsize:=8;
+        cgparalo.alignment:=cgpara.alignment;
+        paraloclo:=cgparalo.add_location;
+        { 2 parameter fields? }
+        if assigned(cgpara.location^.next) then
+          begin
+            { Order for multiple locations is always
+                paraloc^ -> high
+                paraloc^.next -> low }
+            if (target_info.endian=ENDIAN_BIG) then
+              begin
+                { paraloc^ -> high
+                  paraloc^.next -> low }
+                move(cgpara.location^,paralochi^,sizeof(paralochi^));
+                move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
+              end
+            else
+              begin
+                { paraloc^ -> low
+                  paraloc^.next -> high }
+                move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
+                move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
+              end;
+          end
+        else
+          begin
+            { single parameter, this can only be in memory }
+            if cgpara.location^.loc<>LOC_REFERENCE then
+              internalerror(2012090606);
+            move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
+            move(cgpara.location^,paralochi^,sizeof(paralochi^));
+            { for big endian low is at +8, for little endian high }
+            if target_info.endian = endian_big then
+              begin
+                inc(cgparalo.location^.reference.offset,8);
+                cgparalo.alignment:=newalignment(cgparalo.alignment,8);
+              end
+            else
+              begin
+                inc(cgparahi.location^.reference.offset,8);
+                cgparahi.alignment:=newalignment(cgparahi.alignment,8);
+              end;
+          end;
+        { fix size }
+        paraloclo^.size:=cgparalo.size;
+        paraloclo^.next:=nil;
+        paralochi^.size:=cgparahi.size;
+        paralochi^.next:=nil;
+      end;
+
+
+
+
+    procedure tcg128.a_load128_reg_reg(list: TAsmList; regsrc,
+      regdst: tregister128);
+      begin
+        cg.a_load_reg_reg(list,OS_64,OS_64,regsrc.reglo,regdst.reglo);
+        cg.a_load_reg_reg(list,OS_64,OS_64,regsrc.reghi,regdst.reghi);
+      end;
+
+
+    procedure tcg128.a_load128_reg_ref(list: TAsmList; reg: tregister128;
+      const ref: treference);
+      var
+        tmpreg: tregister;
+        tmpref: treference;
+      begin
+        if target_info.endian = endian_big then
+          begin
+            tmpreg:=reg.reglo;
+            reg.reglo:=reg.reghi;
+            reg.reghi:=tmpreg;
+          end;
+        cg.a_load_reg_ref(list,OS_64,OS_64,reg.reglo,ref);
+        tmpref := ref;
+        inc(tmpref.offset,8);
+        cg.a_load_reg_ref(list,OS_64,OS_64,reg.reghi,tmpref);
+      end;
+
+
+    procedure tcg128.a_load128_loc_ref(list: TAsmList; const l: tlocation;
+      const ref: treference);
+      begin
+        case l.loc of
+          LOC_REGISTER,LOC_CREGISTER:
+            a_load128_reg_ref(list,l.register128,ref);
+          { not yet implemented:
+          LOC_CONSTANT :
+            a_load128_const_ref(list,l.value128,ref);
+          LOC_SUBSETREF, LOC_CSUBSETREF:
+            a_load64_subsetref_ref(list,l.sref,ref); }
+          else
+            internalerror(201209061);
+        end;
+      end;
+
+
+    procedure tcg128.a_load128_reg_loc(list: TAsmList; reg: tregister128;
+      const l: tlocation);
+      begin
+        case l.loc of
+          LOC_REFERENCE, LOC_CREFERENCE:
+            a_load128_reg_ref(list,reg,l.reference);
+          LOC_REGISTER,LOC_CREGISTER:
+            a_load128_reg_reg(list,reg,l.register128);
+          { not yet implemented:
+          LOC_SUBSETREF, LOC_CSUBSETREF:
+            a_load64_reg_subsetref(list,reg,l.sref);
+          LOC_MMREGISTER, LOC_CMMREGISTER:
+            a_loadmm_intreg64_reg(list,l.size,reg,l.register); }
+          else
+            internalerror(201209062);
+        end;
+      end;
+
+
+    procedure tcg128.a_load128_loc_cgpara(list: TAsmList; const l: tlocation;
+      const paraloc: TCGPara);
+      begin
+        case l.loc of
+          LOC_REGISTER,
+          LOC_CREGISTER :
+            a_load128_reg_cgpara(list,l.register128,paraloc);
+          {not yet implemented:
+          LOC_CONSTANT :
+            a_load128_const_cgpara(list,l.value64,paraloc);
+          }
+          LOC_CREFERENCE,
+          LOC_REFERENCE :
+            a_load128_ref_cgpara(list,l.reference,paraloc);
+          else
+            internalerror(2012090603);
+        end;
+      end;
+
+
+    procedure tcg128.a_load128_reg_cgpara(list : TAsmList;reg : tregister128;const paraloc : tcgpara);
+      var
+        tmplochi,tmploclo: tcgpara;
+      begin
+        tmploclo.init;
+        tmplochi.init;
+        splitparaloc128(paraloc,tmploclo,tmplochi);
+        cg.a_load_reg_cgpara(list,OS_64,reg.reghi,tmplochi);
+        cg.a_load_reg_cgpara(list,OS_64,reg.reglo,tmploclo);
+        tmploclo.done;
+        tmplochi.done;
+      end;
+
+
+    procedure tcg128.a_load128_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
+      var
+        tmprefhi,tmpreflo : treference;
+        tmploclo,tmplochi : tcgpara;
+      begin
+        tmploclo.init;
+        tmplochi.init;
+        splitparaloc128(paraloc,tmploclo,tmplochi);
+        tmprefhi:=r;
+        tmpreflo:=r;
+        if target_info.endian=endian_big then
+          inc(tmpreflo.offset,8)
+        else
+          inc(tmprefhi.offset,8);
+        cg.a_load_ref_cgpara(list,OS_64,tmprefhi,tmplochi);
+        cg.a_load_ref_cgpara(list,OS_64,tmpreflo,tmploclo);
+        tmploclo.done;
+        tmplochi.done;
+      end;
 {$endif cpu64bitalu}
 {$endif cpu64bitalu}
 
 
     function asmsym2indsymflags(sym: TAsmSymbol): tindsymflags;
     function asmsym2indsymflags(sym: TAsmSymbol): tindsymflags;
@@ -2523,7 +2740,10 @@ implementation
       begin
       begin
         cg.free;
         cg.free;
         cg:=nil;
         cg:=nil;
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+        cg128.free;
+        cg128:=nil;
+{$else cpu64bitalu}
         cg64.free;
         cg64.free;
         cg64:=nil;
         cg64:=nil;
 {$endif cpu64bitalu}
 {$endif cpu64bitalu}

+ 4 - 1
compiler/cgutils.pas

@@ -127,7 +127,10 @@ unit cgutils;
                      registeralias : tregister;
                      registeralias : tregister;
 {$endif m68k}
 {$endif m68k}
                     );
                     );
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+                { overlay a 128 Bit register type }
+                2 : (register128 : tregister128);
+{$else cpu64bitalu}
                 { overlay a 64 Bit register type }
                 { overlay a 64 Bit register type }
                 2 : (register64 : tregister64);
                 2 : (register64 : tregister64);
 {$endif cpu64bitalu}
 {$endif cpu64bitalu}

+ 18 - 8
compiler/hlcg2ll.pas

@@ -1200,11 +1200,15 @@ implementation
         LOC_CREGISTER :
         LOC_CREGISTER :
           begin
           begin
             tg.gethltemp(list,size,size.size,tt_normal,r);
             tg.gethltemp(list,size,size.size,tt_normal,r);
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+            if l.size in [OS_128,OS_S128] then
+              cg128.a_load128_loc_ref(list,l,r)
+            else
+{$else cpu64bitalu}
             if l.size in [OS_64,OS_S64] then
             if l.size in [OS_64,OS_S64] then
               cg64.a_load64_loc_ref(list,l,r)
               cg64.a_load64_loc_ref(list,l,r)
             else
             else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
               a_load_loc_ref(list,size,size,l,r);
               a_load_loc_ref(list,size,size,l,r);
             location_reset_ref(l,LOC_REFERENCE,l.size,0);
             location_reset_ref(l,LOC_REFERENCE,l.size,0);
             l.reference:=r;
             l.reference:=r;
@@ -1329,10 +1333,8 @@ implementation
     end;
     end;
 
 
   procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
   procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
-{$ifndef cpu64bitalu}
     var
     var
       tmploc: tlocation;
       tmploc: tlocation;
-{$endif not cpu64bitalu}
     begin
     begin
       { Handle Floating point types differently
       { Handle Floating point types differently
 
 
@@ -1355,19 +1357,28 @@ implementation
         LOC_REFERENCE,
         LOC_REFERENCE,
         LOC_CREFERENCE :
         LOC_CREFERENCE :
           begin
           begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+            { use cg128 only if no "chained" location is used }
+            if (l.size in [OS_128,OS_S128]) and (cgpara.Size in [OS_128,OS_S128]) then
+              cg128.a_load128_loc_cgpara(list,l,cgpara)
+            else
+{$else cpu64bitalu}
             { use cg64 only for int64, not for 8 byte records }
             { use cg64 only for int64, not for 8 byte records }
             if (l.size in [OS_64,OS_S64]) and (cgpara.Size in [OS_64,OS_S64]) then
             if (l.size in [OS_64,OS_S64]) and (cgpara.Size in [OS_64,OS_S64]) then
               cg64.a_load64_loc_cgpara(list,l,cgpara)
               cg64.a_load64_loc_cgpara(list,l,cgpara)
             else
             else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
               begin
               begin
-{$ifndef cpu64bitalu}
+
                 { Only a_load_ref_cgpara supports multiple locations, when the
                 { Only a_load_ref_cgpara supports multiple locations, when the
                   value is still a const or in a register then write it
                   value is still a const or in a register then write it
                   to a reference first. This situation can be triggered
                   to a reference first. This situation can be triggered
                   by typecasting an int64 constant to a record of 8 bytes }
                   by typecasting an int64 constant to a record of 8 bytes }
+{$ifdef cpu64bitalu}
+                if l.size in [OS_128,OS_S128] then
+{$else cpu64bitalu}
                 if l.size in [OS_64,OS_S64] then
                 if l.size in [OS_64,OS_S64] then
+{$endif cpu64bitalu}
                   begin
                   begin
                     tmploc:=l;
                     tmploc:=l;
                     location_force_mem(list,tmploc,vardef);
                     location_force_mem(list,tmploc,vardef);
@@ -1379,7 +1390,6 @@ implementation
                       location_freetemp(list,tmploc);
                       location_freetemp(list,tmploc);
                   end
                   end
                 else
                 else
-{$endif not cpu64bitalu}
                   a_load_loc_cgpara(list,vardef,l,cgpara);
                   a_load_loc_cgpara(list,vardef,l,cgpara);
               end;
               end;
           end;
           end;

+ 13 - 4
compiler/ncgld.pas

@@ -842,13 +842,18 @@ implementation
               LOC_REGISTER,
               LOC_REGISTER,
               LOC_CREGISTER :
               LOC_CREGISTER :
                 begin
                 begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+                  if left.location.size in [OS_128,OS_S128] then
+                    cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
+                      right.location.register128,left.location)
+                  else
+{$else cpu64bitalu}
                   { also OS_F64 in case of mmreg -> intreg }
                   { also OS_F64 in case of mmreg -> intreg }
                   if left.location.size in [OS_64,OS_S64,OS_F64] then
                   if left.location.size in [OS_64,OS_S64,OS_F64] then
                     cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
                     cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
                       right.location.register64,left.location)
                       right.location.register64,left.location)
                   else
                   else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                     hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
                     hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
                 end;
                 end;
               LOC_FPUREGISTER,
               LOC_FPUREGISTER,
@@ -1274,11 +1279,15 @@ implementation
                      end;
                      end;
                    else
                    else
                      begin
                      begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+                       if hp.left.location.size in [OS_128,OS_S128] then
+                         cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
+                       else
+{$else cpu64bitalu}
                        if hp.left.location.size in [OS_64,OS_S64] then
                        if hp.left.location.size in [OS_64,OS_S64] then
                          cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
                          cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
                        else
                        else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                          hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
                          hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
                      end;
                      end;
                  end;
                  end;

+ 56 - 16
compiler/ncgutil.pas

@@ -1638,9 +1638,7 @@ implementation
       preplaceregrec = ^treplaceregrec;
       preplaceregrec = ^treplaceregrec;
       treplaceregrec = record
       treplaceregrec = record
         old, new: tregister;
         old, new: tregister;
-{$ifndef cpu64bitalu}
         oldhi, newhi: tregister;
         oldhi, newhi: tregister;
-{$endif not cpu64bitalu}
         ressym: tsym;
         ressym: tsym;
         { moved sym }
         { moved sym }
         sym : tsym;
         sym : tsym;
@@ -1665,7 +1663,15 @@ implementation
                  (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
                  (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
                  (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
                  (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
                 begin
                 begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+                  { it's possible a 128 bit location was shifted and/xor typecasted }
+                  { in a 64 bit value, so only 1 register was left in the location }
+                  if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_128,OS_S128]) then
+                    if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi = rr^.oldhi) then
+                      tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi := rr^.newhi
+                    else
+                      exit;
+{$else cpu64bitalu}
                   { it's possible a 64 bit location was shifted and/xor typecasted }
                   { it's possible a 64 bit location was shifted and/xor typecasted }
                   { in a 32 bit value, so only 1 register was left in the location }
                   { in a 32 bit value, so only 1 register was left in the location }
                   if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
                   if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
@@ -1673,7 +1679,7 @@ implementation
                       tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
                       tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
                     else
                     else
                       exit;
                       exit;
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                   tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
                   tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
                   rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry);
                   rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry);
                   result := fen_norecurse_true;
                   result := fen_norecurse_true;
@@ -1685,7 +1691,15 @@ implementation
                  (ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
                  (ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
                  (ttemprefnode(n).tempinfo^.location.register = rr^.old) then
                  (ttemprefnode(n).tempinfo^.location.register = rr^.old) then
                 begin
                 begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+                  { it's possible a 128 bit location was shifted and/xor typecasted }
+                  { in a 64 bit value, so only 1 register was left in the location }
+                  if (ttemprefnode(n).tempinfo^.location.size in [OS_128,OS_S128]) then
+                    if (ttemprefnode(n).tempinfo^.location.register128.reghi = rr^.oldhi) then
+                      ttemprefnode(n).tempinfo^.location.register128.reghi := rr^.newhi
+                    else
+                      exit;
+{$else cpu64bitalu}
                   { it's possible a 64 bit location was shifted and/xor typecasted }
                   { it's possible a 64 bit location was shifted and/xor typecasted }
                   { in a 32 bit value, so only 1 register was left in the location }
                   { in a 32 bit value, so only 1 register was left in the location }
                   if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
                   if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
@@ -1693,7 +1707,7 @@ implementation
                       ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
                       ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
                     else
                     else
                       exit;
                       exit;
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                   ttemprefnode(n).tempinfo^.location.register := rr^.new;
                   ttemprefnode(n).tempinfo^.location.register := rr^.new;
                   result := fen_norecurse_true;
                   result := fen_norecurse_true;
                 end;
                 end;
@@ -1725,13 +1739,19 @@ implementation
         rr.old := n.location.register;
         rr.old := n.location.register;
         rr.ressym := nil;
         rr.ressym := nil;
         rr.sym := nil;
         rr.sym := nil;
-      {$ifndef cpu64bitalu}
         rr.oldhi := NR_NO;
         rr.oldhi := NR_NO;
-      {$endif not cpu64bitalu}
         case n.location.loc of
         case n.location.loc of
           LOC_CREGISTER:
           LOC_CREGISTER:
             begin
             begin
-      {$ifndef cpu64bitalu}
+      {$ifdef cpu64bitalu}
+              if (n.location.size in [OS_128,OS_S128]) then
+                begin
+                  rr.oldhi := n.location.register128.reghi;
+                  rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                  rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                end
+              else
+      {$else cpu64bitalu}
               if (n.location.size in [OS_64,OS_S64]) then
               if (n.location.size in [OS_64,OS_S64]) then
                 begin
                 begin
                   rr.oldhi := n.location.register64.reghi;
                   rr.oldhi := n.location.register64.reghi;
@@ -1739,7 +1759,7 @@ implementation
                   rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
                   rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
                 end
                 end
               else
               else
-      {$endif not cpu64bitalu}
+      {$endif cpu64bitalu}
                 rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
                 rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
             end;
             end;
           LOC_CFPUREGISTER:
           LOC_CFPUREGISTER:
@@ -1769,11 +1789,15 @@ implementation
           case n.location.loc of
           case n.location.loc of
             LOC_CREGISTER:
             LOC_CREGISTER:
               begin
               begin
-      {$ifndef cpu64bitalu}
+      {$ifdef cpu64bitalu}
+                if (n.location.size in [OS_128,OS_S128]) then
+                  cg128.a_load128_reg_reg(list,n.location.register128,joinreg128(rr.new,rr.newhi))
+                else
+      {$else cpu64bitalu}
                 if (n.location.size in [OS_64,OS_S64]) then
                 if (n.location.size in [OS_64,OS_S64]) then
                   cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
                   cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
                 else
                 else
-      {$endif not cpu64bitalu}
+      {$endif cpu64bitalu}
                   cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
                   cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
               end;
               end;
             LOC_CFPUREGISTER:
             LOC_CFPUREGISTER:
@@ -1789,7 +1813,16 @@ implementation
           end;
           end;
 
 
         { now that we've change the loadn/temp, also change the node result location }
         { now that we've change the loadn/temp, also change the node result location }
-      {$ifndef cpu64bitalu}
+      {$ifdef cpu64bitalu}
+        if (n.location.size in [OS_128,OS_S128]) then
+          begin
+            n.location.register128.reglo := rr.new;
+            n.location.register128.reghi := rr.newhi;
+            if assigned(rr.sym) then
+              list.concat(tai_varloc.create128(rr.sym,rr.new,rr.newhi));
+          end
+        else
+      {$else cpu64bitalu}
         if (n.location.size in [OS_64,OS_S64]) then
         if (n.location.size in [OS_64,OS_S64]) then
           begin
           begin
             n.location.register64.reglo := rr.new;
             n.location.register64.reglo := rr.new;
@@ -1798,7 +1831,7 @@ implementation
               list.concat(tai_varloc.create64(rr.sym,rr.new,rr.newhi));
               list.concat(tai_varloc.create64(rr.sym,rr.new,rr.newhi));
           end
           end
         else
         else
-      {$endif not cpu64bitalu}
+      {$endif cpu64bitalu}
           begin
           begin
             n.location.register := rr.new;
             n.location.register := rr.new;
             if assigned(rr.sym) then
             if assigned(rr.sym) then
@@ -1825,14 +1858,21 @@ implementation
                     case localloc.loc of
                     case localloc.loc of
                       LOC_CREGISTER :
                       LOC_CREGISTER :
                         if (pi_has_label in current_procinfo.flags) then
                         if (pi_has_label in current_procinfo.flags) then
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+                          if def_cgsize(vardef) in [OS_128,OS_S128] then
+                            begin
+                              cg.a_reg_sync(list,localloc.register128.reglo);
+                              cg.a_reg_sync(list,localloc.register128.reghi);
+                            end
+                          else
+{$else cpu64bitalu}
                           if def_cgsize(vardef) in [OS_64,OS_S64] then
                           if def_cgsize(vardef) in [OS_64,OS_S64] then
                             begin
                             begin
                               cg.a_reg_sync(list,localloc.register64.reglo);
                               cg.a_reg_sync(list,localloc.register64.reglo);
                               cg.a_reg_sync(list,localloc.register64.reghi);
                               cg.a_reg_sync(list,localloc.register64.reghi);
                             end
                             end
                           else
                           else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                             cg.a_reg_sync(list,localloc.register);
                             cg.a_reg_sync(list,localloc.register);
                       LOC_CFPUREGISTER,
                       LOC_CFPUREGISTER,
                       LOC_CMMREGISTER:
                       LOC_CMMREGISTER:

+ 1 - 0
compiler/powerpc64/cgcpu.pas

@@ -1987,6 +1987,7 @@ end;
 procedure create_codegen;
 procedure create_codegen;
 begin
 begin
   cg := tcgppc.create;
   cg := tcgppc.create;
+  cg128:=tcg128.create;
 end;
 end;
 
 
 end.
 end.

+ 1 - 0
compiler/x86_64/cgcpu.pas

@@ -363,6 +363,7 @@ unit cgcpu;
     procedure create_codegen;
     procedure create_codegen;
       begin
       begin
         cg:=tcgx86_64.create;
         cg:=tcgx86_64.create;
+        cg128:=tcg128.create;
       end;
       end;
 
 
 end.
 end.