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