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