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