new file mode 100644
@@ -0,0 +1,73 @@
+/*
+ * arc-main-helper.c -- provide custom __setup_argv_and_call_main();
+ * This function uses _argc(), _argvlen(), _argv() and _setup_low_level().
+ * Description for these functions can be found below in this file.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <stddef.h>
+#include <stdint.h>
+#include <alloca.h>
+
+/* Return number of arguments passed to host executable. */
+extern int _argc (void);
+/*
+ * Return buffer length to be used for a given argument number.
+ * Buffer length includes '\0' character.
+ */
+extern uint32_t _argvlen (int a);
+/*
+ * Copy argument into buffer arg.
+ * arg must be no less than argvlen(a) length.
+ */
+extern int _argv (int a, char *arg);
+/* Custom setup. Can be used to setup some port-specific stuff. */
+extern int _setup_low_level (void);
+/* main function to call. */
+extern int main (int argc, char **argv);
+
+/* Copy arguments from host to local stack and call main. */
+int
+__setup_argv_and_call_main (void)
+{
+ int i;
+ int argc;
+ char **argv = NULL;
+
+ argc = _argc ();
+ if (argc > 0)
+ argv = alloca ((argc + 1) * sizeof (char *));
+
+ for (i = 0; i < argc; i++)
+ {
+ uint32_t arg_len;
+
+ arg_len = _argvlen (i);
+ if (arg_len == 0)
+ break;
+
+ argv[i] = alloca (arg_len);
+
+ if (_argv (i, argv[i]) < 0)
+ break;
+ }
+
+ if (argv)
+ argv[i] = NULL;
+
+ _setup_low_level ();
+
+ return main (i, argv);
+}
new file mode 100644
@@ -0,0 +1,129 @@
+/*
+ * arc-timer.c -- provide API for ARC timers.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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.
+ *
+ */
+
+#define ARC_TIM_BUILD 0x75
+#define ARC_TIM_BUILD_VER_MASK 0x00FF
+#define ARC_TIM_BUILD_TIM0_FL 0x0100
+#define ARC_TIM_BUILD_TIM1_FL 0x0200
+
+#define ARC_TIM_COUNT0 0x21
+#define ARC_TIM_CONTROL0 0x22
+#define ARC_TIM_LIMIT0 0x23
+
+#define ARC_TIM_COUNT1 0x100
+#define ARC_TIM_CONTROL1 0x101
+#define ARC_TIM_LIMIT1 0x102
+
+#define ARC_TIM_CONTROL_NH_FL 0x0002
+
+/* Timer used by '_default' functions. */
+const unsigned int arc_timer_default = 0;
+
+/* Check if given timer exists. */
+static int
+_arc_timer_present (unsigned int tim)
+{
+ unsigned int bcr = __builtin_arc_lr (ARC_TIM_BUILD);
+ unsigned int ver = bcr & ARC_TIM_BUILD_VER_MASK;
+
+ if (ver == 0)
+ return 0;
+ else if (ver == 1)
+ return 1;
+ else if (tim == 0)
+ return ((bcr & ARC_TIM_BUILD_TIM0_FL) != 0);
+ else if (tim == 1)
+ return ((bcr & ARC_TIM_BUILD_TIM1_FL) != 0);
+ else
+ return 0;
+}
+
+/* Get raw value of a given timer. */
+static unsigned int
+_arc_timer_read (unsigned int tim)
+{
+ if (_arc_timer_present (tim))
+ {
+ if (tim == 0)
+ return __builtin_arc_lr (ARC_TIM_COUNT0);
+ else if (tim == 1)
+ return __builtin_arc_lr (ARC_TIM_COUNT1);
+ }
+
+ return 0;
+}
+
+/*
+ * Set default values to a given timer.
+ * Defaults: Not Halted bit is set, limit is 0xFFFFFFFF, count set to 0.
+ */
+static void
+_arc_timer_reset (unsigned int tim)
+{
+ unsigned int ctrl, tim_control, tim_count, tim_limit;
+
+ if (_arc_timer_present (tim))
+ {
+ if (tim == 0)
+ {
+ tim_control = ARC_TIM_CONTROL0;
+ tim_count = ARC_TIM_COUNT0;
+ tim_limit = ARC_TIM_LIMIT0;
+ }
+ else if (tim == 1)
+ {
+ tim_control = ARC_TIM_CONTROL1;
+ tim_count = ARC_TIM_COUNT1;
+ tim_limit = ARC_TIM_LIMIT1;
+ }
+ else
+ {
+ return;
+ }
+
+ ctrl = __builtin_arc_lr (tim_control);
+ /* Disable timer interrupt when programming. */
+ __builtin_arc_sr (0, tim_control);
+ /* Default limit is 24-bit, increase it to 32-bit. */
+ __builtin_arc_sr (0xFFFFFFFF, tim_limit);
+ /* Set NH bit to count only when processor is running. */
+ __builtin_arc_sr (ctrl | ARC_TIM_CONTROL_NH_FL, tim_control);
+ __builtin_arc_sr (0, tim_count);
+ }
+}
+
+
+/* Check if arc_timer_default exists. */
+int
+_arc_timer_default_present (void)
+{
+ return _arc_timer_present (arc_timer_default);
+}
+
+/* Read arc_timer_default value. */
+unsigned int
+_arc_timer_default_read (void)
+{
+ return _arc_timer_read (arc_timer_default);
+}
+
+/* Reset arc_timer_default. */
+void
+_arc_timer_default_reset (void)
+{
+ _arc_timer_reset (arc_timer_default);
+}
new file mode 100644
@@ -0,0 +1,25 @@
+/*
+ * arc-timer.h -- provide API for the default (number 0) ARC timer.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 _ARC_TIMER_H
+#define _ARC_TIMER_H
+
+void _arc_timer_default_reset (void);
+int _arc_timer_default_present (void);
+unsigned int _arc_timer_default_read (void);
+
+#endif /* !_ARC_TIMER_H */
@@ -206,16 +206,9 @@ __start:
jl @_monstartup
#endif /* PROFILE_SUPPORT */
- mov_s r0, r13
- mov_s r1, r14
; branch to main
-#if defined (__ARCEM__) || defined (__ARCHS__)
mov fp,0 ; initialize frame pointer
- jl @main
-#else
- bl.d @main
- mov fp, 0 ; initialize frame pointer
-#endif /* __ARCEM__ || __ARCHS__ */
+ jl @__setup_argv_and_call_main
#ifdef PROFILE_SUPPORT
mov r13, r0 ; Save return code
@@ -225,6 +218,23 @@ __start:
; r0 contains exit code
j @exit
+ .size __start, .-__start
+
+;;; arc-main-helper.o object can be used to replace this function and
+;;; properly set up arguments and/or other low-level stuff.
+ .section .text.__setup_argv_and_call_main,"ax",@progbits
+ .weak __setup_argv_and_call_main
+ .type __setup_argv_and_call_main, @function
+ .align 4
+
+__setup_argv_and_call_main:
+ push_s blink
+; Call main with argc = 0 and *argv[] = 0
+ mov r0, 0
+ mov r1, 0
+ jl @main
+ pop_s blink
+ j_s [blink]
.section .text._exit_halt,"ax",@progbits
.global _exit_halt
new file mode 100644
@@ -0,0 +1,27 @@
+/*
+ * hl-setup.c -- provide _setup_low_level() to initialize timer.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 "arc-timer.h"
+
+/* Configure and reset the default timer. */
+int
+_setup_low_level (void)
+{
+ _arc_timer_default_reset ();
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,81 @@
+/*
+ * hl-stub.c -- provide _kill() and _getpid().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <unistd.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "glue.h"
+
+
+/* If PID is equal to __MYPID, exit with sig as retcode. */
+int
+_kill (int pid, int sig)
+{
+ if (pid == __MYPID)
+ _exit (sig);
+
+ errno = ENOSYS;
+ return -1;
+}
+
+
+/* Return __MYPID. */
+int
+_getpid (void)
+{
+ return __MYPID;
+}
+
+
+/* hostlink backend has only fstat(), so use fstat() in stat(). */
+int
+_stat (const char *pathname, struct stat *buf)
+{
+ int fd;
+ int ret;
+ int saved_errno;
+
+ fd = open (pathname, O_RDONLY);
+ if (fd < 0)
+ {
+ /* errno is set by open(). */
+ return -1;
+ }
+
+ ret = fstat (fd, buf);
+ saved_errno = errno;
+
+ close (fd);
+
+ errno = saved_errno;
+
+ return ret;
+}
+
+
+/* No Metaware hostlink backend for this call. */
+int
+_link (const char *oldpath __attribute__ ((unused)),
+ const char *newpath __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
new file mode 100644
@@ -0,0 +1,14 @@
+%rename link_gcc_c_sequence hl_link_gcc_c_sequence
+%rename startfile hl_startfile
+
+*hl_libgloss:
+-lhl
+
+*hl_libc:
+%{!specs=nano.specs:-lc} %{specs=nano.specs:-lc_nano}
+
+*link_gcc_c_sequence:
+%(hl_link_gcc_c_sequence) --start-group %G %(hl_libc) %(hl_libgloss) --end-group
+
+*startfile:
+%(hl_startfile) arc-main-helper%O%s
new file mode 100644
@@ -0,0 +1,350 @@
+/*
+ * hl_api.c -- high-level Hostlink IO API.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <string.h>
+#include <stdarg.h>
+
+#include "hl_gw.h"
+#include "hl_api.h"
+
+/* Parameter types. */
+#define PAT_CHAR 1
+#define PAT_SHORT 2
+#define PAT_INT 3
+#define PAT_STRING 4
+/* For future use. */
+#define PAT_INT64 5
+
+/* Used internally to pass user hostlink parameters to _hl_message(). */
+struct _hl_user_info {
+ uint32_t vendor_id;
+ uint32_t opcode;
+ uint32_t result;
+};
+
+/*
+ * Main function to send a message using hostlink.
+ *
+ * syscall - one of HL_SYSCALL_* defines from hl_api.h.
+ *
+ * user - parameters and return value for _user_hostlink implementation.
+ * Packing structure:
+ * uint32 vendor_id - user-defined vendor ID. ID 1025 is reserved for
+ * GNU IO extensions.
+ * uint32 opcode - operation code for user-defined hostlink.
+ * char format[] - argument string in the same format as for
+ * _hl_message() function, see below.
+ *
+ * format - argument and return values format string [(i4sp)*:?(i4sp)*], where
+ * characters before ':' is arguments and after is return values.
+ * Supported format characters:
+ * i or 4 - uint32 value, pack_int will be used;
+ * s - char * data, pack_str will be used;
+ * p - void * data, pack_ptr will be used.
+ *
+ * ap - argument values and pointers to the output values. Must be in sync
+ * with format string.
+ * For hostlink message argument:
+ * i or 4 - uint32 value;
+ * s - char * pointer to the NUL-teminated string;
+ * p - void * pointer to the buffer and uint32 buffer length.
+ * For output values:
+ * i or 4 - uint32 * pointer to uint32 to return;
+ * s - char * pointer to buffer to return, it must have enough
+ * space to store returned data.
+ * You can get packed buffer length with _hl_get_ptr_len();
+ * p - void * pointer and uint32 * length pointer to store
+ * returned data along with length. Buffer must be enough
+ * to store returned data.
+ * You can get packed buffer length with _hl_get_ptr_len();
+ *
+ * return - pointer to the hostlink buffer after output values.
+ */
+static volatile __uncached char *
+_hl_message_va (uint32_t syscall, struct _hl_user_info *user,
+ const char *format, va_list ap)
+{
+ const char *f = format;
+ volatile __uncached char *p = _hl_payload ();
+ int get_answer = 0;
+
+ p = _hl_pack_int (p, syscall);
+
+ if (syscall == HL_SYSCALL_USER)
+ {
+ p = _hl_pack_int (p, user->vendor_id);
+ p = _hl_pack_int (p, user->opcode);
+ p = _hl_pack_str (p, format);
+ }
+
+ for (; *f; f++)
+ {
+ void *ptr;
+ uint32_t len;
+
+ if (*f == ':')
+ {
+ f++;
+ get_answer = 1;
+ break;
+ }
+
+ switch (*f)
+ {
+ case 'i':
+ case '4':
+ p = _hl_pack_int (p, va_arg (ap, uint32_t));
+ break;
+ case 's':
+ p = _hl_pack_str (p, va_arg (ap, char *));
+ break;
+ case 'p':
+ ptr = va_arg (ap, void *);
+ len = va_arg (ap, uint32_t);
+ p = _hl_pack_ptr (p, ptr, len);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (p == NULL)
+ return NULL;
+ }
+
+ _hl_send (p);
+
+ p = _hl_recv ();
+
+ if (syscall == HL_SYSCALL_USER && p)
+ p = _hl_unpack_int (p, &user->result);
+
+ if (p && get_answer)
+ {
+ for (; *f; f++)
+ {
+ void *ptr;
+ uint32_t *plen;
+
+ switch (*f)
+ {
+ case 'i':
+ case '4':
+ p = _hl_unpack_int (p, va_arg (ap, uint32_t *));
+ break;
+ case 's':
+ p = _hl_unpack_str (p, va_arg (ap, char *));
+ break;
+ case 'p':
+ ptr = va_arg (ap, void *);
+ plen = va_arg (ap, uint32_t *);
+ p = _hl_unpack_ptr (p, ptr, plen);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (p == NULL)
+ return NULL;
+ }
+ }
+
+ return p;
+}
+
+/*
+ * Pack integer value (uint32) to provided buffer.
+ * Packing structure:
+ * uint16 type (PAT_INT = 3)
+ * uint16 size (4)
+ * uint32 value
+ */
+volatile __uncached char *
+_hl_pack_int (volatile __uncached char *p, uint32_t x)
+{
+ volatile __uncached uint16_t *type = (volatile __uncached uint16_t *) p;
+ volatile __uncached uint16_t *size = (volatile __uncached uint16_t *)
+ (p + 2);
+ volatile __uncached uint32_t *val = (volatile __uncached uint32_t *)
+ (p + 4);
+ const uint32_t payload_used = 8;
+
+ if (_hl_payload_left (p) < payload_used)
+ return NULL;
+
+ *type = PAT_INT;
+ *size = 4;
+ *val = x;
+
+ return p + payload_used;
+}
+
+/*
+ * Pack data (pointer and legth) to provided buffer.
+ * Packing structure:
+ * uint16 type (PAT_STRING = 4)
+ * uint16 size (length)
+ * char buf[length]
+ */
+volatile __uncached char *
+_hl_pack_ptr (volatile __uncached char *p, const void *s, uint16_t len)
+{
+ volatile __uncached uint16_t *type = (volatile __uncached uint16_t *) p;
+ volatile __uncached uint16_t *size = (volatile __uncached uint16_t *)
+ (p + 2);
+ volatile __uncached char *buf = p + 4;
+ const uint32_t payload_used = 4 + ALIGN (len, 4);
+
+ if (_hl_payload_left (p) < payload_used)
+ return NULL;
+
+ *type = PAT_STRING;
+ *size = len;
+
+ /* _vdmemcpy(buf, s, len); */
+ for (uint16_t i = 0; i < len; i++)
+ buf[i] = ((const char *) s)[i];
+
+ return p + payload_used;
+}
+
+/*
+ * Pack NUL-terminated string to provided buffer.
+ * Packing structure:
+ * uint16 type (PAT_STRING = 4)
+ * uint16 size (length)
+ * char buf[length]
+ */
+volatile __uncached char *
+_hl_pack_str (volatile __uncached char *p, const char *s)
+{
+ return _hl_pack_ptr (p, s, strlen (s) + 1);
+}
+
+/* Unpack integer value (uint32_t) from a buffer. */
+volatile __uncached char *
+_hl_unpack_int (volatile __uncached char *p, uint32_t *x)
+{
+ volatile __uncached uint16_t *type = (volatile __uncached uint16_t *) p;
+ volatile __uncached uint16_t *size = (volatile __uncached uint16_t *)
+ (p + 2);
+ volatile __uncached uint32_t *val = (volatile __uncached uint32_t *)
+ (p + 4);
+ const uint32_t payload_used = 8;
+
+ if (_hl_payload_left (p) < payload_used || *type != PAT_INT || *size != 4)
+ return NULL;
+
+ if (x)
+ *x = *val;
+
+ return p + payload_used;
+}
+
+/* Unpack data from a buffer. */
+volatile __uncached char *
+_hl_unpack_ptr (volatile __uncached char *p, void *s, uint32_t *plen)
+{
+ volatile __uncached uint16_t *type = (volatile __uncached uint16_t *) p;
+ volatile __uncached uint16_t *size = (volatile __uncached uint16_t *)
+ (p + 2);
+ volatile __uncached char *buf = p + 4;
+ uint32_t payload_used;
+ uint32_t len;
+
+ if (_hl_payload_left (p) < 4 || *type != PAT_STRING)
+ return NULL;
+
+ len = *size;
+ payload_used = 4 + ALIGN (len, 4);
+
+ if (_hl_payload_left (p) < payload_used)
+ return NULL;
+
+ if (plen)
+ *plen = len;
+
+ /* _vsmemcpy(s, buf, len); */
+ if (s)
+ {
+ for (uint32_t i = 0; i < len; i++)
+ ((char *) s)[i] = buf[i];
+ }
+
+ return p + payload_used;
+}
+
+/*
+ * Unpack data from a buffer.
+ *
+ * No difference compared to _hl_unpack_ptr, except that this function
+ * does not return a length.
+ */
+volatile __uncached char *
+_hl_unpack_str (volatile __uncached char *p, char *s)
+{
+ return _hl_unpack_ptr (p, s, NULL);
+}
+
+/* Return length of packed data (PAT_STRING) if it is on top of the buffer. */
+uint32_t
+_hl_get_ptr_len (volatile __uncached char *p)
+{
+ volatile __uncached uint16_t *type = (volatile __uncached uint16_t *) p;
+ volatile __uncached uint16_t *size = (volatile __uncached uint16_t *)
+ (p + 2);
+
+ if (_hl_payload_left (p) < 4 || *type != PAT_STRING)
+ return 0;
+
+ return *size;
+}
+
+/* Public version of _hl_message_va(). */
+volatile __uncached char *
+_hl_message (uint32_t syscall, const char *format, ...)
+{
+ va_list ap;
+ volatile __uncached char *p;
+
+ va_start (ap, format);
+
+ p = _hl_message_va (syscall, 0, format, ap);
+
+ va_end (ap);
+
+ return p;
+}
+
+/*
+ * API to call user-defined hostlink. See description of user argument in
+ * _hl_message_va().
+ */
+uint32_t
+_user_hostlink (uint32_t vendor, uint32_t opcode, const char *format, ...)
+{
+ va_list ap;
+ struct _hl_user_info ui = { .vendor_id = vendor,
+ .opcode = opcode };
+
+ va_start (ap, format);
+
+ _hl_message_va (HL_SYSCALL_USER, &ui, format, ap);
+
+ va_end (ap);
+
+ return ui.result;
+}
new file mode 100644
@@ -0,0 +1,77 @@
+/*
+ * hl_api.h -- provide high-level API for Hostlink IO.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <stdint.h>
+#include "hl_toolchain.h"
+
+#ifndef _HL_API_H
+#define _HL_API_H
+
+#define HL_SYSCALL_OPEN 0
+#define HL_SYSCALL_CLOSE 1
+#define HL_SYSCALL_READ 2
+#define HL_SYSCALL_WRITE 3
+#define HL_SYSCALL_LSEEK 4
+#define HL_SYSCALL_UNLINK 5
+#define HL_SYSCALL_ISATTY 6
+#define HL_SYSCALL_TMPNAM 7
+#define HL_SYSCALL_GETENV 8
+#define HL_SYSCALL_CLOCK 9
+#define HL_SYSCALL_TIME 10
+#define HL_SYSCALL_RENAME 11
+#define HL_SYSCALL_ARGC 12
+#define HL_SYSCALL_ARGV 13
+#define HL_SYSCALL_RETCODE 14
+#define HL_SYSCALL_ACCESS 15
+#define HL_SYSCALL_GETPID 16
+#define HL_SYSCALL_GETCWD 17
+#define HL_SYSCALL_USER 18
+
+#define HL_GNUIO_EXT_VENDOR_ID 1025
+
+#define HL_GNUIO_EXT_FSTAT 1
+
+/*
+ * Main functions to work with regular syscalls and user-defined hostlink
+ * messages.
+ */
+volatile __uncached char *_hl_message (uint32_t syscall,
+ const char *format, ...);
+uint32_t _user_hostlink (uint32_t vendor, uint32_t opcode,
+ const char *format, ...);
+
+
+/* Fuctions for direct work with the Hostlink buffer. */
+volatile __uncached char *_hl_pack_int (volatile __uncached char *p,
+ uint32_t x);
+volatile __uncached char *_hl_pack_ptr (volatile __uncached char *p,
+ const void *s, uint16_t len);
+volatile __uncached char *_hl_pack_str (volatile __uncached char *p,
+ const char *s);
+volatile __uncached char *_hl_unpack_int (volatile __uncached char *p,
+ uint32_t *x);
+volatile __uncached char *_hl_unpack_ptr (volatile __uncached char *p,
+ void *s, uint32_t *plen);
+volatile __uncached char *_hl_unpack_str (volatile __uncached char *p,
+ char *s);
+uint32_t _hl_get_ptr_len (volatile __uncached char *p);
+
+/* Low-level functions from hl_gw. */
+extern uint32_t _hl_iochunk_size (void);
+extern void _hl_delete (void);
+
+#endif /* !_HL_API_H */
new file mode 100644
@@ -0,0 +1,45 @@
+/*
+ * hl_argc.c -- provide _argc().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <stddef.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* Implements HL_SYSCALL_ARGC. */
+static __always_inline int
+_hl_argc (void)
+{
+ uint32_t ret;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_ARGC, ":i", (uint32_t *) &ret);
+
+ if (p == NULL)
+ ret = 0;
+
+ _hl_delete ();
+
+ return ret;
+}
+
+/* See arc-main-helper.c. */
+int
+_argc (void)
+{
+ return _hl_argc ();
+}
new file mode 100644
@@ -0,0 +1,67 @@
+/*
+ * hl_argv.c -- provide _argv().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <stddef.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* Get buffer length for argv[a] using HL_SYSCALL_ARGV. */
+static __always_inline uint32_t
+_hl_argvlen (int a)
+{
+ uint32_t ret = 0;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_ARGV, "i", (uint32_t) a);
+ if (p != NULL)
+ ret = _hl_get_ptr_len (p);
+
+ _hl_delete ();
+
+ return ret;
+}
+
+/* Implements HL_SYSCALL_ARGV. */
+static __always_inline int
+_hl_argv (int a, char *arg)
+{
+ int ret = 0;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_ARGV, "i:s", (uint32_t) a, (char *) arg);
+ if (p == NULL)
+ ret = -1;
+
+ _hl_delete ();
+
+ return ret;
+}
+
+/* See arc-main-helper.c. */
+uint32_t
+_argvlen (int a)
+{
+ return _hl_argvlen (a);
+}
+
+/* See arc-main-helper.c. */
+int
+_argv (int a, char *arg)
+{
+ return _hl_argv (a, arg);
+}
new file mode 100644
@@ -0,0 +1,87 @@
+/*
+ * hl_clock.c -- provide _clock() and _times().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <time.h>
+#include <sys/times.h>
+
+#include "../arc-timer.h"
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* Implements HL_SYSCALL_CLOCK. */
+static __always_inline clock_t
+_hl_clock (void)
+{
+ uint32_t ret;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_CLOCK, ":i", (uint32_t *) &ret);
+
+ _hl_delete ();
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+
+ return ret;
+}
+
+/*
+ * This implementation returns timer 0 value if it exists or
+ * host clock() value converted to target clocks.
+ *
+ * Please note that this value cannot be converted to seconds
+ * using CLOCKS_PER_SEC.
+ */
+clock_t
+_clock (void)
+{
+ if (_arc_timer_default_present ())
+ return _arc_timer_default_read ();
+ else
+ return _hl_clock ();
+}
+
+/* All time is counted as user time. */
+clock_t
+_times (struct tms *tp)
+{
+ clock_t ret;
+
+ if (tp == NULL)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+
+ ret = _clock ();
+
+ if (ret == (clock_t) -1)
+ return ret;
+
+ tp->tms_utime = ret;
+ tp->tms_stime = 0;
+ tp->tms_cutime = 0;
+ tp->tms_cstime = 0;
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,58 @@
+/*
+ * hl_close.c -- provide _close().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* Implements HL_SYSCALL_CLOSE. */
+static __always_inline int
+_hl_close (int fd)
+{
+ int32_t ret;
+ uint32_t host_errno;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_CLOSE, "i:ii",
+ (uint32_t) fd, /* i */
+ (uint32_t *) &ret, /* :i */
+ (uint32_t *) &host_errno /* :i */);
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ ret = -1;
+ }
+ else if (ret < 0)
+ {
+ errno = host_errno;
+ ret = -1;
+ }
+
+ _hl_delete ();
+
+ return ret;
+}
+
+int
+_close (int fd)
+{
+ return _hl_close (fd);
+}
new file mode 100644
@@ -0,0 +1,42 @@
+/*
+ * hl_exit.c -- provide _exit().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <stdint.h>
+#include <unistd.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* From crt0. */
+extern void __noreturn __longcall _exit_halt (void);
+
+/* Push retcode to host. Implements HL_SYSCALL_RETCODE. */
+static __always_inline void
+_hl_retcode (int32_t ret)
+{
+ (void) _hl_message (HL_SYSCALL_RETCODE, "i", (uint32_t) ret);
+
+ _hl_delete ();
+}
+
+void __noreturn
+_exit (int ret)
+{
+ _hl_retcode (ret);
+
+ _exit_halt ();
+}
new file mode 100644
@@ -0,0 +1,95 @@
+/*
+ * hl_fstat.c -- provide _fstat().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* Hostlink IO version of struct stat. */
+struct _hl_stat {
+ uint32_t hl_dev; /* ID of device containing file. */
+ uint16_t hl_ino; /* inode number. */
+ uint16_t hl_mode; /* File type and access mode. */
+ int16_t hl_nlink; /* Number of hard links. */
+ int16_t hl_uid; /* Owner's UID. */
+ int16_t hl_gid; /* Owner's GID. */
+ uint8_t hl_pad[2]; /* Padding to match simulator struct. */
+ uint32_t hl_rdev; /* Device ID (if special file). */
+ int32_t hl_size; /* Size in bytes. */
+ int32_t hl_atime; /* Access time. */
+ int32_t hl_mtime; /* Modification time. */
+ int32_t hl_ctime; /* Creation time. */
+} __packed;
+
+/* Map Hostlink version of stat struct into newlib's one. */
+static __always_inline void
+_hl_fstat_map (const struct _hl_stat *hl_stat, struct stat *stat)
+{
+ stat->st_dev = hl_stat->hl_dev;
+ stat->st_ino = hl_stat->hl_ino;
+ stat->st_mode = hl_stat->hl_mode;
+ stat->st_nlink = hl_stat->hl_nlink;
+ stat->st_uid = hl_stat->hl_uid;
+ stat->st_gid = hl_stat->hl_gid;
+ stat->st_rdev = hl_stat->hl_rdev;
+ stat->st_size = hl_stat->hl_size;
+ stat->st_atime = hl_stat->hl_atime;
+ stat->st_mtime = hl_stat->hl_mtime;
+ stat->st_ctime = hl_stat->hl_ctime;
+}
+
+/* Get host file info. Implements HL_GNUIO_EXT_FSTAT. */
+static __always_inline int
+_hl_fstat (int fd, struct stat *buf)
+{
+ struct _hl_stat hl_stat;
+ int32_t ret;
+ uint32_t host_errno;
+
+ /* Special version of hostlink - retuned values are passed
+ * through inargs.
+ */
+ host_errno = _user_hostlink (HL_GNUIO_EXT_VENDOR_ID, HL_GNUIO_EXT_FSTAT,
+ "iii",
+ (uint32_t) fd,
+ (uint32_t) &hl_stat,
+ (uint32_t) &ret);
+
+ if (ret < 0)
+ {
+ errno = host_errno;
+ return ret;
+ }
+
+ _hl_fstat_map (&hl_stat, buf);
+
+ _hl_delete ();
+
+ return ret;
+}
+
+int
+_fstat (int fd, struct stat *buf)
+{
+ return _hl_fstat (fd, buf);
+}
new file mode 100644
@@ -0,0 +1,69 @@
+/*
+ * hl_gettimeofday.c -- provide _gettimeofday().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* Get host time(). Implements HL_SYSCALL_TIME. */
+static __always_inline int
+_hl_time (uint32_t *host_timer)
+{
+ int ret;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_TIME, ":i", (uint32_t *) host_timer);
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ ret = -1;
+ }
+ else
+ {
+ ret = 0;
+ }
+
+ _hl_delete ();
+
+ return ret;
+}
+
+/* gettimeofday() implementation. Clears *tz if specified. */
+int
+_gettimeofday (struct timeval *tv, struct timezone *tz)
+{
+ int ret;
+ uint32_t host_timer;
+
+ if (tz)
+ memset (tz, 0, sizeof (*tz));
+
+ ret = _hl_time (&host_timer);
+
+ if (ret == 0)
+ {
+ tv->tv_sec = host_timer;
+ tv->tv_usec = 0;
+ }
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,180 @@
+/*
+ * hl_gw.c -- Hostlink gateway, low-level hostlink functions.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 "hl_gw.h"
+
+#define HL_VERSION 1
+
+
+/*
+ * Maximum message size without service information,
+ * see also HL_PAYLOAD_RESERVED.
+ */
+#ifndef HL_IOCHUNK
+ #define HL_IOCHUNK 1024
+#endif
+
+/*
+ * Each syscall argument have 4 bytes of service information in hostlink
+ * protocol (2 bytes for type and 2 for size). Here we reserve space for
+ * 32 arguments.
+ */
+#define HL_PAYLOAD_RESERVED (32 * 4)
+
+/* "No message here" mark. */
+#define HL_NOADDRESS 0xFFFFFFFF
+
+/* Hostlink gateway structure. */
+struct _hl_hdr {
+ uint32_t version; /* Current version is 1. */
+ uint32_t target2host_addr; /* Packet address from target to host. */
+ uint32_t host2target_addr; /* Packet address from host to target. */
+ uint32_t buf_addr; /* Address for host to write answer. */
+ uint32_t payload_size; /* Buffer size without packet header. */
+ uint32_t options; /* For future use. */
+ uint32_t break_to_mon_addr; /* For future use. */
+} __uncached __packed;
+
+/* Hostlink packet header. */
+struct _hl_pkt_hdr {
+ uint32_t packet_id; /* Packet id. Always set to 1 here. */
+ uint32_t total_size; /* Size of packet including header. */
+ uint32_t priority; /* For future use. */
+ uint32_t type; /* For future use. */
+ uint32_t checksum; /* For future use. */
+} __uncached __packed;
+
+/* Main hostlink structure. */
+struct _hl {
+ volatile struct _hl_hdr hdr; /* General hostlink information. */
+ /* Start of the hostlink buffer. */
+ volatile struct _hl_pkt_hdr pkt_hdr;
+ volatile char payload[HL_IOCHUNK + HL_PAYLOAD_RESERVED];
+} __aligned (HL_MAX_DCACHE_LINE) __uncached __packed;
+
+
+/*
+ * Main structure. Do not rename because simulator will look for the
+ * '__HOSTLINK__' symbol.
+ */
+volatile struct _hl __HOSTLINK__ = {
+ .hdr = {
+ .version = 1 ,
+ .target2host_addr = HL_NOADDRESS
+ }
+};
+
+/* Get hostlink payload pointer. */
+volatile __uncached void *
+_hl_payload (void)
+{
+ return (volatile __uncached void *) &__HOSTLINK__.payload[0];
+}
+
+/* Get hostlink payload size (iochunk + reserved space). */
+static uint32_t
+_hl_payload_size (void)
+{
+ return sizeof (__HOSTLINK__.payload);
+}
+
+/* Get used space size in the payload. */
+static uint32_t
+_hl_payload_used (volatile __uncached void *p)
+{
+ return (volatile __uncached char *) p
+ - (volatile __uncached char *) _hl_payload ();
+}
+
+/* Fill hostlink packet header. */
+static void
+_hl_pkt_init (volatile __uncached struct _hl_pkt_hdr *pkt, int size)
+{
+ pkt->packet_id = 1;
+ pkt->total_size = ALIGN (size, 4) + sizeof (*pkt);
+ pkt->priority = 0;
+ pkt->type = 0;
+ pkt->checksum = 0;
+}
+
+/* Get hostlink iochunk size. */
+uint32_t
+_hl_iochunk_size (void)
+{
+ return HL_IOCHUNK;
+}
+
+/* Get free space size in the payload. */
+uint32_t
+_hl_payload_left (volatile __uncached void *p)
+{
+ return _hl_payload_size () - _hl_payload_used (p);
+}
+
+/* Send hostlink packet to the host. */
+void
+_hl_send (volatile __uncached void *p)
+{
+ volatile __uncached struct _hl_hdr *hdr = &__HOSTLINK__.hdr;
+ volatile __uncached struct _hl_pkt_hdr *pkt_hdr = &__HOSTLINK__.pkt_hdr;
+
+ _hl_pkt_init (pkt_hdr, _hl_payload_used (p));
+
+ hdr->buf_addr = (uint32_t) pkt_hdr;
+ hdr->payload_size = _hl_payload_size ();
+ hdr->host2target_addr = HL_NOADDRESS;
+ hdr->version = HL_VERSION;
+ hdr->options = 0;
+ hdr->break_to_mon_addr = 0;
+
+ /* This tells the debugger we have a command.
+ * It is responsibility of debugger to set this back to HL_NOADDRESS
+ * after receiving the packet.
+ * Please note that we don't wait here because some implementations
+ * use _hl_blockedPeek() function as a signal that we send a messege.
+ */
+ hdr->target2host_addr = hdr->buf_addr;
+}
+
+/*
+ * Wait for host response and return pointer to hostlink payload.
+ * Symbol _hl_blockedPeek() is used by the simulator as message signal.
+ */
+volatile __uncached char * __noinline
+_hl_blockedPeek (void)
+{
+ while (__HOSTLINK__.hdr.host2target_addr == HL_NOADDRESS)
+ {
+ /* TODO: Timeout. */
+ }
+
+ return _hl_payload ();
+}
+
+/* Get message from host. */
+volatile __uncached char *
+_hl_recv (void)
+{
+ return _hl_blockedPeek ();
+}
+
+/* Mark hostlink buffer as "No message here". */
+void
+_hl_delete (void)
+{
+ __HOSTLINK__.hdr.target2host_addr = HL_NOADDRESS;
+}
new file mode 100644
@@ -0,0 +1,46 @@
+/*
+ * hl_gw.h -- Hostlink gateway, low-level hostlink functions.
+ * This header should not be used directly, please use hl_api.h instead.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 _HL_GW_H
+#define _HL_GW_H
+
+#include <stdint.h>
+
+#include "hl_toolchain.h"
+
+/* Get hostlink payload pointer and size available for using. */
+volatile __uncached void *_hl_payload (void);
+
+/* Maximum amount of data that can be sent via hostlink in one message. */
+uint32_t _hl_iochunk_size (void);
+
+/*
+ * How many bytes are available in the hostlink payload buffer.
+ * This may be bigger than iochunk size because hostlink payload also contains
+ * reserved space for service information.
+ */
+uint32_t _hl_payload_left (volatile __uncached void *p);
+
+/* Send and receive hostlink packet. */
+void _hl_send (volatile __uncached void *p);
+volatile __uncached char *_hl_recv (void);
+
+/* Mark target2host buffer as "No message here". */
+void _hl_delete (void);
+
+#endif /* !_HL_GW_H */
new file mode 100644
@@ -0,0 +1,64 @@
+/*
+ * hl_isatty.c -- provide _isatty().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* Check if fd is a tty on the host. Implements HL_SYSCALL_ISATTY. */
+static __always_inline int
+_hl_isatty (int fd)
+{
+ int32_t ret;
+ uint32_t host_errno;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_ISATTY, "i:ii",
+ (uint32_t) fd, /* i */
+ (uint32_t *) &ret, /* :i */
+ (uint32_t *) &host_errno /* :i */);
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ ret = 0;
+ }
+ /* isatty() returns 1 if fd is a terminal;
+ * otherwise it returns 0 and set errno.
+ */
+ else if (ret == 0)
+ {
+ errno = host_errno;
+ }
+ else
+ {
+ ret = 1;
+ }
+
+ _hl_delete ();
+
+ return ret;
+}
+
+int
+_isatty (int fd)
+{
+ return _hl_isatty (fd);
+}
new file mode 100644
@@ -0,0 +1,68 @@
+/*
+ * hl_lseek.c -- provide _lseek().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+
+/* Implements HL_SYSCALL_LSEEK. */
+static __always_inline off_t
+_hl_lseek (int fd, off_t offset, int whence)
+{
+ ssize_t ret;
+ int32_t n;
+ uint32_t host_errno;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_LSEEK, "iii:ii",
+ (uint32_t) fd, /* i */
+ (uint32_t) offset, /* i */
+ (int32_t) whence, /* i */
+ (uint32_t *) &n, /* :i */
+ (uint32_t *) &host_errno /* :i */);
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ ret = -1;
+ }
+ else if (n < 0)
+ {
+ errno = host_errno;
+ ret = -1;
+ }
+ else
+ {
+ ret = n;
+ }
+
+ _hl_delete ();
+
+ return ret;
+}
+
+off_t
+_lseek (int fd, off_t offset, int whence)
+{
+ return _hl_lseek (fd, offset, whence);
+}
new file mode 100644
@@ -0,0 +1,89 @@
+/*
+ * hl_open.c -- provide _open().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+/* Map newlib open flags into Hostlink IO ones. */
+static __always_inline uint32_t
+_hl_open_flags_map (int flags)
+{
+ uint32_t hl_flags = 0;
+
+ hl_flags |= (flags & O_RDONLY) ? 0x0000 : 0;
+ hl_flags |= (flags & O_WRONLY) ? 0x0001 : 0;
+ hl_flags |= (flags & O_RDWR) ? 0x0002 : 0;
+ hl_flags |= (flags & O_APPEND) ? 0x0008 : 0;
+ hl_flags |= (flags & O_CREAT) ? 0x0100 : 0;
+ hl_flags |= (flags & O_TRUNC) ? 0x0200 : 0;
+ hl_flags |= (flags & O_EXCL) ? 0x0400 : 0;
+
+ return hl_flags;
+}
+
+/* Open file on host. Implements HL_SYSCALL_OPEN. */
+static __always_inline int
+_hl_open (const char *path, int flags, mode_t mode)
+{
+ int32_t fd;
+ uint32_t host_errno;
+ uint32_t hl_flags = _hl_open_flags_map (flags);
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_OPEN, "sii:ii",
+ path, /* s */
+ (uint32_t) hl_flags, /* i */
+ (uint32_t) mode, /* i */
+ (uint32_t *) &fd, /* :i */
+ (uint32_t *) &host_errno /* :i */);
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ fd = -1;
+ }
+ else if (fd < 0)
+ {
+ errno = host_errno;
+ fd = -1;
+ }
+
+ _hl_delete ();
+
+ return fd;
+}
+
+int
+_open (const char *path, int flags, ...)
+{
+ va_list ap;
+ mode_t mode = 0;
+
+ va_start (ap, flags);
+
+ if (flags & O_CREAT)
+ mode = va_arg (ap, mode_t);
+
+ return _hl_open (path, flags, mode);
+}
new file mode 100644
@@ -0,0 +1,105 @@
+/*
+ * hl_read.c -- provide _read().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+
+/* Read one chunk. Implements HL_SYSCALL_READ. */
+static ssize_t
+_hl_read (int fd, void *buf, size_t count)
+{
+ ssize_t ret;
+ int32_t hl_n;
+ uint32_t host_errno;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_READ, "ii:i",
+ (uint32_t) fd, /* i */
+ (uint32_t) count, /* i */
+ (uint32_t *) &hl_n /* :i */);
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ ret = -1;
+ }
+ else if (hl_n < 0)
+ {
+ p = _hl_unpack_int (p, &host_errno);
+ errno = p == NULL ? EIO : host_errno;
+ ret = -1;
+ }
+ else
+ {
+ uint32_t n;
+
+ p = _hl_unpack_ptr (p, buf, &n);
+ ret = n;
+
+ if (p == NULL || n != (uint32_t) hl_n)
+ {
+ errno = EIO;
+ ret = -1;
+ }
+ }
+
+ _hl_delete ();
+
+ return ret;
+}
+
+ssize_t
+_read (int fd, void *buf, size_t count)
+{
+ const uint32_t hl_iochunk = _hl_iochunk_size ();
+ size_t to_read = count;
+ size_t offset = 0;
+ ssize_t ret = 0;
+
+ while (to_read > hl_iochunk)
+ {
+ ret = _hl_read (fd, (char *) buf + offset, hl_iochunk);
+
+ if (ret < 0)
+ return ret;
+
+ offset += ret;
+
+ if (ret != (ssize_t) hl_iochunk)
+ return offset;
+
+ to_read -= hl_iochunk;
+ }
+
+ if (to_read)
+ {
+ ret = _hl_read (fd, (char *) buf + offset, to_read);
+
+ if (ret < 0)
+ return ret;
+
+ ret += offset;
+ }
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,53 @@
+/*
+ * hl_toolchain.h -- provide toolchain-dependent defines.
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 _HL_TOOLCHAIN_H
+#define _HL_TOOLCHAIN_H
+
+#ifndef __uncached
+ #define __uncached __attribute__((uncached))
+#endif /* __uncached */
+
+#ifndef __aligned
+ #define __aligned(x) __attribute__((aligned (x)))
+#endif /* __aligned */
+
+#ifndef __noinline
+ #define __noinline __attribute__((noinline))
+#endif /* __noinline */
+
+#ifndef __always_inline
+ #define __always_inline inline __attribute__((always_inline))
+#endif /* __always_inline */
+
+#ifndef __packed
+ #define __packed __attribute__((packed))
+#endif /* __packed */
+
+#ifndef __noreturn
+ #define __noreturn __attribute__((noreturn))
+#endif /* __noreturn */
+
+#ifndef __longcall
+ #define __longcall __attribute__((long_call))
+#endif /* __longcall */
+
+#define HL_MAX_DCACHE_LINE 256
+
+#define ALIGN(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
+
+#endif /* !_HL_TOOLCHAIN_H */
new file mode 100644
@@ -0,0 +1,59 @@
+/*
+ * hl_unlink.c -- provide _unlink().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+
+/* Unlink host file. Implements HL_SYSCALL_UNLINK. */
+static __always_inline int
+_hl_unlink (const char *path)
+{
+ int32_t ret;
+ uint32_t host_errno;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_UNLINK, "s:ii",
+ path, /* s */
+ (uint32_t *) &ret, /* :i */
+ (uint32_t *) &host_errno /* :i */);
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ ret = -1;
+ }
+ else if (ret < 0)
+ {
+ errno = host_errno;
+ ret = -1;
+ }
+
+ _hl_delete ();
+
+ return ret;
+}
+
+int
+_unlink (const char *path)
+{
+ return _hl_unlink (path);
+}
new file mode 100644
@@ -0,0 +1,97 @@
+/*
+ * hl_write.c -- provide _write().
+ *
+ * Copyright (c) 2024 Synopsys Inc.
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include "hl_toolchain.h"
+#include "hl_api.h"
+
+
+/* Write one chunk to the host file. Implements HL_SYSCALL_WRITE. */
+static ssize_t
+_hl_write (int fd, const char *buf, size_t nbyte)
+{
+ ssize_t ret;
+ int32_t n;
+ uint32_t host_errno;
+ volatile __uncached char *p;
+
+ p = _hl_message (HL_SYSCALL_WRITE, "ipi:ii",
+ (uint32_t) fd, /* i */
+ buf, (uint32_t) nbyte, /* p */
+ (uint32_t) nbyte, /* i */
+ (uint32_t *) &n, /* :i */
+ (uint32_t *) &host_errno /* :i */);
+
+ if (p == NULL)
+ {
+ errno = ETIMEDOUT;
+ ret = -1;
+ }
+ else if (n < 0)
+ {
+ errno = host_errno;
+ ret = -1;
+ }
+ else
+ {
+ ret = n;
+ }
+
+ _hl_delete ();
+
+ return ret;
+}
+
+ssize_t
+_write (int fd, const char *buf, size_t nbyte)
+{
+ const uint32_t hl_iochunk = _hl_iochunk_size ();
+ size_t to_write = nbyte;
+ size_t offset = 0;
+ ssize_t ret = 0;
+
+ while (to_write > hl_iochunk)
+ {
+ ret = _hl_write (fd, buf + offset, hl_iochunk);
+
+ if (ret < 0)
+ return ret;
+
+ offset += ret;
+
+ if (ret != (ssize_t) hl_iochunk)
+ return offset;
+
+ to_write -= hl_iochunk;
+ }
+
+ if (to_write)
+ {
+ ret = _hl_write (fd, buf + offset, to_write);
+
+ if (ret < 0)
+ return ret;
+
+ ret += offset;
+ }
+
+ return ret;
+}
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2015, Synopsys, Inc. All rights reserved.
+ Copyright (c) 2015-2023, Synopsys, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -75,7 +75,7 @@ unsigned __attribute__((weak))
sleep (unsigned seconds)
{
clock_t t0 = _clock ();
- clock_t dt = seconds * CLOCKS_PER_SEC;
+ clock_t dt = (clock_t) seconds * CLOCKS_PER_SEC;
while (_clock () - t0 < dt);
return 0;
@@ -85,7 +85,7 @@ int __attribute__((weak))
usleep (useconds_t useconds)
{
clock_t t0 = _clock ();
- clock_t dt = useconds / (1000000/CLOCKS_PER_SEC);
+ clock_t dt = (clock_t) useconds / (1000000/CLOCKS_PER_SEC);
while (_clock () - t0 < dt);
return 0;
new file mode 100644
@@ -0,0 +1,90 @@
+Metaware hostlink IO
+====================
+
+This directory includes target-side implementation of Metaware hostlink
+interface see Contents section. Target program can use Metaware hostlink
+interface to send messages to nsim simulator or mdb debugger (it can be
+attached to HW or nsim).
+
+Quick start
+-----------
+To link with this version of libgloss please add `-specs=hl.specs` to baremetal
+version of ARC gcc (arc-elf32).
+
+Lets build and run simple program:
+
+ $ cat hello.c
+ #include <stdio.h>
+
+ int main()
+ {
+ printf("Hello World!\n");
+
+ return 0;
+ }
+ $ arc-elf32-gcc -mcpu=hs -specs=hl.specs ./hello.c -o hello
+ $ nsimdrv -prop=nsim_isa_family=av2hs -prop=nsim_hlink_gnu_io_ext=1 ./hello
+ Hello World!
+
+Where `-mcpu` and `-prop=nsim_isa_family` is specific to your version of ARC CPU.
+Option `-prop=nsim_hlink_gnu_io_ext=1` enables GNU IO extension for nSIM which
+is used for some system calls. The `nsimdrv` option `-prop=nsim_emt={0,1,2}`
+enables trap emulation and should be disabled (removed or set to `0`) to use
+Metaware hostlink.
+
+**NB:** Metaware hostlink requires symbols `__HOSTLINK__` and `_hl_blockedPeek`
+to be present. So stripped binary won't work properly with Metaware hostlink.
+
+Contents
+--------
+* `hl/hl_gw.*` -- Hostlink gateway. This API is used in the `hl_api.*`.
+ Please use `hl_message()` from `hl_api.*` for hostlink
+ message exchange.
+* `hl/hl_api.*` -- High-level API to send hostlink messages, as well as
+ functions to work with messages.
+* `hl/hl_<syscall>.*` -- Syscall implementations through hostlink API;
+* `arc-timer.*` -- Provides API to access ARC timers. Used by
+ `hl/hl_clock.c` in `_clock()` implementation.
+* `arc-main-helper.c` -- Provides `__setup_argv_and_call_main()`. The function
+ is called from `__start()` in `crt0.S`. It allows
+ to setup `argc` and `arvg` as well as some custom
+ things through `_setup_low_level()`.
+* `hl-setup.c` -- Provides `_setup_low_level()` for hostlink case.
+ It just configures default timer if it exists. Default
+ timer is used in the hostlink `clock()`
+ implementation.
+* `hl-stub.c` -- Provides functions which are part of newlib but
+ implemented without hostlink.
+ e.g. `_kill()` and `_getpid()`.
+* `sbrk.c` -- Provides `_sbrk()`. It uses `__start_heap` and
+ `__end_heap` variables.
+* `libcfunc.c` -- Additional C system calls.
+* `mcount.c` -- Profiler support.
+
+How it works
+------------
+Simulator looks for `__HOSTLINK__` and `_hl_blockedPeek()` symbols.
+`__HOSTLINK__` is the start of shared structure for message exchange and
+`_hl_blockedPeek()` is a function to be called when program is waiting
+for simulator response.
+
+When program wants to send a message it should follow:
+ 1. Fill `__HOSTLINK__.payload` with packed data.
+ Packing format is following: `{u16 type, u16 size, char data[]}`.
+ Supported types are `char`, `short`, `int`, `string` and `int64`.
+ `hl_api` provides high-level API to this.
+ 2. Fill `__HOSTLINK__.pkt_hdr`. See `hl_pkt_init()` from `hl_gw.c`.
+ 3. Fill `__HOSTLINK__.hdr`. See `hl_send()` from `hl_gw.c`.
+ 4. Call `_hl_blockedPeek()` to get response.
+ At this point message should be delivered to debugger.
+ Some implementations uses change of `__HOSTLINK__.hdr.target2host_addr` as
+ a signal that packet is sent and can be processed. Other implementations
+ wait for `_hl_blockedPeek()` to be called.
+
+ It means that portable implementation must fill
+ `__HOSTLINK__.hdr.target2host_addr` at the last step and then call
+ `_hl_blockedPeek()`.
+ 5. `_hl_blockedPeek()` returns pointer to debugger response which can be
+ processed on target if needed. Because debugger and target share the same
+ buffer the function actually returns `__HOSTLINK__.payload` that was
+ filled with packed data (see step 1) by the debugger.