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