]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m32c/syscalls.c
3cc3cdbf2741aece84ca413408bf6294052ff538
[thirdparty/binutils-gdb.git] / sim / m32c / syscalls.c
1 /* syscalls.c --- implement system calls for the M32C simulator.
2
3 Copyright (C) 2005-2014 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 #include "config.h"
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 /* A16 ABI: arg1 in r1l (QI) or r1 (HI) or stack
47 arg2 in r2 (HI) or stack
48 arg3..N on stack
49 padding: none
50
51 A24 ABI: arg1 in r0l (QI) or r0 (HI) or stack
52 arg2..N on stack
53 padding: qi->hi
54
55 return value in r0l (QI) r0 (HI) r2r0 (SI)
56 structs: pointer pushed on stack last
57
58 */
59
60 int argp, stackp;
61
62 static int
63 arg (int bytes)
64 {
65 int rv = 0;
66 argp++;
67 if (A16)
68 {
69 switch (argp)
70 {
71 case 1:
72 if (bytes == 1)
73 return get_reg (r1l);
74 if (bytes == 2)
75 return get_reg (r1);
76 break;
77 case 2:
78 if (bytes == 2)
79 return get_reg (r2);
80 break;
81 }
82 }
83 else
84 {
85 switch (argp)
86 {
87 case 1:
88 if (bytes == 1)
89 return get_reg (r0l);
90 if (bytes == 2)
91 return get_reg (r0);
92 break;
93 }
94 }
95 if (bytes == 0)
96 bytes = 2;
97 switch (bytes)
98 {
99 case 1:
100 rv = mem_get_qi (get_reg (sp) + stackp);
101 if (A24)
102 stackp++;
103 break;
104 case 2:
105 rv = mem_get_hi (get_reg (sp) + stackp);
106 break;
107 case 3:
108 rv = mem_get_psi (get_reg (sp) + stackp);
109 if (A24)
110 stackp++;
111 break;
112 case 4:
113 rv = mem_get_si (get_reg (sp) + stackp);
114 break;
115 }
116 stackp += bytes;
117 return rv;
118 }
119
120 static void
121 read_target (char *buffer, int address, int count, int asciiz)
122 {
123 char byte;
124 while (count > 0)
125 {
126 byte = mem_get_qi (address++);
127 *buffer++ = byte;
128 if (asciiz && (byte == 0))
129 return;
130 count--;
131 }
132 }
133
134 static void
135 write_target (char *buffer, int address, int count, int asciiz)
136 {
137 char byte;
138 while (count > 0)
139 {
140 byte = *buffer++;
141 mem_put_qi (address++, byte);
142 if (asciiz && (byte == 0))
143 return;
144 count--;
145 }
146 }
147
148 #define PTRSZ (A16 ? 2 : 3)
149
150 static char *callnames[] = {
151 "SYS_zero",
152 "SYS_exit",
153 "SYS_open",
154 "SYS_close",
155 "SYS_read",
156 "SYS_write",
157 "SYS_lseek",
158 "SYS_unlink",
159 "SYS_getpid",
160 "SYS_kill",
161 "SYS_fstat",
162 "SYS_sbrk",
163 "SYS_argvlen",
164 "SYS_argv",
165 "SYS_chdir",
166 "SYS_stat",
167 "SYS_chmod",
168 "SYS_utime",
169 "SYS_time",
170 "SYS_gettimeofday",
171 "SYS_times",
172 "SYS_link"
173 };
174
175 void
176 m32c_syscall (int id)
177 {
178 static char buf[256];
179 int rv;
180
181 argp = 0;
182 stackp = A16 ? 3 : 4;
183 if (trace)
184 printf ("\033[31m/* SYSCALL(%d) = %s */\033[0m\n", id, callnames[id]);
185 switch (id)
186 {
187 case SYS_exit:
188 {
189 int ec = arg (2);
190 if (verbose)
191 printf ("[exit %d]\n", ec);
192 step_result = M32C_MAKE_EXITED (ec);
193 }
194 break;
195
196 case SYS_open:
197 {
198 int path = arg (PTRSZ);
199 int oflags = arg (2);
200 int cflags = arg (2);
201
202 read_target (buf, path, 256, 1);
203 if (trace)
204 printf ("open(\"%s\",0x%x,%#o) = ", buf, oflags, cflags);
205
206 if (callbacks)
207 /* The callback vector ignores CFLAGS. */
208 rv = callbacks->open (callbacks, buf, oflags);
209 else
210 {
211 int h_oflags = 0;
212
213 if (oflags & 0x0001)
214 h_oflags |= O_WRONLY;
215 if (oflags & 0x0002)
216 h_oflags |= O_RDWR;
217 if (oflags & 0x0200)
218 h_oflags |= O_CREAT;
219 if (oflags & 0x0008)
220 h_oflags |= O_APPEND;
221 if (oflags & 0x0400)
222 h_oflags |= O_TRUNC;
223 rv = open (buf, h_oflags, cflags);
224 }
225 if (trace)
226 printf ("%d\n", rv);
227 put_reg (r0, rv);
228 }
229 break;
230
231 case SYS_close:
232 {
233 int fd = arg (2);
234
235 if (callbacks)
236 rv = callbacks->close (callbacks, fd);
237 else if (fd > 2)
238 rv = close (fd);
239 else
240 rv = 0;
241 if (trace)
242 printf ("close(%d) = %d\n", fd, rv);
243 put_reg (r0, rv);
244 }
245 break;
246
247 case SYS_read:
248 {
249 int fd = arg (2);
250 int addr = arg (PTRSZ);
251 int count = arg (2);
252
253 if (count > sizeof (buf))
254 count = sizeof (buf);
255 if (callbacks)
256 rv = callbacks->read (callbacks, fd, buf, count);
257 else
258 rv = read (fd, buf, count);
259 if (trace)
260 printf ("read(%d,%d) = %d\n", fd, count, rv);
261 if (rv > 0)
262 write_target (buf, addr, rv, 0);
263 put_reg (r0, rv);
264 }
265 break;
266
267 case SYS_write:
268 {
269 int fd = arg (2);
270 int addr = arg (PTRSZ);
271 int count = arg (2);
272
273 if (count > sizeof (buf))
274 count = sizeof (buf);
275 if (trace)
276 printf ("write(%d,0x%x,%d)\n", fd, addr, count);
277 read_target (buf, addr, count, 0);
278 if (trace)
279 fflush (stdout);
280 if (callbacks)
281 rv = callbacks->write (callbacks, fd, buf, count);
282 else
283 rv = write (fd, buf, count);
284 if (trace)
285 printf ("write(%d,%d) = %d\n", fd, count, rv);
286 put_reg (r0, rv);
287 }
288 break;
289
290 case SYS_getpid:
291 put_reg (r0, 42);
292 break;
293
294 case SYS_gettimeofday:
295 {
296 int tvaddr = arg (PTRSZ);
297 struct timeval tv;
298
299 rv = gettimeofday (&tv, 0);
300 if (trace)
301 printf ("gettimeofday: %ld sec %ld usec to 0x%x\n", tv.tv_sec,
302 tv.tv_usec, tvaddr);
303 mem_put_si (tvaddr, tv.tv_sec);
304 mem_put_si (tvaddr + 4, tv.tv_usec);
305 put_reg (r0, rv);
306 }
307 break;
308
309 case SYS_kill:
310 {
311 int pid = arg (2);
312 int sig = arg (2);
313 if (pid == 42)
314 {
315 if (verbose)
316 printf ("[signal %d]\n", sig);
317 step_result = M32C_MAKE_STOPPED (sig);
318 }
319 }
320 break;
321
322 case 11:
323 {
324 int heaptop_arg = arg (PTRSZ);
325 if (trace)
326 printf ("sbrk: heap top set to %x\n", heaptop_arg);
327 heaptop = heaptop_arg;
328 if (heapbottom == 0)
329 heapbottom = heaptop_arg;
330 }
331 break;
332
333 }
334 }