[PATCH 3/6] RISC-V Port: libgcc

2017-02-05 Thread Palmer Dabbelt
---
 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 | 463 +
 libgcc/config/riscv/sfp-machine.h  | 137 +++
 libgcc/config/riscv/t-elf  |   6 +
 libgcc/config/riscv/t-elf32|   1 +
 libgcc/config/riscv/t-elf64|   1 +
 libgcc/config/riscv/t-softfp32 |  26 +++
 libgcc/config/riscv/t-softfp64 |   3 +
 15 files changed, 1124 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

diff --git a/libgcc/config.host b/libgcc/config.host
index 540bfa9..9472a60 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -167,6 +167,9 @@ powerpc*-*-*)
;;
 rs6000*-*-*)
;;
+riscv*-*-*)
+   cpu_type=riscv
+   ;;
 sparc64*-*-*)
cpu_type=sparc
;;
@@ -1093,6 +1096,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} 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} 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 000..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
+.  */
+
+#ifdef __riscv_atomic
+
+#include 
+
+#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"  

[PATCH 3/6] RISC-V Port: libgcc

2017-02-02 Thread Palmer Dabbelt
---
 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 | 463 +
 libgcc/config/riscv/sfp-machine.h  | 137 +++
 libgcc/config/riscv/t-elf  |   6 +
 libgcc/config/riscv/t-elf32|   1 +
 libgcc/config/riscv/t-elf64|   1 +
 libgcc/config/riscv/t-softfp32 |  26 +++
 libgcc/config/riscv/t-softfp64 |   3 +
 15 files changed, 1124 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

diff --git a/libgcc/config.host b/libgcc/config.host
index 540bfa9..9472a60 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -167,6 +167,9 @@ powerpc*-*-*)
;;
 rs6000*-*-*)
;;
+riscv*-*-*)
+   cpu_type=riscv
+   ;;
 sparc64*-*-*)
cpu_type=sparc
;;
@@ -1093,6 +1096,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} 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} 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 000..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
+.  */
+
+#ifdef __riscv_atomic
+
+#include 
+
+#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"  

Re: [PATCH 3/6] RISC-V Port: libgcc

2017-01-24 Thread Andrew Waterman
On Fri, Jan 20, 2017 at 10:53 PM, Richard Henderson  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~


Re: [PATCH 3/6] RISC-V Port: libgcc

2017-01-20 Thread Richard Henderson

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~


Re: [PATCH 3/6] RISC-V Port: libgcc

2017-01-12 Thread Andrew Waterman
Thanks again for your feedback.

On Thu, Jan 12, 2017 at 3:30 PM, Joseph Myers  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_ENDIAN4321
>> +
>> +#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
> jos...@codesourcery.com


Re: [PATCH 3/6] RISC-V Port: libgcc

2017-01-12 Thread Joseph Myers
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_ENDIAN4321
> +
> +#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.

-- 
Joseph S. Myers
jos...@codesourcery.com


[PATCH 3/6] RISC-V Port: libgcc

2017-01-11 Thread Palmer Dabbelt
From: Andrew Waterman 

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

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 000..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
+.  */
+
+#ifdef __riscv_atomic
+
+#include 
+
+#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"\
+