Index: arm/ChangeLog
[platform/upstream/binutils.git] / sim / ppc / emul_netbsd.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19     */
20
21
22 #ifndef _EMUL_NETBSD_C_
23 #define _EMUL_NETBSD_C_
24
25
26 /* Note: this module is called via a table.  There is no benefit in
27    making it inline */
28
29 #include "emul_generic.h"
30 #include "emul_netbsd.h"
31
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #else
35 #ifdef HAVE_STRINGS_H
36 #include <strings.h>
37 #endif
38 #endif
39
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <stdio.h>
43 #include <signal.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <sys/errno.h>
47 #include <sys/param.h>
48 #include <sys/time.h>
49
50 #ifdef HAVE_GETRUSAGE
51 #ifndef HAVE_SYS_RESOURCE_H
52 #undef HAVE_GETRUSAGE
53 #endif
54 #endif
55
56 #ifdef HAVE_GETRUSAGE
57 #include <sys/resource.h>
58 int getrusage();
59 #endif
60
61 #if HAVE_SYS_IOCTL_H
62 #include <sys/ioctl.h>
63 #endif
64
65 #if HAVE_DIRENT_H
66 # include <dirent.h>
67 # define NAMLEN(dirent) strlen((dirent)->d_name)
68 #else
69 # define dirent direct
70 # define NAMLEN(dirent) (dirent)->d_namlen
71 # if HAVE_SYS_NDIR_H
72 #  include <sys/ndir.h>
73 # endif
74 # if HAVE_SYS_DIR_H
75 #  include <sys/dir.h>
76 # endif
77 # if HAVE_NDIR_H
78 #  include <ndir.h>
79 # endif
80 #endif
81
82 #ifdef HAVE_UNISTD_H
83 #undef MAXPATHLEN               /* sys/param.h might define this also */
84 #include <unistd.h>
85 #endif
86
87 #ifdef HAVE_STDLIB_H
88 #include <stdlib.h>
89 #endif
90
91 #define WITH_NetBSD_HOST (NetBSD >= 199306)
92 #if WITH_NetBSD_HOST /* here NetBSD as that is what we're emulating */
93 #include <sys/syscall.h> /* FIXME - should not be including this one */
94 #include <sys/sysctl.h>
95 #include <sys/mount.h>
96 extern int getdirentries(int fd, char *buf, int nbytes, long *basep);
97
98 /* NetBSD post 2.0 has the statfs system call (if COMPAT_20), but does
99    not have struct statfs.  In this case don't implement fstatfs.
100    FIXME: Should implement fstatvfs.  */
101 #ifndef HAVE_STRUCT_STATFS
102 #undef HAVE_FSTATFS
103 #endif
104
105 #else
106
107 /* If this is not netbsd, don't allow fstatfs or getdirentries at this time */
108 #undef HAVE_FSTATFS
109 #undef HAVE_GETDIRENTRIES
110 #endif
111
112 #if (BSD < 199306) /* here BSD as just a bug */
113 extern int errno;
114 #endif
115
116 #ifndef STATIC_INLINE_EMUL_NETBSD
117 #define STATIC_INLINE_EMUL_NETBSD STATIC_INLINE
118 #endif
119
120
121 #if WITH_NetBSD_HOST
122 #define SYS(X) ASSERT(call == (SYS_##X))
123 #else
124 #define SYS(X)
125 #endif
126
127 #if WITH_NetBSD_HOST && (PATH_MAX != 1024)
128 #error "PATH_MAX not 1024"
129 #elif !defined(PATH_MAX)
130 #define PATH_MAX 1024
131 #endif
132
133
134 /* EMULATION
135
136    NetBSD - Emulation of user programs for NetBSD/PPC
137
138    DESCRIPTION
139
140    */
141
142
143 /* NetBSD's idea of what is needed to implement emulations */
144
145 struct _os_emul_data {
146   device *vm;
147   emul_syscall *syscalls;
148 };
149
150
151
152 STATIC_INLINE_EMUL_NETBSD void
153 write_stat(unsigned_word addr,
154            struct stat buf,
155            cpu *processor,
156            unsigned_word cia)
157 {
158   H2T(buf.st_dev);
159   H2T(buf.st_ino);
160   H2T(buf.st_mode);
161   H2T(buf.st_nlink);
162   H2T(buf.st_uid);
163   H2T(buf.st_gid);
164   H2T(buf.st_size);
165   H2T(buf.st_atime);
166   /* H2T(buf.st_spare1); */
167   H2T(buf.st_mtime);
168   /* H2T(buf.st_spare2); */
169   H2T(buf.st_ctime);
170   /* H2T(buf.st_spare3); */
171 #ifdef AC_STRUCT_ST_RDEV
172   H2T(buf.st_rdev);
173 #endif
174 #ifdef AC_STRUCT_ST_BLKSIZE
175   H2T(buf.st_blksize);
176 #endif
177 #ifdef AC_STRUCT_ST_BLOCKS
178   H2T(buf.st_blocks);
179 #endif
180 #if WITH_NetBSD_HOST
181   H2T(buf.st_flags);
182   H2T(buf.st_gen);
183 #endif
184   emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
185 }
186
187
188 #ifdef HAVE_FSTATFS
189 STATIC_INLINE_EMUL_NETBSD void
190 write_statfs(unsigned_word addr,
191              struct statfs buf,
192              cpu *processor,
193              unsigned_word cia)
194 {
195   H2T(buf.f_type);
196   H2T(buf.f_flags);
197   H2T(buf.f_bsize);
198   H2T(buf.f_iosize);
199   H2T(buf.f_blocks);
200   H2T(buf.f_bfree);
201   H2T(buf.f_bavail);
202   H2T(buf.f_files);
203   H2T(buf.f_ffree);
204   H2T(buf.f_fsid.val[0]);
205   H2T(buf.f_fsid.val[1]);
206   H2T(buf.f_owner);
207   /* f_spare[4]; */
208   /* f_fstypename[MFSNAMELEN]; */
209   /* f_mntonname[MNAMELEN]; */
210   /* f_mntfromname[MNAMELEN]; */
211   emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
212 }
213 #endif
214
215
216 STATIC_INLINE_EMUL_NETBSD void
217 write_timeval(unsigned_word addr,
218               struct timeval t,
219               cpu *processor,
220               unsigned_word cia)
221 {
222   H2T(t.tv_sec);
223   H2T(t.tv_usec);
224   emul_write_buffer(&t, addr, sizeof(t), processor, cia);
225 }
226
227
228 STATIC_INLINE_EMUL_NETBSD void
229 write_timezone(unsigned_word addr,
230                struct timezone tz,
231                cpu *processor,
232                unsigned_word cia)
233 {
234   H2T(tz.tz_minuteswest);
235   H2T(tz.tz_dsttime);
236   emul_write_buffer(&tz, addr, sizeof(tz), processor, cia);
237 }
238
239
240 #ifdef HAVE_GETDIRENTRIES
241 STATIC_INLINE_EMUL_NETBSD void
242 write_direntries(unsigned_word addr,
243                  char *buf,
244                  int nbytes,
245                  cpu *processor,
246                  unsigned_word cia)
247 {
248   while (nbytes > 0) {
249     struct dirent *out;
250     struct dirent *in = (struct dirent*)buf;
251     ASSERT(in->d_reclen <= nbytes);
252     out = (struct dirent*)zalloc(in->d_reclen);
253     memcpy(out/*dest*/, in/*src*/, in->d_reclen);
254     H2T(out->d_fileno);
255     H2T(out->d_reclen);
256     H2T(out->d_type);
257     H2T(out->d_namlen);
258     emul_write_buffer(out, addr, in->d_reclen, processor, cia);
259     nbytes -= in->d_reclen;
260     addr += in->d_reclen;
261     buf += in->d_reclen;
262     zfree(out);
263   }
264 }
265 #endif
266
267
268 #ifdef HAVE_GETRUSAGE
269 STATIC_INLINE_EMUL_NETBSD void
270 write_rusage(unsigned_word addr,
271              struct rusage rusage,
272              cpu *processor,
273              unsigned_word cia)
274 {
275   H2T(rusage.ru_utime.tv_sec); /* user time used */
276   H2T(rusage.ru_utime.tv_usec);
277   H2T(rusage.ru_stime.tv_sec); /* system time used */
278   H2T(rusage.ru_stime.tv_usec);
279   H2T(rusage.ru_maxrss);          /* integral max resident set size */
280   H2T(rusage.ru_ixrss);           /* integral shared text memory size */
281   H2T(rusage.ru_idrss);           /* integral unshared data size */
282   H2T(rusage.ru_isrss);           /* integral unshared stack size */
283   H2T(rusage.ru_minflt);          /* page reclaims */
284   H2T(rusage.ru_majflt);          /* page faults */
285   H2T(rusage.ru_nswap);           /* swaps */
286   H2T(rusage.ru_inblock);         /* block input operations */
287   H2T(rusage.ru_oublock);         /* block output operations */
288   H2T(rusage.ru_msgsnd);          /* messages sent */
289   H2T(rusage.ru_msgrcv);          /* messages received */
290   H2T(rusage.ru_nsignals);        /* signals received */
291   H2T(rusage.ru_nvcsw);           /* voluntary context switches */
292   H2T(rusage.ru_nivcsw);          /* involuntary context switches */
293   emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);
294 }
295 #endif
296
297 static void
298 do_exit(os_emul_data *emul,
299         unsigned call,
300         const int arg0,
301         cpu *processor,
302         unsigned_word cia)
303 {
304   int status = (int)cpu_registers(processor)->gpr[arg0];
305   SYS(exit);
306   if (WITH_TRACE && ppc_trace[trace_os_emul])
307     printf_filtered ("%d)\n", status);
308
309   cpu_halt(processor, cia, was_exited, status);
310 }
311
312
313 static void
314 do_read(os_emul_data *emul,
315         unsigned call,
316         const int arg0,
317         cpu *processor,
318         unsigned_word cia)
319 {
320   void *scratch_buffer;
321   int d = (int)cpu_registers(processor)->gpr[arg0];
322   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
323   int nbytes = cpu_registers(processor)->gpr[arg0+2];
324   int status;
325   SYS(read);
326
327   if (WITH_TRACE && ppc_trace[trace_os_emul])
328     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
329
330   /* get a tempoary bufer */
331   scratch_buffer = zalloc(nbytes);
332
333   /* check if buffer exists by reading it */
334   emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
335
336   /* read */
337 #if 0
338   if (d == 0) {
339     status = fread (scratch_buffer, 1, nbytes, stdin);
340     if (status == 0 && ferror (stdin))
341       status = -1;
342   }
343 #endif
344   status = read (d, scratch_buffer, nbytes);
345
346   emul_write_status(processor, status, errno);
347   if (status > 0)
348     emul_write_buffer(scratch_buffer, buf, status, processor, cia);
349
350   zfree(scratch_buffer);
351 }
352
353
354 static void
355 do_write(os_emul_data *emul,
356          unsigned call,
357          const int arg0,
358          cpu *processor,
359          unsigned_word cia)
360 {
361   void *scratch_buffer = NULL;
362   int d = (int)cpu_registers(processor)->gpr[arg0];
363   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
364   int nbytes = cpu_registers(processor)->gpr[arg0+2];
365   int status;
366   SYS(write);
367
368   if (WITH_TRACE && ppc_trace[trace_os_emul])
369     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
370
371   /* get a tempoary bufer */
372   scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
373
374   /* copy in */
375   emul_read_buffer(scratch_buffer, buf, nbytes,
376                    processor, cia);
377
378   /* write */
379   status = write(d, scratch_buffer, nbytes);
380   emul_write_status(processor, status, errno);
381   zfree(scratch_buffer);
382
383   flush_stdoutput();
384 }
385
386
387 static void
388 do_open(os_emul_data *emul,
389         unsigned call,
390         const int arg0,
391         cpu *processor,
392         unsigned_word cia)
393 {
394   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
395   char path_buf[PATH_MAX];
396   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
397   int flags = (int)cpu_registers(processor)->gpr[arg0+1];
398   int mode = (int)cpu_registers(processor)->gpr[arg0+2];
399   int hostflags;
400   int status;
401
402   if (WITH_TRACE && ppc_trace[trace_os_emul])
403     printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
404
405   SYS(open);
406
407   /* Do some translation on 'flags' to match it to the host's version.  */
408   /* These flag values were taken from the NetBSD 1.4 header files.  */
409   if ((flags & 3) == 0)
410     hostflags = O_RDONLY;
411   else if ((flags & 3) == 1)
412     hostflags = O_WRONLY;
413   else
414     hostflags = O_RDWR;
415   if (flags & 0x00000008)
416     hostflags |= O_APPEND;
417   if (flags & 0x00000200)
418     hostflags |= O_CREAT;
419   if (flags & 0x00000400)
420     hostflags |= O_TRUNC;
421   if (flags & 0x00000800)
422     hostflags |= O_EXCL;
423
424   /* Can't combine these statements, cuz open sets errno. */
425   status = open(path, hostflags, mode);
426   emul_write_status(processor, status, errno);
427 }
428
429
430 static void
431 do_close(os_emul_data *emul,
432          unsigned call,
433          const int arg0,
434          cpu *processor,
435          unsigned_word cia)
436 {
437   int d = (int)cpu_registers(processor)->gpr[arg0];
438   int status;
439
440   if (WITH_TRACE && ppc_trace[trace_os_emul])
441     printf_filtered ("%d", d);
442
443   SYS(close);
444
445   /* Can't combine these statements, cuz close sets errno. */
446   status = close(d);
447   emul_write_status(processor, status, errno);
448 }
449
450
451 static void
452 do_break(os_emul_data *emul,
453          unsigned call,
454          const int arg0,
455          cpu *processor,
456          unsigned_word cia)
457 {
458   /* just pass this onto the `vm' device */
459   unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
460   int status;
461
462   if (WITH_TRACE && ppc_trace[trace_os_emul])
463     printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
464
465   SYS(break);
466   status = device_ioctl(emul->vm,
467                         processor,
468                         cia,
469                         device_ioctl_break,
470                         new_break); /*ioctl-data*/
471   emul_write_status(processor, 0, status);
472 }
473
474
475 #ifndef HAVE_GETPID
476 #define do_getpid 0
477 #else
478 static void
479 do_getpid(os_emul_data *emul,
480           unsigned call,
481           const int arg0,
482           cpu *processor,
483           unsigned_word cia)
484 {
485   SYS(getpid);
486   emul_write_status(processor, (int)getpid(), 0);
487 }
488 #endif
489
490 #ifndef HAVE_GETUID
491 #define do_getuid 0
492 #else
493 static void
494 do_getuid(os_emul_data *emul,
495           unsigned call,
496           const int arg0,
497           cpu *processor,
498           unsigned_word cia)
499 {
500   SYS(getuid);
501   emul_write_status(processor, (int)getuid(), 0);
502 }
503 #endif
504
505 #ifndef HAVE_GETEUID
506 #define do_geteuid 0
507 #else
508 static void
509 do_geteuid(os_emul_data *emul,
510            unsigned call,
511            const int arg0,
512            cpu *processor,
513            unsigned_word cia)
514 {
515   SYS(geteuid);
516   emul_write_status(processor, (int)geteuid(), 0);
517 }
518 #endif
519
520 #ifndef HAVE_KILL
521 #define do_kill 0
522 #else
523 static void
524 do_kill(os_emul_data *emul,
525         unsigned call,
526         const int arg0,
527         cpu *processor,
528         unsigned_word cia)
529 {
530   pid_t pid = cpu_registers(processor)->gpr[arg0];
531   int sig = cpu_registers(processor)->gpr[arg0+1];
532
533   if (WITH_TRACE && ppc_trace[trace_os_emul])
534     printf_filtered ("%d, %d", (int)pid, sig);
535
536   SYS(kill);
537   printf_filtered("SYS_kill at 0x%lx - more to this than just being killed\n",
538                   (long)cia);
539   cpu_halt(processor, cia, was_signalled, sig);
540 }
541 #endif
542
543 #ifndef HAVE_DUP
544 #define do_dup 0
545 #else
546 static void
547 do_dup(os_emul_data *emul,
548        unsigned call,
549        const int arg0,
550        cpu *processor,
551        unsigned_word cia)
552 {
553   int oldd = cpu_registers(processor)->gpr[arg0];
554   int status = dup(oldd);
555   int err = errno;
556
557   if (WITH_TRACE && ppc_trace[trace_os_emul])
558     printf_filtered ("%d", oldd);
559
560   SYS(dup);
561   emul_write_status(processor, status, err);
562 }
563 #endif
564
565 #ifndef HAVE_GETEGID
566 #define do_getegid 0
567 #else
568 static void
569 do_getegid(os_emul_data *emul,
570            unsigned call,
571            const int arg0,
572            cpu *processor,
573            unsigned_word cia)
574 {
575   SYS(getegid);
576   emul_write_status(processor, (int)getegid(), 0);
577 }
578 #endif
579
580 #ifndef HAVE_GETGID
581 #define do_getgid 0
582 #else
583 static void
584 do_getgid(os_emul_data *emul,
585           unsigned call,
586           const int arg0,
587           cpu *processor,
588           unsigned_word cia)
589 {
590   SYS(getgid);
591   emul_write_status(processor, (int)getgid(), 0);
592 }
593 #endif
594
595 #ifndef HAVE_SIGPROCMASK
596 #define do_sigprocmask 0
597 #else
598 static void
599 do_sigprocmask(os_emul_data *emul,
600                unsigned call,
601                const int arg0,
602                cpu *processor,
603                unsigned_word cia)
604 {
605   natural_word how = cpu_registers(processor)->gpr[arg0];
606   unsigned_word set = cpu_registers(processor)->gpr[arg0+1];
607   unsigned_word oset = cpu_registers(processor)->gpr[arg0+2];
608 #ifdef SYS_sigprocmask
609   SYS(sigprocmask);
610 #endif
611
612   if (WITH_TRACE && ppc_trace[trace_os_emul])
613     printf_filtered ("%ld, 0x%ld, 0x%ld", (long)how, (long)set, (long)oset);
614
615   emul_write_status(processor, 0, 0);
616   cpu_registers(processor)->gpr[4] = set;
617 }
618 #endif
619
620 #ifndef HAVE_IOCTL
621 #define do_ioctl 0
622 #else
623 static void
624 do_ioctl(os_emul_data *emul,
625          unsigned call,
626          const int arg0,
627          cpu *processor,
628          unsigned_word cia)
629 {
630   int d = cpu_registers(processor)->gpr[arg0];
631   unsigned request = cpu_registers(processor)->gpr[arg0+1];
632   unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
633
634 #if !WITH_NetBSD_HOST
635   cpu_registers(processor)->gpr[arg0] = 0; /* just succeed */
636 #else
637   unsigned dir = request & IOC_DIRMASK;
638   int status;
639   SYS(ioctl);
640   /* what we haven't done */
641   if (dir & IOC_IN /* write into the io device */
642       || dir & IOC_OUT
643       || !(dir & IOC_VOID))
644     error("do_ioctl() read or write of parameter not implemented\n");
645   status = ioctl(d, request, NULL);
646   emul_write_status(processor, status, errno);
647 #endif
648
649   if (WITH_TRACE && ppc_trace[trace_os_emul])
650     printf_filtered ("%d, 0x%x, 0x%lx", d, request, (long)argp_addr);
651 }
652 #endif
653
654 #ifndef HAVE_UMASK
655 #define do_umask 0
656 #else
657 static void
658 do_umask(os_emul_data *emul,
659          unsigned call,
660          const int arg0,
661          cpu *processor,
662          unsigned_word cia)
663 {
664   int mask = cpu_registers(processor)->gpr[arg0];
665
666   if (WITH_TRACE && ppc_trace[trace_os_emul])
667     printf_filtered ("0%o", mask);
668
669   SYS(umask);
670   emul_write_status(processor, umask(mask), 0);
671 }
672 #endif
673
674 #ifndef HAVE_DUP2
675 #define do_dup2 0
676 #else
677 static void
678 do_dup2(os_emul_data *emul,
679         unsigned call,
680         const int arg0,
681         cpu *processor,
682         unsigned_word cia)
683 {
684   int oldd = cpu_registers(processor)->gpr[arg0];
685   int newd = cpu_registers(processor)->gpr[arg0+1];
686   int status = dup2(oldd, newd);
687   int err = errno;
688
689   if (WITH_TRACE && ppc_trace[trace_os_emul])
690     printf_filtered ("%d, %d", oldd, newd);
691
692   SYS(dup2);
693   emul_write_status(processor, status, err);
694 }
695 #endif
696
697 #ifndef HAVE_FCNTL
698 #define do_fcntl 0
699 #else
700 static void
701 do_fcntl(os_emul_data *emul,
702          unsigned call,
703          const int arg0,
704          cpu *processor,
705          unsigned_word cia)
706 {
707   int fd = cpu_registers(processor)->gpr[arg0];
708   int cmd = cpu_registers(processor)->gpr[arg0+1];
709   int arg = cpu_registers(processor)->gpr[arg0+2];
710   int status;
711
712   if (WITH_TRACE && ppc_trace[trace_os_emul])
713     printf_filtered ("%d, %d, %d", fd, cmd, arg);
714
715   SYS(fcntl);
716   status = fcntl(fd, cmd, arg);
717   emul_write_status(processor, status, errno);
718 }
719 #endif
720
721 #ifndef HAVE_GETTIMEOFDAY
722 #define do_gettimeofday 0
723 #else
724 static void
725 do_gettimeofday(os_emul_data *emul,
726                 unsigned call,
727                 const int arg0,
728                 cpu *processor,
729                 unsigned_word cia)
730 {
731   unsigned_word t_addr = cpu_registers(processor)->gpr[arg0];
732   unsigned_word tz_addr = cpu_registers(processor)->gpr[arg0+1];
733   struct timeval t;
734   struct timezone tz;
735   int status = gettimeofday((t_addr != 0 ? &t : NULL),
736                             (tz_addr != 0 ? &tz : NULL));
737   int err = errno;
738
739   if (WITH_TRACE && ppc_trace[trace_os_emul])
740     printf_filtered ("0x%lx, 0x%lx", (long)t_addr, (long)tz_addr);
741
742   SYS(gettimeofday);
743   emul_write_status(processor, status, err);
744   if (status == 0) {
745     if (t_addr != 0)
746       write_timeval(t_addr, t, processor, cia);
747     if (tz_addr != 0)
748       write_timezone(tz_addr, tz, processor, cia);
749   }
750 }
751 #endif
752
753 #ifndef HAVE_GETRUSAGE
754 #define do_getrusage 0
755 #else
756 static void
757 do_getrusage(os_emul_data *emul,
758              unsigned call,
759              const int arg0,
760              cpu *processor,
761              unsigned_word cia)
762 {
763   int who = cpu_registers(processor)->gpr[arg0];
764   unsigned_word rusage_addr = cpu_registers(processor)->gpr[arg0+1];
765   struct rusage rusage;
766   int status = getrusage(who, (rusage_addr != 0 ? &rusage : NULL));
767   int err = errno;
768
769   if (WITH_TRACE && ppc_trace[trace_os_emul])
770     printf_filtered ("%d, 0x%lx", who, (long)rusage_addr);
771
772   SYS(getrusage);
773   emul_write_status(processor, status, err);
774   if (status == 0) {
775     if (rusage_addr != 0)
776       write_rusage(rusage_addr, rusage, processor, cia);
777   }
778 }
779 #endif
780
781
782 #ifndef HAVE_FSTATFS
783 #define do_fstatfs 0
784 #else
785 static void
786 do_fstatfs(os_emul_data *emul,
787            unsigned call,
788            const int arg0,
789            cpu *processor,
790            unsigned_word cia)
791 {
792   int fd = cpu_registers(processor)->gpr[arg0];
793   unsigned_word buf_addr = cpu_registers(processor)->gpr[arg0+1];
794   struct statfs buf;
795   int status;
796
797   if (WITH_TRACE && ppc_trace[trace_os_emul])
798     printf_filtered ("%d, 0x%lx", fd, (long)buf_addr);
799
800   SYS(fstatfs);
801   status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf));
802   emul_write_status(processor, status, errno);
803   if (status == 0) {
804     if (buf_addr != 0)
805       write_statfs(buf_addr, buf, processor, cia);
806   }
807 }
808 #endif
809
810 #ifndef HAVE_STAT
811 #define do_stat 0
812 #else
813 static void
814 do_stat(os_emul_data *emul,
815         unsigned call,
816         const int arg0,
817         cpu *processor,
818         unsigned_word cia)
819 {
820   char path_buf[PATH_MAX];
821   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
822   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
823   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
824   struct stat buf;
825   int status;
826 #ifdef SYS_stat
827   SYS(stat);
828 #endif
829   status = stat(path, &buf);
830   emul_write_status(processor, status, errno);
831   if (status == 0)
832     write_stat(stat_buf_addr, buf, processor, cia);
833 }
834 #endif
835
836 #ifndef HAVE_FSTAT
837 #define do_fstat 0
838 #else
839 static void
840 do_fstat(os_emul_data *emul,
841          unsigned call,
842          const int arg0,
843          cpu *processor,
844          unsigned_word cia)
845 {
846   int fd = cpu_registers(processor)->gpr[arg0];
847   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
848   struct stat buf;
849   int status;
850 #ifdef SYS_fstat
851   SYS(fstat);
852 #endif
853   /* Can't combine these statements, cuz fstat sets errno. */
854   status = fstat(fd, &buf);
855   emul_write_status(processor, status, errno);
856   write_stat(stat_buf_addr, buf, processor, cia);
857 }
858 #endif
859
860 #ifndef HAVE_LSTAT
861 #define do_lstat 0
862 #else
863 static void
864 do_lstat(os_emul_data *emul,
865          unsigned call,
866          const int arg0,
867          cpu *processor,
868          unsigned_word cia)
869 {
870   char path_buf[PATH_MAX];
871   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
872   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
873   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
874   struct stat buf;
875   int status;
876 #ifdef SYS_lstat
877   SYS(lstat);
878 #endif
879   /* Can't combine these statements, cuz lstat sets errno. */
880   status = lstat(path, &buf);
881   emul_write_status(processor, status, errno);
882   write_stat(stat_buf_addr, buf, processor, cia);
883 }
884 #endif
885
886 #ifndef HAVE_GETDIRENTRIES
887 #define do_getdirentries 0
888 #else
889 static void
890 do_getdirentries(os_emul_data *emul,
891                  unsigned call,
892                  const int arg0,
893                  cpu *processor,
894                  unsigned_word cia)
895 {
896   int fd = cpu_registers(processor)->gpr[arg0];
897   unsigned_word buf_addr = cpu_registers(processor)->gpr[arg0+1];
898   char *buf;
899   int nbytes = cpu_registers(processor)->gpr[arg0+2];
900   unsigned_word basep_addr = cpu_registers(processor)->gpr[arg0+3];
901   long basep;
902   int status;
903 #ifdef SYS_getdirentries
904   SYS(getdirentries);
905 #endif
906   if (buf_addr != 0 && nbytes >= 0)
907     buf = zalloc(nbytes);
908   else
909     buf = NULL;
910   status = getdirentries(fd,
911                          (buf_addr == 0 ? NULL : buf),
912                          nbytes,
913                          (basep_addr == 0 ? NULL : &basep));
914   emul_write_status(processor, status, errno);
915   if (basep_addr != 0)
916     emul_write_word(basep_addr, basep, processor, cia);
917   if (status > 0)
918     write_direntries(buf_addr, buf, status, processor, cia);
919   if (buf != NULL)
920     zfree(buf);
921 }
922 #endif
923
924
925 static void
926 do___syscall(os_emul_data *emul,
927              unsigned call,
928              const int arg0,
929              cpu *processor,
930              unsigned_word cia)
931 {
932   SYS(__syscall);
933   emul_do_system_call(emul,
934                       emul->syscalls,
935                       cpu_registers(processor)->gpr[arg0],
936                       arg0 + 1,
937                       processor,
938                       cia);
939 }
940
941 #ifndef HAVE_LSEEK
942 #define do_lseek 0
943 #else
944 static void
945 do_lseek(os_emul_data *emul,
946          unsigned call,
947          const int arg0,
948          cpu *processor,
949          unsigned_word cia)
950 {
951   int fildes = cpu_registers(processor)->gpr[arg0];
952   off_t offset = emul_read_gpr64(processor, arg0+2);
953   int whence = cpu_registers(processor)->gpr[arg0+4];
954   off_t status;
955   SYS(lseek);
956   status = lseek(fildes, offset, whence);
957   if (status == -1)
958     emul_write_status(processor, -1, errno);
959   else {
960     emul_write_status(processor, 0, 0); /* success */
961     emul_write_gpr64(processor, 3, status);
962   }
963 }
964 #endif
965
966 static void
967 do___sysctl(os_emul_data *emul,
968             unsigned call,
969             const int arg0,
970             cpu *processor,
971             unsigned_word cia)
972 {
973   /* call the arguments by their real name */
974   unsigned_word name = cpu_registers(processor)->gpr[arg0];
975   natural_word namelen = cpu_registers(processor)->gpr[arg0+1];
976   unsigned_word oldp = cpu_registers(processor)->gpr[arg0+2];
977   unsigned_word oldlenp = cpu_registers(processor)->gpr[arg0+3];
978   natural_word oldlen;
979   natural_word mib;
980   natural_word int_val;
981   SYS(__sysctl);
982
983   /* pluck out the management information base id */
984   if (namelen < 1)
985     error("system_call()SYS___sysctl bad name[0]\n");
986   mib = vm_data_map_read_word(cpu_data_map(processor),
987                               name,
988                               processor,
989                               cia);
990   name += sizeof(mib);
991
992   /* see what to do with it ... */
993   switch ((int)mib) {
994   case 6/*CTL_HW*/:
995 #if WITH_NetBSD_HOST && (CTL_HW != 6)
996 #  error "CTL_HW"
997 #endif
998     if (namelen < 2)
999       error("system_call()SYS___sysctl - CTL_HW - bad name[1]\n");
1000     mib = vm_data_map_read_word(cpu_data_map(processor),
1001                                 name,
1002                                 processor,
1003                                 cia);
1004     name += sizeof(mib);
1005     switch ((int)mib) {
1006     case 7/*HW_PAGESIZE*/:
1007 #if WITH_NetBSD_HOST && (HW_PAGESIZE != 7)
1008 #  error "HW_PAGESIZE"
1009 #endif
1010       oldlen = vm_data_map_read_word(cpu_data_map(processor),
1011                                      oldlenp,
1012                                      processor,
1013                                      cia);
1014       if (sizeof(natural_word) > oldlen)
1015         error("system_call()sysctl - CTL_HW.HW_PAGESIZE - to small\n");
1016       int_val = 8192;
1017       oldlen = sizeof(int_val);
1018       emul_write_word(oldp, int_val, processor, cia);
1019       emul_write_word(oldlenp, oldlen, processor, cia);
1020       break;
1021     default:
1022       error("sysctl() CTL_HW.%d unknown\n", mib);
1023       break;
1024     }
1025     break;
1026   default:
1027     error("sysctl() name[0]=%d unknown\n", (int)mib);
1028     break;
1029   }
1030   emul_write_status(processor, 0, 0); /* always succeed */
1031 }
1032
1033
1034
1035 static emul_syscall_descriptor netbsd_descriptors[] = {
1036   /* 0 */ { 0, "syscall" },
1037   /* 1 */ { do_exit, "exit" },
1038   /* 2 */ { 0, "fork" },
1039   /* 3 */ { do_read, "read" },
1040   /* 4 */ { do_write, "write" },
1041   /* 5 */ { do_open, "open" },
1042   /* 6 */ { do_close, "close" },
1043   /* 7 */ { 0, "wait4" },
1044   { 0, }, /* 8 is old creat */
1045   /* 9 */ { 0, "link" },
1046   /* 10 */ { 0, "unlink" },
1047   { 0, }, /* 11 is obsolete execv */
1048   /* 12 */ { 0, "chdir" },
1049   /* 13 */ { 0, "fchdir" },
1050   /* 14 */ { 0, "mknod" },
1051   /* 15 */ { 0, "chmod" },
1052   /* 16 */ { 0, "chown" },
1053   /* 17 */ { do_break, "break" },
1054   /* 18 */ { 0, "getfsstat" },
1055   { 0, }, /* 19 is old lseek */
1056   /* 20 */ { do_getpid, "getpid" },
1057   /* 21 */ { 0, "mount" },
1058   /* 22 */ { 0, "unmount" },
1059   /* 23 */ { 0, "setuid" },
1060   /* 24 */ { do_getuid, "getuid" },
1061   /* 25 */ { do_geteuid, "geteuid" },
1062   /* 26 */ { 0, "ptrace" },
1063   /* 27 */ { 0, "recvmsg" },
1064   /* 28 */ { 0, "sendmsg" },
1065   /* 29 */ { 0, "recvfrom" },
1066   /* 30 */ { 0, "accept" },
1067   /* 31 */ { 0, "getpeername" },
1068   /* 32 */ { 0, "getsockname" },
1069   /* 33 */ { 0, "access" },
1070   /* 34 */ { 0, "chflags" },
1071   /* 35 */ { 0, "fchflags" },
1072   /* 36 */ { 0, "sync" },
1073   /* 37 */ { do_kill, "kill" },
1074   { 0, }, /* 38 is old stat */
1075   /* 39 */ { 0, "getppid" },
1076   { 0, }, /* 40 is old lstat */
1077   /* 41 */ { do_dup, "dup" },
1078   /* 42 */ { 0, "pipe" },
1079   /* 43 */ { do_getegid, "getegid" },
1080   /* 44 */ { 0, "profil" },
1081   /* 45 */ { 0, "ktrace" },
1082   /* 46 */ { 0, "sigaction" },
1083   /* 47 */ { do_getgid, "getgid" },
1084   /* 48 */ { do_sigprocmask, "sigprocmask" },
1085   /* 49 */ { 0, "getlogin" },
1086   /* 50 */ { 0, "setlogin" },
1087   /* 51 */ { 0, "acct" },
1088   /* 52 */ { 0, "sigpending" },
1089   /* 53 */ { 0, "sigaltstack" },
1090   /* 54 */ { do_ioctl, "ioctl" },
1091   /* 55 */ { 0, "reboot" },
1092   /* 56 */ { 0, "revoke" },
1093   /* 57 */ { 0, "symlink" },
1094   /* 58 */ { 0, "readlink" },
1095   /* 59 */ { 0, "execve" },
1096   /* 60 */ { do_umask, "umask" },
1097   /* 61 */ { 0, "chroot" },
1098   { 0, }, /* 62 is old fstat */
1099   { 0, }, /* 63 is old getkerninfo */
1100   { 0, }, /* 64 is old getpagesize */
1101   /* 65 */ { 0, "msync" },
1102   /* 66 */ { 0, "vfork" },
1103   { 0, }, /* 67 is obsolete vread */
1104   { 0, }, /* 68 is obsolete vwrite */
1105   /* 69 */ { 0, "sbrk" },
1106   /* 70 */ { 0, "sstk" },
1107   { 0, }, /* 71 is old mmap */
1108   /* 72 */ { 0, "vadvise" },
1109   /* 73 */ { 0, "munmap" },
1110   /* 74 */ { 0, "mprotect" },
1111   /* 75 */ { 0, "madvise" },
1112   { 0, }, /* 76 is obsolete vhangup */
1113   { 0, }, /* 77 is obsolete vlimit */
1114   /* 78 */ { 0, "mincore" },
1115   /* 79 */ { 0, "getgroups" },
1116   /* 80 */ { 0, "setgroups" },
1117   /* 81 */ { 0, "getpgrp" },
1118   /* 82 */ { 0, "setpgid" },
1119   /* 83 */ { 0, "setitimer" },
1120   { 0, }, /* 84 is old wait */
1121   /* 85 */ { 0, "swapon" },
1122   /* 86 */ { 0, "getitimer" },
1123   { 0, }, /* 87 is old gethostname */
1124   { 0, }, /* 88 is old sethostname */
1125   { 0, }, /* 89 is old getdtablesize */
1126   { do_dup2, "dup2" },
1127   { 0, }, /* 91 */
1128   /* 92 */ { do_fcntl, "fcntl" },
1129   /* 93 */ { 0, "select" },
1130   { 0, }, /* 94 */
1131   /* 95 */ { 0, "fsync" },
1132   /* 96 */ { 0, "setpriority" },
1133   /* 97 */ { 0, "socket" },
1134   /* 98 */ { 0, "connect" },
1135   { 0, }, /* 99 is old accept */
1136   /* 100 */ { 0, "getpriority" },
1137   { 0, }, /* 101 is old send */
1138   { 0, }, /* 102 is old recv */
1139   /* 103 */ { 0, "sigreturn" },
1140   /* 104 */ { 0, "bind" },
1141   /* 105 */ { 0, "setsockopt" },
1142   /* 106 */ { 0, "listen" },
1143   { 0, }, /* 107 is obsolete vtimes */
1144   { 0, }, /* 108 is old sigvec */
1145   { 0, }, /* 109 is old sigblock */
1146   { 0, }, /* 110 is old sigsetmask */
1147   /* 111 */ { 0, "sigsuspend" },
1148   { 0, }, /* 112 is old sigstack */
1149   { 0, }, /* 113 is old recvmsg */
1150   { 0, }, /* 114 is old sendmsg */
1151   /* - is obsolete vtrace */ { 0, "vtrace       115" },
1152   /* 116 */ { do_gettimeofday, "gettimeofday" },
1153   /* 117 */ { do_getrusage, "getrusage" },
1154   /* 118 */ { 0, "getsockopt" },
1155   /* 119 */ { 0, "resuba" },
1156   /* 120 */ { 0, "readv" },
1157   /* 121 */ { 0, "writev" },
1158   /* 122 */ { 0, "settimeofday" },
1159   /* 123 */ { 0, "fchown" },
1160   /* 124 */ { 0, "fchmod" },
1161   { 0, }, /* 125 is old recvfrom */
1162   { 0, }, /* 126 is old setreuid */
1163   { 0, }, /* 127 is old setregid */
1164   /* 128 */ { 0, "rename" },
1165   { 0, }, /* 129 is old truncate */
1166   { 0, }, /* 130 is old ftruncate */
1167   /* 131 */ { 0, "flock" },
1168   /* 132 */ { 0, "mkfifo" },
1169   /* 133 */ { 0, "sendto" },
1170   /* 134 */ { 0, "shutdown" },
1171   /* 135 */ { 0, "socketpair" },
1172   /* 136 */ { 0, "mkdir" },
1173   /* 137 */ { 0, "rmdir" },
1174   /* 138 */ { 0, "utimes" },
1175   { 0, }, /* 139 is obsolete 4.2 sigreturn */
1176   /* 140 */ { 0, "adjtime" },
1177   { 0, }, /* 141 is old getpeername */
1178   { 0, }, /* 142 is old gethostid */
1179   { 0, }, /* 143 is old sethostid */
1180   { 0, }, /* 144 is old getrlimit */
1181   { 0, }, /* 145 is old setrlimit */
1182   { 0, }, /* 146 is old killpg */
1183   /* 147 */ { 0, "setsid" },
1184   /* 148 */ { 0, "quotactl" },
1185   { 0, }, /* 149 is old quota */
1186   { 0, }, /* 150 is old getsockname */
1187   { 0, }, /* 151 */
1188   { 0, }, /* 152 */
1189   { 0, }, /* 153 */
1190   { 0, }, /* 154 */
1191   /* 155 */ { 0, "nfssvc" },
1192   { 0, }, /* 156 is old getdirentries */
1193   /* 157 */ { 0, "statfs" },
1194   /* 158 */ { do_fstatfs, "fstatfs" },
1195   { 0, }, /* 159 */
1196   { 0, }, /* 160 */
1197   /* 161 */ { 0, "getfh" },
1198   { 0, }, /* 162 is old getdomainname */
1199   { 0, }, /* 163 is old setdomainname */
1200   { 0, }, /* 164 is old uname */
1201   /* 165 */ { 0, "sysarch" },
1202   { 0, }, /* 166 */
1203   { 0, }, /* 167 */
1204   { 0, }, /* 168 */
1205   /* 169 */ { 0, "semsys" },
1206   /* 170 */ { 0, "msgsys" },
1207   /* 171 */ { 0, "shmsys" },
1208   { 0, }, /* 172 */
1209   { 0, }, /* 173 */
1210   { 0, }, /* 174 */
1211   { 0, }, /* 175 */
1212   { 0, }, /* 176 */
1213   { 0, }, /* 177 */
1214   { 0, }, /* 178 */
1215   { 0, }, /* 179 */
1216   { 0, }, /* 180 */
1217   /* 181 */ { 0, "setgid" },
1218   /* 182 */ { 0, "setegid" },
1219   /* 183 */ { 0, "seteuid" },
1220   /* 184 */ { 0, "lfs_bmapv" },
1221   /* 185 */ { 0, "lfs_markv" },
1222   /* 186 */ { 0, "lfs_segclean" },
1223   /* 187 */ { 0, "lfs_segwait" },
1224   /* 188 */ { do_stat, "stat" },
1225   /* 189 */ { do_fstat, "fstat" },
1226   /* 190 */ { do_lstat, "lstat" },
1227   /* 191 */ { 0, "pathconf" },
1228   /* 192 */ { 0, "fpathconf" },
1229   { 0, }, /* 193 */
1230   /* 194 */ { 0, "getrlimit" },
1231   /* 195 */ { 0, "setrlimit" },
1232   /* 196 */ { do_getdirentries, "getdirentries" },
1233   /* 197 */ { 0, "mmap" },
1234   /* 198 */ { do___syscall, "__syscall" },
1235   /* 199 */ { do_lseek, "lseek" },
1236   /* 200 */ { 0, "truncate" },
1237   /* 201 */ { 0, "ftruncate" },
1238   /* 202 */ { do___sysctl, "__sysctl" },
1239   /* 203 */ { 0, "mlock" },
1240   /* 204 */ { 0, "munlock" },
1241 };
1242
1243 static char *(netbsd_error_names[]) = {
1244   /* 0 */ "ESUCCESS",
1245   /* 1 */ "EPERM",
1246   /* 2 */ "ENOENT",
1247   /* 3 */ "ESRCH",
1248   /* 4 */ "EINTR",
1249   /* 5 */ "EIO",
1250   /* 6 */ "ENXIO",
1251   /* 7 */ "E2BIG",
1252   /* 8 */ "ENOEXEC",
1253   /* 9 */ "EBADF",
1254   /* 10 */ "ECHILD",
1255   /* 11 */ "EDEADLK",
1256   /* 12 */ "ENOMEM",
1257   /* 13 */ "EACCES",
1258   /* 14 */ "EFAULT",
1259   /* 15 */ "ENOTBLK",
1260   /* 16 */ "EBUSY",
1261   /* 17 */ "EEXIST",
1262   /* 18 */ "EXDEV",
1263   /* 19 */ "ENODEV",
1264   /* 20 */ "ENOTDIR",
1265   /* 21 */ "EISDIR",
1266   /* 22 */ "EINVAL",
1267   /* 23 */ "ENFILE",
1268   /* 24 */ "EMFILE",
1269   /* 25 */ "ENOTTY",
1270   /* 26 */ "ETXTBSY",
1271   /* 27 */ "EFBIG",
1272   /* 28 */ "ENOSPC",
1273   /* 29 */ "ESPIPE",
1274   /* 30 */ "EROFS",
1275   /* 31 */ "EMLINK",
1276   /* 32 */ "EPIPE",
1277   /* 33 */ "EDOM",
1278   /* 34 */ "ERANGE",
1279   /* 35 */ "EAGAIN",
1280   /* 36 */ "EINPROGRESS",
1281   /* 37 */ "EALREADY",
1282   /* 38 */ "ENOTSOCK",
1283   /* 39 */ "EDESTADDRREQ",
1284   /* 40 */ "EMSGSIZE",
1285   /* 41 */ "EPROTOTYPE",
1286   /* 42 */ "ENOPROTOOPT",
1287   /* 43 */ "EPROTONOSUPPORT",
1288   /* 44 */ "ESOCKTNOSUPPORT",
1289   /* 45 */ "EOPNOTSUPP",
1290   /* 46 */ "EPFNOSUPPORT",
1291   /* 47 */ "EAFNOSUPPORT",
1292   /* 48 */ "EADDRINUSE",
1293   /* 49 */ "EADDRNOTAVAIL",
1294   /* 50 */ "ENETDOWN",
1295   /* 51 */ "ENETUNREACH",
1296   /* 52 */ "ENETRESET",
1297   /* 53 */ "ECONNABORTED",
1298   /* 54 */ "ECONNRESET",
1299   /* 55 */ "ENOBUFS",
1300   /* 56 */ "EISCONN",
1301   /* 57 */ "ENOTCONN",
1302   /* 58 */ "ESHUTDOWN",
1303   /* 59 */ "ETOOMANYREFS",
1304   /* 60 */ "ETIMEDOUT",
1305   /* 61 */ "ECONNREFUSED",
1306   /* 62 */ "ELOOP",
1307   /* 63 */ "ENAMETOOLONG",
1308   /* 64 */ "EHOSTDOWN",
1309   /* 65 */ "EHOSTUNREACH",
1310   /* 66 */ "ENOTEMPTY",
1311   /* 67 */ "EPROCLIM",
1312   /* 68 */ "EUSERS",
1313   /* 69 */ "EDQUOT",
1314   /* 70 */ "ESTALE",
1315   /* 71 */ "EREMOTE",
1316   /* 72 */ "EBADRPC",
1317   /* 73 */ "ERPCMISMATCH",
1318   /* 74 */ "EPROGUNAVAIL",
1319   /* 75 */ "EPROGMISMATCH",
1320   /* 76 */ "EPROCUNAVAIL",
1321   /* 77 */ "ENOLCK",
1322   /* 78 */ "ENOSYS",
1323   /* 79 */ "EFTYPE",
1324   /* 80 */ "EAUTH",
1325   /* 81 */ "ENEEDAUTH",
1326   /* 81 */ "ELAST",
1327 };
1328
1329 static char *(netbsd_signal_names[]) = {
1330   /* 0 */ 0,
1331   /* 1 */ "SIGHUP",
1332   /* 2 */ "SIGINT",
1333   /* 3 */ "SIGQUIT",
1334   /* 4 */ "SIGILL",
1335   /* 5 */ "SIGTRAP",
1336   /* 6 */ "SIGABRT",
1337   /* 7 */ "SIGEMT",
1338   /* 8 */ "SIGFPE",
1339   /* 9 */ "SIGKILL",
1340   /* 10 */ "SIGBUS",
1341   /* 11 */ "SIGSEGV",
1342   /* 12 */ "SIGSYS",
1343   /* 13 */ "SIGPIPE",
1344   /* 14 */ "SIGALRM",
1345   /* 15 */ "SIGTERM",
1346   /* 16 */ "SIGURG",
1347   /* 17 */ "SIGSTOP",
1348   /* 18 */ "SIGTSTP",
1349   /* 19 */ "SIGCONT",
1350   /* 20 */ "SIGCHLD",
1351   /* 21 */ "SIGTTIN",
1352   /* 22 */ "SIGTTOU",
1353   /* 23 */ "SIGIO",
1354   /* 24 */ "SIGXCPU",
1355   /* 25 */ "SIGXFSZ",
1356   /* 26 */ "SIGVTALRM",
1357   /* 27 */ "SIGPROF",
1358   /* 28 */ "SIGWINCH",
1359   /* 29 */ "SIGINFO",
1360   /* 30 */ "SIGUSR1",
1361   /* 31 */ "SIGUSR2",
1362 };
1363
1364 static emul_syscall emul_netbsd_syscalls = {
1365   netbsd_descriptors,
1366   sizeof(netbsd_descriptors) / sizeof(netbsd_descriptors[0]),
1367   netbsd_error_names,
1368   sizeof(netbsd_error_names) / sizeof(netbsd_error_names[0]),
1369   netbsd_signal_names,
1370   sizeof(netbsd_signal_names) / sizeof(netbsd_signal_names[0]),
1371 };
1372
1373
1374 /* NetBSD's os_emul interface, most are just passed on to the generic
1375    syscall stuff */
1376
1377 static os_emul_data *
1378 emul_netbsd_create(device *root,
1379                    bfd *image,
1380                    const char *name)
1381 {
1382   unsigned_word top_of_stack;
1383   unsigned stack_size;
1384   int elf_binary;
1385   os_emul_data *bsd_data;
1386   device *vm;
1387
1388   /* check that this emulation is really for us */
1389   if (name != NULL && strcmp(name, "netbsd") != 0)
1390     return NULL;
1391   if (image == NULL)
1392     return NULL;
1393
1394
1395   /* merge any emulation specific entries into the device tree */
1396
1397   /* establish a few defaults */
1398   if (image->xvec->flavour == bfd_target_elf_flavour) {
1399     elf_binary = 1;
1400     top_of_stack = 0xe0000000;
1401     stack_size =   0x00100000;
1402   }
1403   else {
1404     elf_binary = 0;
1405     top_of_stack = 0x20000000;
1406     stack_size =   0x00100000;
1407   }
1408
1409   /* options */
1410   emul_add_tree_options(root, image, "netbsd",
1411                         (WITH_ENVIRONMENT == USER_ENVIRONMENT
1412                          ? "user" : "virtual"),
1413                         0 /*oea-interrupt-prefix*/);
1414
1415   /* virtual memory - handles growth of stack/heap */
1416   vm = tree_parse(root, "/openprom/vm");
1417   tree_parse(vm, "./stack-base 0x%lx",
1418              (unsigned long)(top_of_stack - stack_size));
1419   tree_parse(vm, "./nr-bytes 0x%x", stack_size);
1420
1421   tree_parse(root, "/openprom/vm/map-binary/file-name %s",
1422              bfd_get_filename(image));
1423
1424   /* finish the init */
1425   tree_parse(root, "/openprom/init/register/pc 0x%lx",
1426              (unsigned long)bfd_get_start_address(image));
1427   tree_parse(root, "/openprom/init/register/sp 0x%lx",
1428              (unsigned long)top_of_stack);
1429   tree_parse(root, "/openprom/init/register/msr 0x%x",
1430              ((tree_find_boolean_property(root, "/options/little-endian?")
1431                ? msr_little_endian_mode
1432                : 0)
1433               | (tree_find_boolean_property(root, "/openprom/options/floating-point?")
1434                  ? (msr_floating_point_available
1435                     | msr_floating_point_exception_mode_0
1436                     | msr_floating_point_exception_mode_1)
1437                  : 0)));
1438   tree_parse(root, "/openprom/init/stack/stack-type %s",
1439              (elf_binary ? "ppc-elf" : "ppc-xcoff"));
1440
1441   /* finally our emulation data */
1442   bsd_data = ZALLOC(os_emul_data);
1443   bsd_data->vm = vm;
1444   bsd_data->syscalls = &emul_netbsd_syscalls;
1445   return bsd_data;
1446 }
1447
1448 static void
1449 emul_netbsd_init(os_emul_data *emul_data,
1450                  int nr_cpus)
1451 {
1452   /* nothing yet */
1453 }
1454
1455 static void
1456 emul_netbsd_system_call(cpu *processor,
1457                         unsigned_word cia,
1458                         os_emul_data *emul_data)
1459 {
1460   emul_do_system_call(emul_data,
1461                       emul_data->syscalls,
1462                       cpu_registers(processor)->gpr[0],
1463                       3, /*r3 contains arg0*/
1464                       processor,
1465                       cia);
1466 }
1467
1468 const os_emul emul_netbsd = {
1469   "netbsd",
1470   emul_netbsd_create,
1471   emul_netbsd_init,
1472   emul_netbsd_system_call,
1473   0, /*instruction_call*/
1474   0 /*data*/
1475 };
1476
1477 #endif  /* _EMUL_NETBSD_C_ */