Просмотр исходного кода

Update freebsd/powerpc64 startup files

Curtis Hamilton 1 месяц назад
Родитель
Сommit
4d975d8a5f

+ 1 - 2
compiler/options.pas

@@ -5898,8 +5898,7 @@ begin
      if (target_info.abi=abi_powerpc_elfv2) and
          (target_info.endian=endian_big) then
         target_info.abi:=abi_powerpc_sysv;
-	if (target_info.system=system_powerpc64_freebsd) and
-         (target_info.endian=endian_big) then
+    if (target_info.system=system_powerpc64_freebsd)  then
         target_info.abi:=abi_powerpc_elfv2;
     end;
 {$endif}

+ 42 - 9
compiler/powerpc64/cgcpu.pas

@@ -1435,6 +1435,24 @@ begin
 
   ref2 := ref;
   fixref(list, ref2);
+
+  { ELFv2 PIC: never materialize absolute symbol addresses.
+    Must load via TOC (r2), otherwise we emit illegal
+    R_PPC64_ADDR16_* relocations in shared objects. }
+  if (cs_create_pic in current_settings.moduleswitches) and
+     (target_info.abi = abi_powerpc_elfv2) and
+     assigned(ref2.symbol) then
+    begin
+      reference_reset(tmpref, ref2.alignment, ref2.volatility);
+      tmpref.symbol := ref2.symbol;
+      tmpref.offset := ref2.offset;
+      tmpref.base   := NR_RTOC;
+      tmpref.refaddr := addr_no;
+
+      a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, r);
+      exit;
+    end;
+
   { load a symbol }
   if (assigned(ref2.symbol) or (hasLargeOffset(ref2))) then begin
     { add the symbol's value to the base of the reference, and if the }
@@ -1736,6 +1754,19 @@ begin
   if (ref.index <> NR_NO) and ((ref.offset <> 0) or (assigned(ref.symbol))) then
     internalerror(200310131);
 
+  { ELFv2 PIC: symbol accesses must be TOC-relative.
+    Absolute address construction here produces forbidden
+    R_PPC64_ADDR16_* relocations in shared libraries. }
+  if (cs_create_pic in current_settings.moduleswitches) and
+     (target_info.abi = abi_powerpc_elfv2) and
+     assigned(ref.symbol) then
+    begin
+      ref.base := NR_RTOC;
+      ref.refaddr := addr_no;
+      list.concat(taicpu.op_reg_ref(op, reg, ref));
+      exit;
+    end;
+
   { if this is a PIC'ed address, handle it and exit }
   if (ref.refaddr in [addr_pic,addr_pic_no_got]) then begin
     if (ref.offset <> 0) then
@@ -1827,15 +1858,17 @@ begin
       end;
       list.concat(taicpu.op_reg_ref(op, reg, tmpref));
     end else begin
-      { when accessing value from a reference without a base register, use the
-        following code template:
-
-        lis rT,SYM+offs@highesta
-        ori rT,SYM+offs@highera
-        sldi rT,rT,32
-        oris rT,rT,SYM+offs@ha
-        ld rD,SYM+offs@l(rT)
-      }
+	  { ELFv2 PIC: load via TOC, never materialize absolute addresses }
+	  if (cs_create_pic in current_settings.moduleswitches) and
+		 (target_info.abi = abi_powerpc_elfv2) then
+		begin
+		  tmpref.base := NR_RTOC;
+          tmpref.refaddr := addr_no;
+          list.concat(taicpu.op_reg_ref(op, reg, tmpref));
+        exit;
+        end;
+
+      { NON-PIC fallback (static / non-shared only) }
       tmpref.refaddr := addr_highesta;
       list.concat(taicpu.op_reg_ref(A_LIS, tmpreg, tmpref));
       tmpref.refaddr := addr_highera;

+ 4 - 3
compiler/powerpc64/cpupara.pas

@@ -547,9 +547,10 @@ implemented
         { general rule: aggregate data is aligned in the most significant bits
           except for ELFv1 c) and Darwin a) }
         if (target_info.endian=endian_big) and
-           ((target_info.abi in [abi_powerpc_aix,abi_powerpc_elfv2]) or
-            ((target_info.abi=abi_powerpc_sysv) and
-             (paralen>8)) or
+           (((target_info.abi in [abi_powerpc_aix,abi_powerpc_elfv2])
+              and (target_info.system <> system_powerpc64_freebsd)) or
+            (((target_info.abi=abi_powerpc_sysv) or (target_info.system=system_powerpc64_freebsd))
+              and (paralen>8)) or
             ((target_info.abi=abi_powerpc_darwin) and
              not(paralen in [1,2,4]))) then
           tailpadding:=true

+ 4 - 4
compiler/ppcgen/aasmcpu.pas

@@ -224,7 +224,7 @@ uses cutils, cclasses;
          ops:=3;
          loadreg(0,_op1);
          loadreg(1,_op2);
-         loadsymbol(0,_op3,_op3ofs);
+         loadsymbol(2,_op3,_op3ofs);
       end;
 
      constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
@@ -290,9 +290,9 @@ uses cutils, cclasses;
          inherited create(op);
          ops:=4;
          loadreg(0,_op1);
-         loadbool(0,_op2);
-         loadreg(0,_op3);
-         loadconst(0,cardinal(_op4));
+         loadbool(1,_op2);
+         loadreg(2,_op3);
+         loadconst(3,cardinal(_op4));
       end;
 
      constructor taicpu.op_reg_reg_reg_const(op : tasmop; _op1, _op2, _op3 : tregister; _op4 : aint);

+ 3 - 3
compiler/systems/t_bsd.pas

@@ -753,10 +753,10 @@ initialization
 {$endif powerpc}
 {$ifdef powerpc64}
  {$ifdef freebsd}
- 	{$ifdef powerpc64le}
-   		system_powerpc64_freebsd_info.endian:=endian_little;
-	 {$else}
+ 	{$ifdef powerpc64}
    		system_powerpc64_freebsd_info.endian:=endian_big;
+	 {$else}
+   		system_powerpc64_freebsd_info.endian:=endian_little;
   	{$endif powerpc64le}
   system_powerpc64_freebsd_info.abi:=abi_powerpc_elfv2;
  {$endif freebsd}

+ 5 - 0
rtl/bsd/powerpc64/syscall.inc

@@ -244,7 +244,12 @@ asm
   ld r4, retaddress
   li r3, -1
   mtlr r4
+<<<<<<< HEAD
 .LDone
 end;
 
 
+=======
+.LDone:
+end;
+>>>>>>> f9fc27c694 (Update freebsd/powerpc64 startup files)

+ 19 - 16
rtl/freebsd/powerpc64/cprt0.as

@@ -3,6 +3,13 @@
         .machine        power8
         .abiversion     2
 
+        /* FreeBSD/ppc64: avoid @toc@ha/@toc@l relocations (not supported by some assemblers).
+           Use full 64-bit absolute address materialization for data symbols. */
+        .macro  LOAD_64BIT_ADDR ra, sym
+		addis     \ra,2,\sym@toc@ha
+		ld        \ra,\sym@toc@l(\ra)
+        .endm
+
         .section .rodata
 .LC0:
         .asciz  ""
@@ -15,8 +22,8 @@
 __progname:
         .quad   .LC0
 
+        /* Provided by startup on FreeBSD */
 		.comm	environ,8,8
-        # libc provides 'environ'
         .globl  environ
         .type   environ, @object
 
@@ -45,28 +52,25 @@ _start:
         addi    2,2,.TOC.-_start@l
         .localentry _start, .-_start
 
-        # Minimal frame (not strictly needed, but harmless)
+        # Minimal frame (save LR correctly if we create a frame)
         stdu    1,-32(1)
+        mflr    0
         std     0,16(1)
 
         # r3=argc, r4=argv, r5=envp (ELFv2 entry convention)
 
-        # Store argc (32-bit) / argv / envp into your globals (TOC-relative)
-        addis   9,2,operatingsystem_parameter_argc@toc@ha
-        addi    9,9,operatingsystem_parameter_argc@toc@l
+        # Store argc (32-bit) / argv / envp into your globals (absolute 64-bit addr)
+        LOAD_64BIT_ADDR 9, operatingsystem_parameter_argc
         stw     3,0(9)
 
-        addis   10,2,operatingsystem_parameter_argv@toc@ha
-        addi    10,10,operatingsystem_parameter_argv@toc@l
+        LOAD_64BIT_ADDR 10, operatingsystem_parameter_argv
         std     4,0(10)
 
-        addis   11,2,operatingsystem_parameter_envp@toc@ha
-        addi    11,11,operatingsystem_parameter_envp@toc@l
+        LOAD_64BIT_ADDR 11, operatingsystem_parameter_envp
         std     5,0(11)
 
         # environ = envp
-        addis   12,2,environ@toc@ha
-        addi    12,12,environ@toc@l
+        LOAD_64BIT_ADDR 12, environ
         std     5,0(12)
 
         # if (argc > 0 && argv[0] != NULL) { __progname = argv[0]; scan for last '/' }
@@ -78,8 +82,7 @@ _start:
         beq     1f
 
         # __progname = argv[0]
-        addis   7,2,__progname@toc@ha
-        addi    7,7,__progname@toc@l
+        LOAD_64BIT_ADDR 7, __progname
         std     6,0(7)
 
         # Scan for last '/' to set __progname past it
@@ -101,9 +104,9 @@ _start:
         nop
 
         # exit(main_ret)
-        mr      3,3
-        bl      exit
-        nop
+    	lwz     3,0(3)    /* r3 = exit code */
+    	li      0,1       /* syscall: exit */
+    	sc
 
         # Should not return; just in case, trap.
         trap

+ 38 - 33
rtl/freebsd/powerpc64/dllprt0.as

@@ -5,16 +5,6 @@
         .machine        power8
         .abiversion     2
 
-/* --- helpers ------------------------------------------------------------ */
-
-.macro LOAD_64BIT_VAL ra, value
-    lis       \ra,\value@highest
-    ori       \ra,\ra,\value@higher
-    sldi      \ra,\ra,32
-    oris      \ra,\ra,\value@h
-    ori       \ra,\ra,\value@l
-.endm
-
 /* ELFv2: no function descriptors; establish TOC from r12 at entry */
 .macro FUNCTION_PROLOG fn
     .text
@@ -27,6 +17,16 @@
     .localentry \fn, .-\fn
 .endm
 
+/* Load the *address* of a data symbol via TOC (large-TOC safe).
+ * Canonical sequence:
+ *   addis  ra,2,sym@toc@ha
+ *   ld     ra,sym@toc@l(ra)
+ */
+.macro LOAD_TOC_ADDR ra, sym
+    addis   \ra,2,\sym@toc@ha
+    ld      \ra,\sym@toc@l(\ra)
+.endm
+
 /* --- code --------------------------------------------------------------- */
 
         .section ".text"
@@ -38,26 +38,23 @@
 FUNCTION_PROLOG FPC_SHARED_LIB_START
     /* standard small frame */
     mflr    0
+    mr      9,1
     stdu    1,-144(1)
     std     0,16(1)
 
     /* store argc/argv/envp to RTL slots */
-    addis   10,2,operatingsystem_parameter_argc@toc@ha
-    addi    10,10,operatingsystem_parameter_argc@toc@l
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_argc
     stw     3,0(10)
 
-    addis   10,2,operatingsystem_parameter_argv@toc@ha
-    addi    10,10,operatingsystem_parameter_argv@toc@l
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_argv
     std     4,0(10)
 
-    addis   10,2,operatingsystem_parameter_envp@toc@ha
-    addi    10,10,operatingsystem_parameter_envp@toc@l
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_envp
     std     5,0(10)
 
     /* stash initial SP */
-    addis   8,2,__stkptr@toc@ha
-    addi    8,8,__stkptr@toc@l
-    std     1,0(8)
+    LOAD_TOC_ADDR 8, __stkptr
+    std     9,0(8)
 
     /* call library initialization */
     bl      PASCALMAIN
@@ -74,12 +71,19 @@ FUNCTION_PROLOG FPC_SHARED_LIB_START
  * Called when the RTL in the shared library performs halt().
  * FreeBSD: no exit_group; just exit(status).
  */
-FUNCTION_PROLOG _haltproc
-    /* r3 = operatingsystem_result */
-    addis   3,2,operatingsystem_result@toc@ha
-    addi    3,3,operatingsystem_result@toc@l
+        .text
+        .align  4
+        .globl  _haltproc
+        .type   _haltproc, @function
+_haltproc:
+        .localentry _haltproc, 0
+    /* r12 = &operatingsystem_result via GOT (large-range safe) */
+	addis	12,2,operatingsystem_result@got@ha
+	ld		12,operatingsystem_result@got@l(12)
+	
     lwz     3,0(3)
-    bl      exit
+    li      0,1       /* syscall: exit */
+    sc
     nop
     /* should not return */
     trap
@@ -94,6 +98,7 @@ __data_start:
 data_start:
 
         .section ".bss"
+        .p2align 3
 
         .type   __stkptr, @object
         .size   __stkptr, 8
@@ -104,12 +109,12 @@ __stkptr:
         .type   operatingsystem_parameters, @object
         .size   operatingsystem_parameters, 24
 operatingsystem_parameters:
-        .skip   3*8
-
-        .globl  operatingsystem_parameter_argc
-        .globl  operatingsystem_parameter_argv
-        .globl  operatingsystem_parameter_envp
-        .set    operatingsystem_parameter_argc, operatingsystem_parameters+0
-        .set    operatingsystem_parameter_argv, operatingsystem_parameters+8
-        .set    operatingsystem_parameter_envp, operatingsystem_parameters+16
-
+		.globl operatingsystem_parameter_argc
+operatingsystem_parameter_argc:
+		.skip 8
+		.globl operatingsystem_parameter_argv
+operatingsystem_parameter_argv:
+		.skip 8
+		.globl operatingsystem_parameter_envp
+operatingsystem_parameter_envp:
+		.skip 8

+ 72 - 27
rtl/freebsd/powerpc64/prt0.as

@@ -2,36 +2,55 @@
  * FreeBSD PowerPC64 (ELFv2) startup code for Free Pascal
  */
 
-.macro LOAD_64BIT_VAL ra, value
-    lis       \ra,\value@highest
-    ori       \ra,\ra,\value@higher
-    sldi      \ra,\ra,32
-    oris      \ra,\ra,\value@h
-    ori       \ra,\ra,\value@l
+/* Load the *address* of a symbol via the TOC (ELFv2 PIC/PIE-safe).
+   Sequence:
+     addis  rA, r2, sym@toc@ha
+     ld     rA, sym@toc@l(rA)
+   After this, rA = &sym. */
+.macro LOAD_TOC_ADDR ra, sym
+    addis   \ra,2,\sym@toc@ha
+    addi    \ra,\ra,\sym@toc@l
 .endm
 
+/* Regular function: assumes r2 already valid (normal call ABI). */
 .macro FUNCTION_PROLOG fn
     .text
     .align  2
     .globl  \fn
     .type   \fn,@function
 \fn:
+    .localentry \fn, 0
+.endm
+
+/* Entry point: establish r2 (TOC) from r12, then mark localentry.
+   At ELFv2 process entry, r12 contains the entry address. */
+.macro ENTRY_PROLOG fn
+    .text
+    .align  2
+    .globl  \fn
+    .type   \fn,@function
+\fn:
+    bl      1f
+1:  mflr    12
+    addis   2,12,.TOC.-1b@ha
+    addi    2,2,.TOC.-1b@l
+    .localentry \fn, .-\fn
 .endm
 
 /* Entry point for dynamic executables */
-FUNCTION_PROLOG _dynamic_start
+ENTRY_PROLOG _dynamic_start
     /* r3 = argc, r4 = argv, r5 = envp */
 
-    LOAD_64BIT_VAL 10, operatingsystem_parameter_argc
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_argc
     stw     3,0(10)
 
-    LOAD_64BIT_VAL 10, operatingsystem_parameter_argv
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_argv
     std     4,0(10)
 
-    LOAD_64BIT_VAL 10, operatingsystem_parameter_envp
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_envp
     std     5,0(10)
 
-    LOAD_64BIT_VAL 8,__stkptr
+    LOAD_TOC_ADDR 8,__stkptr
     std     1,0(8)
 
     mffs    0
@@ -44,19 +63,19 @@ FUNCTION_PROLOG _dynamic_start
     trap  /* should never return */
 
 /* Entry point for static executables */
-FUNCTION_PROLOG _start
+ENTRY_PROLOG _start
     /* FreeBSD ELFv2: r3=argc, r4=argv, r5=envp already valid */
 
-    LOAD_64BIT_VAL 10, operatingsystem_parameter_argc
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_argc
     stw     3,0(10)
 
-    LOAD_64BIT_VAL 10, operatingsystem_parameter_argv
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_argv
     std     4,0(10)
 
-    LOAD_64BIT_VAL 10, operatingsystem_parameter_envp
+    LOAD_TOC_ADDR 10, operatingsystem_parameter_envp
     std     5,0(10)
 
-    LOAD_64BIT_VAL 8,__stkptr
+    LOAD_TOC_ADDR 8,__stkptr
     std     1,0(8)
 
     mffs    0
@@ -69,33 +88,59 @@ FUNCTION_PROLOG _start
     trap
 
 FUNCTION_PROLOG _haltproc
-    /* just call FreeBSD exit() */
-    LOAD_64BIT_VAL 3, operatingsystem_result
-    lwz     3,0(3)    /* r3 = exit code */
+    /* ELFv2 PIC-safe load of operatingsystem_result */
+	addis	12,2,operatingsystem_result@got@ha
+	ld		12,operatingsystem_result@got@l(12)
+	
+    lwz     3,0(3)
     li      0,1       /* syscall: exit */
     sc
     trap
 
 /* BSS globals */
-    .data
+    .section .bss
+    .align  3
+    .globl  environ
+    .type   environ,@object
+    .size   environ,8
+environ:
+    .skip   8
+
+    .section .data
+    .align  3
+    .globl  __progname
+    .type   __progname,@object
+    .size   __progname,8
+__progname:
+    .quad   0
+
     .globl __data_start
 __data_start:
 data_start:
 
     .bss
+    .p2align 3
     .type __stkptr,@object
     .size __stkptr,8
     .globl __stkptr
 __stkptr:
     .skip 8
 
-    .type operatingsystem_parameters,@object
-    .size operatingsystem_parameters,24
-operatingsystem_parameters:
-    .skip 3*8
+    /* These MUST be real defined symbols: the RTL references them directly. */
     .globl operatingsystem_parameter_argc
+    .type  operatingsystem_parameter_argc,@object
+    .size  operatingsystem_parameter_argc,8
+operatingsystem_parameter_argc:
+    .skip 8
+
     .globl operatingsystem_parameter_argv
+    .type  operatingsystem_parameter_argv,@object
+    .size  operatingsystem_parameter_argv,8
+operatingsystem_parameter_argv:
+    .skip 8
+
     .globl operatingsystem_parameter_envp
-    .set operatingsystem_parameter_argc,operatingsystem_parameters+0
-    .set operatingsystem_parameter_argv,operatingsystem_parameters+8
-    .set operatingsystem_parameter_envp,operatingsystem_parameters+16
+    .type  operatingsystem_parameter_envp,@object
+    .size  operatingsystem_parameter_envp,8
+operatingsystem_parameter_envp:
+    .skip 8

+ 12 - 6
rtl/freebsd/powerpc64/sighnd.inc

@@ -20,7 +20,10 @@ var
   res: word;
 
 begin
-  res := 0;
+  res:=0;
+
+  { exception flags are turned off by kernel }
+  SysResetFPU;
   case sig of
     SIGFPE:
       begin
@@ -36,14 +39,15 @@ begin
         end;
         sysResetFPU;               { reset FPSCR on PowerPC64 }
       end;
+    SIGBUS :
+      res:=214;
     SIGILL,
-    SIGBUS,
-    SIGSEGV:
-      res := 216;
+    SIGSEGV :
+      res:=216;
     SIGINT:
-      res := 217;
+        res:=217;
     SIGQUIT:
-      res := 233;
+        res:=233;
   end;
 
   {$ifdef FPC_USE_SIGPROCMASK}
@@ -52,6 +56,8 @@ begin
 
   { give runtime error at the position where the signal was raised }
   if res <> 0 then
+    begin
     HandleError(res);
+    end;
 end;