Browse Source

* fix register method pointer for ppc64 and x86_64-linux

git-svn-id: trunk@22351 -
florian 13 years ago
parent
commit
d93cee995b
5 changed files with 140 additions and 16 deletions
  1. 36 0
      compiler/cgobj.pas
  2. 1 1
      compiler/hlcg2ll.pas
  3. 6 2
      compiler/ncgld.pas
  4. 96 12
      compiler/ncgutil.pas
  5. 1 1
      compiler/x86/cpubase.pas

+ 36 - 0
compiler/cgobj.pas

@@ -465,6 +465,7 @@ unit cgobj;
     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_ref_reg(list : TAsmList;const ref : treference;reg : tregister128);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;
 
@@ -2636,6 +2637,41 @@ implementation
       end;
 
 
+    procedure tcg128.a_load128_ref_reg(list: TAsmList; const ref: treference;
+      reg: tregister128);
+      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;
+        tmpref := ref;
+        if (tmpref.base=reg.reglo) then
+         begin
+           tmpreg:=cg.getaddressregister(list);
+           cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
+           tmpref.base:=tmpreg;
+         end
+        else
+         { this works only for the i386, thus the i386 needs to override  }
+         { this method and this method must be replaced by a more generic }
+         { implementation FK                                              }
+         if (tmpref.index=reg.reglo) then
+          begin
+            tmpreg:=cg.getaddressregister(list);
+            cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
+            tmpref.index:=tmpreg;
+          end;
+        cg.a_load_ref_reg(list,OS_64,OS_64,tmpref,reg.reglo);
+        inc(tmpref.offset,8);
+        cg.a_load_ref_reg(list,OS_64,OS_64,tmpref,reg.reghi);
+      end;
+
+
     procedure tcg128.a_load128_loc_ref(list: TAsmList; const l: tlocation;
       const ref: treference);
       begin

+ 1 - 1
compiler/hlcg2ll.pas

@@ -1359,7 +1359,7 @@ implementation
           begin
 {$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
+            if is_methodpointer(cgpara.def) and (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}

+ 6 - 2
compiler/ncgld.pas

@@ -716,11 +716,15 @@ implementation
                     LOC_REGISTER,
                     LOC_CREGISTER :
                       begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+                        if left.location.size in [OS_128,OS_S128] then
+                          cg128.a_load128_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register128)
+                        else
+{$else cpu64bitalu}
                         if left.location.size in [OS_64,OS_S64] then
                           cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
                         else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                           hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
                       end;
                     LOC_FPUREGISTER,

+ 96 - 12
compiler/ncgutil.pas

@@ -205,7 +205,7 @@ implementation
                     if getsupreg(location.register64.reghi)<first_int_imreg then
                       cg.ungetcpuregister(list,location.register64.reghi);
                   end
-{$endif}
+{$endif cpu64bitalu}
                 else
                   if getsupreg(location.register)<first_int_imreg then
                     cg.ungetcpuregister(list,location.register);
@@ -317,7 +317,17 @@ implementation
                        end;
                      LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
                        begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+                         if opsize in [OS_128,OS_S128] then
+                           begin
+                             hlcg.location_force_reg(list,p.location,p.resultdef,hlcg.tcgsize2orddef(opsize),true);
+                             tmpreg:=cg.getintregister(list,OS_64);
+                             cg.a_op_reg_reg_reg(list,OP_OR,OS_64,p.location.register128.reglo,p.location.register128.reghi,tmpreg);
+                             location_reset(p.location,LOC_REGISTER,OS_64);
+                             p.location.register:=tmpreg;
+                             opsize:=OS_64;
+                           end;
+{$else cpu64bitalu}
                          if opsize in [OS_64,OS_S64] then
                            begin
                              hlcg.location_force_reg(list,p.location,p.resultdef,hlcg.tcgsize2orddef(opsize),true);
@@ -327,7 +337,7 @@ implementation
                              p.location.register:=tmpreg;
                              opsize:=OS_32;
                            end;
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                          cg.a_cmp_const_loc_label(list,opsize,OC_NE,0,p.location,current_procinfo.CurrTrueLabel);
                          cg.a_jmp_always(list,current_procinfo.CurrFalseLabel);
                        end;
@@ -614,14 +624,21 @@ implementation
               location_reset(l,LOC_CREGISTER,l.size)
             else
               location_reset(l,LOC_REGISTER,l.size);
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+            if l.size in [OS_128,OS_S128,OS_F128] then
+              begin
+                l.register128.reglo:=cg.getintregister(list,OS_64);
+                l.register128.reghi:=cg.getintregister(list,OS_64);
+              end
+            else
+{$else cpu64bitalu}
             if l.size in [OS_64,OS_S64,OS_F64] then
               begin
                 l.register64.reglo:=cg.getintregister(list,OS_32);
                 l.register64.reghi:=cg.getintregister(list,OS_32);
               end
             else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
               l.register:=cg.getintregister(list,l.size);
           end;
       end;
@@ -773,7 +790,14 @@ implementation
         case loc.loc of
           LOC_CREGISTER:
             begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+              if loc.size in [OS_128,OS_S128] then
+                begin
+                  loc.register128.reglo:=cg.getintregister(list,OS_64);
+                  loc.register128.reghi:=cg.getintregister(list,OS_64);
+                end
+              else
+{$else cpu64bitalu}
               if loc.size in [OS_64,OS_S64] then
                 begin
                   loc.register64.reglo:=cg.getintregister(list,OS_32);
@@ -803,14 +827,21 @@ implementation
           begin
             { Allocate register already, to prevent first allocation to be
               inside a loop }
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+            if sym.initialloc.size in [OS_128,OS_S128] then
+              begin
+                cg.a_reg_sync(list,sym.initialloc.register128.reglo);
+                cg.a_reg_sync(list,sym.initialloc.register128.reghi);
+              end
+            else
+{$else cpu64bitalu}
             if sym.initialloc.size in [OS_64,OS_S64] then
               begin
                 cg.a_reg_sync(list,sym.initialloc.register64.reglo);
                 cg.a_reg_sync(list,sym.initialloc.register64.reghi);
               end
             else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
              cg.a_reg_sync(list,sym.initialloc.register);
           end;
         sym.localloc:=sym.initialloc;
@@ -897,7 +928,53 @@ implementation
           LOC_REGISTER,
           LOC_CREGISTER :
             begin
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+              if (para.size in [OS_128,OS_S128,OS_F128]) and
+                 ({ in case of fpu emulation, or abi's that pass fpu values
+                    via integer registers }
+                  (vardef.typ=floatdef) or
+                   is_methodpointer(vardef)) then
+                begin
+                  case paraloc^.loc of
+                    LOC_REGISTER:
+                      begin
+                        if not assigned(paraloc^.next) then
+                          internalerror(200410104);
+                        if (target_info.endian=ENDIAN_BIG) then
+                          begin
+                            { paraloc^ -> high
+                              paraloc^.next -> low }
+                            unget_para(paraloc^);
+                            gen_alloc_regloc(list,destloc);
+                            { reg->reg, alignment is irrelevant }
+                            cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reghi,8);
+                            unget_para(paraloc^.next^);
+                            cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^.next^,destloc.register128.reglo,8);
+                          end
+                        else
+                          begin
+                            { paraloc^ -> low
+                              paraloc^.next -> high }
+                            unget_para(paraloc^);
+                            gen_alloc_regloc(list,destloc);
+                            cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reglo,8);
+                            unget_para(paraloc^.next^);
+                            cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^.next^,destloc.register128.reghi,8);
+                          end;
+                      end;
+                    LOC_REFERENCE:
+                      begin
+                        gen_alloc_regloc(list,destloc);
+                        reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset,para.alignment);
+                        cg128.a_load128_ref_reg(list,href,destloc.register128);
+                        unget_para(paraloc^);
+                      end;
+                    else
+                      internalerror(2012090607);
+                  end
+                end
+              else
+{$else cpu64bitalu}
               if (para.size in [OS_64,OS_S64,OS_F64]) and
                  (is_64bit(vardef) or
                   { in case of fpu emulation, or abi's that pass fpu values
@@ -944,7 +1021,7 @@ implementation
                   end
                 end
               else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
                 begin
                   if assigned(paraloc^.next) then
                     internalerror(200410105);
@@ -1520,14 +1597,21 @@ implementation
       begin
         case location.loc of
           LOC_CREGISTER:
-{$ifndef cpu64bitalu}
+{$ifdef cpu64bitalu}
+            if location.size in [OS_128,OS_S128] then
+              begin
+                rv.intregvars.addnodup(getsupreg(location.register128.reglo));
+                rv.intregvars.addnodup(getsupreg(location.register128.reghi));
+              end
+            else
+{$else cpu64bitalu}
             if location.size in [OS_64,OS_S64] then
               begin
                 rv.intregvars.addnodup(getsupreg(location.register64.reglo));
                 rv.intregvars.addnodup(getsupreg(location.register64.reghi));
               end
             else
-{$endif not cpu64bitalu}
+{$endif cpu64bitalu}
               rv.intregvars.addnodup(getsupreg(location.register));
           LOC_CFPUREGISTER:
             rv.fpuregvars.addnodup(getsupreg(location.register));

+ 1 - 1
compiler/x86/cpubase.pas

@@ -359,7 +359,7 @@ implementation
                 reg_cgsize:=OS_32
             end
           else
-            internalerror(200303181);
+            internalerror(2003031801);
           end;
         end;