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