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