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

Message ID 20181027043702.18414-2-shorne@gmail.com
State New
Headers show
Series
  • OpenRISC port
Related show

Commit Message

Stafford Horne Oct. 27, 2018, 4:37 a.m.
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                |  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

-- 
2.17.1

Comments

Segher Boessenkool Oct. 27, 2018, 11:25 p.m. | #1
Hi!

On Sat, Oct 27, 2018 at 01:37:00PM +0900, Stafford Horne wrote:
> +	/* Given R = X * Y ... */

> +1:	l.sfeq		r4, r0			/* while (y != 0) */

> +	l.bf		2f

> +	 l.andi		r5, r4, 1		/* if (y & 1) ... */


Do the extra leading spaces mean something?

> +        l.sfeqi		r4, 0		/* division by zero; return 0.  */


In some places (like here) you ident with 8 spaces instead of a tab.

> +/* 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.

> + */


You mean "y" instead of "b" I think.


Segher
Stafford Horne Oct. 28, 2018, 12:37 a.m. | #2
Hi,

Thanks for the review.

On Sat, Oct 27, 2018 at 06:25:04PM -0500, Segher Boessenkool wrote:
> Hi!

> 

> On Sat, Oct 27, 2018 at 01:37:00PM +0900, Stafford Horne wrote:

> > +	/* Given R = X * Y ... */

> > +1:	l.sfeq		r4, r0			/* while (y != 0) */

> > +	l.bf		2f

> > +	 l.andi		r5, r4, 1		/* if (y & 1) ... */

> 

> Do the extra leading spaces mean something?


Yes, we put those to indicate a branch delay slot instruction.

> > +        l.sfeqi		r4, 0		/* division by zero; return 0.  */

> 

> In some places (like here) you ident with 8 spaces instead of a tab.


Thanks, I will fix those, it should be tab.

> > +/* 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.

> > + */

> 

> You mean "y" instead of "b" I think.


I believe so, I will read through it.  This part was done by Richard I should
have reviewed it better.

-Stafford
Richard Henderson Oct. 28, 2018, 1:25 a.m. | #3
On 10/27/18 5:37 AM, Stafford Horne wrote:
> +/* 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,@function

> +_init:

> +	.global	_fini

> +	.type	_fini,@function

> +_fini:

> +	l.jr	r9

> +	 l.nop


Where are they referenced from?  Perhaps just a binutils bug, in that the
linker script needs adjustment?

> +	/* 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


This move could be the add to save 1 cycle in the !cmov case.

> +	/* 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


Simiarly.

Although both mul nor div are correct as-is, and need not be fixed immediately.
 I'm only concerned about _init and _fini.


r~
Stafford Horne Oct. 29, 2018, 1:44 p.m. | #4
On Sun, Oct 28, 2018 at 01:25:54AM +0000, Richard Henderson wrote:
> On 10/27/18 5:37 AM, Stafford Horne wrote:

> > +/* 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,@function

> > +_init:

> > +	.global	_fini

> > +	.type	_fini,@function

> > +_fini:

> > +	l.jr	r9

> > +	 l.nop

> 

> Where are they referenced from?  Perhaps just a binutils bug, in that the

> linker script needs adjustment?


I was getting the issue with newlib.  Here:

 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libc/misc/init.c
 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libc/misc/fini.c

The HAVE_INIT_FINI was not there when I last checked. Now, thanks to risc-v, we
can turn off the need for _init/_fini see:

 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=commit;f=newlib/libc/misc/fini.c;h=6158b30e3e9b1b582ae60b15d64e775fa1705483

I guess thats what you were referring to before though, I just missed it.

> > +	/* 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

> 

> This move could be the add to save 1 cycle in the !cmov case.

> 

> > +	/* 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

> 

> Simiarly.

> 

> Although both mul nor div are correct as-is, and need not be fixed immediately.

>  I'm only concerned about _init and _fini.


Sure, let me look into them.

-Stafford

Patch

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
+<http://www.gnu.org/licenses/>.  */
+
+/* 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,@function
+_init:
+	.global	_fini
+	.type	_fini,@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
+<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 % 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
+<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