This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch committed] sh*-linux*: Add some atomic operations as library functions
- From: Kaz Kojima <kkojima at rr dot iij4u dot or dot jp>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 01 Apr 2006 07:35:32 +0900 (JST)
- Subject: [patch committed] sh*-linux*: Add some atomic operations as library functions
Hi,
I've checked the attached sh[34]-linux* specific patch in on
the trunk. It adds the minimal __sync_* routines to the libgcc
for those targets to avoid some link time failures of libgomp
tests caused with the absence of these routines. The functions
use the software atomic sequence which is supported by the linux
kernels for SH3/4.
I thought about adding insn patterns for these atomic sequences
first, but adding such highly OS specific insns seems not a good
idea, especially from the maintenance point of view. SH4A will
use movli/movco instructions for the atomic patterns which don't
depend on kernel. For SH3/4 cores without the SMP support,
the performance of these atomic operations doesn't matter so much
and the library functions would be enough for them.
The patch is tested with bootstrap and the toplevel "make -k check"
on sh4-*-linux-gnu. The x86 cross sh64-*-linux-gnu is also tested
with its build and the toplevel "make -k check".
Regards,
kaz
--
2006-03-31 Kaz Kojima <kkojima@gcc.gnu.org>
* config/sh/linux-atomic.asm: New file.
* config/sh/t-linux (LIB2FUNCS_EXTRA): Add linux-atomic.asm.
diff -uprN ORIG/trunk/gcc/config/sh/linux-atomic.asm LOCAL/trunk/gcc/config/sh/linux-atomic.asm
--- ORIG/trunk/gcc/config/sh/linux-atomic.asm 1970-01-01 09:00:00.000000000 +0900
+++ LOCAL/trunk/gcc/config/sh/linux-atomic.asm 2006-03-30 08:22:44.000000000 +0900
@@ -0,0 +1,138 @@
+/* Copyright (C) 2006 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 2, 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 COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+!! Linux specific atomic routines for the Renesas / SuperH SH CPUs.
+!! Linux kernel for SH3/4 has implemented the support for software
+!! atomic sequences.
+
+#define FUNC(X) .type X,@function
+#define HIDDEN_FUNC(X) FUNC(X); .hidden X
+#define ENDFUNC0(X) .Lfe_##X: .size X,.Lfe_##X-X
+#define ENDFUNC(X) ENDFUNC0(X)
+
+#if ! __SH5__
+
+#define ATOMIC_TEST_AND_SET(N,T) \
+ .global __sync_lock_test_and_set_##N; \
+ HIDDEN_FUNC(__sync_lock_test_and_set_##N); \
+ .align 2; \
+__sync_lock_test_and_set_##N:; \
+ mova 1f, r0; \
+ nop; \
+ mov r15, r1; \
+ mov #(0f-1f), r15; \
+0: mov.##T @r4, r2; \
+ mov.##T r5, @r4; \
+1: mov r1, r15; \
+ rts; \
+ mov r2, r0; \
+ ENDFUNC(__sync_lock_test_and_set_##N)
+
+ATOMIC_TEST_AND_SET (1,b)
+ATOMIC_TEST_AND_SET (2,w)
+ATOMIC_TEST_AND_SET (4,l)
+
+#define ATOMIC_COMPARE_AND_SWAP(N,T) \
+ .global __sync_compare_and_swap_##N; \
+ HIDDEN_FUNC(__sync_compare_and_swap_##N); \
+ .align 2; \
+__sync_compare_and_swap_##N:; \
+ mova 1f, r0; \
+ nop; \
+ mov r15, r1; \
+ mov #(0f-1f), r15; \
+0: mov.##T @r4, r2; \
+ cmp/eq r2, r5; \
+ bf 1f; \
+ mov.##T r6, @r4; \
+1: mov r1, r15; \
+ rts; \
+ mov r2, r0; \
+ ENDFUNC(__sync_compare_and_swap_##N)
+
+ATOMIC_COMPARE_AND_SWAP (1,b)
+ATOMIC_COMPARE_AND_SWAP (2,w)
+ATOMIC_COMPARE_AND_SWAP (4,l)
+
+#define ATOMIC_FETCH_AND_OP(OP,N,T) \
+ .global __sync_fetch_and_##OP##_##N; \
+ HIDDEN_FUNC(__sync_fetch_and_##OP##_##N); \
+ .align 2; \
+__sync_fetch_and_##OP##_##N:; \
+ mova 1f, r0; \
+ mov r15, r1; \
+ mov #(0f-1f), r15; \
+0: mov.##T @r4, r2; \
+ OP r2, r5; \
+ mov.##T r5, @r4; \
+1: mov r1, r15; \
+ rts; \
+ mov r2, r0; \
+ ENDFUNC(__sync_fetch_and_##OP##_##N)
+
+ATOMIC_FETCH_AND_OP(add,1,b)
+ATOMIC_FETCH_AND_OP(add,2,w)
+ATOMIC_FETCH_AND_OP(add,4,l)
+
+ATOMIC_FETCH_AND_OP(or,1,b)
+ATOMIC_FETCH_AND_OP(or,2,w)
+ATOMIC_FETCH_AND_OP(or,4,l)
+
+ATOMIC_FETCH_AND_OP(and,1,b)
+ATOMIC_FETCH_AND_OP(and,2,w)
+ATOMIC_FETCH_AND_OP(and,4,l)
+
+ATOMIC_FETCH_AND_OP(xor,1,b)
+ATOMIC_FETCH_AND_OP(xor,2,w)
+ATOMIC_FETCH_AND_OP(xor,4,l)
+
+#define ATOMIC_FETCH_AND_COMBOP(OP,OP0,OP1,N,T) \
+ .global __sync_fetch_and_##OP##_##N; \
+ HIDDEN_FUNC(__sync_fetch_and_##OP##_##N); \
+ .align 2; \
+__sync_fetch_and_##OP##_##N:; \
+ mova 1f, r0; \
+ nop; \
+ mov r15, r1; \
+ mov #(0f-1f), r15; \
+0: mov.##T @r4, r2; \
+ OP0 r2, r5; \
+ OP1 r5, r5; \
+ mov.##T r5, @r4; \
+1: mov r1, r15; \
+ rts; \
+ mov r2, r0; \
+ ENDFUNC(__sync_fetch_and_##OP##_##N)
+
+ATOMIC_FETCH_AND_COMBOP(sub,sub,neg,1,b)
+ATOMIC_FETCH_AND_COMBOP(sub,sub,neg,2,w)
+ATOMIC_FETCH_AND_COMBOP(sub,sub,neg,4,l)
+
+ATOMIC_FETCH_AND_COMBOP(nand,and,not,1,b)
+ATOMIC_FETCH_AND_COMBOP(nand,and,not,2,w)
+ATOMIC_FETCH_AND_COMBOP(nand,and,not,4,l)
+
+#endif /* ! __SH5__ */
diff -uprN ORIG/trunk/gcc/config/sh/t-linux LOCAL/trunk/gcc/config/sh/t-linux
--- ORIG/trunk/gcc/config/sh/t-linux 2005-10-29 06:52:01.000000000 +0900
+++ LOCAL/trunk/gcc/config/sh/t-linux 2006-03-29 08:35:29.000000000 +0900
@@ -1,7 +1,7 @@
TARGET_LIBGCC2_CFLAGS = -fpic -DNO_FPSCR_VALUES
LIB1ASMFUNCS_CACHE = _ic_invalidate _ic_invalidate_array
-LIB2FUNCS_EXTRA=
+LIB2FUNCS_EXTRA= $(srcdir)/config/sh/linux-atomic.asm
MULTILIB_DIRNAMES=
MULTILIB_MATCHES =