diff options
Diffstat (limited to 'gcc-4.9/libgcc/config/sparc')
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/crtfastmath.c | 44 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/crti.S | 77 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/crtn.S | 63 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/lb1spc.S | 784 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/libgcc-glibc.ver | 93 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/linux-unwind.h | 215 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/sol2-c1.S | 103 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/sol2-unwind.h | 414 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/t-linux | 4 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/t-linux64 | 1 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/t-softmul | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/sparc/t-sol2 | 6 |
12 files changed, 1806 insertions, 0 deletions
diff --git a/gcc-4.9/libgcc/config/sparc/crtfastmath.c b/gcc-4.9/libgcc/config/sparc/crtfastmath.c new file mode 100644 index 000000000..2bc2fb5b4 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/crtfastmath.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2001-2014 Free Software Foundation, Inc. + * Contributed by David S. Miller (davem@redhat.com) + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 3, or (at your option) any + * later version. + * + * This file 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 + * General Public License for more details. + * + * Under Section 7 of GPL version 3, you are granted additional + * permissions described in the GCC Runtime Library Exception, version + * 3.1, as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License and + * a copy of the GCC Runtime Library Exception along with this program; + * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#define FPRS_NS (1 << 22) /* Non-Standard fpu results */ + +static void __attribute__((constructor)) +set_fast_math (void) +{ + unsigned int fsr; + + /* This works for the 64-bit case because, even if 32-bit ld/st of + the fsr register modified the upper 32-bit, the only thing up there + are the 3 other condition codes which are "do not care" at the time + that this runs. */ + + __asm__("st %%fsr, %0" + : "=m" (fsr)); + + fsr |= FPRS_NS; + + __asm__("ld %0, %%fsr" + : : "m" (fsr)); +} diff --git a/gcc-4.9/libgcc/config/sparc/crti.S b/gcc-4.9/libgcc/config/sparc/crti.S new file mode 100644 index 000000000..e48aefb81 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/crti.S @@ -0,0 +1,77 @@ +! crti.S for SPARC + +! Copyright (C) 1992-2014 Free Software Foundation, Inc. +! Written By David Vinayak Henkel-Wallace, June 1992 +! +! This file is free software; you can redistribute it and/or modify it +! under the terms of the GNU General Public License as published by the +! Free Software Foundation; either version 3, or (at your option) any +! later version. +! +! This file 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 +! General Public License for more details. +! +! Under Section 7 of GPL version 3, you are granted additional +! permissions described in the GCC Runtime Library Exception, version +! 3.1, as published by the Free Software Foundation. +! +! You should have received a copy of the GNU General Public License and +! a copy of the GCC Runtime Library Exception along with this program; +! see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +! <http://www.gnu.org/licenses/>. + +! This file just make a stack frame for the contents of the .fini and +! .init sections. Users may put any desired instructions in those +! sections. + +! This file is linked in before the Values-Xx.o files and also before +! crtbegin, with which perhaps it should be merged. + + .section ".init" + .proc 022 + .global _init + .type _init,#function + .align 4 +_init: +#ifdef _FLAT +#ifdef __sparcv9 + stx %i7, [%sp+2167] + add %sp, -176, %sp +#else + st %i7, [%sp+60] + add %sp, -96, %sp +#endif + mov %o7, %i7 +#else +#ifdef __sparcv9 + save %sp, -176, %sp +#else + save %sp, -96, %sp +#endif +#endif + + + .section ".fini" + .proc 022 + .global _fini + .type _fini,#function + .align 4 +_fini: +#ifdef _FLAT +#ifdef __sparcv9 + stx %i7, [%sp+2167] + add %sp, -176, %sp +#else + st %i7, [%sp+60] + add %sp, -96, %sp +#endif + mov %o7, %i7 +#else +#ifdef __sparcv9 + save %sp, -176, %sp +#else + save %sp, -96, %sp +#endif +#endif diff --git a/gcc-4.9/libgcc/config/sparc/crtn.S b/gcc-4.9/libgcc/config/sparc/crtn.S new file mode 100644 index 000000000..5b15f759d --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/crtn.S @@ -0,0 +1,63 @@ +! crtn.S for SPARC + +! Copyright (C) 1992-2014 Free Software Foundation, Inc. +! Written By David Vinayak Henkel-Wallace, June 1992 +! +! This file is free software; you can redistribute it and/or modify it +! under the terms of the GNU General Public License as published by the +! Free Software Foundation; either version 3, or (at your option) any +! later version. +! +! This file 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 +! General Public License for more details. +! +! Under Section 7 of GPL version 3, you are granted additional +! permissions described in the GCC Runtime Library Exception, version +! 3.1, as published by the Free Software Foundation. +! +! You should have received a copy of the GNU General Public License and +! a copy of the GCC Runtime Library Exception along with this program; +! see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +! <http://www.gnu.org/licenses/>. + +! This file just makes sure that the .fini and .init sections do in +! fact return. Users may put any desired instructions in those sections. +! This file is the last thing linked into any executable. + + .section ".init" + .align 4 +#ifdef _FLAT + mov %i7, %o7 +#ifdef __sparcv9 + ldx [%sp+2343], %i7 + sub %sp, -176, %sp +#else + ld [%sp+156], %i7 + sub %sp, -96, %sp +#endif +#else + restore +#endif + jmp %o7+8 + nop + + .section ".fini" + .align 4 +#ifdef _FLAT + mov %i7, %o7 +#ifdef __sparcv9 + ldx [%sp+2343], %i7 + sub %sp, -176, %sp +#else + ld [%sp+156], %i7 + sub %sp, -96, %sp +#endif +#else + restore +#endif + jmp %o7+8 + nop + +! Th-th-th-that is all folks! diff --git a/gcc-4.9/libgcc/config/sparc/lb1spc.S b/gcc-4.9/libgcc/config/sparc/lb1spc.S new file mode 100644 index 000000000..b60bd5740 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/lb1spc.S @@ -0,0 +1,784 @@ +/* This is an assembly language implementation of mulsi3, divsi3, and modsi3 + for the sparc processor. + + These routines are derived from the SPARC Architecture Manual, version 8, + slightly edited to match the desired calling convention, and also to + optimize them for our purposes. */ + +#ifdef L_mulsi3 +.text + .align 4 + .global .umul + .proc 4 +.umul: + or %o0, %o1, %o4 ! logical or of multiplier and multiplicand + mov %o0, %y ! multiplier to Y register + andncc %o4, 0xfff, %o5 ! mask out lower 12 bits + be mul_shortway ! can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product and clear NV cc + ! + ! long multiply + ! + mulscc %o4, %o1, %o4 ! first iteration of 33 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 ! 32nd iteration + mulscc %o4, %g0, %o4 ! last iteration only shifts + ! the upper 32 bits of product are wrong, but we do not care + retl + rd %y, %o0 + ! + ! short multiply + ! +mul_shortway: + mulscc %o4, %o1, %o4 ! first iteration of 13 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 + mulscc %o4, %o1, %o4 ! 12th iteration + mulscc %o4, %g0, %o4 ! last iteration only shifts + rd %y, %o5 + sll %o4, 12, %o4 ! left shift partial product by 12 bits + srl %o5, 20, %o5 ! right shift partial product by 20 bits + retl + or %o5, %o4, %o0 ! merge for true product +#endif + +#ifdef L_divsi3 +/* + * Division and remainder, from Appendix E of the SPARC Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .div name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * true true=true => signed; true=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + .global .udiv + .align 4 + .proc 4 + .text +.udiv: + b ready_to_divide + mov 0, %g3 ! result is always positive + + .global .div + .align 4 + .proc 4 + .text +.div: + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge ready_to_divide ! no, go do the divide + xor %o1, %o0, %g3 ! compute sign in any case + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge ready_to_divide ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative + + +ready_to_divide: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta 0x2 ! ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu got_result ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu not_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc not_too_big + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b do_single_div + sub %g2, 1, %g2 + + not_too_big: + 3: cmp %o5, %o3 + blu 2b + nop + be do_single_div + nop + /* NB: these are commented out in the V8-SPARC manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + do_single_div: + subcc %g2, 1, %g2 + bl end_regular_divide + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b end_single_divloop + nop + single_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + end_single_divloop: + subcc %g2, 1, %g2 + bge single_divloop + tst %o3 + b,a end_regular_divide + +not_really_big: +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be got_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +divloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +L4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +L3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + +L2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + +L3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + +L1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + +L3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + +L2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + +L3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + 9: +end_regular_divide: + subcc %o4, 1, %o4 + bge divloop + tst %o3 + bl,a got_result + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + + +got_result: + ! check to see if answer should be < 0 + tst %g3 + bl,a 1f + sub %g0, %o2, %o2 +1: + retl + mov %o2, %o0 +#endif + +#ifdef L_modsi3 +/* This implementation was taken from glibc: + * + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ +.text + .align 4 + .global .urem + .proc 4 +.urem: + b divide + mov 0, %g3 ! result always positive + + .align 4 + .global .rem + .proc 4 +.rem: + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge 2f ! no, go do the divide + mov %o0, %g3 ! sign of remainder matches %o0 + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge 2f ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative +2: + + ! Ready to divide. Compute size of quotient; scale comparand. +divide: + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta 0x2 !ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu got_result ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu not_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc not_too_big + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b do_single_div + sub %g2, 1, %g2 + + not_too_big: + 3: cmp %o5, %o3 + blu 2b + nop + be do_single_div + nop + /* NB: these are commented out in the V8-SPARC manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + do_single_div: + subcc %g2, 1, %g2 + bl end_regular_divide + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b end_single_divloop + nop + single_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + end_single_divloop: + subcc %g2, 1, %g2 + bge single_divloop + tst %o3 + b,a end_regular_divide + +not_really_big: +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be got_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +divloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 +L4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + +L3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + +L2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + +L3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + +L1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + +L3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + +L2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + +L3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + 9: +end_regular_divide: + subcc %o4, 1, %o4 + bge divloop + tst %o3 + bl,a got_result + ! non-restoring fixup here (one instruction only!) + add %o3, %o1, %o3 + +got_result: + ! check to see if answer should be < 0 + tst %g3 + bl,a 1f + sub %g0, %o3, %o3 +1: + retl + mov %o3, %o0 + +#endif + diff --git a/gcc-4.9/libgcc/config/sparc/libgcc-glibc.ver b/gcc-4.9/libgcc/config/sparc/libgcc-glibc.ver new file mode 100644 index 000000000..b9447d139 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/libgcc-glibc.ver @@ -0,0 +1,93 @@ +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# In order to work around the very problems that force us to now generally +# create a libgcc.so, glibc reexported a number of routines from libgcc.a. +# By now choosing the same version tags for these specific routines, we +# maintain enough binary compatibility to allow future versions of glibc +# to defer implementation of these routines to libgcc.so via DT_AUXILIARY. + +%exclude { + __divdi3 + __moddi3 + __udivdi3 + __umoddi3 + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + +%ifdef __arch64__ +%define GLIBC_VER GLIBC_2.2 +%else +%define GLIBC_VER GLIBC_2.0 +%endif +%inherit GCC_3.0 GLIBC_VER +GLIBC_VER { + # Sampling of DImode arithmetic used by (at least) i386 and m68k. + __divdi3 + __moddi3 + __udivdi3 + __umoddi3 + + # Exception handling support functions used by most everyone. + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + +%if !defined (__arch64__) && defined (__LONG_DOUBLE_128__) + +# long double 128 bit support from 32-bit libgcc_s.so.1 is only available +# when configured with --with-long-double-128. Make sure all the +# symbols are available at @@GCC_LDBL_* versions to make it clear +# there is a configurable symbol set. + +%exclude { + __fixtfdi + __fixunstfdi + __floatditf + + __divtc3 + __multc3 + __powitf2 +} + +%inherit GCC_LDBL_3.0 GCC_3.0 +GCC_LDBL_3.0 { + __fixtfdi + __fixunstfdi + __floatditf +} + +%inherit GCC_LDBL_4.0.0 GCC_4.0.0 +GCC_LDBL_4.0.0 { + __divtc3 + __multc3 + __powitf2 +} + +%endif diff --git a/gcc-4.9/libgcc/config/sparc/linux-unwind.h b/gcc-4.9/libgcc/config/sparc/linux-unwind.h new file mode 100644 index 000000000..61ba47174 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/linux-unwind.h @@ -0,0 +1,215 @@ +/* DWARF2 EH unwinding support for SPARC Linux. + Copyright (C) 2004-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC 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 General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#if defined(__arch64__) + +#undef STACK_BIAS +#define STACK_BIAS 2047 + +/* 64-bit SPARC version */ +#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state + +static _Unwind_Reason_Code +sparc64_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned int *pc = context->ra; + long this_cfa = (long) context->cfa; + long new_cfa, ra_location, shifted_ra_location; + long regs_off, fpu_save_off; + long fpu_save; + int i; + + if (pc[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */ + || pc[1] != 0x91d0206d) /* ta 0x6d */ + return _URC_END_OF_STACK; + + regs_off = 192 + 128; + fpu_save_off = regs_off + (16 * 8) + (3 * 8) + (2 * 4); + + new_cfa = *(long *)(this_cfa + regs_off + (14 * 8)); + /* The frame address is %sp + STACK_BIAS in 64-bit mode. */ + new_cfa += STACK_BIAS; + fpu_save = *(long *)(this_cfa + fpu_save_off); + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = new_cfa - this_cfa; + + for (i = 1; i < 16; i++) + { + /* We never restore %sp as everything is purely CFA-based. */ + if ((unsigned int) i == __builtin_dwarf_sp_column ()) + continue; + + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = this_cfa + regs_off + (i * 8) - new_cfa; + } + for (i = 0; i < 16; i++) + { + fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 16].loc.offset + = this_cfa + (i * 8) - new_cfa; + } + if (fpu_save) + { + for (i = 0; i < 64; i++) + { + if (i > 32 && (i & 0x1)) + continue; + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset + = fpu_save + (i * 4) - new_cfa; + } + } + + /* State the rules to find the kernel's code "return address", which is + the address of the active instruction when the signal was caught. + On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we + need to preventively subtract it from the purported return address. */ + ra_location = this_cfa + regs_off + 17 * 8; + shifted_ra_location = this_cfa + regs_off + 19 * 8; /* Y register */ + *(long *)shifted_ra_location = *(long *)ra_location - 8; + fs->retaddr_column = 0; + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#define MD_FROB_UPDATE_CONTEXT sparc64_frob_update_context + +static void +sparc64_frob_update_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + /* The column of %sp contains the old CFA, not the old value of %sp. + The CFA offset already comprises the stack bias so, when %sp is the + CFA register, we must avoid counting the stack bias twice. Do not + do that for signal frames as the offset is artificial for them. */ + if (fs->regs.cfa_reg == __builtin_dwarf_sp_column () + && fs->regs.cfa_how == CFA_REG_OFFSET + && fs->regs.cfa_offset != 0 + && !fs->signal_frame) + { + long i; + + context->cfa -= STACK_BIAS; + + for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i) + if (fs->regs.reg[i].how == REG_SAVED_OFFSET) + _Unwind_SetGRPtr (context, i, + _Unwind_GetGRPtr (context, i) - STACK_BIAS); + } +} + +#else + +/* 32-bit SPARC version */ +#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state + +static _Unwind_Reason_Code +sparc_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned int *pc = context->ra; + int this_cfa = (int) context->cfa; + int new_cfa, ra_location, shifted_ra_location; + int regs_off, fpu_save_off; + int fpu_save; + int old_style, i; + + if (pc[1] != 0x91d02010) /* ta 0x10 */ + return _URC_END_OF_STACK; + + if (pc[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ + old_style = 1; + else if (pc[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ + old_style = 0; + else + return _URC_END_OF_STACK; + + if (old_style) + { + regs_off = 96; + fpu_save_off = regs_off + (4 * 4) + (16 * 4); + } + else + { + regs_off = 96 + 128; + fpu_save_off = regs_off + (4 * 4) + (16 * 4) + (2 * 4); + } + + new_cfa = *(int *)(this_cfa + regs_off + (4 * 4) + (14 * 4)); + fpu_save = *(int *)(this_cfa + fpu_save_off); + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = new_cfa - this_cfa; + + for (i = 1; i < 16; i++) + { + /* We never restore %sp as everything is purely CFA-based. */ + if ((unsigned int) i == __builtin_dwarf_sp_column ()) + continue; + + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = this_cfa + regs_off + (4 * 4) + (i * 4) - new_cfa; + } + for (i = 0; i < 16; i++) + { + fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 16].loc.offset + = this_cfa + (i * 4) - new_cfa; + } + if (fpu_save) + { + for (i = 0; i < 32; i++) + { + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset + = fpu_save + (i * 4) - new_cfa; + } + } + + /* State the rules to find the kernel's code "return address", which is + the address of the active instruction when the signal was caught. + On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we + need to preventively subtract it from the purported return address. */ + ra_location = this_cfa + regs_off + 4; + shifted_ra_location = this_cfa + regs_off + 3 * 4; /* Y register */ + *(int *)shifted_ra_location = *(int *)ra_location - 8; + fs->retaddr_column = 0; + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#endif diff --git a/gcc-4.9/libgcc/config/sparc/sol2-c1.S b/gcc-4.9/libgcc/config/sparc/sol2-c1.S new file mode 100644 index 000000000..674e1b688 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/sol2-c1.S @@ -0,0 +1,103 @@ +! crt1.s for sparc & sparcv9 (SunOS 5) + +! Copyright (C) 1992-2014 Free Software Foundation, Inc. +! Written By David Vinayak Henkel-Wallace, June 1992 +! +! This file is free software; you can redistribute it and/or modify it +! under the terms of the GNU General Public License as published by the +! Free Software Foundation; either version 3, or (at your option) any +! later version. +! +! This file 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 +! General Public License for more details. +! +! Under Section 7 of GPL version 3, you are granted additional +! permissions described in the GCC Runtime Library Exception, version +! 3.1, as published by the Free Software Foundation. +! +! You should have received a copy of the GNU General Public License and +! a copy of the GCC Runtime Library Exception along with this program; +! see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +! <http://www.gnu.org/licenses/>. + +! This file takes control of the process from the kernel, as specified +! in section 3 of the SVr4 ABI. +! This file is the first thing linked into any executable. + +#ifdef __sparcv9 +#define CPTRSIZE 8 +#define CPTRSHIFT 3 +#define STACK_BIAS 2047 +#define ldn ldx +#define stn stx +#define setn(s, scratch, dst) setx s, scratch, dst +#else +#define CPTRSIZE 4 +#define CPTRSHIFT 2 +#define STACK_BIAS 0 +#define ldn ld +#define stn st +#define setn(s, scratch, dst) set s, dst +#endif + + .section ".text" + .proc 022 + .global _start + +_start: + mov 0, %fp ! Mark bottom frame pointer + ldn [%sp + (16 * CPTRSIZE) + STACK_BIAS], %l0 ! argc + add %sp, (17 * CPTRSIZE) + STACK_BIAS, %l1 ! argv + + ! Leave some room for a call. Sun leaves 32 octets (to sit on + ! a cache line?) so we do too. +#ifdef __sparcv9 + sub %sp, 48, %sp +#else + sub %sp, 32, %sp +#endif + + ! %g1 may contain a function to be registered w/atexit + orcc %g0, %g1, %g0 +#ifdef __sparcv9 + be %xcc, .nope +#else + be .nope +#endif + mov %g1, %o0 + call atexit + nop +.nope: + ! Now make sure constructors and destructors are handled. + setn(_fini, %o1, %o0) + call atexit, 1 + nop + call _init, 0 + nop + + ! We ignore the auxiliary vector; there is no defined way to + ! access those data anyway. Instead, go straight to main: + mov %l0, %o0 ! argc + mov %l1, %o1 ! argv +#ifdef GCRT1 + setn(___Argv, %o4, %o3) + stn %o1, [%o3] ! *___Argv +#endif + ! Skip argc words past argv, to env: + sll %l0, CPTRSHIFT, %o2 + add %o2, CPTRSIZE, %o2 + add %l1, %o2, %o2 ! env + setn(_environ, %o4, %o3) + stn %o2, [%o3] ! *_environ + call main, 4 + nop + call exit, 0 + nop + call _exit, 0 + nop + ! We should never get here. + + .type _start,#function + .size _start,.-_start diff --git a/gcc-4.9/libgcc/config/sparc/sol2-unwind.h b/gcc-4.9/libgcc/config/sparc/sol2-unwind.h new file mode 100644 index 000000000..37807f9a9 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/sol2-unwind.h @@ -0,0 +1,414 @@ +/* DWARF2 EH unwinding support for SPARC Solaris. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC 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 General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#include <ucontext.h> +#include <sys/frame.h> +#include <sys/stack.h> + +#ifdef __arch64__ + +#define IS_SIGHANDLER sparc64_is_sighandler + +static int +sparc64_is_sighandler (unsigned int *pc, void *cfa, int *nframes) +{ + if (/* Solaris 9 - single-threaded + ---------------------------- + The pattern changes slightly in different versions of the + operating system, so we skip the comparison against pc[-6] for + Solaris 9. + + <sigacthandler+24>: sra %i0, 0, %l1 + + Solaris 9 5/02: + <sigacthandler+28>: ldx [ %o2 + 0xf68 ], %g5 + Solaris 9 9/05: + <sigacthandler+28>: ldx [ %o2 + 0xe50 ], %g5 + + <sigacthandler+32>: sllx %l1, 3, %g4 + <sigacthandler+36>: mov %l1, %o0 + <sigacthandler+40>: ldx [ %g4 + %g5 ], %l0 + <sigacthandler+44>: call %l0 + <sigacthandler+48>: mov %i2, %o2 + <sigacthandler+52>: cmp %l1, 8 <--- PC */ + ( pc[-7] == 0xa33e2000 + /* skip pc[-6] */ + && pc[-5] == 0x892c7003 + && pc[-4] == 0x90100011 + && pc[-3] == 0xe0590005 + && pc[-2] == 0x9fc40000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x80a46008)) + { + /* We need to move up one frame: + + <signal handler> <-- context->cfa + sigacthandler + <kernel> + */ + *nframes = 1; + return 1; + } + + if (/* Solaris 8+ - multi-threaded + ---------------------------- + <__sighndlr>: save %sp, -176, %sp + <__sighndlr+4>: mov %i0, %o0 + <__sighndlr+8>: mov %i1, %o1 + <__sighndlr+12>: call %i3 + <__sighndlr+16>: mov %i2, %o2 + <__sighndlr+20>: ret <--- PC + <__sighndlr+24>: restore */ + pc[-5] == 0x9de3bf50 + && pc[-4] == 0x90100018 + && pc[-3] == 0x92100019 + && pc[-2] == 0x9fc6c000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x81c7e008 + && pc[ 1] == 0x81e80000) + { + /* We have observed different calling frames among different + versions of the operating system, so that we need to + discriminate using the upper frame. We look for the return + address of the caller frame (there is an offset of 15 double + words between the frame address and the place where this return + address is stored) in order to do some more pattern matching. */ + unsigned int cuh_pattern + = *(unsigned int *)(*(unsigned long *)(cfa + 15*8) - 4); + + if (cuh_pattern == 0x92100019) + /* This matches the call_user_handler pattern for Solaris 11. + This is the same setup as for Solaris 9, see below. */ + *nframes = 3; + + else if (cuh_pattern == 0xd25fa7ef) + { + /* This matches the call_user_handler pattern for Solaris 10. + There are 2 cases so we look for the return address of the + caller's caller frame in order to do more pattern matching. */ + unsigned long sah_address = *(unsigned long *)(cfa + 176 + 15*8); + + if (sah_address && *(unsigned int *)(sah_address - 4) == 0x92100019) + /* This is the same setup as for Solaris 9, see below. */ + *nframes = 3; + else + /* The sigacthandler frame isn't present in the chain. + We need to move up two frames: + + <signal handler> <-- context->cfa + __sighndlr + call_user_handler frame + <kernel> + */ + *nframes = 2; + } + + else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x94100013) + /* This matches the call_user_handler pattern for Solaris 9. + We need to move up three frames: + + <signal handler> <-- context->cfa + __sighndlr + call_user_handler + sigacthandler + <kernel> + */ + *nframes = 3; + + return 1; + } + + return 0; +} + +#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state + +#define MD_FROB_UPDATE_CONTEXT sparc64_frob_update_context + +static void +sparc64_frob_update_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + /* The column of %sp contains the old CFA, not the old value of %sp. + The CFA offset already comprises the stack bias so, when %sp is the + CFA register, we must avoid counting the stack bias twice. */ + if (fs->regs.cfa_reg == __builtin_dwarf_sp_column () + && fs->regs.cfa_how == CFA_REG_OFFSET + && fs->regs.cfa_offset != 0) + { + long i; + + context->cfa -= STACK_BIAS; + + for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i) + if (fs->regs.reg[i].how == REG_SAVED_OFFSET) + _Unwind_SetGRPtr (context, i, + _Unwind_GetGRPtr (context, i) - STACK_BIAS); + } +} + +#else + +#define IS_SIGHANDLER sparc_is_sighandler + +static int +sparc_is_sighandler (unsigned int *pc, void *cfa, int *nframes) +{ + if (/* Solaris 9 - single-threaded + ---------------------------- + The pattern changes slightly in different versions of the operating + system, so we skip the comparison against pc[-6]. + + <sigacthandler+16>: add %o1, %o7, %o3 + <sigacthandler+20>: mov %i1, %o1 + + <sigacthandler+24>: ld [ %o3 + <offset> ], %o2 + + <sigacthandler+28>: sll %i0, 2, %o0 + <sigacthandler+32>: ld [ %o0 + %o2 ], %l0 + <sigacthandler+36>: mov %i0, %o0 + <sigacthandler+40>: call %l0 + <sigacthandler+44>: mov %i2, %o2 + <sigacthandler+48>: cmp %i0, 8 <--- PC */ + pc[-8] == 0x9602400f + && pc[-7] == 0x92100019 + /* skip pc[-6] */ + && pc[-5] == 0x912e2002 + && pc[-4] == 0xe002000a + && pc[-3] == 0x90100018 + && pc[-2] == 0x9fc40000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x80a62008) + { + /* We need to move up one frame: + + <signal handler> <-- context->cfa + sigacthandler + <kernel> + */ + *nframes = 1; + return 1; + } + + if(/* Solaris 8+ - multi-threaded + ---------------------------- + <__sighndlr>: save %sp, -96, %sp + <__sighndlr+4>: mov %i0, %o0 + <__sighndlr+8>: mov %i1, %o1 + <__sighndlr+12>: call %i3 + <__sighndlr+16>: mov %i2, %o2 + <__sighndlr+20>: ret <--- PC + <__sighndlr+24>: restore */ + pc[-5] == 0x9de3bfa0 + && pc[-4] == 0x90100018 + && pc[-3] == 0x92100019 + && pc[-2] == 0x9fc6c000 + && pc[-1] == 0x9410001a + && pc[ 0] == 0x81c7e008 + && pc[ 1] == 0x81e80000) + { + /* We have observed different calling frames among different + versions of the operating system, so that we need to + discriminate using the upper frame. We look for the return + address of the caller frame (there is an offset of 15 words + between the frame address and the place where this return + address is stored) in order to do some more pattern matching. */ + unsigned int cuh_pattern + = *(unsigned int *)(*(unsigned int *)(cfa + 15*4) - 4); + + if (cuh_pattern == 0x92100019) + /* This matches the call_user_handler pattern for Solaris 11. + This is the same setup as for Solaris 9, see below. */ + *nframes = 3; + + else if (cuh_pattern == 0xd407a04c) + { + /* This matches the call_user_handler pattern for Solaris 10. + There are 2 cases so we look for the return address of the + caller's caller frame in order to do more pattern matching. */ + unsigned int sah_address = *(unsigned int *)(cfa + 96 + 15*4); + + if (sah_address && *(unsigned int *)(sah_address - 4) == 0x92100019) + /* This is the same setup as for Solaris 9, see below. */ + *nframes = 3; + else + /* The sigacthandler frame isn't present in the chain. + We need to move up two frames: + + <signal handler> <-- context->cfa + __sighndlr + call_user_handler frame + <kernel> + */ + *nframes = 2; + } + + else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x9410001b) + /* This matches the call_user_handler pattern for Solaris 9. + We need to move up three frames: + + <signal handler> <-- context->cfa + __sighndlr + call_user_handler + sigacthandler + <kernel> + */ + *nframes = 3; + + return 1; + } + + return 0; +} + +#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state + +#endif + +static _Unwind_Reason_Code +MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + void *pc = context->ra; + void *this_cfa = context->cfa; + int nframes = 0; + long new_cfa; + void *ra_location, *shifted_ra_location; + mcontext_t *mctx; + int i; + + /* Deal with frame-less function from which a signal was raised. */ + if (_Unwind_IsSignalFrame (context)) + { + /* The CFA is by definition unmodified in this case. */ + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = 0; + + /* This is the canonical RA column. */ + fs->retaddr_column = 15; + + return _URC_NO_REASON; + } + + /* Do some pattern matching at the return address. */ + if (IS_SIGHANDLER (pc, this_cfa, &nframes)) + { + struct frame *fp = (struct frame *) this_cfa; + struct handler_args { + struct frame frwin; + ucontext_t ucontext; + } *handler_args; + ucontext_t *ucp; + + /* this_cfa points into the frame after the saved frame pointer and + saved pc (struct frame). + + The ucontext_t structure is in the kernel frame after a struct + frame. Since the frame sizes vary even within OS releases, we + need to walk the stack to get there. */ + for (i = 0; i < nframes; i++) + fp = (struct frame *) ((char *)fp->fr_savfp + STACK_BIAS); + + handler_args = (struct handler_args *) fp; + ucp = &handler_args->ucontext; + mctx = &ucp->uc_mcontext; + } + else + return _URC_END_OF_STACK; + + /* The frame address is %sp + STACK_BIAS in 64-bit mode. */ + new_cfa = mctx->gregs[REG_SP] + STACK_BIAS; + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = new_cfa - (long) this_cfa + STACK_BIAS; + + /* Restore global and out registers (in this order) from the + ucontext_t structure, uc_mcontext.gregs field. */ + for (i = 1; i < 16; i++) + { + /* We never restore %sp as everything is purely CFA-based. */ + if ((unsigned int) i == __builtin_dwarf_sp_column ()) + continue; + + /* First the global registers and then the out registers. */ + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = (long)&mctx->gregs[REG_Y + i] - new_cfa; + } + + /* Just above the stack pointer there are 16 extended words in which + the register window (in and local registers) was saved. */ + for (i = 0; i < 16; i++) + { + fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 16].loc.offset = i * sizeof(long); + } + + /* Check whether we need to restore FPU registers. */ + if (mctx->fpregs.fpu_qcnt) + { + for (i = 0; i < 32; i++) + { + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset + = (long)&mctx->fpregs.fpu_fr.fpu_regs[i] - new_cfa; + } + +#ifdef __arch64__ + /* For 64-bit, fpu_fr.fpu_dregs contains 32 instead of 16 doubles. */ + for (i = 32; i < 64; i++) + { + if (i > 32 && (i & 1)) + continue; + + fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.reg[i + 32].loc.offset + = (long)&mctx->fpregs.fpu_fr.fpu_dregs[i/2] - new_cfa; + } +#endif + } + + /* State the rules to find the kernel's code "return address", which is + the address of the active instruction when the signal was caught. + On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we + need to preventively subtract it from the purported return address. */ + ra_location = &mctx->gregs[REG_PC]; + shifted_ra_location = &mctx->gregs[REG_Y]; + *(void **)shifted_ra_location = *(void **)ra_location - 8; + fs->retaddr_column = 0; + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (long)shifted_ra_location - new_cfa; + + /* SIGFPE for IEEE-754 exceptions is delivered after the faulting insn + rather than before it, so don't set fs->signal_frame in that case. + We test whether the cexc field of the FSR is zero. */ + if ((mctx->fpregs.fpu_fsr & 0x1f) == 0) + fs->signal_frame = 1; + + return _URC_NO_REASON; +} diff --git a/gcc-4.9/libgcc/config/sparc/t-linux b/gcc-4.9/libgcc/config/sparc/t-linux new file mode 100644 index 000000000..474f1755e --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/t-linux @@ -0,0 +1,4 @@ +# Override t-slibgcc-elf-ver to export some libgcc symbols with +# the symbol versions that glibc used. +# Avoid the t-linux version file. +SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/sparc/libgcc-glibc.ver diff --git a/gcc-4.9/libgcc/config/sparc/t-linux64 b/gcc-4.9/libgcc/config/sparc/t-linux64 new file mode 100644 index 000000000..6583fe25a --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/t-linux64 @@ -0,0 +1 @@ +CRTSTUFF_T_CFLAGS = -mcmodel=medany diff --git a/gcc-4.9/libgcc/config/sparc/t-softmul b/gcc-4.9/libgcc/config/sparc/t-softmul new file mode 100644 index 000000000..714220060 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/t-softmul @@ -0,0 +1,2 @@ +LIB1ASMSRC = sparc/lb1spc.S +LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 diff --git a/gcc-4.9/libgcc/config/sparc/t-sol2 b/gcc-4.9/libgcc/config/sparc/t-sol2 new file mode 100644 index 000000000..ea3fa63a2 --- /dev/null +++ b/gcc-4.9/libgcc/config/sparc/t-sol2 @@ -0,0 +1,6 @@ +# We need to use -fPIC when we are using gcc to compile the routines in +# crtstuff.c. This is only really needed when we are going to use gcc/g++ +# to produce a shared library, but since we don't know ahead of time when +# we will be doing that, we just always use -fPIC when compiling the +# routines in crtstuff.c. +CRTSTUFF_T_CFLAGS = $(PICFLAG) |