/[gxemul]/upstream/0.4.4/src/useremul.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/0.4.4/src/useremul.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
Original Path: trunk/src/useremul.c
File MIME type: text/plain
File size: 43974 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


1 dpavlin 2 /*
2 dpavlin 34 * Copyright (C) 2004-2007 Anders Gavare. All rights reserved.
3 dpavlin 2 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 34 * $Id: useremul.c,v 1.74 2007/02/10 14:04:51 debug Exp $
29 dpavlin 2 *
30     * Userland (syscall) emulation.
31     *
32     * TODO:
33     *
34 dpavlin 14 * environment passing for most emulation modes
35 dpavlin 2 *
36 dpavlin 14 * implement more syscalls
37     *
38 dpavlin 2 * 32-bit vs 64-bit problems? MIPS n32, o32, n64?
39     *
40     * Dynamic ELFs?
41     *
42     * Try to prefix "/emul/mips/" or similar to all filenames,
43 dpavlin 28 * and only if that fails, try the given filename.
44     * Read this setting from an environment variable, and only
45     * if there is none, fall back to hardcoded string.
46 dpavlin 2 *
47 dpavlin 28 * Automagic errno translation!
48 dpavlin 2 *
49 dpavlin 28 * Memory allocation? mmap, munmap, mprotect, etc.
50     * mprotect = unmap in dyntrans...
51 dpavlin 2 *
52 dpavlin 28 * File descriptor (0,1,2) assumptions? Find and fix these?
53 dpavlin 2 *
54     *
55     * This module needs more cleanup.
56     * -------------------------------
57     *
58     *
59 dpavlin 28 * NOTE: This module (useremul.c) is just a quick hack so far, to see if
60     * userland emulation works at all. It only works for Hello World-
61     * style programs compiled for FreeBSD/alpha or NetBSD/mips.
62 dpavlin 2 */
63    
64     #include <errno.h>
65     #include <fcntl.h>
66     #include <stdio.h>
67     #include <stdlib.h>
68     #include <stdarg.h>
69     #include <string.h>
70     #include <unistd.h>
71     #include <sys/time.h>
72     #include <sys/stat.h>
73     #include <sys/socket.h>
74 dpavlin 12 #include <sys/resource.h>
75 dpavlin 2 #include <time.h>
76    
77     #include "cpu.h"
78     #include "cpu_mips.h"
79     #include "emul.h"
80     #include "machine.h"
81     #include "memory.h"
82     #include "misc.h"
83     #include "syscall_linux_ppc.h"
84     #include "syscall_netbsd.h"
85     #include "syscall_ultrix.h"
86     #include "sysctl_netbsd.h"
87    
88     struct syscall_emul {
89     char *name;
90     int arch;
91     char *cpu_name;
92     void (*f)(struct cpu *, uint32_t);
93     void (*setup)(struct cpu *, int, char **);
94    
95     struct syscall_emul *next;
96     };
97    
98     static struct syscall_emul *first_syscall_emul;
99    
100     /* Max length of strings passed using syscall parameters: */
101     #define MAXLEN 8192
102    
103    
104     /*
105     * useremul_setup():
106     *
107     * Set up an emulated environment suitable for running userland code. The
108     * program should already have been loaded into memory when this function
109     * is called.
110     */
111     void useremul_setup(struct cpu *cpu, int argc, char **host_argv)
112     {
113     struct syscall_emul *sep;
114    
115     sep = first_syscall_emul;
116    
117     while (sep != NULL) {
118     if (strcasecmp(cpu->machine->userland_emul, sep->name) == 0) {
119     sep->setup(cpu, argc, host_argv);
120     return;
121     }
122     sep = sep->next;
123     }
124    
125     fatal("useremul_setup(): internal error, unimplemented emulation?\n");
126     exit(1);
127     }
128    
129    
130     /*
131     * useremul__freebsd_setup():
132     *
133     * Set up an emulated userland environment suitable for running FreeBSD
134     * binaries.
135     */
136     void useremul__freebsd_setup(struct cpu *cpu, int argc, char **host_argv)
137     {
138     debug("useremul__freebsd_setup(): TODO\n");
139    
140 dpavlin 12 switch (cpu->machine->arch) {
141     case ARCH_ALPHA:
142     /* According to FreeBSD's /usr/src/lib/csu/alpha/crt1.c: */
143     /* a0 = char **ap */
144     /* a1 = void (*cleanup)(void) from shared loader */
145     /* a2 = struct Struct_Obj_Entry *obj from shared loader */
146     /* a3 = struct ps_strings *ps_strings */
147     cpu->cd.alpha.r[ALPHA_A0] = 0;
148     cpu->cd.alpha.r[ALPHA_A1] = 0;
149     cpu->cd.alpha.r[ALPHA_A2] = 0;
150     cpu->cd.alpha.r[ALPHA_A3] = 0;
151    
152     /* What is a good stack pointer? TODO */
153     cpu->cd.alpha.r[ALPHA_SP] = 0x120000000ULL +
154     1048576 * cpu->machine->physical_ram_in_mb - 1024;
155     break;
156     default:
157 dpavlin 2 fatal("non-Alpha not yet implemented for freebsd emul.\n");
158     exit(1);
159     }
160     }
161    
162    
163     /*
164     * useremul__linux_setup():
165     *
166     * Set up an emulated userland environment suitable for running Linux
167     * binaries.
168     */
169     void useremul__linux_setup(struct cpu *cpu, int argc, char **host_argv)
170     {
171     debug("useremul__linux_setup(): TODO\n");
172    
173     if (cpu->machine->arch != ARCH_PPC) {
174     fatal("non-PPC not yet implemented for linux emul.\n");
175     exit(1);
176     }
177    
178     /* What is a good stack pointer? TODO */
179     cpu->cd.ppc.gpr[1] = 0x7ffff000ULL;
180     }
181    
182    
183     /*
184     * useremul__netbsd_setup():
185     *
186     * Set up an emulated userland environment suitable for running NetBSD
187     * binaries.
188     */
189     void useremul__netbsd_setup(struct cpu *cpu, int argc, char **host_argv)
190     {
191     uint64_t stack_top = 0x7fff0000;
192     uint64_t stacksize = 8 * 1048576;
193     uint64_t stack_margin = 16384;
194     uint64_t cur_argv;
195     int i, i2;
196     int envc = 1;
197    
198     switch (cpu->machine->arch) {
199     case ARCH_MIPS:
200     /* See netbsd/sys/src/arch/mips/mips_machdep.c:setregs() */
201     cpu->cd.mips.gpr[MIPS_GPR_A0] = stack_top - stack_margin;
202     cpu->cd.mips.gpr[25] = cpu->pc; /* reg. t9 */
203    
204     /* The userland stack: */
205     cpu->cd.mips.gpr[MIPS_GPR_SP] = stack_top - stack_margin;
206     add_symbol_name(&cpu->machine->symbol_context,
207 dpavlin 12 stack_top - stacksize, stacksize, "userstack", 0, 0);
208 dpavlin 2
209     /* Stack contents: (TODO: is this correct?) */
210     store_32bit_word(cpu, stack_top - stack_margin, argc);
211    
212     cur_argv = stack_top - stack_margin + 128 + (argc + envc)
213     * sizeof(uint32_t);
214     for (i=0; i<argc; i++) {
215     debug("adding argv[%i]: '%s'\n", i, host_argv[i]);
216    
217     store_32bit_word(cpu, stack_top - stack_margin +
218     4 + i*sizeof(uint32_t), cur_argv);
219     store_string(cpu, cur_argv, host_argv[i]);
220     cur_argv += strlen(host_argv[i]) + 1;
221     }
222    
223     /* Store a NULL value between the args and the environment
224     strings: */
225     store_32bit_word(cpu, stack_top - stack_margin +
226     4 + i*sizeof(uint32_t), 0); i++;
227    
228     /* TODO: get environment strings from somewhere */
229    
230     /* Store all environment strings: */
231     for (i2 = 0; i2 < envc; i2 ++) {
232     store_32bit_word(cpu, stack_top - stack_margin + 4
233     + (i+i2)*sizeof(uint32_t), cur_argv);
234     store_string(cpu, cur_argv, "DISPLAY=localhost:0.0");
235     cur_argv += strlen("DISPLAY=localhost:0.0") + 1;
236     }
237     break;
238    
239 dpavlin 14 case ARCH_ALPHA:
240     debug("useremul__netbsd_setup(): ALPHA: TODO\n");
241     break;
242    
243 dpavlin 12 case ARCH_ARM:
244     debug("useremul__netbsd_setup(): ARM: TODO\n");
245     break;
246    
247 dpavlin 2 case ARCH_PPC:
248 dpavlin 4 debug("useremul__netbsd_setup(): PPC: TODO\n");
249 dpavlin 2
250     /* What is a good stack pointer? TODO */
251     cpu->cd.ppc.gpr[1] = 0x7ffff000ULL;
252    
253     break;
254    
255 dpavlin 32 case ARCH_SH:
256     debug("useremul__netbsd_setup(): SH: TODO\n");
257     break;
258    
259 dpavlin 2 default:
260     fatal("useremul__netbsd_setup(): unimplemented arch\n");
261     exit(1);
262     }
263     }
264    
265    
266     /*
267     * useremul__ultrix_setup():
268     *
269     * Set up an emulated userland environment suitable for running Ultrix
270     * binaries.
271     */
272     void useremul__ultrix_setup(struct cpu *cpu, int argc, char **host_argv)
273     {
274     uint64_t stack_top = 0x7fff0000;
275     uint64_t stacksize = 8 * 1048576;
276     uint64_t stack_margin = 16384;
277     uint64_t cur_argv;
278     int i, i2;
279     int envc = 1;
280    
281     /* TODO: is this correct? */
282     cpu->cd.mips.gpr[MIPS_GPR_A0] = stack_top - stack_margin;
283     cpu->cd.mips.gpr[25] = cpu->pc; /* reg. t9 */
284    
285     /* The userland stack: */
286     cpu->cd.mips.gpr[MIPS_GPR_SP] = stack_top - stack_margin;
287     add_symbol_name(&cpu->machine->symbol_context,
288 dpavlin 12 stack_top - stacksize, stacksize, "userstack", 0, 0);
289 dpavlin 2
290     /* Stack contents: (TODO: is this correct?) */
291     store_32bit_word(cpu, stack_top - stack_margin, argc);
292    
293     cur_argv = stack_top - stack_margin + 128 +
294     (argc + envc) * sizeof(uint32_t);
295     for (i=0; i<argc; i++) {
296     debug("adding argv[%i]: '%s'\n", i, host_argv[i]);
297    
298     store_32bit_word(cpu, stack_top - stack_margin +
299     4 + i*sizeof(uint32_t), cur_argv);
300     store_string(cpu, cur_argv, host_argv[i]);
301     cur_argv += strlen(host_argv[i]) + 1;
302     }
303    
304     /* Store a NULL value between the args and the environment strings: */
305     store_32bit_word(cpu, stack_top - stack_margin
306     + 4 + i*sizeof(uint32_t), 0); i++;
307    
308     /* TODO: get environment strings from somewhere */
309    
310     /* Store all environment strings: */
311     for (i2 = 0; i2 < envc; i2 ++) {
312     store_32bit_word(cpu, stack_top - stack_margin + 4 +
313     (i+i2)*sizeof(uint32_t), cur_argv);
314     store_string(cpu, cur_argv, "DISPLAY=localhost:0.0");
315     cur_argv += strlen("DISPLAY=localhost:0.0") + 1;
316     }
317     }
318    
319    
320     /*
321     * get_userland_string():
322     *
323     * This can be used to retrieve strings, for example filenames,
324     * from the emulated memory.
325     *
326     * NOTE: This function returns a pointer to a malloced buffer. It is up to
327     * the caller to use free().
328     */
329     static unsigned char *get_userland_string(struct cpu *cpu, uint64_t baseaddr)
330     {
331     unsigned char *charbuf;
332     int i, len = 16384;
333    
334     charbuf = malloc(len);
335     if (charbuf == NULL) {
336     fprintf(stderr, "get_userland_string(): out of memory (trying"
337     " to allocate %i bytes)\n", len);
338     exit(1);
339     }
340    
341     /* TODO: address validity check */
342    
343     for (i=0; i<len; i++) {
344     cpu->memory_rw(cpu, cpu->mem, baseaddr+i, charbuf+i,
345     1, MEM_READ, CACHE_DATA);
346     if (charbuf[i] == '\0')
347     break;
348     }
349    
350     charbuf[MAXLEN-1] = 0;
351     return charbuf;
352     }
353    
354    
355     /*
356     * get_userland_buf():
357     *
358     * This can be used to retrieve buffers, for example inet_addr, from
359     * emulated memory.
360     *
361     * NOTE: This function returns a pointer to a malloced buffer. It is up to
362     * the caller to use free().
363     *
364     * TODO: combine this with get_userland_string() in some way
365     */
366     static unsigned char *get_userland_buf(struct cpu *cpu,
367 dpavlin 12 uint64_t baseaddr, uint64_t len)
368 dpavlin 2 {
369     unsigned char *charbuf;
370 dpavlin 22 size_t i;
371 dpavlin 2
372     charbuf = malloc(len);
373     if (charbuf == NULL) {
374     fprintf(stderr, "get_userland_buf(): out of memory (trying"
375 dpavlin 12 " to allocate %lli bytes)\n", (long long)len);
376 dpavlin 2 exit(1);
377     }
378    
379     /* TODO: address validity check */
380     for (i=0; i<len; i++) {
381     cpu->memory_rw(cpu, cpu->mem, baseaddr+i, charbuf+i, 1,
382     MEM_READ, CACHE_DATA);
383     /* debug(" %02x", charbuf[i]); */
384     }
385     debug("\n");
386    
387     return charbuf;
388     }
389    
390    
391     /*
392     * useremul_syscall():
393     *
394     * Handle userland syscalls. This function is called whenever a userland
395     * process runs a 'syscall' instruction. The code argument is the code
396     * embedded into the syscall instruction, if any. (This 'code' value is not
397     * necessarily used by specific emulations.)
398     */
399     void useremul_syscall(struct cpu *cpu, uint32_t code)
400     {
401     if (cpu->useremul_syscall == NULL) {
402     fatal("useremul_syscall(): cpu->useremul_syscall == NULL\n");
403     } else
404     cpu->useremul_syscall(cpu, code);
405     }
406    
407    
408 dpavlin 12 /*****************************************************************************/
409    
410    
411 dpavlin 2 /*
412 dpavlin 12 * useremul_exit():
413     */
414     int useremul_exit(struct cpu *cpu, uint64_t arg0)
415     {
416     debug("[ exit(%i) ]\n", (int)arg0);
417     cpu->running = 0;
418     cpu->machine->exit_without_entering_debugger = 1;
419     return 0;
420     }
421    
422    
423     /*
424     * useremul_write():
425     */
426     int64_t useremul_write(struct cpu *cpu, int64_t *errnop,
427     uint64_t arg0, uint64_t arg1, uint64_t arg2)
428     {
429     int64_t res = 0;
430     *errnop = 0;
431     debug("[ write(%i,0x%llx,%lli) ]\n",
432     (int)arg0, (long long)arg1, (long long)arg2);
433     if (arg2 != 0) {
434     unsigned char *cp = get_userland_buf(cpu, arg1, arg2);
435     res = write(arg0, cp, arg2);
436     if (res < 0)
437     *errnop = errno;
438     free(cp);
439     }
440     return res;
441     }
442    
443    
444     /*
445     * useremul_break():
446     */
447     int64_t useremul_break(struct cpu *cpu, uint64_t arg0)
448     {
449     debug("[ break(0x%llx): TODO ]\n", (long long)arg0);
450    
451     /* TODO */
452     return 0;
453     }
454    
455    
456     /*
457     * useremul_getpid():
458     */
459     int64_t useremul_getpid(struct cpu *cpu)
460     {
461     int64_t pid = getpid();
462     debug("[ getpid(): %lli ]\n", (long long)pid);
463     return pid;
464     }
465    
466    
467     /*
468     * useremul_getuid():
469     */
470     int64_t useremul_getuid(struct cpu *cpu)
471     {
472     int64_t uid = getuid();
473     debug("[ getuid(): %lli ]\n", (long long)uid);
474     return uid;
475     }
476    
477    
478     /*
479     * useremul_getegid():
480     */
481     int64_t useremul_getegid(struct cpu *cpu)
482     {
483     int64_t egid = getegid();
484     debug("[ getegid(): %lli ]\n", (long long)egid);
485     return egid;
486     }
487    
488    
489     /*
490     * useremul_getgid():
491     */
492     int64_t useremul_getgid(struct cpu *cpu)
493     {
494     int64_t gid = getgid();
495     debug("[ getgid(): %lli ]\n", (long long)gid);
496     return gid;
497     }
498    
499    
500     /*
501     * useremul_sync():
502     */
503     int useremul_sync(struct cpu *cpu)
504     {
505     debug("[ sync() ]\n");
506     sync();
507     return 0;
508     }
509    
510    
511     /*
512     * useremul_readlink():
513     */
514     int64_t useremul_readlink(struct cpu *cpu, int64_t *errnop,
515     uint64_t arg0, uint64_t arg1, int64_t arg2)
516     {
517     int64_t res = 0;
518     unsigned char *charbuf = get_userland_string(cpu, arg0);
519     unsigned char *buf2;
520    
521     debug("[ readlink(\"%s\",0x%llx,%lli) ]\n",
522     charbuf, (long long)arg1, (long long)arg2);
523     if (arg2 == 0 || arg2 > 150000) {
524     fprintf(stderr, "[ useremul_readlink(): TODO ]\n");
525     exit(1);
526     }
527    
528     buf2 = malloc(arg2);
529     if (buf2 == NULL) {
530     fprintf(stderr, "[ useremul_readlink(): out of memory ]\n");
531     exit(1);
532     }
533     res = readlink((char *)charbuf, (char *)buf2, arg2);
534     buf2[arg2-1] = '\0';
535     if (res < 0)
536     *errnop = errno;
537     else
538     store_string(cpu, arg1, (char *)buf2);
539     free(buf2);
540     free(charbuf);
541     return res;
542     }
543    
544    
545     /*
546     * useremul_getrusage():
547     */
548     int64_t useremul_getrusage(struct cpu *cpu, int64_t *errnop,
549     uint64_t arg0, uint64_t arg1)
550     {
551     int64_t res;
552     struct rusage rusage;
553     debug("[ getrusage(%i,0x%llx) ]\n", (int)arg0, (long long)arg1);
554     res = getrusage(arg0, &rusage);
555    
556     fatal("TODO: convert rusage into emulated memory!\n");
557     store_64bit_word(cpu, arg1 + 0, rusage.ru_utime.tv_sec);
558     store_64bit_word(cpu, arg1 + 8, rusage.ru_utime.tv_usec);
559     store_64bit_word(cpu, arg1 + 16, rusage.ru_stime.tv_sec);
560     store_64bit_word(cpu, arg1 + 24, rusage.ru_stime.tv_usec);
561    
562     return res;
563     }
564    
565    
566     /*
567     * useremul_fstat():
568     */
569     int64_t useremul_fstat(struct cpu *cpu, int64_t *errnop,
570     int64_t arg0, uint64_t arg1)
571     {
572     int64_t res;
573     struct stat sb;
574     debug("[ fstat(%i,0x%llx) ]\n", (int)arg0, (long long)arg1);
575     res = fstat(arg0, &sb);
576     if (res < 0)
577     *errnop = errno;
578     else {
579     fatal("TODO: convert sb into emulated memory!\n");
580    
581     /* NOTE: FreeBSD/alpha only */
582    
583     store_32bit_word(cpu, arg1 + 0, sb.st_dev);
584     store_32bit_word(cpu, arg1 + 4, sb.st_ino);
585     /* store_16bit_word(cpu, arg1 + 8, sb.st_mode);
586     */ store_16bit_word(cpu, arg1 + 10, sb.st_nlink);
587     store_32bit_word(cpu, arg1 + 12, sb.st_uid);
588     store_32bit_word(cpu, arg1 + 16, sb.st_gid);
589     store_32bit_word(cpu, arg1 + 20, sb.st_rdev);
590     #if 0
591     store_64bit_word(cpu, arg1 + 24, sb.st_atimespec.tv_sec);
592     store_64bit_word(cpu, arg1 + 32, sb.st_atimespec.tv_nsec);
593     store_64bit_word(cpu, arg1 + 40, sb.st_mtimespec.tv_sec);
594     store_64bit_word(cpu, arg1 + 48, sb.st_mtimespec.tv_nsec);
595     store_64bit_word(cpu, arg1 + 56, sb.st_ctimespec.tv_sec);
596     store_64bit_word(cpu, arg1 + 64, sb.st_ctimespec.tv_nsec);
597    
598     store_64bit_word(cpu, arg1 + 72, sb.st_size);
599     store_64bit_word(cpu, arg1 + 80, sb.st_blocks);
600     store_64bit_word(cpu, arg1 + 88, sb.st_blksize);
601     store_64bit_word(cpu, arg1 + 92, sb.st_flags);
602     store_64bit_word(cpu, arg1 + 96, sb.st_gen);
603     #endif
604     }
605     return res;
606     }
607    
608    
609     /*
610     * useremul_mmap():
611     */
612     int64_t useremul_mmap(struct cpu *cpu, int64_t *errnop,
613     uint64_t arg0, int64_t arg1, int64_t arg2,
614     int64_t arg3, int64_t arg4, uint64_t arg5)
615     {
616     int64_t res = 0;
617    
618     /* arg0..5: addr, len, prot, flags, fd, offset */
619     debug("[ mmap(0x%llx,%lli,%i,%i,%i,%lli) ]\n",
620     (long long)arg0, (long long)arg1,
621     (int)arg2, (int)arg3, (int)arg4, (long long)arg5);
622    
623     if (arg4 != -1) {
624     fatal("[ useremul_mmap(): fd != -1: TODO ]\n");
625     cpu->running = 0;
626     return 0;
627     }
628    
629     /* Anonymous allocation. */
630     if (arg0 != 0) {
631     fatal("[ useremul_mmap(): addr != 0: TODO ]\n");
632     cpu->running = 0;
633     return 0;
634     }
635    
636     fatal("[ useremul_mmap(): TODO ]\n");
637    
638     res = 0x18000000ULL;
639    
640     return res;
641     }
642    
643    
644     /*****************************************************************************/
645    
646    
647     /*
648 dpavlin 2 * useremul__freebsd():
649     *
650 dpavlin 12 * FreeBSD/Alpha syscall emulation.
651 dpavlin 2 *
652     * TODO: How to make this work nicely with non-Alpha archs.
653     */
654     static void useremul__freebsd(struct cpu *cpu, uint32_t code)
655     {
656     int nr;
657 dpavlin 12 int64_t res = 0, err = 0;
658     uint64_t arg0, arg1, arg2, arg3, arg4, arg5;
659 dpavlin 2
660 dpavlin 12 nr = cpu->cd.alpha.r[ALPHA_V0];
661     arg0 = cpu->cd.alpha.r[ALPHA_A0];
662     arg1 = cpu->cd.alpha.r[ALPHA_A1];
663     arg2 = cpu->cd.alpha.r[ALPHA_A2];
664     arg3 = cpu->cd.alpha.r[ALPHA_A3];
665     arg4 = cpu->cd.alpha.r[ALPHA_A4];
666     arg5 = cpu->cd.alpha.r[ALPHA_A5];
667 dpavlin 2
668 dpavlin 12 if (nr == 198) {
669     /* ___syscall */
670     nr = arg0;
671     arg0 = arg1;
672     arg1 = arg2;
673     arg2 = arg3;
674     arg3 = arg4;
675     arg4 = arg5;
676     /* TODO: stack arguments */
677     }
678    
679 dpavlin 2 switch (nr) {
680    
681 dpavlin 12 case 1: res = useremul_exit(cpu, arg0);
682 dpavlin 2 break;
683    
684 dpavlin 12 case 4: res = useremul_write(cpu, &err, arg0, arg1, arg2);
685 dpavlin 2 break;
686    
687 dpavlin 12 case 17:res = useremul_break(cpu, arg0);
688     break;
689    
690     case 20:res = useremul_getpid(cpu);
691     break;
692    
693     case 24:res = useremul_getuid(cpu);
694     break;
695    
696     case 43:res = useremul_getegid(cpu);
697     break;
698    
699     case 47:res = useremul_getgid(cpu);
700     break;
701    
702     case 58:res = useremul_readlink(cpu, &err, arg0, arg1, arg2);
703     break;
704    
705 dpavlin 22 case 73:/* munmap. TODO */
706     res = 1;
707     break;
708    
709 dpavlin 12 case 117:res = useremul_getrusage(cpu, &err, arg0, arg1);
710     break;
711    
712     case 189:res = useremul_fstat(cpu, &err, arg0, arg1);
713     break;
714    
715     case 197:res = useremul_mmap(cpu, &err, arg0, arg1, arg2, arg3,
716     arg4, arg5);
717     break;
718    
719     default:fatal("useremul__freebsd(): syscall %i not yet "
720     "implemented\n", nr);
721 dpavlin 2 cpu->running = 0;
722     }
723 dpavlin 12
724     if (err) {
725     cpu->cd.alpha.r[ALPHA_A3] = 1;
726     cpu->cd.alpha.r[ALPHA_V0] = err;
727     } else {
728     cpu->cd.alpha.r[ALPHA_A3] = 0;
729     cpu->cd.alpha.r[ALPHA_V0] = res;
730     }
731 dpavlin 2 }
732    
733    
734     /*
735     * useremul__linux():
736     *
737     * Linux syscall emulation.
738     *
739     * TODO: How to make this work nicely with non-PPC archs.
740     */
741     static void useremul__linux(struct cpu *cpu, uint32_t code)
742     {
743     int nr;
744 dpavlin 12 int64_t res = 0, err = 0;
745 dpavlin 2 uint64_t arg0, arg1, arg2, arg3;
746    
747     if (code != 0) {
748     fatal("useremul__linux(): code %i: TODO\n", (int)code);
749     exit(1);
750     }
751    
752     nr = cpu->cd.ppc.gpr[0];
753     arg0 = cpu->cd.ppc.gpr[3];
754     arg1 = cpu->cd.ppc.gpr[4];
755     arg2 = cpu->cd.ppc.gpr[5];
756     arg3 = cpu->cd.ppc.gpr[6];
757    
758     switch (nr) {
759    
760     case LINUX_PPC_SYS_exit:
761 dpavlin 12 res = useremul_exit(cpu, arg0);
762 dpavlin 2 break;
763    
764     case LINUX_PPC_SYS_write:
765 dpavlin 12 res = useremul_write(cpu, &err, arg0, arg1, arg2);
766 dpavlin 2 break;
767    
768     default:
769     fatal("useremul__linux(): syscall %i not yet implemented\n",
770     nr);
771     cpu->running = 0;
772     }
773 dpavlin 12
774     /* return res: TODO */
775 dpavlin 2 }
776    
777    
778     /*
779     * useremul__netbsd():
780     *
781     * NetBSD syscall emulation.
782     */
783     static void useremul__netbsd(struct cpu *cpu, uint32_t code)
784     {
785     int error_flag = 0, result_high_set = 0;
786     uint64_t arg0=0,arg1=0,arg2=0,arg3=0,stack0=0,stack1=0,stack2=0;
787     int sysnr = 0;
788 dpavlin 12 int64_t error_code = 0;
789 dpavlin 2 uint64_t result_low = 0;
790     uint64_t result_high = 0;
791     struct timeval tv;
792     struct timezone tz;
793     int descr;
794     uint64_t length, mipsbuf, flags;
795     unsigned char *charbuf;
796     uint32_t sysctl_name, sysctl_namelen, sysctl_oldp,
797     sysctl_oldlenp, sysctl_newp, sysctl_newlen;
798     uint32_t name0, name1, name2, name3;
799    
800     switch (cpu->machine->arch) {
801     case ARCH_MIPS:
802     sysnr = cpu->cd.mips.gpr[MIPS_GPR_V0];
803     if (sysnr == NETBSD_SYS___syscall) {
804     sysnr = cpu->cd.mips.gpr[MIPS_GPR_A0] +
805     (cpu->cd.mips.gpr[MIPS_GPR_A1] << 32);
806     arg0 = cpu->cd.mips.gpr[MIPS_GPR_A2];
807     arg1 = cpu->cd.mips.gpr[MIPS_GPR_A3];
808     /* TODO: stack arguments? Are these correct? */
809     arg2 = load_32bit_word(cpu,
810     cpu->cd.mips.gpr[MIPS_GPR_SP] + 8);
811     arg3 = load_32bit_word(cpu,
812     cpu->cd.mips.gpr[MIPS_GPR_SP] + 16);
813     stack0 = load_32bit_word(cpu,
814     cpu->cd.mips.gpr[MIPS_GPR_SP] + 24);
815     stack1 = load_32bit_word(cpu,
816     cpu->cd.mips.gpr[MIPS_GPR_SP] + 32);
817     stack2 = load_32bit_word(cpu,
818     cpu->cd.mips.gpr[MIPS_GPR_SP] + 40);
819     } else {
820     arg0 = cpu->cd.mips.gpr[MIPS_GPR_A0];
821     arg1 = cpu->cd.mips.gpr[MIPS_GPR_A1];
822     arg2 = cpu->cd.mips.gpr[MIPS_GPR_A2];
823     arg3 = cpu->cd.mips.gpr[MIPS_GPR_A3];
824     /* TODO: stack arguments? Are these correct? */
825     stack0 = load_32bit_word(cpu,
826     cpu->cd.mips.gpr[MIPS_GPR_SP] + 4);
827     stack1 = load_32bit_word(cpu,
828     cpu->cd.mips.gpr[MIPS_GPR_SP] + 8);
829     stack2 = load_32bit_word(cpu,
830     cpu->cd.mips.gpr[MIPS_GPR_SP] + 12);
831     }
832     break;
833    
834     case ARCH_PPC:
835     sysnr = cpu->cd.ppc.gpr[0];
836     arg0 = cpu->cd.ppc.gpr[3];
837     arg1 = cpu->cd.ppc.gpr[4];
838     arg2 = cpu->cd.ppc.gpr[5];
839     arg3 = cpu->cd.ppc.gpr[6];
840     /* TODO: More arguments? Stack arguments? */
841     break;
842 dpavlin 14
843     case ARCH_ARM:
844     sysnr = code & 0xfffff;
845     arg0 = cpu->cd.arm.r[0];
846     arg1 = cpu->cd.arm.r[1];
847     arg2 = cpu->cd.arm.r[2];
848     arg3 = cpu->cd.arm.r[3];
849     /* TODO: More arguments? Stack arguments? */
850     break;
851    
852     default:fatal("netbsd syscall for this arch: TODO\n");
853     exit(1);
854 dpavlin 2 }
855    
856     /*
857 dpavlin 18 * NOTE/TODO: The following code should not be CPU arch dependent!
858 dpavlin 2 */
859    
860     switch (sysnr) {
861    
862     case NETBSD_SYS_exit:
863     debug("[ exit(%i) ]\n", (int)arg0);
864     cpu->running = 0;
865     cpu->machine->exit_without_entering_debugger = 1;
866     break;
867    
868     case NETBSD_SYS_read:
869     debug("[ read(%i,0x%llx,%lli) ]\n",
870     (int)arg0, (long long)arg1, (long long)arg2);
871    
872     if (arg2 != 0) {
873     charbuf = malloc(arg2);
874     if (charbuf == NULL) {
875     fprintf(stderr, "out of memory in "
876     "useremul__netbsd()\n");
877     exit(1);
878     }
879     result_low = read(arg0, charbuf, arg2);
880     if ((int64_t)result_low < 0) {
881     error_code = errno;
882     error_flag = 1;
883     }
884    
885     /* TODO: address validity check */
886     cpu->memory_rw(cpu, cpu->mem, arg1, charbuf,
887     arg2, MEM_WRITE, CACHE_DATA);
888     free(charbuf);
889     }
890     break;
891    
892     case NETBSD_SYS_write:
893     descr = arg0;
894     mipsbuf = arg1;
895     length = arg2;
896     debug("[ write(%i,0x%llx,%lli) ]\n",
897     (int)descr, (long long)mipsbuf, (long long)length);
898     if (length != 0) {
899     charbuf = malloc(length);
900     if (charbuf == NULL) {
901     fprintf(stderr, "out of memory in "
902     "useremul__netbsd()\n");
903     exit(1);
904     }
905     /* TODO: address validity check */
906     cpu->memory_rw(cpu, cpu->mem, mipsbuf, charbuf,
907     length, MEM_READ, CACHE_DATA);
908     result_low = write(descr, charbuf, length);
909     if ((int64_t)result_low < 0) {
910     error_code = errno;
911     error_flag = 1;
912     }
913     free(charbuf);
914     }
915     break;
916    
917     case NETBSD_SYS_open:
918     charbuf = get_userland_string(cpu, arg0);
919     debug("[ open(\"%s\", 0x%llx, 0x%llx) ]\n",
920     charbuf, (long long)arg1, (long long)arg2);
921     result_low = open((char *)charbuf, arg1, arg2);
922     if ((int64_t)result_low < 0) {
923     error_flag = 1;
924     error_code = errno;
925     }
926     free(charbuf);
927     break;
928    
929     case NETBSD_SYS_close:
930     descr = arg0;
931     debug("[ close(%i) ]\n", (int)descr);
932     error_code = close(descr);
933     if (error_code != 0)
934     error_flag = 1;
935     break;
936    
937     case NETBSD_SYS_access:
938     charbuf = get_userland_string(cpu, arg0);
939     debug("[ access(\"%s\", 0x%llx) ]\n",
940     charbuf, (long long) arg1);
941     result_low = access((char *)charbuf, arg1);
942     if (result_low != 0) {
943     error_flag = 1;
944     error_code = errno;
945     }
946     free(charbuf);
947     break;
948    
949     case NETBSD_SYS_getuid:
950 dpavlin 12 result_low = useremul_getuid(cpu);
951 dpavlin 2 break;
952    
953     case NETBSD_SYS_geteuid:
954     debug("[ geteuid() ]\n");
955     result_low = geteuid();
956     break;
957    
958     case NETBSD_SYS_getgid:
959     debug("[ getgid() ]\n");
960     result_low = getgid();
961     break;
962    
963     case NETBSD_SYS_getegid:
964     debug("[ getegid() ]\n");
965     result_low = getegid();
966     break;
967    
968     case NETBSD_SYS_getfsstat:
969     mipsbuf = arg0;
970     length = arg1;
971     flags = arg2;
972     debug("[ getfsstat(0x%llx,%lli,0x%llx) ]\n",
973     (long long)mipsbuf, (long long)length,
974     (long long)flags);
975    
976     result_low = 0; /* nr of mounted filesystems,
977     for now (TODO) */
978    
979     /* Fill in the struct statfs buffer at arg0...
980     copy data from the host's getfsstat(). TODO */
981     #if 1
982     result_low = 1;
983     store_32bit_word(cpu, mipsbuf + 0, 0); /* f_spare2 */
984     store_32bit_word(cpu, mipsbuf + 4, 1024); /* f_bsize */
985     store_32bit_word(cpu, mipsbuf + 8, 65536); /* f_iosize */
986     store_32bit_word(cpu, mipsbuf + 12, 100); /* f_blocks */
987     store_32bit_word(cpu, mipsbuf + 16, 50); /* f_bfree */
988     store_32bit_word(cpu, mipsbuf + 20, 10); /* f_bavail */
989     store_32bit_word(cpu, mipsbuf + 24, 50); /* f_files */
990     store_32bit_word(cpu, mipsbuf + 28, 25); /* f_ffree */
991     store_32bit_word(cpu, mipsbuf + 28, 0x1234); /* f_fsid */
992     store_32bit_word(cpu, mipsbuf + 32, 0); /* f_owner */
993     store_32bit_word(cpu, mipsbuf + 36, 0); /* f_type */
994     store_32bit_word(cpu, mipsbuf + 40, 0); /* f_flags */
995     store_32bit_word(cpu, mipsbuf + 44, 0); /* f_fspare[0] */
996     store_32bit_word(cpu, mipsbuf + 48, 0); /* f_fspare[1] */
997     store_string(cpu, mipsbuf + 52, "ffs"); /* f_typename */
998     #define MFSNAMELEN 16
999     #define MNAMELEN 90
1000     store_string(cpu, mipsbuf + 52 + MFSNAMELEN, "/");
1001     /* f_mntonname */
1002     store_string(cpu, mipsbuf + 52 + MFSNAMELEN + MNAMELEN, "ffs");
1003     /* f_mntfromname */
1004     #endif
1005     break;
1006    
1007     case NETBSD_SYS_break:
1008 dpavlin 12 useremul_break(cpu, arg0);
1009 dpavlin 2 break;
1010    
1011     case NETBSD_SYS_readlink:
1012 dpavlin 12 result_low = useremul_readlink(cpu, &error_code,
1013     arg0, arg1, arg2);
1014 dpavlin 2 break;
1015    
1016     case NETBSD_SYS_sync:
1017 dpavlin 12 useremul_sync(cpu);
1018 dpavlin 2 break;
1019    
1020     case NETBSD_SYS_gettimeofday:
1021     debug("[ gettimeofday(0x%llx,0x%llx) ]\n",
1022     (long long)arg0, (long long)arg1);
1023     result_low = gettimeofday(&tv, &tz);
1024     if (result_low) {
1025     error_flag = 1;
1026     error_code = errno;
1027     } else {
1028     if (arg0 != 0) {
1029     /* Store tv.tv_sec and tv.tv_usec as
1030     'long' (32-bit) values: */
1031     store_32bit_word(cpu, arg0 + 0,
1032     tv.tv_sec);
1033     store_32bit_word(cpu, arg0 + 4,
1034     tv.tv_usec);
1035     }
1036     if (arg1 != 0) {
1037     /* Store tz.tz_minuteswest and
1038     tz.tz_dsttime as 'long'
1039     (32-bit) values: */
1040     store_32bit_word(cpu, arg1 + 0,
1041     tz.tz_minuteswest);
1042     store_32bit_word(cpu, arg1 + 4,
1043     tz.tz_dsttime);
1044     }
1045     }
1046     break;
1047    
1048     case NETBSD_SYS_mmap:
1049     debug("[ mmap(0x%x,%i,%i,%i,%i,0x%llx): TODO ]\n",
1050     arg0, arg1, arg2, arg3, stack0, (long long)stack1);
1051    
1052     if ((int32_t)stack0 == -1) {
1053     /*
1054     * Anonymous allocation:
1055     *
1056     * TODO: Fix this!!!
1057     *
1058     * This quick hack simply allocates anonymous
1059     * mmap memory approximately below the stack.
1060     * This will probably not work with dynamically
1061     * loaded libraries and such.
1062     */
1063     static uint32_t mmap_anon_ptr = 0x70000000;
1064     mmap_anon_ptr -= arg1;
1065     /* round down to page boundary: */
1066     mmap_anon_ptr &= ~4095;
1067     debug("ANON: %i bytes at 0x%08x (TODO: not "
1068     "working yet?)\n", (int)arg1,
1069     mmap_anon_ptr);
1070     result_low = mmap_anon_ptr;
1071     } else {
1072     /* Return NULL for now */
1073     }
1074     break;
1075    
1076     case NETBSD_SYS_dup:
1077     debug("[ dup(%i) ]\n", (int)arg0);
1078     result_low = dup(arg0);
1079     if ((int64_t)result_low < 0) {
1080     error_code = errno;
1081     error_flag = 1;
1082     }
1083     break;
1084    
1085     case NETBSD_SYS_socket:
1086     debug("[ socket(%i,%i,%i) ]\n",
1087     (int)arg0, (int)arg1, (int)arg2);
1088     result_low = socket(arg0,arg1,arg2);
1089     if ((int64_t)result_low < 0) {
1090     error_code = errno;
1091     error_flag = 1;
1092     }
1093     break;
1094    
1095     case NETBSD_SYS_issetugid:
1096     debug("[ issetugid() ]\n");
1097     /* TODO: actually call the real issetugid? */
1098     break;
1099    
1100     case NETBSD_SYS_nanosleep:
1101     debug("[ nanosleep(0x%llx,0x%llx) ]\n",
1102     (long long)arg0, (long long)arg1);
1103    
1104     if (arg0 != 0) {
1105     uint32_t sec = load_32bit_word(cpu, arg0 + 0);
1106     uint32_t nsec = load_32bit_word(cpu, arg0 + 4);
1107     struct timespec ts;
1108     ts.tv_sec = sec;
1109     ts.tv_nsec = nsec;
1110     result_low = nanosleep(&ts, NULL);
1111     if (result_low)
1112     fprintf(stderr, "netbsd emulation "
1113     "nanosleep() failed\n");
1114     /* TODO: arg1 */
1115     } else {
1116     error_flag = 1;
1117     error_code = 14; /* EFAULT */
1118     }
1119     break;
1120    
1121     case NETBSD_SYS___fstat13:
1122     debug("[ __fstat13(%lli,0x%llx): TODO ]\n",
1123     (long long)arg0, (long long)arg1);
1124     error_flag = 1;
1125     error_code = 9; /* EBADF */
1126     break;
1127    
1128     case NETBSD_SYS___getcwd:
1129     debug("[ __getcwd(0x%llx,%lli): TODO ]\n",
1130     (long long)arg0, (long long)arg1);
1131     if (arg1 != 0 && arg1 < 500000) {
1132     char *buf = malloc(arg1);
1133     unsigned int i;
1134    
1135     getcwd(buf, arg1);
1136    
1137     /* zero-terminate in host's space: */
1138     buf[arg1 - 1] = 0;
1139    
1140     for (i = 0; i<arg1 && i < arg1; i++)
1141     cpu->memory_rw(cpu, cpu->mem, arg0 + i,
1142     (unsigned char *)&buf[i], 1,
1143     MEM_WRITE, CACHE_NONE);
1144    
1145     /* zero-terminate in emulated space: */
1146     cpu->memory_rw(cpu, cpu->mem, arg0 + arg1-1,
1147     (unsigned char *)&buf[arg1 - 1],
1148     1, MEM_WRITE, CACHE_NONE);
1149    
1150     free(buf);
1151     }
1152     result_low = arg0;
1153     break;
1154    
1155     case NETBSD_SYS___sigaction14:
1156     debug("[ __sigaction14(%lli,0x%llx,0x%llx): TODO ]\n",
1157     (long long)arg0, (long long)arg1, (long long)arg2);
1158     error_flag = 1;
1159     error_code = 9; /* EBADF */
1160     break;
1161    
1162     case NETBSD_SYS___sysctl:
1163     sysctl_name = arg0;
1164     sysctl_namelen = arg1;
1165     sysctl_oldp = arg2;
1166     sysctl_oldlenp = arg3;
1167     sysctl_newp = load_32bit_word(cpu,
1168     cpu->cd.mips.gpr[MIPS_GPR_SP]);
1169     /* TODO: +4 and +8 ?? */
1170     sysctl_newlen = load_32bit_word(cpu,
1171     cpu->cd.mips.gpr[MIPS_GPR_SP] + 4);
1172     debug("[ __sysctl(");
1173    
1174     name0 = load_32bit_word(cpu, sysctl_name + 0);
1175     name1 = load_32bit_word(cpu, sysctl_name + 4);
1176     name2 = load_32bit_word(cpu, sysctl_name + 8);
1177     name3 = load_32bit_word(cpu, sysctl_name + 12);
1178     debug("name (@ 0x%08x) = %i, %i, %i, %i) ]\n",
1179     sysctl_name, name0, name1, name2, name3);
1180    
1181     if (name0 == CTL_KERN && name1 == KERN_HOSTNAME) {
1182     char hname[256];
1183     hname[0] = '\0';
1184     gethostname(hname, sizeof(hname));
1185     hname[sizeof(hname)-1] = '\0';
1186     if (sysctl_oldp != 0)
1187     store_string(cpu, sysctl_oldp, hname);
1188     if (sysctl_oldlenp != 0)
1189     store_32bit_word(cpu, sysctl_oldlenp,
1190     strlen(hname));
1191     } else if (name0 == CTL_HW && name1 == HW_PAGESIZE) {
1192     if (sysctl_oldp != 0)
1193     store_32bit_word(cpu,
1194     sysctl_oldp, 4096);
1195     if (sysctl_oldlenp != 0)
1196     store_32bit_word(cpu,
1197     sysctl_oldlenp, sizeof(uint32_t));
1198     } else {
1199     error_flag = 1;
1200     error_code = 2; /* ENOENT */
1201     }
1202     break;
1203    
1204     default:
1205     fatal("[ UNIMPLEMENTED netbsd syscall %i ]\n", sysnr);
1206     error_flag = 1;
1207     error_code = 78; /* ENOSYS */
1208     }
1209    
1210    
1211     switch (cpu->machine->arch) {
1212 dpavlin 14 case ARCH_ARM:
1213     /* NetBSD/arm return values: */
1214     cpu->cd.arm.r[0] = result_low;
1215     cpu->cd.arm.cpsr &= ~ARM_FLAG_C;
1216     if (error_flag) {
1217     cpu->cd.arm.cpsr |= ARM_FLAG_C;
1218     cpu->cd.arm.r[0] = error_code;
1219     }
1220     if (result_high_set)
1221     cpu->cd.arm.r[1] = result_high;
1222 dpavlin 20 cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
1223 dpavlin 14 break;
1224 dpavlin 2 case ARCH_MIPS:
1225     /*
1226     * NetBSD/mips return values:
1227     *
1228     * a3 is 0 if the syscall was ok, otherwise 1.
1229     * v0 (and sometimes v1) contain the result value.
1230     */
1231     cpu->cd.mips.gpr[MIPS_GPR_A3] = error_flag;
1232     if (error_flag)
1233     cpu->cd.mips.gpr[MIPS_GPR_V0] = error_code;
1234     else
1235     cpu->cd.mips.gpr[MIPS_GPR_V0] = result_low;
1236    
1237     if (result_high_set)
1238     cpu->cd.mips.gpr[MIPS_GPR_V1] = result_high;
1239     break;
1240     case ARCH_PPC:
1241     /*
1242     * NetBSD/powerpc return values:
1243     *
1244     * TODO
1245     */
1246     cpu->cd.ppc.gpr[3] = result_low;
1247    
1248     if (result_high_set)
1249     cpu->cd.ppc.gpr[4] = result_high;
1250     break;
1251     }
1252     }
1253    
1254    
1255     /*
1256     * useremul__ultrix():
1257     *
1258     * Ultrix syscall emulation.
1259     */
1260     static void useremul__ultrix(struct cpu *cpu, uint32_t code)
1261     {
1262     int error_flag = 0, result_high_set = 0;
1263     uint64_t arg0,arg1,arg2,arg3,stack0=0,stack1=0,stack2;
1264     int sysnr = 0;
1265 dpavlin 12 int64_t error_code = 0;
1266 dpavlin 2 uint64_t result_low = 0;
1267     uint64_t result_high = 0;
1268     struct timeval tv;
1269     struct timezone tz;
1270     int descr;
1271     uint64_t length, mipsbuf;
1272     unsigned char *charbuf;
1273    
1274     /*
1275     * Ultrix/pmax gets the syscall number in register v0,
1276     * and syscall arguments in registers a0, a1, ...
1277     *
1278     * TODO: If there is a __syscall-like syscall (as in NetBSD)
1279     * then 64-bit args may be passed in two registers or something...
1280     * If so, then copy from the section above (NetBSD).
1281     */
1282     sysnr = cpu->cd.mips.gpr[MIPS_GPR_V0];
1283    
1284     arg0 = cpu->cd.mips.gpr[MIPS_GPR_A0];
1285     arg1 = cpu->cd.mips.gpr[MIPS_GPR_A1];
1286     arg2 = cpu->cd.mips.gpr[MIPS_GPR_A2];
1287     arg3 = cpu->cd.mips.gpr[MIPS_GPR_A3];
1288     /* TODO: stack arguments? Are these correct? */
1289     stack0 = load_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_SP] + 0);
1290     stack1 = load_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_SP] + 4);
1291     stack2 = load_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_SP] + 8);
1292    
1293     switch (sysnr) {
1294    
1295     case ULTRIX_SYS_exit:
1296     debug("[ exit(%i) ]\n", (int)arg0);
1297     cpu->running = 0;
1298     cpu->machine->exit_without_entering_debugger = 1;
1299     break;
1300    
1301     case ULTRIX_SYS_read:
1302     debug("[ read(%i,0x%llx,%lli) ]\n",
1303     (int)arg0, (long long)arg1, (long long)arg2);
1304    
1305     if (arg2 != 0) {
1306     charbuf = malloc(arg2);
1307     if (charbuf == NULL) {
1308     fprintf(stderr, "out of memory in "
1309     "useremul__ultrix()\n");
1310     exit(1);
1311     }
1312    
1313     result_low = read(arg0, charbuf, arg2);
1314     if ((int64_t)result_low < 0) {
1315     error_code = errno;
1316     error_flag = 1;
1317     }
1318    
1319     /* TODO: address validity check */
1320     cpu->memory_rw(cpu, cpu->mem, arg1, charbuf,
1321     arg2, MEM_WRITE, CACHE_DATA);
1322    
1323     free(charbuf);
1324     }
1325     break;
1326    
1327     case ULTRIX_SYS_write:
1328     descr = arg0;
1329     mipsbuf = arg1;
1330     length = arg2;
1331     debug("[ write(%i,0x%llx,%lli) ]\n",
1332     (int)descr, (long long)mipsbuf, (long long)length);
1333    
1334     if (length != 0) {
1335     charbuf = malloc(length);
1336     if (charbuf == NULL) {
1337     fprintf(stderr, "out of memory in "
1338     "useremul__ultrix()\n");
1339     exit(1);
1340     }
1341    
1342     /* TODO: address validity check */
1343     cpu->memory_rw(cpu, cpu->mem, mipsbuf, charbuf,
1344     length, MEM_READ, CACHE_DATA);
1345    
1346     result_low = write(descr, charbuf, length);
1347     if ((int64_t)result_low < 0) {
1348     error_code = errno;
1349     error_flag = 1;
1350     }
1351     free(charbuf);
1352     }
1353     break;
1354    
1355     case ULTRIX_SYS_open:
1356     charbuf = get_userland_string(cpu, arg0);
1357     debug("[ open(\"%s\", 0x%llx, 0x%llx) ]\n",
1358     charbuf, (long long)arg1, (long long)arg2);
1359    
1360     result_low = open((char *)charbuf, arg1, arg2);
1361     if ((int64_t)result_low < 0) {
1362     error_flag = 1;
1363     error_code = errno;
1364     }
1365     free(charbuf);
1366     break;
1367    
1368     case ULTRIX_SYS_close:
1369     descr = arg0;
1370     debug("[ close(%i) ]\n", (int)descr);
1371    
1372     /* Special case because some Ultrix programs tend
1373     to close low descriptors: */
1374     if (descr <= 2) {
1375     error_flag = 1;
1376     error_code = 2; /* TODO: Ultrix ENOENT error code */
1377     break;
1378     }
1379    
1380     error_code = close(descr);
1381     if (error_code != 0)
1382     error_flag = 1;
1383     break;
1384    
1385     case ULTRIX_SYS_break:
1386 dpavlin 12 useremul_break(cpu, arg0);
1387 dpavlin 2 break;
1388    
1389     case ULTRIX_SYS_sync:
1390 dpavlin 12 useremul_sync(cpu);
1391 dpavlin 2 break;
1392    
1393     case ULTRIX_SYS_getuid:
1394 dpavlin 12 result_low = useremul_getuid(cpu);
1395 dpavlin 2 break;
1396    
1397     case ULTRIX_SYS_getgid:
1398     debug("[ getgid() ]\n");
1399     result_low = getgid();
1400     break;
1401    
1402     case ULTRIX_SYS_dup:
1403     debug("[ dup(%i) ]\n", (int)arg0);
1404     result_low = dup(arg0);
1405     if ((int64_t)result_low < 0) {
1406     error_code = errno;
1407     error_flag = 1;
1408     }
1409     break;
1410    
1411     case ULTRIX_SYS_socket:
1412     debug("[ socket(%i,%i,%i) ]\n",
1413     (int)arg0, (int)arg1, (int)arg2);
1414     result_low = socket(arg0,arg1,arg2);
1415     if ((int64_t)result_low < 0) {
1416     error_code = errno;
1417     error_flag = 1;
1418     }
1419     break;
1420    
1421     case ULTRIX_SYS_select:
1422     debug("[ select(%i,0x%x,0x%x,0x%x,0x%x): TODO ]\n",
1423     (int)arg0, (int)arg1, (int)arg2, (int)arg3, (int)stack0);
1424    
1425     /* TODO */
1426     {
1427     fd_set fdset;
1428     FD_SET(3, &fdset);
1429     result_low = select(4, &fdset, NULL, NULL, NULL);
1430     }
1431     break;
1432    
1433     case ULTRIX_SYS_setsockopt:
1434     debug("[ setsockopt(%i,%i,%i,0x%x,%i): TODO ]\n",
1435     (int)arg0, (int)arg1, (int)arg2, (int)arg3, (int)stack0);
1436     /* TODO: len is not 4, len is stack0? */
1437     charbuf = get_userland_buf(cpu, arg3, 4);
1438     /* TODO: endianness of charbuf, etc */
1439     result_low = setsockopt(arg0, arg1, arg2, (void *)charbuf, 4);
1440     if ((int64_t)result_low < 0) {
1441     error_code = errno;
1442     error_flag = 1;
1443     }
1444     free(charbuf);
1445     printf("setsockopt!!!! res = %i error=%i\n",
1446     (int)result_low, (int)error_code);
1447     break;
1448    
1449     case ULTRIX_SYS_connect:
1450     debug("[ connect(%i,0x%x,%i) ]\n",
1451     (int)arg0, (int)arg1, (int)arg2);
1452     charbuf = get_userland_buf(cpu, arg1, arg2);
1453     result_low = connect(arg0, (void *)charbuf, arg2);
1454     if ((int64_t)result_low < 0) {
1455     error_code = errno;
1456     error_flag = 1;
1457     }
1458     printf("connect!!!! res = %i error=%i\n",
1459     (int)result_low, (int)error_code);
1460     free(charbuf);
1461     break;
1462    
1463     case ULTRIX_SYS_fcntl:
1464     debug("[ fcntl(%i,%i,0x%x): TODO ]\n",
1465     (int)arg0, (int)arg1, (int)arg2);
1466     /* TODO: how about that third argument? */
1467     result_low = fcntl(arg0, arg1, arg2);
1468     if ((int64_t)result_low < 0) {
1469     error_code = errno;
1470     error_flag = 1;
1471     }
1472     printf("fcntl!!!! res = %i error=%i\n",
1473     (int)result_low, (int)error_code);
1474     break;
1475    
1476     case ULTRIX_SYS_stat43:
1477     charbuf = get_userland_string(cpu, arg0);
1478     debug("[ stat(\"%s\", 0x%llx): TODO ]\n",
1479     charbuf, (long long)arg1);
1480    
1481     if (arg1 != 0) {
1482     struct stat st;
1483     result_low = stat((char *)charbuf, &st);
1484     if ((int64_t)result_low < 0) {
1485     error_flag = 1;
1486     error_code = errno;
1487     } else {
1488     /* Fill in the Ultrix stat struct at arg1: */
1489    
1490     /* TODO */
1491     }
1492     } else {
1493     error_flag = 1;
1494     error_code = 1111; /* TODO: ultrix ENOMEM? */
1495     }
1496     free(charbuf);
1497     break;
1498    
1499     case ULTRIX_SYS_fstat:
1500 dpavlin 12 result_low = useremul_fstat(cpu, &error_code, arg0, arg1);
1501 dpavlin 2 break;
1502    
1503     case ULTRIX_SYS_getpagesize:
1504     debug("[ getpagesize() ]\n");
1505     result_low = 4096;
1506     break;
1507    
1508     case ULTRIX_SYS_getdtablesize:
1509     debug("[ getdtablesize() ]\n");
1510     result_low = getdtablesize();
1511     break;
1512    
1513     case ULTRIX_SYS_gethostname:
1514     debug("[ gethostname(0x%llx,%lli) ]\n",
1515     (long long)arg0, (long long)arg1);
1516     result_low = 0;
1517     if (arg1 != 0 && arg1 < 500000) {
1518     unsigned char *buf = malloc(arg1);
1519     unsigned int i;
1520    
1521     result_low = gethostname((char *)buf, arg1);
1522     for (i = 0; i<arg1 && i < arg1; i++)
1523     cpu->memory_rw(cpu, cpu->mem, arg0 + i,
1524     &buf[i], 1, MEM_WRITE, CACHE_NONE);
1525    
1526     free(buf);
1527     } else {
1528     error_flag = 1;
1529     error_code = 5555; /* TODO */ /* ENOMEM */
1530     }
1531     break;
1532    
1533     case ULTRIX_SYS_writev:
1534     descr = arg0;
1535     debug("[ writev(%lli,0x%llx,%lli) ]\n",
1536     (long long)arg0, (long long)arg1, (long long)arg2);
1537    
1538     if (arg1 != 0) {
1539     unsigned int i, total = 0;
1540    
1541     for (i=0; i<arg2; i++) {
1542     uint32_t iov_base, iov_len;
1543     iov_base = load_32bit_word(cpu,
1544     arg1 + 8*i + 0); /* char * */
1545     iov_len = load_32bit_word(cpu,
1546     arg1 + 8*i + 4); /* size_t */
1547    
1548     if (iov_len != 0) {
1549     unsigned char *charbuf =
1550     malloc(iov_len);
1551     if (charbuf == NULL) {
1552     fprintf(stderr, "out of memory"
1553     " in useremul__ultrix()\n");
1554     exit(1);
1555     }
1556    
1557     /* TODO: address validity check */
1558     cpu->memory_rw(cpu, cpu->mem, (uint64_t)
1559     iov_base, charbuf, iov_len,
1560     MEM_READ, CACHE_DATA);
1561     total += write(descr, charbuf, iov_len);
1562     free(charbuf);
1563     }
1564     }
1565    
1566     result_low = total;
1567     }
1568     break;
1569    
1570     case ULTRIX_SYS_gethostid:
1571     debug("[ gethostid() ]\n");
1572     /* This is supposed to return a unique 32-bit host id. */
1573     result_low = 0x12345678;
1574     break;
1575    
1576     case ULTRIX_SYS_gettimeofday:
1577     debug("[ gettimeofday(0x%llx,0x%llx) ]\n",
1578     (long long)arg0, (long long)arg1);
1579     result_low = gettimeofday(&tv, &tz);
1580     if (result_low) {
1581     error_flag = 1;
1582     error_code = errno;
1583     } else {
1584     if (arg0 != 0) {
1585     /* Store tv.tv_sec and tv.tv_usec
1586     as 'long' (32-bit) values: */
1587     store_32bit_word(cpu, arg0 + 0, tv.tv_sec);
1588     store_32bit_word(cpu, arg0 + 4, tv.tv_usec);
1589     }
1590     if (arg1 != 0) {
1591     /* Store tz.tz_minuteswest and
1592     tz.tz_dsttime as 'long' (32-bit) values: */
1593     store_32bit_word(cpu, arg1 + 0,
1594     tz.tz_minuteswest);
1595     store_32bit_word(cpu, arg1 + 4, tz.tz_dsttime);
1596     }
1597     }
1598     break;
1599    
1600     default:
1601     fatal("[ UNIMPLEMENTED ultrix syscall %i ]\n", sysnr);
1602     error_flag = 1;
1603     error_code = 78; /* ENOSYS */
1604     }
1605    
1606     /*
1607     * Ultrix/mips return values:
1608     *
1609     * TODO
1610     *
1611     * a3 is 0 if the syscall was ok, otherwise 1.
1612     * v0 (and sometimes v1) contain the result value.
1613     */
1614     cpu->cd.mips.gpr[MIPS_GPR_A3] = error_flag;
1615     if (error_flag)
1616     cpu->cd.mips.gpr[MIPS_GPR_V0] = error_code;
1617     else
1618     cpu->cd.mips.gpr[MIPS_GPR_V0] = result_low;
1619    
1620     if (result_high_set)
1621     cpu->cd.mips.gpr[MIPS_GPR_V1] = result_high;
1622    
1623     /* TODO */
1624     }
1625    
1626    
1627     /*
1628     * useremul_name_to_useremul():
1629     *
1630     * Example:
1631     * Input: name = "netbsd/pmax"
1632     * Output: sets *arch = ARCH_MIPS, *machine_name = "NetBSD/pmax",
1633     * and *cpu_name = "R3000".
1634     */
1635     void useremul_name_to_useremul(struct cpu *cpu, char *name, int *arch,
1636     char **machine_name, char **cpu_name)
1637     {
1638     struct syscall_emul *sep;
1639    
1640     sep = first_syscall_emul;
1641    
1642     while (sep != NULL) {
1643     if (strcasecmp(name, sep->name) == 0) {
1644     if (cpu_family_ptr_by_number(sep->arch) == NULL) {
1645     printf("\nSupport for the CPU family needed"
1646     " for '%s' userland emulation was not"
1647     " enabled at configuration time.\n",
1648     sep->name);
1649     exit(1);
1650     }
1651    
1652     if (cpu != NULL)
1653     cpu->useremul_syscall = sep->f;
1654    
1655     if (arch != NULL)
1656     *arch = sep->arch;
1657    
1658     if (machine_name != NULL) {
1659     *machine_name = strdup(sep->name);
1660     if (*machine_name == NULL) {
1661     printf("out of memory\n");
1662     exit(1);
1663     }
1664     }
1665    
1666     if (cpu_name != NULL) {
1667     *cpu_name = strdup(sep->cpu_name);
1668     if (*cpu_name == NULL) {
1669     printf("out of memory\n");
1670     exit(1);
1671     }
1672     }
1673     return;
1674     }
1675    
1676     sep = sep->next;
1677     }
1678    
1679     fatal("Unknown userland emulation '%s'\n", name);
1680     exit(1);
1681     }
1682    
1683    
1684     /*
1685     * add_useremul():
1686     *
1687     * For internal use, from useremul_init() only. Adds an emulation mode.
1688     */
1689     static void add_useremul(char *name, int arch, char *cpu_name,
1690     void (*f)(struct cpu *, uint32_t),
1691     void (*setup)(struct cpu *, int, char **))
1692     {
1693     struct syscall_emul *sep;
1694    
1695     sep = malloc(sizeof(struct syscall_emul));
1696     if (sep == NULL) {
1697     printf("add_useremul(): out of memory\n");
1698     exit(1);
1699     }
1700     memset(sep, 0, sizeof(sep));
1701    
1702     sep->name = name;
1703     sep->arch = arch;
1704     sep->cpu_name = cpu_name;
1705     sep->f = f;
1706     sep->setup = setup;
1707    
1708     sep->next = first_syscall_emul;
1709     first_syscall_emul = sep;
1710     }
1711    
1712    
1713     /*
1714     * useremul_list_emuls():
1715     *
1716     * List all available userland emulation modes. (Actually, only those which
1717     * have CPU support enabled.)
1718     */
1719     void useremul_list_emuls(void)
1720     {
1721     struct syscall_emul *sep;
1722 dpavlin 22 int iadd = DEBUG_INDENTATION * 2;
1723 dpavlin 2
1724     sep = first_syscall_emul;
1725    
1726     if (sep == NULL)
1727     return;
1728    
1729     debug("The following userland-only (syscall) emulation modes are"
1730     " available:\n\n");
1731     debug_indentation(iadd);
1732    
1733     while (sep != NULL) {
1734     if (cpu_family_ptr_by_number(sep->arch) != NULL) {
1735     debug("%s (default CPU \"%s\")\n",
1736     sep->name, sep->cpu_name);
1737     }
1738    
1739     sep = sep->next;
1740     }
1741    
1742     debug_indentation(-iadd);
1743     debug("\n(Most of these modes are bogus.)\n\n");
1744     }
1745    
1746    
1747     /*
1748     * useremul_init():
1749     *
1750     * This function should be called before any other useremul_*() function
1751     * is used.
1752     */
1753     void useremul_init(void)
1754     {
1755     /* Note: These are in reverse alphabetic order: */
1756    
1757     add_useremul("Ultrix", ARCH_MIPS, "R3000",
1758     useremul__ultrix, useremul__ultrix_setup);
1759    
1760 dpavlin 32 add_useremul("NetBSD/sh", ARCH_SH, "SH4",
1761     useremul__netbsd, useremul__netbsd_setup);
1762    
1763 dpavlin 2 add_useremul("NetBSD/powerpc", ARCH_PPC, "PPC750",
1764     useremul__netbsd, useremul__netbsd_setup);
1765    
1766     add_useremul("NetBSD/pmax", ARCH_MIPS, "R3000",
1767     useremul__netbsd, useremul__netbsd_setup);
1768    
1769 dpavlin 14 add_useremul("NetBSD/arm", ARCH_ARM, "SA1110",
1770 dpavlin 12 useremul__netbsd, useremul__netbsd_setup);
1771    
1772 dpavlin 14 add_useremul("NetBSD/alpha", ARCH_ALPHA, "Alpha",
1773     useremul__netbsd, useremul__netbsd_setup);
1774    
1775 dpavlin 2 add_useremul("Linux/PPC64", ARCH_PPC, "PPC970",
1776     useremul__linux, useremul__linux_setup);
1777    
1778 dpavlin 12 add_useremul("FreeBSD/Alpha", ARCH_ALPHA, "Alpha",
1779 dpavlin 2 useremul__freebsd, useremul__freebsd_setup);
1780     }
1781    

  ViewVC Help
Powered by ViewVC 1.1.26