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