xref: /netbsd-src/external/gpl3/gdb/dist/sim/m32c/syscalls.c (revision 71f621822dbfd5073a314948bec169b7bb05f7be)
1 /* syscalls.c --- implement system calls for the M32C simulator.
2 
3 Copyright (C) 2005-2024 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 "target-newlib-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 /* 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_NEWLIB_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_NEWLIB_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_NEWLIB_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_NEWLIB_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_NEWLIB_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_NEWLIB_SYS_getpid:
292       put_reg (r0, 42);
293       break;
294 
295     case TARGET_NEWLIB_SYS_gettimeofday:
296       {
297 	int tvaddr = arg (PTRSZ);
298 	struct timeval tv;
299 
300 	rv = gettimeofday (&tv, 0);
301 	if (trace)
302 	  printf ("gettimeofday: %" PRId64 " sec %" PRId64 " usec to 0x%x\n",
303 		  (int64_t)tv.tv_sec, (int64_t)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_NEWLIB_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 }
336