diff mbox

[23/23] bsd-user: add arm cpu support

Message ID 1372039435-41921-24-git-send-email-sson@FreeBSD.org
State New
Headers show

Commit Message

Stacey Son June 24, 2013, 2:03 a.m. UTC
This change adds support for the arm cpu target.  In addition, it moves the
cpu dependent code out of main.c into the individual architecture directories
and cleans up main.c in general. Credit for much of this code: Olivier Houchard.

Signed-off-by: Stacey Son <sson@FreeBSD.org>
---
 bsd-user/Makefile.objs                |    2 +-
 bsd-user/arm/syscall.h                |   36 ++
 bsd-user/arm/target_arch.h            |   13 +
 bsd-user/arm/target_arch_cpu.h        |  405 +++++++++++++
 bsd-user/arm/target_arch_signal.h     |  255 ++++++++
 bsd-user/arm/target_arch_sigtramp.h   |   33 +
 bsd-user/arm/target_arch_sysarch.h    |   80 +++
 bsd-user/arm/target_arch_thread.h     |   40 ++
 bsd-user/arm/target_arch_vmparam.h    |   49 ++
 bsd-user/freebsd/host_os.h            |   46 ++
 bsd-user/i386/target_arch.h           |   11 +
 bsd-user/i386/target_arch_cpu.c       |   79 +++
 bsd-user/i386/target_arch_cpu.h       |  290 +++++++++
 bsd-user/i386/target_arch_signal.h    |    7 +
 bsd-user/main.c                       | 1062 ++-------------------------------
 bsd-user/mips/target_arch.h           |   13 +
 bsd-user/mips/target_arch_cpu.h       |  227 +++++++
 bsd-user/mips/target_arch_signal.h    |    9 +
 bsd-user/mips64/target_arch.h         |   13 +
 bsd-user/mips64/target_arch_cpu.h     |  226 +++++++
 bsd-user/mips64/target_arch_signal.h  |    9 +
 bsd-user/netbsd/host_os.h             |   31 +
 bsd-user/openbsd/host_os.h            |   31 +
 bsd-user/qemu.h                       |   11 +
 bsd-user/signal.c                     |   20 +-
 bsd-user/sparc/target_arch.h          |    9 +
 bsd-user/sparc/target_arch_cpu.c      |  113 ++++
 bsd-user/sparc/target_arch_cpu.h      |  143 +++++
 bsd-user/sparc/target_arch_signal.h   |    7 +
 bsd-user/sparc64/target_arch.h        |    9 +
 bsd-user/sparc64/target_arch_cpu.c    |  118 ++++
 bsd-user/sparc64/target_arch_cpu.h    |  175 ++++++
 bsd-user/sparc64/target_arch_signal.h |    7 +
 bsd-user/syscall.c                    |    7 +
 bsd-user/x86_64/target_arch.h         |   11 +
 bsd-user/x86_64/target_arch_cpu.c     |   79 +++
 bsd-user/x86_64/target_arch_cpu.h     |  312 ++++++++++
 bsd-user/x86_64/target_arch_signal.h  |   11 +-
 default-configs/arm-bsd-user.mak      |    3 +
 default-configs/armeb-bsd-user.mak    |    3 +
 40 files changed, 2971 insertions(+), 1034 deletions(-)
 create mode 100644 bsd-user/arm/syscall.h
 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_signal.h
 create mode 100644 bsd-user/arm/target_arch_sigtramp.h
 create mode 100644 bsd-user/arm/target_arch_sysarch.h
 create mode 100644 bsd-user/arm/target_arch_thread.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/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/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/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/touch_arch.cpu.c
 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/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/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 default-configs/arm-bsd-user.mak
 create mode 100644 default-configs/armeb-bsd-user.mak

Comments

Peter Maydell June 24, 2013, 5:18 p.m. UTC | #1
On 24 June 2013 03:03, Stacey Son <sson@freebsd.org> wrote:
> This change adds support for the arm cpu target.  In addition, it moves the
> cpu dependent code out of main.c into the individual architecture directories
> and cleans up main.c in general. Credit for much of this code: Olivier Houchard.

Rule of thumb: if your commit message says "also" or "in addition"
it's a sign it should probably be more than one patch.

>  bsd-user/Makefile.objs                |    2 +-
>  bsd-user/arm/syscall.h                |   36 ++
>  bsd-user/arm/target_arch.h            |   13 +
>  bsd-user/arm/target_arch_cpu.h        |  405 +++++++++++++
>  bsd-user/arm/target_arch_signal.h     |  255 ++++++++
>  bsd-user/arm/target_arch_sigtramp.h   |   33 +
>  bsd-user/arm/target_arch_sysarch.h    |   80 +++
>  bsd-user/arm/target_arch_thread.h     |   40 ++
>  bsd-user/arm/target_arch_vmparam.h    |   49 ++
>  bsd-user/freebsd/host_os.h            |   46 ++
>  bsd-user/i386/target_arch.h           |   11 +
>  bsd-user/i386/target_arch_cpu.c       |   79 +++
>  bsd-user/i386/target_arch_cpu.h       |  290 +++++++++
>  bsd-user/i386/target_arch_signal.h    |    7 +
>  bsd-user/main.c                       | 1062 ++-------------------------------
>  bsd-user/mips/target_arch.h           |   13 +
>  bsd-user/mips/target_arch_cpu.h       |  227 +++++++
>  bsd-user/mips/target_arch_signal.h    |    9 +
>  bsd-user/mips64/target_arch.h         |   13 +
>  bsd-user/mips64/target_arch_cpu.h     |  226 +++++++
>  bsd-user/mips64/target_arch_signal.h  |    9 +

...in particular an "add ARM support" patch shouldn't be touching
i386, mips, sparc, etc code.

thanks
-- PMM
diff mbox

Patch

diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
index 06a3026..ddc91ff 100644
--- a/bsd-user/Makefile.objs
+++ b/bsd-user/Makefile.objs
@@ -3,5 +3,5 @@  obj-y = main.o bsdload.o elfload.o ioctl.o mmap.o signal.o strace.o syscall.o \
 			$(HOST_ABI_DIR)/os-extattr.o $(HOST_ABI_DIR)/os-proc.o \
 			$(HOST_ABI_DIR)/os-socket.o $(HOST_ABI_DIR)/os-stat.o \
 			$(HOST_ABI_DIR)/os-sys.o $(HOST_ABI_DIR)/os-thread.o  \
-			$(HOST_ABI_DIR)/os-time.o
+			$(HOST_ABI_DIR)/os-time.o $(TARGET_ABI_DIR)/target_arch_cpu.o
 
diff --git a/bsd-user/arm/syscall.h b/bsd-user/arm/syscall.h
new file mode 100644
index 0000000..bc3d6e6
--- /dev/null
+++ b/bsd-user/arm/syscall.h
@@ -0,0 +1,36 @@ 
+#ifndef __ARCH_SYSCALL_H_
+#define __ARCH_SYSCALL_H_
+
+struct target_pt_regs {
+    abi_long uregs[17];
+};
+
+#define ARM_cpsr    uregs[16]
+#define ARM_pc      uregs[15]
+#define ARM_lr      uregs[14]
+#define ARM_sp      uregs[13]
+#define ARM_ip      uregs[12]
+#define ARM_fp      uregs[11]
+#define ARM_r10     uregs[10]
+#define ARM_r9      uregs[9]
+#define ARM_r8      uregs[8]
+#define ARM_r7      uregs[7]
+#define ARM_r6      uregs[6]
+#define ARM_r5      uregs[5]
+#define ARM_r4      uregs[4]
+#define ARM_r3      uregs[3]
+#define ARM_r2      uregs[2]
+#define ARM_r1      uregs[1]
+#define ARM_r0      uregs[0]
+
+#define ARM_SYSCALL_BASE    0 /* XXX: FreeBSD only */
+
+#define TARGET_FREEBSD_ARM_SYNC_ICACHE      0
+#define TARGET_FREEBSD_ARM_DRAIN_WRITEBUF   1
+#define TARGET_FREEBSD_ARM_SET_TP       2
+#define TARGET_FREEBSD_ARM_GET_TP       3
+
+#define TARGET_HW_MACHINE       "arm"
+#define TARGET_HW_MACHINE_ARCH  "armv6"
+
+#endif /* !__ARCH_SYSCALL_H_ */
diff --git a/bsd-user/arm/target_arch.h b/bsd-user/arm/target_arch.h
new file mode 100644
index 0000000..f186986
--- /dev/null
+++ b/bsd-user/arm/target_arch.h
@@ -0,0 +1,13 @@ 
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+#include "cpu.h"
+
+/* main.c */
+static inline void start_exclusive(void);
+static inline void end_exclusive(void);
+static inline void cpu_exec_start(CPUState *env);
+static inline void cpu_exec_end(CPUState *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..e69de29
diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h
new file mode 100644
index 0000000..4d1e575
--- /dev/null
+++ b/bsd-user/arm/target_arch_cpu.h
@@ -0,0 +1,405 @@ 
+/*
+ *  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, insn;
+    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? */
+                        get_user_u16(insn, env->regs[15]);
+                        n = insn & 0xff;
+                        env->regs[15] += 2;
+                    } else {
+                        /* FIXME - what to do if get_user() fails? */
+                        get_user_u32(insn, env->regs[15]);
+                        n = (insn & 0xf) | ((insn >> 4) & 0xff0);
+                        env->regs[15] += 4;
+                    }
+                } else {
+                    if (env->thumb) {
+                        /* FIXME - what to do if get_user() fails? */
+                        get_user_u16(insn, env->regs[15] - 2);
+                        n = insn & 0xff;
+                    } else {
+                        /* FIXME - what to do if get_user() fails? */
+                        get_user_u32(insn, env->regs[15] - 4);
+                        n = insn & 0xffffff;
+                    }
+                }
+
+#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(env, 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(env, stderr, fprintf, 0);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+
+#endif /* !_TARGET_ARCH_CPU_H */
diff --git a/bsd-user/arm/target_arch_signal.h b/bsd-user/arm/target_arch_signal.h
new file mode 100644
index 0000000..7f3c200
--- /dev/null
+++ b/bsd-user/arm/target_arch_signal.h
@@ -0,0 +1,255 @@ 
+/*
+ *  arm signal 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 _TARGET_ARCH_SIGNAL_H_
+#define _TARGET_ARCH_SIGNAL_H_
+
+#include "cpu.h"
+
+#define TARGET_REG_R0   0
+#define TARGET_REG_R1   1
+#define TARGET_REG_R2   2
+#define TARGET_REG_R3   3
+#define TARGET_REG_R4   4
+#define TARGET_REG_R5   5
+#define TARGET_REG_R6   6
+#define TARGET_REG_R7   7
+#define TARGET_REG_R8   8
+#define TARGET_REG_R9   9
+#define TARGET_REG_R10  10
+#define TARGET_REG_R11  11
+#define TARGET_REG_R12  12
+#define TARGET_REG_R13  13
+#define TARGET_REG_R14  14
+#define TARGET_REG_R15  15
+#define TARGET_REG_CPSR 16
+#define TARGET__NGREG   17
+/* Convenience synonyms */
+#define TARGET_REG_FP   TARGET_REG_R11
+#define TARGET_REG_SP   TARGET_REG_R13
+#define TARGET_REG_LR   TARGET_REG_R14
+#define TARGET_REG_PC   TARGET_REG_R15
+
+#define TARGET_INSN_SIZE    4       /* arm instruction size */
+
+/* Size of the signal trampolin code. See _sigtramp(). */
+#define TARGET_SZSIGCODE    ((abi_ulong)(8 * TARGET_INSN_SIZE))
+
+/* compare to arm/include/_limits.h */
+#define TARGET_MINSIGSTKSZ  (1024 * 4)                  /* min sig stack size */
+#define TARGET_SIGSTKSZ     (TARGET_MINSIGSTKSZ + 32768)  /* recommended size */
+
+/* arm/arm/machdep.c */
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+#define TARGET_MC_ADD_MAGIC     0x0002
+#define TARGET_MC_SET_ONSTACK   0x0004
+
+struct target_sigcontext {
+    target_sigset_t sc_mask;    /* signal mask to retstore */
+    int32_t     sc_onstack;     /* sigstack state to restore */
+    abi_long    sc_pc;          /* pc at time of signal */
+    abi_long    sc_reg[32];     /* processor regs 0 to 31 */
+    abi_long    mullo, mulhi;   /* mullo and mulhi registers */
+    int32_t     sc_fpused;      /* fp has been used */
+    abi_long    sc_fpregs[33];  /* fp regs 0 to 31 & csr */
+    abi_long    sc_fpc_eir;     /* fp exception instr reg */
+    /* int32_t reserved[8]; */
+};
+
+typedef struct {
+    uint32_t    __fp_fpsr;
+    struct {
+        uint32_t    __fp_exponent;
+        uint32_t    __fp_mantissa_hi;
+        uint32_t    __fp_mantissa_lo;
+    }       __fp_fr[8];
+} target__fpregset_t;
+
+typedef struct {
+    uint32_t    __vfp_fpscr;
+    uint32_t    __vfp_fstmx[33];
+    uint32_t    __vfp_fpsid;
+} target__vfpregset_t;
+
+typedef struct target_mcontext {
+    uint32_t        __gregs[TARGET__NGREG];
+    union {
+        target__fpregset_t  __fpregs;
+        target__vfpregset_t __vfpregs;
+    } __fpu;
+} target_mcontext_t;
+
+typedef struct target_ucontext {
+    target_sigset_t     uc_sigmask;
+    target_mcontext_t   uc_mcontext;
+    abi_ulong           uc_link;
+    target_stack_t      uc_stack;
+    int32_t             uc_flags;
+    int32_t             __spare__[4];
+} target_ucontext_t;
+
+struct target_sigframe {
+    target_siginfo_t    sf_si;  /* saved siginfo */
+    target_ucontext_t   sf_uc;  /* saved ucontext */
+};
+
+
+/* compare to sys/arm/include/frame.h */
+struct target_trapframe {
+    abi_ulong tf_spsr; /* Zero on arm26 */
+    abi_ulong tf_r0;
+    abi_ulong tf_r1;
+    abi_ulong tf_r2;
+    abi_ulong tf_r3;
+    abi_ulong tf_r4;
+    abi_ulong tf_r5;
+    abi_ulong tf_r6;
+    abi_ulong tf_r7;
+    abi_ulong tf_r8;
+    abi_ulong tf_r9;
+    abi_ulong tf_r10;
+    abi_ulong tf_r11;
+    abi_ulong tf_r12;
+    abi_ulong tf_usr_sp;
+    abi_ulong tf_usr_lr;
+    abi_ulong tf_svc_sp; /* Not used on arm26 */
+    abi_ulong tf_svc_lr; /* Not used on arm26 */
+    abi_ulong tf_pc;
+};
+
+/*
+ * Compare to arm/arm/machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+static inline abi_long
+set_sigtramp_args(CPUARMState *regs, int sig, struct target_sigframe *frame,
+    abi_ulong frame_addr, struct target_sigaction *ka)
+{
+    /*
+     * Arguments to signal handler:
+     *  r0 = signal number
+     *  r1 = siginfo pointer
+     *  r2 = ucontext pointer
+     *  r5 = ucontext pointer
+     *  pc = signal handler pointer
+     *  sp = sigframe struct pointer
+     *  lr = sigtramp at base of user stack
+     */
+
+    regs->regs[0] = sig;
+    regs->regs[1] = frame_addr +
+        offsetof(struct target_sigframe, sf_si);
+    regs->regs[2] = frame_addr +
+        offsetof(struct target_sigframe, sf_uc);
+
+    /* the trampoline uses r5 as the uc address */
+    regs->regs[5] = frame_addr +
+        offsetof(struct target_sigframe, sf_uc);
+    regs->regs[TARGET_REG_PC] = ka->_sa_handler;
+    regs->regs[TARGET_REG_SP] = frame_addr;
+    regs->regs[TARGET_REG_LR] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
+
+    return 0;
+}
+
+/*
+ * Compare to arm/arm/machdep.c get_mcontext()
+ * Assumes that the memory is locked if mcp points to user memory.
+ */
+static inline abi_long get_mcontext(CPUARMState *regs, target_mcontext_t *mcp,
+        int flags)
+{
+    int err = 0;
+    uint32_t *gr = mcp->__gregs;
+
+
+    if (flags & TARGET_MC_GET_CLEAR_RET) {
+        gr[TARGET_REG_R0] = 0;
+    } else {
+        gr[TARGET_REG_R0] = tswap32(regs->regs[0]);
+    }
+
+    gr[TARGET_REG_R1] = tswap32(regs->regs[1]);
+    gr[TARGET_REG_R2] = tswap32(regs->regs[2]);
+    gr[TARGET_REG_R3] = tswap32(regs->regs[3]);
+    gr[TARGET_REG_R4] = tswap32(regs->regs[4]);
+    gr[TARGET_REG_R5] = tswap32(regs->regs[5]);
+    gr[TARGET_REG_R6] = tswap32(regs->regs[6]);
+    gr[TARGET_REG_R7] = tswap32(regs->regs[7]);
+    gr[TARGET_REG_R8] = tswap32(regs->regs[8]);
+    gr[TARGET_REG_R9] = tswap32(regs->regs[9]);
+    gr[TARGET_REG_R10] = tswap32(regs->regs[10]);
+    gr[TARGET_REG_R11] = tswap32(regs->regs[11]);
+    gr[TARGET_REG_R12] = tswap32(regs->regs[12]);
+
+    gr[TARGET_REG_SP] = tswap32(regs->regs[13]);
+    gr[TARGET_REG_LR] = tswap32(regs->regs[14]);
+    gr[TARGET_REG_PC] = tswap32(regs->regs[15]);
+    gr[TARGET_REG_CPSR] = tswap32(cpsr_read(regs));
+
+    return err;
+}
+
+/* Compare to arm/arm/machdep.c set_mcontext() */
+static inline abi_long set_mcontext(CPUARMState *regs, target_mcontext_t *mcp,
+        int srflag)
+{
+    int err = 0;
+    const uint32_t *gr = mcp->__gregs;
+    uint32_t cpsr;
+
+    regs->regs[0] = tswap32(gr[TARGET_REG_R0]);
+    regs->regs[1] = tswap32(gr[TARGET_REG_R1]);
+    regs->regs[2] = tswap32(gr[TARGET_REG_R2]);
+    regs->regs[3] = tswap32(gr[TARGET_REG_R3]);
+    regs->regs[4] = tswap32(gr[TARGET_REG_R4]);
+    regs->regs[5] = tswap32(gr[TARGET_REG_R5]);
+    regs->regs[6] = tswap32(gr[TARGET_REG_R6]);
+    regs->regs[7] = tswap32(gr[TARGET_REG_R7]);
+    regs->regs[8] = tswap32(gr[TARGET_REG_R8]);
+    regs->regs[9] = tswap32(gr[TARGET_REG_R9]);
+    regs->regs[10] = tswap32(gr[TARGET_REG_R10]);
+    regs->regs[11] = tswap32(gr[TARGET_REG_R11]);
+    regs->regs[12] = tswap32(gr[TARGET_REG_R12]);
+
+    regs->regs[13] = tswap32(gr[TARGET_REG_SP]);
+    regs->regs[14] = tswap32(gr[TARGET_REG_LR]);
+    regs->regs[15] = tswap32(gr[TARGET_REG_PC]);
+    cpsr = tswap32(gr[TARGET_REG_CPSR]);
+    cpsr_write(regs, cpsr, CPSR_USER | CPSR_EXEC);
+
+    return err;
+}
+
+/* Compare to arm/arm/machdep.c sys_sigreturn() */
+static inline abi_long get_ucontext_sigreturn(CPUARMState *regs,
+        abi_ulong target_sf, abi_ulong *target_uc)
+{
+    uint32_t cpsr = cpsr_read(regs);
+
+    if ((cpsr & CPSR_M) != ARM_CPU_MODE_USR ||
+            (cpsr & (CPSR_I | CPSR_F)) != 0) {
+        return -TARGET_EINVAL;
+    }
+
+    *target_uc = target_sf + offsetof(struct target_sigframe, sf_uc);
+
+    return 0;
+}
+
+
+#endif /* !_TARGET_ARCH_SIGNAL_H_ */
diff --git a/bsd-user/arm/target_arch_sigtramp.h b/bsd-user/arm/target_arch_sigtramp.h
new file mode 100644
index 0000000..98dc313
--- /dev/null
+++ b/bsd-user/arm/target_arch_sigtramp.h
@@ -0,0 +1,33 @@ 
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+/* Compare to arm/arm/locore.S ENTRY_NP(sigcode) */
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+        unsigned sys_sigreturn)
+{
+    int i;
+    uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
+    /*
+     * The code has to load r7 manually rather than using
+     * "ldr r7, =SYS_return to make sure the size of the
+     * code is correct.
+     */
+    uint32_t sigtramp_code[] = {
+    /* 1 */ 0xE1A0000D,         /* mov r0, sp */
+    /* 2 */ 0xE59F700C,         /* ldr r7, [pc, #12] */
+    /* 3 */ 0xEF000000 + sys_sigreturn, /* swi (SYS_sigreturn) */
+    /* 4 */ 0xE59F7008,         /* ldr r7, [pc, #8] */
+    /* 5 */ 0xEF000000 + sys_exit,      /* swi (SYS_exit)*/
+    /* 6 */ 0xEAFFFFFA,         /* b . -16 */
+    /* 7 */ sys_sigreturn,
+    /* 8 */ sys_exit
+    };
+
+    for (i = 0; i < 8; i++) {
+        tswap32s(&sigtramp_code[i]);
+    }
+
+    return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/arm/target_arch_sysarch.h b/bsd-user/arm/target_arch_sysarch.h
new file mode 100644
index 0000000..e22e7a9
--- /dev/null
+++ b/bsd-user/arm/target_arch_sysarch.h
@@ -0,0 +1,80 @@ 
+/*
+ *  arm sysarch() system call emulation
+ *
+ *  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 __ARCH_SYSARCH_H_
+#define __ARCH_SYSARCH_H_
+
+#include "syscall.h"
+
+static inline abi_long do_freebsd_arch_sysarch(CPUARMState *env, int op,
+        abi_ulong parms)
+{
+    int ret = 0;
+
+    switch (op) {
+    case TARGET_FREEBSD_ARM_SYNC_ICACHE:
+    case TARGET_FREEBSD_ARM_DRAIN_WRITEBUF:
+        break;
+
+    case TARGET_FREEBSD_ARM_SET_TP:
+        cpu_set_tls(env, parms);
+        break;
+
+    case TARGET_FREEBSD_ARM_GET_TP:
+        /* XXX Need a cpu_get_tls() */
+        if (put_user(env->cp15.c13_tls2, parms, abi_ulong)) {
+            ret = -TARGET_EFAULT;
+        }
+        break;
+
+    default:
+        ret = -TARGET_EINVAL;
+        break;
+    }
+    return ret;
+}
+
+static inline void do_freebsd_arch_print_sysarch(
+        const struct syscallname *name, abi_long arg1, abi_long arg2,
+        abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
+{
+
+    switch (arg1) {
+    case TARGET_FREEBSD_ARM_SYNC_ICACHE:
+        gemu_log("%s(ARM_SYNC_ICACHE, ...)", name->name);
+        break;
+
+    case TARGET_FREEBSD_ARM_DRAIN_WRITEBUF:
+        gemu_log("%s(ARM_DRAIN_WRITEBUF, ...)", name->name);
+        break;
+
+    case TARGET_FREEBSD_ARM_SET_TP:
+        gemu_log("%s(ARM_SET_TP, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2);
+        break;
+
+    case TARGET_FREEBSD_ARM_GET_TP:
+        gemu_log("%s(ARM_GET_TP, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2);
+        break;
+
+    default:
+        gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")", (int)arg1, arg2);
+    }
+}
+
+#endif /*!__ARCH_SYSARCH_H_ */
diff --git a/bsd-user/arm/target_arch_thread.h b/bsd-user/arm/target_arch_thread.h
new file mode 100644
index 0000000..7090cd5
--- /dev/null
+++ b/bsd-user/arm/target_arch_thread.h
@@ -0,0 +1,40 @@ 
+/*
+ *  arm thread support
+ *
+ *  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_THREAD_H_
+#define _TARGET_ARCH_THREAD_H_
+
+/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */
+static inline void
+thread_set_upcall(CPUARMState *regs, abi_ulong entry,
+    abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
+{
+    abi_ulong sp;
+
+    sp = ((stack_base + stack_size) & (8 - 1)) -
+        sizeof(struct target_trapframe);
+
+    /* fp = sp = stack base */
+    regs->regs[11] = regs->regs[13] = sp;
+    /* pc = start function entry */
+    regs->regs[15] = regs->regs[14] = entry & 0xfffffffe;
+    /* r0 = arg */
+    regs->regs[0] = arg;
+}
+
+#endif /* !_TARGET_ARCH_THREAD_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/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/i386/target_arch.h b/bsd-user/i386/target_arch.h
new file mode 100644
index 0000000..5f14ee7
--- /dev/null
+++ b/bsd-user/i386/target_arch.h
@@ -0,0 +1,11 @@ 
+
+#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);
+
+#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..2b77ab1
--- /dev/null
+++ b/bsd-user/i386/target_arch_cpu.h
@@ -0,0 +1,290 @@ 
+/*
+ *  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);
+    }
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h
index 7fd1399..d4f219e 100644
--- a/bsd-user/i386/target_arch_signal.h
+++ b/bsd-user/i386/target_arch_signal.h
@@ -71,4 +71,11 @@  static inline abi_long set_mcontext(CPUX86State *regs,
     return -TARGET_EOPNOTSUPP;
 }
 
+static inline abi_long get_ucontext_sigreturn(CPUX86State *regs,
+                        abi_ulong target_sf, abi_ulong *target_uc)
+{
+    /* XXX */
+    return -TARGET_EOPNOTSUPP;
+}
+
 #endif /* TARGET_ARCH_SIGNAL_H */
diff --git a/bsd-user/main.c b/bsd-user/main.c
index bcfc7ce..23dd4a1 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -1,5 +1,5 @@ 
-/**
- *  qemu user main
+/*
+ *  qemu bsd user main
  *
  *  Copyright (c) 2003-2008 Fabrice Bellard
  *  Copyright (c) 2013 Stacey Son
@@ -27,7 +27,6 @@ 
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/mman.h>
-#include <sys/sysctl.h>
 
 #include "qemu.h"
 #include "qemu-common.h"
@@ -36,6 +35,9 @@ 
 #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;
@@ -56,47 +58,7 @@  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 */
 
-#ifdef __FreeBSD__
-char qemu_proc_pathname[PATH_MAX];
-
-static void save_proc_pathname(void)
-{
-    int mib[4];
-    size_t len;
-
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_PROC;
-    mib[2] = KERN_PROC_PATHNAME;
-    mib[3] = -1;
-
-    len = sizeof(qemu_proc_pathname);
-    if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
-        perror("sysctl");
-    }
-}
-
-#else
-
-static void save_prov_pathname(void)
-{
-}
-#endif /* !__FreeBSD__ */
-
-void gemu_log(const char *fmt, ...)
-{
-    va_list ap;
-
-    va_start(ap, fmt);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
-}
-
-#if defined(TARGET_I386)
-int cpu_get_pic_interrupt(CPUX86State *env)
-{
-    return -1;
-}
-#endif
+char qemu_proc_pathname[PATH_MAX];  /* full path to exeutable */
 
 #if defined(CONFIG_USE_NPTL)
 /* Helper routines for implementing atomic operations. */
@@ -148,8 +110,7 @@  void fork_end(int child)
  * Wait for pending exclusive operations to complete.  The exclusive lock
  * must be held.
  */
-static inline void
-exclusive_idle(void)
+static inline void exclusive_idle(void)
 {
     while (pending_cpus) {
         pthread_cond_wait(&exclusive_resume, &exclusive_lock);
@@ -157,8 +118,7 @@  exclusive_idle(void)
 }
 
 /* Start an exclusive operation.  Must only be called outside of cpu_exec. */
-static inline void
-start_exclusive(void)
+static inline void start_exclusive(void)
 {
     CPUArchState *other;
     CPUState *other_cpu;
@@ -181,8 +141,7 @@  start_exclusive(void)
 }
 
 /* Finish an exclusive operation. */
-static inline void
-end_exclusive(void)
+static inline void end_exclusive(void)
 {
     pending_cpus = 0;
     pthread_cond_broadcast(&exclusive_resume);
@@ -190,8 +149,7 @@  end_exclusive(void)
 }
 
 /* Wait for exclusive ops to finish, and begin cpu execution. */
-static inline void
-cpu_exec_start(CPUState *env)
+static inline void cpu_exec_start(CPUState *env)
 {
     pthread_mutex_lock(&exclusive_lock);
     exclusive_idle();
@@ -200,8 +158,7 @@  cpu_exec_start(CPUState *env)
 }
 
 /* Mark cpu as not excuting, and release pending exclusive ops. */
-static inline void
-cpu_exec_end(CPUState *env)
+static inline void cpu_exec_end(CPUState *env)
 {
     pthread_mutex_lock(&exclusive_lock);
     env->running = 0;
@@ -215,14 +172,12 @@  cpu_exec_end(CPUState *env)
     pthread_mutex_unlock(&exclusive_lock);
 }
 
-void
-cpu_list_lock(void)
+void cpu_list_lock(void)
 {
     pthread_mutex_lock(&cpu_list_mutex);
 }
 
-void
-cpu_list_unlock(void)
+void cpu_list_unlock(void)
 {
     pthread_mutex_unlock(&cpu_list_mutex);
 }
@@ -230,830 +185,53 @@  cpu_list_unlock(void)
 #else /* ! CONFIG_USE_NPTL */
 
 /* These are no-ops because we are not threadsafe.  */
-void
-fork_start(void)
+void fork_start(void)
 {
 }
 
-void
-fork_end(int child)
+void fork_end(int child)
 {
     if (child) {
         gdbserver_fork(thread_env);
     }
 }
 
-static inline void
-exclusive_idle(void)
+static inline void exclusive_idle(void)
 {
 }
 
-static inline void
-start_exclusive(void)
+static inline void start_exclusive(void)
 {
 }
 
-static inline void
-end_exclusive(void)
+static inline void end_exclusive(void)
 {
 }
 
-static inline void
-cpu_exec_start(CPUState *env)
+static inline void cpu_exec_start(CPUState *env)
 {
 }
 
 
-static inline void
-cpu_exec_end(CPUState *env)
+static inline void cpu_exec_end(CPUState *env)
 {
 }
 
-void
-cpu_list_lock(void)
+void cpu_list_lock(void)
 {
 }
 
-void
-cpu_list_unlock(void)
+void cpu_list_unlock(void)
 {
 }
 #endif /* ! CONFIG_USE_NPTL */
 
-#ifdef TARGET_I386
-/***********************************************************/
-/* CPUX86 core interface */
-
-void cpu_smm_update(CPUX86State *env)
-{
-}
-
-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)
-{
-    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)
-{
-    set_gate(idt_table + n, 0, dpl, 0, 0);
-}
-#endif
-
-void 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;
-#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
-
-#if defined(TARGET_MIPS)
-
-/* Compare to sys/mips/mips/trap.c */
-
-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;
-}
-
-void 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 */
-            syscall_num = env->active_tc.gpr[2]; /* v0 */
-            env->active_tc.PC += TARGET_INSN_SIZE;
-            if (syscall_num >= SYS_MAXSYSCALL) {
-                ret = -TARGET_ENOSYS;
-            } else {
-                if (SYS_syscall == syscall_num ||
-                    SYS___syscall == syscall_num) {
-#if defined(TARGET_MIPS64)
-                    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 {
-                    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]
-                        );
-
-#else /* ! TARGET_MIPS64 */
-                    /* 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 */
-                        );
-#endif /* ! TARGET_MIPS64 */
-                }
-            }
-
-            /* 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 */
-            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(env, 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(env, stderr, fprintf, 0);
-            abort();
-        }
-        process_pending_signals(env);
-    }
-}
-#endif /* TARGET_MIPS */
-
-#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)
-{
-    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)
+void cpu_loop(CPUArchState *env)
 {
-    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
+    target_cpu_loop(env);
 }
 
-static void restore_window(CPUSPARCState *env)
-{
-#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)
-{
-    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)
-{
-    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 (env, 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(env, stderr, fprintf, 0);
-            exit (1);
-        }
-        process_pending_signals (env);
-    }
-}
-
-#endif
-
 static void usage(void)
 {
     printf("qemu-" TARGET_NAME " version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
@@ -1122,6 +300,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;
@@ -1138,16 +325,12 @@  int main(int argc, char **argv)
     int gdbstub_port = 0;
     char **target_environ, **wrk;
     envlist_t *envlist = NULL;
-#ifdef __FreeBSD__
-    bsd_type = target_freebsd;
-#else
-    bsd_type = target_openbsd;
-#endif
+    bsd_type = HOST_DEFAULT_BSD_TYPE;
 
     if (argc <= 1)
         usage();
 
-    save_proc_pathname();
+    save_proc_pathname(argv[0]);
 
     module_call_init(MODULE_INIT_QOM);
 
@@ -1295,27 +478,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_MIPS)
-#if defined(TARGET_MIPS) || defined(TARGET_MIPS64)
-        cpu_model = "20Kc";
-#else
-        cpu_model = "24Kf";
-#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();
@@ -1326,9 +489,7 @@  int main(int argc, char **argv)
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_reset(ENV_GET_CPU(env));
-#endif
+    TARGET_CPU_RESET(env);
     thread_env = env;
 
     if (getenv("QEMU_STRACE")) {
@@ -1415,154 +576,7 @@  int main(int argc, char **argv)
     ts->bprm = &bprm;
     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_MIPS)
-    {
-        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;
-        }
-#if defined(TARGET_MIPS64)
-        env->hflags |= MIPS_HFLAG_UX | MIPS_HFLAG_64;
-#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..f186986
--- /dev/null
+++ b/bsd-user/mips/target_arch.h
@@ -0,0 +1,13 @@ 
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+#include "cpu.h"
+
+/* main.c */
+static inline void start_exclusive(void);
+static inline void end_exclusive(void);
+static inline void cpu_exec_start(CPUState *env);
+static inline void cpu_exec_end(CPUState *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..e69de29
diff --git a/bsd-user/mips/target_arch_cpu.h b/bsd-user/mips/target_arch_cpu.h
new file mode 100644
index 0000000..11f25a3
--- /dev/null
+++ b/bsd-user/mips/target_arch_cpu.h
@@ -0,0 +1,227 @@ 
+/*
+ *  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 */
+            syscall_num = env->active_tc.gpr[2]; /* v0 */
+            env->active_tc.PC += TARGET_INSN_SIZE;
+            if (syscall_num >= SYS_MAXSYSCALL) {
+                ret = -TARGET_ENOSYS;
+            } else {
+                /* mips(32) uses regs 4-7,12-15 for args */
+                if (SYS_syscall == syscall_num ||
+                    SYS___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 */
+            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(env, 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(env, stderr, fprintf, 0);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/mips/target_arch_signal.h b/bsd-user/mips/target_arch_signal.h
index 6be34c6..8d20e85 100644
--- a/bsd-user/mips/target_arch_signal.h
+++ b/bsd-user/mips/target_arch_signal.h
@@ -225,4 +225,13 @@  static inline abi_long set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp,
     return err;
 }
 
+static inline abi_long get_ucontext_sigreturn(CPUMIPSState *regs,
+                abi_ulong target_sf, abi_ulong *target_uc)
+{
+
+    *target_uc = target_sf;
+    return 0;
+}
+
+
 #endif /* !_TARGET_ARCH_SIGNAL_H_ */
diff --git a/bsd-user/mips64/target_arch.h b/bsd-user/mips64/target_arch.h
new file mode 100644
index 0000000..f186986
--- /dev/null
+++ b/bsd-user/mips64/target_arch.h
@@ -0,0 +1,13 @@ 
+
+#ifndef _TARGET_ARCH_H_
+#define _TARGET_ARCH_H_
+
+#include "cpu.h"
+
+/* main.c */
+static inline void start_exclusive(void);
+static inline void end_exclusive(void);
+static inline void cpu_exec_start(CPUState *env);
+static inline void cpu_exec_end(CPUState *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..e69de29
diff --git a/bsd-user/mips64/target_arch_cpu.h b/bsd-user/mips64/target_arch_cpu.h
new file mode 100644
index 0000000..31d8c95
--- /dev/null
+++ b/bsd-user/mips64/target_arch_cpu.h
@@ -0,0 +1,226 @@ 
+/*
+ *  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 */
+            syscall_num = env->active_tc.gpr[2]; /* v0 */
+            env->active_tc.PC += TARGET_INSN_SIZE;
+            if (syscall_num >= SYS_MAXSYSCALL) {
+                ret = -TARGET_ENOSYS;
+            } else {
+                /* mips64 uses regs 4-11 for args */
+                if (SYS_syscall == syscall_num ||
+                    SYS___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 */
+            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(env, 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(env, stderr, fprintf, 0);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/mips64/target_arch_signal.h b/bsd-user/mips64/target_arch_signal.h
index ab84e0f..7f531c8 100644
--- a/bsd-user/mips64/target_arch_signal.h
+++ b/bsd-user/mips64/target_arch_signal.h
@@ -224,4 +224,13 @@  static inline abi_long set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp,
     return err;
 }
 
+static inline abi_long get_ucontext_sigreturn(CPUMIPSState *regs,
+                        abi_ulong target_sf, abi_ulong *target_uc)
+{
+
+    /* mips passes ucontext struct as the stack frame */
+    *target_uc = target_sf;
+    return 0;
+}
+
 #endif /* !_TARGET_ARCH_SIGNAL_H_ */
diff --git a/bsd-user/mips64/touch_arch.cpu.c b/bsd-user/mips64/touch_arch.cpu.c
new file mode 100644
index 0000000..e69de29
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 3967e22..edc21d8 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -68,6 +68,8 @@  struct image_info {
     abi_ulong entry;
     abi_ulong code_offset;
     abi_ulong data_offset;
+    abi_ulong arg_start;
+    abi_ulong arg_end;
     int       personality;
 };
 
@@ -90,6 +92,15 @@  struct emulated_sigtable {
 typedef struct TaskState {
     struct TaskState *next;
     int used; /* non zero if used */
+#ifdef TARGET_ARM
+    int swi_errno;
+#endif
+#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
+    /* Extra fields for semihosted binaries. */
+    uint32_t heap_base;
+    uint32_t heap_limit;
+    uint32_t stack_base;
+#endif
     struct image_info *info;
     struct bsd_binprm *bprm;
 
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index 4ee97af..b1c6743 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -748,11 +748,17 @@  static int reset_signal_mask(target_ucontext_t *ucontext)
 
 long do_sigreturn(CPUArchState *regs, abi_ulong addr)
 {
-    target_ucontext_t *ucontext;
+    long ret;
+    abi_ulong target_ucontext;
+    target_ucontext_t *ucontext = NULL;
 
-    /* Lock the memory and get the ucontext ptr from the stack frame */
-    if (!lock_user_struct(VERIFY_READ, ucontext,  addr, 0)) {
-            goto badframe;
+    /* Get the target ucontext address from the stack frame */
+    ret = get_ucontext_sigreturn(regs, addr, &target_ucontext);
+    if (is_error(ret)) {
+        return ret;
+    }
+    if (!lock_user_struct(VERIFY_READ, ucontext, target_ucontext, 0)) {
+        goto badframe;
     }
 
     /* Set the register state back to before the signal. */
@@ -765,12 +771,12 @@  long do_sigreturn(CPUArchState *regs, abi_ulong addr)
         goto badframe;
     }
 
-    unlock_user_struct(ucontext, addr, 0);
+    unlock_user_struct(ucontext, target_ucontext, 0);
     return -TARGET_EJUSTRETURN;
 
 badframe:
-    if (addr != 0) {
-        unlock_user_struct(ucontext, addr, 0);
+    if (ucontext != NULL) {
+        unlock_user_struct(ucontext, target_ucontext, 0);
     }
     force_sig(TARGET_SIGSEGV);
     return -TARGET_EFAULT;
diff --git a/bsd-user/sparc/target_arch.h b/bsd-user/sparc/target_arch.h
new file mode 100644
index 0000000..878bbc4
--- /dev/null
+++ b/bsd-user/sparc/target_arch.h
@@ -0,0 +1,9 @@ 
+
+#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);
+
+#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..d387f72
--- /dev/null
+++ b/bsd-user/sparc/target_arch_cpu.h
@@ -0,0 +1,143 @@ 
+/*
+ *  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)
+{
+    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(env, 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(env, stderr, fprintf, 0);
+            exit(1);
+        }
+        process_pending_signals(env);
+    }
+}
+
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/sparc/target_arch_signal.h b/bsd-user/sparc/target_arch_signal.h
index 70b89b9..5c54c78 100644
--- a/bsd-user/sparc/target_arch_signal.h
+++ b/bsd-user/sparc/target_arch_signal.h
@@ -54,4 +54,11 @@  static inline abi_long set_mcontext(CPUSPARCState *regs,
     return -TARGET_EOPNOTSUPP;
 }
 
+static inline abi_long get_ucontext_sigreturn(CPUSPARCState *regs,
+        abi_ulong target_sf, abi_ulong *target_uc)
+{
+    /* XXX */
+    return -TARGET_EOPNOTSUPP;
+}
+
 #endif /* TARGET_ARCH_SIGNAL_H */
diff --git a/bsd-user/sparc64/target_arch.h b/bsd-user/sparc64/target_arch.h
new file mode 100644
index 0000000..06021ec
--- /dev/null
+++ b/bsd-user/sparc64/target_arch.h
@@ -0,0 +1,9 @@ 
+
+#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);
+
+#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..72c8af4
--- /dev/null
+++ b/bsd-user/sparc64/target_arch_cpu.h
@@ -0,0 +1,175 @@ 
+/*
+ *  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)
+{
+    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(env, 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(env, stderr, fprintf, 0);
+            exit(1);
+        }
+        process_pending_signals(env);
+    }
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/sparc64/target_arch_signal.h b/bsd-user/sparc64/target_arch_signal.h
index cc075ed..4204807 100644
--- a/bsd-user/sparc64/target_arch_signal.h
+++ b/bsd-user/sparc64/target_arch_signal.h
@@ -71,4 +71,11 @@  static inline abi_long set_mcontext(CPUSPARCState *regs,
     return -TARGET_EOPNOTSUPP;
 }
 
+static inline abi_long get_ucontext_sigreturn(CPUSPARCState *regs,
+        abi_ulong target_sf, abi_ulong *target_uc)
+{
+    /* XXX */
+    return -TARGET_EOPNOTSUPP;
+}
+
 #endif /* !_TARGET_ARCH_SIGNAL_H_ */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 0e639fe..84c3c63 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -134,6 +134,13 @@  static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
     return 0;
 }
 
+
+/* stub for arm semihosting support */
+abi_long do_brk(abi_ulong new_brk)
+{
+    return do_obreak(new_brk);
+}
+
 /* do_syscall() should always have a single exit point at the end so
    that actions, such as logging of syscall results, can be performed.
    All errnos that do_syscall() returns must be -TARGET_<errcode>. */
diff --git a/bsd-user/x86_64/target_arch.h b/bsd-user/x86_64/target_arch.h
new file mode 100644
index 0000000..a200af5
--- /dev/null
+++ b/bsd-user/x86_64/target_arch.h
@@ -0,0 +1,11 @@ 
+
+#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);
+
+#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..e39aecf
--- /dev/null
+++ b/bsd-user/x86_64/target_arch_cpu.h
@@ -0,0 +1,312 @@ 
+/*
+ *  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);
+    }
+}
+
+#endif /* ! _TARGET_ARCH_CPU_H_ */
diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h
index 7525a56..9752684 100644
--- a/bsd-user/x86_64/target_arch_signal.h
+++ b/bsd-user/x86_64/target_arch_signal.h
@@ -59,8 +59,8 @@  struct target_sigframe {
 static inline abi_long get_mcontext(CPUX86State *regs,
                 target_mcontext_t *mcp, int flags)
 {
-        /* XXX */
-        return -TARGET_EOPNOTSUPP;
+    /* XXX */
+    return -TARGET_EOPNOTSUPP;
 }
 
 /* Compare to amd64/amd64/machdep.c set_mcontext() */
@@ -71,4 +71,11 @@  static inline abi_long set_mcontext(CPUX86State *regs,
     return -TARGET_EOPNOTSUPP;
 }
 
+static inline abi_long get_ucontext_sigreturn(CPUX86State *regs,
+        abi_ulong target_sf, abi_ulong *target_uc)
+{
+    /* XXX */
+    return -TARGET_EOPNOTSUPP;
+}
+
 #endif /* !TARGET_ARCH_SIGNAL_H_ */
diff --git a/default-configs/arm-bsd-user.mak b/default-configs/arm-bsd-user.mak
new file mode 100644
index 0000000..46d4aa2
--- /dev/null
+++ b/default-configs/arm-bsd-user.mak
@@ -0,0 +1,3 @@ 
+# Default configuration for arm-linux-user
+
+CONFIG_GDBSTUB_XML=y
diff --git a/default-configs/armeb-bsd-user.mak b/default-configs/armeb-bsd-user.mak
new file mode 100644
index 0000000..46d4aa2
--- /dev/null
+++ b/default-configs/armeb-bsd-user.mak
@@ -0,0 +1,3 @@ 
+# Default configuration for arm-linux-user
+
+CONFIG_GDBSTUB_XML=y