diff mbox series

[v4,1/3] or1k: libgcc: initial support for openrisc

Message ID 20181106212111.31800-2-shorne@gmail.com
State New
Headers show
Series OpenRISC port | expand

Commit Message

Stafford Horne Nov. 6, 2018, 9:21 p.m. UTC
yyyy-mm-dd  Stafford Horne  <shorne@gmail.com>
	    Richard Henderson  <rth@twiddle.net>

libgcc/ChangeLog:

	* config.host: Add OpenRISC support.
	* config/or1k/*: New.
---
 libgcc/config.host                |  12 ++
 libgcc/config/or1k/lib1funcs.S    | 222 ++++++++++++++++++++++++++++++
 libgcc/config/or1k/linux-unwind.h |  87 ++++++++++++
 libgcc/config/or1k/sfp-machine.h  |  54 ++++++++
 libgcc/config/or1k/t-or1k         |  22 +++
 5 files changed, 397 insertions(+)
 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 mbox series

Patch

diff --git a/libgcc/config.host b/libgcc/config.host
index 029f6569caf..1cbc8aca1cb 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,15 @@  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"
+	;;
 pdp11-*-*)
 	tmake_file="pdp11/t-pdp11 t-fdpbit"
 	;;
diff --git a/libgcc/config/or1k/lib1funcs.S b/libgcc/config/or1k/lib1funcs.S
new file mode 100644
index 00000000000..0ec41c3eba1
--- /dev/null
+++ b/libgcc/config/or1k/lib1funcs.S
@@ -0,0 +1,222 @@ 
+/* 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
+<http://www.gnu.org/licenses/>.  */
+
+
+#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 % y
+
+   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
+<http://www.gnu.org/licenses/>.  */
+
+#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 <signal.h>
+#include <sys/ucontext.h>
+
+#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
+# <http://www.gnu.org/licenses/>.
+
+LIB1ASMSRC = or1k/lib1funcs.S
+LIB1ASMFUNCS = __mulsi3 __udivsi3 __divsi3 __umodsi3 __modsi3