Browse Source

* release old stack pointer register on ppc64 after method prolog
* threading fixes for ppc64
* fixed a_param_ref to respect the size parameter on ppc64
* better stack size calculation for ppc64

git-svn-id: trunk@1599 -

tom_at_work 20 năm trước cách đây
mục cha
commit
c5f89d7efd

+ 5 - 0
compiler/ncgutil.pas

@@ -1497,6 +1497,11 @@ implementation
         { which is used to access the parameters in their original callee-side location  }
         cg.a_reg_dealloc(list,NR_R12);
 {$endif powerpc}
+{$ifdef powerpc64}
+        { unget the register that contains the stack pointer before the procedure entry, }
+        { which is used to access the parameters in their original callee-side location  }
+        cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG);
+{$endif powerpc64}
       end;
 
 

+ 9 - 5
compiler/powerpc64/cgcpu.pas

@@ -244,8 +244,12 @@ begin
     case location^.loc of
       LOC_REGISTER, LOC_CREGISTER:
         begin
-          a_load_ref_reg(list, location^.size, location^.size, tmpref,
-            location^.register);
+          if (size <> OS_NO) then
+            a_load_ref_reg(list, size, location^.size, tmpref,
+              location^.register)
+          else
+            a_load_ref_reg(list, location^.size, location^.size, tmpref,
+              location^.register)
         end;
       LOC_REFERENCE:
         begin
@@ -303,7 +307,7 @@ end;
 
 procedure tcgppc.a_call_name(list: taasmoutput; const s: string);
 begin
-        a_call_name_direct(list, s, true, true);
+    a_call_name_direct(list, s, true, true);
 end;
 
 procedure tcgppc.a_call_name_direct(list: taasmoutput; s: string; prependDot : boolean; addNOP : boolean);
@@ -1026,8 +1030,8 @@ begin
   end;
   { save old stack frame pointer }
   if (localsize > 0) then begin
-    a_reg_alloc(list, NR_R12);
-    list.concat(taicpu.op_reg_reg(A_MR, NR_R12, NR_STACK_POINTER_REG));
+    a_reg_alloc(list, NR_OLD_STACK_POINTER_REG);
+    list.concat(taicpu.op_reg_reg(A_MR, NR_OLD_STACK_POINTER_REG, NR_STACK_POINTER_REG));
   end;
   { save registers, FPU first, then GPR }
   reference_reset_base(href, NR_STACK_POINTER_REG, -8);

+ 4 - 2
compiler/powerpc64/cpubase.pas

@@ -300,6 +300,9 @@ const
   // Stack pointer register
   NR_STACK_POINTER_REG = NR_R1;
   RS_STACK_POINTER_REG = RS_R1;
+  // old stack pointer register used during copying variables from the caller
+  // stack frame
+  NR_OLD_STACK_POINTER_REG = NR_R12;
   // Frame pointer register
   NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG;
   RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG;
@@ -387,8 +390,7 @@ function std_regname(r: Tregister): string;
 function is_condreg(r: tregister): boolean;
 
 function inverse_cond(const c: TAsmCond): Tasmcond;
-{$IFDEF USEINLINE}inline;
-{$ENDIF USEINLINE}
+{$IFDEF USEINLINE}inline;{$ENDIF USEINLINE}
 function conditions_equal(const c1, c2: TAsmCond): boolean;
 
 implementation

+ 17 - 27
compiler/powerpc64/cpupara.pas

@@ -97,10 +97,7 @@ begin
     end else begin
       loc := LOC_REFERENCE;
       paraloc^.reference.index := NR_STACK_POINTER_REG;
-      if (target_info.abi <> abi_powerpc_aix) then
-        reference.offset := sizeof(aint) * (nr - 8)
-      else
-        reference.offset := sizeof(aint) * (nr);
+      reference.offset := sizeof(aint) * (nr - 8);
     end;
   end;
 end;
@@ -177,10 +174,9 @@ begin
     recorddef:
       result :=
         ((varspez = vs_const) and
-        ((calloption = pocall_mwpascal) or
-        (not (calloption in [pocall_cdecl, pocall_cppdecl]) and
-        (def.size > 8)
-        )
+        (
+         (not (calloption in [pocall_cdecl, pocall_cppdecl]) and
+         (def.size > 8))
         )
         );
     arraydef:
@@ -267,12 +263,12 @@ end;
 
 function tppcparamanager.create_paraloc_info_intern(p: tabstractprocdef; side:
   tcallercallee; paras: tparalist;
-var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
+  var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
   aword): longint;
 var
   stack_offset: longint;
   paralen: aint;
-  nextintreg, nextfloatreg, nextmmreg, maxfpureg: tsuperregister;
+  nextintreg, nextfloatreg, nextmmreg : tsuperregister;
   paradef: tdef;
   paraloc: pcgparalocation;
   i: integer;
@@ -292,8 +288,6 @@ begin
   nextmmreg := curmmreg;
   stack_offset := cur_stack_offset;
 
-  maxfpureg := RS_F13;
-
   for i := 0 to paras.count - 1 do begin
     hp := tparavarsym(paras[i]);
     paradef := hp.vartype.def;
@@ -380,9 +374,9 @@ begin
         inc(nextintreg);
         dec(paralen, tcgsize2size[paraloc^.size]);
 
-        inc(stack_offset, tcgsize2size[paraloc^.size]);
+        inc(stack_offset, tcgsize2size[OS_INT]);
       end else if (loc = LOC_FPUREGISTER) and
-        (nextfloatreg <= maxfpureg) then begin
+        (nextfloatreg <= RS_F13) then begin
         paraloc^.loc := loc;
         paraloc^.size := paracgsize;
         paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
@@ -391,8 +385,8 @@ begin
         inc(nextintreg);
         inc(nextfloatreg);
         dec(paralen, tcgsize2size[paraloc^.size]);
-
-        inc(stack_offset, tcgsize2size[paraloc^.size]);
+        
+        inc(stack_offset, tcgsize2size[OS_FLOAT]);
       end else if (loc = LOC_MMREGISTER) then begin
         { Altivec not supported }
         internalerror(200510192);
@@ -404,11 +398,11 @@ begin
         if (side = callerside) then
           paraloc^.reference.index := NR_STACK_POINTER_REG
         else
-          { during procedure entry, R12 contains the old stack pointer }
-          paraloc^.reference.index := NR_R12;
+          { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
+          paraloc^.reference.index := NR_OLD_STACK_POINTER_REG;
         paraloc^.reference.offset := stack_offset;
 
-        { TODO: change this to the next power of two (natural alignment) }
+        { align temp contents to next register size }
         inc(stack_offset, align(paralen, 8));
         paralen := 0;
       end;
@@ -436,20 +430,16 @@ begin
 
   result := create_paraloc_info_intern(p, callerside, p.paras, curintreg,
     curfloatreg, curmmreg, cur_stack_offset);
-  if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) then
+  if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) then begin
     { just continue loading the parameters in the registers }
-  begin
     result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
       curfloatreg, curmmreg, cur_stack_offset);
-    { varargs routines have to reserve at least 64 bytes for the AIX abi }
+    { varargs routines have to reserve at least 64 bytes for the PPC64 ABI }
     if (result < 64) then
       result := 64;
-  end
-  else
-  begin
+  end else begin
     parasize := cur_stack_offset;
-    for i := 0 to varargspara.count - 1 do
-    begin
+    for i := 0 to varargspara.count - 1 do begin
       hp := tparavarsym(varargspara[i]);
       hp.paraloc[callerside].alignment := 8;
       paraloc := hp.paraloc[callerside].add_location;

+ 8 - 6
compiler/powerpc64/cpupi.pas

@@ -65,14 +65,16 @@ var
   locals: longint;
 begin
   if not (po_assembler in procdef.procoptions) then begin
+    { align the stack properly }
+    ofs := align(maxpushedparasize + LinkageAreaSizeELF, ELF_STACK_ALIGN);
+
     { the ABI specification says that it is required to always allocate space for 8 * 8 bytes
       for registers R3-R10 and stack header if there's a stack frame, but GCC doesn't do that,
       so we don't that too. Uncomment the next three lines if this is required }
-    // if (maxpushedparasize < 64) then begin
-    //  maxpushedparasize := 64;
-    // end;
-    { align the stack properly }
-    ofs := align(maxpushedparasize + LinkageAreaSizeELF, ELF_STACK_ALIGN);
+//    if (ofs < 112) then begin
+//      ofs := 112;
+//    end;
+
     tg.setfirsttemp(ofs);
   end else begin
     locals := 0;
@@ -91,7 +93,7 @@ end;
 
 function tppcprocinfo.calc_stackframe_size: longint;
 begin
-  calc_stackframe_size(18, 18);
+  result := calc_stackframe_size(18, 18);
 end;
 
 function tppcprocinfo.calc_stackframe_size(numgpr, numfpr : longint) : longint;

+ 16 - 8
rtl/linux/powerpc64/syscall.inc

@@ -28,7 +28,7 @@ function FpSysCall(sysnr:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYS
   copies back the registers as they are after the SysCall.
 }
 var
-  temp : longint;
+  temp : qword;
   retaddress: ptruint;
 asm
   mr  r0,r3
@@ -51,12 +51,13 @@ asm
 .LThreaded:
   std   r3,temp
   mflr  r3
+  std   r3,retaddress
+  ld	r10, 0(r10)
   mtctr r10
   lis   r4, (errno)@highesta
   ori	r4, r4, (errno)@highera
   sldi	r4, r4, 32
   oris	r4, r4, (errno)@ha
-  std   r3,retaddress
   ld	r3,(errno)@l(r4)
   bctrl
   ld	r4,temp
@@ -74,7 +75,7 @@ function FpSysCall(sysnr,param1:TSysParam):TSysResult; assembler;[public,alias:'
   copies back the registers as they are after the SysCall.
 }
 var
-  temp : int64;
+  temp : qword;
   retaddress: ptruint;
 asm
   mr	r0,r3
@@ -99,6 +100,8 @@ asm
   std   r3,temp
   mflr  r3
   mtctr r10
+  ld	r10, 0(r10)
+
   lis   r4, (errno)@highesta
   ori	r4, r4, (errno)@highera
   sldi	r4, r4, 32
@@ -121,7 +124,7 @@ function FpSysCall(sysnr,param1,param2:TSysParam):TSysResult; assembler;[public,
   copies back the registers as they are after the SysCall.
 }
 var
-  temp : int64;
+  temp : qword;
   retaddress: ptruint;
 asm
   mr	r0,r3
@@ -146,6 +149,7 @@ asm
 .LThreaded:
   std   r3,temp
   mflr  r3
+  ld	r10, 0(r10)
   mtctr r10
   lis   r4, (errno)@highesta
   ori	r4, r4, (errno)@highera
@@ -170,7 +174,7 @@ function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler;[
   copies back the registers as they are after the SysCall.
 }
 var
-  temp : int64;
+  temp : qword;
   retaddress: ptruint;
 asm
   mr	r0,r3
@@ -196,6 +200,7 @@ asm
 .LThreaded:
   std   r3,temp
   mflr  r3
+  ld	r10, 0(r10)
   mtctr r10
   lis   r4, (errno)@highesta
   ori	r4, r4, (errno)@highera
@@ -220,7 +225,7 @@ function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; asse
   copies back the registers as they are after the SysCall.
 }
 var
-  temp : int64;
+  temp : qword;
   retaddress: ptruint;
 asm
   mr	r0,r3
@@ -247,6 +252,7 @@ asm
 .LThreaded:
   std   r3,temp
   mflr  r3
+  ld	r10, 0(r10)
   mtctr r10
   lis   r4, (errno)@highesta
   ori	r4, r4, (errno)@highera
@@ -271,7 +277,7 @@ function FpSysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResul
   copies back the registers as they are after the SysCall.
 }
 var
-  temp : int64;
+  temp : qword;
   retaddress: ptruint;
 asm
   mr	r0,r3
@@ -299,6 +305,7 @@ asm
 .LThreaded:
   std   r3,temp
   mflr  r3
+  ld	r10, 0(r10)
   mtctr r10
   lis   r4, (errno)@highesta
   ori	r4, r4, (errno)@highera
@@ -323,7 +330,7 @@ function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TS
   copies back the registers as they are after the SysCall.
 }
 var
-  temp : int64;
+  temp : qword;
   retaddress: ptruint;
 asm
   mr	r0,r3
@@ -352,6 +359,7 @@ asm
 .LThreaded:
   std   r3,temp
   mflr  r3
+  ld	r10, 0(r10)
   mtctr r10
   lis   r4, (errno)@highesta
   ori	r4, r4, (errno)@highera

+ 4 - 0
rtl/linux/sysosh.inc

@@ -19,7 +19,11 @@
 type
   { fd are int in C also for 64bit targets (x86_64) }
   THandle = Longint;
+  {$ifdef CPUPOWERPC64}
+  TThreadID = QWord;
+  {$else}
   TThreadID = THandle;
+  {$endif}
   
   { pthread_mutex_t }
   PRTLCriticalSection = ^TRTLCriticalSection;

+ 4 - 0
rtl/unix/cthreads.pp

@@ -93,6 +93,10 @@ Type  PINTRTLEvent = ^TINTRTLEvent;
         threadvarblocksize:=align(threadvarblocksize,16);
         {$endif cpux86_64}
 
+        {$ifdef cpupowerpc64}
+        threadvarblocksize:=align(threadvarblocksize,16);
+        {$endif cpupowerpc64}
+
         offset:=threadvarblocksize;
 
         inc(threadvarblocksize,size);