* COPYING.LIBGLOSS: Add Controls and Data Services copyright.
* COPYING.NEWLIB: Likewise. libgloss/ * configure.in: Add Visium support. * configure: Regenerate. * visium/: New directory. newlib/ * configure.host: Add Visium support. * libc/machine/configure.in: Likewise. * libc/machine/configure: Regenerate. * libc/machine/visium/: New directory. * libc/include/machine/setjmp.h (_JBLEN): Define for Visium. * libc/include/machine/ieeefp.h (__IEEE_BIG_ENDIAN): Likewise. * libc/include/machine/time.h (_CLOCKS_PER_SEC_): Likewise.
This commit is contained in:
341
libgloss/visium/syscalls.c
Normal file
341
libgloss/visium/syscalls.c
Normal file
@@ -0,0 +1,341 @@
|
||||
/* system calls for the Visium processor.
|
||||
|
||||
Copyright (c) 2015 Rolls-Royce Controls and Data Services Limited.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Rolls-Royce Controls and Data Services Limited nor
|
||||
the names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "io.h"
|
||||
#include "syscall.h"
|
||||
|
||||
#ifdef TARGET_SIM
|
||||
struct file_register2
|
||||
{
|
||||
unsigned action;
|
||||
unsigned p1, p2, p3, p4;
|
||||
unsigned error;
|
||||
unsigned retval;
|
||||
};
|
||||
|
||||
extern struct file_register2 _sim_fileio_register;
|
||||
|
||||
static volatile struct file_register2 *const fileio = &_sim_fileio_register;
|
||||
|
||||
static int
|
||||
do_syscall (unsigned action, unsigned p1, unsigned p2,
|
||||
unsigned p3, unsigned p4, int *error)
|
||||
{
|
||||
fileio->p1 = p1;
|
||||
fileio->p2 = p2;
|
||||
fileio->p3 = p3;
|
||||
fileio->p4 = p4;
|
||||
fileio->action = action;
|
||||
|
||||
*error = (int) fileio->error;
|
||||
return (int) fileio->retval;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
do_syscall (unsigned action, unsigned p1, unsigned p2,
|
||||
unsigned p3, unsigned p4, int *error)
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
/* There is a two instruction delay after the software interrupt is
|
||||
initiated, to allow it to take effect. */
|
||||
|
||||
asm volatile ("\n\
|
||||
move.l r1,%3\n\
|
||||
move.l r2,%4\n\
|
||||
move.l r3,%5\n\
|
||||
moviu r5,%%u 0x20002208\n\
|
||||
movil r5,%%l 0x20002208\n\
|
||||
move.l r4,%6\n\
|
||||
write.l (r5),%2\n\
|
||||
nop\n\
|
||||
nop\n\
|
||||
move.l %0,r1\n\
|
||||
move.l %1,r2"
|
||||
: "=r" (ret), "=r" (err)
|
||||
: "r" (action), "r" (p1), "r" (p2), "r" (p3), "r" (p4)
|
||||
: "r1", "r2", "r3", "r4", "r5");
|
||||
|
||||
*error = err;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
close (int fildes)
|
||||
{
|
||||
int status;
|
||||
int error;
|
||||
|
||||
status = do_syscall (SYS_close, fildes, 0, 0, 0, &error);
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void _exit (int) __attribute ((__noreturn__));
|
||||
|
||||
void
|
||||
_exit (int code)
|
||||
{
|
||||
#ifdef TARGET_SIM
|
||||
asm volatile ("stop 0,%0" : : "r" (code & 0xff));
|
||||
#else
|
||||
int error;
|
||||
do_syscall (SYS_exit, code, 0, 0, 0, &error);
|
||||
#endif
|
||||
|
||||
/* Should never reach this point. Since this function is not supposed to
|
||||
return, pretend to get stuck in a loop. */
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef TARGET_SIM
|
||||
extern long long _sim_cmdline_header;
|
||||
|
||||
long long
|
||||
_get_cmdline (void)
|
||||
{
|
||||
return _sim_cmdline_header;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
fstat (int fildes, struct stat *st)
|
||||
{
|
||||
struct gdb_stat gst;
|
||||
int status;
|
||||
int error;
|
||||
|
||||
status = do_syscall (SYS_fstat, fildes, (unsigned) &gst, 0, 0, &error);
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
else
|
||||
__hosted_from_gdb_stat (&gst, st);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
gettimeofday (struct timeval *__p, void *__tz)
|
||||
{
|
||||
struct timeval *tv = __p;
|
||||
struct timezone *tz = __tz;
|
||||
struct gdb_timeval gtv;
|
||||
int status;
|
||||
int error;
|
||||
|
||||
status = do_syscall (SYS_gettimeofday, (unsigned) >v, 0, 0, 0, &error);
|
||||
|
||||
/* The timezone argument is not really supported so:
|
||||
Local time is GMT, no daylight saving */
|
||||
if (tz)
|
||||
{
|
||||
tz->tz_minuteswest = 0;
|
||||
tz->tz_dsttime = 0;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
else
|
||||
__hosted_from_gdb_timeval (>v, tv);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
isatty (int fildes)
|
||||
{
|
||||
int status;
|
||||
int error;
|
||||
|
||||
status = do_syscall (SYS_isatty, fildes, 0, 0, 0, &error);
|
||||
|
||||
if (status == 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
off_t
|
||||
lseek (int fildes, off_t offset, int whence)
|
||||
{
|
||||
off_t ret;
|
||||
int error;
|
||||
|
||||
ret = do_syscall (SYS_lseek, fildes, offset,
|
||||
__hosted_to_gdb_lseek_flags (whence), 0, &error);
|
||||
|
||||
if (ret == (off_t)-1)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
open (const char *path, int oflag, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
int status;
|
||||
int error;
|
||||
int len = strlen (path) + 1;
|
||||
|
||||
if (oflag & O_CREAT)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, oflag);
|
||||
mode = va_arg (ap, mode_t);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
status = do_syscall (SYS_open, (unsigned) path, len,
|
||||
__hosted_to_gdb_open_flags (oflag),
|
||||
__hosted_to_gdb_mode_t (mode), &error);
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
read (int fildes, void *buf, size_t nbyte)
|
||||
{
|
||||
int status;
|
||||
int error;
|
||||
|
||||
status = do_syscall (SYS_read, fildes, (unsigned) buf, nbyte, 0, &error);
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
rename (const char *old, const char *new)
|
||||
{
|
||||
int status;
|
||||
int error;
|
||||
int oldlen = strlen (old) + 1;
|
||||
int newlen = strlen (new) + 1;
|
||||
|
||||
status = do_syscall (SYS_rename, (unsigned) old, oldlen, (unsigned) new,
|
||||
newlen, &error);
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
stat (const char *path, struct stat *st)
|
||||
{
|
||||
struct gdb_stat gst;
|
||||
int status;
|
||||
int error;
|
||||
int len = strlen (path) + 1;
|
||||
|
||||
status = do_syscall (SYS_stat, (unsigned) path, len, (unsigned) &gst, 0,
|
||||
&error);
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
else
|
||||
__hosted_from_gdb_stat (&gst, st);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
system (const char *string)
|
||||
{
|
||||
int status;
|
||||
int error;
|
||||
int len = strlen (string) + 1;
|
||||
|
||||
status = do_syscall (SYS_system, (unsigned) string, len, 0, 0, &error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
unlink (const char *path)
|
||||
{
|
||||
int status;
|
||||
int error;
|
||||
int len = strlen (path) + 1;
|
||||
|
||||
status = do_syscall (SYS_unlink, (unsigned) path, len, 0, 0, &error);
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
write (int fildes, const void *buf, size_t nbyte)
|
||||
{
|
||||
int status;
|
||||
int error;
|
||||
|
||||
status = do_syscall (SYS_write, fildes, (unsigned) buf, nbyte, 0, &error);
|
||||
|
||||
if (status < 0)
|
||||
errno = __hosted_from_gdb_errno (error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
extern clock_t _sim_clock;
|
||||
|
||||
clock_t
|
||||
clock (void)
|
||||
{
|
||||
#ifdef TARGET_SIM
|
||||
return _sim_clock;
|
||||
#else
|
||||
return (clock_t) -1;
|
||||
#endif
|
||||
}
|
Reference in New Issue
Block a user