xref: /netbsd-src/external/gpl3/gdb/dist/sim/ppc/emul_netbsd.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
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 <dirent.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     free(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 
297 /* File descriptors 0, 1, and 2 should not be closed.  fd_closed[]
298    tracks whether these descriptors have been closed in do_close()
299    below.  */
300 
301 static int fd_closed[3];
302 
303 /* Check for some occurrences of bad file descriptors.  We only check
304    whether fd 0, 1, or 2 are "closed".  By "closed" we mean that these
305    descriptors aren't actually closed, but are considered to be closed
306    by this layer.
307 
308    Other checks are performed by the underlying OS call.  */
309 
310 static int
311 fdbad (int fd)
312 {
313   if (fd >=0 && fd <= 2 && fd_closed[fd])
314     {
315       errno = EBADF;
316       return -1;
317     }
318   return 0;
319 }
320 
321 static void
322 do_exit(os_emul_data *emul,
323 	unsigned call,
324 	const int arg0,
325 	cpu *processor,
326 	unsigned_word cia)
327 {
328   int status = (int)cpu_registers(processor)->gpr[arg0];
329   SYS(exit);
330   if (WITH_TRACE && ppc_trace[trace_os_emul])
331     printf_filtered ("%d)\n", status);
332 
333   cpu_halt(processor, cia, was_exited, status);
334 }
335 
336 
337 static void
338 do_read(os_emul_data *emul,
339 	unsigned call,
340 	const int arg0,
341 	cpu *processor,
342 	unsigned_word cia)
343 {
344   void *scratch_buffer;
345   int d = (int)cpu_registers(processor)->gpr[arg0];
346   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
347   int nbytes = cpu_registers(processor)->gpr[arg0+2];
348   int status;
349   SYS(read);
350 
351   if (WITH_TRACE && ppc_trace[trace_os_emul])
352     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
353 
354   /* get a tempoary bufer */
355   scratch_buffer = zalloc(nbytes);
356 
357   /* check if buffer exists by reading it */
358   emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
359 
360   /* read */
361 #if 0
362   if (d == 0) {
363     status = fread (scratch_buffer, 1, nbytes, stdin);
364     if (status == 0 && ferror (stdin))
365       status = -1;
366   }
367 #endif
368   status = fdbad (d);
369   if (status == 0)
370     status = read (d, scratch_buffer, nbytes);
371 
372   emul_write_status(processor, status, errno);
373   if (status > 0)
374     emul_write_buffer(scratch_buffer, buf, status, processor, cia);
375 
376   free(scratch_buffer);
377 }
378 
379 
380 static void
381 do_write(os_emul_data *emul,
382 	 unsigned call,
383 	 const int arg0,
384 	 cpu *processor,
385 	 unsigned_word cia)
386 {
387   void *scratch_buffer = NULL;
388   int d = (int)cpu_registers(processor)->gpr[arg0];
389   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
390   int nbytes = cpu_registers(processor)->gpr[arg0+2];
391   int status;
392   SYS(write);
393 
394   if (WITH_TRACE && ppc_trace[trace_os_emul])
395     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
396 
397   /* get a tempoary bufer */
398   scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
399 
400   /* copy in */
401   emul_read_buffer(scratch_buffer, buf, nbytes,
402 		   processor, cia);
403 
404   /* write */
405   status = fdbad (d);
406   if (status == 0)
407     status = write(d, scratch_buffer, nbytes);
408 
409   emul_write_status(processor, status, errno);
410   free(scratch_buffer);
411 
412   flush_stdoutput();
413 }
414 
415 
416 static void
417 do_open(os_emul_data *emul,
418 	unsigned call,
419 	const int arg0,
420 	cpu *processor,
421 	unsigned_word cia)
422 {
423   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
424   char path_buf[PATH_MAX];
425   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
426   int flags = (int)cpu_registers(processor)->gpr[arg0+1];
427   int mode = (int)cpu_registers(processor)->gpr[arg0+2];
428   int hostflags;
429   int status;
430 
431   if (WITH_TRACE && ppc_trace[trace_os_emul])
432     printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
433 
434   SYS(open);
435 
436   /* Do some translation on 'flags' to match it to the host's version.  */
437   /* These flag values were taken from the NetBSD 1.4 header files.  */
438   if ((flags & 3) == 0)
439     hostflags = O_RDONLY;
440   else if ((flags & 3) == 1)
441     hostflags = O_WRONLY;
442   else
443     hostflags = O_RDWR;
444   if (flags & 0x00000008)
445     hostflags |= O_APPEND;
446   if (flags & 0x00000200)
447     hostflags |= O_CREAT;
448   if (flags & 0x00000400)
449     hostflags |= O_TRUNC;
450   if (flags & 0x00000800)
451     hostflags |= O_EXCL;
452 
453   /* Can't combine these statements, cuz open sets errno. */
454   status = open(path, hostflags, mode);
455   emul_write_status(processor, status, errno);
456 }
457 
458 
459 static void
460 do_close(os_emul_data *emul,
461 	 unsigned call,
462 	 const int arg0,
463 	 cpu *processor,
464 	 unsigned_word cia)
465 {
466   int d = (int)cpu_registers(processor)->gpr[arg0];
467   int status;
468 
469   if (WITH_TRACE && ppc_trace[trace_os_emul])
470     printf_filtered ("%d", d);
471 
472   SYS(close);
473 
474   status = fdbad (d);
475   if (status == 0)
476     {
477       /* Do not close stdin, stdout, or stderr. GDB may still need access to
478 	 these descriptors.  */
479       if (d == 0 || d == 1 || d == 2)
480 	{
481 	  fd_closed[d] = 1;
482 	  status = 0;
483 	}
484       else
485 	status = close(d);
486     }
487 
488   emul_write_status(processor, status, errno);
489 }
490 
491 
492 static void
493 do_break(os_emul_data *emul,
494 	 unsigned call,
495 	 const int arg0,
496 	 cpu *processor,
497 	 unsigned_word cia)
498 {
499   /* just pass this onto the `vm' device */
500   unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
501   int status;
502 
503   if (WITH_TRACE && ppc_trace[trace_os_emul])
504     printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
505 
506   SYS(break);
507   status = device_ioctl(emul->vm,
508 			processor,
509 			cia,
510 			device_ioctl_break,
511 			new_break); /*ioctl-data*/
512   emul_write_status(processor, 0, status);
513 }
514 
515 
516 #ifndef HAVE_GETPID
517 #define do_getpid 0
518 #else
519 static void
520 do_getpid(os_emul_data *emul,
521 	  unsigned call,
522 	  const int arg0,
523 	  cpu *processor,
524 	  unsigned_word cia)
525 {
526   SYS(getpid);
527   emul_write_status(processor, (int)getpid(), 0);
528 }
529 #endif
530 
531 #ifndef HAVE_GETUID
532 #define do_getuid 0
533 #else
534 static void
535 do_getuid(os_emul_data *emul,
536 	  unsigned call,
537 	  const int arg0,
538 	  cpu *processor,
539 	  unsigned_word cia)
540 {
541   SYS(getuid);
542   emul_write_status(processor, (int)getuid(), 0);
543 }
544 #endif
545 
546 #ifndef HAVE_GETEUID
547 #define do_geteuid 0
548 #else
549 static void
550 do_geteuid(os_emul_data *emul,
551 	   unsigned call,
552 	   const int arg0,
553 	   cpu *processor,
554 	   unsigned_word cia)
555 {
556   SYS(geteuid);
557   emul_write_status(processor, (int)geteuid(), 0);
558 }
559 #endif
560 
561 #ifndef HAVE_KILL
562 #define do_kill 0
563 #else
564 static void
565 do_kill(os_emul_data *emul,
566 	unsigned call,
567 	const int arg0,
568 	cpu *processor,
569 	unsigned_word cia)
570 {
571   pid_t pid = cpu_registers(processor)->gpr[arg0];
572   int sig = cpu_registers(processor)->gpr[arg0+1];
573 
574   if (WITH_TRACE && ppc_trace[trace_os_emul])
575     printf_filtered ("%d, %d", (int)pid, sig);
576 
577   SYS(kill);
578   printf_filtered("SYS_kill at 0x%lx - more to this than just being killed\n",
579 		  (long)cia);
580   cpu_halt(processor, cia, was_signalled, sig);
581 }
582 #endif
583 
584 #ifndef HAVE_DUP
585 #define do_dup 0
586 #else
587 static void
588 do_dup(os_emul_data *emul,
589        unsigned call,
590        const int arg0,
591        cpu *processor,
592        unsigned_word cia)
593 {
594   int oldd = cpu_registers(processor)->gpr[arg0];
595   int status = (fdbad (oldd) < 0) ? -1 : dup(oldd);
596   int err = errno;
597 
598   if (WITH_TRACE && ppc_trace[trace_os_emul])
599     printf_filtered ("%d", oldd);
600 
601   SYS(dup);
602   emul_write_status(processor, status, err);
603 }
604 #endif
605 
606 #ifndef HAVE_GETEGID
607 #define do_getegid 0
608 #else
609 static void
610 do_getegid(os_emul_data *emul,
611 	   unsigned call,
612 	   const int arg0,
613 	   cpu *processor,
614 	   unsigned_word cia)
615 {
616   SYS(getegid);
617   emul_write_status(processor, (int)getegid(), 0);
618 }
619 #endif
620 
621 #ifndef HAVE_GETGID
622 #define do_getgid 0
623 #else
624 static void
625 do_getgid(os_emul_data *emul,
626 	  unsigned call,
627 	  const int arg0,
628 	  cpu *processor,
629 	  unsigned_word cia)
630 {
631   SYS(getgid);
632   emul_write_status(processor, (int)getgid(), 0);
633 }
634 #endif
635 
636 #ifndef HAVE_SIGPROCMASK
637 #define do_sigprocmask 0
638 #else
639 static void
640 do_sigprocmask(os_emul_data *emul,
641 	       unsigned call,
642 	       const int arg0,
643 	       cpu *processor,
644 	       unsigned_word cia)
645 {
646   natural_word how = cpu_registers(processor)->gpr[arg0];
647   unsigned_word set = cpu_registers(processor)->gpr[arg0+1];
648   unsigned_word oset = cpu_registers(processor)->gpr[arg0+2];
649 #ifdef SYS_sigprocmask
650   SYS(sigprocmask);
651 #endif
652 
653   if (WITH_TRACE && ppc_trace[trace_os_emul])
654     printf_filtered ("%ld, 0x%ld, 0x%ld", (long)how, (long)set, (long)oset);
655 
656   emul_write_status(processor, 0, 0);
657   cpu_registers(processor)->gpr[4] = set;
658 }
659 #endif
660 
661 #ifndef HAVE_IOCTL
662 #define do_ioctl 0
663 #else
664 static void
665 do_ioctl(os_emul_data *emul,
666 	 unsigned call,
667 	 const int arg0,
668 	 cpu *processor,
669 	 unsigned_word cia)
670 {
671   int d = cpu_registers(processor)->gpr[arg0];
672   unsigned request = cpu_registers(processor)->gpr[arg0+1];
673   unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
674 
675 #if !WITH_NetBSD_HOST
676   cpu_registers(processor)->gpr[arg0] = 0; /* just succeed */
677 #else
678   unsigned dir = request & IOC_DIRMASK;
679   int status;
680   SYS(ioctl);
681   /* what we haven't done */
682   if (dir & IOC_IN /* write into the io device */
683       || dir & IOC_OUT
684       || !(dir & IOC_VOID))
685     error("do_ioctl() read or write of parameter not implemented\n");
686   status = fdbad (d);
687   if (status == 0)
688     status = ioctl(d, request, NULL);
689   emul_write_status(processor, status, errno);
690 #endif
691 
692   if (WITH_TRACE && ppc_trace[trace_os_emul])
693     printf_filtered ("%d, 0x%x, 0x%lx", d, request, (long)argp_addr);
694 }
695 #endif
696 
697 #ifndef HAVE_UMASK
698 #define do_umask 0
699 #else
700 static void
701 do_umask(os_emul_data *emul,
702 	 unsigned call,
703 	 const int arg0,
704 	 cpu *processor,
705 	 unsigned_word cia)
706 {
707   int mask = cpu_registers(processor)->gpr[arg0];
708 
709   if (WITH_TRACE && ppc_trace[trace_os_emul])
710     printf_filtered ("0%o", mask);
711 
712   SYS(umask);
713   emul_write_status(processor, umask(mask), 0);
714 }
715 #endif
716 
717 #ifndef HAVE_DUP2
718 #define do_dup2 0
719 #else
720 static void
721 do_dup2(os_emul_data *emul,
722 	unsigned call,
723 	const int arg0,
724 	cpu *processor,
725 	unsigned_word cia)
726 {
727   int oldd = cpu_registers(processor)->gpr[arg0];
728   int newd = cpu_registers(processor)->gpr[arg0+1];
729   int status = (fdbad (oldd) < 0) ? -1 : dup2(oldd, newd);
730   int err = errno;
731 
732   if (WITH_TRACE && ppc_trace[trace_os_emul])
733     printf_filtered ("%d, %d", oldd, newd);
734 
735   SYS(dup2);
736   emul_write_status(processor, status, err);
737 }
738 #endif
739 
740 #ifndef HAVE_FCNTL
741 #define do_fcntl 0
742 #else
743 static void
744 do_fcntl(os_emul_data *emul,
745 	 unsigned call,
746 	 const int arg0,
747 	 cpu *processor,
748 	 unsigned_word cia)
749 {
750   int fd = cpu_registers(processor)->gpr[arg0];
751   int cmd = cpu_registers(processor)->gpr[arg0+1];
752   int arg = cpu_registers(processor)->gpr[arg0+2];
753   int status;
754 
755   if (WITH_TRACE && ppc_trace[trace_os_emul])
756     printf_filtered ("%d, %d, %d", fd, cmd, arg);
757 
758   SYS(fcntl);
759   status = fdbad (fd);
760   if (status == 0)
761     status = fcntl(fd, cmd, arg);
762   emul_write_status(processor, status, errno);
763 }
764 #endif
765 
766 #ifndef HAVE_GETTIMEOFDAY
767 #define do_gettimeofday 0
768 #else
769 static void
770 do_gettimeofday(os_emul_data *emul,
771 		unsigned call,
772 		const int arg0,
773 		cpu *processor,
774 		unsigned_word cia)
775 {
776   unsigned_word t_addr = cpu_registers(processor)->gpr[arg0];
777   unsigned_word tz_addr = cpu_registers(processor)->gpr[arg0+1];
778   struct timeval t;
779   struct timezone tz;
780   int status = gettimeofday((t_addr != 0 ? &t : NULL),
781 			    (tz_addr != 0 ? &tz : NULL));
782   int err = errno;
783 
784   if (WITH_TRACE && ppc_trace[trace_os_emul])
785     printf_filtered ("0x%lx, 0x%lx", (long)t_addr, (long)tz_addr);
786 
787   SYS(__gettimeofday50);
788   emul_write_status(processor, status, err);
789   if (status == 0) {
790     if (t_addr != 0)
791       write_timeval(t_addr, t, processor, cia);
792     if (tz_addr != 0)
793       write_timezone(tz_addr, tz, processor, cia);
794   }
795 }
796 #endif
797 
798 #ifndef HAVE_GETRUSAGE
799 #define do_getrusage 0
800 #else
801 static void
802 do_getrusage(os_emul_data *emul,
803 	     unsigned call,
804 	     const int arg0,
805 	     cpu *processor,
806 	     unsigned_word cia)
807 {
808   int who = cpu_registers(processor)->gpr[arg0];
809   unsigned_word rusage_addr = cpu_registers(processor)->gpr[arg0+1];
810   struct rusage rusage;
811   int status = getrusage(who, (rusage_addr != 0 ? &rusage : NULL));
812   int err = errno;
813 
814   if (WITH_TRACE && ppc_trace[trace_os_emul])
815     printf_filtered ("%d, 0x%lx", who, (long)rusage_addr);
816 
817   SYS(__getrusage50);
818   emul_write_status(processor, status, err);
819   if (status == 0) {
820     if (rusage_addr != 0)
821       write_rusage(rusage_addr, rusage, processor, cia);
822   }
823 }
824 #endif
825 
826 
827 #ifndef HAVE_FSTATFS
828 #define do_fstatfs 0
829 #else
830 static void
831 do_fstatfs(os_emul_data *emul,
832 	   unsigned call,
833 	   const int arg0,
834 	   cpu *processor,
835 	   unsigned_word cia)
836 {
837   int fd = cpu_registers(processor)->gpr[arg0];
838   unsigned_word buf_addr = cpu_registers(processor)->gpr[arg0+1];
839   struct statfs buf;
840   int status;
841 
842   if (WITH_TRACE && ppc_trace[trace_os_emul])
843     printf_filtered ("%d, 0x%lx", fd, (long)buf_addr);
844 
845   SYS(fstatfs);
846   status = fdbad (fd);
847   if (status == 0)
848     status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf));
849   emul_write_status(processor, status, errno);
850   if (status == 0) {
851     if (buf_addr != 0)
852       write_statfs(buf_addr, buf, processor, cia);
853   }
854 }
855 #endif
856 
857 #ifndef HAVE_STAT
858 #define do_stat 0
859 #else
860 static void
861 do_stat(os_emul_data *emul,
862 	unsigned call,
863 	const int arg0,
864 	cpu *processor,
865 	unsigned_word cia)
866 {
867   char path_buf[PATH_MAX];
868   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
869   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
870   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
871   struct stat buf;
872   int status;
873 #ifdef SYS_stat
874   SYS(stat);
875 #endif
876   status = stat(path, &buf);
877   emul_write_status(processor, status, errno);
878   if (status == 0)
879     write_stat(stat_buf_addr, buf, processor, cia);
880 }
881 #endif
882 
883 #ifndef HAVE_FSTAT
884 #define do_fstat 0
885 #else
886 static void
887 do_fstat(os_emul_data *emul,
888 	 unsigned call,
889 	 const int arg0,
890 	 cpu *processor,
891 	 unsigned_word cia)
892 {
893   int fd = cpu_registers(processor)->gpr[arg0];
894   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
895   struct stat buf;
896   int status;
897 #ifdef SYS_fstat
898   SYS(fstat);
899 #endif
900   /* Can't combine these statements, cuz fstat sets errno. */
901   status = fdbad (fd);
902   if (status == 0)
903     status = fstat(fd, &buf);
904   emul_write_status(processor, status, errno);
905   write_stat(stat_buf_addr, buf, processor, cia);
906 }
907 #endif
908 
909 #ifndef HAVE_LSTAT
910 #define do_lstat 0
911 #else
912 static void
913 do_lstat(os_emul_data *emul,
914 	 unsigned call,
915 	 const int arg0,
916 	 cpu *processor,
917 	 unsigned_word cia)
918 {
919   char path_buf[PATH_MAX];
920   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
921   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
922   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
923   struct stat buf;
924   int status;
925 #ifdef SYS_lstat
926   SYS(lstat);
927 #endif
928   /* Can't combine these statements, cuz lstat sets errno. */
929   status = lstat(path, &buf);
930   emul_write_status(processor, status, errno);
931   write_stat(stat_buf_addr, buf, processor, cia);
932 }
933 #endif
934 
935 #ifndef HAVE_GETDIRENTRIES
936 #define do_getdirentries 0
937 #else
938 static void
939 do_getdirentries(os_emul_data *emul,
940 		 unsigned call,
941 		 const int arg0,
942 		 cpu *processor,
943 		 unsigned_word cia)
944 {
945   int fd = cpu_registers(processor)->gpr[arg0];
946   unsigned_word buf_addr = cpu_registers(processor)->gpr[arg0+1];
947   char *buf;
948   int nbytes = cpu_registers(processor)->gpr[arg0+2];
949   unsigned_word basep_addr = cpu_registers(processor)->gpr[arg0+3];
950   long basep;
951   int status;
952 #ifdef SYS_getdirentries
953   SYS(getdirentries);
954 #endif
955   if (buf_addr != 0 && nbytes >= 0)
956     buf = zalloc(nbytes);
957   else
958     buf = NULL;
959   status = getdirentries(fd,
960 			 (buf_addr == 0 ? NULL : buf),
961 			 nbytes,
962 			 (basep_addr == 0 ? NULL : &basep));
963   emul_write_status(processor, status, errno);
964   if (basep_addr != 0)
965     emul_write_word(basep_addr, basep, processor, cia);
966   if (status > 0)
967     write_direntries(buf_addr, buf, status, processor, cia);
968   if (buf != NULL)
969     free(buf);
970 }
971 #endif
972 
973 
974 static void
975 do___syscall(os_emul_data *emul,
976 	     unsigned call,
977 	     const int arg0,
978 	     cpu *processor,
979 	     unsigned_word cia)
980 {
981   SYS(__syscall);
982   emul_do_system_call(emul,
983 		      emul->syscalls,
984 		      cpu_registers(processor)->gpr[arg0],
985 		      arg0 + 1,
986 		      processor,
987 		      cia);
988 }
989 
990 #ifndef HAVE_LSEEK
991 #define do_lseek 0
992 #else
993 static void
994 do_lseek(os_emul_data *emul,
995 	 unsigned call,
996 	 const int arg0,
997 	 cpu *processor,
998 	 unsigned_word cia)
999 {
1000   int fildes = cpu_registers(processor)->gpr[arg0];
1001   off_t offset = emul_read_gpr64(processor, arg0+2);
1002   int whence = cpu_registers(processor)->gpr[arg0+4];
1003   off_t status;
1004   SYS(lseek);
1005   status = fdbad (fildes);
1006   if (status == 0)
1007     status = lseek(fildes, offset, whence);
1008   if (status == -1)
1009     emul_write_status(processor, -1, errno);
1010   else {
1011     emul_write_status(processor, 0, 0); /* success */
1012     emul_write_gpr64(processor, 3, status);
1013   }
1014 }
1015 #endif
1016 
1017 static void
1018 do___sysctl(os_emul_data *emul,
1019 	    unsigned call,
1020 	    const int arg0,
1021 	    cpu *processor,
1022 	    unsigned_word cia)
1023 {
1024   /* call the arguments by their real name */
1025   unsigned_word name = cpu_registers(processor)->gpr[arg0];
1026   natural_word namelen = cpu_registers(processor)->gpr[arg0+1];
1027   unsigned_word oldp = cpu_registers(processor)->gpr[arg0+2];
1028   unsigned_word oldlenp = cpu_registers(processor)->gpr[arg0+3];
1029   natural_word oldlen;
1030   natural_word mib;
1031   natural_word int_val;
1032   SYS(__sysctl);
1033 
1034   /* pluck out the management information base id */
1035   if (namelen < 1)
1036     error("system_call()SYS___sysctl bad name[0]\n");
1037   mib = vm_data_map_read_word(cpu_data_map(processor),
1038 			      name,
1039 			      processor,
1040 			      cia);
1041   name += sizeof(mib);
1042 
1043   /* see what to do with it ... */
1044   switch ((int)mib) {
1045   case 6/*CTL_HW*/:
1046 #if WITH_NetBSD_HOST && (CTL_HW != 6)
1047 #  error "CTL_HW"
1048 #endif
1049     if (namelen < 2)
1050       error("system_call()SYS___sysctl - CTL_HW - bad name[1]\n");
1051     mib = vm_data_map_read_word(cpu_data_map(processor),
1052 				name,
1053 				processor,
1054 				cia);
1055     name += sizeof(mib);
1056     switch ((int)mib) {
1057     case 7/*HW_PAGESIZE*/:
1058 #if WITH_NetBSD_HOST && (HW_PAGESIZE != 7)
1059 #  error "HW_PAGESIZE"
1060 #endif
1061       oldlen = vm_data_map_read_word(cpu_data_map(processor),
1062 				     oldlenp,
1063 				     processor,
1064 				     cia);
1065       if (sizeof(natural_word) > oldlen)
1066 	error("system_call()sysctl - CTL_HW.HW_PAGESIZE - to small\n");
1067       int_val = 8192;
1068       oldlen = sizeof(int_val);
1069       emul_write_word(oldp, int_val, processor, cia);
1070       emul_write_word(oldlenp, oldlen, processor, cia);
1071       break;
1072     default:
1073       error("sysctl() CTL_HW.%d unknown\n", mib);
1074       break;
1075     }
1076     break;
1077   default:
1078     error("sysctl() name[0]=%d unknown\n", (int)mib);
1079     break;
1080   }
1081   emul_write_status(processor, 0, 0); /* always succeed */
1082 }
1083 
1084 
1085 
1086 static emul_syscall_descriptor netbsd_descriptors[] = {
1087   /* 0 */ { 0, "syscall" },
1088   /* 1 */ { do_exit, "exit" },
1089   /* 2 */ { 0, "fork" },
1090   /* 3 */ { do_read, "read" },
1091   /* 4 */ { do_write, "write" },
1092   /* 5 */ { do_open, "open" },
1093   /* 6 */ { do_close, "close" },
1094   { 0, }, /* 7 is old wait4 */
1095   { 0, }, /* 8 is old creat */
1096   /* 9 */ { 0, "link" },
1097   /* 10 */ { 0, "unlink" },
1098   { 0, }, /* 11 is obsolete execv */
1099   /* 12 */ { 0, "chdir" },
1100   /* 13 */ { 0, "fchdir" },
1101   { 0, }, /* 14 is old mknod */
1102   /* 15 */ { 0, "chmod" },
1103   /* 16 */ { 0, "chown" },
1104   /* 17 */ { do_break, "break" },
1105   { 0, }, /* 18 is old getfsstat */
1106   { 0, }, /* 19 is old lseek */
1107   /* 20 */ { do_getpid, "getpid" },
1108   { 0, }, /* 21 is old mount */
1109   /* 22 */ { 0, "unmount" },
1110   /* 23 */ { 0, "setuid" },
1111   /* 24 */ { do_getuid, "getuid" },
1112   /* 25 */ { do_geteuid, "geteuid" },
1113   /* 26 */ { 0, "ptrace" },
1114   /* 27 */ { 0, "recvmsg" },
1115   /* 28 */ { 0, "sendmsg" },
1116   /* 29 */ { 0, "recvfrom" },
1117   /* 30 */ { 0, "accept" },
1118   /* 31 */ { 0, "getpeername" },
1119   /* 32 */ { 0, "getsockname" },
1120   /* 33 */ { 0, "access" },
1121   /* 34 */ { 0, "chflags" },
1122   /* 35 */ { 0, "fchflags" },
1123   /* 36 */ { 0, "sync" },
1124   /* 37 */ { do_kill, "kill" },
1125   { 0, }, /* 38 is old stat */
1126   /* 39 */ { 0, "getppid" },
1127   { 0, }, /* 40 is old lstat */
1128   /* 41 */ { do_dup, "dup" },
1129   /* 42 */ { 0, "pipe" },
1130   /* 43 */ { do_getegid, "getegid" },
1131   /* 44 */ { 0, "profil" },
1132   /* 45 */ { 0, "ktrace" },
1133   { 0, }, /* 46 is old sigaction */
1134   /* 47 */ { do_getgid, "getgid" },
1135   { 0, }, /* 48 is old sigprocmask */
1136   /* 49 */ { 0, "getlogin" },
1137   /* 50 */ { 0, "setlogin" },
1138   /* 51 */ { 0, "acct" },
1139   { 0, }, /* 52 is old sigpending */
1140   { 0, }, /* 53 is old sigaltstack */
1141   /* 54 */ { do_ioctl, "ioctl" },
1142   { 0, }, /* 55 is old reboot */
1143   /* 56 */ { 0, "revoke" },
1144   /* 57 */ { 0, "symlink" },
1145   /* 58 */ { 0, "readlink" },
1146   /* 59 */ { 0, "execve" },
1147   /* 60 */ { do_umask, "umask" },
1148   /* 61 */ { 0, "chroot" },
1149   { 0, }, /* 62 is old fstat */
1150   { 0, }, /* 63 is old getkerninfo */
1151   { 0, }, /* 64 is old getpagesize */
1152   { 0, }, /* 65 is old msync */
1153   /* 66 */ { 0, "vfork" },
1154   { 0, }, /* 67 is obsolete vread */
1155   { 0, }, /* 68 is obsolete vwrite */
1156   /* 69 */ { 0, "sbrk" },
1157   { 0, }, /* 70 is obsolete sstk */
1158   { 0, }, /* 71 is old mmap */
1159   { 0, }, /* 72 is obsolete vadvise */
1160   /* 73 */ { 0, "munmap" },
1161   /* 74 */ { 0, "mprotect" },
1162   /* 75 */ { 0, "madvise" },
1163   { 0, }, /* 76 is obsolete vhangup */
1164   { 0, }, /* 77 is obsolete vlimit */
1165   /* 78 */ { 0, "mincore" },
1166   /* 79 */ { 0, "getgroups" },
1167   /* 80 */ { 0, "setgroups" },
1168   /* 81 */ { 0, "getpgrp" },
1169   /* 82 */ { 0, "setpgid" },
1170   { 0, }, /* 83 is old setitimer */
1171   { 0, }, /* 84 is old wait */
1172   { 0, }, /* 85 is old swapon */
1173   { 0, }, /* 86 is old getitimer */
1174   { 0, }, /* 87 is old gethostname */
1175   { 0, }, /* 88 is old sethostname */
1176   { 0, }, /* 89 is old getdtablesize */
1177   { do_dup2, "dup2" },
1178   { 0, }, /* 91 */
1179   /* 92 */ { do_fcntl, "fcntl" },
1180   { 0, }, /* 93 is old select */
1181   { 0, }, /* 94 */
1182   /* 95 */ { 0, "fsync" },
1183   /* 96 */ { 0, "setpriority" },
1184   { 0, }, /* 97 is old socket */
1185   { 0, }, /* 98 is old connect */
1186   { 0, }, /* 99 is old accept */
1187   /* 100 */ { 0, "getpriority" },
1188   { 0, }, /* 101 is old send */
1189   { 0, }, /* 102 is old recv */
1190   { 0, }, /* 103 is old sigreturn */
1191   /* 104 */ { 0, "bind" },
1192   /* 105 */ { 0, "setsockopt" },
1193   /* 106 */ { 0, "listen" },
1194   { 0, }, /* 107 is obsolete vtimes */
1195   { 0, }, /* 108 is old sigvec */
1196   { 0, }, /* 109 is old sigblock */
1197   { 0, }, /* 110 is old sigsetmask */
1198   { 0, }, /* 111 is old sigsuspend */
1199   { 0, }, /* 112 is old sigstack */
1200   { 0, }, /* 113 is old recvmsg */
1201   { 0, }, /* 114 is old sendmsg */
1202   /* - is obsolete vtrace */ { 0, "vtrace	115" },
1203   { 0, }, /* 116 is old gettimeofday */
1204   { 0, }, /* 117 is old getrusage */
1205   /* 118 */ { 0, "getsockopt" },
1206   /* - is obsolete resuba */ { 0, "resuba	119" },
1207   /* 120 */ { 0, "readv" },
1208   /* 121 */ { 0, "writev" },
1209   { 0, }, /* 122 is old settimeofday */
1210   /* 123 */ { 0, "fchown" },
1211   /* 124 */ { 0, "fchmod" },
1212   { 0, }, /* 125 is old recvfrom */
1213   { 0, }, /* 126 is old setreuid */
1214   { 0, }, /* 127 is old setregid */
1215   /* 126 */ { 0, "setreuid" },
1216   /* 127 */ { 0, "setregid" },
1217   /* 128 */ { 0, "rename" },
1218   { 0, }, /* 129 is old truncate */
1219   { 0, }, /* 130 is old ftruncate */
1220   /* 131 */ { 0, "flock" },
1221   /* 132 */ { 0, "mkfifo" },
1222   /* 133 */ { 0, "sendto" },
1223   /* 134 */ { 0, "shutdown" },
1224   /* 135 */ { 0, "socketpair" },
1225   /* 136 */ { 0, "mkdir" },
1226   /* 137 */ { 0, "rmdir" },
1227   { 0, }, /* 138 is old utimes */
1228   { 0, }, /* 139 is obsolete 4.2 sigreturn */
1229   { 0, }, /* 140 is old adjtime */
1230   { 0, }, /* 141 is old getpeername */
1231   { 0, }, /* 142 is old gethostid */
1232   { 0, }, /* 143 is old sethostid */
1233   { 0, }, /* 144 is old getrlimit */
1234   { 0, }, /* 145 is old setrlimit */
1235   { 0, }, /* 146 is old killpg */
1236   /* 147 */ { 0, "setsid" },
1237   /* 148 */ { 0, "quotactl" },
1238   { 0, }, /* 149 is old quota */
1239   { 0, }, /* 150 is old getsockname */
1240   { 0, }, /* 151 */
1241   { 0, }, /* 152 */
1242   { 0, }, /* 153 */
1243   { 0, }, /* 154 */
1244   /* 155 */ { 0, "nfssvc" },
1245   { 0, }, /* 156 is old getdirentries */
1246   { 0, }, /* 157 is old statfs */
1247   { 0, }, /* 158 is old fstatfs */
1248   { 0, }, /* 159 */
1249   { 0, }, /* 160 */
1250   { 0, }, /* 161 is old getfh */
1251   { 0, }, /* 162 is old getdomainname */
1252   { 0, }, /* 163 is old setdomainname */
1253   { 0, }, /* 164 is old uname */
1254   /* 165 */ { 0, "sysarch" },
1255   { 0, }, /* 166 */
1256   { 0, }, /* 167 */
1257   { 0, }, /* 168 */
1258   { 0, }, /* 169 is old semsys */
1259   { 0, }, /* 170 is old msgsys */
1260   { 0, }, /* 171 is old shmsys */
1261   { 0, }, /* 172 */
1262   /* 173 */ { 0, "pread" },
1263   /* 174 */ { 0, "pwrite" },
1264   { 0, }, /* 175 is old ntp_gettime */
1265   /* 176 */ { 0, "ntp_adjtime" },
1266   { 0, }, /* 177 */
1267   { 0, }, /* 178 */
1268   { 0, }, /* 179 */
1269   { 0, }, /* 180 */
1270   /* 181 */ { 0, "setgid" },
1271   /* 182 */ { 0, "setegid" },
1272   /* 183 */ { 0, "seteuid" },
1273   /* 184 */ { 0, "lfs_bmapv" },
1274   /* 185 */ { 0, "lfs_markv" },
1275   /* 186 */ { 0, "lfs_segclean" },
1276   /* 187 */ { 0, "lfs_segwait" },
1277   { 0, }, /* 188 is old stat" */
1278   { 0, }, /* 189 is old fstat */
1279   { 0, }, /* 190 is old lstat */
1280   /* 191 */ { 0, "pathconf" },
1281   /* 192 */ { 0, "fpathconf" },
1282   { 0, }, /* 193 */
1283   /* 194 */ { 0, "getrlimit" },
1284   /* 195 */ { 0, "setrlimit" },
1285   { 0, }, /* 196 is old getdirentries */
1286   /* 197 */ { 0, "mmap" },
1287   /* 198 */ { do___syscall, "__syscall" },
1288   /* 199 */ { do_lseek, "lseek" },
1289   /* 200 */ { 0, "truncate" },
1290   /* 201 */ { 0, "ftruncate" },
1291   /* 202 */ { do___sysctl, "__sysctl" },
1292   /* 203 */ { 0, "mlock" },
1293   /* 204 */ { 0, "munlock" },
1294   /* 205 */ { 0, "undelete" },
1295   { 0, }, /* 206 is old futimes */
1296   /* 207 */ { 0, "getpgid" },
1297   /* 208 */ { 0, "reboot" },
1298   /* 209 */ { 0, "poll" },
1299   { 0, }, /* 210 */
1300   { 0, }, /* 211 */
1301   { 0, }, /* 212 */
1302   { 0, }, /* 213 */
1303   { 0, }, /* 214 */
1304   { 0, }, /* 215 */
1305   { 0, }, /* 216 */
1306   { 0, }, /* 217 */
1307   { 0, }, /* 218 */
1308   { 0, }, /* 219 */
1309   { 0, }, /* 220 is old semctl */
1310   /* 221 */ { 0, "semget" },
1311   /* 222 */ { 0, "semop" },
1312   /* 223 */ { 0, "semconfig" },
1313   { 0, }, /* 224 is old msgctl */
1314   /* 225 */ { 0, "msgget" },
1315   /* 226 */ { 0, "msgsnd" },
1316   /* 227 */ { 0, "msgrcv" },
1317   /* 228 */ { 0, "shmat" },
1318   { 0, }, /* 229 is old shmctl */
1319   /* 230 */ { 0, "shmdt" },
1320   /* 231 */ { 0, "shmget" },
1321   { 0, }, /* 232 is old clock_gettime */
1322   { 0, }, /* 233 is old clock_settime */
1323   { 0, }, /* 234 is old clock_getres */
1324   /* 235 */ { 0, "timer_create" },
1325   /* 236 */ { 0, "timer_delete" },
1326   { 0, }, /* 237 is old timer_settime */
1327   { 0, }, /* 238 is old timer_gettime */
1328   /* 239 */ { 0, "timer_getoverrun" },
1329   { 0, }, /* 240 is old nanosleep */
1330   /* 241 */ { 0, "fdatasync" },
1331   /* 242 */ { 0, "mlockall" },
1332   /* 243 */ { 0, "munlockall" },
1333   { 0, }, /* 244 is old sigtimedwait */
1334   { 0, }, /* 245 */
1335   /* 246 */ { 0, "modctl" },
1336   /* 247 */ { 0, "_ksem_init" },
1337   /* 248 */ { 0, "_ksem_open" },
1338   /* 249 */ { 0, "_ksem_unlink" },
1339   /* 250 */ { 0, "_ksem_close" },
1340   /* 251 */ { 0, "_ksem_post" },
1341   /* 252 */ { 0, "_ksem_wait" },
1342   /* 253 */ { 0, "_ksem_trywait" },
1343   /* 254 */ { 0, "_ksem_getvalue" },
1344   /* 255 */ { 0, "_ksem_destroy" },
1345   /* 256 */ { 0, "_ksem_timedwait" },
1346   /* 257 */ { 0, "mq_open" },
1347   /* 258 */ { 0, "mq_close" },
1348   /* 259 */ { 0, "mq_unlink" },
1349   /* 260 */ { 0, "mq_getattr" },
1350   /* 261 */ { 0, "mq_setattr" },
1351   /* 262 */ { 0, "mq_notify" },
1352   /* 263 */ { 0, "mq_send" },
1353   /* 264 */ { 0, "mq_receive" },
1354   { 0, }, /* 265 is old mq_timedsend */
1355   { 0, }, /* 266 is old mq_timedrecive */
1356   { 0, }, /* 267 */
1357   { 0, }, /* 268 */
1358   { 0, }, /* 269 */
1359   /* 270 */ { 0, "__posix_rename" },
1360   /* 271 */ { 0, "swapctl" },
1361   { 0, }, /* 272 is old getdents */
1362   /* 273 */ { 0, "minherit" },
1363   /* 274 */ { 0, "lchmod" },
1364   /* 275 */ { 0, "lchown" },
1365   { 0, }, /* 276 is old lutimes */
1366   /* 277 */ { 0, "__msync13" },
1367   { 0, }, /* 278 is old stat */
1368   { 0, }, /* 279 is old fstat */
1369   { 0, }, /* 280 is old lstat */
1370   /* 281 */ { 0, "__sigaltstack13" },
1371   /* 282 */ { 0, "__vfork14" },
1372   /* 283 */ { 0, "__posix_chown" },
1373   /* 284 */ { 0, "__posix_fchown" },
1374   /* 285 */ { 0, "__posix_lchown" },
1375   /* 286 */ { 0, "getsid" },
1376   /* 287 */ { 0, "__clone" },
1377   /* 288 */ { 0, "fktrace" },
1378   /* 289 */ { 0, "preadv" },
1379   /* 290 */ { 0, "pwritev" },
1380   { 0, }, /* 291 is old sigaction */
1381   /* 292 */ { 0, "__sigpending14" },
1382   /* 293 */ { do_sigprocmask, "__sigprocmask14" },
1383   /* 294 */ { 0, "__sigsuspend14" },
1384   /* 295 */ { 0, "__sigreturn14" },
1385   /* 296 */ { 0, "__getcwd" },
1386   /* 297 */ { 0, "fchroot" },
1387   { 0, }, /* 298 is old fhopen */
1388   { 0, }, /* 299 is old fhstat */
1389   { 0, }, /* 300 is old fhstatfs */
1390   { 0, }, /* 301 is old semctl */
1391   { 0, }, /* 302 is old msgctl */
1392   { 0, }, /* 303 is old shmctl */
1393   /* 304 */ { 0, "lchflags" },
1394   /* 305 */ { 0, "issetugid" },
1395   /* 306 */ { 0, "utrace" },
1396   /* 307 */ { 0, "getcontext" },
1397   /* 308 */ { 0, "setcontext" },
1398   /* 309 */ { 0, "_lwp_create" },
1399   /* 310 */ { 0, "_lwp_exit" },
1400   /* 311 */ { 0, "_lwp_self" },
1401   /* 312 */ { 0, "_lwp_wait" },
1402   /* 313 */ { 0, "_lwp_suspend" },
1403   /* 314 */ { 0, "_lwp_continue" },
1404   /* 315 */ { 0, "_lwp_wakeup" },
1405   /* 316 */ { 0, "_lwp_getprivate" },
1406   /* 317 */ { 0, "_lwp_setprivate" },
1407   /* 318 */ { 0, "_lwp_kill" },
1408   /* 319 */ { 0, "_lwp_detach" },
1409   { 0, }, /* 320 is old _lwp_park */
1410   /* 321 */ { 0, "_lwp_unpark" },
1411   /* 322 */ { 0, "_lwp_unpark_all" },
1412   /* 323 */ { 0, "_lwp_setname" },
1413   /* 324 */ { 0, "_lwp_getname" },
1414   /* 325 */ { 0, "_lwp_ctl" },
1415   { 0, }, /* 326 */
1416   { 0, }, /* 327 */
1417   { 0, }, /* 328 */
1418   { 0, }, /* 329 */
1419   /* 330 */ { 0, "sa_register" },
1420   /* 331 */ { 0, "sa_stacks" },
1421   /* 332 */ { 0, "sa_enable" },
1422   /* 333 */ { 0, "sa_setconcurrency" },
1423   /* 334 */ { 0, "sa_yield" },
1424   /* 335 */ { 0, "sa_preempt" },
1425   { 0, }, /* 336 */
1426   { 0, }, /* 337 */
1427   { 0, }, /* 338 */
1428   { 0, }, /* 339 */
1429   /* 340 */ { 0, "__sigaction_sigtramp" },
1430   /* 341 */ { 0, "pmc_get_info" },
1431   /* 342 */ { 0, "pmc_control" },
1432   /* 343 */ { 0, "rasctl" },
1433   /* 344 */ { 0, "kqueue" },
1434   { 0, }, /* 345 is old kevent */
1435   /* 346 */ { 0, "_sched_setparam" },
1436   /* 347 */ { 0, "_sched_getparam" },
1437   /* 348 */ { 0, "_sched_setaffinity" },
1438   /* 349 */ { 0, "_sched_getaffinity" },
1439   /* 350 */ { 0, "sched_yield" },
1440   { 0, }, /* 351 */
1441   { 0, }, /* 352 */
1442   { 0, }, /* 353 */
1443   /* 354 */ { 0, "fsync_range" },
1444   /* 355 */ { 0, "uuidgen" },
1445   /* 356 */ { 0, "getvfsstat" },
1446   /* 357 */ { 0, "statvfs1" },
1447   /* 358 */ { 0, "fstatvfs1" },
1448   { 0, }, /* 359 is old fhstatvfs1 */
1449   /* 360 */ { 0, "extattrctl" },
1450   /* 361 */ { 0, "extattr_set_file" },
1451   /* 362 */ { 0, "extattr_get_file" },
1452   /* 363 */ { 0, "extattr_delete_file" },
1453   /* 364 */ { 0, "extattr_set_fd" },
1454   /* 365 */ { 0, "extattr_get_fd" },
1455   /* 366 */ { 0, "extattr_delete_fd" },
1456   /* 367 */ { 0, "extattr_set_link" },
1457   /* 368 */ { 0, "extattr_get_link" },
1458   /* 369 */ { 0, "extattr_delete_link" },
1459   /* 370 */ { 0, "extattr_list_fd" },
1460   /* 371 */ { 0, "extattr_list_file" },
1461   /* 372 */ { 0, "extattr_list_link" },
1462   { 0, }, /* 373 is old pselect */
1463   { 0, }, /* 374 is old pollts */
1464   /* 375 */ { 0, "setxattr" },
1465   /* 376 */ { 0, "lsetxattr" },
1466   /* 377 */ { 0, "fsetxattr" },
1467   /* 378 */ { 0, "getxattr" },
1468   /* 379 */ { 0, "lgetxattr" },
1469   /* 380 */ { 0, "fgetxattr" },
1470   /* 381 */ { 0, "listxattr" },
1471   /* 382 */ { 0, "llistxattr" },
1472   /* 383 */ { 0, "flistxattr" },
1473   /* 384 */ { 0, "removexattr" },
1474   /* 385 */ { 0, "lremovexattr" },
1475   /* 386 */ { 0, "fremovexattr" },
1476   { 0, }, /* 387 is old stat */
1477   { 0, }, /* 388 is old fstat */
1478   { 0, }, /* 389 is old lstat */
1479   /* 390 */ { do_getdirentries, "__getdents30" },
1480   { 0, }, /* 391 is old posix_fadvise */
1481   { 0, }, /* 392 is old fhstat */
1482   { 0, }, /* 393 is old ntp_gettime */
1483   /* 394 */ { 0, "__socket30" },
1484   /* 395 */ { 0, "__getfh30" },
1485   /* 396 */ { 0, "__fhopen40" },
1486   /* 397 */ { 0, "__fhstatvfs140" },
1487   { 0, }, /* 398 is old fhstat */
1488   /* 399 */ { 0, "aio_cancel" },
1489   /* 400 */ { 0, "aio_error" },
1490   /* 401 */ { 0, "aio_fsync" },
1491   /* 402 */ { 0, "aio_read" },
1492   /* 403 */ { 0, "aio_return" },
1493   { 0, }, /* 404 is old aio_suspend */
1494   /* 405 */ { 0, "aio_write" },
1495   /* 406 */ { 0, "lio_listio" },
1496   { 0, }, /* 407 */
1497   { 0, }, /* 408 */
1498   { 0, }, /* 409 */
1499   /* 410 */ { 0, "__mount50" },
1500   /* 411 */ { 0, "mremap" },
1501   /* 412 */ { 0, "pset_create" },
1502   /* 413 */ { 0, "pset_destroy" },
1503   /* 414 */ { 0, "pset_assign" },
1504   /* 415 */ { 0, "_pset_bind" },
1505   /* 416 */ { 0, "__posix_fadvise50" },
1506   /* 417 */ { 0, "__select50" },
1507   /* 418 */ { do_gettimeofday, "__gettimeofday50" },
1508   /* 419 */ { 0, "__settimeofday50" },
1509   /* 420 */ { 0, "__utimes50" },
1510   /* 421 */ { 0, "__adjtime50" },
1511   /* 422 */ { 0, "__lfs_segwait50" },
1512   /* 423 */ { 0, "__futimes50" },
1513   /* 424 */ { 0, "__lutimes50" },
1514   /* 425 */ { 0, "__setitimer50" },
1515   /* 426 */ { 0, "__getitimer50" },
1516   /* 427 */ { 0, "__clock_gettime50" },
1517   /* 428 */ { 0, "__clock_settime50" },
1518   /* 429 */ { 0, "__clock_getres50" },
1519   /* 430 */ { 0, "__nanosleep50" },
1520   /* 431 */ { 0, "____sigtimedwait50" },
1521   /* 432 */ { 0, "__mq_timedsend50" },
1522   /* 433 */ { 0, "__mq_timedreceive50" },
1523   /* 434 */ { 0, "____lwp_park50" },
1524   /* 435 */ { 0, "__kevent50" },
1525   /* 436 */ { 0, "__pselect50" },
1526   /* 437 */ { 0, "__pollts50" },
1527   /* 438 */ { 0, "__aio_suspend50" },
1528   /* 439 */ { do_stat, "__stat50" },
1529   /* 440 */ { do_fstat, "__fstat50" },
1530   /* 441 */ { do_lstat, "__lstat50" },
1531   /* 442 */ { 0, "____semctl50" },
1532   /* 443 */ { 0, "__shmctl50" },
1533   /* 444 */ { 0, "__msgctl50" },
1534   /* 445 */ { do_getrusage, "__getrusage50" },
1535   /* 446 */ { 0, "__timer_settime50" },
1536   /* 447 */ { 0, "__timer_gettime50" },
1537   /* 448 */ { 0, "__ntp_gettime50" },
1538   /* 449 */ { 0, "__wait450" },
1539   /* 450 */ { 0, "__mknod50" },
1540   /* 451 */ { 0, "__fhstat50" },
1541   { 0, }, /* 452 is obsolete 5.99 __quotactl50 */
1542   /* 453 */ { 0, "pipe2" },
1543   /* 454 */ { 0, "dup3" },
1544   /* 455 */ { 0, "kqueue1" },
1545   /* 456 */ { 0, "paccept" },
1546   /* 457 */ { 0, "linkat" },
1547   /* 458 */ { 0, "renameat" },
1548   /* 459 */ { 0, "mkfifoat" },
1549   /* 460 */ { 0, "mknodat" },
1550   /* 461 */ { 0, "mkdirat" },
1551   /* 462 */ { 0, "faccessat" },
1552   /* 463 */ { 0, "fchmodat" },
1553   /* 464 */ { 0, "fchownat" },
1554   /* 465 */ { 0, "fexecve" },
1555   /* 466 */ { 0, "fstatat" },
1556   /* 467 */ { 0, "utimensat" },
1557   /* 468 */ { 0, "openat" },
1558   /* 469 */ { 0, "readlinkat" },
1559   /* 470 */ { 0, "symlinkat" },
1560   /* 471 */ { 0, "unlinkat" },
1561   /* 472 */ { 0, "futimens" },
1562   /* 473 */ { 0, "__quotactl" },
1563 };
1564 
1565 static char *(netbsd_error_names[]) = {
1566   /* 0 */ "ESUCCESS",
1567   /* 1 */ "EPERM",
1568   /* 2 */ "ENOENT",
1569   /* 3 */ "ESRCH",
1570   /* 4 */ "EINTR",
1571   /* 5 */ "EIO",
1572   /* 6 */ "ENXIO",
1573   /* 7 */ "E2BIG",
1574   /* 8 */ "ENOEXEC",
1575   /* 9 */ "EBADF",
1576   /* 10 */ "ECHILD",
1577   /* 11 */ "EDEADLK",
1578   /* 12 */ "ENOMEM",
1579   /* 13 */ "EACCES",
1580   /* 14 */ "EFAULT",
1581   /* 15 */ "ENOTBLK",
1582   /* 16 */ "EBUSY",
1583   /* 17 */ "EEXIST",
1584   /* 18 */ "EXDEV",
1585   /* 19 */ "ENODEV",
1586   /* 20 */ "ENOTDIR",
1587   /* 21 */ "EISDIR",
1588   /* 22 */ "EINVAL",
1589   /* 23 */ "ENFILE",
1590   /* 24 */ "EMFILE",
1591   /* 25 */ "ENOTTY",
1592   /* 26 */ "ETXTBSY",
1593   /* 27 */ "EFBIG",
1594   /* 28 */ "ENOSPC",
1595   /* 29 */ "ESPIPE",
1596   /* 30 */ "EROFS",
1597   /* 31 */ "EMLINK",
1598   /* 32 */ "EPIPE",
1599   /* 33 */ "EDOM",
1600   /* 34 */ "ERANGE",
1601   /* 35 */ "EAGAIN",
1602   /* 36 */ "EINPROGRESS",
1603   /* 37 */ "EALREADY",
1604   /* 38 */ "ENOTSOCK",
1605   /* 39 */ "EDESTADDRREQ",
1606   /* 40 */ "EMSGSIZE",
1607   /* 41 */ "EPROTOTYPE",
1608   /* 42 */ "ENOPROTOOPT",
1609   /* 43 */ "EPROTONOSUPPORT",
1610   /* 44 */ "ESOCKTNOSUPPORT",
1611   /* 45 */ "EOPNOTSUPP",
1612   /* 46 */ "EPFNOSUPPORT",
1613   /* 47 */ "EAFNOSUPPORT",
1614   /* 48 */ "EADDRINUSE",
1615   /* 49 */ "EADDRNOTAVAIL",
1616   /* 50 */ "ENETDOWN",
1617   /* 51 */ "ENETUNREACH",
1618   /* 52 */ "ENETRESET",
1619   /* 53 */ "ECONNABORTED",
1620   /* 54 */ "ECONNRESET",
1621   /* 55 */ "ENOBUFS",
1622   /* 56 */ "EISCONN",
1623   /* 57 */ "ENOTCONN",
1624   /* 58 */ "ESHUTDOWN",
1625   /* 59 */ "ETOOMANYREFS",
1626   /* 60 */ "ETIMEDOUT",
1627   /* 61 */ "ECONNREFUSED",
1628   /* 62 */ "ELOOP",
1629   /* 63 */ "ENAMETOOLONG",
1630   /* 64 */ "EHOSTDOWN",
1631   /* 65 */ "EHOSTUNREACH",
1632   /* 66 */ "ENOTEMPTY",
1633   /* 67 */ "EPROCLIM",
1634   /* 68 */ "EUSERS",
1635   /* 69 */ "EDQUOT",
1636   /* 70 */ "ESTALE",
1637   /* 71 */ "EREMOTE",
1638   /* 72 */ "EBADRPC",
1639   /* 73 */ "ERPCMISMATCH",
1640   /* 74 */ "EPROGUNAVAIL",
1641   /* 75 */ "EPROGMISMATCH",
1642   /* 76 */ "EPROCUNAVAIL",
1643   /* 77 */ "ENOLCK",
1644   /* 78 */ "ENOSYS",
1645   /* 79 */ "EFTYPE",
1646   /* 80 */ "EAUTH",
1647   /* 81 */ "ENEEDAUTH",
1648   /* 82 */ "EIDRM",
1649   /* 83 */ "ENOMSG",
1650   /* 84 */ "EOVERFLOW",
1651   /* 85 */ "EILSEQ",
1652   /* 86 */ "ENOTSUP",
1653   /* 87 */ "ECANCELED",
1654   /* 88 */ "EBADMSG",
1655   /* 89 */ "ENODATA",
1656   /* 90 */ "ENOSR",
1657   /* 91 */ "ENOSTR",
1658   /* 92 */ "ETIME",
1659   /* 93 */ "ENOATTR",
1660   /* 94 */ "EMULTIHOP",
1661   /* 95 */ "ENOLINK",
1662   /* 96 */ "EPROTO",
1663   /* 96 */ "ELAST",
1664 };
1665 
1666 static char *(netbsd_signal_names[]) = {
1667   /* 0 */ 0,
1668   /* 1 */ "SIGHUP",
1669   /* 2 */ "SIGINT",
1670   /* 3 */ "SIGQUIT",
1671   /* 4 */ "SIGILL",
1672   /* 5 */ "SIGTRAP",
1673   /* 6 */ "SIGABRT",
1674   /* 7 */ "SIGEMT",
1675   /* 8 */ "SIGFPE",
1676   /* 9 */ "SIGKILL",
1677   /* 10 */ "SIGBUS",
1678   /* 11 */ "SIGSEGV",
1679   /* 12 */ "SIGSYS",
1680   /* 13 */ "SIGPIPE",
1681   /* 14 */ "SIGALRM",
1682   /* 15 */ "SIGTERM",
1683   /* 16 */ "SIGURG",
1684   /* 17 */ "SIGSTOP",
1685   /* 18 */ "SIGTSTP",
1686   /* 19 */ "SIGCONT",
1687   /* 20 */ "SIGCHLD",
1688   /* 21 */ "SIGTTIN",
1689   /* 22 */ "SIGTTOU",
1690   /* 23 */ "SIGIO",
1691   /* 24 */ "SIGXCPU",
1692   /* 25 */ "SIGXFSZ",
1693   /* 26 */ "SIGVTALRM",
1694   /* 27 */ "SIGPROF",
1695   /* 28 */ "SIGWINCH",
1696   /* 29 */ "SIGINFO",
1697   /* 30 */ "SIGUSR1",
1698   /* 31 */ "SIGUSR2",
1699   /* 32 */ "SIGPWR",
1700 };
1701 
1702 static emul_syscall emul_netbsd_syscalls = {
1703   netbsd_descriptors,
1704   ARRAY_SIZE (netbsd_descriptors),
1705   netbsd_error_names,
1706   ARRAY_SIZE (netbsd_error_names),
1707   netbsd_signal_names,
1708   ARRAY_SIZE (netbsd_signal_names),
1709 };
1710 
1711 
1712 /* NetBSD's os_emul interface, most are just passed on to the generic
1713    syscall stuff */
1714 
1715 static os_emul_data *
1716 emul_netbsd_create(device *root,
1717 		   bfd *image,
1718 		   const char *name)
1719 {
1720   unsigned_word top_of_stack;
1721   unsigned stack_size;
1722   int elf_binary;
1723   os_emul_data *bsd_data;
1724   device *vm;
1725   char *filename;
1726 
1727   /* check that this emulation is really for us */
1728   if (name != NULL && strcmp(name, "netbsd") != 0)
1729     return NULL;
1730   if (image == NULL)
1731     return NULL;
1732 
1733 
1734   /* merge any emulation specific entries into the device tree */
1735 
1736   /* establish a few defaults */
1737   if (image->xvec->flavour == bfd_target_elf_flavour) {
1738     elf_binary = 1;
1739     top_of_stack = 0xe0000000;
1740     stack_size =   0x00100000;
1741   }
1742   else {
1743     elf_binary = 0;
1744     top_of_stack = 0x20000000;
1745     stack_size =   0x00100000;
1746   }
1747 
1748   /* options */
1749   emul_add_tree_options(root, image, "netbsd",
1750 			(WITH_ENVIRONMENT == USER_ENVIRONMENT
1751 			 ? "user" : "virtual"),
1752 			0 /*oea-interrupt-prefix*/);
1753 
1754   /* virtual memory - handles growth of stack/heap */
1755   vm = tree_parse(root, "/openprom/vm");
1756   tree_parse(vm, "./stack-base 0x%lx",
1757 	     (unsigned long)(top_of_stack - stack_size));
1758   tree_parse(vm, "./nr-bytes 0x%x", stack_size);
1759 
1760   filename = tree_quote_property (bfd_get_filename(image));
1761   tree_parse(root, "/openprom/vm/map-binary/file-name %s",
1762 	     filename);
1763   free (filename);
1764 
1765   /* finish the init */
1766   tree_parse(root, "/openprom/init/register/pc 0x%lx",
1767 	     (unsigned long)bfd_get_start_address(image));
1768   tree_parse(root, "/openprom/init/register/sp 0x%lx",
1769 	     (unsigned long)top_of_stack);
1770   tree_parse(root, "/openprom/init/register/msr 0x%x",
1771 	     ((tree_find_boolean_property(root, "/options/little-endian?")
1772 	       ? msr_little_endian_mode
1773 	       : 0)
1774 	      | (tree_find_boolean_property(root, "/openprom/options/floating-point?")
1775 		 ? (msr_floating_point_available
1776 		    | msr_floating_point_exception_mode_0
1777 		    | msr_floating_point_exception_mode_1)
1778 		 : 0)));
1779   tree_parse(root, "/openprom/init/stack/stack-type %s",
1780 	     (elf_binary ? "ppc-elf" : "ppc-xcoff"));
1781 
1782   /* finally our emulation data */
1783   bsd_data = ZALLOC(os_emul_data);
1784   bsd_data->vm = vm;
1785   bsd_data->syscalls = &emul_netbsd_syscalls;
1786   return bsd_data;
1787 }
1788 
1789 static void
1790 emul_netbsd_init(os_emul_data *emul_data,
1791 		 int nr_cpus)
1792 {
1793   fd_closed[0] = 0;
1794   fd_closed[1] = 0;
1795   fd_closed[2] = 0;
1796 }
1797 
1798 static void
1799 emul_netbsd_system_call(cpu *processor,
1800 			unsigned_word cia,
1801 			os_emul_data *emul_data)
1802 {
1803   emul_do_system_call(emul_data,
1804 		      emul_data->syscalls,
1805 		      cpu_registers(processor)->gpr[0],
1806 		      3, /*r3 contains arg0*/
1807 		      processor,
1808 		      cia);
1809 }
1810 
1811 const os_emul emul_netbsd = {
1812   "netbsd",
1813   emul_netbsd_create,
1814   emul_netbsd_init,
1815   emul_netbsd_system_call,
1816   0, /*instruction_call*/
1817   0 /*data*/
1818 };
1819 
1820 #endif	/* _EMUL_NETBSD_C_ */
1821