tweak previous entry to keep chronology right
[deliverable/binutils-gdb.git] / sim / rx / syscalls.c
CommitLineData
4f8d4a38
DD
1/* syscalls.c --- implement system calls for the RX simulator.
2
dc3cf14f 3Copyright (C) 2005, 2007, 2008, 2009, 2010 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
22#include <stdio.h>
23#include <stdlib.h>
24#include <fcntl.h>
25#include <unistd.h>
26#include <sys/time.h>
27
28#include "gdb/callback.h"
29
30#include "cpu.h"
31#include "mem.h"
32#include "syscalls.h"
33
34#include "syscall.h"
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
45
46/* Arguments 1..4 are in R1..R4, remainder on stack.
47
48 Return value in R1..R4 as needed.
49 structs bigger than 16 bytes: pointer pushed on stack last
50
51 We only support arguments that fit in general registers.
52
53 The system call number is in R5. We expect ssycalls to look like
54 this in libgloss:
55
56 _exit:
57 mov #SYS_exit, r5
58 int #255
59 rts
60*/
61
62int argp, stackp;
63
64static int
65arg ()
66{
67 int rv = 0;
68 argp++;
69
70 if (argp < 4)
71 return get_reg (argp);
72
73 rv = mem_get_si (get_reg (sp) + stackp);
74 stackp += 4;
75 return rv;
76}
77
78static void
79read_target (char *buffer, int address, int count, int asciiz)
80{
81 char byte;
82 while (count > 0)
83 {
84 byte = mem_get_qi (address++);
85 *buffer++ = byte;
86 if (asciiz && (byte == 0))
87 return;
88 count--;
89 }
90}
91
92static void
93write_target (char *buffer, int address, int count, int asciiz)
94{
95 char byte;
96 while (count > 0)
97 {
98 byte = *buffer++;
99 mem_put_qi (address++, byte);
100 if (asciiz && (byte == 0))
101 return;
102 count--;
103 }
104}
105
106#define PTRSZ (A16 ? 2 : 3)
107
108static char *callnames[] = {
109 "SYS_zero",
110 "SYS_exit",
111 "SYS_open",
112 "SYS_close",
113 "SYS_read",
114 "SYS_write",
115 "SYS_lseek",
116 "SYS_unlink",
117 "SYS_getpid",
118 "SYS_kill",
119 "SYS_fstat",
120 "SYS_sbrk",
121 "SYS_argvlen",
122 "SYS_argv",
123 "SYS_chdir",
124 "SYS_stat",
125 "SYS_chmod",
126 "SYS_utime",
127 "SYS_time",
128 "SYS_gettimeofday",
129 "SYS_times",
130 "SYS_link"
131};
132
133int
134rx_syscall (int id)
135{
136 static char buf[256];
137 int rv;
138
139 argp = 0;
140 stackp = 4;
141 if (trace)
142 printf ("\033[31m/* SYSCALL(%d) = %s */\033[0m\n", id, id <= SYS_link ? callnames[id] : "unknown");
143 switch (id)
144 {
145 case SYS_exit:
146 {
147 int ec = arg ();
148 if (verbose)
149 printf ("[exit %d]\n", ec);
150 return RX_MAKE_EXITED (ec);
151 }
152 break;
153
154 case SYS_open:
155 {
156 int path = arg ();
157 /* The open function is defined as taking a variable number of arguments
158 because the third parameter to it is optional:
159 open (const char * filename, int flags, ...);
160 Hence the oflags and cflags arguments will be on the stack and we need
161 to skip the (empty) argument registers r3 and r4. */
162 argp = 4;
163 int oflags = arg ();
164 int cflags = arg ();
165
166 read_target (buf, path, 256, 1);
167 if (trace)
168 printf ("open(\"%s\",0x%x,%#o) = ", buf, oflags, cflags);
169
170 if (callbacks)
171 /* The callback vector ignores CFLAGS. */
172 rv = callbacks->open (callbacks, buf, oflags);
173 else
174 {
175 int h_oflags = 0;
176
177 if (oflags & 0x0001)
178 h_oflags |= O_WRONLY;
179 if (oflags & 0x0002)
180 h_oflags |= O_RDWR;
181 if (oflags & 0x0200)
182 h_oflags |= O_CREAT;
183 if (oflags & 0x0008)
184 h_oflags |= O_APPEND;
185 if (oflags & 0x0400)
186 h_oflags |= O_TRUNC;
187 rv = open (buf, h_oflags, cflags);
188 }
189 if (trace)
190 printf ("%d\n", rv);
191 put_reg (1, rv);
192 }
193 break;
194
195 case SYS_close:
196 {
197 int fd = arg ();
198
199 if (callbacks)
200 rv = callbacks->close (callbacks, fd);
201 else if (fd > 2)
202 rv = close (fd);
203 else
204 rv = 0;
205 if (trace)
206 printf ("close(%d) = %d\n", fd, rv);
207 put_reg (1, rv);
208 }
209 break;
210
211 case SYS_read:
212 {
213 int fd = arg ();
214 int addr = arg ();
215 int count = arg ();
216
217 if (count > sizeof (buf))
218 count = sizeof (buf);
219 if (callbacks)
220 rv = callbacks->read (callbacks, fd, buf, count);
221 else
222 rv = read (fd, buf, count);
223 if (trace)
224 printf ("read(%d,%d) = %d\n", fd, count, rv);
225 if (rv > 0)
226 write_target (buf, addr, rv, 0);
227 put_reg (1, rv);
228 }
229 break;
230
231 case SYS_write:
232 {
233 int fd = arg ();
234 int addr = arg ();
235 int count = arg ();
236
237 if (count > sizeof (buf))
238 count = sizeof (buf);
239 if (trace)
240 printf ("write(%d,0x%x,%d)\n", fd, addr, count);
241 read_target (buf, addr, count, 0);
242 if (trace)
243 fflush (stdout);
244 if (callbacks)
245 rv = callbacks->write (callbacks, fd, buf, count);
246 else
247 rv = write (fd, buf, count);
248 if (trace)
249 printf ("write(%d,%d) = %d\n", fd, count, rv);
250 put_reg (1, rv);
251 }
252 break;
253
254 case SYS_getpid:
255 put_reg (1, 42);
256 break;
257
258 case SYS_gettimeofday:
259 {
260 int tvaddr = arg ();
261 struct timeval tv;
262
263 rv = gettimeofday (&tv, 0);
264 if (trace)
265 printf ("gettimeofday: %ld sec %ld usec to 0x%x\n", tv.tv_sec,
266 tv.tv_usec, tvaddr);
267 mem_put_si (tvaddr, tv.tv_sec);
268 mem_put_si (tvaddr + 4, tv.tv_usec);
269 put_reg (1, rv);
270 }
271 break;
272
273 case SYS_kill:
274 {
275 int pid = arg ();
276 int sig = arg ();
277 if (pid == 42)
278 {
279 if (verbose)
280 printf ("[signal %d]\n", sig);
281 return RX_MAKE_STOPPED (sig);
282 }
283 }
284 break;
285
286 case 11:
287 {
288 int heaptop_arg = arg ();
289 if (trace)
290 printf ("sbrk: heap top set to %x\n", heaptop_arg);
291 heaptop = heaptop_arg;
292 if (heapbottom == 0)
293 heapbottom = heaptop_arg;
294 }
295 break;
296
297 case 255:
298 {
299 int addr = arg ();
300 mem_put_si (addr, rx_cycles + mem_usage_cycles());
301 }
302 break;
303
304 }
305 return RX_MAKE_STEPPED ();
306}
This page took 0.0409 seconds and 4 git commands to generate.