xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/m32c/syscalls.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1bb16d227Schristos /* syscalls.c --- implement system calls for the M32C simulator.
2bb16d227Schristos 
3*8b657b07Schristos Copyright (C) 2005-2023 Free Software Foundation, Inc.
4bb16d227Schristos Contributed by Red Hat, Inc.
5bb16d227Schristos 
6bb16d227Schristos This file is part of the GNU simulators.
7bb16d227Schristos 
8bb16d227Schristos This program is free software; you can redistribute it and/or modify
9bb16d227Schristos it under the terms of the GNU General Public License as published by
10bb16d227Schristos the Free Software Foundation; either version 3 of the License, or
11bb16d227Schristos (at your option) any later version.
12bb16d227Schristos 
13bb16d227Schristos This program is distributed in the hope that it will be useful,
14bb16d227Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
15bb16d227Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16bb16d227Schristos GNU General Public License for more details.
17bb16d227Schristos 
18bb16d227Schristos You should have received a copy of the GNU General Public License
19bb16d227Schristos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20bb16d227Schristos 
21*8b657b07Schristos /* This must come before any other includes.  */
22*8b657b07Schristos #include "defs.h"
23*8b657b07Schristos 
24bb16d227Schristos #include <stdio.h>
25bb16d227Schristos #include <stdlib.h>
26bb16d227Schristos #include <fcntl.h>
27bb16d227Schristos #include <unistd.h>
28bb16d227Schristos #include <sys/time.h>
29bb16d227Schristos 
30*8b657b07Schristos #include "sim/callback.h"
31bb16d227Schristos 
32bb16d227Schristos #include "cpu.h"
33bb16d227Schristos #include "mem.h"
34bb16d227Schristos #include "syscalls.h"
35*8b657b07Schristos #include "target-newlib-syscall.h"
36bb16d227Schristos 
37bb16d227Schristos /* The current syscall callbacks we're using.  */
38bb16d227Schristos static struct host_callback_struct *callbacks;
39bb16d227Schristos 
40bb16d227Schristos void
41bb16d227Schristos set_callbacks (struct host_callback_struct *cb)
42bb16d227Schristos {
43bb16d227Schristos   callbacks = cb;
44bb16d227Schristos }
45bb16d227Schristos 
46bb16d227Schristos 
47bb16d227Schristos /* A16 ABI: arg1 in r1l (QI) or r1 (HI) or stack
48bb16d227Schristos             arg2 in r2 (HI) or stack
49bb16d227Schristos 	    arg3..N on stack
50bb16d227Schristos 	    padding: none
51bb16d227Schristos 
52bb16d227Schristos    A24 ABI: arg1 in r0l (QI) or r0 (HI) or stack
53bb16d227Schristos 	    arg2..N on stack
54bb16d227Schristos 	    padding: qi->hi
55bb16d227Schristos 
56bb16d227Schristos    return value in r0l (QI) r0 (HI) r2r0 (SI)
57bb16d227Schristos      structs: pointer pushed on stack last
58bb16d227Schristos 
59bb16d227Schristos */
60bb16d227Schristos 
61bb16d227Schristos int argp, stackp;
62bb16d227Schristos 
63bb16d227Schristos static int
64bb16d227Schristos arg (int bytes)
65bb16d227Schristos {
66bb16d227Schristos   int rv = 0;
67bb16d227Schristos   argp++;
68bb16d227Schristos   if (A16)
69bb16d227Schristos     {
70bb16d227Schristos       switch (argp)
71bb16d227Schristos 	{
72bb16d227Schristos 	case 1:
73bb16d227Schristos 	  if (bytes == 1)
74bb16d227Schristos 	    return get_reg (r1l);
75bb16d227Schristos 	  if (bytes == 2)
76bb16d227Schristos 	    return get_reg (r1);
77bb16d227Schristos 	  break;
78bb16d227Schristos 	case 2:
79bb16d227Schristos 	  if (bytes == 2)
80bb16d227Schristos 	    return get_reg (r2);
81bb16d227Schristos 	  break;
82bb16d227Schristos 	}
83bb16d227Schristos     }
84bb16d227Schristos   else
85bb16d227Schristos     {
86bb16d227Schristos       switch (argp)
87bb16d227Schristos 	{
88bb16d227Schristos 	case 1:
89bb16d227Schristos 	  if (bytes == 1)
90bb16d227Schristos 	    return get_reg (r0l);
91bb16d227Schristos 	  if (bytes == 2)
92bb16d227Schristos 	    return get_reg (r0);
93bb16d227Schristos 	  break;
94bb16d227Schristos 	}
95bb16d227Schristos     }
96bb16d227Schristos   if (bytes == 0)
97bb16d227Schristos     bytes = 2;
98bb16d227Schristos   switch (bytes)
99bb16d227Schristos     {
100bb16d227Schristos     case 1:
101bb16d227Schristos       rv = mem_get_qi (get_reg (sp) + stackp);
102bb16d227Schristos       if (A24)
103bb16d227Schristos 	stackp++;
104bb16d227Schristos       break;
105bb16d227Schristos     case 2:
106bb16d227Schristos       rv = mem_get_hi (get_reg (sp) + stackp);
107bb16d227Schristos       break;
108bb16d227Schristos     case 3:
109bb16d227Schristos       rv = mem_get_psi (get_reg (sp) + stackp);
110bb16d227Schristos       if (A24)
111bb16d227Schristos 	stackp++;
112bb16d227Schristos       break;
113bb16d227Schristos     case 4:
114bb16d227Schristos       rv = mem_get_si (get_reg (sp) + stackp);
115bb16d227Schristos       break;
116bb16d227Schristos     }
117bb16d227Schristos   stackp += bytes;
118bb16d227Schristos   return rv;
119bb16d227Schristos }
120bb16d227Schristos 
121bb16d227Schristos static void
122bb16d227Schristos read_target (char *buffer, int address, int count, int asciiz)
123bb16d227Schristos {
124bb16d227Schristos   char byte;
125bb16d227Schristos   while (count > 0)
126bb16d227Schristos     {
127bb16d227Schristos       byte = mem_get_qi (address++);
128bb16d227Schristos       *buffer++ = byte;
129bb16d227Schristos       if (asciiz && (byte == 0))
130bb16d227Schristos 	return;
131bb16d227Schristos       count--;
132bb16d227Schristos     }
133bb16d227Schristos }
134bb16d227Schristos 
135bb16d227Schristos static void
136bb16d227Schristos write_target (char *buffer, int address, int count, int asciiz)
137bb16d227Schristos {
138bb16d227Schristos   char byte;
139bb16d227Schristos   while (count > 0)
140bb16d227Schristos     {
141bb16d227Schristos       byte = *buffer++;
142bb16d227Schristos       mem_put_qi (address++, byte);
143bb16d227Schristos       if (asciiz && (byte == 0))
144bb16d227Schristos 	return;
145bb16d227Schristos       count--;
146bb16d227Schristos     }
147bb16d227Schristos }
148bb16d227Schristos 
149bb16d227Schristos #define PTRSZ (A16 ? 2 : 3)
150bb16d227Schristos 
151bb16d227Schristos static char *callnames[] = {
152bb16d227Schristos   "SYS_zero",
153bb16d227Schristos   "SYS_exit",
154bb16d227Schristos   "SYS_open",
155bb16d227Schristos   "SYS_close",
156bb16d227Schristos   "SYS_read",
157bb16d227Schristos   "SYS_write",
158bb16d227Schristos   "SYS_lseek",
159bb16d227Schristos   "SYS_unlink",
160bb16d227Schristos   "SYS_getpid",
161bb16d227Schristos   "SYS_kill",
162bb16d227Schristos   "SYS_fstat",
163bb16d227Schristos   "SYS_sbrk",
164bb16d227Schristos   "SYS_argvlen",
165bb16d227Schristos   "SYS_argv",
166bb16d227Schristos   "SYS_chdir",
167bb16d227Schristos   "SYS_stat",
168bb16d227Schristos   "SYS_chmod",
169bb16d227Schristos   "SYS_utime",
170bb16d227Schristos   "SYS_time",
171bb16d227Schristos   "SYS_gettimeofday",
172bb16d227Schristos   "SYS_times",
173bb16d227Schristos   "SYS_link"
174bb16d227Schristos };
175bb16d227Schristos 
176bb16d227Schristos void
177bb16d227Schristos m32c_syscall (int id)
178bb16d227Schristos {
179bb16d227Schristos   static char buf[256];
180bb16d227Schristos   int rv;
181bb16d227Schristos 
182bb16d227Schristos   argp = 0;
183bb16d227Schristos   stackp = A16 ? 3 : 4;
184bb16d227Schristos   if (trace)
185bb16d227Schristos     printf ("\033[31m/* SYSCALL(%d) = %s */\033[0m\n", id, callnames[id]);
186bb16d227Schristos   switch (id)
187bb16d227Schristos     {
188*8b657b07Schristos     case TARGET_NEWLIB_SYS_exit:
189bb16d227Schristos       {
190bb16d227Schristos 	int ec = arg (2);
191bb16d227Schristos 	if (verbose)
192bb16d227Schristos 	  printf ("[exit %d]\n", ec);
193bb16d227Schristos 	step_result = M32C_MAKE_EXITED (ec);
194bb16d227Schristos       }
195bb16d227Schristos       break;
196bb16d227Schristos 
197*8b657b07Schristos     case TARGET_NEWLIB_SYS_open:
198bb16d227Schristos       {
199bb16d227Schristos 	int path = arg (PTRSZ);
200bb16d227Schristos 	int oflags = arg (2);
201bb16d227Schristos 	int cflags = arg (2);
202bb16d227Schristos 
203bb16d227Schristos 	read_target (buf, path, 256, 1);
204bb16d227Schristos 	if (trace)
205bb16d227Schristos 	  printf ("open(\"%s\",0x%x,%#o) = ", buf, oflags, cflags);
206bb16d227Schristos 
207bb16d227Schristos 	if (callbacks)
208bb16d227Schristos 	  /* The callback vector ignores CFLAGS.  */
209bb16d227Schristos 	  rv = callbacks->open (callbacks, buf, oflags);
210bb16d227Schristos 	else
211bb16d227Schristos 	  {
212bb16d227Schristos 	    int h_oflags = 0;
213bb16d227Schristos 
214bb16d227Schristos 	    if (oflags & 0x0001)
215bb16d227Schristos 	      h_oflags |= O_WRONLY;
216bb16d227Schristos 	    if (oflags & 0x0002)
217bb16d227Schristos 	      h_oflags |= O_RDWR;
218bb16d227Schristos 	    if (oflags & 0x0200)
219bb16d227Schristos 	      h_oflags |= O_CREAT;
220bb16d227Schristos 	    if (oflags & 0x0008)
221bb16d227Schristos 	      h_oflags |= O_APPEND;
222bb16d227Schristos 	    if (oflags & 0x0400)
223bb16d227Schristos 	      h_oflags |= O_TRUNC;
224bb16d227Schristos 	    rv = open (buf, h_oflags, cflags);
225bb16d227Schristos 	  }
226bb16d227Schristos 	if (trace)
227bb16d227Schristos 	  printf ("%d\n", rv);
228bb16d227Schristos 	put_reg (r0, rv);
229bb16d227Schristos       }
230bb16d227Schristos       break;
231bb16d227Schristos 
232*8b657b07Schristos     case TARGET_NEWLIB_SYS_close:
233bb16d227Schristos       {
234bb16d227Schristos 	int fd = arg (2);
235bb16d227Schristos 
236bb16d227Schristos 	if (callbacks)
237bb16d227Schristos 	  rv = callbacks->close (callbacks, fd);
238bb16d227Schristos 	else if (fd > 2)
239bb16d227Schristos 	  rv = close (fd);
240bb16d227Schristos 	else
241bb16d227Schristos 	  rv = 0;
242bb16d227Schristos 	if (trace)
243bb16d227Schristos 	  printf ("close(%d) = %d\n", fd, rv);
244bb16d227Schristos 	put_reg (r0, rv);
245bb16d227Schristos       }
246bb16d227Schristos       break;
247bb16d227Schristos 
248*8b657b07Schristos     case TARGET_NEWLIB_SYS_read:
249bb16d227Schristos       {
250bb16d227Schristos 	int fd = arg (2);
251bb16d227Schristos 	int addr = arg (PTRSZ);
252bb16d227Schristos 	int count = arg (2);
253bb16d227Schristos 
254bb16d227Schristos 	if (count > sizeof (buf))
255bb16d227Schristos 	  count = sizeof (buf);
256bb16d227Schristos 	if (callbacks)
257bb16d227Schristos 	  rv = callbacks->read (callbacks, fd, buf, count);
258bb16d227Schristos 	else
259bb16d227Schristos 	  rv = read (fd, buf, count);
260bb16d227Schristos 	if (trace)
261bb16d227Schristos 	  printf ("read(%d,%d) = %d\n", fd, count, rv);
262bb16d227Schristos 	if (rv > 0)
263bb16d227Schristos 	  write_target (buf, addr, rv, 0);
264bb16d227Schristos 	put_reg (r0, rv);
265bb16d227Schristos       }
266bb16d227Schristos       break;
267bb16d227Schristos 
268*8b657b07Schristos     case TARGET_NEWLIB_SYS_write:
269bb16d227Schristos       {
270bb16d227Schristos 	int fd = arg (2);
271bb16d227Schristos 	int addr = arg (PTRSZ);
272bb16d227Schristos 	int count = arg (2);
273bb16d227Schristos 
274bb16d227Schristos 	if (count > sizeof (buf))
275bb16d227Schristos 	  count = sizeof (buf);
276bb16d227Schristos 	if (trace)
277bb16d227Schristos 	  printf ("write(%d,0x%x,%d)\n", fd, addr, count);
278bb16d227Schristos 	read_target (buf, addr, count, 0);
279bb16d227Schristos 	if (trace)
280bb16d227Schristos 	  fflush (stdout);
281bb16d227Schristos 	if (callbacks)
282bb16d227Schristos 	  rv = callbacks->write (callbacks, fd, buf, count);
283bb16d227Schristos 	else
284bb16d227Schristos 	  rv = write (fd, buf, count);
285bb16d227Schristos 	if (trace)
286bb16d227Schristos 	  printf ("write(%d,%d) = %d\n", fd, count, rv);
287bb16d227Schristos 	put_reg (r0, rv);
288bb16d227Schristos       }
289bb16d227Schristos       break;
290bb16d227Schristos 
291*8b657b07Schristos     case TARGET_NEWLIB_SYS_getpid:
292bb16d227Schristos       put_reg (r0, 42);
293bb16d227Schristos       break;
294bb16d227Schristos 
295*8b657b07Schristos     case TARGET_NEWLIB_SYS_gettimeofday:
296bb16d227Schristos       {
297bb16d227Schristos 	int tvaddr = arg (PTRSZ);
298bb16d227Schristos 	struct timeval tv;
299bb16d227Schristos 
300bb16d227Schristos 	rv = gettimeofday (&tv, 0);
301bb16d227Schristos 	if (trace)
302*8b657b07Schristos 	  printf ("gettimeofday: %" PRId64 " sec %" PRId64 " usec to 0x%x\n",
303*8b657b07Schristos 		  (int64_t)tv.tv_sec, (int64_t)tv.tv_usec, tvaddr);
304bb16d227Schristos 	mem_put_si (tvaddr, tv.tv_sec);
305bb16d227Schristos 	mem_put_si (tvaddr + 4, tv.tv_usec);
306bb16d227Schristos 	put_reg (r0, rv);
307bb16d227Schristos       }
308bb16d227Schristos       break;
309bb16d227Schristos 
310*8b657b07Schristos     case TARGET_NEWLIB_SYS_kill:
311bb16d227Schristos       {
312bb16d227Schristos 	int pid = arg (2);
313bb16d227Schristos 	int sig = arg (2);
314bb16d227Schristos 	if (pid == 42)
315bb16d227Schristos 	  {
316bb16d227Schristos 	    if (verbose)
317bb16d227Schristos 	      printf ("[signal %d]\n", sig);
318bb16d227Schristos 	    step_result = M32C_MAKE_STOPPED (sig);
319bb16d227Schristos 	  }
320bb16d227Schristos       }
321bb16d227Schristos       break;
322bb16d227Schristos 
323bb16d227Schristos     case 11:
324bb16d227Schristos       {
325bb16d227Schristos 	int heaptop_arg = arg (PTRSZ);
326bb16d227Schristos 	if (trace)
327bb16d227Schristos 	  printf ("sbrk: heap top set to %x\n", heaptop_arg);
328bb16d227Schristos 	heaptop = heaptop_arg;
329bb16d227Schristos 	if (heapbottom == 0)
330bb16d227Schristos 	  heapbottom = heaptop_arg;
331bb16d227Schristos       }
332bb16d227Schristos       break;
333bb16d227Schristos 
334bb16d227Schristos     }
335bb16d227Schristos }
336