tweak previous entry to keep chronology right
[deliverable/binutils-gdb.git] / sim / rx / syscalls.c
1 /* syscalls.c --- implement system calls for the RX simulator.
2
3 Copyright (C) 2005, 2007, 2008, 2009, 2010 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
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. */
37 static struct host_callback_struct *callbacks;
38
39 void
40 set_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
62 int argp, stackp;
63
64 static int
65 arg ()
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
78 static void
79 read_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
92 static void
93 write_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
108 static 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
133 int
134 rx_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.03664 seconds and 4 git commands to generate.