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