run copyright.sh for 2011.
[external/binutils.git] / sim / m32c / syscalls.c
1 /* syscalls.c --- implement system calls for the M32C simulator.
2
3 Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
5 Contributed by Red Hat, Inc.
6
7 This file is part of the GNU simulators.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <sys/time.h>
28
29 #include "gdb/callback.h"
30
31 #include "cpu.h"
32 #include "mem.h"
33 #include "syscalls.h"
34
35 #include "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 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 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 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 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 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 SYS_getpid:
292       put_reg (r0, 42);
293       break;
294
295     case 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 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 }