Browse Source

+ 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 years ago
parent
commit
7361e19799

+ 16 - 1
compiler/aasmtai.pas

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

+ 1 - 0
compiler/alpha/cgcpu.pas

@@ -162,6 +162,7 @@ end;
 procedure create_codegen;
   begin
     cg:=tcgalpha.create;
+    cg128:=tcg128.create;
   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_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_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
@@ -366,8 +365,6 @@ unit cg64f32;
       end;
 
 
-
-
     procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
 
       var

+ 8 - 0
compiler/cgbase.pas

@@ -209,6 +209,9 @@ interface
       { A type to store register locations for 64 Bit values. }
 {$ifdef cpu64bitalu}
       tregister64 = tregister;
+      tregister128 = record
+         reglo,reghi : tregister;
+      end;
 {$else cpu64bitalu}
       tregister64 = record
          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
         );
       begin
+{$ifdef cpu64bitalu}
+        if a=16 then
+          result:=OS_128
+        else
+{$endif cpu64bitalu}
         if a>8 then
           result:=OS_NO
         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;
        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)
        This class implements an abstract code generator class
        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_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_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;
@@ -537,10 +554,13 @@ unit cgobj;
 {$endif cpu64bitalu}
 
     var
-       {# Main code generator class }
+       { Main code generator class }
        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;
 {$endif cpu64bitalu}
 
@@ -556,7 +576,6 @@ implementation
        tgobj,cutils,procinfo,
        ncgrtti;
 
-
 {*****************************************************************************
                             basic functionallity
 ******************************************************************************}
@@ -2508,6 +2527,204 @@ implementation
             internalerror(2006082211);
         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}
 
     function asmsym2indsymflags(sym: TAsmSymbol): tindsymflags;
@@ -2523,7 +2740,10 @@ implementation
       begin
         cg.free;
         cg:=nil;
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+        cg128.free;
+        cg128:=nil;
+{$else cpu64bitalu}
         cg64.free;
         cg64:=nil;
 {$endif cpu64bitalu}

+ 4 - 1
compiler/cgutils.pas

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

+ 18 - 8
compiler/hlcg2ll.pas

@@ -1200,11 +1200,15 @@ implementation
         LOC_CREGISTER :
           begin
             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
               cg64.a_load64_loc_ref(list,l,r)
             else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
               a_load_loc_ref(list,size,size,l,r);
             location_reset_ref(l,LOC_REFERENCE,l.size,0);
             l.reference:=r;
@@ -1329,10 +1333,8 @@ implementation
     end;
 
   procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
-{$ifndef cpu64bitalu}
     var
       tmploc: tlocation;
-{$endif not cpu64bitalu}
     begin
       { Handle Floating point types differently
 
@@ -1355,19 +1357,28 @@ implementation
         LOC_REFERENCE,
         LOC_CREFERENCE :
           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 }
             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)
             else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
               begin
-{$ifndef cpu64bitalu}
+
                 { Only a_load_ref_cgpara supports multiple locations, when the
                   value is still a const or in a register then write it
                   to a reference first. This situation can be triggered
                   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
+{$endif cpu64bitalu}
                   begin
                     tmploc:=l;
                     location_force_mem(list,tmploc,vardef);
@@ -1379,7 +1390,6 @@ implementation
                       location_freetemp(list,tmploc);
                   end
                 else
-{$endif not cpu64bitalu}
                   a_load_loc_cgpara(list,vardef,l,cgpara);
               end;
           end;

+ 13 - 4
compiler/ncgld.pas

@@ -842,13 +842,18 @@ implementation
               LOC_REGISTER,
               LOC_CREGISTER :
                 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 }
                   if left.location.size in [OS_64,OS_S64,OS_F64] then
                     cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
                       right.location.register64,left.location)
                   else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                     hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
                 end;
               LOC_FPUREGISTER,
@@ -1274,11 +1279,15 @@ implementation
                      end;
                    else
                      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
                          cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
                        else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                          hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
                      end;
                  end;

+ 56 - 16
compiler/ncgutil.pas

@@ -1638,9 +1638,7 @@ implementation
       preplaceregrec = ^treplaceregrec;
       treplaceregrec = record
         old, new: tregister;
-{$ifndef cpu64bitalu}
         oldhi, newhi: tregister;
-{$endif not cpu64bitalu}
         ressym: tsym;
         { moved sym }
         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.register = rr^.old) then
                 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 }
                   { 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
@@ -1673,7 +1679,7 @@ implementation
                       tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
                     else
                       exit;
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                   tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
                   rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry);
                   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.register = rr^.old) then
                 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 }
                   { 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
@@ -1693,7 +1707,7 @@ implementation
                       ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
                     else
                       exit;
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                   ttemprefnode(n).tempinfo^.location.register := rr^.new;
                   result := fen_norecurse_true;
                 end;
@@ -1725,13 +1739,19 @@ implementation
         rr.old := n.location.register;
         rr.ressym := nil;
         rr.sym := nil;
-      {$ifndef cpu64bitalu}
         rr.oldhi := NR_NO;
-      {$endif not cpu64bitalu}
         case n.location.loc of
           LOC_CREGISTER:
             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
                 begin
                   rr.oldhi := n.location.register64.reghi;
@@ -1739,7 +1759,7 @@ implementation
                   rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
                 end
               else
-      {$endif not cpu64bitalu}
+      {$endif cpu64bitalu}
                 rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
             end;
           LOC_CFPUREGISTER:
@@ -1769,11 +1789,15 @@ implementation
           case n.location.loc of
             LOC_CREGISTER:
               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
                   cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
                 else
-      {$endif not cpu64bitalu}
+      {$endif cpu64bitalu}
                   cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
               end;
             LOC_CFPUREGISTER:
@@ -1789,7 +1813,16 @@ implementation
           end;
 
         { 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
           begin
             n.location.register64.reglo := rr.new;
@@ -1798,7 +1831,7 @@ implementation
               list.concat(tai_varloc.create64(rr.sym,rr.new,rr.newhi));
           end
         else
-      {$endif not cpu64bitalu}
+      {$endif cpu64bitalu}
           begin
             n.location.register := rr.new;
             if assigned(rr.sym) then
@@ -1825,14 +1858,21 @@ implementation
                     case localloc.loc of
                       LOC_CREGISTER :
                         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
                             begin
                               cg.a_reg_sync(list,localloc.register64.reglo);
                               cg.a_reg_sync(list,localloc.register64.reghi);
                             end
                           else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                             cg.a_reg_sync(list,localloc.register);
                       LOC_CFPUREGISTER,
                       LOC_CMMREGISTER:

+ 1 - 0
compiler/powerpc64/cgcpu.pas

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

+ 1 - 0
compiler/x86_64/cgcpu.pas

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