Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/tic6x/syscalls.c')
-rw-r--r--libgloss/tic6x/syscalls.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/libgloss/tic6x/syscalls.c b/libgloss/tic6x/syscalls.c
new file mode 100644
index 000000000..dc0633ba6
--- /dev/null
+++ b/libgloss/tic6x/syscalls.c
@@ -0,0 +1,361 @@
+/* Copyright (c) 2010 CodeSourcery, 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:
+ * 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 CodeSourcery 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 CODESOURCERY, INC. ``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 CODESOURCERY 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 <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#define _DTOPEN 0xf0
+#define _DTCLOSE 0xf1
+#define _DTREAD 0xf2
+#define _DTWRITE 0xf3
+#define _DTLSEEK 0xf4
+#define _DTUNLINK 0xf5
+#define _DTGETENV 0xf6
+#define _DTRENAME 0xf7
+#define _DTGETTIME 0xf8
+#define _DTGETCLK 0xf9
+#define _DTSYNC 0xff
+
+#define CIOBUFSIZ (BUFSIZ + 32)
+
+struct __attribute__((packed)) cio_open_to_host
+{
+ /* Suggested file descriptor (little endian). */
+ short fd;
+ /* Flags (little endian). */
+ short flags;
+};
+
+struct __attribute__((packed)) cio_open_from_host
+{
+ /* File descriptor (little endian). */
+ short fd;
+};
+
+struct __attribute__((packed)) cio_close_to_host
+{
+ /* File descriptor (little endian). */
+ short fd;
+};
+
+struct __attribute__((packed)) cio_close_from_host
+{
+ /* Result (little endian). */
+ short result;
+};
+
+struct __attribute__((packed)) cio_read_to_host
+{
+ /* File descriptor (little endian). */
+ short fd;
+ /* Length (little endian). */
+ short length;
+};
+
+struct __attribute__((packed)) cio_read_from_host
+{
+ /* Result (little endian). */
+ short result;
+};
+
+struct __attribute__((packed)) cio_write_to_host
+{
+ /* File descriptor (little endian). */
+ short fd;
+ /* Length (little endian). */
+ short length;
+};
+
+struct __attribute__((packed)) cio_write_from_host
+{
+ /* Result (little endian). */
+ short result;
+};
+
+struct __attribute__((packed)) cio_lseek_to_host
+{
+ /* File descriptor (little endian). */
+ short fd;
+ /* Offset (little endian). */
+ int offset;
+ /* Whence (little endian). */
+ short whence;
+};
+
+struct __attribute__((packed)) cio_lseek_from_host
+{
+ /* Result (little endian). */
+ int result;
+};
+
+struct __attribute__((packed)) cio_unlink_to_host
+{
+ /* Empty. */
+};
+
+struct __attribute__((packed)) cio_unlink_from_host
+{
+ /* Result (little endian). */
+ short result;
+};
+
+struct __attribute__((packed)) cio_rename_to_host
+{
+ /* Empty. */
+};
+
+struct __attribute__((packed)) cio_rename_from_host
+{
+ /* Result (little endian). */
+ short result;
+};
+
+struct __attribute__((packed)) cio_gettime_to_host
+{
+ /* Empty. */
+};
+
+struct __attribute__((packed)) cio_gettime_from_host
+{
+ /* Time (little endian). */
+ int time;
+};
+
+struct __attribute__((packed)) cio_to_host
+{
+ /* Data length (target endian). */
+ unsigned int length;
+ /* Command. */
+ unsigned char command;
+ /* Parameters. */
+ union
+ {
+ unsigned char buf[8];
+ struct cio_open_to_host open;
+ struct cio_close_to_host close;
+ struct cio_read_to_host read;
+ struct cio_write_to_host write;
+ struct cio_lseek_to_host lseek;
+ struct cio_unlink_to_host unlink;
+ struct cio_rename_to_host rename;
+ struct cio_gettime_to_host gettime;
+ } parms;
+ /* Variable-length data. */
+ unsigned char data[];
+};
+
+struct __attribute__((packed)) cio_from_host
+{
+ /* Length (target endian). */
+ unsigned int length;
+ /* Parameters. */
+ union
+ {
+ unsigned char buf[8];
+ struct cio_open_from_host open;
+ struct cio_close_from_host close;
+ struct cio_read_from_host read;
+ struct cio_write_from_host write;
+ struct cio_lseek_from_host lseek;
+ struct cio_unlink_from_host unlink;
+ struct cio_rename_from_host rename;
+ struct cio_gettime_from_host gettime;
+ } parms;
+ /* Data. */
+ unsigned char data[];
+};
+
+union
+{
+ unsigned char buf[CIOBUFSIZ];
+ int align;
+ union
+ {
+ struct cio_to_host to_host;
+ struct cio_from_host from_host;
+ } u;
+} _CIOBUF_ __attribute__((section(".cio")));
+
+#ifdef _BIG_ENDIAN
+#define SWAPSHORT(s) ((short)((((s) & 0xff) << 8) | (((s) & 0xff00) >> 8)))
+#define SWAPINT(i) (__builtin_bswap32 (i))
+#else
+#define SWAPSHORT(s) (s)
+#define SWAPINT(i) (i)
+#endif
+
+static void __attribute__((noinline))
+do_semi_call (void)
+{
+ asm volatile (".globl C$$IO$$\nnop\nC$$IO$$:nop" : "+m" (_CIOBUF_));
+}
+
+static inline void
+semi_call_wrapper (unsigned char command, const char *data,
+ unsigned int length)
+{
+ _CIOBUF_.u.to_host.length = length;
+ _CIOBUF_.u.to_host.command = command;
+ if (data != NULL)
+ memcpy (_CIOBUF_.u.to_host.data, data, length);
+ do_semi_call ();
+}
+
+static inline void
+semi_call_wrapper2 (unsigned char command, const char *data1,
+ unsigned int length1, const char *data2,
+ unsigned int length2)
+{
+ _CIOBUF_.u.to_host.length = length1 + length2;
+ _CIOBUF_.u.to_host.command = command;
+ if (data1 != NULL)
+ memcpy (_CIOBUF_.u.to_host.data, data1, length1);
+ if (data2 != NULL)
+ memcpy (_CIOBUF_.u.to_host.data + length1, data2, length2);
+ do_semi_call ();
+}
+
+void
+_exit (int status)
+{
+ /* The semihosting interface appears to provide no way to return an
+ exit status. */
+ asm volatile (".globl C$$EXIT\nnop\nC$$EXIT:nop");
+}
+
+int
+open (const char *path, int flags, ...)
+{
+ /* ??? It's not clear what the suggested fd is for. */
+ static short suggest_fd = 3;
+ short ret_fd;
+ ++suggest_fd;
+ _CIOBUF_.u.to_host.parms.open.fd = SWAPSHORT (suggest_fd);
+ _CIOBUF_.u.to_host.parms.open.flags = SWAPSHORT (flags);
+ semi_call_wrapper (_DTOPEN, path, strlen (path) + 1);
+ ret_fd = SWAPSHORT (_CIOBUF_.u.from_host.parms.open.fd);
+ if (ret_fd == -1)
+ return -1;
+ return suggest_fd;
+}
+
+int
+close (int fd)
+{
+ _CIOBUF_.u.to_host.parms.close.fd = SWAPSHORT (fd);
+ semi_call_wrapper (_DTCLOSE, NULL, 0);
+ return SWAPSHORT (_CIOBUF_.u.from_host.parms.close.result);
+}
+
+int
+read (int fd, char *ptr, int len)
+{
+ if (len > BUFSIZ)
+ len = BUFSIZ;
+ _CIOBUF_.u.to_host.parms.read.fd = SWAPSHORT (fd);
+ _CIOBUF_.u.to_host.parms.read.length = SWAPSHORT (len);
+ semi_call_wrapper (_DTREAD, NULL, 0);
+ memcpy (ptr, _CIOBUF_.u.from_host.data, _CIOBUF_.u.from_host.length);
+ return SWAPSHORT (_CIOBUF_.u.from_host.parms.read.result);
+}
+
+int
+write (int fd, char *ptr, int len)
+{
+ if (len > BUFSIZ)
+ len = BUFSIZ;
+ _CIOBUF_.u.to_host.parms.write.fd = SWAPSHORT (fd);
+ _CIOBUF_.u.to_host.parms.write.length = SWAPSHORT (len);
+ semi_call_wrapper (_DTWRITE, ptr, len);
+ return SWAPSHORT (_CIOBUF_.u.from_host.parms.write.result);
+}
+
+int
+lseek (int fd, int offset, int whence)
+{
+ _CIOBUF_.u.to_host.parms.lseek.fd = SWAPSHORT (fd);
+ _CIOBUF_.u.to_host.parms.lseek.offset = SWAPINT (offset);
+ _CIOBUF_.u.to_host.parms.lseek.whence = SWAPSHORT (whence);
+ semi_call_wrapper (_DTLSEEK, NULL, 0);
+ return SWAPINT (_CIOBUF_.u.from_host.parms.lseek.result);
+}
+
+int
+unlink (const char *path)
+{
+ semi_call_wrapper (_DTUNLINK, path, strlen (path) + 1);
+ return SWAPSHORT (_CIOBUF_.u.from_host.parms.unlink.result);
+}
+
+int
+rename (const char *oldpath, const char *newpath)
+{
+ semi_call_wrapper2 (_DTRENAME, oldpath, strlen (oldpath) + 1,
+ newpath, strlen (newpath) + 1);
+ return SWAPSHORT (_CIOBUF_.u.from_host.parms.rename.result);
+}
+
+int
+gettimeofday (struct timeval *tp, void *tzvp)
+{
+ struct timezone *tzp = tzvp;
+
+ if (tp)
+ {
+ semi_call_wrapper (_DTGETTIME, NULL, 0);
+ tp->tv_sec = SWAPINT (_CIOBUF_.u.from_host.parms.gettime.time);
+ tp->tv_usec = 0;
+ }
+
+ if (tzp)
+ {
+ tzp->tz_minuteswest = 0;
+ tzp->tz_dsttime = 0;
+ }
+
+ return 0;
+}
+
+int
+isatty (int file __attribute__((unused)))
+{
+ errno = ENOSYS;
+ return 0;
+}
+
+int
+fstat (int fd, struct stat *buf)
+{
+ buf->st_mode = S_IFCHR; /* Always pretend to be a tty */
+ buf->st_blksize = 0;
+
+ return (0);
+}