arc: libgloss: Introduce hostlink interface

There is a special interface built in ARC simulators (such as
nSIM) called MetaWare hostlink IO which can be used to implement
system calls. This commit adds support for this interface to the
ARC port of libgloss.

Here is an example of using this interface:

    $ arc-elf32-gcc -mcpu=hs -specs=hl.specs main.c -o main
    $ nsimdrv -tcf $NSIM_HOME/etc/tcf/templates/hs48_full.tcf main
    Hello, World!

Signed-off-by: Vladimir Isaev <vvisaev@gmail.com>
This commit is contained in:
Vladimir Isaev 2024-05-21 10:56:49 +01:00 committed by Jeff Johnston
parent 25d110dcbd
commit 6d5331054e
27 changed files with 2111 additions and 11 deletions

View File

@ -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);
}

129
libgloss/arc/arc-timer.c Normal file
View File

@ -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);
}

25
libgloss/arc/arc-timer.h Normal file
View File

@ -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 */

View File

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

27
libgloss/arc/hl-setup.c Normal file
View File

@ -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;
}

81
libgloss/arc/hl-stub.c Normal file
View File

@ -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;
}

14
libgloss/arc/hl.specs Normal file
View File

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

350
libgloss/arc/hl/hl_api.c Normal file
View File

@ -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;
}

77
libgloss/arc/hl/hl_api.h Normal file
View File

@ -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 */

45
libgloss/arc/hl/hl_argc.c Normal file
View File

@ -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 ();
}

67
libgloss/arc/hl/hl_argv.c Normal file
View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

42
libgloss/arc/hl/hl_exit.c Normal file
View File

@ -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 ();
}

View File

@ -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);
}

View File

@ -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;
}

180
libgloss/arc/hl/hl_gw.c Normal file
View File

@ -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;
}

46
libgloss/arc/hl/hl_gw.h Normal file
View File

@ -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 */

View File

@ -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);
}

View File

@ -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);
}

89
libgloss/arc/hl/hl_open.c Normal file
View File

@ -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);
}

105
libgloss/arc/hl/hl_read.c Normal file
View File

@ -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;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}

View File

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

View File

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