]> Git Repo - binutils.git/blob - sim/rx/syscalls.c
Automatic date update in version.in
[binutils.git] / sim / rx / syscalls.c
1 /* syscalls.c --- implement system calls for the RX simulator.
2
3 Copyright (C) 2005-2022 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
5
6 This file is part of the GNU simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 /* This must come before any other includes.  */
22 #include "defs.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <sys/time.h>
29
30 #include "sim/callback.h"
31
32 #include "cpu.h"
33 #include "mem.h"
34 #include "syscalls.h"
35 #include "target-newlib-syscall.h"
36
37 /* The current syscall callbacks we're using.  */
38 static struct host_callback_struct *callbacks;
39
40 void
41 set_callbacks (struct host_callback_struct *cb)
42 {
43   callbacks = cb;
44 }
45
46 struct host_callback_struct *
47 get_callbacks (void)
48 {
49   return callbacks;
50 }
51
52
53 /* Arguments 1..4 are in R1..R4, remainder on stack.
54
55    Return value in R1..R4 as needed.
56      structs bigger than 16 bytes: pointer pushed on stack last
57
58    We only support arguments that fit in general registers.
59
60    The system call number is in R5.  We expect ssycalls to look like
61    this in libgloss:
62
63    _exit:
64         mov     #SYS_exit, r5
65         int     #255
66         rts
67 */
68
69 int argp, stackp;
70
71 static int
72 arg (void)
73 {
74   int rv = 0;
75   argp++;
76
77   if (argp < 4)
78     return get_reg (argp);
79
80   rv = mem_get_si (get_reg (sp) + stackp);
81   stackp += 4;
82   return rv;
83 }
84
85 static void
86 read_target (char *buffer, int address, int count, int asciiz)
87 {
88   char byte;
89   while (count > 0)
90     {
91       byte = mem_get_qi (address++);
92       *buffer++ = byte;
93       if (asciiz && (byte == 0))
94         return;
95       count--;
96     }
97 }
98
99 static void
100 write_target (char *buffer, int address, int count, int asciiz)
101 {
102   char byte;
103   while (count > 0)
104     {
105       byte = *buffer++;
106       mem_put_qi (address++, byte);
107       if (asciiz && (byte == 0))
108         return;
109       count--;
110     }
111 }
112
113 #define PTRSZ (A16 ? 2 : 3)
114
115 static char *callnames[] = {
116   "SYS_zero",
117   "SYS_exit",
118   "SYS_open",
119   "SYS_close",
120   "SYS_read",
121   "SYS_write",
122   "SYS_lseek",
123   "SYS_unlink",
124   "SYS_getpid",
125   "SYS_kill",
126   "SYS_fstat",
127   "SYS_sbrk",
128   "SYS_argvlen",
129   "SYS_argv",
130   "SYS_chdir",
131   "SYS_stat",
132   "SYS_chmod",
133   "SYS_utime",
134   "SYS_time",
135   "SYS_gettimeofday",
136   "SYS_times",
137   "SYS_link"
138 };
139
140 int
141 rx_syscall (int id)
142 {
143   static char buf[256];
144   int rv;
145
146   argp = 0;
147   stackp = 4;
148   if (trace)
149     printf ("\033[31m/* SYSCALL(%d) = %s */\033[0m\n", id, id <= TARGET_NEWLIB_SYS_link ? callnames[id] : "unknown");
150   switch (id)
151     {
152     case TARGET_NEWLIB_SYS_exit:
153       {
154         int ec = arg ();
155         if (verbose)
156           printf ("[exit %d]\n", ec);
157         return RX_MAKE_EXITED (ec);
158       }
159       break;
160
161     case TARGET_NEWLIB_SYS_open:
162       {
163         int oflags, cflags;
164         int path = arg ();
165         /* The open function is defined as taking a variable number of arguments
166            because the third parameter to it is optional:
167              open (const char * filename, int flags, ...);
168            Hence the oflags and cflags arguments will be on the stack and we need
169            to skip the (empty) argument registers r3 and r4.  */
170         argp = 4;
171         oflags = arg ();
172         cflags = arg ();
173
174         read_target (buf, path, 256, 1);
175         if (trace)
176           printf ("open(\"%s\",0x%x,%#o) = ", buf, oflags, cflags);
177
178         if (callbacks)
179           /* The callback vector ignores CFLAGS.  */
180           rv = callbacks->open (callbacks, buf, oflags);
181         else
182           {
183             int h_oflags = 0;
184
185             if (oflags & 0x0001)
186               h_oflags |= O_WRONLY;
187             if (oflags & 0x0002)
188               h_oflags |= O_RDWR;
189             if (oflags & 0x0200)
190               h_oflags |= O_CREAT;
191             if (oflags & 0x0008)
192               h_oflags |= O_APPEND;
193             if (oflags & 0x0400)
194               h_oflags |= O_TRUNC;
195             rv = open (buf, h_oflags, cflags);
196           }
197         if (trace)
198           printf ("%d\n", rv);
199         put_reg (1, rv);
200       }
201       break;
202
203     case TARGET_NEWLIB_SYS_close:
204       {
205         int fd = arg ();
206
207         if (callbacks)
208           rv = callbacks->close (callbacks, fd);
209         else if (fd > 2)
210           rv = close (fd);
211         else
212           rv = 0;
213         if (trace)
214           printf ("close(%d) = %d\n", fd, rv);
215         put_reg (1, rv);
216       }
217       break;
218
219     case TARGET_NEWLIB_SYS_read:
220       {
221         int fd = arg ();
222         int addr = arg ();
223         int count = arg ();
224
225         if (count > sizeof (buf))
226           count = sizeof (buf);
227         if (callbacks)
228           rv = callbacks->read (callbacks, fd, buf, count);
229         else
230           rv = read (fd, buf, count);
231         if (trace)
232           printf ("read(%d,%d) = %d\n", fd, count, rv);
233         if (rv > 0)
234           write_target (buf, addr, rv, 0);
235         put_reg (1, rv);
236       }
237       break;
238
239     case TARGET_NEWLIB_SYS_write:
240       {
241         int fd = arg ();
242         int addr = arg ();
243         int count = arg ();
244
245         if (count > sizeof (buf))
246           count = sizeof (buf);
247         if (trace)
248           printf ("write(%d,0x%x,%d)\n", fd, addr, count);
249         read_target (buf, addr, count, 0);
250         if (trace)
251           fflush (stdout);
252         if (callbacks)
253           rv = callbacks->write (callbacks, fd, buf, count);
254         else
255           rv = write (fd, buf, count);
256         if (trace)
257           printf ("write(%d,%d) = %d\n", fd, count, rv);
258         put_reg (1, rv);
259       }
260       break;
261
262     case TARGET_NEWLIB_SYS_getpid:
263       put_reg (1, 42);
264       break;
265
266     case TARGET_NEWLIB_SYS_gettimeofday:
267       {
268         int tvaddr = arg ();
269         struct timeval tv;
270
271         rv = gettimeofday (&tv, 0);
272         if (trace)
273           printf ("gettimeofday: %" PRId64 " sec %" PRId64 " usec to 0x%x\n",
274                   (int64_t)tv.tv_sec, (int64_t)tv.tv_usec, tvaddr);
275         mem_put_si (tvaddr, tv.tv_sec);
276         mem_put_si (tvaddr + 4, tv.tv_usec);
277         put_reg (1, rv);
278       }
279       break;
280
281     case TARGET_NEWLIB_SYS_kill:
282       {
283         int pid = arg ();
284         int sig = arg ();
285         if (pid == 42)
286           {
287             if (verbose)
288               printf ("[signal %d]\n", sig);
289             return RX_MAKE_STOPPED (sig);
290           }
291       }
292       break;
293
294     case 11:
295       {
296         int heaptop_arg = arg ();
297         if (trace)
298           printf ("sbrk: heap top set to %x\n", heaptop_arg);
299         heaptop = heaptop_arg;
300         if (heapbottom == 0)
301           heapbottom = heaptop_arg;
302       }
303       break;
304
305     case 255:
306       {
307         int addr = arg ();
308         mem_put_si (addr, rx_cycles + mem_usage_cycles());
309       }
310       break;
311
312     }
313   return RX_MAKE_STEPPED ();
314 }
This page took 0.040935 seconds and 4 git commands to generate.