Commit 1787e9d0 authored by Jeff Johnston's avatar Jeff Johnston

AMD GCN Port contributed by Andrew Stubbs <ams@codesourcery.com>

Add support for the AMD GCN GPU architecture.  This is primarily intended for
use with OpenMP and OpenACC offloading.  It can also be used for stand-alone
programs, but this is intended mostly for testing the compiler and is not
expected to be useful in general.

The GPU architecture is highly parallel, and therefore Newlib must be
configured to use dynamic re-entrancy, and thread-safe malloc.

The only I/O available is a via a shared-memory interface provided by libgomp
and the gcn-run tool included with GCC.  At this time this is limited to
stdout, argc/argv, and the return code.
parent 4d2d891b
......@@ -1179,3 +1179,17 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
(51) Mentor Graphics (amdgcn-* targets)
Copyright (c) 2014-2017 Mentor Graphics.
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
......@@ -118,6 +118,10 @@ case "${host_cpu}" in
machine_dir=aarch64
libm_machine_dir=aarch64
;;
amdgcn*)
newlib_cflags="${newlib_cflags} -D__DYNAMIC_REENT__"
machine_dir=amdgcn
;;
arc*)
machine_dir=arc
;;
......@@ -442,6 +446,10 @@ case "${host}" in
aarch64*-*-*)
newlib_cflags="${newlib_cflags} -D_COMPILING_NEWLIB"
;;
amdgcn*)
sys_dir=amdgcn
have_crt0="no"
;;
arm*-*-*)
newlib_cflags="${newlib_cflags} -D_COMPILING_NEWLIB"
sys_dir=arm
......
......@@ -452,6 +452,10 @@
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __AMDGCN__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __CYGWIN__
#define __OBSOLETE_MATH_DEFAULT 0
#endif
......
......@@ -8,6 +8,10 @@
#define MALLOC_ALIGNMENT 16
#endif
#ifdef __AMDGCN__
#define __DYNAMIC_REENT__
#endif
/* exceptions first */
#if defined(__H8500__) || defined(__W65__)
#define __SMALL_BITFIELDS
......
## Process this file with automake to generate Makefile.in
AUTOMAKE_OPTIONS = cygnus
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
AM_CCASFLAGS = $(INCLUDES)
noinst_LIBRARIES = lib.a
lib_a_SOURCES = abort.c exit.c atexit.c malloc_support.c getreent.c signal.c
lib_a_CFLAGS = $(AM_CFLAGS)
ACLOCAL_AMFLAGS = -I ../../.. -I ../../../..
CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
This diff is collapsed.
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2014-2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <stdlib.h>
#include <signal.h>
#include "exit-value.h"
void __attribute__((noreturn))
abort (void)
{
write (2, "GCN Kernel Aborted\n", 19);
exit_with_status_and_signal (0, SIGABRT);
}
This diff is collapsed.
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2014-2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <stdlib.h>
int
atexit (void (*function)(void))
{
/* Our current implementation of exit does not run functions registered with
atexit, so fail here. */
abort ();
return 1;
}
This diff is collapsed.
dnl This is the newlib/libc/machine/amdgcn configure.in file.
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT([newlib],[NEWLIB_VERSION])
AC_CONFIG_SRCDIR([Makefile.am])
dnl Can't be done in NEWLIB_CONFIGURE because that confuses automake.
AC_CONFIG_AUX_DIR(../../../..)
NEWLIB_CONFIGURE(../../..)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#ifndef _AMDGCN_EXIT_VALUE_H_
#define _AMDGCN_EXIT_VALUE_H_
static inline void __attribute__((noreturn))
exit_with_int (int val)
{
/* Write the exit value to the conventional place. */
int *return_value;
asm ("s_load_dwordx2 %0, s[8:9], 16 glc\n\t"
"s_waitcnt 0" : "=Sg"(return_value));
*return_value = val;
/* Terminate the current kernel. */
asm ("s_dcache_wb");
asm ("s_endpgm");
__builtin_unreachable ();
}
static inline void __attribute__((noreturn))
exit_with_status_and_signal (int val, int signal)
{
if (signal == 0)
val = val & 0xff;
else
{
val = (128 + signal) & 0xff;
signal = signal & 0xff;
}
exit_with_int ((0xffff << 16) | (signal << 8) | val);
}
#endif
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2014-2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <stdlib.h>
#include "exit-value.h"
void __attribute__((noreturn))
exit (int val)
{
exit_with_status_and_signal (val, 0);
}
/* get thread-specific reentrant pointer */
#include <reent.h>
#include <stdint.h>
#include <stdlib.h>
/* Copied from the HSA documentation. */
typedef struct hsa_signal_s {
uint64_t handle;
} hsa_signal_t;
typedef struct hsa_kernel_dispatch_packet_s {
uint16_t header ;
uint16_t setup;
uint16_t workgroup_size_x ;
uint16_t workgroup_size_y ;
uint16_t workgroup_size_z;
uint16_t reserved0;
uint32_t grid_size_x ;
uint32_t grid_size_y ;
uint32_t grid_size_z;
uint32_t private_segment_size;
uint32_t group_segment_size;
uint64_t kernel_object;
uint64_t reserved2;
hsa_signal_t completion_signal;
} hsa_kernel_dispatch_packet_t;
struct _reent *
__getreent (void)
{
/* Place the reent data at the top of the stack allocation.
s[0:1] contains a 48-bit private segment base address.
s11 contains the offset to the base of the stack.
s[4:5] contains the dispatch pointer.
WARNING: this code will break if s[0:3] is ever used for anything! */
const register long buffer_descriptor asm("s0");
long private_segment = buffer_descriptor & 0x0000ffffffffffff;
const register int stack_offset asm("s11");
const register hsa_kernel_dispatch_packet_t *dispatch_ptr asm("s4");
struct data {
int marker;
struct _reent reent;
} *data;
long stack_base = private_segment + stack_offset;
long stack_end = stack_base + dispatch_ptr->private_segment_size * 64;
long addr = (stack_end - sizeof(struct data)) & ~7;
data = (struct data *)addr;
register long sp asm("s16");
if (sp >= addr)
goto stackoverflow;
/* Place a marker in s3 to indicate that the reent data is initialized.
The register is known to hold part of an unused buffer descriptor
when the kernel is launched. This may not be unused forever, but
we already used s0 and s1 above, so this doesn't do extra harm. */
register int s3 asm("s3");
if (s3 != 123456)
{
asm("s_mov_b32 s3, 123456");
data->marker = 123456;
__builtin_memset (&data->reent, 0, sizeof(struct _reent));
_REENT_INIT_PTR_ZEROED (&data->reent);
}
else if (data->marker != 123456)
goto stackoverflow;
return &data->reent;
stackoverflow:
write (2, "GCN Stack Overflow!\n", 20);
abort ();
}
/*
* Support file for AMDGCN in newlib.
* Copyright (c) 2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <stdlib.h>
#include <stdint.h>
#include <reent.h>
/* _sbrk_r expects us to use the real errno, not the reentrant one. */
#include <errno.h>
#undef errno
extern int errno;
/* The runtime passes in heap space like this. */
struct heap {
int64_t size;
char data[0];
};
static char *__heap_ptr = (char*)-1;
static char *__heap_end = (char*)-1;
static int __heap_lock = 0;
static void *__heap_lock_id = NULL;
static int __heap_lock_cnt = 0;
void *
sbrk (ptrdiff_t nbytes)
{
if (__heap_ptr == (char *)-1)
{
/* Find the heap from kernargs.
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 heap data is at kernargs[3]. */
struct heap *heap = *(struct heap **)(kernargs + 24);
__heap_ptr = heap->data;
__heap_end = __heap_ptr + heap->size;
}
if ((__heap_ptr + nbytes) >= __heap_end)
{
errno = ENOMEM;
return (void*)-1;
}
char *base = __heap_ptr;
__heap_ptr += nbytes;
return base;
}
void
__malloc_lock (struct _reent *reent)
{
void *id = reent;
if (id == __heap_lock_id)
{
if (__heap_lock_cnt < 1)
abort ();
++__heap_lock_cnt;
return;
}
while (__sync_lock_test_and_set (&__heap_lock, 1))
/* A sleep seems like it should allow the wavefront to yeild (maybe?)
Use the shortest possible sleep time of 1*64 cycles. */
asm volatile ("s_sleep\t1" ::: "memory");
if (__heap_lock_id != NULL)
abort ();
if (__heap_lock_cnt != 0)
abort ();
__heap_lock_cnt = 1;
__heap_lock_id = id;
}
void
__malloc_unlock (struct _reent *reent)
{
void *id = reent;
if (id != __heap_lock_id)
abort ();
if (__heap_lock_cnt < 1)
abort ();
--__heap_lock_cnt;
if (__heap_lock_cnt > 0)
return;
__heap_lock_id = NULL;
__sync_lock_release (&__heap_lock);
}
#include <signal.h>
#include <errno.h>
_sig_func_ptr
signal (int sig,
_sig_func_ptr func)
{
errno = EINVAL;
return NULL;
}
......@@ -787,6 +787,7 @@ CPPFLAGS
CPP'
ac_subdirs_all='a29k
aarch64
amdgcn
arc
arm
bfin
......@@ -11502,7 +11503,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11505 "configure"
#line 11506 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
......@@ -11608,7 +11609,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11611 "configure"
#line 11612 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
......@@ -11854,6 +11855,8 @@ if test -n "${machine_dir}"; then
subdirs="$subdirs a29k"
;;
aarch64) subdirs="$subdirs aarch64"
;;
amdgcn) subdirs="$subdirs amdgcn"
;;
arc) subdirs="$subdirs arc"
;;
......
......@@ -25,6 +25,7 @@ if test -n "${machine_dir}"; then
case ${machine_dir} in
a29k) AC_CONFIG_SUBDIRS(a29k) ;;
aarch64) AC_CONFIG_SUBDIRS(aarch64) ;;
amdgcn) AC_CONFIG_SUBDIRS(amdgcn) ;;
arc) AC_CONFIG_SUBDIRS(arc) ;;
arm) AC_CONFIG_SUBDIRS(arm) ;;
bfin) AC_CONFIG_SUBDIRS(bfin) ;;
......
......@@ -5,6 +5,11 @@
#include <string.h>
#include <unistd.h>
#if defined(__AMDGCN__)
/* GCN does not support constructors, yet. */
uintptr_t __stack_chk_guard = 0x00000aff; /* 0, 0, '\n', 255 */
#else
uintptr_t __stack_chk_guard = 0;
void
......@@ -24,6 +29,7 @@ __stack_chk_init (void)
((unsigned char *)&__stack_chk_guard)[3] = 255;
#endif
}
#endif
void
__attribute__((__noreturn__))
......
## Process this file with automake to generate Makefile.in
AUTOMAKE_OPTIONS = cygnus
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
AM_CCASFLAGS = $(INCLUDES) $(CFLAGS)
noinst_LIBRARIES = lib.a
lib_a_SOURCES = close.c fstat.c isatty.c lseek.c read.c write.c
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
lib_a_CFLAGS = $(AM_CFLAGS)
ACLOCAL_AMFLAGS = -I ../../.. -I ../../../..
CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
This diff is collapsed.
This diff is collapsed.
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <unistd.h>
#include <errno.h>
int close(int fildes)
{
errno = EIO;
return -1;
}
This diff is collapsed.
dnl This is the newlib/libc/sys/amdgcn configure.in file.
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT([newlib],[NEWLIB_VERSION])
AC_CONFIG_SRCDIR([close.c])
dnl Can't be done in NEWLIB_CONFIGURE because that confuses automake.
AC_CONFIG_AUX_DIR(../../../..)
NEWLIB_CONFIGURE(../../..)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <unistd.h>
#include <errno.h>
int fstat(int fildes, struct stat *buf)
{
errno = EIO;
return -1;
}
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <unistd.h>
#include <errno.h>
int isatty(int fd)
{
errno = EINVAL;
return 0;
}
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <unistd.h>
#include <errno.h>
off_t lseek(int fildes, off_t offset, int whence)
{
errno = ESPIPE;
return -1;
}
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <stdio.h>
_READ_WRITE_RETURN_TYPE read (int fildes, void *buf, size_t nbyte)
{
return 0;
}
/*
* Support file for amdgcn in newlib.
* Copyright (c) 2014, 2017 Mentor Graphics.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
/* 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];
};
_READ_WRITE_RETURN_TYPE write (int fd, const void *buf, size_t count)
{
if (fd != 1 && fd != 2)
{
errno = EBADF;
return -1;
}
/* The output data is at ((void*)kernargs)[2]. */
register void **kernargs asm("s8");
struct output *data = (struct output *)kernargs[2];
/* Each output slot allows 256 bytes, so reserve as many as we need. */
int slot_count = ((count+1)/256)+1;
int index = __atomic_fetch_add (&data->next_output, slot_count,
__ATOMIC_ACQUIRE);
for (int c = count;
c >= 0 && index < 1000;
buf += 256, c -= 256, index++)
{
if (c < 128)
{
memcpy (data->queue[index].msg, buf, c);
data->queue[index].msg[c] = '\0';
data->queue[index].text[0] = '\0';
}
else if (c < 256)
{
memcpy (data->queue[index].msg, buf, 128);
memcpy (data->queue[index].text, buf+128, c-128);
data->queue[index].text[c-128] = '\0';
}
else
{
memcpy (data->queue[index].msg, buf, 128);
memcpy (data->queue[index].text, buf+128, 128);
}
data->queue[index].type = 3; /* Raw. */
__atomic_store_n (&data->queue[index].written, 1, __ATOMIC_RELEASE);