diff --git a/linux-user/signal.c b/linux-user/signal.c
index ded12ca..fc570cc 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -587,7 +587,11 @@ int do_sigaction(int sig, const struct target_sigaction *act,
 #endif
     if (oact) {
         oact->_sa_handler = tswapal(k->_sa_handler);
-        oact->sa_flags = tswapal(k->sa_flags);
+#if defined(TARGET_MIPS)
+        oact->sa_flags = bswap32(k->sa_flags);
+#else
+        oact->sa_flags = tswapal(act->sa_flags);
+#endif
 #if !defined(TARGET_MIPS)
         oact->sa_restorer = tswapal(k->sa_restorer);
 #endif
@@ -596,7 +600,11 @@ int do_sigaction(int sig, const struct target_sigaction *act,
     if (act) {
         /* FIXME: This is not threadsafe.  */
         k->_sa_handler = tswapal(act->_sa_handler);
+#if defined(TARGET_MIPS)
+        k->sa_flags = bswap32(act->sa_flags);
+#else
         k->sa_flags = tswapal(act->sa_flags);
+#endif
 #if !defined(TARGET_MIPS)
         k->sa_restorer = tswapal(act->sa_restorer);
 #endif
@@ -2414,35 +2422,6 @@ void sparc64_get_context(CPUSPARCState *env)
     force_sig(TARGET_SIGSEGV);
 }
 #endif
-#elif defined(TARGET_ABI_MIPSN64)
-
-# warning signal handling not implemented
-
-static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
-{
-    fprintf(stderr, "setup_frame: not implemented\n");
-}
-
-static void setup_rt_frame(int sig, struct target_sigaction *ka,
-                           target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
-{
-    fprintf(stderr, "setup_rt_frame: not implemented\n");
-}
-
-long do_sigreturn(CPUState *env)
-{
-    fprintf(stderr, "do_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
-}
-
-long do_rt_sigreturn(CPUState *env)
-{
-    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
-}
-
 #elif defined(TARGET_ABI_MIPSN32)
 
 # warning signal handling not implemented
@@ -2472,7 +2451,9 @@ long do_rt_sigreturn(CPUState *env)
     return -TARGET_ENOSYS;
 }
 
-#elif defined(TARGET_ABI_MIPSO32)
+#elif defined(TARGET_MIPS)
+
+#if defined(TARGET_ABI_MIPSO32)
 
 struct target_sigcontext {
     uint32_t   sc_regmask;     /* Unused */
@@ -2496,6 +2477,136 @@ struct target_sigcontext {
     target_ulong   sc_lo3;
 };
 
+/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
+static void setup_frame(int sig, struct target_sigaction *ka,
+                        target_sigset_t *set, CPUState *regs)
+{
+    struct sigframe *frame;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+        goto give_sigsegv;
+
+    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
+
+    if (setup_sigcontext(regs, &frame->sf_sc))
+        goto give_sigsegv;
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        if (__put_user(set->sig[i], &frame->sf_mask.sig[i]))
+            goto give_sigsegv;
+    }
+
+    /*
+    * Arguments to signal handler:
+    *
+    *   a0 = signal number
+    *   a1 = 0 (should be cause)
+    *   a2 = pointer to struct sigcontext
+    *
+    * $25 and PC point to the signal handler, $29 points to the
+    * struct sigframe.
+    */
+    regs->active_tc.gpr[4] = sig;
+    regs->active_tc.gpr[5] = 0;
+    regs->active_tc.gpr[6] = frame_addr + offsetof(struct sigframe, sf_sc);
+    regs->active_tc.gpr[29] = frame_addr;
+    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
+    /* The original kernel code sets CP0_EPC to the handler
+    * since it returns to userland using eret
+    * we cannot do this here, and we must set PC directly */
+    regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+
+give_sigsegv:
+    unlock_user_struct(frame, frame_addr, 1);
+    force_sig(TARGET_SIGSEGV/*, current*/);
+    return;
+}
+
+long do_sigreturn(CPUState *regs)
+{
+    struct sigframe *frame;
+    abi_ulong frame_addr;
+    sigset_t blocked;
+    target_sigset_t target_set;
+    int i;
+
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "do_sigreturn\n");
+#endif
+    frame_addr = regs->active_tc.gpr[29];
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
+        goto badframe;
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        if (__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
+            goto badframe;
+    }
+
+    target_to_host_sigset_internal(&blocked, &target_set);
+    sigprocmask(SIG_SETMASK, &blocked, NULL);
+
+    if (restore_sigcontext(regs, &frame->sf_sc))
+        goto badframe;
+
+#if 0
+    /*
+     * Don't let your children do this ...
+     */
+    __asm__ __volatile__(
+    "move\t$29, %0\n\t"
+    "j\tsyscall_exit"
+    :/* no outputs */
+    : "r" (&regs));
+    /* Unreached */
+#endif
+
+    regs->active_tc.PC = regs->CP0_EPC;
+    /* I am not sure this is right, but it seems to work
+    * maybe a problem with nested signals ? */
+    regs->CP0_EPC = 0;
+    return -TARGET_QEMU_ESIGRETURN;
+
+badframe:
+    force_sig(TARGET_SIGSEGV/*, current*/);
+    return 0;
+}
+
+#else
+
+struct target_sigcontext {
+        uint64_t   sc_regs[32];
+        uint64_t   sc_fpregs[32];
+        uint64_t   sc_mdhi;
+        uint64_t   sc_hi1;
+        uint64_t   sc_hi2;
+        uint64_t   sc_hi3;
+        uint64_t   sc_mdlo;
+        uint64_t   sc_lo1;
+        uint64_t   sc_lo2;
+        uint64_t   sc_lo3;
+        uint64_t   sc_pc;
+        uint32_t   sc_fpc_csr;
+        uint32_t   sc_used_math;
+        uint32_t   sc_dsp;
+        uint32_t   sc_reserved;
+};
+static void setup_frame(int sig, struct target_sigaction *ka,
+            target_sigset_t *set, CPUState *env)
+{
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+long do_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -TARGET_ENOSYS;
+}
+#endif
+
 struct sigframe {
     uint32_t sf_ass[4];			/* argument save space for o32 */
     uint32_t sf_code[2];			/* signal trampoline */
@@ -2706,105 +2817,6 @@ get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
     return (sp - frame_size) & ~7;
 }
 
-/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
-static void setup_frame(int sig, struct target_sigaction * ka,
-                        target_sigset_t *set, CPUState *regs)
-{
-    struct sigframe *frame;
-    abi_ulong frame_addr;
-    int i;
-
-    frame_addr = get_sigframe(ka, regs, sizeof(*frame));
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-	goto give_sigsegv;
-
-    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
-
-    if(setup_sigcontext(regs, &frame->sf_sc))
-	goto give_sigsegv;
-
-    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
-	if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
-	    goto give_sigsegv;
-    }
-
-    /*
-    * Arguments to signal handler:
-    *
-    *   a0 = signal number
-    *   a1 = 0 (should be cause)
-    *   a2 = pointer to struct sigcontext
-    *
-    * $25 and PC point to the signal handler, $29 points to the
-    * struct sigframe.
-    */
-    regs->active_tc.gpr[ 4] = sig;
-    regs->active_tc.gpr[ 5] = 0;
-    regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
-    regs->active_tc.gpr[29] = frame_addr;
-    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
-    /* The original kernel code sets CP0_EPC to the handler
-    * since it returns to userland using eret
-    * we cannot do this here, and we must set PC directly */
-    regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-
-give_sigsegv:
-    unlock_user_struct(frame, frame_addr, 1);
-    force_sig(TARGET_SIGSEGV/*, current*/);
-    return;
-}
-
-long do_sigreturn(CPUState *regs)
-{
-    struct sigframe *frame;
-    abi_ulong frame_addr;
-    sigset_t blocked;
-    target_sigset_t target_set;
-    int i;
-
-#if defined(DEBUG_SIGNAL)
-    fprintf(stderr, "do_sigreturn\n");
-#endif
-    frame_addr = regs->active_tc.gpr[29];
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-   	goto badframe;
-
-    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
-   	if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
-	    goto badframe;
-    }
-
-    target_to_host_sigset_internal(&blocked, &target_set);
-    sigprocmask(SIG_SETMASK, &blocked, NULL);
-
-    if (restore_sigcontext(regs, &frame->sf_sc))
-   	goto badframe;
-
-#if 0
-    /*
-     * Don't let your children do this ...
-     */
-    __asm__ __volatile__(
-   	"move\t$29, %0\n\t"
-   	"j\tsyscall_exit"
-   	:/* no outputs */
-   	:"r" (&regs));
-    /* Unreached */
-#endif
-
-    regs->active_tc.PC = regs->CP0_EPC;
-    /* I am not sure this is right, but it seems to work
-    * maybe a problem with nested signals ? */
-    regs->CP0_EPC = 0;
-    return -TARGET_QEMU_ESIGRETURN;
-
-badframe:
-    force_sig(TARGET_SIGSEGV/*, current*/);
-    return 0;
-}
-
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
 			   target_sigset_t *set, CPUState *env)
