فهرست منبع

* pass varargs float parameters only in integer registers instead of only
in fpu registers for aix abi. Proper fix is to pass them in both, but
at least gcc under Mac OS X only seems to use the contents in the integer
registers currently.

git-svn-id: trunk@1576 -

Jonas Maebe 20 سال پیش
والد
کامیت
89094457c5
2فایلهای تغییر یافته به همراه45 افزوده شده و 5 حذف شده
  1. 28 0
      compiler/ncgcal.pas
  2. 17 5
      compiler/powerpc/cpupara.pas

+ 28 - 0
compiler/ncgcal.pas

@@ -216,6 +216,21 @@ implementation
                      cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
                      cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
                    end;
                    end;
 {$endif x86_64}
 {$endif x86_64}
+{$ifdef powerpc}
+                 LOC_REGISTER,
+                 LOC_CREGISTER :
+                   begin
+                     { aix abi passes floats of varargs in both fpu and }
+                     { integer registers                                }
+                     location_force_mem(exprasmlist,left.location);
+                     { force integer size }
+                     left.location.size:=int_cgsize(tcgsize2size[left.location.size]);
+                     if (left.location.size in [OS_32,OS_S32]) then
+                       cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara)
+                     else
+                       cg64.a_param64_ref(exprasmlist,left.location.reference,tempcgpara);
+                   end;
+{$endif powerpc}
 {$if defined(sparc) or defined(arm)}
 {$if defined(sparc) or defined(arm)}
                  { sparc and arm pass floats in normal registers }
                  { sparc and arm pass floats in normal registers }
                  LOC_REGISTER,
                  LOC_REGISTER,
@@ -245,6 +260,19 @@ implementation
                      cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
                      cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
                    end;
                    end;
 {$endif x86_64}
 {$endif x86_64}
+{$ifdef powerpc}
+                 { x86_64 pushes s64comp in normal register }
+                 LOC_REGISTER,
+                 LOC_CREGISTER :
+                   begin
+                     { force integer size }
+                     left.location.size:=int_cgsize(tcgsize2size[left.location.size]);
+                     if (left.location.size in [OS_32,OS_S32]) then
+                       cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara)
+                     else
+                       cg64.a_param64_ref(exprasmlist,left.location.reference,tempcgpara);
+                   end;
+{$endif powerpc}
 {$if defined(sparc) or defined(arm) }
 {$if defined(sparc) or defined(arm) }
                  { sparc and arm pass floats in normal registers }
                  { sparc and arm pass floats in normal registers }
                  LOC_REGISTER,
                  LOC_REGISTER,

+ 17 - 5
compiler/powerpc/cpupara.pas

@@ -45,7 +45,7 @@ unit cpupara;
          private
          private
           procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
           procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
           function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
           function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
-              var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+              var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
           function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
           function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
        end;
        end;
 
 
@@ -298,7 +298,7 @@ unit cpupara;
       begin
       begin
         init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
         init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
 
 
-        result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+        result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
 
 
         create_funcretloc_info(p,side);
         create_funcretloc_info(p,side);
       end;
       end;
@@ -306,7 +306,7 @@ unit cpupara;
 
 
 
 
     function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
     function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
-               var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+               var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
       var
       var
          stack_offset: longint;
          stack_offset: longint;
          paralen: aint;
          paralen: aint;
@@ -413,6 +413,18 @@ unit cpupara;
                         end;
                         end;
                     end
                     end
                 end;
                 end;
+
+              if varargsparas and
+                 (target_info.abi = abi_powerpc_aix) and
+                 (paradef.deftype = floatdef) then
+                begin
+                  loc := LOC_REGISTER;
+                  if paracgsize = OS_F64 then
+                    paracgsize := OS_64
+                  else
+                    paracgsize := OS_32;
+                end;
+
               hp.paraloc[side].alignment:=std_param_align;
               hp.paraloc[side].alignment:=std_param_align;
               hp.paraloc[side].size:=paracgsize;
               hp.paraloc[side].size:=paracgsize;
               hp.paraloc[side].intsize:=paralen;
               hp.paraloc[side].intsize:=paralen;
@@ -522,11 +534,11 @@ unit cpupara;
         init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
         init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
         firstfloatreg:=curfloatreg;
         firstfloatreg:=curfloatreg;
 
 
-        result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+        result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
         if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
         if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
           { just continue loading the parameters in the registers }
           { just continue loading the parameters in the registers }
           begin
           begin
-            result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+            result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
             { varargs routines have to reserve at least 32 bytes for the AIX abi }
             { varargs routines have to reserve at least 32 bytes for the AIX abi }
             if (target_info.abi = abi_powerpc_aix) and
             if (target_info.abi = abi_powerpc_aix) and
                (result < 32) then
                (result < 32) then