All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Jacobowitz <drow@false.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] Current MIPS fixes
Date: Sun, 4 Dec 2005 16:19:30 -0500	[thread overview]
Message-ID: <20051204211930.GA23961@nevyn.them.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 340 bytes --]

Fabrice, since the last combined patch I sent you, I've dropped the exec.c
bits; added EXCP_HALTED; improved the unaligned access traps; and shaved two
bits off the branch delay slot state.  It's still pretty slow, but I'm
confident it can go faster.  Also has the command line passing bits merged.

-- 
Daniel Jacobowitz
CodeSourcery, LLC

[-- Attachment #2: total-mips-fixes-20051204.patch --]
[-- Type: text/plain, Size: 39750 bytes --]

Index: cpu-exec.c
===================================================================
RCS file: /cvsroot/qemu/qemu/cpu-exec.c,v
retrieving revision 1.69
diff -u -p -r1.69 cpu-exec.c
--- cpu-exec.c	4 Dec 2005 18:46:05 -0000	1.69
+++ cpu-exec.c	4 Dec 2005 21:15:43 -0000
@@ -191,7 +191,7 @@ static inline TranslationBlock *tb_find_
     cs_base = 0;
     pc = env->nip;
 #elif defined(TARGET_MIPS)
-    flags = env->hflags & MIPS_HFLAGS_TMASK;
+    flags = env->hflags & (MIPS_HFLAGS_TMASK | MIPS_HFLAG_BMASK);
     cs_base = 0;
     pc = env->PC;
 #else
@@ -280,6 +280,15 @@ int cpu_exec(CPUState *env1)
            set.  */
         if (env1->interrupt_request
             & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
+            env1->halted = 0;
+        } else {
+            return EXCP_HALTED;
+        }
+    }
+#elif defined(TARGET_MIPS)
+    if (env1->halted) {
+        if (env1->interrupt_request &
+            (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
             env1->halted = 0;
         } else {
             return EXCP_HALTED;
Index: exec-all.h
===================================================================
RCS file: /cvsroot/qemu/qemu/exec-all.h,v
retrieving revision 1.43
diff -u -p -r1.43 exec-all.h
--- exec-all.h	28 Nov 2005 21:19:04 -0000	1.43
+++ exec-all.h	4 Dec 2005 21:15:43 -0000
@@ -62,6 +62,7 @@ extern target_ulong gen_opc_npc[OPC_BUF_
 extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
 extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
 extern target_ulong gen_opc_jump_pc[2];
+extern uint32_t gen_opc_hflags[OPC_BUF_SIZE];
 
 typedef void (GenOpFunc)(void);
 typedef void (GenOpFunc1)(long);
Index: gdbstub.c
===================================================================
RCS file: /cvsroot/qemu/qemu/gdbstub.c,v
retrieving revision 1.33
diff -u -p -r1.33 gdbstub.c
--- gdbstub.c	26 Nov 2005 10:38:38 -0000	1.33
+++ gdbstub.c	4 Dec 2005 21:15:43 -0000
@@ -421,6 +421,72 @@ static void cpu_gdb_write_registers(CPUS
     ptr += 8 * 12 + 4;
     cpsr_write (env, tswapl(*(uint32_t *)ptr), 0xffffffff);
 }
+#elif defined (TARGET_MIPS)
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+    int i;
+    uint8_t *ptr;
+
+    ptr = mem_buf;
+    for (i = 0; i < 32; i++)
+      {
+        *(uint32_t *)ptr = tswapl(env->gpr[i]);
+        ptr += 4;
+      }
+
+    *(uint32_t *)ptr = tswapl(env->CP0_Status);
+    ptr += 4;
+
+    *(uint32_t *)ptr = tswapl(env->LO);
+    ptr += 4;
+
+    *(uint32_t *)ptr = tswapl(env->HI);
+    ptr += 4;
+
+    *(uint32_t *)ptr = tswapl(env->CP0_BadVAddr);
+    ptr += 4;
+
+    *(uint32_t *)ptr = tswapl(env->CP0_Cause);
+    ptr += 4;
+
+    *(uint32_t *)ptr = tswapl(env->PC);
+    ptr += 4;
+
+    /* 32 FP registers, fsr, fir, fp.  Not yet implemented.  */
+
+    return ptr - mem_buf;
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+    int i;
+    uint8_t *ptr;
+
+    ptr = mem_buf;
+    for (i = 0; i < 32; i++)
+      {
+        env->gpr[i] = tswapl(*(uint32_t *)ptr);
+        ptr += 4;
+      }
+
+    env->CP0_Status = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+
+    env->LO = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+
+    env->HI = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+
+    env->CP0_BadVAddr = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+
+    env->CP0_Cause = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+
+    env->PC = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+}
 #else
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
 {
@@ -511,10 +577,12 @@ static int gdb_handle_packet(GDBState *s
         if (*p == ',')
             p++;
         len = strtoul(p, NULL, 16);
-        if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0)
-            memset(mem_buf, 0, len);
-        memtohex(buf, mem_buf, len);
-        put_packet(s, buf);
+        if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) {
+            put_packet (s, "E14");
+        } else {
+            memtohex(buf, mem_buf, len);
+            put_packet(s, buf);
+        }
         break;
     case 'M':
         addr = strtoul(p, (char **)&p, 16);
Index: softmmu_template.h
===================================================================
RCS file: /cvsroot/qemu/qemu/softmmu_template.h,v
retrieving revision 1.14
diff -u -p -r1.14 softmmu_template.h
--- softmmu_template.h	28 Nov 2005 21:19:04 -0000	1.14
+++ softmmu_template.h	4 Dec 2005 21:15:43 -0000
@@ -97,15 +97,28 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUF
             /* slow unaligned access (it spans two pages or IO) */
         do_unaligned_access:
             retaddr = GETPC();
+#ifdef ALIGNED_ONLY
+            do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+#endif
             res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr, 
                                                          is_user, retaddr);
         } else {
-            /* unaligned access in the same page */
+            /* unaligned/aligned access in the same page */
+#ifdef ALIGNED_ONLY
+            if ((addr & (DATA_SIZE - 1)) != 0) {
+                retaddr = GETPC();
+                do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+            }
+#endif
             res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)physaddr);
         }
     } else {
         /* the page is not in the TLB : fill it */
         retaddr = GETPC();
+#ifdef ALIGNED_ONLY
+        if ((addr & (DATA_SIZE - 1)) != 0)
+            do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+#endif
         tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr);
         goto redo;
     }
@@ -213,15 +226,28 @@ void REGPARM(2) glue(glue(__st, SUFFIX),
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
             retaddr = GETPC();
+#ifdef ALIGNED_ONLY
+            do_unaligned_access(addr, 1, is_user, retaddr);
+#endif
             glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val, 
                                                    is_user, retaddr);
         } else {
             /* aligned/unaligned access in the same page */
+#ifdef ALIGNED_ONLY
+            if ((addr & (DATA_SIZE - 1)) != 0) {
+                retaddr = GETPC();
+                do_unaligned_access(addr, 1, is_user, retaddr);
+            }
+#endif
             glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)physaddr, val);
         }
     } else {
         /* the page is not in the TLB : fill it */
         retaddr = GETPC();
+#ifdef ALIGNED_ONLY
+        if ((addr & (DATA_SIZE - 1)) != 0)
+            do_unaligned_access(addr, 1, is_user, retaddr);
+#endif
         tlb_fill(addr, 1, is_user, retaddr);
         goto redo;
     }
Index: translate-all.c
===================================================================
RCS file: /cvsroot/qemu/qemu/translate-all.c,v
retrieving revision 1.13
diff -u -p -r1.13 translate-all.c
--- translate-all.c	2 Jul 2005 14:56:31 -0000	1.13
+++ translate-all.c	4 Dec 2005 21:15:43 -0000
@@ -53,6 +53,8 @@ uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
 #elif defined(TARGET_SPARC)
 target_ulong gen_opc_npc[OPC_BUF_SIZE];
 target_ulong gen_opc_jump_pc[2];
+#elif defined(TARGET_MIPS)
+uint32_t gen_opc_hflags[OPC_BUF_SIZE];
 #endif
 
 int code_copy_enabled = 1;
@@ -302,6 +304,8 @@ int cpu_restore_state(TranslationBlock *
     }
 #elif defined(TARGET_MIPS)
     env->PC = gen_opc_pc[j];
+    env->hflags &= ~MIPS_HFLAG_BMASK;
+    env->hflags |= gen_opc_hflags[j];
 #endif
     return 0;
 }
Index: hw/mips_r4k.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/mips_r4k.c,v
retrieving revision 1.11
diff -u -p -r1.11 mips_r4k.c
--- hw/mips_r4k.c	23 Nov 2005 21:11:49 -0000	1.11
+++ hw/mips_r4k.c	4 Dec 2005 21:15:43 -0000
@@ -53,7 +53,7 @@ static void cpu_mips_update_count (CPUSt
     next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
     if (next == now)
 	next++;
-#if 1
+#if 0
     if (logfile) {
         fprintf(logfile, "%s: 0x%08llx %08x %08x => 0x%08llx\n",
                 __func__, now, count, compare, next - now);
@@ -84,7 +84,7 @@ static void mips_timer_cb (void *opaque)
     CPUState *env;
 
     env = opaque;
-#if 1
+#if 0
     if (logfile) {
         fprintf(logfile, "%s\n", __func__);
     }
@@ -103,23 +103,29 @@ void cpu_mips_clock_init (CPUState *env)
 
 static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
 {
+#if 0
     if (logfile)
         fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
+#endif
     cpu_outb(NULL, addr & 0xffff, value);
 }
 
 static uint32_t io_readb (void *opaque, target_phys_addr_t addr)
 {
     uint32_t ret = cpu_inb(NULL, addr & 0xffff);
+#if 0
     if (logfile)
         fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
+#endif
     return ret;
 }
 
 static void io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
 {
+#if 0
     if (logfile)
         fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
+#endif
 #ifdef TARGET_WORDS_BIGENDIAN
     value = bswap16(value);
 #endif
@@ -132,15 +138,19 @@ static uint32_t io_readw (void *opaque, 
 #ifdef TARGET_WORDS_BIGENDIAN
     ret = bswap16(ret);
 #endif
+#if 0
     if (logfile)
         fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
+#endif
     return ret;
 }
 
 static void io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
 {
+#if 0
     if (logfile)
         fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
+#endif
 #ifdef TARGET_WORDS_BIGENDIAN
     value = bswap32(value);
 #endif
@@ -154,8 +164,10 @@ static uint32_t io_readl (void *opaque, 
 #ifdef TARGET_WORDS_BIGENDIAN
     ret = bswap32(ret);
 #endif
+#if 0
     if (logfile)
         fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
+#endif
     return ret;
 }
 
@@ -233,6 +245,11 @@ void mips_r4k_init (int ram_size, int vg
             initrd_size = 0;
         }
         env->PC = KERNEL_LOAD_ADDR;
+	/* Store command line.  */
+        strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
+        /* FIXME: little endian support */
+        *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
+        *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
     } else {
         kernel_base = 0;
         kernel_size = 0;
Index: target-mips/cpu.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/cpu.h,v
retrieving revision 1.3
diff -u -p -r1.3 cpu.h
--- target-mips/cpu.h	20 Nov 2005 10:29:33 -0000	1.3
+++ target-mips/cpu.h	4 Dec 2005 21:15:43 -0000
@@ -1,6 +1,8 @@
 #if !defined (__MIPS_CPU_H__)
 #define __MIPS_CPU_H__
 
+#define TARGET_HAS_ICE 1
+
 #include "mips-defs.h"
 #include "cpu-defs.h"
 #include "config.h"
@@ -18,6 +20,7 @@ typedef struct tlb_t tlb_t;
 struct tlb_t {
     target_ulong VPN;
     target_ulong end;
+    target_ulong end2;
     uint8_t ASID;
     uint8_t G;
     uint8_t C[2];
@@ -151,18 +154,20 @@ struct CPUMIPSState {
 #define MIPS_HFLAG_DM     0x0008 /* Debug mode                         */
 #define MIPS_HFLAG_SM     0x0010 /* Supervisor mode                    */
 #define MIPS_HFLAG_RE     0x0040 /* Reversed endianness                */
-#define MIPS_HFLAG_DS     0x0080 /* In / out of delay slot             */
-    /* Those flags keep the branch state if the translation is interrupted
-     * between the branch instruction and the delay slot
-     */
-#define MIPS_HFLAG_BMASK  0x0F00
-#define MIPS_HFLAG_B      0x0100 /* Unconditional branch               */
-#define MIPS_HFLAG_BC     0x0200 /* Conditional branch                 */
-#define MIPS_HFLAG_BL     0x0400 /* Likely branch                      */
-#define MIPS_HFLAG_BR     0x0800 /* branch to register (can't link TB) */
+    /* If translation is interrupted between the branch instruction and
+     * the delay slot, record what type of branch it is so that we can
+     * resume translation properly.  It might be possible to reduce
+     * this from three bits to two.  */
+#define MIPS_HFLAG_BMASK  0x0380
+#define MIPS_HFLAG_B      0x0080 /* Unconditional branch               */
+#define MIPS_HFLAG_BC     0x0100 /* Conditional branch                 */
+#define MIPS_HFLAG_BL     0x0180 /* Likely branch                      */
+#define MIPS_HFLAG_BR     0x0200 /* branch to register (can't link TB) */
     target_ulong btarget;        /* Jump / branch target               */
     int bcond;                   /* Branch condition (if needed)       */
 
+    int halted; /* TRUE if the CPU is in suspend state */
+
     CPU_COMMON
 };
 
@@ -202,15 +207,15 @@ enum {
     EXCP_IBE,
     EXCP_DBp,
     EXCP_SYSCALL,
-    EXCP_BREAK,
-    EXCP_CpU, /* 16 */
+    EXCP_BREAK, /* 16 */
+    EXCP_CpU,
     EXCP_RI,
     EXCP_OVERFLOW,
     EXCP_TRAP,
     EXCP_DDBS,
     EXCP_DWATCH,
-    EXCP_LAE, /* 22 */
-    EXCP_SAE,
+    EXCP_LAE,
+    EXCP_SAE, /* 24 */
     EXCP_LTLBL,
     EXCP_TLBL,
     EXCP_TLBS,
Index: target-mips/exec.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.4
diff -u -p -r1.4 exec.h
--- target-mips/exec.h	30 Oct 2005 18:16:26 -0000	1.4
+++ target-mips/exec.h	4 Dec 2005 21:15:43 -0000
@@ -65,19 +65,19 @@ void do_tlbwi (void);
 void do_tlbwr (void);
 void do_tlbp (void);
 void do_tlbr (void);
-void do_lwl_raw (void);
-void do_lwr_raw (void);
-void do_swl_raw (void);
-void do_swr_raw (void);
+void do_lwl_raw (uint32_t);
+void do_lwr_raw (uint32_t);
+uint32_t do_swl_raw (uint32_t);
+uint32_t do_swr_raw (uint32_t);
 #if !defined(CONFIG_USER_ONLY)
-void do_lwl_user (void);
-void do_lwl_kernel (void);
-void do_lwr_user (void);
-void do_lwr_kernel (void);
-void do_swl_user (void);
-void do_swl_kernel (void);
-void do_swr_user (void);
-void do_swr_kernel (void);
+void do_lwl_user (uint32_t);
+void do_lwl_kernel (uint32_t);
+void do_lwr_user (uint32_t);
+void do_lwr_kernel (uint32_t);
+uint32_t do_swl_user (uint32_t);
+uint32_t do_swl_kernel (uint32_t);
+uint32_t do_swr_user (uint32_t);
+uint32_t do_swr_kernel (uint32_t);
 #endif
 void do_pmon (int function);
 
@@ -88,6 +88,7 @@ void do_interrupt (CPUState *env);
 void cpu_loop_exit(void);
 void do_raise_exception_err (uint32_t exception, int error_code);
 void do_raise_exception (uint32_t exception);
+void do_raise_exception_direct (uint32_t exception);
 
 void cpu_dump_state(CPUState *env, FILE *f, 
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
Index: target-mips/helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/helper.c,v
retrieving revision 1.7
diff -u -p -r1.7 helper.c
--- target-mips/helper.c	4 Jul 2005 22:17:32 -0000	1.7
+++ target-mips/helper.c	4 Dec 2005 21:15:43 -0000
@@ -46,7 +46,7 @@ static int map_address (CPUState *env, t
         tlb = &env->tlb[i];
         /* Check ASID, virtual page number & size */
         if ((tlb->G == 1 || tlb->ASID == ASID) &&
-            tlb->VPN == tag && address < tlb->end) {
+            tlb->VPN == tag && address < tlb->end2) {
             /* TLB match */
             n = (address >> 12) & 1;
             /* Check access rights */
@@ -167,10 +167,15 @@ int cpu_mips_handle_mmu_fault (CPUState 
     int ret = 0;
 
     if (logfile) {
+#if 0
         cpu_dump_state(env, logfile, fprintf, 0);
+#endif
         fprintf(logfile, "%s pc %08x ad %08x rw %d is_user %d smmu %d\n",
                 __func__, env->PC, address, rw, is_user, is_softmmu);
     }
+
+    rw &= 1;
+
     /* data access */
     /* XXX: put correct access by using cpu_restore_state()
        correctly */
@@ -226,7 +231,7 @@ int cpu_mips_handle_mmu_fault (CPUState 
         /* Raise exception */
         env->CP0_BadVAddr = address;
         env->CP0_Context = (env->CP0_Context & 0xff800000) |
-	                   ((address >> 8) &   0x007ffff0);
+	                   ((address >> 9) &   0x007ffff0);
         env->CP0_EntryHi =
             (env->CP0_EntryHi & 0x000000FF) | (address & 0xFFFFF000);
         env->exception_index = exception;
@@ -276,11 +281,12 @@ void do_interrupt (CPUState *env)
         env->CP0_Debug |= 1 << CP0DB_DDBL;
         goto set_DEPC;
     set_DEPC:
-        if (env->hflags & MIPS_HFLAG_DS) {
+        if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
              * come back to the jump
              */
             env->CP0_DEPC = env->PC - 4;
+            env->hflags &= ~MIPS_HFLAG_BMASK;
         } else {
             env->CP0_DEPC = env->PC;
         }
@@ -316,8 +322,7 @@ void do_interrupt (CPUState *env)
         env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
             (1 << CP0St_NMI);
     set_error_EPC:
-        env->hflags = MIPS_HFLAG_ERL;
-        if (env->hflags & MIPS_HFLAG_DS) {
+        if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
              * come back to the jump
              */
@@ -325,6 +330,7 @@ void do_interrupt (CPUState *env)
         } else {
             env->CP0_ErrorEPC = env->PC;
         }
+        env->hflags = MIPS_HFLAG_ERL;
         pc = 0xBFC00000;
         break;
     case EXCP_MCHECK:
@@ -366,7 +372,7 @@ void do_interrupt (CPUState *env)
         goto set_EPC;
     case EXCP_CpU:
         cause = 11;
-        /* XXX: fill in the faulty unit number */
+        env->CP0_Cause = (env->CP0_Cause & ~0x03000000) | (env->error_code << 28);
         goto set_EPC;
     case EXCP_OVERFLOW:
         cause = 12;
@@ -391,12 +397,13 @@ void do_interrupt (CPUState *env)
         env->hflags |= MIPS_HFLAG_EXL;
         pc += offset;
         env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
-        if (env->hflags & MIPS_HFLAG_DS) {
+        if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
              * come back to the jump
              */
             env->CP0_EPC = env->PC - 4;
             env->CP0_Cause |= 0x80000000;
+            env->hflags &= ~MIPS_HFLAG_BMASK;
         } else {
             env->CP0_EPC = env->PC;
             env->CP0_Cause &= ~0x80000000;
Index: target-mips/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/op.c,v
retrieving revision 1.4
diff -u -p -r1.4 op.c
--- target-mips/op.c	30 Oct 2005 21:39:18 -0000	1.4
+++ target-mips/op.c	4 Dec 2005 21:15:43 -0000
@@ -207,7 +207,7 @@ void op_addo (void)
     tmp = T0;
     T0 += T1;
     if ((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31)) {
-        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
+        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
     }
     RETURN();
 }
@@ -225,7 +225,7 @@ void op_subo (void)
     tmp = T0;
     T0 = (int32_t)T0 - (int32_t)T1;
     if (!((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31))) {
-        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
+        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
     }
     RETURN();
 }
@@ -364,7 +364,7 @@ static inline void set_HILO (uint64_t HI
 
 void op_mult (void)
 {
-    set_HILO((int64_t)T0 * (int64_t)T1);
+    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
     RETURN();
 }
 
@@ -378,7 +378,7 @@ void op_madd (void)
 {
     int64_t tmp;
 
-    tmp = ((int64_t)T0 * (int64_t)T1);
+    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
     set_HILO((int64_t)get_HILO() + tmp);
     RETURN();
 }
@@ -396,7 +396,7 @@ void op_msub (void)
 {
     int64_t tmp;
 
-    tmp = ((int64_t)T0 * (int64_t)T1);
+    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
     set_HILO((int64_t)get_HILO() - tmp);
     RETURN();
 }
@@ -595,11 +595,16 @@ void op_pmon (void)
 void op_trap (void)
 {
     if (T0) {
-        CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
+        CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
     }
     RETURN();
 }
 
+void op_debug (void)
+{
+  CALL_FROM_TB1(do_raise_exception_direct, EXCP_DEBUG);
+}
+
 void op_set_lladdr (void)
 {
     env->CP0_LLAddr = T2;
@@ -654,3 +659,8 @@ void op_exit_tb (void)
     EXIT_TB();
 }
 
+void op_wait (void)
+{
+    env->halted = 1;
+    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
+}
Index: target-mips/op_helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.7
diff -u -p -r1.7 op_helper.c
--- target-mips/op_helper.c	26 Nov 2005 18:47:20 -0000	1.7
+++ target-mips/op_helper.c	4 Dec 2005 21:15:44 -0000
@@ -22,6 +22,8 @@
 
 #define MIPS_DEBUG_DISAS
 
+#define GETPC() (__builtin_return_address(0))
+
 /*****************************************************************************/
 /* Exceptions processing helpers */
 void cpu_loop_exit(void)
@@ -46,6 +48,21 @@ void do_raise_exception (uint32_t except
     do_raise_exception_err(exception, 0);
 }
 
+void do_restore_state (void *pc_ptr)
+{
+  TranslationBlock *tb;
+  unsigned long pc = (unsigned long) pc_ptr;
+
+  tb = tb_find_pc (pc);
+  cpu_restore_state (tb, env, pc, NULL);
+}
+
+void do_raise_exception_direct (uint32_t exception)
+{
+    do_restore_state (GETPC ());
+    do_raise_exception_err (exception, 0);
+}
+
 #define MEMSUFFIX _raw
 #include "op_helper_mem.c"
 #undef MEMSUFFIX
@@ -73,7 +90,7 @@ static inline void set_HILO (uint64_t HI
 
 void do_mult (void)
 {
-    set_HILO((int64_t)T0 * (int64_t)T1);
+    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
 }
 
 void do_multu (void)
@@ -85,7 +102,7 @@ void do_madd (void)
 {
     int64_t tmp;
 
-    tmp = ((int64_t)T0 * (int64_t)T1);
+    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
     set_HILO((int64_t)get_HILO() + tmp);
 }
 
@@ -101,7 +118,7 @@ void do_msub (void)
 {
     int64_t tmp;
 
-    tmp = ((int64_t)T0 * (int64_t)T1);
+    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
     set_HILO((int64_t)get_HILO() - tmp);
 }
 
@@ -353,6 +370,9 @@ void do_mtc0 (int reg, int sel)
         val = T0 & 0xFFFFF0FF;
         old = env->CP0_EntryHi;
         env->CP0_EntryHi = val;
+	/* If the ASID changes, flush qemu's TLB.  */
+	if ((old & 0xFF) != (val & 0xFF))
+	  tlb_flush (env, 1);
         rn = "EntryHi";
         break;
     case 11:
@@ -525,11 +545,25 @@ static void invalidate_tb (int idx)
         addr = tlb->PFN[0];
         end = addr + (tlb->end - tlb->VPN);
         tb_invalidate_page_range(addr, end);
+        /* FIXME: Might be faster to just invalidate the whole "tlb" here
+           and refill it on demand from our simulated TLB.  */
+        addr = tlb->VPN;
+        while (addr < tlb->end) {
+            tlb_flush_page (env, addr);
+            addr += TARGET_PAGE_SIZE;
+        }
     }
     if (tlb->V[1]) {
         addr = tlb->PFN[1];
         end = addr + (tlb->end - tlb->VPN);
         tb_invalidate_page_range(addr, end);
+        /* FIXME: Might be faster to just invalidate the whole "tlb" here
+           and refill it on demand from our simulated TLB.  */
+        addr = tlb->end;
+        while (addr < tlb->end2) {
+            tlb_flush_page (env, addr);
+            addr += TARGET_PAGE_SIZE;
+        }
     }
 }
 
@@ -545,6 +579,7 @@ static void fill_tb (int idx)
     size = env->CP0_PageMask >> 13;
     size = 4 * (size + 1);
     tlb->end = tlb->VPN + (1 << (8 + size));
+    tlb->end2 = tlb->end + (1 << (8 + size));
     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
     tlb->V[0] = env->CP0_EntryLo0 & 2;
     tlb->D[0] = env->CP0_EntryLo0 & 4;
@@ -601,6 +636,12 @@ void do_tlbr (void)
     int size;
 
     tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
+
+    /* If this will change the current ASID, flush qemu's TLB.  */
+    /* FIXME: Could avoid flushing things which match global entries... */
+    if ((env->CP0_EntryHi & 0xFF) != tlb->ASID)
+      tlb_flush (env, 1);
+
     env->CP0_EntryHi = tlb->VPN | tlb->ASID;
     size = (tlb->end - tlb->VPN) >> 12;
     env->CP0_PageMask = (size - 1) << 13;
@@ -664,8 +705,10 @@ void do_pmon (int function)
 
 #if !defined(CONFIG_USER_ONLY) 
 
+static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
+
 #define MMUSUFFIX _mmu
-#define GETPC() (__builtin_return_address(0))
+#define ALIGNED_ONLY
 
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -678,6 +721,13 @@ void do_pmon (int function)
 
 #define SHIFT 3
 #include "softmmu_template.h"
+
+static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
+{
+    env->CP0_BadVAddr = addr;
+    do_restore_state (retaddr);
+    do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
+}
 
 void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
 {
Index: target-mips/op_helper_mem.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/op_helper_mem.c,v
retrieving revision 1.1
diff -u -p -r1.1 op_helper_mem.c
--- target-mips/op_helper_mem.c	2 Jul 2005 14:57:14 -0000	1.1
+++ target-mips/op_helper_mem.c	4 Dec 2005 21:15:44 -0000
@@ -1,11 +1,9 @@
-void glue(do_lwl, MEMSUFFIX) (void)
+void glue(do_lwl, MEMSUFFIX) (uint32_t tmp)
 {
 #if defined (DEBUG_OP)
     target_ulong sav = T0;
 #endif
-    uint32_t tmp;
 
-    tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
     /* XXX: this is valid only in big-endian mode
      *      should be reverted for little-endian...
      */
@@ -32,14 +30,12 @@ void glue(do_lwl, MEMSUFFIX) (void)
     RETURN();
 }
 
-void glue(do_lwr, MEMSUFFIX) (void)
+void glue(do_lwr, MEMSUFFIX) (uint32_t tmp)
 {
 #if defined (DEBUG_OP)
     target_ulong sav = T0;
 #endif
-    uint32_t tmp;
 
-    tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
     /* XXX: this is valid only in big-endian mode
      *      should be reverted for little-endian...
      */
@@ -66,14 +62,12 @@ void glue(do_lwr, MEMSUFFIX) (void)
     RETURN();
 }
 
-void glue(do_swl, MEMSUFFIX) (void)
+uint32_t glue(do_swl, MEMSUFFIX) (uint32_t tmp)
 {
 #if defined (DEBUG_OP)
     target_ulong sav;
 #endif
-    uint32_t tmp;
 
-    tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
 #if defined (DEBUG_OP)
     sav = tmp;
 #endif
@@ -94,7 +88,6 @@ void glue(do_swl, MEMSUFFIX) (void)
         tmp = (tmp & 0xFFFFFF00) | (T1 >> 24);
         break;
     }
-    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
 #if defined (DEBUG_OP)
     if (logfile) {
         fprintf(logfile, "%s: %08x - %08x %08x => %08x\n",
@@ -102,16 +95,15 @@ void glue(do_swl, MEMSUFFIX) (void)
     }
 #endif
     RETURN();
+    return tmp;
 }
 
-void glue(do_swr, MEMSUFFIX) (void)
+uint32_t glue(do_swr, MEMSUFFIX) (uint32_t tmp)
 {
 #if defined (DEBUG_OP)
     target_ulong sav;
 #endif
-    uint32_t tmp;
 
-    tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
 #if defined (DEBUG_OP)
     sav = tmp;
 #endif
@@ -132,7 +124,6 @@ void glue(do_swr, MEMSUFFIX) (void)
         tmp = T1;
         break;
     }
-    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
 #if defined (DEBUG_OP)
     if (logfile) {
         fprintf(logfile, "%s: %08x - %08x %08x => %08x\n",
@@ -140,4 +131,5 @@ void glue(do_swr, MEMSUFFIX) (void)
     }
 #endif
     RETURN();
+    return tmp;
 }
Index: target-mips/op_mem.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/op_mem.c,v
retrieving revision 1.1
diff -u -p -r1.1 op_mem.c
--- target-mips/op_mem.c	2 Jul 2005 14:57:14 -0000	1.1
+++ target-mips/op_mem.c	4 Dec 2005 21:15:44 -0000
@@ -67,28 +67,35 @@ void glue(op_sw, MEMSUFFIX) (void)
     RETURN();
 }
 
-/* "half" load and stores */
+/* "half" load and stores.  We must do the memory access inline,
+   or fault handling won't work.  */
 void glue(op_lwl, MEMSUFFIX) (void)
 {
-    CALL_FROM_TB0(glue(do_lwl, MEMSUFFIX));
+    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
+    CALL_FROM_TB1(glue(do_lwl, MEMSUFFIX), tmp);
     RETURN();
 }
 
 void glue(op_lwr, MEMSUFFIX) (void)
 {
-    CALL_FROM_TB0(glue(do_lwr, MEMSUFFIX));
+    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
+    CALL_FROM_TB1(glue(do_lwr, MEMSUFFIX), tmp);
     RETURN();
 }
 
 void glue(op_swl, MEMSUFFIX) (void)
 {
-    CALL_FROM_TB0(glue(do_swl, MEMSUFFIX));
+    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
+    tmp = CALL_FROM_TB1(glue(do_swl, MEMSUFFIX), tmp);
+    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
     RETURN();
 }
 
 void glue(op_swr, MEMSUFFIX) (void)
 {
-    CALL_FROM_TB0(glue(do_swr, MEMSUFFIX));
+    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
+    tmp = CALL_FROM_TB1(glue(do_swr, MEMSUFFIX), tmp);
+    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
     RETURN();
 }
 
Index: target-mips/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/translate.c,v
retrieving revision 1.10
diff -u -p -r1.10 translate.c
--- target-mips/translate.c	26 Nov 2005 18:47:06 -0000	1.10
+++ target-mips/translate.c	4 Dec 2005 21:15:44 -0000
@@ -338,17 +338,25 @@ static inline void save_cpu_state (Disas
     }
 }
 
-static inline void generate_exception (DisasContext *ctx, int excp)
+static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
 {
 #if defined MIPS_DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM)
             fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
 #endif
     save_cpu_state(ctx, 1);
-    gen_op_raise_exception(excp);
+    if (err == 0)
+        gen_op_raise_exception(excp);
+    else
+        gen_op_raise_exception_err(excp, err);
     ctx->bstate = BS_EXCP;
 }
 
+static inline void generate_exception (DisasContext *ctx, int excp)
+{
+    generate_exception_err (ctx, excp, 0);
+}
+
 #if defined(CONFIG_USER_ONLY)
 #define op_ldst(name)        gen_op_##name##_raw()
 #define OP_LD_TABLE(width)
@@ -1020,14 +1028,14 @@ static void gen_compute_branch (DisasCon
         case OPC_BLEZ:    /* 0 <= 0          */
         case OPC_BLEZL:   /* 0 <= 0 likely   */
             /* Always take */
-            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
+            ctx->hflags |= MIPS_HFLAG_B;
             MIPS_DEBUG("balways");
             break;
         case OPC_BGEZAL:  /* 0 >= 0          */
         case OPC_BGEZALL: /* 0 >= 0 likely   */
             /* Always take and link */
             blink = 31;
-            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
+            ctx->hflags |= MIPS_HFLAG_B;
             MIPS_DEBUG("balways and link");
             break;
         case OPC_BNE:     /* rx != rx        */
@@ -1053,21 +1061,21 @@ static void gen_compute_branch (DisasCon
             gen_goto_tb(ctx, 0, ctx->pc + 4);
             return;
         case OPC_J:
-            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
+            ctx->hflags |= MIPS_HFLAG_B;
             MIPS_DEBUG("j %08x", btarget);
             break;
         case OPC_JAL:
             blink = 31;
-            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
+            ctx->hflags |= MIPS_HFLAG_B;
             MIPS_DEBUG("jal %08x", btarget);
             break;
         case OPC_JR:
-            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
+            ctx->hflags |= MIPS_HFLAG_BR;
             MIPS_DEBUG("jr %s", regnames[rs]);
             break;
         case OPC_JALR:
             blink = rt;
-            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
+            ctx->hflags |= MIPS_HFLAG_BR;
             MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
             break;
         default:
@@ -1144,14 +1152,14 @@ static void gen_compute_branch (DisasCon
             blink = 31;
             MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
         not_likely:
-            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BC;
+            ctx->hflags |= MIPS_HFLAG_BC;
             break;
         case OPC_BLTZALL:
             gen_op_ltz();
             blink = 31;
             MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
         likely:
-            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BL;
+            ctx->hflags |= MIPS_HFLAG_BL;
             break;
         }
         gen_op_set_bcond();
@@ -1178,7 +1186,7 @@ static void gen_cp0 (DisasContext *ctx, 
         if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "CP0 is not usable\n");
         }
-        gen_op_raise_exception_err(EXCP_CpU, 0);
+        generate_exception_err (ctx, EXCP_CpU, 0);
         return;
     }
     switch (opc) {
@@ -1236,7 +1244,15 @@ static void gen_cp0 (DisasContext *ctx, 
             ctx->bstate = BS_EXCP;
         }
         break;
-    /* XXX: TODO: WAIT */
+    case OPC_WAIT:
+        opn = "wait";
+        /* If we get an exception, we want to restart at next instruction */
+        ctx->pc += 4;
+        save_cpu_state(ctx, 1);
+        ctx->pc -= 4;
+        gen_op_wait();
+        ctx->bstate = BS_EXCP;
+        break;
     default:
         if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
@@ -1292,7 +1308,7 @@ static void gen_blikely(DisasContext *ct
     int l1;
     l1 = gen_new_label();
     gen_op_jnz_T2(l1);
-    gen_op_save_state(ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS));
+    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
     gen_goto_tb(ctx, 1, ctx->pc + 4);
     gen_set_label(l1);
 }
@@ -1304,8 +1320,7 @@ static void decode_opc (DisasContext *ct
     uint16_t op, op1;
     int16_t imm;
 
-    if ((ctx->hflags & MIPS_HFLAG_DS) &&
-        (ctx->hflags & MIPS_HFLAG_BL)) {
+    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
         /* Handle blikely not taken case */
         MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
         gen_blikely(ctx);
@@ -1361,9 +1376,16 @@ static void decode_opc (DisasContext *ct
         case 0x05:          /* Pmon entry point */
             gen_op_pmon((ctx->opcode >> 6) & 0x1F);
             break;
-#if defined (MIPS_HAS_MOVCI)
+
         case 0x01:          /* MOVCI */
+#if defined (MIPS_HAS_MOVCI)
+            /* XXX */
+#else
+            /* Not implemented */
+            generate_exception_err (ctx, EXCP_CpU, 1);
 #endif
+            break;
+
 #if defined (TARGET_MIPS64)
         case 0x14: /* MIPS64 specific opcodes */
         case 0x16:
@@ -1438,7 +1460,7 @@ static void decode_opc (DisasContext *ct
             gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
             break;
         default:
-            gen_cp0(ctx, (ctx->opcode & 0x1F) | EXT_CP0, rt, rd);
+            gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd);
             break;
         }
         break;
@@ -1467,23 +1489,35 @@ static void decode_opc (DisasContext *ct
         break;
     case 0x3F: /* HACK */
         break;
+
+    /* Floating point.  */
+    case 0x31: /* LWC1 */
+    case 0x35: /* LDC1 */
+    case 0x39: /* SWC1 */
+    case 0x3D: /* SDC1 */
+    case 0x11:          /* CP1 opcode */
 #if defined(MIPS_USES_FPU)
-    case 0x31 ... 0x32: /* Floating point load/store */
-    case 0x35 ... 0x36:
-    case 0x3A ... 0x3B:
-    case 0x3D ... 0x3E:
-        /* Not implemented */
         /* XXX: not correct */
+#else
+        generate_exception_err(ctx, EXCP_CpU, 1);
 #endif
-    case 0x11:          /* CP1 opcode */
-        /* Not implemented */
-        /* XXX: not correct */
+        break;
+
+    /* COP2.  */
+    case 0x32: /* LWC2 */
+    case 0x36: /* LDC2 */
+    case 0x3A: /* SWC2 */
+    case 0x3E: /* SDC2 */
     case 0x12:          /* CP2 opcode */
         /* Not implemented */
-        /* XXX: not correct */
+        generate_exception_err(ctx, EXCP_CpU, 2);
+        break;
+
     case 0x13:          /* CP3 opcode */
         /* Not implemented */
-        /* XXX: not correct */
+        generate_exception_err(ctx, EXCP_CpU, 3);
+        break;
+
 #if defined (TARGET_MIPS64)
     case 0x18 ... 0x1B:
     case 0x27:
@@ -1497,21 +1531,15 @@ static void decode_opc (DisasContext *ct
 #endif
     case 0x1E:
         /* ASE specific */
-#if defined (MIPS_HAS_LSC)
-    case 0x31: /* LWC1 */
-    case 0x32: /* LWC2 */
-    case 0x35: /* SDC1 */
-    case 0x36: /* SDC2 */
-#endif
     default:            /* Invalid */
         MIPS_INVAL("");
         generate_exception(ctx, EXCP_RI);
         break;
     }
-    if (ctx->hflags & MIPS_HFLAG_DS) {
+    if (ctx->hflags & MIPS_HFLAG_BMASK) {
         int hflags = ctx->hflags;
         /* Branches completion */
-        ctx->hflags &= ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS);
+        ctx->hflags &= ~MIPS_HFLAG_BMASK;
         ctx->bstate = BS_BRANCH;
         save_cpu_state(ctx, 0);
         switch (hflags & MIPS_HFLAG_BMASK) {
@@ -1557,16 +1585,20 @@ int gen_intermediate_code_internal (CPUS
     uint16_t *gen_opc_end;
     int j, lj = -1;
 
+    if (search_pc && loglevel)
+	fprintf (logfile, "search pc %d\n", search_pc);
+
     pc_start = tb->pc;
     gen_opc_ptr = gen_opc_buf;
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
     gen_opparam_ptr = gen_opparam_buf;
     nb_gen_labels = 0;
     ctx.pc = pc_start;
+    ctx.saved_pc = -1;
     ctx.tb = tb;
     ctx.bstate = BS_NONE;
-    /* Restore delay slot state */
-    ctx.hflags = env->hflags;
+    /* Restore delay slot state from the tb context.  */
+    ctx.hflags = tb->flags;
     ctx.saved_hflags = ctx.hflags;
     if (ctx.hflags & MIPS_HFLAG_BR) {
         gen_op_restore_breg_target();
@@ -1588,42 +1620,65 @@ int gen_intermediate_code_internal (CPUS
 #ifdef DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_CPU) {
         fprintf(logfile, "------------------------------------------------\n");
+        /* FIXME: This may print out stale hflags from env... */
         cpu_dump_state(env, logfile, fprintf, 0);
     }
 #endif
 #if defined MIPS_DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM)
-        fprintf(logfile, "\ntb %p super %d cond %04x %04x\n",
-                tb, ctx.mem_idx, ctx.hflags, env->hflags);
+        fprintf(logfile, "\ntb %p super %d cond %04x\n",
+                tb, ctx.mem_idx, ctx.hflags);
 #endif
     while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
+        if (env->nb_breakpoints > 0) {
+            for(j = 0; j < env->nb_breakpoints; j++) {
+                if (env->breakpoints[j] == ctx.pc) {
+                    save_cpu_state(ctxp, 1);
+                    ctx.bstate = BS_BRANCH;
+                    gen_op_debug();
+                    goto done_generating;
+                }
+            }
+        }
+
         if (search_pc) {
             j = gen_opc_ptr - gen_opc_buf;
-            save_cpu_state(ctxp, 1);
             if (lj < j) {
                 lj++;
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
-                gen_opc_pc[lj] = ctx.pc;
-                gen_opc_instr_start[lj] = 1;
             }
+            gen_opc_pc[lj] = ctx.pc;
+            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
+            gen_opc_instr_start[lj] = 1;
         }
         ctx.opcode = ldl_code(ctx.pc);
         decode_opc(&ctx);
         ctx.pc += 4;
+
+        if (env->singlestep_enabled)
+            break;
+
         if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
             break;
+
 #if defined (MIPS_SINGLE_STEP)
         break;
 #endif
     }
-    if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
+    if (env->singlestep_enabled) {
+        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
+        gen_op_debug();
+        goto done_generating;
+    }
+    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
         save_cpu_state(ctxp, 0);
         gen_goto_tb(&ctx, 0, ctx.pc);
     }
     gen_op_reset_T0();
     /* Generate the return instruction */
     gen_op_exit_tb();
+done_generating:
     *gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         j = gen_opc_ptr - gen_opc_buf;

             reply	other threads:[~2005-12-04 21:19 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-12-04 21:19 Daniel Jacobowitz [this message]
2005-12-05 19:50 ` [Qemu-devel] Current MIPS fixes Fabrice Bellard
2005-12-05 20:30   ` Daniel Jacobowitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20051204211930.GA23961@nevyn.them.org \
    --to=drow@false.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.