diff mbox

[3/6] RISC-V Port: libgcc

Message ID 20170112023038.13449-4-palmer@dabbelt.com
State New
Headers show

Commit Message

Palmer Dabbelt Jan. 12, 2017, 2:30 a.m. UTC
From: Andrew Waterman <andrew@sifive.com>

---
 libgcc/config.host                 |  12 ++
 libgcc/config/riscv/atomic.c       | 111 +++++++++++++++++
 libgcc/config/riscv/crti.S         |   1 +
 libgcc/config/riscv/crtn.S         |   1 +
 libgcc/config/riscv/div.S          | 146 ++++++++++++++++++++++
 libgcc/config/riscv/linux-unwind.h |  89 ++++++++++++++
 libgcc/config/riscv/muldi3.S       |  46 +++++++
 libgcc/config/riscv/multi3.S       |  81 ++++++++++++
 libgcc/config/riscv/save-restore.S | 245 +++++++++++++++++++++++++++++++++++++
 libgcc/config/riscv/sfp-machine.h  | 156 +++++++++++++++++++++++
 libgcc/config/riscv/t-elf          |   6 +
 libgcc/config/riscv/t-elf32        |   1 +
 libgcc/config/riscv/t-elf64        |   1 +
 libgcc/config/riscv/t-softfp32     |   3 +
 libgcc/config/riscv/t-softfp64     |   4 +
 15 files changed, 903 insertions(+)
 create mode 100644 libgcc/config/riscv/atomic.c
 create mode 100644 libgcc/config/riscv/crti.S
 create mode 100644 libgcc/config/riscv/crtn.S
 create mode 100644 libgcc/config/riscv/div.S
 create mode 100644 libgcc/config/riscv/linux-unwind.h
 create mode 100644 libgcc/config/riscv/muldi3.S
 create mode 100644 libgcc/config/riscv/multi3.S
 create mode 100644 libgcc/config/riscv/save-restore.S
 create mode 100644 libgcc/config/riscv/sfp-machine.h
 create mode 100644 libgcc/config/riscv/t-elf
 create mode 100644 libgcc/config/riscv/t-elf32
 create mode 100644 libgcc/config/riscv/t-elf64
 create mode 100644 libgcc/config/riscv/t-softfp32
 create mode 100644 libgcc/config/riscv/t-softfp64

Comments

Joseph Myers Jan. 12, 2017, 11:30 p.m. UTC | #1
On Wed, 11 Jan 2017, Palmer Dabbelt wrote:

> +riscv*-*-linux*)
> +	tmake_file="${tmake_file} t-softfp-sfdf riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}"
> +	extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o crtendS.o crtbeginT.o"
> +	md_unwind_header=riscv/linux-unwind.h
> +	;;
> +riscv*-*-*)
> +	tmake_file="${tmake_file} t-softfp-sfdf riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}"
> +	extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o"
> +	;;

This looks like you're building soft-fp functions into libgcc for all 
types whether or not you have hardware floating point support for them.

If your ABIs are such that hardware and software floating point are ABI 
compatible at the function call level, then both copies of libgcc (the 
shared library, at least) should indeed have the same ABI (so a soft-float 
program can run with a hard-float copy of libgcc) - but for the hardware 
types, it's better to use t-hardfp.  If they are not ABI compatible, it's 
best for libgcc to contain only the functions that are actually needed.  
That is, in general, it only needs to contain functions that are not 
implemented in hardware, or are implemented in hardware but might not be 
implemented in hardware for some configurations using the same ABI (and in 
the latter case, the t-hardfp implementations are preferred).

> +#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

This is different from the default NaN the specification says is used by 
hardware (all mantissa bits clear except for the MSB used to indicate a 
quiet NaN).  I'd expect the soft-fp configuration to make the same choices 
here as hardware.

> +#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
> +#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
> +#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1

Likewise.

> +#define _FP_KEEPNANFRACP 1

And since the hardware semantics don't propagate payloads I'd expect this 
to be zero, and ...

> +/* From my experiments it seems X is chosen unless one of the
> +   NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
> +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\

 ... this to use a canonical NaN unconditionally, so that again you do the 
same as hardware (the comment here is actively misleading in this case as 
it describes something contrary to the hardware specification as being 
what experiments show hardware does).

> +#define FP_ROUNDMODE		(_fcw >> 5)

I'm unclear from the specification whether the high 24 bits of fcsr are 
architecturally defined always to read as zero, or whether that's only the 
case in present architecture versions and they are reserved for possible 
future feature additions.  If the latter, it would seem desirable to mask 
the result of shifting so existing binaries using the soft-fp code 
continue to work on future hardware that might set some of the high bits.

> +#define	__LITTLE_ENDIAN	1234
> +#define	__BIG_ENDIAN	4321
> +
> +#if defined __big_endian__
> +# define __BYTE_ORDER __BIG_ENDIAN
> +#else
> +# define __BYTE_ORDER __LITTLE_ENDIAN
> +#endif

As far as I can tell the port is always little-endian and there is no 
__big_endian__ macro, so that #if should not be there.
Andrew Waterman Jan. 13, 2017, 7:33 a.m. UTC | #2
Thanks again for your feedback.

On Thu, Jan 12, 2017 at 3:30 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Wed, 11 Jan 2017, Palmer Dabbelt wrote:
>
>> +riscv*-*-linux*)
>> +     tmake_file="${tmake_file} t-softfp-sfdf riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}"
>> +     extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o crtendS.o crtbeginT.o"
>> +     md_unwind_header=riscv/linux-unwind.h
>> +     ;;
>> +riscv*-*-*)
>> +     tmake_file="${tmake_file} t-softfp-sfdf riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}"
>> +     extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o"
>> +     ;;
>
> This looks like you're building soft-fp functions into libgcc for all
> types whether or not you have hardware floating point support for them.
>
> If your ABIs are such that hardware and software floating point are ABI
> compatible at the function call level, then both copies of libgcc (the
> shared library, at least) should indeed have the same ABI (so a soft-float
> program can run with a hard-float copy of libgcc) - but for the hardware
> types, it's better to use t-hardfp.  If they are not ABI compatible, it's
> best for libgcc to contain only the functions that are actually needed.
> That is, in general, it only needs to contain functions that are not
> implemented in hardware, or are implemented in hardware but might not be
> implemented in hardware for some configurations using the same ABI (and in
> the latter case, the t-hardfp implementations are preferred).

Yes, some soft-float routines are needlessly built for some ABIs.
We'll rectify this.

>
>> +#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
>
> This is different from the default NaN the specification says is used by
> hardware (all mantissa bits clear except for the MSB used to indicate a
> quiet NaN).  I'd expect the soft-fp configuration to make the same choices
> here as hardware.
>
>> +#define _FP_NANFRAC_S                ((_FP_QNANBIT_S << 1) - 1)
>> +#define _FP_NANFRAC_D                ((_FP_QNANBIT_D << 1) - 1)
>> +#define _FP_NANFRAC_Q                ((_FP_QNANBIT_Q << 1) - 1), -1
>
> Likewise.
>
>> +#define _FP_KEEPNANFRACP 1
>
> And since the hardware semantics don't propagate payloads I'd expect this
> to be zero, and ...
>
>> +/* From my experiments it seems X is chosen unless one of the
>> +   NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
>> +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)                   \
>
>  ... this to use a canonical NaN unconditionally, so that again you do the
> same as hardware (the comment here is actively misleading in this case as
> it describes something contrary to the hardware specification as being
> what experiments show hardware does).

Thanks for pointing this out.  We will make the soft-float canonical
NaN value and NaN propagation behavior match the ISA.

>
>> +#define FP_ROUNDMODE         (_fcw >> 5)
>
> I'm unclear from the specification whether the high 24 bits of fcsr are
> architecturally defined always to read as zero, or whether that's only the
> case in present architecture versions and they are reserved for possible
> future feature additions.  If the latter, it would seem desirable to mask
> the result of shifting so existing binaries using the soft-fp code
> continue to work on future hardware that might set some of the high bits.

I will see to it that the ISA spec is clarified on this point.  In the
mean time, I will obviate the issue by accessing the rounding mode and
exceptions through the frm and fflags shadow CSRs, rather than through
the fcsr.  (This should also be more performant.)

>
>> +#define      __LITTLE_ENDIAN 1234
>> +#define      __BIG_ENDIAN    4321
>> +
>> +#if defined __big_endian__
>> +# define __BYTE_ORDER __BIG_ENDIAN
>> +#else
>> +# define __BYTE_ORDER __LITTLE_ENDIAN
>> +#endif
>
> As far as I can tell the port is always little-endian and there is no
> __big_endian__ macro, so that #if should not be there.

Indeed.

>
> --
> Joseph S. Myers
> joseph@codesourcery.com
Richard Henderson Jan. 21, 2017, 6:53 a.m. UTC | #3
On 01/11/2017 06:30 PM, Palmer Dabbelt wrote:
> +__riscv_save_12:
> +  addi sp, sp, -112
> +  li t1, 0
> +  sd s11, 8(sp)
> +  j .Ls10
> +
> +__riscv_save_11:
> +__riscv_save_10:
> +  addi sp, sp, -112
> +  li t1, -16

No unwind info?


r~
Andrew Waterman Jan. 24, 2017, 8:08 p.m. UTC | #4
On Fri, Jan 20, 2017 at 10:53 PM, Richard Henderson <rth@redhat.com> wrote:
> On 01/11/2017 06:30 PM, Palmer Dabbelt wrote:
>>
>> +__riscv_save_12:
>> +  addi sp, sp, -112
>> +  li t1, 0
>> +  sd s11, 8(sp)
>> +  j .Ls10
>> +
>> +__riscv_save_11:
>> +__riscv_save_10:
>> +  addi sp, sp, -112
>> +  li t1, -16
>
>
> No unwind info?

Next patch set will have unwind info.

>
>
> r~
diff mbox

Patch

diff --git a/libgcc/config.host b/libgcc/config.host
index 6f2e458..bb6d5370e 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -167,6 +167,9 @@  powerpc*-*-*)
 	;;
 rs6000*-*-*)
 	;;
+riscv*)
+	cpu_type=riscv
+	;;
 sparc64*-*-*)
 	cpu_type=sparc
 	;;
@@ -1091,6 +1094,15 @@  powerpcle-*-eabi*)
 	tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
 	extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
 	;;
+riscv*-*-linux*)
+	tmake_file="${tmake_file} t-softfp-sfdf riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}"
+	extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o crtendS.o crtbeginT.o"
+	md_unwind_header=riscv/linux-unwind.h
+	;;
+riscv*-*-*)
+	tmake_file="${tmake_file} t-softfp-sfdf riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}"
+	extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o"
+	;;
 rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
 	md_unwind_header=rs6000/aix-unwind.h
 	tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble"
diff --git a/libgcc/config/riscv/atomic.c b/libgcc/config/riscv/atomic.c
new file mode 100644
index 0000000..448b0e5
--- /dev/null
+++ b/libgcc/config/riscv/atomic.c
@@ -0,0 +1,111 @@ 
+/* Legacy sub-word atomics for RISC-V.
+ 
+   Copyright (C) 2016-2017 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/>.  */
+
+#ifdef __riscv_atomic
+
+#include <stdbool.h>
+
+#define INVERT		"not %[tmp1], %[tmp1]\n\t"
+#define DONT_INVERT	""
+
+#define GENERATE_FETCH_AND_OP(type, size, opname, insn, invert, cop)	\
+  type __sync_fetch_and_ ## opname ## _ ## size (type *p, type v)	\
+  {									\
+    unsigned long aligned_addr = ((unsigned long) p) & ~3UL;		\
+    int shift = (((unsigned long) p) & 3) * 8;				\
+    unsigned mask = ((1U << ((sizeof v) * 8)) - 1) << shift;		\
+    unsigned old, tmp1, tmp2;						\
+									\
+    asm volatile ("1:\n\t"						\
+		  "lr.w.aq %[old], %[mem]\n\t"				\
+		  #insn " %[tmp1], %[old], %[value]\n\t"		\
+		  invert						\
+		  "and %[tmp1], %[tmp1], %[mask]\n\t"			\
+		  "and %[tmp2], %[old], %[not_mask]\n\t"		\
+		  "or %[tmp2], %[tmp2], %[tmp1]\n\t"			\
+		  "sc.w.rl %[tmp1], %[tmp2], %[mem]\n\t"		\
+		  "bnez %[tmp1], 1b"					\
+		  : [old] "=&r" (old),					\
+		    [mem] "+A" (*(volatile unsigned*) aligned_addr),	\
+		    [tmp1] "=&r" (tmp1),				\
+		    [tmp2] "=&r" (tmp2)					\
+		  : [value] "r" (((unsigned) v) << shift),		\
+		    [mask] "r" (mask),					\
+		    [not_mask] "r" (~mask));				\
+									\
+    return (type) (old >> shift);					\
+  }									\
+									\
+  type __sync_ ## opname ## _and_fetch_ ## size (type *p, type v)	\
+  {									\
+    type o = __sync_fetch_and_ ## opname ## _ ## size (p, v);		\
+    return cop;								\
+  }
+
+#define GENERATE_COMPARE_AND_SWAP(type, size)				\
+  type __sync_val_compare_and_swap_ ## size (type *p, type o, type n)	\
+  {									\
+    unsigned long aligned_addr = ((unsigned long) p) & ~3UL;		\
+    int shift = (((unsigned long) p) & 3) * 8;				\
+    unsigned mask = ((1U << ((sizeof o) * 8)) - 1) << shift;		\
+    unsigned old, tmp1;							\
+									\
+    asm volatile ("1:\n\t"						\
+		  "lr.w.aq %[old], %[mem]\n\t"				\
+		  "and %[tmp1], %[old], %[mask]\n\t"			\
+		  "bne %[tmp1], %[o], 1f\n\t"				\
+		  "and %[tmp1], %[old], %[not_mask]\n\t"		\
+		  "or %[tmp1], %[tmp1], %[n]\n\t"			\
+		  "sc.w.rl %[tmp1], %[tmp1], %[mem]\n\t"		\
+		  "bnez %[tmp1], 1b\n\t"				\
+		  "1:"							\
+		  : [old] "=&r" (old),					\
+		    [mem] "+A" (*(volatile unsigned*) aligned_addr),	\
+		    [tmp1] "=&r" (tmp1)					\
+		  : [o] "r" ((((unsigned) o) << shift) & mask),		\
+		    [n] "r" ((((unsigned) n) << shift) & mask),		\
+		    [mask] "r" (mask),					\
+		    [not_mask] "r" (~mask));				\
+									\
+    return (type) (old >> shift);					\
+  }									\
+  bool __sync_bool_compare_and_swap_ ## size (type *p, type o, type n)	\
+  {									\
+    return __sync_val_compare_and_swap(p, o, n) == o;			\
+  }
+
+#define GENERATE_ALL(type, size)					\
+  GENERATE_FETCH_AND_OP(type, size, add, add, DONT_INVERT, o + v)	\
+  GENERATE_FETCH_AND_OP(type, size, sub, sub, DONT_INVERT, o - v)	\
+  GENERATE_FETCH_AND_OP(type, size, and, and, DONT_INVERT, o & v)	\
+  GENERATE_FETCH_AND_OP(type, size, xor, xor, DONT_INVERT, o ^ v)	\
+  GENERATE_FETCH_AND_OP(type, size, or, or, DONT_INVERT, o | v)		\
+  GENERATE_FETCH_AND_OP(type, size, nand, and, INVERT, ~(o & v))	\
+  GENERATE_COMPARE_AND_SWAP(type, size)
+
+GENERATE_ALL(unsigned char, 1)
+GENERATE_ALL(unsigned short, 2)
+
+#endif
diff --git a/libgcc/config/riscv/crti.S b/libgcc/config/riscv/crti.S
new file mode 100644
index 0000000..89bac70
--- /dev/null
+++ b/libgcc/config/riscv/crti.S
@@ -0,0 +1 @@ 
+/* crti.S is empty because .init_array/.fini_array are used exclusively. */
diff --git a/libgcc/config/riscv/crtn.S b/libgcc/config/riscv/crtn.S
new file mode 100644
index 0000000..ca6ee7b
--- /dev/null
+++ b/libgcc/config/riscv/crtn.S
@@ -0,0 +1 @@ 
+/* crtn.S is empty because .init_array/.fini_array are used exclusively. */
diff --git a/libgcc/config/riscv/div.S b/libgcc/config/riscv/div.S
new file mode 100644
index 0000000..63d542e
--- /dev/null
+++ b/libgcc/config/riscv/div.S
@@ -0,0 +1,146 @@ 
+/* Integer division routines for RISC-V.
+
+   Copyright (C) 2016-2017 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/>.  */
+
+  .text
+  .align 2
+
+#if __riscv_xlen == 32
+/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines.  */
+# define __udivdi3 __udivsi3
+# define __umoddi3 __umodsi3
+# define __divdi3 __divsi3
+# define __moddi3 __modsi3
+#else
+  .globl __udivsi3
+__udivsi3:
+  /* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t.  */
+  sll    a0, a0, 32
+  sll    a1, a1, 32
+  move   t0, ra
+  jal    __udivdi3
+  sext.w a0, a0
+  jr     t0
+
+  .globl __umodsi3
+__umodsi3:
+  /* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t.  */
+  sll    a0, a0, 32
+  sll    a1, a1, 32
+  srl    a0, a0, 32
+  srl    a1, a1, 32
+  move   t0, ra
+  jal    __udivdi3
+  sext.w a0, a1
+  jr     t0
+
+  .globl __modsi3
+  __modsi3 = __moddi3
+
+  .globl __divsi3
+__divsi3:
+  /* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3.  */
+  li    t0, -1
+  beq   a1, t0, .L20
+#endif
+
+  .globl __divdi3
+__divdi3:
+  bltz  a0, .L10
+  bltz  a1, .L11
+  /* Since the quotient is positive, fall into __udivdi3.  */
+
+  .globl __udivdi3
+__udivdi3:
+  mv    a2, a1
+  mv    a1, a0
+  li    a0, -1
+  beqz  a2, .L5
+  li    a3, 1
+  bgeu  a2, a1, .L2
+.L1:
+  blez  a2, .L2
+  slli  a2, a2, 1
+  slli  a3, a3, 1
+  bgtu  a1, a2, .L1
+.L2:
+  li    a0, 0
+.L3:
+  bltu  a1, a2, .L4
+  sub   a1, a1, a2
+  or    a0, a0, a3
+.L4:
+  srli  a3, a3, 1
+  srli  a2, a2, 1
+  bnez  a3, .L3
+.L5:
+  ret
+
+  .globl __umoddi3
+__umoddi3:
+  /* Call __udivdi3(a0, a1), then return the remainder, which is in a1.  */
+  move  t0, ra
+  jal   __udivdi3
+  move  a0, a1
+  jr    t0
+
+  /* Handle negative arguments to __divdi3.  */
+.L10:
+  neg   a0, a0
+  bgez  a1, .L12      /* Compute __udivdi3(-a0, a1), then negate the result.  */
+  neg   a1, a1
+  j     __udivdi3     /* Compute __udivdi3(-a0, -a1).  */
+.L11:                 /* Compute __udivdi3(a0, -a1), then negate the result.  */
+  neg   a1, a1
+.L12:
+  move  t0, ra
+  jal   __udivdi3
+  neg   a0, a0
+  jr    t0
+
+  .globl __moddi3
+__moddi3:
+  move   t0, ra
+  bltz   a1, .L31
+  bltz   a0, .L32
+.L30:
+  jal    __udivdi3    /* The dividend is not negative.  */
+  move   a0, a1
+  jr     t0
+.L31:
+  neg    a1, a1
+  bgez   a0, .L30
+.L32:
+  neg    a0, a0
+  jal    __udivdi3    /* The dividend is hella negative.  */
+  neg    a0, a1
+  jr     t0
+
+#if __riscv_xlen == 64
+  /* continuation of __divsi3 */
+.L20:
+  sll   t0, t0, 31
+  bne   a0, t0, __divdi3
+  ret
+#endif
diff --git a/libgcc/config/riscv/linux-unwind.h b/libgcc/config/riscv/linux-unwind.h
new file mode 100644
index 0000000..a051a28
--- /dev/null
+++ b/libgcc/config/riscv/linux-unwind.h
@@ -0,0 +1,89 @@ 
+/* Copyright (C) 2016-2017 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/>.  */
+
+#ifndef inhibit_libc
+
+#include <signal.h>
+#include <stdint.h>
+#include <sys/ucontext.h>
+
+#define LI_A7_8B 0x08b00893
+#define ECALL    0x00000073
+
+#define MD_FALLBACK_FRAME_STATE_FOR riscv_fallback_frame_state
+
+static _Unwind_Reason_Code
+riscv_fallback_frame_state (struct _Unwind_Context *context,
+			    _Unwind_FrameState * fs)
+{
+  /* The kernel creates an rt_sigframe on the stack immediately prior
+     to delivering a signal.
+
+     This structure must have the same shape as the linux kernel
+     equivalent.  */
+  struct rt_sigframe
+  {
+    siginfo_t info;
+    struct ucontext uc;
+  };
+
+  struct rt_sigframe *rt_;
+  _Unwind_Ptr new_cfa;
+  uint16_t *pc = context->ra;
+  struct sigcontext *sc;
+  int i;
+
+  /* A signal frame will have a return address pointing to
+     __default_sa_restorer. This code is hardwired as:
+
+     0x08b00893		li	a7,0x8b
+     0x00000073		ecall
+
+     Note, the PC might only have 2-byte alignment.
+   */
+  if (pc[0] != (uint16_t)LI_A7_8B || pc[1] != (uint16_t)(LI_A7_8B >> 16)
+      || pc[2] != (uint16_t)ECALL || pc[3] != (uint16_t)(ECALL >> 16))
+    return _URC_END_OF_STACK;
+
+  rt_ = context->cfa;
+  sc = &rt_->uc.uc_mcontext;
+
+  new_cfa = (_Unwind_Ptr) sc;
+  fs->regs.cfa_how = CFA_REG_OFFSET;
+  fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
+  fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
+
+  for (i = 0; i < 32; i++)
+    {
+      fs->regs.reg[i].how = REG_SAVED_OFFSET;
+      fs->regs.reg[i].loc.offset = (_Unwind_Ptr) &sc->gregs[i] - new_cfa;
+    }
+
+  fs->signal_frame = 1;
+  fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__;
+  fs->regs.reg[fs->retaddr_column].how = REG_SAVED_VAL_OFFSET;
+  fs->regs.reg[fs->retaddr_column].loc.offset =
+    (_Unwind_Ptr) sc->gregs[0] - new_cfa;
+
+  return _URC_NO_REASON;
+}
+
+#endif
diff --git a/libgcc/config/riscv/muldi3.S b/libgcc/config/riscv/muldi3.S
new file mode 100644
index 0000000..eb3d9b0
--- /dev/null
+++ b/libgcc/config/riscv/muldi3.S
@@ -0,0 +1,46 @@ 
+/* Integer multiplication routines for RISC-V.
+
+   Copyright (C) 2016-2017 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/>.  */
+
+  .text
+  .align 2
+
+#if __riscv_xlen == 32
+/* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine.  */
+# define __muldi3 __mulsi3
+#endif
+
+  .globl __muldi3
+__muldi3:
+  mv     a2, a0
+  li     a0, 0
+.L1:
+  andi   a3, a1, 1
+  beqz   a3, .L2
+  add    a0, a0, a2
+.L2:
+  srli   a1, a1, 1
+  slli   a2, a2, 1
+  bnez   a1, .L1
+  ret
diff --git a/libgcc/config/riscv/multi3.S b/libgcc/config/riscv/multi3.S
new file mode 100644
index 0000000..4d454e6
--- /dev/null
+++ b/libgcc/config/riscv/multi3.S
@@ -0,0 +1,81 @@ 
+/* Integer multiplication routines for RISC-V.
+
+   Copyright (C) 2016-2017 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/>.  */
+
+  .text
+  .align 2
+
+#if __riscv_xlen == 32
+/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines.  */
+# define __multi3 __muldi3
+#endif
+
+  .globl __multi3
+__multi3:
+
+#if __riscv_xlen == 32
+/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines.  */
+# define __muldi3 __mulsi3
+#endif
+
+/* We rely on the fact that __muldi3 doesn't clobber the t-registers.  */
+
+  mv  t0, ra
+  mv  t5, a0
+  mv  a0, a1
+  mv  t6, a3
+  mv  a1, t5
+  mv  a4, a2
+  li  a5, 0
+  li  t2, 0
+  li  t4, 0
+.L1:
+  add  a6, t2, a1
+  andi t3, a4, 1
+  slli a7, a5, 1
+  slti t1, a1, 0
+  srli a4, a4, 1
+  add  a5, t4, a5
+  beqz t3, .L2
+  sltu t3, a6, t2
+  mv   t2, a6
+  add  t4, t3, a5
+.L2:
+  slli a1, a1, 1
+  or   a5, t1, a7
+  bnez a4, .L1
+  beqz a0, .L3
+  mv   a1, a2
+  call __muldi3
+  add  t4, t4, a0
+.L3:
+  beqz t6, .L4
+  mv   a1, t6
+  mv   a0, t5
+  call  __muldi3
+  add  t4, t4, a0
+.L4:
+  mv  a0, t2
+  mv  a1, t4
+  jr  t0
diff --git a/libgcc/config/riscv/save-restore.S b/libgcc/config/riscv/save-restore.S
new file mode 100644
index 0000000..299bb8b
--- /dev/null
+++ b/libgcc/config/riscv/save-restore.S
@@ -0,0 +1,245 @@ 
+/* Callee-saved register spill and fill routines for RISC-V.
+
+   Copyright (C) 2016-2017 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/>.  */
+
+  .text
+
+  .globl __riscv_save_12
+  .globl __riscv_save_11
+  .globl __riscv_save_10
+  .globl __riscv_save_9
+  .globl __riscv_save_8
+  .globl __riscv_save_7
+  .globl __riscv_save_6
+  .globl __riscv_save_5
+  .globl __riscv_save_4
+  .globl __riscv_save_3
+  .globl __riscv_save_2
+  .globl __riscv_save_1
+  .globl __riscv_save_0
+
+  .globl __riscv_restore_12
+  .globl __riscv_restore_11
+  .globl __riscv_restore_10
+  .globl __riscv_restore_9
+  .globl __riscv_restore_8
+  .globl __riscv_restore_7
+  .globl __riscv_restore_6
+  .globl __riscv_restore_5
+  .globl __riscv_restore_4
+  .globl __riscv_restore_3
+  .globl __riscv_restore_2
+  .globl __riscv_restore_1
+  .globl __riscv_restore_0
+
+#if __riscv_xlen == 64
+
+__riscv_save_12:
+  addi sp, sp, -112
+  li t1, 0
+  sd s11, 8(sp)
+  j .Ls10
+
+__riscv_save_11:
+__riscv_save_10:
+  addi sp, sp, -112
+  li t1, -16
+.Ls10:
+  sd s10, 16(sp)
+  sd s9, 24(sp)
+  j .Ls8
+
+__riscv_save_9:
+__riscv_save_8:
+  addi sp, sp, -112
+  li t1, -32
+.Ls8:
+  sd s8, 32(sp)
+  sd s7, 40(sp)
+  j .Ls6
+
+__riscv_save_7:
+__riscv_save_6:
+  addi sp, sp, -112
+  li t1, -48
+.Ls6:
+  sd s6, 48(sp)
+  sd s5, 56(sp)
+  j .Ls4
+
+__riscv_save_5:
+__riscv_save_4:
+  addi sp, sp, -112
+  li t1, -64
+.Ls4:
+  sd s4, 64(sp)
+  sd s3, 72(sp)
+  j .Ls2
+
+__riscv_save_3:
+__riscv_save_2:
+  addi sp, sp, -112
+  li t1, -80
+.Ls2:
+  sd s2, 80(sp)
+  sd s1, 88(sp)
+  sd s0, 96(sp)
+  sd ra, 104(sp)
+  sub sp, sp, t1
+  jr t0
+
+__riscv_save_1:
+__riscv_save_0:
+  addi sp, sp, -16
+  sd s0, 0(sp)
+  sd ra, 8(sp)
+  jr t0
+
+__riscv_restore_12:
+  ld s11, 8(sp)
+  addi sp, sp, 16
+
+__riscv_restore_11:
+__riscv_restore_10:
+  ld s10, 0(sp)
+  ld s9, 8(sp)
+  addi sp, sp, 16
+
+__riscv_restore_9:
+__riscv_restore_8:
+  ld s8, 0(sp)
+  ld s7, 8(sp)
+  addi sp, sp, 16
+
+__riscv_restore_7:
+__riscv_restore_6:
+  ld s6, 0(sp)
+  ld s5, 8(sp)
+  addi sp, sp, 16
+
+__riscv_restore_5:
+__riscv_restore_4:
+  ld s4, 0(sp)
+  ld s3, 8(sp)
+  addi sp, sp, 16
+
+__riscv_restore_3:
+__riscv_restore_2:
+  ld s2, 0(sp)
+  ld s1, 8(sp)
+  addi sp, sp, 16
+
+__riscv_restore_1:
+__riscv_restore_0:
+  ld s0, 0(sp)
+  ld ra, 8(sp)
+  addi sp, sp, 16
+  ret
+
+#else
+
+__riscv_save_12:
+  addi sp, sp, -64
+  li t1, 0
+  sw s11, 12(sp)
+  j .Ls10
+
+__riscv_save_11:
+__riscv_save_10:
+__riscv_save_9:
+__riscv_save_8:
+  addi sp, sp, -64
+  li t1, -16
+.Ls10:
+  sw s10, 16(sp)
+  sw s9, 20(sp)
+  sw s8, 24(sp)
+  sw s7, 28(sp)
+  j .Ls6
+
+__riscv_save_7:
+__riscv_save_6:
+__riscv_save_5:
+__riscv_save_4:
+  addi sp, sp, -64
+  li t1, -32
+.Ls6:
+  sw s6, 32(sp)
+  sw s5, 36(sp)
+  sw s4, 40(sp)
+  sw s3, 44(sp)
+  sw s2, 48(sp)
+  sw s1, 52(sp)
+  sw s0, 56(sp)
+  sw ra, 60(sp)
+  sub sp, sp, t1
+  jr t0
+
+__riscv_save_3:
+__riscv_save_2:
+__riscv_save_1:
+__riscv_save_0:
+  addi sp, sp, -16
+  sw s2, 0(sp)
+  sw s1, 4(sp)
+  sw s0, 8(sp)
+  sw ra, 12(sp)
+  jr t0
+
+__riscv_restore_12:
+  lw s11, 12(sp)
+  addi sp, sp, 16
+
+__riscv_restore_11:
+__riscv_restore_10:
+__riscv_restore_9:
+__riscv_restore_8:
+  lw s10, 0(sp)
+  lw s9, 4(sp)
+  lw s8, 8(sp)
+  lw s7, 12(sp)
+  addi sp, sp, 16
+
+__riscv_restore_7:
+__riscv_restore_6:
+__riscv_restore_5:
+__riscv_restore_4:
+  lw s6, 0(sp)
+  lw s5, 4(sp)
+  lw s4, 8(sp)
+  lw s3, 12(sp)
+  addi sp, sp, 16
+
+__riscv_restore_3:
+__riscv_restore_2:
+__riscv_restore_1:
+__riscv_restore_0:
+  lw s2, 0(sp)
+  lw s1, 4(sp)
+  lw s0, 8(sp)
+  lw ra, 12(sp)
+  addi sp, sp, 16
+  ret
+
+#endif
diff --git a/libgcc/config/riscv/sfp-machine.h b/libgcc/config/riscv/sfp-machine.h
new file mode 100644
index 0000000..340c8e1
--- /dev/null
+++ b/libgcc/config/riscv/sfp-machine.h
@@ -0,0 +1,156 @@ 
+/* Software floating-point machine description for RISC-V.
+
+   Copyright (C) 2016-2017 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/>.  */
+
+typedef unsigned int fpu_control_t;
+
+#if __riscv_xlen == 32
+
+#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_udiv_norm(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
+
+#else
+
+#define _FP_W_TYPE_SIZE		64
+#define _FP_W_TYPE		unsigned long long
+#define _FP_WS_TYPE		signed long long
+#define _FP_I_TYPE		long long
+
+#define _FP_MUL_MEAT_S(R,X,Y)					\
+  _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y)					\
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)					\
+  _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
+
+#endif
+
+#if __riscv_xlen == 64
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype))
+#endif
+
+/* The type of the result of a floating point comparison.  This must
+   match __libgcc_cmp_return__ in GCC for the target.  */
+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
+#define CMPtype __gcc_CMPtype
+
+#define _FP_NANSIGN_S		0
+#define _FP_NANSIGN_D		0
+#define _FP_NANSIGN_Q		0
+
+#define _FP_KEEPNANFRACP 1
+#define _FP_QNANNEGATEDP 0
+
+
+/* From my experiments it seems X is chosen unless one of the
+   NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
+  do {								\
+    if ((_FP_FRAC_HIGH_RAW_##fs(X) |				\
+	 _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs)		\
+      {								\
+	R##_s = _FP_NANSIGN_##fs;				\
+        _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs);			\
+      }								\
+    else							\
+      {								\
+	R##_s = X##_s;						\
+        _FP_FRAC_COPY_##wc(R,X);				\
+      }								\
+    R##_c = FP_CLS_NAN;						\
+  } while (0)
+
+#define _FP_DECL_EX		fpu_control_t _fcw
+
+#define FP_ROUNDMODE		(_fcw >> 5)
+
+#define FP_RND_NEAREST		0x0
+#define FP_RND_ZERO		0x1
+#define FP_RND_PINF		0x3
+#define FP_RND_MINF		0x2
+
+#define FP_EX_INVALID		0x10
+#define FP_EX_OVERFLOW		0x04
+#define FP_EX_UNDERFLOW		0x02
+#define FP_EX_DIVZERO		0x08
+#define FP_EX_INEXACT		0x01
+
+#define _FP_TININESS_AFTER_ROUNDING 1
+
+#ifdef __riscv_flen
+#define FP_INIT_ROUNDMODE			\
+do {						\
+  __asm__ volatile ("frsr %0" : "=r" (_fcw));	\
+} while (0)
+
+#define FP_HANDLE_EXCEPTIONS					\
+do {								\
+  if (__builtin_expect (_fex, 0))				\
+    __asm__ volatile ("fssr %z0" : : "rJ" (_fcw | _fex));	\
+} while (0)
+#else
+#define FP_INIT_ROUNDMODE	_fcw = 0 /* No exceptions; FP_RND_NEAREST.  */
+#endif
+
+#define	__LITTLE_ENDIAN	1234
+#define	__BIG_ENDIAN	4321
+
+#if defined __big_endian__
+# define __BYTE_ORDER __BIG_ENDIAN
+#else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+
+/* 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/riscv/t-elf b/libgcc/config/riscv/t-elf
new file mode 100644
index 0000000..01d5eba
--- /dev/null
+++ b/libgcc/config/riscv/t-elf
@@ -0,0 +1,6 @@ 
+LIB2ADD += $(srcdir)/config/riscv/save-restore.S \
+	   $(srcdir)/config/riscv/muldi3.S \
+	   $(srcdir)/config/riscv/multi3.S \
+	   $(srcdir)/config/riscv/div.S \
+	   $(srcdir)/config/riscv/atomic.c \
+
diff --git a/libgcc/config/riscv/t-elf32 b/libgcc/config/riscv/t-elf32
new file mode 100644
index 0000000..f375123
--- /dev/null
+++ b/libgcc/config/riscv/t-elf32
@@ -0,0 +1 @@ 
+LIB2FUNCS_EXCLUDE += _divsi3 _modsi3 _udivsi3 _umodsi3 _mulsi3 _muldi3
diff --git a/libgcc/config/riscv/t-elf64 b/libgcc/config/riscv/t-elf64
new file mode 100644
index 0000000..f375123
--- /dev/null
+++ b/libgcc/config/riscv/t-elf64
@@ -0,0 +1 @@ 
+LIB2FUNCS_EXCLUDE += _divsi3 _modsi3 _udivsi3 _umodsi3 _mulsi3 _muldi3
diff --git a/libgcc/config/riscv/t-softfp32 b/libgcc/config/riscv/t-softfp32
new file mode 100644
index 0000000..306677b
--- /dev/null
+++ b/libgcc/config/riscv/t-softfp32
@@ -0,0 +1,3 @@ 
+softfp_float_modes += tf
+softfp_extensions += sftf dftf
+softfp_truncations += tfsf tfdf
diff --git a/libgcc/config/riscv/t-softfp64 b/libgcc/config/riscv/t-softfp64
new file mode 100644
index 0000000..61a8bff
--- /dev/null
+++ b/libgcc/config/riscv/t-softfp64
@@ -0,0 +1,4 @@ 
+softfp_float_modes += tf
+softfp_int_modes += ti
+softfp_extensions += sftf dftf
+softfp_truncations += tfsf tfdf