* 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.
		
			
				
	
	
		
			342 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			342 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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
 | 
						|
}
 |