xref: /netbsd-src/external/gpl3/gdb/dist/sim/m32c/syscalls.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /* syscalls.c --- implement system calls for the M32C simulator.
2 
3 Copyright (C) 2005-2020 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 }
335