newlib-cygwin/libgloss/xtensa/syscalls.c

206 lines
3.8 KiB
C

/*
* Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <unistd.h>
#include <syscalls.h>
#include <sys/stat.h>
#include <soc/uart.h>
#if defined (OPENOCD_SEMIHOSTING) || (QEMU_SEMIHOSTING)
# define WITH_SEMIHOSTING
# define __WEAK_FUNCTION_ATTR__
#else
# define __WEAK_FUNCTION_ATTR__ __attribute__((__weak__))
#endif
/* __semihosting_call is a function in case semihosting usage, macro (-1) otherwise */
#ifdef WITH_SEMIHOSTING
static inline int
__attribute__ ((always_inline))
__semihosting_call(int id, int arg1, int arg2, int arg3, int arg4)
{
# ifdef OPENOCD_SEMIHOSTING
register long a2 asm("a2") = id;
long args[] = {arg1, arg2, arg3, arg4};
register long a3 asm("a3") = (long)&args;
/* OpenOCD has different semihosting api for sys_exit on 32-bit and 64-bit */
if (id == SYS_exit && sizeof(void *) != 8) {
a3 = ADP_STOPPED_APPLICATION_EXIT;
}
__asm__ __volatile__ (
"break 1, 14\n"
: "+r"(a2): "r"(a3)
: "memory");
// return code is placed in a2 register, so return it to the caller
return a2;
# else // OPENOCD_SEMIHOSTING
extern int __sim_call(int id, int arg1, int arg2, int arg3, int arg4);
return __sim_call(id, arg1, arg2, arg3, arg4);
# endif // OPENOCD_SEMIHOSTING
}
# ifdef OPENOCD_SEMIHOSTING
int
__semihosting_init (void)
{
struct {
int version;
} ver_info = { 2 };
__semihosting_call(ESP_SEMIHOSTING_SYS_DRV_INFO, (long) &ver_info, sizeof(ver_info), 0, 0);
}
# endif // OPENOCD_SEMIHOSTING
#else // !WITH_SEMIHOSTING
# define __semihosting_call(...) (-1)
#endif // WITH_SEMIHOSTING
void
__WEAK_FUNCTION_ATTR__
__attribute__ ((noreturn))
_exit (int status)
{
__semihosting_call(SYS_exit, status, 0, 0, 0);
for (;;) {
;
}
}
int
__WEAK_FUNCTION_ATTR__
_open (const char *file, int flags, int mode)
{
return __semihosting_call(SYS_open, (int) file, flags, mode, 0);
}
int
__WEAK_FUNCTION_ATTR__
_lseek (int fd, _off_t off, int whence)
{
return __semihosting_call(SYS_lseek, fd, off, whence, 0);
}
int
__WEAK_FUNCTION_ATTR__
_close (int fd)
{
return __semihosting_call(SYS_close, fd, 0, 0, 0);
}
_ssize_t
__WEAK_FUNCTION_ATTR__
_write (int fd, const char *buf, size_t cnt)
{
int ret = 0;
#ifdef WITH_SEMIHOSTING
ret = __semihosting_call(SYS_write, fd, (int) buf, cnt, 0);
# ifdef OPENOCD_SEMIHOSTING
/* ret - number of bytes that are NOT written. Calculate written */
ret = cnt - ret;
# endif // OPENOCD_SEMIHOSTING
#else // !WITH_SEMIHOSTING
if (fd != STDOUT_FILENO && fd != STDERR_FILENO) {
return -1;
}
for (uint32_t i = 0; i < cnt; i++) {
board_uart_write_char(buf[i]);
}
ret = cnt;
#endif // WITH_SEMIHOSTING
return ret;
}
/* Do not compile functions with common implementation
* if building semihosting library
*/
#ifndef WITH_SEMIHOSTING
struct _reent*
__WEAK_FUNCTION_ATTR__
__getreent(void)
{
return _GLOBAL_REENT;
}
int
__WEAK_FUNCTION_ATTR__
_fstat (int fd, struct stat *pstat)
{
if (fd < STDERR_FILENO)
{
pstat->st_mode = S_IFCHR;
return 0;
}
return -1;
}
_ssize_t
__WEAK_FUNCTION_ATTR__
_read (int fd, char *buf, size_t cnt)
{
return -1;
}
int
__WEAK_FUNCTION_ATTR__
_getpid (void)
{
return -1;
}
int
__WEAK_FUNCTION_ATTR__
_kill (int sig)
{
return -1;
}
void *
__WEAK_FUNCTION_ATTR__
_sbrk (int incr)
{
extern char end; /* Set by linker. */
static char * heap_end;
char * prev_heap_end;
if (heap_end == 0) {
heap_end = & end;
}
prev_heap_end = heap_end;
heap_end += incr;
return (void *) prev_heap_end;
}
int
__WEAK_FUNCTION_ATTR__
pthread_setcancelstate (int state, int *oldstate)
{
return 0;
}
#endif // WITH_SEMIHOSTING