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