This patch contains the GCN port of libgcc. I've broken it out just to keep both parts more manageable.
We have the usual stuff, plus a "gomp_print" implementation intended to provide a means to output text to console without using the full printf. Originally this was because we did not have a working Newlib port, but now it provides the underlying mechanism for printf. It's also much lighter than printf, and therefore more suitable for debugging offload kernels (for which there is no debugger, yet). In order to work in offload kernels the same function must be present in both host and GCN toolchains. Therefore it needs to live in libgomp (hence the name). However, having found it also useful in stand alone testing I have moved the GCN implementation to libgcc. It was also necessary to provide a means to disable EMUTLS. 2018-09-05 Andrew Stubbs <a...@codesourcery.com> Kwok Cheung Yeung <k...@codesourcery.com> Julian Brown <jul...@codesourcery.com> Tom de Vries <t...@codesourcery.com> libgcc/ * Makefile.in: Don't add emutls.c when --enable-emutls is "no". * config.host: Recognize amdgcn*-*-amdhsa. * config/gcn/crt0.c: New file. * config/gcn/gomp_print.c: New file. * config/gcn/lib2-divmod-hi.c: New file. * config/gcn/lib2-divmod.c: New file. * config/gcn/lib2-gcn.h: New file. * config/gcn/reduction.c: New file. * config/gcn/sfp-machine.h: New file. * config/gcn/t-amdgcn: New file. --- libgcc/Makefile.in | 2 + libgcc/config.host | 8 +++ libgcc/config/gcn/crt0.c | 23 ++++++++ libgcc/config/gcn/gomp_print.c | 99 +++++++++++++++++++++++++++++++ libgcc/config/gcn/lib2-divmod-hi.c | 117 +++++++++++++++++++++++++++++++++++++ libgcc/config/gcn/lib2-divmod.c | 117 +++++++++++++++++++++++++++++++++++++ libgcc/config/gcn/lib2-gcn.h | 49 ++++++++++++++++ libgcc/config/gcn/reduction.c | 30 ++++++++++ libgcc/config/gcn/sfp-machine.h | 51 ++++++++++++++++ libgcc/config/gcn/t-amdgcn | 25 ++++++++ 10 files changed, 521 insertions(+) create mode 100644 libgcc/config/gcn/crt0.c create mode 100644 libgcc/config/gcn/gomp_print.c create mode 100644 libgcc/config/gcn/lib2-divmod-hi.c create mode 100644 libgcc/config/gcn/lib2-divmod.c create mode 100644 libgcc/config/gcn/lib2-gcn.h create mode 100644 libgcc/config/gcn/reduction.c create mode 100644 libgcc/config/gcn/sfp-machine.h create mode 100644 libgcc/config/gcn/t-amdgcn
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index 0c5b264..6f68257 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -429,9 +429,11 @@ LIB2ADD += enable-execute-stack.c # While emutls.c has nothing to do with EH, it is in LIB2ADDEH* # instead of LIB2ADD because that's the way to be sure on some targets # (e.g. *-*-darwin*) only one copy of it is linked. +ifneq ($(enable_emutls),no) LIB2ADDEH += $(srcdir)/emutls.c LIB2ADDEHSTATIC += $(srcdir)/emutls.c LIB2ADDEHSHARED += $(srcdir)/emutls.c +endif # Library members defined in libgcc2.c. lib2funcs = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _cmpdi2 _ucmpdi2 \ diff --git a/libgcc/config.host b/libgcc/config.host index 029f656..29178da 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -91,6 +91,10 @@ alpha*-*-*) am33_2.0-*-linux*) cpu_type=mn10300 ;; +amdgcn*-*-*) + cpu_type=gcn + tmake_file="${tmake_file} t-softfp-sfdf t-softfp" + ;; arc*-*-*) cpu_type=arc ;; @@ -384,6 +388,10 @@ alpha*-dec-*vms*) extra_parts="$extra_parts vms-dwarf2.o vms-dwarf2eh.o" md_unwind_header=alpha/vms-unwind.h ;; +amdgcn*-*-amdhsa) + tmake_file="$tmake_file gcn/t-amdgcn" + extra_parts="crt0.o" + ;; arc*-*-elf*) tmake_file="arc/t-arc" extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o" diff --git a/libgcc/config/gcn/crt0.c b/libgcc/config/gcn/crt0.c new file mode 100644 index 0000000..f4f367b --- /dev/null +++ b/libgcc/config/gcn/crt0.c @@ -0,0 +1,23 @@ +/* Copyright (C) 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/>. */ + +/* Provide an entry point symbol to silence a linker warning. */ +void _start() {} diff --git a/libgcc/config/gcn/gomp_print.c b/libgcc/config/gcn/gomp_print.c new file mode 100644 index 0000000..41f50c3 --- /dev/null +++ b/libgcc/config/gcn/gomp_print.c @@ -0,0 +1,99 @@ +/* Newlib may not have been built yet. */ +typedef long int64_t; +typedef long size_t; +extern char *strncpy (char *dst, const char *src, size_t length); +extern void exit(int); + +void gomp_print_string (const char *msg, const char *value); +void gomp_print_integer (const char *msg, int64_t value); +void gomp_print_double (const char *msg, double value); + +/* This struct must match the one used by gcn-run and libgomp. + It holds all the data output from a kernel (besides mapping data). + + The base address pointer can be found at kernargs+16. + + The next_output counter must be atomically incremented for each + print output. Only when the print data is fully written can the + "written" flag be set. */ +struct output { + int return_value; + int next_output; + struct printf_data { + int written; + char msg[128]; + int type; + union { + int64_t ivalue; + double dvalue; + char text[128]; + }; + } queue[1000]; +}; + +static struct printf_data * +reserve_print_slot (void) { + /* The kernargs pointer is in s[8:9]. + This will break if the enable_sgpr_* flags are ever changed. */ + char *kernargs; + asm ("s_mov_b64 %0, s[8:9]" : "=Sg"(kernargs)); + + /* The output data is at kernargs[2]. */ + struct output *data = *(struct output **)(kernargs + 16); + + /* We don't have atomic operators in C yet. + "glc" means return original value. */ + int index = 0; + asm ("flat_atomic_add %0, %1, %2 glc\n\t" + "s_waitcnt 0" + : "=v"(index) + : "v"(&data->next_output), "v"(1), "e"(1l)); + + if (index >= 1000) + exit(1); + + return &(data->queue[index]); +} + +void +gomp_print_string (const char *msg, const char *value) +{ + struct printf_data *output = reserve_print_slot (); + output->type = 2; /* String. */ + + strncpy (output->msg, msg, 127); + output->msg[127] = '\0'; + strncpy (output->text, value, 127); + output->text[127] = '\0'; + + asm ("" ::: "memory"); + output->written = 1; +} + +void +gomp_print_integer (const char *msg, int64_t value) +{ + struct printf_data *output = reserve_print_slot (); + output->type = 0; /* Integer. */ + + strncpy (output->msg, msg, 127); + output->msg[127] = '\0'; + output->ivalue = value; + + asm ("" ::: "memory"); + output->written = 1; +} + +void +gomp_print_double (const char *msg, double value) +{ + struct printf_data *output = reserve_print_slot (); + output->type = 1; /* Double. */ + + strncpy (output->msg, msg, 127); + output->msg[127] = '\0'; + output->dvalue = value; + + asm ("" ::: "memory"); + output->written = 1; +} diff --git a/libgcc/config/gcn/lib2-divmod-hi.c b/libgcc/config/gcn/lib2-divmod-hi.c new file mode 100644 index 0000000..d57e145 --- /dev/null +++ b/libgcc/config/gcn/lib2-divmod-hi.c @@ -0,0 +1,117 @@ +/* Copyright (C) 2012-2017 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, 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/>. */ + +#include "lib2-gcn.h" + +/* 16-bit HI divide and modulo as used in gcn. */ + +static UHItype +udivmodhi4 (UHItype num, UHItype den, word_type modwanted) +{ + UHItype bit = 1; + UHItype res = 0; + + while (den < num && bit && !(den & (1L<<15))) + { + den <<=1; + bit <<=1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>=1; + den >>=1; + } + if (modwanted) + return num; + return res; +} + + +HItype +__divhi3 (HItype a, HItype b) +{ + word_type neg = 0; + HItype res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = udivmodhi4 (a, b, 0); + + if (neg) + res = -res; + + return res; +} + + +HItype +__modhi3 (HItype a, HItype b) +{ + word_type neg = 0; + HItype res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodhi4 (a, b, 1); + + if (neg) + res = -res; + + return res; +} + + +UHItype +__udivhi3 (UHItype a, UHItype b) +{ + return udivmodhi4 (a, b, 0); +} + + +UHItype +__umodhi3 (UHItype a, UHItype b) +{ + return udivmodhi4 (a, b, 1); +} + diff --git a/libgcc/config/gcn/lib2-divmod.c b/libgcc/config/gcn/lib2-divmod.c new file mode 100644 index 0000000..08e7103 --- /dev/null +++ b/libgcc/config/gcn/lib2-divmod.c @@ -0,0 +1,117 @@ +/* Copyright (C) 2012-2017 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, 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/>. */ + +#include "lib2-gcn.h" + +/* 32-bit SI divide and modulo as used in gcn. */ + +static USItype +udivmodsi4 (USItype num, USItype den, word_type modwanted) +{ + USItype bit = 1; + USItype res = 0; + + while (den < num && bit && !(den & (1L<<31))) + { + den <<=1; + bit <<=1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>=1; + den >>=1; + } + if (modwanted) + return num; + return res; +} + + +SItype +__divsi3 (SItype a, SItype b) +{ + word_type neg = 0; + SItype res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = udivmodsi4 (a, b, 0); + + if (neg) + res = -res; + + return res; +} + + +SItype +__modsi3 (SItype a, SItype b) +{ + word_type neg = 0; + SItype res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodsi4 (a, b, 1); + + if (neg) + res = -res; + + return res; +} + + +SItype +__udivsi3 (SItype a, SItype b) +{ + return udivmodsi4 (a, b, 0); +} + + +SItype +__umodsi3 (SItype a, SItype b) +{ + return udivmodsi4 (a, b, 1); +} + diff --git a/libgcc/config/gcn/lib2-gcn.h b/libgcc/config/gcn/lib2-gcn.h new file mode 100644 index 0000000..aff0bd2 --- /dev/null +++ b/libgcc/config/gcn/lib2-gcn.h @@ -0,0 +1,49 @@ +/* Integer arithmetic support for gcn. + + Copyright (C) 2012-2017 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, 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 LIB2_GCN_H +#define LIB2_GCN_H + +/* Types. */ + +typedef char QItype __attribute__ ((mode (QI))); +typedef unsigned char UQItype __attribute__ ((mode (QI))); +typedef short HItype __attribute__ ((mode (HI))); +typedef unsigned short UHItype __attribute__ ((mode (HI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int word_type __attribute__ ((mode (__word__))); + +/* Exported functions. */ +extern SItype __divsi3 (SItype, SItype); +extern SItype __modsi3 (SItype, SItype); +extern SItype __udivsi3 (SItype, SItype); +extern SItype __umodsi3 (SItype, SItype); +extern HItype __divhi3 (HItype, HItype); +extern HItype __modhi3 (HItype, HItype); +extern UHItype __udivhi3 (UHItype, UHItype); +extern UHItype __umodhi3 (UHItype, UHItype); +extern SItype __mulsi3 (SItype, SItype); + +#endif /* LIB2_GCN_H */ diff --git a/libgcc/config/gcn/reduction.c b/libgcc/config/gcn/reduction.c new file mode 100644 index 0000000..fbe9aaa --- /dev/null +++ b/libgcc/config/gcn/reduction.c @@ -0,0 +1,30 @@ +/* Oversized reductions lock variable + Copyright (C) 2017 Free Software Foundation, Inc. + Contributed by Mentor Graphics. + +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/>. */ + +/* We use a global lock variable for reductions on objects larger than + 64 bits. Until and unless proven that lock contention for + different reductions is a problem, a single lock will suffice. */ + +unsigned volatile __reduction_lock = 0; diff --git a/libgcc/config/gcn/sfp-machine.h b/libgcc/config/gcn/sfp-machine.h new file mode 100644 index 0000000..7874081 --- /dev/null +++ b/libgcc/config/gcn/sfp-machine.h @@ -0,0 +1,51 @@ +/* Use 32-bit types here to prevent longlong.h trying to use TImode. + Once TImode works we might be better to use 64-bit here. */ + +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned int +#define _FP_WS_TYPE signed int +#define _FP_I_TYPE int + +#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_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_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) +#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 +#define _FP_NANSIGN_S 0 +#define _FP_NANSIGN_D 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 _FP_TININESS_AFTER_ROUNDING 0 + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN + +/* 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/gcn/t-amdgcn b/libgcc/config/gcn/t-amdgcn new file mode 100644 index 0000000..d0c423d --- /dev/null +++ b/libgcc/config/gcn/t-amdgcn @@ -0,0 +1,25 @@ +LIB2ADD += $(srcdir)/config/gcn/gomp_print.c + +LIB2ADD += $(srcdir)/config/gcn/lib2-divmod.c \ + $(srcdir)/config/gcn/lib2-divmod-hi.c + +LIB2ADD += $(srcdir)/config/gcn/reduction.c + +LIB2ADDEH= +LIB2FUNCS_EXCLUDE=__main + +override LIB2FUNCS_ST := $(filter-out __gcc_bcmp,$(LIB2FUNCS_ST)) + +# Debug information is not useful, and probably uses broken relocations +LIBGCC2_DEBUG_CFLAGS = -g0 + +crt0.o: $(srcdir)/config/gcn/crt0.c + $(crt_compile) -c $< + +# Prevent building "advanced" stuff (for example, gcov support). We don't +# support it, and it may cause the build to fail, because of alloca usage, for +# example. +INHIBIT_LIBC_CFLAGS = -Dinhibit_libc + +# Disable emutls.c (temporarily?) +enable_emutls = no