From a9df7aa81abebd216596e2fa9c002b0235b29aa2 Mon Sep 17 00:00:00 2001 From: tom_at_work <tom_at_work@idefix.freepascal.org> Date: Thu, 20 Apr 2006 11:55:06 +0000 Subject: [PATCH] * forgot to commit ppc64 gprt0.as used for gprof support * fixed ppc64 exception mask stuff (same as 3136 for ppc32) git-svn-id: trunk@3298 - --- rtl/linux/powerpc64/gprt0.as | 445 ++++++++++++++++++++++++++++++++++- rtl/powerpc64/mathu.inc | 21 +- 2 files changed, 452 insertions(+), 14 deletions(-) diff --git a/rtl/linux/powerpc64/gprt0.as b/rtl/linux/powerpc64/gprt0.as index 099137f01d..c6d317792f 100644 --- a/rtl/linux/powerpc64/gprt0.as +++ b/rtl/linux/powerpc64/gprt0.as @@ -1,4 +1,441 @@ -/* -*/ - -/* empty */ +/* + * Startup code for programs linked with GNU libc, PowerPC64 + * version. + * + * Adapted from the glibc-sources (2.3.5) in the file + * + * sysdeps/powerpc/powerpc64/elf/start.S + * + * Original header follows. + */ + +/* Startup code for programs linked with GNU libc. PowerPC64 version. + Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* some macros which simplify the startup code */ + +/* load the 64 bit value "value" into register ra */ +.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 + +/* create function prolog for symbol "fn" */ +.macro FUNCTION_PROLOG fn + .section ".text" + .align 2 + .globl \fn + .section ".opd", "aw" + .align 3 +\fn: + .quad .\fn, .TOC.@tocbase, 0 + .previous + .size \fn, 24 + .type \fn, @function + .globl .\fn +.\fn: +.endm + +/* + * "ptrgl" glue code for calls via pointer. This function + * sequence loads the data from the function descriptor + * referenced by R11 into the CTR register (function address), + * R2 (GOT/TOC pointer), and R11 (the outer frame pointer). + * + * On entry, R11 must be set to point to the function descriptor. + * + * See also the 64-bit PowerPC ABI specification for more + * information, chapter 3.5.11 (in v1.7). + */ +.section ".text" +.align 3 +.globl .ptrgl +.ptrgl: + ld 0, 0(11) + std 2, 40(1) + mtctr 0 + ld 2, 8(11) + ld 11, 8(11) + bctr +.long 0 +.byte 0, 12, 128, 0, 0, 0, 0, 0 +.type .ptrgl, @function +.size .ptrgl, . - .ptrgl + +/* + * Function prolog/epilog helpers, which are part of the 64-bit + * PowerPC ABI. + * + * See also the 64-bit PowerPC ABI specification for more + * information, chapter 3.5.5, "Register saving and restoring + * function" (in v1.7). + */ + +/* Each _savegpr0_N routine saves the general registers from rN to r31, + * inclusive. When the routine is called, r1 must point to the start + * of the general register save area. R0 must contain the old LR on + * entry. + */ +_savegpr0_14: std 14,-144(1) +_savegpr0_15: std 15,-136(1) +_savegpr0_16: std 16,-128(1) +_savegpr0_17: std 17,-120(1) +_savegpr0_18: std 18,-112(1) +_savegpr0_19: std 19,-104(1) +_savegpr0_20: std 20,-96(1) +_savegpr0_21: std 21,-88(1) +_savegpr0_22: std 22,-80(1) +_savegpr0_23: std 23,-72(1) +_savegpr0_24: std 24,-64(1) +_savegpr0_25: std 25,-56(1) +_savegpr0_26: std 26,-48(1) +_savegpr0_27: std 27,-40(1) +_savegpr0_28: std 28,-32(1) +_savegpr0_29: std 29,-24(1) +_savegpr0_30: std 30,-16(1) +_savegpr0_31: + std 31,-8(1) + std 0, 16(1) + blr +.long 0 +.byte 0, 12, 64, 0, 0, 0, 0, 0 + +/* Each _restgpr0_N routine restores the general registers from rN to r31, + * inclusive. When the routine is called, r1 must point to the start + * of the general register save area. + */ +_restgpr0_14: ld 14,-144(1) +_restgpr0_15: ld 15,-136(1) +_restgpr0_16: ld 16,-128(1) +_restgpr0_17: ld 17,-120(1) +_restgpr0_18: ld 18,-112(1) +_restgpr0_19: ld 19,-104(1) +_restgpr0_20: ld 20,-96(1) +_restgpr0_21: ld 21,-88(1) +_restgpr0_22: ld 22,-80(1) +_restgpr0_23: ld 23,-72(1) +_restgpr0_24: ld 24,-64(1) +_restgpr0_25: ld 25,-56(1) +_restgpr0_26: ld 26,-48(1) +_restgpr0_27: ld 27,-40(1) +_restgpr0_28: ld 28,-32(1) +_restgpr0_29: + ld 0, 16(1) + ld 29,-24(1) + mtlr 0 + ld 30,-16(1) + ld 31,-8(1) + blr +.long 0 +.byte 0, 12, 64, 0, 0, 0, 0, 0 + +_restgpr0_30: ld 30,-16(1) +_restgpr0_31: ld 0, 16(1) + ld 31,-8(1) + mtlr 0 + blr +.long 0 +.byte 0, 12, 64, 0, 0, 0, 0, 0 + +/* Each _savegpr1_N routine saves the general registers from rN to r31, + * inclusive. When the routine is called, r12 + * must point to the start of the general register save area. + */ +_savegpr1_14: std 14,-144(12) +_savegpr1_15: std 15,-136(12) +_savegpr1_16: std 16,-128(12) +_savegpr1_17: std 17,-120(12) +_savegpr1_18: std 18,-112(12) +_savegpr1_19: std 19,-104(12) +_savegpr1_20: std 20,-96(12) +_savegpr1_21: std 21,-88(12) +_savegpr1_22: std 22,-80(12) +_savegpr1_23: std 23,-72(12) +_savegpr1_24: std 24,-64(12) +_savegpr1_25: std 25,-56(12) +_savegpr1_26: std 26,-48(12) +_savegpr1_27: std 27,-40(12) +_savegpr1_28: std 28,-32(12) +_savegpr1_29: std 29,-24(12) +_savegpr1_30: std 30,-16(12) +_savegpr1_31: std 31,-8(12) + blr +.long 0 +.byte 0, 12, 64, 0, 0, 0, 0, 0 + +/* The _restgpr1_N routines restore the general registers from rN to r31. + * When the routine is called, r12 must point to the start of the general + * register save area. + */ +_restgpr1_14: ld 14,-144(12) +_restgpr1_15: ld 15,-136(12) +_restgpr1_16: ld 16,-128(12) +_restgpr1_17: ld 17,-120(12) +_restgpr1_18: ld 18,-112(12) +_restgpr1_19: ld 19,-104(12) +_restgpr1_20: ld 20,-96(12) +_restgpr1_21: ld 21,-88(12) +_restgpr1_22: ld 22,-80(12) +_restgpr1_23: ld 23,-72(12) +_restgpr1_24: ld 24,-64(12) +_restgpr1_25: ld 25,-56(12) +_restgpr1_26: ld 26,-48(12) +_restgpr1_27: ld 27,-40(12) +_restgpr1_28: ld 28,-32(12) +_restgpr1_29: ld 29,-24(12) +_restgpr1_30: ld 30,-16(12) +_restgpr1_31: ld 31,-8(12) + blr +.long 0 +.byte 0, 12, 64, 0, 0, 0, 0, 0 +/* Each _savefpr_M routine saves the floating point registers from fM to f31, + * inclusive. When the routine is called, r1 must point to the start of the + * floating point register save area, and r0 must contain the value of LR on + * function entry. + */ +_savefpr_14: stfd 14,-144(1) +_savefpr_15: stfd 15,-136(1) +_savefpr_16: stfd 16,-128(1) +_savefpr_17: stfd 17,-120(1) +_savefpr_18: stfd 18,-112(1) +_savefpr_19: stfd 19,-104(1) +_savefpr_20: stfd 20,-96(1) +_savefpr_21: stfd 21,-88(1) +_savefpr_22: stfd 22,-80(1) +_savefpr_23: stfd 23,-72(1) +_savefpr_24: stfd 24,-64(1) +_savefpr_25: stfd 25,-56(1) +_savefpr_26: stfd 26,-48(1) +_savefpr_27: stfd 27,-40(1) +_savefpr_28: stfd 28,-32(1) +_savefpr_29: stfd 29,-24(1) +_savefpr_30: stfd 30,-16(1) +_savefpr_31: stfd 31,-8(1) + std 0, 16(1) + blr +.long 0 +.byte 0, 12, 64, 0, 0, 0, 0, 0 + +/* The _restfpr_M routines restore the floating point registers from fM to f31. + * When the routine is called, r1 must point to the start of the floating point + * register save area. + */ +_restfpr_14: lfd 14,-144(1) +_restfpr_15: lfd 15,-136(1) +_restfpr_16: lfd 16,-128(1) +_restfpr_17: lfd 17,-120(1) +_restfpr_18: lfd 18,-112(1) +_restfpr_19: lfd 19,-104(1) +_restfpr_20: lfd 20,-96(1) +_restfpr_21: lfd 21,-88(1) +_restfpr_22: lfd 22,-80(1) +_restfpr_23: lfd 23,-72(1) +_restfpr_24: lfd 24,-64(1) +_restfpr_25: lfd 25,-56(1) +_restfpr_26: lfd 26,-48(1) +_restfpr_27: lfd 27,-40(1) +_restfpr_28: lfd 28,-32(1) +_restfpr_29: + ld 0, 16(1) + lfd 29,-24(1) + mtlr 0 + lfd 30,-16(1) + lfd 31,-8(1) + blr +.long 0 +.byte 0, 12, 64, 0, 0, 0, 0, 0 + +_restfpr_30: lfd 30,-16(1) +_restfpr_31: + ld 0, 16(1) + lfd 31,-8(1) + mtlr 0 + blr +.long 0 +.byte 0, 12, 64, 0, 0, 0, 0, 0 + +/* Each _savevr_M routine saves the vector registers from vM to v31, inclusive. + * When the routine is called, r0 must point to the word just beyound the end + * of the vector register save area. On return the value of r0 is unchanged + * while r12 may be modified. + */ +/* commented out for now, unused +_savevr_20: addi r12,r0,-192 + stvx v20,r12,r0 +_savevr_21: addi r12,r0,-176 + stvx v21,r12,r0 +_savevr_22: addi r12,r0,-160 + stvx v22,r12,r0 +_savevr_23: addi r12,r0,-144 + stvx v23,r12,r0 +_savevr_24: addi r12,r0,-128 + stvx v24,r12,r0 +_savevr_25: addi r12,r0,-112 + stvx v25,r12,r0 +_savevr_26: addi r12,r0,-96 + stvx v26,r12,r0 +_savevr_27: addi r12,r0,-80 + stvx v27,r12,r0 +_savevr_28: addi r12,r0,-64 + stvx v28,r12,r0 +_savevr_29: addi r12,r0,-48 + stvx v29,r12,r0 +_savevr_30: addi r12,r0,-32 + stvx v30,r12,r0 +_savevr_31: addi r12,r0,-16 + stvx v31,r12,r0 + blr +*/ +/* The _restvr_M routines restore the vector registers from vM to v31. When the + * routine is called, r0 must point to the word just beyound the end of the + * vector register save area. On return the value of r0 is unchanged while r12 + * may be modified. + */ +/* commented out for now, unused +_restvr_20: addi r12,r0,-192 + lvx v20,r12,r0 +_restvr_21: addi r12,r0,-176 + lvx v21,r12,r0 +_restvr_22: addi r12,r0,-160 + lvx v22,r12,r0 +_restvr_23: addi r12,r0,-144 + lvx v23,r12,r0 +_restvr_24: addi r12,r0,-128 + lvx v24,r12,r0 +_restvr_25: addi r12,r0,-112 + lvx v25,r12,r0 +_restvr_26: addi r12,r0,-96 + lvx v26,r12,r0 +_restvr_27: addi r12,r0,-80 + lvx v27,r12,r0 +_restvr_28: addi r12,r0,-64 + lvx v28,r12,r0 +_restvr_29: addi r12,r0,-48 + lvx v29,r12,r0 +_restvr_30: addi r12,r0,-32 + lvx v30,r12,r0 +_restvr_31: addi r12,r0,-16 + lvx v31,r12,r0 + blr +*/ + +/* + * start_addresses is a structure containing the real + * entry point (next to other things not interesting to + * us here). + * + * All references in the struct are function descriptors + * + */ + .section ".rodata" + .align 3 +start_addresses: + .quad 0 /* was _SDA_BASE_ but not in 64-bit ABI*/ + .quad main_stub + .quad __libc_csu_init + .quad __libc_csu_fini + .size start_adresses, .-start_addresses + +/* + * the real entry point for the program + */ +FUNCTION_PROLOG _start + mr 9,1 /* save the stack pointer */ + + /* Set up an initial stack frame, and clear the LR. */ + + clrrdi 1,1,4 + li 0,0 + stdu 1,-128(1) + mtlr 0 + std 0,0(1) + + /* put the address of start_addresses in r8... */ + /* PPC64 ABI uses R13 for thread local, so we leave it alone */ + LOAD_64BIT_VAL 8, start_addresses + + b .__libc_start_main + nop /* a NOP for the linker */ + +/* + * This is our FreePascal main procedure which is called by + * libc after initializing. + */ + +FUNCTION_PROLOG main_stub + mflr 0 + std 0,16(1) + stdu 1,-128(1) + + LOAD_64BIT_VAL 8, operatingsystem_parameter_argc + stw 3,0(8) + + LOAD_64BIT_VAL 8, operatingsystem_parameter_argv + std 4,0(8) + + LOAD_64BIT_VAL 8, operatingsystem_parameter_envp + std 5,0(8) + + LOAD_64BIT_VAL 8, __stkptr + std 1,0(8) + + LOAD_64BIT_VAL 8, ___fpc_ret + std 1,0(8) + + LOAD_64BIT_VAL 3, _start + ld 3, 0(3) + LOAD_64BIT_VAL 4, etext + bl .__monstartup + nop + + LOAD_64BIT_VAL 3, _mcleanup + bl .atexit + nop + + bl .PASCALMAIN + nop + + b ._haltproc + +FUNCTION_PROLOG _haltproc + LOAD_64BIT_VAL 8, ___fpc_ret + ld 1, 0(8) + addi 1, 1, 128 + ld 0, 16(1) + mtlr 0 + blr + + /* Define a symbol for the first piece of initialized data. */ + .section ".data" + .globl __data_start +__data_start: +data_start: + +___fpc_ret: /* return address to libc */ + .quad 0 + +.text + .comm __stkptr, 8 + + .comm operatingsystem_parameter_argc, 4 + .comm operatingsystem_parameter_argv, 8 + .comm operatingsystem_parameter_envp, 8 diff --git a/rtl/powerpc64/mathu.inc b/rtl/powerpc64/mathu.inc index aedc9e4a72..69895cad7b 100644 --- a/rtl/powerpc64/mathu.inc +++ b/rtl/powerpc64/mathu.inc @@ -21,6 +21,7 @@ const UnderflowMask = %00100000; ZeroDivideMask = %00010000; InexactMask = %00001000; + ExceptionsPendingMask = %11111111111111100000011100000000; ExceptionMask = InvalidOperationMask or OverflowMask or UnderflowMask or ZeroDivideMask or InexactMask; @@ -29,14 +30,14 @@ const function getFPSCR : DWord; assembler; nostackframe; asm mffs f0 - stfd f0, -8(r1) - ld r3, -8(r1) + stfd f0, -12(r1) + lwz r3, -8(r1) end; procedure setFPSCR(newFPSCR : DWord); assembler; nostackframe; asm - std r3, -8(r1) - lfd f0, -8(r1) + stw r3, -8(r1) + lfd f0, -12(r1) mtfsf 255, f0 end; @@ -80,15 +81,15 @@ end; function GetExceptionMask: TFPUExceptionMask; begin result := []; - if ((getFPSCR and InvalidOperationMask) <> 0) then + if ((getFPSCR and InvalidOperationMask) = 0) then result := result + [exInvalidOp]; - if ((getFPSCR and OverflowMask) <> 0) then + if ((getFPSCR and OverflowMask) = 0) then result := result + [exOverflow]; - if ((getFPSCR and UnderflowMask) <> 0) then + if ((getFPSCR and UnderflowMask) = 0) then result := result + [exUnderflow]; - if ((getFPSCR and ZeroDivideMask) <> 0) then + if ((getFPSCR and ZeroDivideMask) = 0) then result := result + [exZeroDivide]; - if ((getFPSCR and InexactMask) <> 0) then + if ((getFPSCR and InexactMask) = 0) then result := result + [exPrecision]; end; @@ -108,7 +109,7 @@ begin if (exPrecision in Mask) then mode := mode or InexactMask; - setFPSCR((getFPSCR and (not ExceptionMask)) or mode); + setFPSCR((getFPSCR or ExceptionMask) and not mode and not ExceptionsPendingMask); result := Mask - [exDenormalized]; end;