qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 04/18] bsd-user: move target arch and host OS depend


From: Stacey Son
Subject: [Qemu-devel] [PATCH 04/18] bsd-user: move target arch and host OS dependent code out of main.c
Date: Wed, 16 Oct 2013 09:36:58 -0500

This change moves the cpu initialization and main loop code from
main.c to the OS and arch dependent directories. This eliminates
many of the #ifdef's in main.c. The cpu initialization and loop
code is now located in the arch directory along with target arch
support code.

Signed-off-by: Stacey Son <address@hidden>
---
 bsd-user/Makefile.objs                 |    2 +-
 bsd-user/arm/target_arch.h             |   10 +
 bsd-user/arm/target_arch_cpu.c         |   27 ++
 bsd-user/arm/target_arch_cpu.h         |  435 +++++++++++++++++
 bsd-user/arm/target_arch_vmparam.h     |   49 ++
 bsd-user/elfload.c                     |    2 +-
 bsd-user/freebsd/host_os.h             |   46 ++
 bsd-user/freebsd/target_os_vmparam.h   |   23 +
 bsd-user/i386/target_arch.h            |   13 +
 bsd-user/i386/target_arch_cpu.c        |   79 ++++
 bsd-user/i386/target_arch_cpu.h        |  302 ++++++++++++
 bsd-user/i386/target_arch_vmparam.h    |   26 +
 bsd-user/i386/target_signal.h          |    6 -
 bsd-user/main.c                        |  803 +++-----------------------------
 bsd-user/mips/target_arch.h            |   10 +
 bsd-user/mips/target_arch_cpu.c        |   27 ++
 bsd-user/mips/target_arch_cpu.h        |  243 ++++++++++
 bsd-user/mips/target_arch_vmparam.h    |   47 ++
 bsd-user/mips64/target_arch.h          |   10 +
 bsd-user/mips64/target_arch_cpu.c      |   27 ++
 bsd-user/mips64/target_arch_cpu.h      |  243 ++++++++++
 bsd-user/mips64/target_arch_vmparam.h  |   47 ++
 bsd-user/netbsd/host_os.h              |   31 ++
 bsd-user/openbsd/host_os.h             |   31 ++
 bsd-user/qemu.h                        |   10 +-
 bsd-user/sparc/target_arch.h           |   11 +
 bsd-user/sparc/target_arch_cpu.c       |  113 +++++
 bsd-user/sparc/target_arch_cpu.h       |  158 +++++++
 bsd-user/sparc/target_arch_vmparam.h   |   35 ++
 bsd-user/sparc/target_signal.h         |    5 -
 bsd-user/sparc64/target_arch.h         |   11 +
 bsd-user/sparc64/target_arch_cpu.c     |  118 +++++
 bsd-user/sparc64/target_arch_cpu.h     |  191 ++++++++
 bsd-user/sparc64/target_arch_vmparam.h |   37 ++
 bsd-user/sparc64/target_signal.h       |    5 -
 bsd-user/x86_64/target_arch.h          |   13 +
 bsd-user/x86_64/target_arch_cpu.c      |   79 ++++
 bsd-user/x86_64/target_arch_cpu.h      |  324 +++++++++++++
 bsd-user/x86_64/target_arch_vmparam.h  |   28 ++
 bsd-user/x86_64/target_signal.h        |    5 -
 40 files changed, 2915 insertions(+), 767 deletions(-)
 create mode 100644 bsd-user/arm/target_arch.h
 create mode 100644 bsd-user/arm/target_arch_cpu.c
 create mode 100644 bsd-user/arm/target_arch_cpu.h
 create mode 100644 bsd-user/arm/target_arch_vmparam.h
 create mode 100644 bsd-user/freebsd/host_os.h
 create mode 100644 bsd-user/freebsd/target_os_vmparam.h
 create mode 100644 bsd-user/i386/target_arch.h
 create mode 100644 bsd-user/i386/target_arch_cpu.c
 create mode 100644 bsd-user/i386/target_arch_cpu.h
 create mode 100644 bsd-user/i386/target_arch_vmparam.h
 create mode 100644 bsd-user/mips/target_arch.h
 create mode 100644 bsd-user/mips/target_arch_cpu.c
 create mode 100644 bsd-user/mips/target_arch_cpu.h
 create mode 100644 bsd-user/mips/target_arch_vmparam.h
 create mode 100644 bsd-user/mips64/target_arch.h
 create mode 100644 bsd-user/mips64/target_arch_cpu.c
 create mode 100644 bsd-user/mips64/target_arch_cpu.h
 create mode 100644 bsd-user/mips64/target_arch_vmparam.h
 create mode 100644 bsd-user/netbsd/host_os.h
 create mode 100644 bsd-user/openbsd/host_os.h
 create mode 100644 bsd-user/sparc/target_arch.h
 create mode 100644 bsd-user/sparc/target_arch_cpu.c
 create mode 100644 bsd-user/sparc/target_arch_cpu.h
 create mode 100644 bsd-user/sparc/target_arch_vmparam.h
 create mode 100644 bsd-user/sparc64/target_arch.h
 create mode 100644 bsd-user/sparc64/target_arch_cpu.c
 create mode 100644 bsd-user/sparc64/target_arch_cpu.h
 create mode 100644 bsd-user/sparc64/target_arch_vmparam.h
 create mode 100644 bsd-user/x86_64/target_arch.h
 create mode 100644 bsd-user/x86_64/target_arch_cpu.c
 create mode 100644 bsd-user/x86_64/target_arch_cpu.h
 create mode 100644 bsd-user/x86_64/target_arch_vmparam.h

diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
index 5e77f57..41e8dce 100644
--- a/bsd-user/Makefile.objs
+++ b/bsd-user/Makefile.objs
@@ -1,2 +1,2 @@
 obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
-               uaccess.o
+               uaccess.o $(TARGET_ABI_DIR)/target_arch_cpu.o
diff --git a/bsd-user/arm/target_arch.h b/bsd-user/arm/target_arch.h
new file mode 100644
index 0000000..b5c5ddb
--- /dev/null
+++ b/bsd-user/arm/target_arch.h
@@ -0,0 +1,10 @@
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+#include "qemu.h"
+
+void target_cpu_set_tls(CPUARMState *env, target_ulong newtls);
+target_ulong target_cpu_get_tls(CPUARMState *env);
+
+#endif /* !_TARGET_ARCH_H_ */
diff --git a/bsd-user/arm/target_arch_cpu.c b/bsd-user/arm/target_arch_cpu.c
new file mode 100644
index 0000000..d94a32a
--- /dev/null
+++ b/bsd-user/arm/target_arch_cpu.c
@@ -0,0 +1,27 @@
+/*
+ *  arm cpu related code
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "target_arch.h"
+
+void target_cpu_set_tls(CPUARMState *env, target_ulong newtls)
+{
+    env->cp15.c13_tls2 = newtls;
+}
+
+target_ulong target_cpu_get_tls(CPUARMState *env)
+{
+    return (env->cp15.c13_tls2);
+}
diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h
new file mode 100644
index 0000000..713cec4
--- /dev/null
+++ b/bsd-user/arm/target_arch_cpu.h
@@ -0,0 +1,435 @@
+/*
+ *  arm cpu init and loop
+ *
+ *  Olivier Houchard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TARGET_ARCH_CPU_H_
+#define _TARGET_ARCH_CPU_H_
+
+#include "target_arch.h"
+
+/* #define DEBUG_ARM */
+
+#define TARGET_DEFAULT_CPU_MODEL "any"
+
+#define TARGET_CPU_RESET(env)
+
+static inline void target_cpu_init(CPUARMState *env,
+        struct target_pt_regs *regs)
+{
+    int i;
+
+    cpsr_write(env, regs->uregs[16], 0xffffffff);
+    for (i = 0; i < 16; i++) {
+        env->regs[i] = regs->uregs[i];
+    }
+}
+
+static inline int do_strex(CPUARMState *env)
+{
+    uint32_t val;
+    int size;
+    int rc = 1;
+    int segv = 0;
+    uint32_t addr;
+    start_exclusive();
+    addr = env->exclusive_addr;
+    if (addr != env->exclusive_test) {
+        goto fail;
+    }
+    size = env->exclusive_info & 0xf;
+    switch (size) {
+    case 0:
+        segv = get_user_u8(val, addr);
+        break;
+    case 1:
+        segv = get_user_u16(val, addr);
+        break;
+    case 2:
+    case 3:
+        segv = get_user_u32(val, addr);
+        break;
+    default:
+        abort();
+    }
+    if (segv) {
+        env->cp15.c6_data = addr;
+        goto done;
+    }
+    if (val != env->exclusive_val) {
+        goto fail;
+    }
+    if (size == 3) {
+        segv = get_user_u32(val, addr + 4);
+        if (segv) {
+            env->cp15.c6_data = addr + 4;
+            goto done;
+        }
+        if (val != env->exclusive_high) {
+            goto fail;
+        }
+    }
+    val = env->regs[(env->exclusive_info >> 8) & 0xf];
+    switch (size) {
+    case 0:
+        segv = put_user_u8(val, addr);
+        break;
+    case 1:
+        segv = put_user_u16(val, addr);
+        break;
+    case 2:
+    case 3:
+        segv = put_user_u32(val, addr);
+        break;
+    }
+    if (segv) {
+        env->cp15.c6_data = addr;
+        goto done;
+    }
+    if (size == 3) {
+        val = env->regs[(env->exclusive_info >> 12) & 0xf];
+        segv = put_user_u32(val, addr + 4);
+        if (segv) {
+            env->cp15.c6_data = addr + 4;
+            goto done;
+        }
+    }
+    rc = 0;
+fail:
+    env->regs[15] += 4;
+    env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
+done:
+    end_exclusive();
+    return segv;
+}
+
+static inline void target_cpu_loop(CPUARMState *env)
+{
+    int trapnr;
+    unsigned int n;
+#ifdef FREEBSD_ARM_OABI
+    unsigned int insn;
+#endif
+    uint32_t addr;
+    CPUState *cs = CPU(arm_env_get_cpu(env));
+
+    for (;;) {
+#ifdef DEBUG_ARM
+        printf("CPU LOOPING\n");
+#endif
+        cpu_exec_start(cs);
+#ifdef DEBUG_ARM
+        printf("EXECUTING...\n");
+#endif
+        trapnr = cpu_arm_exec(env);
+#ifdef DEBUG_ARM
+        printf("trapnr %d\n", trapnr);
+#endif
+        cpu_exec_end(cs);
+        switch (trapnr) {
+        case EXCP_UDEF:
+            {
+#if 0
+                TaskState *ts = env->opaque;
+                uint32_t opcode;
+                int rc;
+
+                /* we handle the FPU emulation here, as Linux */
+                /* we get the opcode */
+                /* FIXME - what to do if get_user() fails? */
+                get_user_u32(opcode, env->regs[15]);
+
+                rc = EmulateAll(opcode, &ts->fpa, env);
+                if (rc == 0) { /* illegal instruction */
+                    info.si_signo = SIGILL;
+                    info.si_errno = 0;
+                    info.si_code = TARGET_ILL_ILLOPN;
+                    info._sifields._sigfault._addr = env->regs[15];
+                    queue_signal(env, info.si_signo, &info);
+
+                } else if (rc < 0) { /* FP exception */
+                    int arm_fpe = 0;
+
+                    /* translate softfloat flags to FPSR flags */
+                    if (-rc & float_flag_invalid) {
+                        arm_fpe |= BIT_IOC;
+                    }
+                    if (-rc & float_flag_divbyzero) {
+                        arm_fpe |= BIT_DZC;
+                    }
+                    if (-rc & float_flag_overflow) {
+                        arm_fpe |= BIT_OFC;
+                    }
+                    if (-rc & float_flag_underflow) {
+                        arm_fpe |= BIT_UFC;
+                    }
+                    if (-rc & float_flag_inexact) {
+                        arm_fpe |= BIT_IXC;
+                    }
+
+                    FPSR fpsr = ts->fpa.fpsr;
+                    /* printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); */
+
+                    if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
+                        info.si_signo = SIGFPE;
+                        info.si_errno = 0;
+
+                        /* ordered by priority, least first */
+                        if (arm_fpe & BIT_IXC) {
+                            info.si_code = TARGET_FPE_FLTRES;
+                        }
+                        if (arm_fpe & BIT_UFC) {
+                            info.si_code = TARGET_FPE_FLTUND;
+                        }
+                        if (arm_fpe & BIT_OFC) {
+                            info.si_code = TARGET_FPE_FLTOVF;
+                        }
+                        if (arm_fpe & BIT_DZC) {
+                            info.si_code = TARGET_FPE_FLTDIV;
+                        }
+                        if (arm_fpe & BIT_IOC) {
+                            info.si_code = TARGET_FPE_FLTINV;
+                        }
+                        info._sifields._sigfault._addr = env->regs[15];
+                        queue_signal(env, info.si_signo, &info);
+                    } else {
+                        env->regs[15] += 4;
+                    }
+
+                    /* accumulate unenabled exceptions */
+                    if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) {
+                        fpsr |= BIT_IXC;
+                    }
+                    if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) {
+                        fpsr |= BIT_UFC;
+                    }
+                    if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) {
+                        fpsr |= BIT_OFC;
+                    }
+                    if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) {
+                        fpsr |= BIT_DZC;
+                    }
+                    if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) {
+                        fpsr |= BIT_IOC;
+                    }
+                    ts->fpa.fpsr = fpsr;
+                } else { /* everything OK */
+                    /* increment PC */
+                    env->regs[15] += 4;
+                }
+            }
+#endif
+            break;
+        case EXCP_SWI:
+        case EXCP_BKPT:
+            {
+                env->eabi = 1;
+                /* system call */
+                if (trapnr == EXCP_BKPT) {
+                    if (env->thumb) {
+                        /* FIXME - what to do if get_user() fails? */
+#ifdef FREEBSD_ARM_OABI
+                        get_user_u16(insn, env->regs[15]);
+                        n = insn & 0xff;
+#else
+                        n = env->regs[7];
+#endif
+                        env->regs[15] += 2;
+                    } else {
+                        /* FIXME - what to do if get_user() fails? */
+#ifdef FREEBSD_ARM_OABI
+                        get_user_u32(insn, env->regs[15]);
+                        n = (insn & 0xf) | ((insn >> 4) & 0xff0);
+#else
+                        n = env->regs[7];
+#endif
+                        env->regs[15] += 4;
+                    }
+                } else {
+                    if (env->thumb) {
+#ifdef FREEBSD_ARM_OABI
+                        /* FIXME - what to do if get_user() fails? */
+                        get_user_u16(insn, env->regs[15] - 2);
+                        n = insn & 0xff;
+#else
+                        n = env->regs[7];
+#endif
+                    } else {
+#ifdef FREEBSD_ARM_OABI
+                        /* FIXME - what to do if get_user() fails? */
+                        get_user_u32(insn, env->regs[15] - 4);
+                        n = insn & 0xffffff;
+#else
+                        n = env->regs[7];
+#endif
+                    }
+                }
+
+#ifdef DEBUG_ARM
+        printf("AVANT CALL %d\n", n);
+#endif
+                if (bsd_type == target_freebsd) {
+                    int ret;
+                    abi_ulong params = get_sp_from_cpustate(env);
+                    int32_t syscall_nr = n;
+                    int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
+
+#if 0 /* XXX FIXME */
+                    if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
+                        get_user_s32(syscall_nr, params);
+                        params += sizeof(int32_t);
+                    } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
+                        get_user_s32(syscall_nr, params);
+                        params += sizeof(int64_t);
+                    }
+#endif
+                    arg1 = env->regs[0];
+                    arg2 = env->regs[1];
+                    arg3 = env->regs[2];
+                    arg4 = env->regs[3];
+                    get_user_s32(arg5, params);
+                    params += sizeof(int32_t);
+                    get_user_s32(arg6, params);
+                    params += sizeof(int32_t);
+                    get_user_s32(arg7, params);
+                    params += sizeof(int32_t);
+                    get_user_s32(arg8, params);
+                    ret = do_freebsd_syscall(env,
+                                                      syscall_nr,
+                                                      arg1,
+                                                      arg2,
+                                                      arg3,
+                                                      arg4,
+                                                      arg5,
+                                                      arg6,
+                                                      arg7,
+                                                      arg8);
+                    /*
+                     * Compare to arm/arm/vm_machdep.c
+                     * cpu_set_syscall_retval()
+                     */
+                    /* XXX armeb may need some extra magic here */
+                    if (-TARGET_EJUSTRETURN == ret) {
+                        /*
+                         * Returning from a successful sigreturn syscall.
+                         * Avoid clobbering register state.
+                         */
+                        break;
+                    }
+                    /*
+                     * XXX Need to handle ERESTART. Backup the PC by
+                     * 1 instruction.
+                     */
+                    if ((unsigned int)ret >= (unsigned int)(-515)) {
+                        ret = -ret;
+                        cpsr_write(env, CPSR_C, CPSR_C);
+                        env->regs[0] = ret;
+                    } else {
+                        cpsr_write(env, 0, CPSR_C);
+                        env->regs[0] = ret; /* XXX need to handle lseek()? */
+                        /* env->regs[1] = 0; */
+                    }
+                } else {
+                    /* XXX is this correct? */
+                    env->regs[0] = do_openbsd_syscall(env,
+                        n,
+                        env->regs[0],
+                        env->regs[1],
+                        env->regs[2],
+                        env->regs[3],
+                        env->regs[4],
+                        env->regs[5]);
+                }
+#ifdef DEBUG_ARM
+                printf("APRES CALL\n");
+#endif
+            }
+        }
+            break;
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+        case EXCP_PREFETCH_ABORT:
+            addr = env->cp15.c6_insn;
+            goto do_segv;
+        case EXCP_DATA_ABORT:
+            addr = env->cp15.c6_data;
+        do_segv:
+            {
+#if 0
+                info.si_signo = SIGSEGV;
+                info.si_errno = 0;
+                /* XXX: check env->error_code */
+                info.si_code = TARGET_SEGV_MAPERR;
+                info._sifields._sigfault._addr = addr;
+                queue_signal(env, info.si_signo, &info);
+#endif
+            }
+            break;
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
+                if (sig) {
+#if 0
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TARGET_TRAP_BRKPT;
+                    queue_signal(env, info.si_signo, &info);
+#endif
+                }
+            }
+            break;
+#if 0
+        case EXCP_KERNEL_TRAP:
+            if (do_kernel_trap(env)) {
+                goto error;
+            }
+            break;
+#endif
+        case EXCP_STREX:
+            if (do_strex(env)) {
+                addr = env->cp15.c6_data;
+                goto do_segv;
+            }
+            break;
+#if 0
+        error:
+#endif
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+                    trapnr);
+            cpu_dump_state(cs, stderr, fprintf, 0);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+
+static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp)
+{
+    if (newsp)
+        env->regs[13] = newsp;
+    env->regs[0] = 0;
+}
+
+static inline void target_cpu_reset(CPUArchState *cpu)
+{
+}
+
+#endif /* !_TARGET_ARCH_CPU_H */
diff --git a/bsd-user/arm/target_arch_vmparam.h 
b/bsd-user/arm/target_arch_vmparam.h
new file mode 100644
index 0000000..46cd0cf
--- /dev/null
+++ b/bsd-user/arm/target_arch_vmparam.h
@@ -0,0 +1,49 @@
+/*
+ *  arm VM parameters definitions
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_ARCH_VMPARAM_H_
+#define _TARGET_ARCH_VMPARAM_H_
+
+#include "cpu.h"
+
+/* compare to sys/arm/include/vmparam.h */
+#define TARGET_MAXTSIZ      (64UL*1024*1024)   /* max text size */
+#define TARGET_DFLDSIZ      (128UL*1024*1024)   /* initial data size limit */
+#define TARGET_MAXDSIZ      (512UL*1024*1024)    /* max data size */
+#define TARGET_DFLSSIZ      (2UL*1024*1024)     /* initial stack size limit */
+#define TARGET_MAXSSIZ      (8UL*1024*1024)    /* max stack size */
+#define TARGET_SGROWSIZ     (128UL*1024)        /* amount to grow stack */
+
+                /* KERNBASE - 512 MB */
+#define TARGET_VM_MAXUSER_ADDRESS   (0xc0000000 - (512 * 1024 * 1024))
+#define TARGET_USRSTACK             TARGET_VM_MAXUSER_ADDRESS
+
+#define TARGET_SPACE_USRSPACE   4096
+#define TARGET_ARG_MAX          262144
+
+static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
+{
+    return state->regs[13]; /* sp */
+}
+
+static inline void set_second_rval(CPUARMState *state, abi_ulong retval2)
+{
+    state->regs[1] = retval2;
+}
+
+#endif  /* ! _TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 93fd9e4..ccf72d1 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -674,7 +674,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct 
linux_binprm *bprm,
     /* Create enough stack to hold everything.  If we don't use
      * it for args, we'll use it for something else...
      */
-    size = x86_stack_size;
+    size = target_dflssiz;
     if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
         size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
     error = target_mmap(0,
diff --git a/bsd-user/freebsd/host_os.h b/bsd-user/freebsd/host_os.h
new file mode 100644
index 0000000..efe2351
--- /dev/null
+++ b/bsd-user/freebsd/host_os.h
@@ -0,0 +1,46 @@
+/*
+ *  FreeBSD host dependent code and definitions
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HOST_OS_H_
+#define __HOST_OS_H_
+
+#include <stdio.h>
+#include <sys/sysctl.h>
+
+#include "qemu.h"
+
+#define HOST_DEFAULT_BSD_TYPE target_freebsd
+
+static inline void save_proc_pathname(char *argv0)
+{
+    int mib[4];
+    size_t len;
+
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PROC;
+    mib[2] = KERN_PROC_PATHNAME;
+    mib[3] = -1;
+
+    len = PATH_MAX;
+    if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
+        perror("sysctl");
+    }
+}
+
+#endif /*!__HOST_OS_H_ */
diff --git a/bsd-user/freebsd/target_os_vmparam.h 
b/bsd-user/freebsd/target_os_vmparam.h
new file mode 100644
index 0000000..80ac6c8
--- /dev/null
+++ b/bsd-user/freebsd/target_os_vmparam.h
@@ -0,0 +1,23 @@
+#ifndef _TARGET_OS_VMPARAM_H_
+#define _TARGET_OS_VMPARAM_H_
+
+#include "target_arch_vmparam.h"
+
+#define TARGET_SPACE_USRSPACE   4096
+#define TARGET_ARG_MAX          262144
+
+/* Compare to sys/exec.h */
+struct target_ps_strings {
+    abi_ulong ps_argvstr;
+    uint32_t ps_nargvstr;
+    abi_ulong ps_envstr;
+    uint32_t ps_nenvstr;
+};
+
+extern abi_ulong target_stkbas;
+extern abi_ulong target_stksiz;
+
+#define TARGET_PS_STRINGS  ((target_stkbas + target_stksiz) - \
+               sizeof(struct target_ps_strings))
+
+#endif /* !TARGET_OS_VMPARAM_H_ */
diff --git a/bsd-user/i386/target_arch.h b/bsd-user/i386/target_arch.h
new file mode 100644
index 0000000..4cb398c
--- /dev/null
+++ b/bsd-user/i386/target_arch.h
@@ -0,0 +1,13 @@
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+/* target_arch_cpu.c */
+void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
+                int flags);
+void bsd_i386_set_idt(int n, unsigned int dpl);
+void bsd_i386_set_idt_base(uint64_t base);
+
+#define target_cpu_set_tls(env, newtls)
+
+#endif /* ! _TARGET_ARCH_H_ */
diff --git a/bsd-user/i386/target_arch_cpu.c b/bsd-user/i386/target_arch_cpu.c
new file mode 100644
index 0000000..2e0eec0
--- /dev/null
+++ b/bsd-user/i386/target_arch_cpu.c
@@ -0,0 +1,79 @@
+/*
+ *  i386 cpu related code
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+
+#include "cpu.h"
+#include "qemu.h"
+#include "qemu/timer.h"
+
+#include "target_arch.h"
+
+static uint64_t *idt_table;
+
+/* CPUX86 core interface */
+void cpu_smm_update(CPUX86State *env)
+{
+}
+
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+    return cpu_get_real_ticks();
+}
+
+int cpu_get_pic_interrupt(CPUX86State *env)
+{
+    return -1;
+}
+
+void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
+                     int flags)
+{
+    unsigned int e1, e2;
+    uint32_t *p;
+    e1 = (addr << 16) | (limit & 0xffff);
+    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
+    e2 |= flags;
+    p = ptr;
+    p[0] = tswap32(e1);
+    p[1] = tswap32(e2);
+}
+
+
+static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
+                     uint32_t addr, unsigned int sel)
+{
+    uint32_t *p, e1, e2;
+    e1 = (addr & 0xffff) | (sel << 16);
+    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
+    p = ptr;
+    p[0] = tswap32(e1);
+    p[1] = tswap32(e2);
+}
+
+/* only dpl matters as we do only user space emulation */
+void bsd_i386_set_idt(int n, unsigned int dpl)
+{
+    set_gate(idt_table + n, 0, dpl, 0, 0);
+}
+
+void bsd_i386_set_idt_base(uint64_t base)
+{
+    idt_table = g2h(base);
+}
+
diff --git a/bsd-user/i386/target_arch_cpu.h b/bsd-user/i386/target_arch_cpu.h
new file mode 100644
index 0000000..c3df814
--- /dev/null
+++ b/bsd-user/i386/target_arch_cpu.h
@@ -0,0 +1,302 @@
+/*
+ *  i386 cpu init and loop
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TARGET_ARCH_CPU_H_
+#define _TARGET_ARCH_CPU_H_
+
+#include "target_arch.h"
+
+#define TARGET_DEFAULT_CPU_MODEL "qemu32"
+
+#define TARGET_CPU_RESET(env)
+
+static inline void target_cpu_init(CPUX86State *env,
+        struct target_pt_regs *regs)
+{
+    uint64_t *gdt_table;
+
+    cpu_x86_set_cpl(env, 3);
+
+    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
+    env->hflags |= HF_PE_MASK;
+    if (env->features[FEAT_1_EDX] & CPUID_SSE) {
+        env->cr[4] |= CR4_OSFXSR_MASK;
+        env->hflags |= HF_OSFXSR_MASK;
+    }
+
+    /* flags setup : we activate the IRQs by default as in user mode */
+    env->eflags |= IF_MASK;
+
+    /* register setup */
+    env->regs[R_EAX] = regs->eax;
+    env->regs[R_EBX] = regs->ebx;
+    env->regs[R_ECX] = regs->ecx;
+    env->regs[R_EDX] = regs->edx;
+    env->regs[R_ESI] = regs->esi;
+    env->regs[R_EDI] = regs->edi;
+    env->regs[R_EBP] = regs->ebp;
+    env->regs[R_ESP] = regs->esp;
+    env->eip = regs->eip;
+
+    /* interrupt setup */
+    env->idt.limit = 255;
+
+    env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
+        PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+    bsd_i386_set_idt_base(env->idt.base);
+    bsd_i386_set_idt(0, 0);
+    bsd_i386_set_idt(1, 0);
+    bsd_i386_set_idt(2, 0);
+    bsd_i386_set_idt(3, 3);
+    bsd_i386_set_idt(4, 3);
+    bsd_i386_set_idt(5, 0);
+    bsd_i386_set_idt(6, 0);
+    bsd_i386_set_idt(7, 0);
+    bsd_i386_set_idt(8, 0);
+    bsd_i386_set_idt(9, 0);
+    bsd_i386_set_idt(10, 0);
+    bsd_i386_set_idt(11, 0);
+    bsd_i386_set_idt(12, 0);
+    bsd_i386_set_idt(13, 0);
+    bsd_i386_set_idt(14, 0);
+    bsd_i386_set_idt(15, 0);
+    bsd_i386_set_idt(16, 0);
+    bsd_i386_set_idt(17, 0);
+    bsd_i386_set_idt(18, 0);
+    bsd_i386_set_idt(19, 0);
+    bsd_i386_set_idt(0x80, 3);
+
+    /* segment setup */
+    env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
+            PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+    env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
+    gdt_table = g2h(env->gdt.base);
+
+    bsd_i386_write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
+            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+            (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
+
+    bsd_i386_write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
+            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+            (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+
+    cpu_x86_load_seg(env, R_CS, __USER_CS);
+    cpu_x86_load_seg(env, R_SS, __USER_DS);
+    cpu_x86_load_seg(env, R_DS, __USER_DS);
+    cpu_x86_load_seg(env, R_ES, __USER_DS);
+    cpu_x86_load_seg(env, R_FS, __USER_DS);
+    cpu_x86_load_seg(env, R_GS, __USER_DS);
+    /* This hack makes Wine work... */
+    env->segs[R_FS].selector = 0;
+}
+
+static inline void target_cpu_loop(CPUX86State *env)
+{
+    int trapnr;
+    abi_ulong pc;
+    /* target_siginfo_t info; */
+
+    for (;;) {
+        trapnr = cpu_x86_exec(env);
+        switch (trapnr) {
+        case 0x80:
+            /* syscall from int $0x80 */
+            if (bsd_type == target_freebsd) {
+                abi_ulong params = (abi_ulong) env->regs[R_ESP] +
+                    sizeof(int32_t);
+                int32_t syscall_nr = env->regs[R_EAX];
+                int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
+
+                if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
+                    get_user_s32(syscall_nr, params);
+                    params += sizeof(int32_t);
+                } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
+                    get_user_s32(syscall_nr, params);
+                    params += sizeof(int64_t);
+                }
+                get_user_s32(arg1, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg2, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg3, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg4, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg5, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg6, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg7, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg8, params);
+                env->regs[R_EAX] = do_freebsd_syscall(env,
+                                                      syscall_nr,
+                                                      arg1,
+                                                      arg2,
+                                                      arg3,
+                                                      arg4,
+                                                      arg5,
+                                                      arg6,
+                                                      arg7,
+                                                      arg8);
+            } else { /* if (bsd_type == target_openbsd) */
+                env->regs[R_EAX] = do_openbsd_syscall(env,
+                                                      env->regs[R_EAX],
+                                                      env->regs[R_EBX],
+                                                      env->regs[R_ECX],
+                                                      env->regs[R_EDX],
+                                                      env->regs[R_ESI],
+                                                      env->regs[R_EDI],
+                                                      env->regs[R_EBP]);
+            }
+            if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
+                env->regs[R_EAX] = -env->regs[R_EAX];
+                env->eflags |= CC_C;
+            } else {
+                env->eflags &= ~CC_C;
+            }
+            break;
+
+#if 0
+        case EXCP0B_NOSEG:
+        case EXCP0C_STACK:
+            info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = TARGET_SI_KERNEL;
+            info._sifields._sigfault._addr = 0;
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP0D_GPF:
+            /* XXX: potential problem if ABI32 */
+            if (env->eflags & VM_MASK) {
+                handle_vm86_fault(env);
+            } else {
+                info.si_signo = SIGSEGV;
+                info.si_errno = 0;
+                info.si_code = TARGET_SI_KERNEL;
+                info._sifields._sigfault._addr = 0;
+                queue_signal(env, info.si_signo, &info);
+            }
+            break;
+
+        case EXCP0E_PAGE:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            if (!(env->error_code & 1)) {
+                info.si_code = TARGET_SEGV_MAPERR;
+            } else {
+                info.si_code = TARGET_SEGV_ACCERR;
+            }
+            info._sifields._sigfault._addr = env->cr[2];
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP00_DIVZ:
+            if (env->eflags & VM_MASK) {
+                handle_vm86_trap(env, trapnr);
+            } else {
+                /* division by zero */
+                info.si_signo = SIGFPE;
+                info.si_errno = 0;
+                info.si_code = TARGET_FPE_INTDIV;
+                info._sifields._sigfault._addr = env->eip;
+                queue_signal(env, info.si_signo, &info);
+            }
+            break;
+
+        case EXCP01_DB:
+        case EXCP03_INT3:
+            if (env->eflags & VM_MASK) {
+                handle_vm86_trap(env, trapnr);
+            } else {
+                info.si_signo = SIGTRAP;
+                info.si_errno = 0;
+                if (trapnr == EXCP01_DB) {
+                    info.si_code = TARGET_TRAP_BRKPT;
+                    info._sifields._sigfault._addr = env->eip;
+                } else {
+                    info.si_code = TARGET_SI_KERNEL;
+                    info._sifields._sigfault._addr = 0;
+                }
+                queue_signal(env, info.si_signo, &info);
+            }
+            break;
+
+        case EXCP04_INTO:
+        case EXCP05_BOUND:
+            if (env->eflags & VM_MASK) {
+                handle_vm86_trap(env, trapnr);
+            } else {
+                info.si_signo = SIGSEGV;
+                info.si_errno = 0;
+                info.si_code = TARGET_SI_KERNEL;
+                info._sifields._sigfault._addr = 0;
+                queue_signal(env, info.si_signo, &info);
+            }
+            break;
+
+        case EXCP06_ILLOP:
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_ILLOPN;
+            info._sifields._sigfault._addr = env->eip;
+            queue_signal(env, info.si_signo, &info);
+            break;
+#endif
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+#if 0
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                if (sig) {
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TARGET_TRAP_BRKPT;
+                    queue_signal(env, info.si_signo, &info);
+                }
+            }
+            break;
+#endif
+        default:
+            pc = env->segs[R_CS].base + env->eip;
+            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
+                    "aborting\n", (long)pc, trapnr);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+
+static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
+{
+    if (newsp)
+        env->regs[R_ESP] = newsp;
+    env->regs[R_EAX] = 0;
+}
+
+static inline void target_cpu_reset(CPUArchState *cpu)
+{
+    cpu_reset(ENV_GET_CPU(cpu));
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/i386/target_arch_vmparam.h 
b/bsd-user/i386/target_arch_vmparam.h
new file mode 100644
index 0000000..654400a
--- /dev/null
+++ b/bsd-user/i386/target_arch_vmparam.h
@@ -0,0 +1,26 @@
+#ifndef _TARGET_ARCH_VMPARAM_H_
+#define _TARGET_ARCH_VMPARAM_H_
+
+#include "cpu.h"
+
+/* compare to i386/include/vmparam.h */
+#define TARGET_MAXTSIZ  (128UL*1024*1024)   /* max text size */
+#define TARGET_DFLDSIZ  (128UL*1024*1024)   /* initial data size limit */
+#define TARGET_MAXDSIZ  (512UL*1024*1024)   /* max data size */
+#define TARGET_DFLSSIZ  (8UL*1024*1024)     /* initial stack size limit */
+#define TARGET_MAXSSIZ  (64UL*1024*1024)    /* max stack size */
+#define TARGET_SGROWSIZ (128UL*1024)        /* amount to grow stack */
+
+#define TARGET_USRSTACK (0xbfc00000)
+
+static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+{
+    return state->regs[R_ESP];
+}
+
+static inline void set_second_rval(CPUX86State *state, abi_ulong retval2)
+{
+    state->regs[R_EDX] = retval2;
+}
+
+#endif /* !_TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h
index 2ef36d1..5491687 100644
--- a/bsd-user/i386/target_signal.h
+++ b/bsd-user/i386/target_signal.h
@@ -11,10 +11,4 @@ typedef struct target_sigaltstack {
        abi_ulong ss_size;
 } target_stack_t;
 
-
-static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
-{
-    return state->regs[R_ESP];
-}
-
 #endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/main.c b/bsd-user/main.c
index f9246aa..3b8fb60 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -1,7 +1,8 @@
 /*
- *  qemu user main
+ *  qemu bsd user main
  *
  *  Copyright (c) 2003-2008 Fabrice Bellard
+ *  Copyright (c) 2013 Stacey Son
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,17 +24,20 @@
 #include <errno.h>
 #include <unistd.h>
 #include <machine/trap.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 
 #include "qemu.h"
 #include "qemu-common.h"
-/* For tb_lock */
 #include "cpu.h"
 #include "tcg.h"
 #include "qemu/timer.h"
 #include "qemu/envlist.h"
 
+#include "host_os.h"
+#include "target_arch_cpu.h"
+
 int singlestep;
 #if defined(CONFIG_USE_GUEST_BASE)
 unsigned long mmap_min_addr;
@@ -47,44 +51,16 @@ const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
 extern char **environ;
 enum BSDType bsd_type;
 
-/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
-   we allocate a bigger stack. Need a better solution, for example
-   by remapping the process stack directly at the right place */
-unsigned long x86_stack_size = 512 * 1024;
-
-void gemu_log(const char *fmt, ...)
-{
-    va_list ap;
-
-    va_start(ap, fmt);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
-}
+unsigned long target_maxtsiz = TARGET_MAXTSIZ;   /* max text size */
+unsigned long target_dfldsiz = TARGET_DFLDSIZ;   /* initial data size limit */
+unsigned long target_maxdsiz = TARGET_MAXDSIZ;   /* max data size */
+unsigned long target_dflssiz = TARGET_DFLSSIZ;   /* initial data size limit */
+unsigned long target_maxssiz = TARGET_MAXSSIZ;   /* max stack size */
+unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
 
-#if defined(TARGET_I386)
-int cpu_get_pic_interrupt(CPUX86State *env)
-{
-    return -1;
-}
-#endif
+char qemu_proc_pathname[PATH_MAX];  /* full path to exeutable */
 
 /* These are no-ops because we are not threadsafe.  */
-static inline void cpu_exec_start(CPUArchState *env)
-{
-}
-
-static inline void cpu_exec_end(CPUArchState *env)
-{
-}
-
-static inline void start_exclusive(void)
-{
-}
-
-static inline void end_exclusive(void)
-{
-}
-
 void fork_start(void)
 {
 }
@@ -96,579 +72,41 @@ void fork_end(int child)
     }
 }
 
-void cpu_list_lock(void)
-{
-}
-
-void cpu_list_unlock(void)
-{
-}
-
-#ifdef TARGET_I386
-/***********************************************************/
-/* CPUX86 core interface */
-
-void cpu_smm_update(CPUX86State *env)
+static inline void exclusive_idle(void)
 {
 }
 
-uint64_t cpu_get_tsc(CPUX86State *env)
-{
-    return cpu_get_real_ticks();
-}
-
-static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
-                     int flags)
-{
-    unsigned int e1, e2;
-    uint32_t *p;
-    e1 = (addr << 16) | (limit & 0xffff);
-    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
-    e2 |= flags;
-    p = ptr;
-    p[0] = tswap32(e1);
-    p[1] = tswap32(e2);
-}
-
-static uint64_t *idt_table;
-#ifdef TARGET_X86_64
-static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
-                       uint64_t addr, unsigned int sel)
-{
-    uint32_t *p, e1, e2;
-    e1 = (addr & 0xffff) | (sel << 16);
-    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
-    p = ptr;
-    p[0] = tswap32(e1);
-    p[1] = tswap32(e2);
-    p[2] = tswap32(addr >> 32);
-    p[3] = 0;
-}
-/* only dpl matters as we do only user space emulation */
-static void set_idt(int n, unsigned int dpl)
-{
-    set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
-}
-#else
-static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
-                     uint32_t addr, unsigned int sel)
+static inline void start_exclusive(void)
 {
-    uint32_t *p, e1, e2;
-    e1 = (addr & 0xffff) | (sel << 16);
-    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
-    p = ptr;
-    p[0] = tswap32(e1);
-    p[1] = tswap32(e2);
 }
 
-/* only dpl matters as we do only user space emulation */
-static void set_idt(int n, unsigned int dpl)
+static inline void end_exclusive(void)
 {
-    set_gate(idt_table + n, 0, dpl, 0, 0);
 }
-#endif
 
-void cpu_loop(CPUX86State *env)
+static inline void cpu_exec_start(CPUState *env)
 {
-    int trapnr;
-    abi_ulong pc;
-    //target_siginfo_t info;
-
-    for(;;) {
-        trapnr = cpu_x86_exec(env);
-        switch(trapnr) {
-        case 0x80:
-            /* syscall from int $0x80 */
-            if (bsd_type == target_freebsd) {
-                abi_ulong params = (abi_ulong) env->regs[R_ESP] +
-                    sizeof(int32_t);
-                int32_t syscall_nr = env->regs[R_EAX];
-                int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
-
-                if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
-                    get_user_s32(syscall_nr, params);
-                    params += sizeof(int32_t);
-                } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
-                    get_user_s32(syscall_nr, params);
-                    params += sizeof(int64_t);
-                }
-                get_user_s32(arg1, params);
-                params += sizeof(int32_t);
-                get_user_s32(arg2, params);
-                params += sizeof(int32_t);
-                get_user_s32(arg3, params);
-                params += sizeof(int32_t);
-                get_user_s32(arg4, params);
-                params += sizeof(int32_t);
-                get_user_s32(arg5, params);
-                params += sizeof(int32_t);
-                get_user_s32(arg6, params);
-                params += sizeof(int32_t);
-                get_user_s32(arg7, params);
-                params += sizeof(int32_t);
-                get_user_s32(arg8, params);
-                env->regs[R_EAX] = do_freebsd_syscall(env,
-                                                      syscall_nr,
-                                                      arg1,
-                                                      arg2,
-                                                      arg3,
-                                                      arg4,
-                                                      arg5,
-                                                      arg6,
-                                                      arg7,
-                                                      arg8);
-            } else { //if (bsd_type == target_openbsd)
-                env->regs[R_EAX] = do_openbsd_syscall(env,
-                                                      env->regs[R_EAX],
-                                                      env->regs[R_EBX],
-                                                      env->regs[R_ECX],
-                                                      env->regs[R_EDX],
-                                                      env->regs[R_ESI],
-                                                      env->regs[R_EDI],
-                                                      env->regs[R_EBP]);
-            }
-            if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
-                env->regs[R_EAX] = -env->regs[R_EAX];
-                env->eflags |= CC_C;
-            } else {
-                env->eflags &= ~CC_C;
-            }
-            break;
-#ifndef TARGET_ABI32
-        case EXCP_SYSCALL:
-            /* syscall from syscall instruction */
-            if (bsd_type == target_freebsd)
-                env->regs[R_EAX] = do_freebsd_syscall(env,
-                                                      env->regs[R_EAX],
-                                                      env->regs[R_EDI],
-                                                      env->regs[R_ESI],
-                                                      env->regs[R_EDX],
-                                                      env->regs[R_ECX],
-                                                      env->regs[8],
-                                                      env->regs[9], 0, 0);
-            else { //if (bsd_type == target_openbsd)
-                env->regs[R_EAX] = do_openbsd_syscall(env,
-                                                      env->regs[R_EAX],
-                                                      env->regs[R_EDI],
-                                                      env->regs[R_ESI],
-                                                      env->regs[R_EDX],
-                                                      env->regs[10],
-                                                      env->regs[8],
-                                                      env->regs[9]);
-            }
-            env->eip = env->exception_next_eip;
-            if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
-                env->regs[R_EAX] = -env->regs[R_EAX];
-                env->eflags |= CC_C;
-            } else {
-                env->eflags &= ~CC_C;
-            }
-            break;
-#endif
-#if 0
-        case EXCP0B_NOSEG:
-        case EXCP0C_STACK:
-            info.si_signo = SIGBUS;
-            info.si_errno = 0;
-            info.si_code = TARGET_SI_KERNEL;
-            info._sifields._sigfault._addr = 0;
-            queue_signal(env, info.si_signo, &info);
-            break;
-        case EXCP0D_GPF:
-            /* XXX: potential problem if ABI32 */
-#ifndef TARGET_X86_64
-            if (env->eflags & VM_MASK) {
-                handle_vm86_fault(env);
-            } else
-#endif
-            {
-                info.si_signo = SIGSEGV;
-                info.si_errno = 0;
-                info.si_code = TARGET_SI_KERNEL;
-                info._sifields._sigfault._addr = 0;
-                queue_signal(env, info.si_signo, &info);
-            }
-            break;
-        case EXCP0E_PAGE:
-            info.si_signo = SIGSEGV;
-            info.si_errno = 0;
-            if (!(env->error_code & 1))
-                info.si_code = TARGET_SEGV_MAPERR;
-            else
-                info.si_code = TARGET_SEGV_ACCERR;
-            info._sifields._sigfault._addr = env->cr[2];
-            queue_signal(env, info.si_signo, &info);
-            break;
-        case EXCP00_DIVZ:
-#ifndef TARGET_X86_64
-            if (env->eflags & VM_MASK) {
-                handle_vm86_trap(env, trapnr);
-            } else
-#endif
-            {
-                /* division by zero */
-                info.si_signo = SIGFPE;
-                info.si_errno = 0;
-                info.si_code = TARGET_FPE_INTDIV;
-                info._sifields._sigfault._addr = env->eip;
-                queue_signal(env, info.si_signo, &info);
-            }
-            break;
-        case EXCP01_DB:
-        case EXCP03_INT3:
-#ifndef TARGET_X86_64
-            if (env->eflags & VM_MASK) {
-                handle_vm86_trap(env, trapnr);
-            } else
-#endif
-            {
-                info.si_signo = SIGTRAP;
-                info.si_errno = 0;
-                if (trapnr == EXCP01_DB) {
-                    info.si_code = TARGET_TRAP_BRKPT;
-                    info._sifields._sigfault._addr = env->eip;
-                } else {
-                    info.si_code = TARGET_SI_KERNEL;
-                    info._sifields._sigfault._addr = 0;
-                }
-                queue_signal(env, info.si_signo, &info);
-            }
-            break;
-        case EXCP04_INTO:
-        case EXCP05_BOUND:
-#ifndef TARGET_X86_64
-            if (env->eflags & VM_MASK) {
-                handle_vm86_trap(env, trapnr);
-            } else
-#endif
-            {
-                info.si_signo = SIGSEGV;
-                info.si_errno = 0;
-                info.si_code = TARGET_SI_KERNEL;
-                info._sifields._sigfault._addr = 0;
-                queue_signal(env, info.si_signo, &info);
-            }
-            break;
-        case EXCP06_ILLOP:
-            info.si_signo = SIGILL;
-            info.si_errno = 0;
-            info.si_code = TARGET_ILL_ILLOPN;
-            info._sifields._sigfault._addr = env->eip;
-            queue_signal(env, info.si_signo, &info);
-            break;
-#endif
-        case EXCP_INTERRUPT:
-            /* just indicate that signals should be handled asap */
-            break;
-#if 0
-        case EXCP_DEBUG:
-            {
-                int sig;
-
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
-                if (sig)
-                  {
-                    info.si_signo = sig;
-                    info.si_errno = 0;
-                    info.si_code = TARGET_TRAP_BRKPT;
-                    queue_signal(env, info.si_signo, &info);
-                  }
-            }
-            break;
-#endif
-        default:
-            pc = env->segs[R_CS].base + env->eip;
-            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - 
aborting\n",
-                    (long)pc, trapnr);
-            abort();
-        }
-        process_pending_signals(env);
-    }
 }
-#endif
 
-#ifdef TARGET_SPARC
-#define SPARC64_STACK_BIAS 2047
 
-//#define DEBUG_WIN
-/* WARNING: dealing with register windows _is_ complicated. More info
-   can be found at http://www.sics.se/~psm/sparcstack.html */
-static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
+static inline void cpu_exec_end(CPUState *env)
 {
-    index = (index + cwp * 16) % (16 * env->nwindows);
-    /* wrap handling : if cwp is on the last window, then we use the
-       registers 'after' the end */
-    if (index < 8 && env->cwp == env->nwindows - 1)
-        index += 16 * env->nwindows;
-    return index;
 }
 
-/* save the register window 'cwp1' */
-static inline void save_window_offset(CPUSPARCState *env, int cwp1)
-{
-    unsigned int i;
-    abi_ulong sp_ptr;
-
-    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
-#ifdef TARGET_SPARC64
-    if (sp_ptr & 3)
-        sp_ptr += SPARC64_STACK_BIAS;
-#endif
-#if defined(DEBUG_WIN)
-    printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
-           sp_ptr, cwp1);
-#endif
-    for(i = 0; i < 16; i++) {
-        /* FIXME - what to do if put_user() fails? */
-        put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
-        sp_ptr += sizeof(abi_ulong);
-    }
-}
-
-static void save_window(CPUSPARCState *env)
-{
-#ifndef TARGET_SPARC64
-    unsigned int new_wim;
-    new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
-        ((1LL << env->nwindows) - 1);
-    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
-    env->wim = new_wim;
-#else
-    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
-    env->cansave++;
-    env->canrestore--;
-#endif
-}
-
-static void restore_window(CPUSPARCState *env)
+void cpu_list_lock(void)
 {
-#ifndef TARGET_SPARC64
-    unsigned int new_wim;
-#endif
-    unsigned int i, cwp1;
-    abi_ulong sp_ptr;
-
-#ifndef TARGET_SPARC64
-    new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
-        ((1LL << env->nwindows) - 1);
-#endif
-
-    /* restore the invalid window */
-    cwp1 = cpu_cwp_inc(env, env->cwp + 1);
-    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
-#ifdef TARGET_SPARC64
-    if (sp_ptr & 3)
-        sp_ptr += SPARC64_STACK_BIAS;
-#endif
-#if defined(DEBUG_WIN)
-    printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
-           sp_ptr, cwp1);
-#endif
-    for(i = 0; i < 16; i++) {
-        /* FIXME - what to do if get_user() fails? */
-        get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
-        sp_ptr += sizeof(abi_ulong);
-    }
-#ifdef TARGET_SPARC64
-    env->canrestore++;
-    if (env->cleanwin < env->nwindows - 1)
-        env->cleanwin++;
-    env->cansave--;
-#else
-    env->wim = new_wim;
-#endif
 }
 
-static void flush_windows(CPUSPARCState *env)
+void cpu_list_unlock(void)
 {
-    int offset, cwp1;
-
-    offset = 1;
-    for(;;) {
-        /* if restore would invoke restore_window(), then we can stop */
-        cwp1 = cpu_cwp_inc(env, env->cwp + offset);
-#ifndef TARGET_SPARC64
-        if (env->wim & (1 << cwp1))
-            break;
-#else
-        if (env->canrestore == 0)
-            break;
-        env->cansave++;
-        env->canrestore--;
-#endif
-        save_window_offset(env, cwp1);
-        offset++;
-    }
-    cwp1 = cpu_cwp_inc(env, env->cwp + 1);
-#ifndef TARGET_SPARC64
-    /* set wim so that restore will reload the registers */
-    env->wim = 1 << cwp1;
-#endif
-#if defined(DEBUG_WIN)
-    printf("flush_windows: nb=%d\n", offset - 1);
-#endif
 }
 
-void cpu_loop(CPUSPARCState *env)
+void cpu_loop(CPUArchState *env)
 {
-    CPUState *cs = CPU(sparc_env_get_cpu(env));
-    int trapnr, ret, syscall_nr;
-    //target_siginfo_t info;
 
-    while (1) {
-        trapnr = cpu_sparc_exec (env);
-
-        switch (trapnr) {
-#ifndef TARGET_SPARC64
-        case 0x80:
-#else
-        /* FreeBSD uses 0x141 for syscalls too */
-        case 0x141:
-            if (bsd_type != target_freebsd)
-                goto badtrap;
-        case 0x100:
-#endif
-            syscall_nr = env->gregs[1];
-            if (bsd_type == target_freebsd)
-                ret = do_freebsd_syscall(env, syscall_nr,
-                                         env->regwptr[0], env->regwptr[1],
-                                         env->regwptr[2], env->regwptr[3],
-                                         env->regwptr[4], env->regwptr[5], 0, 
0);
-            else if (bsd_type == target_netbsd)
-                ret = do_netbsd_syscall(env, syscall_nr,
-                                        env->regwptr[0], env->regwptr[1],
-                                        env->regwptr[2], env->regwptr[3],
-                                        env->regwptr[4], env->regwptr[5]);
-            else { //if (bsd_type == target_openbsd)
-#if defined(TARGET_SPARC64)
-                syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
-                                TARGET_OPENBSD_SYSCALL_G2RFLAG);
-#endif
-                ret = do_openbsd_syscall(env, syscall_nr,
-                                         env->regwptr[0], env->regwptr[1],
-                                         env->regwptr[2], env->regwptr[3],
-                                         env->regwptr[4], env->regwptr[5]);
-            }
-            if ((unsigned int)ret >= (unsigned int)(-515)) {
-                ret = -ret;
-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
-                env->xcc |= PSR_CARRY;
-#else
-                env->psr |= PSR_CARRY;
-#endif
-            } else {
-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
-                env->xcc &= ~PSR_CARRY;
-#else
-                env->psr &= ~PSR_CARRY;
-#endif
-            }
-            env->regwptr[0] = ret;
-            /* next instruction */
-#if defined(TARGET_SPARC64)
-            if (bsd_type == target_openbsd &&
-                env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
-                env->pc = env->gregs[2];
-                env->npc = env->pc + 4;
-            } else if (bsd_type == target_openbsd &&
-                       env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
-                env->pc = env->gregs[7];
-                env->npc = env->pc + 4;
-            } else {
-                env->pc = env->npc;
-                env->npc = env->npc + 4;
-            }
-#else
-            env->pc = env->npc;
-            env->npc = env->npc + 4;
-#endif
-            break;
-        case 0x83: /* flush windows */
-#ifdef TARGET_ABI32
-        case 0x103:
-#endif
-            flush_windows(env);
-            /* next instruction */
-            env->pc = env->npc;
-            env->npc = env->npc + 4;
-            break;
-#ifndef TARGET_SPARC64
-        case TT_WIN_OVF: /* window overflow */
-            save_window(env);
-            break;
-        case TT_WIN_UNF: /* window underflow */
-            restore_window(env);
-            break;
-        case TT_TFAULT:
-        case TT_DFAULT:
-#if 0
-            {
-                info.si_signo = SIGSEGV;
-                info.si_errno = 0;
-                /* XXX: check env->error_code */
-                info.si_code = TARGET_SEGV_MAPERR;
-                info._sifields._sigfault._addr = env->mmuregs[4];
-                queue_signal(env, info.si_signo, &info);
-            }
-#endif
-            break;
-#else
-        case TT_SPILL: /* window overflow */
-            save_window(env);
-            break;
-        case TT_FILL: /* window underflow */
-            restore_window(env);
-            break;
-        case TT_TFAULT:
-        case TT_DFAULT:
-#if 0
-            {
-                info.si_signo = SIGSEGV;
-                info.si_errno = 0;
-                /* XXX: check env->error_code */
-                info.si_code = TARGET_SEGV_MAPERR;
-                if (trapnr == TT_DFAULT)
-                    info._sifields._sigfault._addr = env->dmmuregs[4];
-                else
-                    info._sifields._sigfault._addr = env->tsptr->tpc;
-                //queue_signal(env, info.si_signo, &info);
-            }
-#endif
-            break;
-#endif
-        case EXCP_INTERRUPT:
-            /* just indicate that signals should be handled asap */
-            break;
-        case EXCP_DEBUG:
-            {
-                int sig;
-
-                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
-#if 0
-                if (sig)
-                  {
-                    info.si_signo = sig;
-                    info.si_errno = 0;
-                    info.si_code = TARGET_TRAP_BRKPT;
-                    //queue_signal(env, info.si_signo, &info);
-                  }
-#endif
-            }
-            break;
-        default:
-#ifdef TARGET_SPARC64
-        badtrap:
-#endif
-            printf ("Unhandled trap: 0x%x\n", trapnr);
-            cpu_dump_state(cs, stderr, fprintf, 0);
-            exit (1);
-        }
-        process_pending_signals (env);
-    }
+    target_cpu_loop(env);
 }
 
-#endif
-
 static void usage(void)
 {
     printf("qemu-" TARGET_NAME " version " QEMU_VERSION ", Copyright (c) 
2003-2008 Fabrice Bellard\n"
@@ -709,12 +147,21 @@ static void usage(void)
            ,
            TARGET_NAME,
            interp_prefix,
-           x86_stack_size);
+           target_dflssiz);
     exit(1);
 }
 
 THREAD CPUState *thread_cpu;
 
+void stop_all_tasks(void)
+{
+    /*
+     * We trust when using NPTL (pthreads) start_exclusive() handles thread
+     * stopping correctly.
+     */
+    start_exclusive();
+}
+
 /* Assumes contents are already zeroed.  */
 void init_task_state(TaskState *ts)
 {
@@ -728,6 +175,15 @@ void init_task_state(TaskState *ts)
     ts->sigqueue_table[i].next = NULL;
 }
 
+void gemu_log(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+}
+
 int main(int argc, char **argv)
 {
     const char *filename;
@@ -744,11 +200,13 @@ int main(int argc, char **argv)
     int gdbstub_port = 0;
     char **target_environ, **wrk;
     envlist_t *envlist = NULL;
-    bsd_type = target_openbsd;
+    bsd_type = HOST_DEFAULT_BSD_TYPE;
 
     if (argc <= 1)
         usage();
 
+    save_proc_pathname(argv[0]);
+
     module_call_init(MODULE_INIT_QOM);
 
     if ((envlist = envlist_create()) == NULL) {
@@ -767,7 +225,7 @@ int main(int argc, char **argv)
 #endif
 
     optind = 1;
-    for(;;) {
+    for (;;) {
         if (optind >= argc)
             break;
         r = argv[optind];
@@ -803,13 +261,18 @@ int main(int argc, char **argv)
                 usage();
         } else if (!strcmp(r, "s")) {
             r = argv[optind++];
-            x86_stack_size = strtol(r, (char **)&r, 0);
-            if (x86_stack_size <= 0)
+            target_dflssiz = strtol(r, (char **)&r, 0);
+            if (target_dflssiz <= 0) {
+                usage();
+            }
+            if (*r == 'M') {
+                target_dflssiz *= 1024 * 1024;
+            } else if (*r == 'k' || *r == 'K') {
+                target_dflssiz *= 1024;
+            }
+            if (target_dflssiz > target_maxssiz) {
                 usage();
-            if (*r == 'M')
-                x86_stack_size *= 1024 * 1024;
-            else if (*r == 'k' || *r == 'K')
-                x86_stack_size *= 1024;
+            }
         } else if (!strcmp(r, "L")) {
             interp_prefix = argv[optind++];
         } else if (!strcmp(r, "p")) {
@@ -888,21 +351,7 @@ int main(int argc, char **argv)
     init_paths(interp_prefix);
 
     if (cpu_model == NULL) {
-#if defined(TARGET_I386)
-#ifdef TARGET_X86_64
-        cpu_model = "qemu64";
-#else
-        cpu_model = "qemu32";
-#endif
-#elif defined(TARGET_SPARC)
-#ifdef TARGET_SPARC64
-        cpu_model = "TI UltraSparc II";
-#else
-        cpu_model = "Fujitsu MB86904";
-#endif
-#else
-        cpu_model = "any";
-#endif
+        cpu_model = TARGET_DEFAULT_CPU_MODEL;
     }
     tcg_exec_init(0);
     cpu_exec_init_all();
@@ -914,9 +363,7 @@ int main(int argc, char **argv)
         exit(1);
     }
     cpu = ENV_GET_CPU(env);
-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_reset(cpu);
-#endif
+    TARGET_CPU_RESET(env);
     thread_cpu = cpu;
 
     if (getenv("QEMU_STRACE")) {
@@ -955,7 +402,7 @@ int main(int argc, char **argv)
     }
 #endif /* CONFIG_USE_GUEST_BASE */
 
-    if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
+    if (loader_exec(filename, argv+optind, target_environ, regs, info)) {
         printf("Error loading %s\n", filename);
         _exit(1);
     }
@@ -1002,137 +449,7 @@ int main(int argc, char **argv)
     ts->info = info;
     env->opaque = ts;
 
-#if defined(TARGET_I386)
-    cpu_x86_set_cpl(env, 3);
-
-    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
-    env->hflags |= HF_PE_MASK;
-    if (env->features[FEAT_1_EDX] & CPUID_SSE) {
-        env->cr[4] |= CR4_OSFXSR_MASK;
-        env->hflags |= HF_OSFXSR_MASK;
-    }
-#ifndef TARGET_ABI32
-    /* enable 64 bit mode if possible */
-    if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
-        fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
-        exit(1);
-    }
-    env->cr[4] |= CR4_PAE_MASK;
-    env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
-    env->hflags |= HF_LMA_MASK;
-#endif
-
-    /* flags setup : we activate the IRQs by default as in user mode */
-    env->eflags |= IF_MASK;
-
-    /* linux register setup */
-#ifndef TARGET_ABI32
-    env->regs[R_EAX] = regs->rax;
-    env->regs[R_EBX] = regs->rbx;
-    env->regs[R_ECX] = regs->rcx;
-    env->regs[R_EDX] = regs->rdx;
-    env->regs[R_ESI] = regs->rsi;
-    env->regs[R_EDI] = regs->rdi;
-    env->regs[R_EBP] = regs->rbp;
-    env->regs[R_ESP] = regs->rsp;
-    env->eip = regs->rip;
-#else
-    env->regs[R_EAX] = regs->eax;
-    env->regs[R_EBX] = regs->ebx;
-    env->regs[R_ECX] = regs->ecx;
-    env->regs[R_EDX] = regs->edx;
-    env->regs[R_ESI] = regs->esi;
-    env->regs[R_EDI] = regs->edi;
-    env->regs[R_EBP] = regs->ebp;
-    env->regs[R_ESP] = regs->esp;
-    env->eip = regs->eip;
-#endif
-
-    /* linux interrupt setup */
-#ifndef TARGET_ABI32
-    env->idt.limit = 511;
-#else
-    env->idt.limit = 255;
-#endif
-    env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
-                                PROT_READ|PROT_WRITE,
-                                MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
-    idt_table = g2h(env->idt.base);
-    set_idt(0, 0);
-    set_idt(1, 0);
-    set_idt(2, 0);
-    set_idt(3, 3);
-    set_idt(4, 3);
-    set_idt(5, 0);
-    set_idt(6, 0);
-    set_idt(7, 0);
-    set_idt(8, 0);
-    set_idt(9, 0);
-    set_idt(10, 0);
-    set_idt(11, 0);
-    set_idt(12, 0);
-    set_idt(13, 0);
-    set_idt(14, 0);
-    set_idt(15, 0);
-    set_idt(16, 0);
-    set_idt(17, 0);
-    set_idt(18, 0);
-    set_idt(19, 0);
-    set_idt(0x80, 3);
-
-    /* linux segment setup */
-    {
-        uint64_t *gdt_table;
-        env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
-                                    PROT_READ|PROT_WRITE,
-                                    MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
-        env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
-        gdt_table = g2h(env->gdt.base);
-#ifdef TARGET_ABI32
-        write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
-                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
-                 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
-#else
-        /* 64 bit code segment */
-        write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
-                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
-                 DESC_L_MASK |
-                 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
-#endif
-        write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
-                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
-                 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
-    }
-
-    cpu_x86_load_seg(env, R_CS, __USER_CS);
-    cpu_x86_load_seg(env, R_SS, __USER_DS);
-#ifdef TARGET_ABI32
-    cpu_x86_load_seg(env, R_DS, __USER_DS);
-    cpu_x86_load_seg(env, R_ES, __USER_DS);
-    cpu_x86_load_seg(env, R_FS, __USER_DS);
-    cpu_x86_load_seg(env, R_GS, __USER_DS);
-    /* This hack makes Wine work... */
-    env->segs[R_FS].selector = 0;
-#else
-    cpu_x86_load_seg(env, R_DS, 0);
-    cpu_x86_load_seg(env, R_ES, 0);
-    cpu_x86_load_seg(env, R_FS, 0);
-    cpu_x86_load_seg(env, R_GS, 0);
-#endif
-#elif defined(TARGET_SPARC)
-    {
-        int i;
-        env->pc = regs->pc;
-        env->npc = regs->npc;
-        env->y = regs->y;
-        for(i = 0; i < 8; i++)
-            env->gregs[i] = regs->u_regs[i];
-        for(i = 0; i < 8; i++)
-            env->regwptr[i] = regs->u_regs[i + 8];
-    }
-#else
-#error unsupported target CPU
-#endif
+    target_cpu_init(env, regs);
 
     if (gdbstub_port) {
         gdbserver_start (gdbstub_port);
diff --git a/bsd-user/mips/target_arch.h b/bsd-user/mips/target_arch.h
new file mode 100644
index 0000000..b3d32ba
--- /dev/null
+++ b/bsd-user/mips/target_arch.h
@@ -0,0 +1,10 @@
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+#include "qemu.h"
+
+void target_cpu_set_tls(CPUMIPSState *env, target_ulong newtls);
+target_ulong target_cpu_get_tls(CPUMIPSState *env);
+
+#endif /* !_TARGET_ARCH_H_ */
diff --git a/bsd-user/mips/target_arch_cpu.c b/bsd-user/mips/target_arch_cpu.c
new file mode 100644
index 0000000..dd59435
--- /dev/null
+++ b/bsd-user/mips/target_arch_cpu.c
@@ -0,0 +1,27 @@
+/*
+ *  mips cpu related code
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "target_arch.h"
+
+void target_cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
+{
+    env->tls_value = newtls;
+}
+
+target_ulong target_cpu_get_tls(CPUMIPSState *env)
+{
+    return (env->tls_value);
+}
diff --git a/bsd-user/mips/target_arch_cpu.h b/bsd-user/mips/target_arch_cpu.h
new file mode 100644
index 0000000..b92deb6
--- /dev/null
+++ b/bsd-user/mips/target_arch_cpu.h
@@ -0,0 +1,243 @@
+/*
+ *  mips cpu init and loop
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TARGET_ARCH_CPU_H_
+#define _TARGET_ARCH_CPU_H_
+
+#include "target_arch.h"
+
+#if defined(TARGET_ABI_MIPSN32)
+#  define TARGET_DEFAULT_CPU_MODEL "20Kc"
+#else
+#  define TARGET_DEFAULT_CPU_MODEL "24f"
+#endif
+
+#define TARGET_CPU_RESET(env)
+
+static inline void target_cpu_init(CPUMIPSState *env,
+        struct target_pt_regs *regs)
+{
+    int i;
+
+    for (i = 0; i < 32; i++) {
+        env->active_tc.gpr[i] = regs->regs[i];
+    }
+    env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
+    if (regs->cp0_epc & 1) {
+        env->hflags |= MIPS_HFLAG_M16;
+    }
+}
+
+static int do_store_exclusive(CPUMIPSState *env)
+{
+    target_ulong addr;
+    target_ulong page_addr;
+    target_ulong val;
+    int flags;
+    int segv = 0;
+    int reg;
+    int d;
+
+    addr = env->lladdr;
+    page_addr = addr & TARGET_PAGE_MASK;
+    start_exclusive();
+    mmap_lock();
+    flags = page_get_flags(page_addr);
+    if ((flags & PAGE_READ) == 0) {
+        segv = 1;
+    } else {
+        reg = env->llreg & 0x1f;
+        d = (env->llreg & 0x20) != 0;
+        if (d) {
+            segv = get_user_s64(val, addr);
+        } else {
+            segv = get_user_s32(val, addr);
+        }
+        if (!segv) {
+            if (val != env->llval) {
+                env->active_tc.gpr[reg] = 0;
+            } else {
+                if (d) {
+                    segv = put_user_u64(env->llnewval, addr);
+                } else {
+                    segv = put_user_u32(env->llnewval, addr);
+                }
+                if (!segv) {
+                    env->active_tc.gpr[reg] = 1;
+                }
+            }
+        }
+    }
+    env->lladdr = -1;
+    if (!segv) {
+        env->active_tc.PC += 4;
+    }
+    mmap_unlock();
+    end_exclusive();
+    return segv;
+}
+
+static inline void target_cpu_loop(CPUMIPSState *env)
+{
+    CPUState *cs = CPU(mips_env_get_cpu(env));
+    target_siginfo_t info;
+    int trapnr;
+    abi_long ret;
+    unsigned int syscall_num;
+
+    for (;;) {
+        cpu_exec_start(cs);
+        trapnr = cpu_mips_exec(env);
+        cpu_exec_end(cs);
+        switch (trapnr) {
+        case EXCP_SYSCALL: /* syscall exception */
+            if (bsd_type == target_freebsd) {
+                syscall_num = env->active_tc.gpr[2]; /* v0 */
+                env->active_tc.PC += TARGET_INSN_SIZE;
+                if (syscall_num >= TARGET_FREEBSD_NR_MAXSYSCALL) {
+                    ret = -TARGET_ENOSYS;
+                } else {
+                    /* mips(32) uses regs 4-7,12-15 for args */
+                    if (TARGET_FREEBSD_NR___syscall == syscall_num ||
+                            TARGET_FREEBSD_NR_syscall == syscall_num) {
+                        /* indirect syscall */
+                        ret = do_freebsd_syscall(env,
+                                env->active_tc.gpr[4],/* syscall #*/
+                                env->active_tc.gpr[5], /* a1/arg0 */
+                                env->active_tc.gpr[6], /* a2/arg1 */
+                                env->active_tc.gpr[7], /* a3/arg2 */
+                                env->active_tc.gpr[12],/* t4/arg3 */
+                                env->active_tc.gpr[13],/* t5/arg4 */
+                                env->active_tc.gpr[14],/* t6/arg5 */
+                                env->active_tc.gpr[15],/* t7/arg6 */
+                                0  /* no arg7 */
+                                );
+                    } else {
+                        /* direct syscall */
+                        ret = do_freebsd_syscall(env,
+                                syscall_num,
+                                env->active_tc.gpr[4], /* a0/arg0 */
+                                env->active_tc.gpr[5], /* a1/arg1 */
+                                env->active_tc.gpr[6], /* a2/arg2 */
+                                env->active_tc.gpr[7], /* a3/arg3 */
+                                env->active_tc.gpr[12],/* t4/arg4 */
+                                env->active_tc.gpr[13],/* t5/arg5 */
+                                env->active_tc.gpr[14],/* t6/arg6 */
+                                env->active_tc.gpr[15] /* t7/arg7 */
+                                );
+                    }
+                }
+                /* Compare to mips/mips/vm_machdep.c cpu_set_syscall_retval() 
*/
+                if (-TARGET_EJUSTRETURN == ret) {
+                    /*
+                     * Returning from a successful sigreturn
+                     * syscall.  Avoid clobbering register state.
+                     */
+                    break;
+                }
+                if (-TARGET_ERESTART == ret) {
+                    /* Backup the pc to point at the swi. */
+                    env->active_tc.PC -= TARGET_INSN_SIZE;
+                    break;
+                }
+                if ((unsigned int)ret >= (unsigned int)(-1133)) {
+                    env->active_tc.gpr[7] = 1;
+                    ret = -ret;
+                } else {
+                    env->active_tc.gpr[7] = 0;
+                }
+                env->active_tc.gpr[2] = ret; /* v0 <- ret */
+            } /* else if (bsd_type == target_openbsd)... */
+            else {
+                fprintf(stderr, "qemu: bsd_type (= %d) syscall not 
supported\n",
+                        bsd_type);
+            }
+            break;
+
+        case EXCP_TLBL: /* TLB miss on load */
+        case EXCP_TLBS: /* TLB miss on store */
+        case EXCP_AdEL: /* bad address on load */
+        case EXCP_AdES: /* bad address on store */
+            info.target_si_signo = TARGET_SIGSEGV;
+            info.target_si_errno = 0;
+            /* XXX: check env->error_code */
+            info.target_si_code = TARGET_SEGV_MAPERR;
+            info.target_si_addr = env->CP0_BadVAddr;
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP_CpU: /* coprocessor unusable */
+        case EXCP_RI:  /* reserved instruction */
+            info.target_si_signo = TARGET_SIGILL;
+            info.target_si_errno = 0;
+            info.target_si_code = 0;
+            queue_signal(env, info.target_si_signo, &info);
+            break;
+
+        case EXCP_INTERRUPT: /* async interrupt */
+            /* just indicate that signals should be handled asap */
+            break;
+
+        case EXCP_DEBUG: /* cpu stopped after a breakpoint */
+            {
+                int sig;
+
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
+                if (sig) {
+                    info.target_si_signo = sig;
+                    info.target_si_errno = 0;
+                    info.target_si_code = TARGET_TRAP_BRKPT;
+                    queue_signal(env, info.target_si_signo, &info);
+                }
+            }
+            break;
+
+        case EXCP_SC:
+            if (do_store_exclusive(env)) {
+                info.target_si_signo = TARGET_SIGSEGV;
+                info.target_si_errno = 0;
+                info.target_si_code = TARGET_SEGV_MAPERR;
+                info.target_si_addr = env->active_tc.PC;
+                queue_signal(env, info.target_si_signo, &info);
+            }
+            break;
+
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception "
+                "0x%x - aborting\n", trapnr);
+            cpu_dump_state(cs, stderr, fprintf, 0);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+
+static inline void target_cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
+{
+    if (newsp)
+        env->active_tc.gpr[29] = newsp;
+    env->active_tc.gpr[7] = 0;
+    env->active_tc.gpr[2] = 0;
+}
+
+static inline void target_cpu_reset(CPUArchState *cpu)
+{
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/mips/target_arch_vmparam.h 
b/bsd-user/mips/target_arch_vmparam.h
new file mode 100644
index 0000000..f9e54ce
--- /dev/null
+++ b/bsd-user/mips/target_arch_vmparam.h
@@ -0,0 +1,47 @@
+/*
+ *  mips VM parameters definitions
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_ARCH_VMPARAM_H_
+#define _TARGET_ARCH_VMPARAM_H_
+
+#include "cpu.h"
+
+/* compare to sys/mips/include/vmparam.h */
+#define TARGET_MAXTSIZ      (128UL*1024*1024)   /* max text size */
+#define TARGET_DFLDSIZ      (128UL*1024*1024)   /* initial data size limit */
+#define TARGET_MAXDSIZ      (1*1024UL*1024*1024)    /* max data size */
+#define TARGET_DFLSSIZ      (8UL*1024*1024)     /* initial stack size limit */
+#define TARGET_MAXSSIZ      (64UL*1024*1024)    /* max stack size */
+#define TARGET_SGROWSIZ     (128UL*1024)        /* amount to grow stack */
+
+#define TARGET_VM_MINUSER_ADDRESS   (0x00000000)
+#define TARGET_VM_MAXUSER_ADDRESS   (0x80000000)
+
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
+
+static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
+{
+    return state->active_tc.gpr[29];
+}
+
+static inline void set_second_rval(CPUMIPSState *state, abi_ulong retval2)
+{
+    state->active_tc.gpr[3] = retval2;
+}
+
+#endif  /* ! _TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/mips64/target_arch.h b/bsd-user/mips64/target_arch.h
new file mode 100644
index 0000000..b3d32ba
--- /dev/null
+++ b/bsd-user/mips64/target_arch.h
@@ -0,0 +1,10 @@
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+#include "qemu.h"
+
+void target_cpu_set_tls(CPUMIPSState *env, target_ulong newtls);
+target_ulong target_cpu_get_tls(CPUMIPSState *env);
+
+#endif /* !_TARGET_ARCH_H_ */
diff --git a/bsd-user/mips64/target_arch_cpu.c 
b/bsd-user/mips64/target_arch_cpu.c
new file mode 100644
index 0000000..9d016a3
--- /dev/null
+++ b/bsd-user/mips64/target_arch_cpu.c
@@ -0,0 +1,27 @@
+/*
+ *  mips64 cpu related code
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "target_arch.h"
+
+void target_cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
+{
+    env->tls_value = newtls;
+}
+
+target_ulong target_cpu_get_tls(CPUMIPSState *env)
+{
+    return (env->tls_value);
+}
diff --git a/bsd-user/mips64/target_arch_cpu.h 
b/bsd-user/mips64/target_arch_cpu.h
new file mode 100644
index 0000000..c5a4acd
--- /dev/null
+++ b/bsd-user/mips64/target_arch_cpu.h
@@ -0,0 +1,243 @@
+/*
+ *  mips64 cpu init and loop
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TARGET_ARCH_CPU_H_
+#define _TARGET_ARCH_CPU_H_
+
+#include "target_arch.h"
+
+#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
+#  define TARGET_DEFAULT_CPU_MODEL "20Kc"
+#else
+#  define TARGET_DEFAULT_CPU_MODEL "24f"
+#endif
+
+#define TARGET_CPU_RESET(env)
+
+static inline void target_cpu_init(CPUMIPSState *env,
+        struct target_pt_regs *regs)
+{
+    int i;
+
+    for (i = 0; i < 32; i++) {
+        env->active_tc.gpr[i] = regs->regs[i];
+    }
+    env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
+    if (regs->cp0_epc & 1) {
+        env->hflags |= MIPS_HFLAG_M16;
+    }
+    env->hflags |= MIPS_HFLAG_UX | MIPS_HFLAG_64;
+}
+
+static int do_store_exclusive(CPUMIPSState *env)
+{
+    target_ulong addr;
+    target_ulong page_addr;
+    target_ulong val;
+    int flags;
+    int segv = 0;
+    int reg;
+    int d;
+
+    addr = env->lladdr;
+    page_addr = addr & TARGET_PAGE_MASK;
+    start_exclusive();
+    mmap_lock();
+    flags = page_get_flags(page_addr);
+    if ((flags & PAGE_READ) == 0) {
+        segv = 1;
+    } else {
+        reg = env->llreg & 0x1f;
+        d = (env->llreg & 0x20) != 0;
+        if (d) {
+            segv = get_user_s64(val, addr);
+        } else {
+            segv = get_user_s32(val, addr);
+        }
+        if (!segv) {
+            if (val != env->llval) {
+                env->active_tc.gpr[reg] = 0;
+            } else {
+                if (d) {
+                    segv = put_user_u64(env->llnewval, addr);
+                } else {
+                    segv = put_user_u32(env->llnewval, addr);
+                }
+                if (!segv) {
+                    env->active_tc.gpr[reg] = 1;
+                }
+            }
+        }
+    }
+    env->lladdr = -1;
+    if (!segv) {
+        env->active_tc.PC += 4;
+    }
+    mmap_unlock();
+    end_exclusive();
+    return segv;
+}
+
+static inline void target_cpu_loop(CPUMIPSState *env)
+{
+    CPUState *cs = CPU(mips_env_get_cpu(env));
+    target_siginfo_t info;
+    int trapnr;
+    abi_long ret;
+    unsigned int syscall_num;
+
+    for (;;) {
+        cpu_exec_start(cs);
+        trapnr = cpu_mips_exec(env);
+        cpu_exec_end(cs);
+        switch (trapnr) {
+        case EXCP_SYSCALL: /* syscall exception */
+            if (bsd_type == target_freebsd) {
+                syscall_num = env->active_tc.gpr[2]; /* v0 */
+                env->active_tc.PC += TARGET_INSN_SIZE;
+                if (syscall_num >= TARGET_FREEBSD_NR_MAXSYSCALL) {
+                    ret = -TARGET_ENOSYS;
+                } else {
+                    /* mips64 uses regs 4-11 for args */
+                    if (TARGET_FREEBSD_NR___syscall == syscall_num ||
+                            TARGET_FREEBSD_NR_syscall == syscall_num) {
+                        /* indirect syscall */
+                        ret = do_freebsd_syscall(env,
+                                env->active_tc.gpr[4],/* syscall #*/
+                                env->active_tc.gpr[5], /* arg0 */
+                                env->active_tc.gpr[6], /* arg1 */
+                                env->active_tc.gpr[7], /* arg2 */
+                                env->active_tc.gpr[8], /* arg3 */
+                                env->active_tc.gpr[9], /* arg4 */
+                                env->active_tc.gpr[10],/* arg5 */
+                                env->active_tc.gpr[11],/* arg6 */
+                                0 /* no arg 7 */);
+                    } else {
+                        /* direct syscall */
+                        ret = do_freebsd_syscall(env,
+                                syscall_num,
+                                env->active_tc.gpr[4],
+                                env->active_tc.gpr[5],
+                                env->active_tc.gpr[6],
+                                env->active_tc.gpr[7],
+                                env->active_tc.gpr[8],
+                                env->active_tc.gpr[9],
+                                env->active_tc.gpr[10],
+                                env->active_tc.gpr[11]
+                                );
+                    }
+                }
+                /* Compare to mips/mips/vm_machdep.c cpu_set_syscall_retval() 
*/
+                if (-TARGET_EJUSTRETURN == ret) {
+                    /*
+                     * Returning from a successful sigreturn
+                     * syscall.  Avoid clobbering register state.
+                     */
+                    break;
+                }
+                if (-TARGET_ERESTART == ret) {
+                    /* Backup the pc to point at the swi. */
+                    env->active_tc.PC -= TARGET_INSN_SIZE;
+                    break;
+                }
+                if ((unsigned int)ret >= (unsigned int)(-1133)) {
+                    env->active_tc.gpr[7] = 1;
+                    ret = -ret;
+                } else {
+                    env->active_tc.gpr[7] = 0;
+                }
+                env->active_tc.gpr[2] = ret; /* v0 <- ret */
+            } /* else if (bsd_type == target_openbsd)... */
+            else {
+                fprintf(stderr, "qemu: bsd_type (= %d) syscall not 
supported\n",
+                        bsd_type);
+            }
+            break;
+
+        case EXCP_TLBL: /* TLB miss on load */
+        case EXCP_TLBS: /* TLB miss on store */
+        case EXCP_AdEL: /* bad address on load */
+        case EXCP_AdES: /* bad address on store */
+            info.target_si_signo = TARGET_SIGSEGV;
+            info.target_si_errno = 0;
+            /* XXX: check env->error_code */
+            info.target_si_code = TARGET_SEGV_MAPERR;
+            info.target_si_addr = env->CP0_BadVAddr;
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP_CpU: /* coprocessor unusable */
+        case EXCP_RI:  /* reserved instruction */
+            info.target_si_signo = TARGET_SIGILL;
+            info.target_si_errno = 0;
+            info.target_si_code = 0;
+            queue_signal(env, info.target_si_signo, &info);
+            break;
+
+        case EXCP_INTERRUPT: /* async interrupt */
+            /* just indicate that signals should be handled asap */
+            break;
+
+        case EXCP_DEBUG: /* cpu stopped after a breakpoint */
+            {
+                int sig;
+
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
+                if (sig) {
+                    info.target_si_signo = sig;
+                    info.target_si_errno = 0;
+                    info.target_si_code = TARGET_TRAP_BRKPT;
+                    queue_signal(env, info.target_si_signo, &info);
+                }
+            }
+            break;
+
+        case EXCP_SC:
+            if (do_store_exclusive(env)) {
+                info.target_si_signo = TARGET_SIGSEGV;
+                info.target_si_errno = 0;
+                info.target_si_code = TARGET_SEGV_MAPERR;
+                info.target_si_addr = env->active_tc.PC;
+                queue_signal(env, info.target_si_signo, &info);
+            }
+            break;
+
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception "
+                "0x%x - aborting\n", trapnr);
+            cpu_dump_state(cs, stderr, fprintf, 0);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+
+static inline void target_cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
+{
+    if (newsp)
+        env->active_tc.gpr[29] = newsp;
+    env->active_tc.gpr[7] = 0;
+    env->active_tc.gpr[2] = 0;
+}
+
+static inline void target_cpu_reset(CPUArchState *cpu)
+{
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/mips64/target_arch_vmparam.h 
b/bsd-user/mips64/target_arch_vmparam.h
new file mode 100644
index 0000000..1ba09e0
--- /dev/null
+++ b/bsd-user/mips64/target_arch_vmparam.h
@@ -0,0 +1,47 @@
+/*
+ *  mips64 VM parameters definitions
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_ARCH_VMPARAM_H_
+#define _TARGET_ARCH_VMPARAM_H_
+
+#include "cpu.h"
+
+/* compare to sys/mips/include/vmparam.h */
+#define TARGET_MAXTSIZ      (128UL*1024*1024)   /* max text size */
+#define TARGET_DFLDSIZ      (128UL*1024*1024)   /* initial data size limit */
+#define TARGET_MAXDSIZ      (1*1024UL*1024*1024)    /* max data size */
+#define TARGET_DFLSSIZ      (8UL*1024*1024)     /* initial stack size limit */
+#define TARGET_MAXSSIZ      (64UL*1024*1024)    /* max stack size */
+#define TARGET_SGROWSIZ     (128UL*1024)        /* amount to grow stack */
+
+#define TARGET_VM_MINUSER_ADDRESS   (0x0000000000000000UL)
+#define TARGET_VM_MAXUSER_ADDRESS   (0x0000008000000000UL)
+
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
+
+static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
+{
+    return state->active_tc.gpr[29];
+}
+
+static inline void set_second_rval(CPUMIPSState *state, abi_ulong retval2)
+{
+    state->active_tc.gpr[3] = retval2;
+}
+
+#endif  /* ! _TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/netbsd/host_os.h b/bsd-user/netbsd/host_os.h
new file mode 100644
index 0000000..5c492e3
--- /dev/null
+++ b/bsd-user/netbsd/host_os.h
@@ -0,0 +1,31 @@
+/*
+ *  NetBSD host dependent code and definitions
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HOST_OS_H_
+#define __HOST_OS_H_
+
+#include "qemu.h"
+
+#define HOST_DEFAULT_BSD_TYPE target_netbsd
+
+static inline void save_proc_pathname(char *argv0)
+{
+    /* XXX */
+}
+
+#endif /*!__HOST_OS_H_ */
diff --git a/bsd-user/openbsd/host_os.h b/bsd-user/openbsd/host_os.h
new file mode 100644
index 0000000..162ce58
--- /dev/null
+++ b/bsd-user/openbsd/host_os.h
@@ -0,0 +1,31 @@
+/*
+ *  OpenBSD host dependent code and definitions
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HOST_OS_H_
+#define __HOST_OS_H_
+
+#include "qemu.h"
+
+#define HOST_DEFAULT_BSD_TYPE target_openbsd
+
+static inline void save_proc_pathname(char *argv0)
+{
+    /* XXX */
+}
+
+#endif /*!__HOST_OS_H_ */
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index b8a34c7..cb77069 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -38,6 +38,7 @@ extern enum BSDType bsd_type;
 
 #include "syscall_defs.h"
 #include "syscall.h"
+#include "target_os_vmparam.h"
 #include "target_signal.h"
 #include "exec/gdbstub.h"
 
@@ -99,6 +100,7 @@ typedef struct TaskState {
 } __attribute__((aligned(16))) TaskState;
 
 void init_task_state(TaskState *ts);
+void stop_all_tasks(void);
 extern const char *qemu_uname_release;
 #if defined(CONFIG_USE_GUEST_BASE)
 extern unsigned long mmap_min_addr;
@@ -222,7 +224,13 @@ void mmap_fork_end(int child);
 #endif
 
 /* main.c */
-extern unsigned long x86_stack_size;
+extern unsigned long target_maxtsiz;
+extern unsigned long target_dfldsiz;
+extern unsigned long target_maxdsiz;
+extern unsigned long target_dflssiz;
+extern unsigned long target_maxssiz;
+extern unsigned long target_sgrowsiz;
+extern char qemu_proc_pathname[];
 
 /* user access */
 
diff --git a/bsd-user/sparc/target_arch.h b/bsd-user/sparc/target_arch.h
new file mode 100644
index 0000000..5ee479b
--- /dev/null
+++ b/bsd-user/sparc/target_arch.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+void bsd_sparc_save_window(CPUSPARCState *env);
+void bsd_sparc_restore_window(CPUSPARCState *env);
+void bsd_sparc_flush_windows(CPUSPARCState *env);
+
+#define target_cpu_set_tls(env, newtls)
+
+#endif /* ! _TARGET_ARCH_H_ */
diff --git a/bsd-user/sparc/target_arch_cpu.c b/bsd-user/sparc/target_arch_cpu.c
new file mode 100644
index 0000000..0af5c7e
--- /dev/null
+++ b/bsd-user/sparc/target_arch_cpu.c
@@ -0,0 +1,113 @@
+/*
+ *  sparc cpu related code
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+
+#include "cpu.h"
+#include "qemu.h"
+
+#include "target_arch.h"
+
+/* #define DEBUG_WIN */
+/* WARNING: dealing with register windows _is_ complicated. More info
+   can be found at http://www.sics.se/~psm/sparcstack.html */
+static int get_reg_index(CPUSPARCState *env, int cwp, int index)
+{
+    index = (index + cwp * 16) % (16 * env->nwindows);
+    /* wrap handling : if cwp is on the last window, then we use the
+       registers 'after' the end */
+    if (index < 8 && env->cwp == env->nwindows - 1) {
+        index += 16 * env->nwindows;
+    }
+    return index;
+}
+
+/* save the register window 'cwp1' */
+static void save_window_offset(CPUSPARCState *env, int cwp1)
+{
+    unsigned int i;
+    abi_ulong sp_ptr;
+
+    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
+#if defined(DEBUG_WIN)
+    printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
+           sp_ptr, cwp1);
+#endif
+    for (i = 0; i < 16; i++) {
+        /* FIXME - what to do if put_user() fails? */
+        put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
+        sp_ptr += sizeof(abi_ulong);
+    }
+}
+
+void bsd_sparc_save_window(CPUSPARCState *env)
+{
+    unsigned int new_wim;
+
+    new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
+        ((1LL << env->nwindows) - 1);
+    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
+    env->wim = new_wim;
+}
+
+void bsd_sparc_restore_window(CPUSPARCState *env)
+{
+    unsigned int new_wim;
+    unsigned int i, cwp1;
+    abi_ulong sp_ptr;
+
+    new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
+        ((1LL << env->nwindows) - 1);
+
+    /* restore the invalid window */
+    cwp1 = cpu_cwp_inc(env, env->cwp + 1);
+    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
+#if defined(DEBUG_WIN)
+    printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
+           sp_ptr, cwp1);
+#endif
+    for (i = 0; i < 16; i++) {
+        /* FIXME - what to do if get_user() fails? */
+        get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
+        sp_ptr += sizeof(abi_ulong);
+    }
+    env->wim = new_wim;
+}
+
+void bsd_sparc_flush_windows(CPUSPARCState *env)
+{
+    int offset, cwp1;
+
+    offset = 1;
+    for (;;) {
+        /* if restore would invoke restore_window(), then we can stop */
+        cwp1 = cpu_cwp_inc(env, env->cwp + offset);
+        if (env->wim & (1 << cwp1)) {
+            break;
+        }
+        save_window_offset(env, cwp1);
+        offset++;
+    }
+    cwp1 = cpu_cwp_inc(env, env->cwp + 1);
+    /* set wim so that restore will reload the registers */
+    env->wim = 1 << cwp1;
+#if defined(DEBUG_WIN)
+    printf("bsd_sparc_flush_windows: nb=%d\n", offset - 1);
+#endif
+}
+
diff --git a/bsd-user/sparc/target_arch_cpu.h b/bsd-user/sparc/target_arch_cpu.h
new file mode 100644
index 0000000..2eabff6
--- /dev/null
+++ b/bsd-user/sparc/target_arch_cpu.h
@@ -0,0 +1,158 @@
+/*
+ *  sparc cpu init and loop
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TARGET_ARCH_CPU_H_
+#define _TARGET_ARCH_CPU_H_
+
+#include "target_arch.h"
+
+#define TARGET_DEFAULT_CPU_MODEL "Fujitsu MB86904"
+
+#define TARGET_CPU_RESET(env) cpu_reset(ENV_GET_CPU(env))
+
+static inline void target_cpu_init(CPUSPARCState *env,
+        struct target_pt_regs *regs)
+{
+    int i;
+
+    env->pc = regs->pc;
+    env->npc = regs->npc;
+    env->y = regs->y;
+    for (i = 0; i < 8; i++) {
+        env->gregs[i] = regs->u_regs[i];
+    }
+    for (i = 0; i < 8; i++) {
+        env->regwptr[i] = regs->u_regs[i + 8];
+    }
+}
+
+static inline void target_cpu_loop(CPUSPARCState *env)
+{
+    CPUState *cs = CPU(sparc_env_get_cpu(env));
+    int trapnr, ret, syscall_nr;
+    /* target_siginfo_t info; */
+
+    while (1) {
+        trapnr = cpu_sparc_exec(env);
+
+        switch (trapnr) {
+        case 0x80:
+            syscall_nr = env->gregs[1];
+            if (bsd_type == target_freebsd) {
+                ret = do_freebsd_syscall(env, syscall_nr,
+                                        env->regwptr[0], env->regwptr[1],
+                                        env->regwptr[2], env->regwptr[3],
+                                        env->regwptr[4], env->regwptr[5], 0, 
0);
+            } else if (bsd_type == target_netbsd) {
+                ret = do_netbsd_syscall(env, syscall_nr,
+                                        env->regwptr[0], env->regwptr[1],
+                                        env->regwptr[2], env->regwptr[3],
+                                        env->regwptr[4], env->regwptr[5]);
+            } else { /* if (bsd_type == target_openbsd) */
+                ret = do_openbsd_syscall(env, syscall_nr,
+                                         env->regwptr[0], env->regwptr[1],
+                                         env->regwptr[2], env->regwptr[3],
+                                         env->regwptr[4], env->regwptr[5]);
+            }
+            if ((unsigned int)ret >= (unsigned int)(-515)) {
+                ret = -ret;
+                env->psr |= PSR_CARRY;
+            } else {
+                env->psr &= ~PSR_CARRY;
+            }
+            env->regwptr[0] = ret;
+            /* next instruction */
+            env->pc = env->npc;
+            env->npc = env->npc + 4;
+            break;
+        case 0x83: /* flush windows */
+#ifdef TARGET_ABI32
+        case 0x103:
+#endif
+            bsd_sparc_flush_windows(env);
+            /* next instruction */
+            env->pc = env->npc;
+            env->npc = env->npc + 4;
+            break;
+
+        case TT_WIN_OVF: /* window overflow */
+            bsd_sparc_save_window(env);
+            break;
+
+        case TT_WIN_UNF: /* window underflow */
+            bsd_sparc_restore_window(env);
+            break;
+
+        case TT_TFAULT:
+        case TT_DFAULT:
+#if 0
+            {
+                info.si_signo = SIGSEGV;
+                info.si_errno = 0;
+                /* XXX: check env->error_code */
+                info.si_code = TARGET_SEGV_MAPERR;
+                info._sifields._sigfault._addr = env->mmuregs[4];
+                queue_signal(env, info.si_signo, &info);
+            }
+#endif
+            break;
+
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
+#if 0
+                if (sig) {
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TARGET_TRAP_BRKPT;
+                    /* queue_signal(env, info.si_signo, &info); */
+                }
+#endif
+            }
+            break;
+        default:
+            printf("Unhandled trap: 0x%x\n", trapnr);
+            cpu_dump_state(cs, stderr, fprintf, 0);
+            exit(1);
+        }
+        process_pending_signals(env);
+    }
+}
+
+static inline void target_cpu_clone_regs(CPUSPARCState *env, target_ulong 
newsp)
+{
+    if (newsp)
+        env->regwptr[22] = newsp;
+    env->regwptr[0] = 0;
+    /* FIXME: Do we also need to clear CF?  */
+    /* XXXXX */
+    printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
+}
+
+static inline void target_cpu_reset(CPUArchState *cpu)
+{
+    cpu_reset(ENV_GET_CPU(cpu));
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/sparc/target_arch_vmparam.h 
b/bsd-user/sparc/target_arch_vmparam.h
new file mode 100644
index 0000000..75bbeeb
--- /dev/null
+++ b/bsd-user/sparc/target_arch_vmparam.h
@@ -0,0 +1,35 @@
+#ifndef _TARGET_ARCH_VMPARAM_H_
+#define _TARGET_ARCH_VMPARAM_H_
+
+#include "cpu.h"
+
+#define TARGET_MAXTSIZ  (1*1024*1024*1024)  /* max text size */
+#define TARGET_DFLDSIZ  (128*1024*1024)     /* initial data size limit */
+#define TARGET_MAXDSIZ  (1*1024*1024*1024)  /* max data size */
+#define TARGET_DFLSSIZ  (128*1024*1024)     /* initial stack size limit */
+#define TARGET_MAXSSIZ  (1*1024*1024*1024)  /* max stack size */
+#define TARGET_SGROWSIZ (128*1024)      /* amount to grow stack */
+
+/* XXX this may not be right */
+#define TARGET_VM_MAXUSER_ADDRESS   (0xc0000000 - (512 * 1024 * 1024))
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
+
+#ifndef UREG_I6
+#define UREG_I6        6
+#endif
+#ifndef UREG_FP
+#define UREG_FP        UREG_I6
+#endif
+
+static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+{
+    return state->regwptr[UREG_FP];
+}
+
+static inline void set_second_rval(CPUSPARCState *state, abi_ulong retval2)
+{
+    state->regwptr[1] = retval2;
+}
+
+#endif /* !_TARGET_ARCH_VMPARAM_H_ */
+
diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h
index 5b2abba..181867a 100644
--- a/bsd-user/sparc/target_signal.h
+++ b/bsd-user/sparc/target_signal.h
@@ -19,9 +19,4 @@ typedef struct target_sigaltstack {
 #define UREG_FP        UREG_I6
 #endif
 
-static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
-{
-    return state->regwptr[UREG_FP];
-}
-
 #endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/sparc64/target_arch.h b/bsd-user/sparc64/target_arch.h
new file mode 100644
index 0000000..46bbcf8
--- /dev/null
+++ b/bsd-user/sparc64/target_arch.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+void bsd_sparc64_save_window(CPUSPARCState *env);
+void bsd_sparc64_restore_window(CPUSPARCState *env);
+void bsd_sparc64_flush_windows(CPUSPARCState *env);
+
+#define target_cpu_set_tls(env, newtls)
+
+#endif /* ! _TARGET_ARCH_H_ */
diff --git a/bsd-user/sparc64/target_arch_cpu.c 
b/bsd-user/sparc64/target_arch_cpu.c
new file mode 100644
index 0000000..e7bede8
--- /dev/null
+++ b/bsd-user/sparc64/target_arch_cpu.c
@@ -0,0 +1,118 @@
+/*
+ *  sparc64 cpu related code
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+
+#include "cpu.h"
+#include "qemu.h"
+
+#include "target_arch.h"
+
+#define SPARC64_STACK_BIAS 2047
+
+/* #define DEBUG_WIN */
+/* WARNING: dealing with register windows _is_ complicated. More info
+   can be found at http://www.sics.se/~psm/sparcstack.html */
+static int get_reg_index(CPUSPARCState *env, int cwp, int index)
+{
+    index = (index + cwp * 16) % (16 * env->nwindows);
+    /* wrap handling : if cwp is on the last window, then we use the
+       registers 'after' the end */
+    if (index < 8 && env->cwp == env->nwindows - 1) {
+        index += 16 * env->nwindows;
+    }
+    return index;
+}
+
+/* save the register window 'cwp1' */
+static void save_window_offset(CPUSPARCState *env, int cwp1)
+{
+    unsigned int i;
+    abi_ulong sp_ptr;
+
+    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
+    if (sp_ptr & 3) {
+        sp_ptr += SPARC64_STACK_BIAS;
+    }
+#if defined(DEBUG_WIN)
+    printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
+           sp_ptr, cwp1);
+#endif
+    for (i = 0; i < 16; i++) {
+        /* FIXME - what to do if put_user() fails? */
+        put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
+        sp_ptr += sizeof(abi_ulong);
+    }
+}
+
+void bsd_sparc64_save_window(CPUSPARCState *env)
+{
+    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
+    env->cansave++;
+    env->canrestore--;
+}
+
+void bsd_sparc64_restore_window(CPUSPARCState *env)
+{
+    unsigned int i, cwp1;
+    abi_ulong sp_ptr;
+
+    /* restore the invalid window */
+    cwp1 = cpu_cwp_inc(env, env->cwp + 1);
+    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
+    if (sp_ptr & 3) {
+        sp_ptr += SPARC64_STACK_BIAS;
+    }
+#if defined(DEBUG_WIN)
+    printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
+           sp_ptr, cwp1);
+#endif
+    for (i = 0; i < 16; i++) {
+        /* FIXME - what to do if get_user() fails? */
+        get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
+        sp_ptr += sizeof(abi_ulong);
+    }
+    env->canrestore++;
+    if (env->cleanwin < env->nwindows - 1) {
+        env->cleanwin++;
+    }
+    env->cansave--;
+}
+
+void bsd_sparc64_flush_windows(CPUSPARCState *env)
+{
+    int offset, cwp1;
+
+    offset = 1;
+    for (;;) {
+        /* if restore would invoke restore_window(), then we can stop */
+        cwp1 = cpu_cwp_inc(env, env->cwp + offset);
+        if (env->canrestore == 0) {
+            break;
+        }
+        env->cansave++;
+        env->canrestore--;
+        save_window_offset(env, cwp1);
+        offset++;
+    }
+    cwp1 = cpu_cwp_inc(env, env->cwp + 1);
+#if defined(DEBUG_WIN)
+    printf("bsd_sparc64_flush_windows: nb=%d\n", offset - 1);
+#endif
+}
+
diff --git a/bsd-user/sparc64/target_arch_cpu.h 
b/bsd-user/sparc64/target_arch_cpu.h
new file mode 100644
index 0000000..e497711
--- /dev/null
+++ b/bsd-user/sparc64/target_arch_cpu.h
@@ -0,0 +1,191 @@
+/*
+ *  sparc64 cpu init and loop
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TARGET_ARCH_CPU_H_
+#define _TARGET_ARCH_CPU_H_
+
+#include "target_arch.h"
+
+#define TARGET_DEFAULT_CPU_MODEL "TI UltraSparc II"
+
+#define TARGET_CPU_RESET(env) cpu_reset(ENV_GET_CPU(env))
+
+static inline void target_cpu_init(CPUSPARCState *env,
+        struct target_pt_regs *regs)
+{
+    int i;
+
+    env->pc = regs->pc;
+    env->npc = regs->npc;
+    env->y = regs->y;
+    for (i = 0; i < 8; i++) {
+        env->gregs[i] = regs->u_regs[i];
+    }
+    for (i = 0; i < 8; i++) {
+        env->regwptr[i] = regs->u_regs[i + 8];
+    }
+}
+
+
+static inline void target_cpu_loop(CPUSPARCState *env)
+{
+    CPUState *cs = CPU(sparc_env_get_cpu(env));
+    int trapnr, ret, syscall_nr;
+    /* target_siginfo_t info; */
+
+    while (1) {
+        trapnr = cpu_sparc_exec(env);
+
+        switch (trapnr) {
+        /* FreeBSD uses 0x141 for syscalls too */
+        case 0x141:
+            if (bsd_type != target_freebsd) {
+                goto badtrap;
+            }
+        case 0x100:
+            syscall_nr = env->gregs[1];
+            if (bsd_type == target_freebsd) {
+                ret = do_freebsd_syscall(env, syscall_nr,
+                                        env->regwptr[0], env->regwptr[1],
+                                        env->regwptr[2], env->regwptr[3],
+                                        env->regwptr[4], env->regwptr[5], 0, 
0);
+            } else if (bsd_type == target_netbsd) {
+                ret = do_netbsd_syscall(env, syscall_nr,
+                                        env->regwptr[0], env->regwptr[1],
+                                        env->regwptr[2], env->regwptr[3],
+                                        env->regwptr[4], env->regwptr[5]);
+            } else { /* if (bsd_type == target_openbsd) */
+                syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
+                                TARGET_OPENBSD_SYSCALL_G2RFLAG);
+                ret = do_openbsd_syscall(env, syscall_nr,
+                                         env->regwptr[0], env->regwptr[1],
+                                         env->regwptr[2], env->regwptr[3],
+                                         env->regwptr[4], env->regwptr[5]);
+            }
+            if ((unsigned int)ret >= (unsigned int)(-515)) {
+                ret = -ret;
+#if !defined(TARGET_ABI32)
+                env->xcc |= PSR_CARRY;
+#else
+                env->psr |= PSR_CARRY;
+#endif
+            } else {
+#if !defined(TARGET_ABI32)
+                env->xcc &= ~PSR_CARRY;
+#else
+                env->psr &= ~PSR_CARRY;
+#endif
+            }
+            env->regwptr[0] = ret;
+            /* next instruction */
+            if (bsd_type == target_openbsd &&
+                env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
+                env->pc = env->gregs[2];
+                env->npc = env->pc + 4;
+            } else if (bsd_type == target_openbsd &&
+                       env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
+                env->pc = env->gregs[7];
+                env->npc = env->pc + 4;
+            } else {
+                env->pc = env->npc;
+                env->npc = env->npc + 4;
+            }
+            break;
+
+        case 0x83: /* flush windows */
+#ifdef TARGET_ABI32
+        case 0x103:
+#endif
+            bsd_sparc64_flush_windows(env);
+            /* next instruction */
+            env->pc = env->npc;
+            env->npc = env->npc + 4;
+            break;
+
+        case TT_SPILL: /* window overflow */
+            bsd_sparc64_save_window(env);
+            break;
+
+        case TT_FILL: /* window underflow */
+            bsd_sparc64_restore_window(env);
+            break;
+
+        case TT_TFAULT:
+        case TT_DFAULT:
+#if 0
+            {
+                info.si_signo = SIGSEGV;
+                info.si_errno = 0;
+                /* XXX: check env->error_code */
+                info.si_code = TARGET_SEGV_MAPERR;
+                if (trapnr == TT_DFAULT) {
+                    info._sifields._sigfault._addr = env->dmmuregs[4];
+                } else {
+                    info._sifields._sigfault._addr = env->tsptr->tpc;
+                    /* queue_signal(env, info.si_signo, &info); */
+                }
+            }
+#endif
+            break;
+
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
+#if 0
+                if (sig) {
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TARGET_TRAP_BRKPT;
+                    /* queue_signal(env, info.si_signo, &info); */
+                }
+#endif
+            }
+            break;
+
+        default:
+badtrap:
+            printf("Unhandled trap: 0x%x\n", trapnr);
+            cpu_dump_state(cs, stderr, fprintf, 0);
+            exit(1);
+        }
+        process_pending_signals(env);
+    }
+}
+
+static inline void target_cpu_clone_regs(CPUSPARCState *env, target_ulong 
newsp)
+{
+    if (newsp)
+        env->regwptr[22] = newsp;
+    env->regwptr[0] = 0;
+    /* FIXME: Do we also need to clear CF?  */
+    /* XXXXX */
+    printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
+}
+
+static inline void target_cpu_reset(CPUArchState *cpu)
+{
+    cpu_reset(ENV_GET_CPU(cpu));
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/sparc64/target_arch_vmparam.h 
b/bsd-user/sparc64/target_arch_vmparam.h
new file mode 100644
index 0000000..2c2323b
--- /dev/null
+++ b/bsd-user/sparc64/target_arch_vmparam.h
@@ -0,0 +1,37 @@
+#ifndef _TARGET_ARCH_VMPARAM_H_
+#define _TARGET_ARCH_VMPARAM_H_
+
+#include "cpu.h"
+
+/* compare to amd64/include/vmparam.h */
+#define TARGET_MAXTSIZ  (1*1024*1024*1024)  /* max text size */
+#define TARGET_DFLDSIZ  (128*1024*1024)     /* initial data size limit */
+#define TARGET_MAXDSIZ  (1*1024*1024*1024)  /* max data size */
+#define TARGET_DFLSSIZ  (128*1024*1024)     /* initial stack size limit */
+#define TARGET_MAXSSIZ  (1*1024*1024*1024)  /* max stack size */
+#define TARGET_SGROWSIZ (128*1024)      /* amount to grow stack */
+
+/* XXX */
+#define TARGET_VM_MINUSER_ADDRESS   (0x0000000000000000UL)
+#define TARGET_VM_MAXUSER_ADDRESS   (0x000007fe00000000UL)
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
+
+#ifndef UREG_I6
+#define UREG_I6        6
+#endif
+#ifndef UREG_FP
+#define UREG_FP        UREG_I6
+#endif
+
+static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+{
+    return state->regwptr[UREG_FP];
+}
+
+static inline void set_second_rval(CPUSPARCState *state, abi_ulong retval2)
+{
+    state->regwptr[1] = retval2;
+}
+
+#endif /* !_TARGET_ARCH_VMPARAM_H_ */
+
diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h
index 5b2abba..181867a 100644
--- a/bsd-user/sparc64/target_signal.h
+++ b/bsd-user/sparc64/target_signal.h
@@ -19,9 +19,4 @@ typedef struct target_sigaltstack {
 #define UREG_FP        UREG_I6
 #endif
 
-static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
-{
-    return state->regwptr[UREG_FP];
-}
-
 #endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/x86_64/target_arch.h b/bsd-user/x86_64/target_arch.h
new file mode 100644
index 0000000..7fe81dc
--- /dev/null
+++ b/bsd-user/x86_64/target_arch.h
@@ -0,0 +1,13 @@
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+/* target_arch_cpu.c */
+void bsd_x86_64_write_dt(void *ptr, unsigned long addr, unsigned long limit,
+                int flags);
+void bsd_x86_64_set_idt(int n, unsigned int dpl);
+void bsd_x86_64_set_idt_base(uint64_t base);
+
+#define target_cpu_set_tls(env, newtls)
+
+#endif /* !_TARGET_ARCH_H_ */
diff --git a/bsd-user/x86_64/target_arch_cpu.c 
b/bsd-user/x86_64/target_arch_cpu.c
new file mode 100644
index 0000000..5cfdfca
--- /dev/null
+++ b/bsd-user/x86_64/target_arch_cpu.c
@@ -0,0 +1,79 @@
+/*
+ *  x86_64 cpu related code
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+
+#include "cpu.h"
+#include "qemu.h"
+#include "qemu/timer.h"
+
+#include "target_arch.h"
+
+static uint64_t *idt_table;
+
+/* CPUX86 core interface */
+void cpu_smm_update(CPUX86State *env)
+{
+}
+
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+    return cpu_get_real_ticks();
+}
+
+int cpu_get_pic_interrupt(CPUX86State *env)
+{
+    return -1;
+}
+
+void bsd_x86_64_write_dt(void *ptr, unsigned long addr,
+        unsigned long limit, int flags)
+{
+    unsigned int e1, e2;
+    uint32_t *p;
+    e1 = (addr << 16) | (limit & 0xffff);
+    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
+    e2 |= flags;
+    p = ptr;
+    p[0] = tswap32(e1);
+    p[1] = tswap32(e2);
+}
+
+static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
+        uint64_t addr, unsigned int sel)
+{
+    uint32_t *p, e1, e2;
+    e1 = (addr & 0xffff) | (sel << 16);
+    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
+    p = ptr;
+    p[0] = tswap32(e1);
+    p[1] = tswap32(e2);
+    p[2] = tswap32(addr >> 32);
+    p[3] = 0;
+}
+
+/* only dpl matters as we do only user space emulation */
+void bsd_x86_64_set_idt(int n, unsigned int dpl)
+{
+    set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
+}
+
+void bsd_x86_64_set_idt_base(uint64_t base)
+{
+    idt_table = g2h(base);
+}
diff --git a/bsd-user/x86_64/target_arch_cpu.h 
b/bsd-user/x86_64/target_arch_cpu.h
new file mode 100644
index 0000000..9a66b67
--- /dev/null
+++ b/bsd-user/x86_64/target_arch_cpu.h
@@ -0,0 +1,324 @@
+/*
+ *  x86_64 cpu init and loop
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TARGET_ARCH_CPU_H_
+#define _TARGET_ARCH_CPU_H_
+
+#include "target_arch.h"
+
+#define TARGET_DEFAULT_CPU_MODEL "qemu64"
+
+#define TARGET_CPU_RESET(env)
+
+static inline void target_cpu_init(CPUX86State *env,
+        struct target_pt_regs *regs)
+{
+    uint64_t *gdt_table;
+
+    cpu_x86_set_cpl(env, 3);
+
+    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
+    env->hflags |= HF_PE_MASK;
+    if (env->features[FEAT_1_EDX] & CPUID_SSE) {
+        env->cr[4] |= CR4_OSFXSR_MASK;
+        env->hflags |= HF_OSFXSR_MASK;
+    }
+
+    /* enable 64 bit mode if possible */
+    if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
+        fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
+        exit(1);
+    }
+    env->cr[4] |= CR4_PAE_MASK;
+    env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
+    env->hflags |= HF_LMA_MASK;
+
+    /* flags setup : we activate the IRQs by default as in user mode */
+    env->eflags |= IF_MASK;
+
+    /* register setup */
+    env->regs[R_EAX] = regs->rax;
+    env->regs[R_EBX] = regs->rbx;
+    env->regs[R_ECX] = regs->rcx;
+    env->regs[R_EDX] = regs->rdx;
+    env->regs[R_ESI] = regs->rsi;
+    env->regs[R_EDI] = regs->rdi;
+    env->regs[R_EBP] = regs->rbp;
+    env->regs[R_ESP] = regs->rsp;
+    env->eip = regs->rip;
+
+    /* interrupt setup */
+    env->idt.limit = 511;
+
+    env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
+        PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+    bsd_x86_64_set_idt_base(env->idt.base);
+    bsd_x86_64_set_idt(0, 0);
+    bsd_x86_64_set_idt(1, 0);
+    bsd_x86_64_set_idt(2, 0);
+    bsd_x86_64_set_idt(3, 3);
+    bsd_x86_64_set_idt(4, 3);
+    bsd_x86_64_set_idt(5, 0);
+    bsd_x86_64_set_idt(6, 0);
+    bsd_x86_64_set_idt(7, 0);
+    bsd_x86_64_set_idt(8, 0);
+    bsd_x86_64_set_idt(9, 0);
+    bsd_x86_64_set_idt(10, 0);
+    bsd_x86_64_set_idt(11, 0);
+    bsd_x86_64_set_idt(12, 0);
+    bsd_x86_64_set_idt(13, 0);
+    bsd_x86_64_set_idt(14, 0);
+    bsd_x86_64_set_idt(15, 0);
+    bsd_x86_64_set_idt(16, 0);
+    bsd_x86_64_set_idt(17, 0);
+    bsd_x86_64_set_idt(18, 0);
+    bsd_x86_64_set_idt(19, 0);
+    bsd_x86_64_set_idt(0x80, 3);
+
+    /* segment setup */
+    env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
+            PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+    env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
+    gdt_table = g2h(env->gdt.base);
+
+    /* 64 bit code segment */
+    bsd_x86_64_write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
+            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | DESC_L_MASK
+            | (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
+
+    bsd_x86_64_write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
+            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+            (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+
+    cpu_x86_load_seg(env, R_CS, __USER_CS);
+    cpu_x86_load_seg(env, R_SS, __USER_DS);
+    cpu_x86_load_seg(env, R_DS, 0);
+    cpu_x86_load_seg(env, R_ES, 0);
+    cpu_x86_load_seg(env, R_FS, 0);
+    cpu_x86_load_seg(env, R_GS, 0);
+}
+
+static inline void target_cpu_loop(CPUX86State *env)
+{
+    int trapnr;
+    abi_ulong pc;
+    /* target_siginfo_t info; */
+
+    for (;;) {
+        trapnr = cpu_x86_exec(env);
+        switch (trapnr) {
+        case 0x80:
+            /* syscall from int $0x80 */
+            if (bsd_type == target_freebsd) {
+                abi_ulong params = (abi_ulong) env->regs[R_ESP] +
+                    sizeof(int32_t);
+                int32_t syscall_nr = env->regs[R_EAX];
+                int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
+
+                if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
+                    get_user_s32(syscall_nr, params);
+                    params += sizeof(int32_t);
+                } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
+                    get_user_s32(syscall_nr, params);
+                    params += sizeof(int64_t);
+                }
+                get_user_s32(arg1, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg2, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg3, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg4, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg5, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg6, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg7, params);
+                params += sizeof(int32_t);
+                get_user_s32(arg8, params);
+                env->regs[R_EAX] = do_freebsd_syscall(env,
+                                                      syscall_nr,
+                                                      arg1,
+                                                      arg2,
+                                                      arg3,
+                                                      arg4,
+                                                      arg5,
+                                                      arg6,
+                                                      arg7,
+                                                      arg8);
+            } else { /* if (bsd_type == target_openbsd) */
+                env->regs[R_EAX] = do_openbsd_syscall(env,
+                                                      env->regs[R_EAX],
+                                                      env->regs[R_EBX],
+                                                      env->regs[R_ECX],
+                                                      env->regs[R_EDX],
+                                                      env->regs[R_ESI],
+                                                      env->regs[R_EDI],
+                                                      env->regs[R_EBP]);
+            }
+            if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
+                env->regs[R_EAX] = -env->regs[R_EAX];
+                env->eflags |= CC_C;
+            } else {
+                env->eflags &= ~CC_C;
+            }
+            break;
+
+        case EXCP_SYSCALL:
+            /* syscall from syscall instruction */
+            if (bsd_type == target_freebsd) {
+                env->regs[R_EAX] = do_freebsd_syscall(env,
+                                                      env->regs[R_EAX],
+                                                      env->regs[R_EDI],
+                                                      env->regs[R_ESI],
+                                                      env->regs[R_EDX],
+                                                      env->regs[R_ECX],
+                                                      env->regs[8],
+                                                      env->regs[9], 0, 0);
+            } else { /* if (bsd_type == target_openbsd) */
+                env->regs[R_EAX] = do_openbsd_syscall(env,
+                                                      env->regs[R_EAX],
+                                                      env->regs[R_EDI],
+                                                      env->regs[R_ESI],
+                                                      env->regs[R_EDX],
+                                                      env->regs[10],
+                                                      env->regs[8],
+                                                      env->regs[9]);
+            }
+            env->eip = env->exception_next_eip;
+            if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
+                env->regs[R_EAX] = -env->regs[R_EAX];
+                env->eflags |= CC_C;
+            } else {
+                env->eflags &= ~CC_C;
+            }
+            break;
+
+#if 0
+        case EXCP0B_NOSEG:
+        case EXCP0C_STACK:
+            info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = TARGET_SI_KERNEL;
+            info._sifields._sigfault._addr = 0;
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP0D_GPF:
+            /* XXX: potential problem if ABI32 */
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            info.si_code = TARGET_SI_KERNEL;
+            info._sifields._sigfault._addr = 0;
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP0E_PAGE:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            if (!(env->error_code & 1)) {
+                info.si_code = TARGET_SEGV_MAPERR;
+            } else {
+                info.si_code = TARGET_SEGV_ACCERR;
+            }
+            info._sifields._sigfault._addr = env->cr[2];
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP00_DIVZ:
+            /* division by zero */
+            info.si_signo = SIGFPE;
+            info.si_errno = 0;
+            info.si_code = TARGET_FPE_INTDIV;
+            info._sifields._sigfault._addr = env->eip;
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP01_DB:
+        case EXCP03_INT3:
+            info.si_signo = SIGTRAP;
+            info.si_errno = 0;
+            if (trapnr == EXCP01_DB) {
+                info.si_code = TARGET_TRAP_BRKPT;
+                info._sifields._sigfault._addr = env->eip;
+            } else {
+                info.si_code = TARGET_SI_KERNEL;
+                info._sifields._sigfault._addr = 0;
+            }
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP04_INTO:
+        case EXCP05_BOUND:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            info.si_code = TARGET_SI_KERNEL;
+            info._sifields._sigfault._addr = 0;
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP06_ILLOP:
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_ILLOPN;
+            info._sifields._sigfault._addr = env->eip;
+            queue_signal(env, info.si_signo, &info);
+            break;
+#endif
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+#if 0
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                if (sig) {
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TARGET_TRAP_BRKPT;
+                    queue_signal(env, info.si_signo, &info);
+                }
+            }
+            break;
+#endif
+        default:
+            pc = env->segs[R_CS].base + env->eip;
+            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
+                    "aborting\n", (long)pc, trapnr);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+
+static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
+{
+    if (newsp)
+        env->regs[R_ESP] = newsp;
+    env->regs[R_EAX] = 0;
+}
+
+static inline void target_cpu_reset(CPUArchState *cpu)
+{
+    cpu_reset(ENV_GET_CPU(cpu));
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/x86_64/target_arch_vmparam.h 
b/bsd-user/x86_64/target_arch_vmparam.h
new file mode 100644
index 0000000..5e13076
--- /dev/null
+++ b/bsd-user/x86_64/target_arch_vmparam.h
@@ -0,0 +1,28 @@
+#ifndef _TARGET_ARCH_VMPARAM_H_
+#define _TARGET_ARCH_VMPARAM_H_
+
+#include "cpu.h"
+
+/* compare to amd64/include/vmparam.h */
+#define TARGET_MAXTSIZ  (128UL*1024*1024)   /* max text size */
+#define TARGET_DFLDSIZ  (32768UL*1024*1024) /* initial data size limit */
+#define TARGET_MAXDSIZ  (32768UL*1024*1024) /* max data size */
+#define TARGET_DFLSSIZ  (8UL*1024*1024)     /* initial stack size limit */
+#define TARGET_MAXSSIZ  (512UL*1024*1024)   /* max stack size */
+#define TARGET_SGROWSIZ (128UL*1024)        /* amount to grow stack */
+
+#define TARGET_VM_MAXUSER_ADDRESS   (0x0000800000000000UL)
+
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
+
+static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+{
+    return state->regs[R_ESP];
+}
+
+static inline void set_second_rval(CPUX86State *state, abi_ulong retval2)
+{
+    state->regs[R_EDX] = retval2;
+}
+
+#endif /* !_TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h
index 659cd40..5491687 100644
--- a/bsd-user/x86_64/target_signal.h
+++ b/bsd-user/x86_64/target_signal.h
@@ -11,9 +11,4 @@ typedef struct target_sigaltstack {
        abi_ulong ss_size;
 } target_stack_t;
 
-static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
-{
-    return state->regs[R_ESP];
-}
-
 #endif /* TARGET_SIGNAL_H */
-- 
1.7.8




reply via email to

[Prev in Thread] Current Thread [Next in Thread]