]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/rx/syscalls.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / rx / syscalls.c
CommitLineData
4f8d4a38
DD
1/* syscalls.c --- implement system calls for the RX simulator.
2
8acc9f48 3Copyright (C) 2005-2013 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
29#include "gdb/callback.h"
30
31#include "cpu.h"
32#include "mem.h"
33#include "syscalls.h"
34
35#include "syscall.h"
36
37/* The current syscall callbacks we're using. */
38static struct host_callback_struct *callbacks;
39
40void
41set_callbacks (struct host_callback_struct *cb)
42{
43 callbacks = cb;
44}
45
d98bfeb0
KB
46struct host_callback_struct *
47get_callbacks (void)
48{
49 return callbacks;
50}
51
4f8d4a38
DD
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
69int argp, stackp;
70
71static int
72arg ()
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
85static void
86read_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
99static void
100write_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
115static 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
140int
141rx_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 <= SYS_link ? callnames[id] : "unknown");
150 switch (id)
151 {
152 case 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 SYS_open:
162 {
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;
170 int oflags = arg ();
171 int cflags = arg ();
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
202 case SYS_close:
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
218 case SYS_read:
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
238 case SYS_write:
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
261 case SYS_getpid:
262 put_reg (1, 42);
263 break;
264
265 case SYS_gettimeofday:
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
280 case SYS_kill:
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}