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