From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stafford Horne Date: Sat, 27 Oct 2018 13:37:00 +0900 Subject: [OpenRISC] [PATCH v3 1/3] or1k: libgcc: initial support for openrisc In-Reply-To: <20181027043702.18414-1-shorne@gmail.com> References: <20181027043702.18414-1-shorne@gmail.com> Message-ID: <20181027043702.18414-2-shorne@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: openrisc@lists.librecores.org yyyy-mm-dd Stafford Horne Richard Henderson libgcc/ChangeLog: * config.host: Add OpenRISC support. * config/or1k/*: New. --- libgcc/config.host | 13 ++ libgcc/config/or1k/crti.S | 33 +++++ libgcc/config/or1k/crtn.S | 1 + libgcc/config/or1k/lib1funcs.S | 223 ++++++++++++++++++++++++++++++ libgcc/config/or1k/linux-unwind.h | 87 ++++++++++++ libgcc/config/or1k/sfp-machine.h | 54 ++++++++ libgcc/config/or1k/t-or1k | 22 +++ 7 files changed, 433 insertions(+) create mode 100644 libgcc/config/or1k/crti.S create mode 100644 libgcc/config/or1k/crtn.S create mode 100644 libgcc/config/or1k/lib1funcs.S create mode 100644 libgcc/config/or1k/linux-unwind.h create mode 100644 libgcc/config/or1k/sfp-machine.h create mode 100644 libgcc/config/or1k/t-or1k diff --git a/libgcc/config.host b/libgcc/config.host index 029f6569caf..e32b2541ea1 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -165,6 +165,9 @@ nds32*-*) nios2*-*-*) cpu_type=nios2 ;; +or1k*-*-*) + cpu_type=or1k + ;; powerpc*-*-*) cpu_type=rs6000 ;; @@ -1039,6 +1042,16 @@ nios2-*-*) tmake_file="$tmake_file nios2/t-nios2 t-softfp-sfdf t-softfp-excl t-softfp" extra_parts="$extra_parts crti.o crtn.o" ;; +or1k-*-linux*) + tmake_file="$tmake_file or1k/t-or1k" + tmake_file="$tmake_file t-softfp-sfdf t-softfp" + md_unwind_header=or1k/linux-unwind.h + ;; +or1k-*-*) + tmake_file="$tmake_file or1k/t-or1k" + tmake_file="$tmake_file t-softfp-sfdf t-softfp" + extra_parts="$extra_parts crti.o crtn.o" + ;; pdp11-*-*) tmake_file="pdp11/t-pdp11 t-fdpbit" ;; diff --git a/libgcc/config/or1k/crti.S b/libgcc/config/or1k/crti.S new file mode 100644 index 00000000000..9fcf6ae5995 --- /dev/null +++ b/libgcc/config/or1k/crti.S @@ -0,0 +1,33 @@ +/* Copyright (C) 2012-2018 Free Software Foundation, Inc. + +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 +. */ + +/* Here _init and _fini are empty because .init_array/.fini_array are used + exclusively. However, the functions are still needed as required when + linking. */ + .align 4 + .global _init + .type _init, at function +_init: + .global _fini + .type _fini, at function +_fini: + l.jr r9 + l.nop diff --git a/libgcc/config/or1k/crtn.S b/libgcc/config/or1k/crtn.S new file mode 100644 index 00000000000..ca6ee7b6fba --- /dev/null +++ b/libgcc/config/or1k/crtn.S @@ -0,0 +1 @@ +/* crtn.S is empty because .init_array/.fini_array are used exclusively. */ diff --git a/libgcc/config/or1k/lib1funcs.S b/libgcc/config/or1k/lib1funcs.S new file mode 100644 index 00000000000..354aadae8c4 --- /dev/null +++ b/libgcc/config/or1k/lib1funcs.S @@ -0,0 +1,223 @@ +/* Copyright (C) 2018 Free Software Foundation, Inc. + +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 +. */ + + +#ifdef L__mulsi3 + .balign 4 + .globl __mulsi3 + .type __mulsi3, @function +__mulsi3: + l.movhi r11, 0 /* initial r */ + + /* Given R = X * Y ... */ +1: l.sfeq r4, r0 /* while (y != 0) */ + l.bf 2f + l.andi r5, r4, 1 /* if (y & 1) ... */ + l.add r12, r11, r3 + l.sfne r5, r0 +#if defined(__or1k_cmov__) + l.cmov r11, r12, r11 /* ... r += x. */ + l.srli r4, r4, 1 /* y >>= 1 */ +#else + l.bnf 3f + l.srli r4, r4, 1 /* y >>= 1 */ + l.ori r11, r12, 0 +3: +#endif + l.j 1b + l.add r3, r3, r3 /* x <<= 1 */ + +2: l.jr r9 + l.nop + + .size __mulsi3, . - __mulsi3 +#endif + +#if defined(L__udivsi3) || defined(L__umodsi3) \ + || defined(L__divsi3) || defined(L__modsi3) + .global __udivmodsi3_internal + .hidden __udivmodsi3_internal + .type __udivmodsi3_internal, @function +#endif + +#ifdef L__udivsi3 + .balign 4 + .global __udivsi3 + .type __udivsi3, @function +__udivsi3: +__udivmodsi3_internal: + /* Note that the other division routines assume that r13 + is not clobbered by this routine, and use that as to + save a return address without creating a stack frame. */ + + l.sfeqi r4, 0 /* division by zero; return 0. */ + l.ori r11, r0, 0 /* initial quotient */ + l.bf 9f + l.ori r12, r3, 0 /* initial remainder */ + + /* Given X/Y, shift Y left until Y >= X. */ + l.ori r6, r0, 1 /* mask = 1 */ +1: l.sfltsi r4, 0 /* y has msb set */ + l.bf 2f + l.sfltu r4, r12 /* y < x */ + l.add r4, r4, r4 /* y <<= 1 */ + l.bnf 1b + l.add r6, r6, r6 /* mask <<= 1 */ + + /* Shift Y back to the right again, subtracting from X. */ +2: l.add r7, r11, r6 /* tmp1 = quot + mask */ +3: l.srli r6, r6, 1 /* mask >>= 1 */ + l.sub r8, r12, r4 /* tmp2 = x - y */ + l.sfleu r4, r12 /* y <= x */ + l.srli r4, r4, 1 /* y >>= 1 */ +#if defined(__or1k_cmov__) + l.cmov r11, r7, r11 /* if (y <= x) quot = tmp1 */ + l.cmov r12, r8, r12 /* if (y <= x) x = tmp2 */ +#else + l.bnf 4f + l.nop + l.ori r11, r7, 0 + l.ori r12, r8, 0 +4: +#endif + l.sfne r6, r0 /* loop until mask == 0 */ + l.bf 3b + l.add r7, r11, r6 /* delay fill from loop start */ + +9: l.jr r9 + l.nop + + .size __udivsi3, . - __udivsi3 + .size __udivmodsi3_internal, . - __udivmodsi3_internal +#endif + +#ifdef L__umodsi3 + .balign 4 + .global __umodsi3 + .type __umodsi3, @function + .cfi_startproc +__umodsi3: + /* Know that __udivmodsi3_internal does not clobber r13. */ + l.ori r13, r9, 0 + .cfi_register 9, 13 + l.jal __udivmodsi3_internal + l.nop + l.jr r13 /* return to saved lr */ + l.ori r11, r12, 0 /* move remainder to rv */ + + .cfi_endproc + .size __umodsi3, . - __umodsi3 +#endif + +/* For signed division we do: + * + * -x / y = x / -y = -(x / y) + * -x % y = -(x % y) + * x % -y = x % b + * + * which has the property that (x/y)*y + (x%y) = x. + */ + +#ifdef L__divsi3 + .balign 4 + .global __divsi3 + .type __divsi3, @function + .cfi_startproc +__divsi3: + l.xor r6, r3, r4 /* need result negate? */ + + l.sflts r3, r0 /* abs(x) */ +#if defined(__or1k_cmov__) + l.sub r5, r0, r3 + l.cmov r3, r5, r3 +#else + l.bnf 1f + l.sub r5, r0, r3 + l.ori r3, r5, 0 +1: +#endif + l.sflts r4, r0 /* abs(y) */ +#if defined(__or1k_cmov__) + l.sub r5, r0, r4 + l.cmov r4, r5, r4 +#else + l.bnf 2f + l.sub r5, r0, r4 + l.ori r4, r5, 0 +2: +#endif + + /* If the result will not require sign flip, tail call. */ + l.sflts r6, r0 + l.bnf __udivmodsi3_internal + l.ori r13, r9, 0 /* save lr */ + + /* Otherwise, know that __udivmodsi3_internal does not clobber r13. + Perform a normal call, then negate and return via saved lr. */ + .cfi_register 9, 13 + l.jal __udivmodsi3_internal + l.nop + l.jr r13 + l.sub r11, r0, r11 + + .cfi_endproc + .size __divsi3, . - __divsi3 +#endif + +#ifdef L__modsi3 + .balign 4 + .global __modsi3 + .type __modsi3, @function + .cfi_startproc +__modsi3: + l.sflts r4, r0 /* abs(y) */ +#if defined(__or1k_cmov__) + l.sub r5, r0, r4 + l.cmov r4, r5, r4 +#else + l.bnf 2f + l.sub r5, r0, r4 + l.ori r4, r5, 0 +2: +#endif + + l.sflts r3, r0 /* x negative? */ + l.bf 1f + l.ori r13, r9, 0 /* save lr */ + + /* Know that __udivmodsi3_internal does not clobber r13. */ + .cfi_register 9, 13 + + /* X positive; no negate of the result required. */ + l.jal __udivmodsi3_internal + l.nop + l.jr r13 /* return to saved lr */ + l.ori r11, r12, 0 /* move remainder to rv */ + + /* X negative; negate both X and the result. */ +1: l.jal __udivmodsi3_internal + l.sub r3, r0, r3 + l.jr r13 /* return to saved lr */ + l.sub r11, r0, r12 /* negate remainder to rv */ + + .cfi_endproc + .size __modsi3, .- __modsi3 +#endif diff --git a/libgcc/config/or1k/linux-unwind.h b/libgcc/config/or1k/linux-unwind.h new file mode 100644 index 00000000000..e80e9e0f309 --- /dev/null +++ b/libgcc/config/or1k/linux-unwind.h @@ -0,0 +1,87 @@ +/* DWARF2 EH unwinding support for OpenRISC Linux. + Copyright (C) 2018 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 +. */ + +#ifndef inhibit_libc +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#include +#include + +#define MD_FALLBACK_FRAME_STATE_FOR or1k_fallback_frame_state + +static _Unwind_Reason_Code +or1k_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned int *pc = context->ra; + struct rt_sigframe { + siginfo_t info; + ucontext_t uc; + } *rt; + struct sigcontext *sc; + long new_cfa; + int i; + + if (pc[0] != 0xa960008b /* l.ori r11, r0, NR_rt_sigreturn */ + || pc[1] != 0x20000001) /* l.sys 1 */ + return _URC_END_OF_STACK; + if (context->cfa == 0) + return _URC_END_OF_STACK; + + rt = context->cfa; + sc = &rt->uc.uc_mcontext; + + new_cfa = sc->regs.gpr[1]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 1; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + for (i = 2; i < 32; ++i) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = (long) &sc->regs.gpr[i] - new_cfa; + } + fs->regs.reg[32].how = REG_SAVED_OFFSET; + fs->regs.reg[32].loc.offset = (long)&sc->regs.pc - new_cfa; + fs->retaddr_column = 32; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#define MD_FROB_UPDATE_CONTEXT or1k_frob_update_context + +/* Fix up for signal handlers that don't have S flag set. */ + +static void +or1k_frob_update_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs ATTRIBUTE_UNUSED) +{ + unsigned int *pc = context->ra; + + if (pc[0] == 0xa960008b /* l.ori r11, r0, NR_rt_sigreturn */ + && pc[1] == 0x20000001) /* l.sys 1 */ + _Unwind_SetSignalFrame (context, 1); +} +#endif diff --git a/libgcc/config/or1k/sfp-machine.h b/libgcc/config/or1k/sfp-machine.h new file mode 100644 index 00000000000..5da9e84990d --- /dev/null +++ b/libgcc/config/or1k/sfp-machine.h @@ -0,0 +1,54 @@ +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) + +#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) +#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 +#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 +#define _FP_NANSIGN_S 0 +#define _FP_NANSIGN_D 0 +#define _FP_NANSIGN_Q 0 + +#define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 + +/* Someone please check this. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \ + && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#define __BYTE_ORDER __BIG_ENDIAN + +#define _FP_TININESS_AFTER_ROUNDING 0 + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); diff --git a/libgcc/config/or1k/t-or1k b/libgcc/config/or1k/t-or1k new file mode 100644 index 00000000000..73a703ac58d --- /dev/null +++ b/libgcc/config/or1k/t-or1k @@ -0,0 +1,22 @@ +# Libgcc Makefile fragment for OpenRISC +# Copyright (C) 2018 Free Software Foundation, Inc. +# Contributed by Stafford Horne. +# +# 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 +# . + +LIB1ASMSRC = or1k/lib1funcs.S +LIB1ASMFUNCS = __mulsi3 __udivsi3 __divsi3 __umodsi3 __modsi3 -- 2.17.1