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