Commit 4ad40f366f20f6991b640d7af63c9fc3a59246fa

Authored by bellard
1 parent 6810e154

MIPS fixes (Daniel Jacobowitz)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1690 c046a42c-6fe2-441c-8c8c-71466251a162
target-mips/cpu.h
1 #if !defined (__MIPS_CPU_H__) 1 #if !defined (__MIPS_CPU_H__)
2 #define __MIPS_CPU_H__ 2 #define __MIPS_CPU_H__
3 3
  4 +#define TARGET_HAS_ICE 1
  5 +
4 #include "mips-defs.h" 6 #include "mips-defs.h"
5 #include "cpu-defs.h" 7 #include "cpu-defs.h"
6 #include "config.h" 8 #include "config.h"
@@ -18,6 +20,7 @@ typedef struct tlb_t tlb_t; @@ -18,6 +20,7 @@ typedef struct tlb_t tlb_t;
18 struct tlb_t { 20 struct tlb_t {
19 target_ulong VPN; 21 target_ulong VPN;
20 target_ulong end; 22 target_ulong end;
  23 + target_ulong end2;
21 uint8_t ASID; 24 uint8_t ASID;
22 uint8_t G; 25 uint8_t G;
23 uint8_t C[2]; 26 uint8_t C[2];
@@ -151,18 +154,20 @@ struct CPUMIPSState { @@ -151,18 +154,20 @@ struct CPUMIPSState {
151 #define MIPS_HFLAG_DM 0x0008 /* Debug mode */ 154 #define MIPS_HFLAG_DM 0x0008 /* Debug mode */
152 #define MIPS_HFLAG_SM 0x0010 /* Supervisor mode */ 155 #define MIPS_HFLAG_SM 0x0010 /* Supervisor mode */
153 #define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */ 156 #define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */
154 -#define MIPS_HFLAG_DS 0x0080 /* In / out of delay slot */  
155 - /* Those flags keep the branch state if the translation is interrupted  
156 - * between the branch instruction and the delay slot  
157 - */  
158 -#define MIPS_HFLAG_BMASK 0x0F00  
159 -#define MIPS_HFLAG_B 0x0100 /* Unconditional branch */  
160 -#define MIPS_HFLAG_BC 0x0200 /* Conditional branch */  
161 -#define MIPS_HFLAG_BL 0x0400 /* Likely branch */  
162 -#define MIPS_HFLAG_BR 0x0800 /* branch to register (can't link TB) */ 157 + /* If translation is interrupted between the branch instruction and
  158 + * the delay slot, record what type of branch it is so that we can
  159 + * resume translation properly. It might be possible to reduce
  160 + * this from three bits to two. */
  161 +#define MIPS_HFLAG_BMASK 0x0380
  162 +#define MIPS_HFLAG_B 0x0080 /* Unconditional branch */
  163 +#define MIPS_HFLAG_BC 0x0100 /* Conditional branch */
  164 +#define MIPS_HFLAG_BL 0x0180 /* Likely branch */
  165 +#define MIPS_HFLAG_BR 0x0200 /* branch to register (can't link TB) */
163 target_ulong btarget; /* Jump / branch target */ 166 target_ulong btarget; /* Jump / branch target */
164 int bcond; /* Branch condition (if needed) */ 167 int bcond; /* Branch condition (if needed) */
165 168
  169 + int halted; /* TRUE if the CPU is in suspend state */
  170 +
166 CPU_COMMON 171 CPU_COMMON
167 }; 172 };
168 173
@@ -202,15 +207,15 @@ enum { @@ -202,15 +207,15 @@ enum {
202 EXCP_IBE, 207 EXCP_IBE,
203 EXCP_DBp, 208 EXCP_DBp,
204 EXCP_SYSCALL, 209 EXCP_SYSCALL,
205 - EXCP_BREAK,  
206 - EXCP_CpU, /* 16 */ 210 + EXCP_BREAK, /* 16 */
  211 + EXCP_CpU,
207 EXCP_RI, 212 EXCP_RI,
208 EXCP_OVERFLOW, 213 EXCP_OVERFLOW,
209 EXCP_TRAP, 214 EXCP_TRAP,
210 EXCP_DDBS, 215 EXCP_DDBS,
211 EXCP_DWATCH, 216 EXCP_DWATCH,
212 - EXCP_LAE, /* 22 */  
213 - EXCP_SAE, 217 + EXCP_LAE,
  218 + EXCP_SAE, /* 24 */
214 EXCP_LTLBL, 219 EXCP_LTLBL,
215 EXCP_TLBL, 220 EXCP_TLBL,
216 EXCP_TLBS, 221 EXCP_TLBS,
target-mips/exec.h
@@ -65,19 +65,19 @@ void do_tlbwi (void); @@ -65,19 +65,19 @@ void do_tlbwi (void);
65 void do_tlbwr (void); 65 void do_tlbwr (void);
66 void do_tlbp (void); 66 void do_tlbp (void);
67 void do_tlbr (void); 67 void do_tlbr (void);
68 -void do_lwl_raw (void);  
69 -void do_lwr_raw (void);  
70 -void do_swl_raw (void);  
71 -void do_swr_raw (void); 68 +void do_lwl_raw (uint32_t);
  69 +void do_lwr_raw (uint32_t);
  70 +uint32_t do_swl_raw (uint32_t);
  71 +uint32_t do_swr_raw (uint32_t);
72 #if !defined(CONFIG_USER_ONLY) 72 #if !defined(CONFIG_USER_ONLY)
73 -void do_lwl_user (void);  
74 -void do_lwl_kernel (void);  
75 -void do_lwr_user (void);  
76 -void do_lwr_kernel (void);  
77 -void do_swl_user (void);  
78 -void do_swl_kernel (void);  
79 -void do_swr_user (void);  
80 -void do_swr_kernel (void); 73 +void do_lwl_user (uint32_t);
  74 +void do_lwl_kernel (uint32_t);
  75 +void do_lwr_user (uint32_t);
  76 +void do_lwr_kernel (uint32_t);
  77 +uint32_t do_swl_user (uint32_t);
  78 +uint32_t do_swl_kernel (uint32_t);
  79 +uint32_t do_swr_user (uint32_t);
  80 +uint32_t do_swr_kernel (uint32_t);
81 #endif 81 #endif
82 void do_pmon (int function); 82 void do_pmon (int function);
83 83
@@ -88,6 +88,7 @@ void do_interrupt (CPUState *env); @@ -88,6 +88,7 @@ void do_interrupt (CPUState *env);
88 void cpu_loop_exit(void); 88 void cpu_loop_exit(void);
89 void do_raise_exception_err (uint32_t exception, int error_code); 89 void do_raise_exception_err (uint32_t exception, int error_code);
90 void do_raise_exception (uint32_t exception); 90 void do_raise_exception (uint32_t exception);
  91 +void do_raise_exception_direct (uint32_t exception);
91 92
92 void cpu_dump_state(CPUState *env, FILE *f, 93 void cpu_dump_state(CPUState *env, FILE *f,
93 int (*cpu_fprintf)(FILE *f, const char *fmt, ...), 94 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
target-mips/helper.c
@@ -46,7 +46,7 @@ static int map_address (CPUState *env, target_ulong *physical, int *prot, @@ -46,7 +46,7 @@ static int map_address (CPUState *env, target_ulong *physical, int *prot,
46 tlb = &env->tlb[i]; 46 tlb = &env->tlb[i];
47 /* Check ASID, virtual page number & size */ 47 /* Check ASID, virtual page number & size */
48 if ((tlb->G == 1 || tlb->ASID == ASID) && 48 if ((tlb->G == 1 || tlb->ASID == ASID) &&
49 - tlb->VPN == tag && address < tlb->end) { 49 + tlb->VPN == tag && address < tlb->end2) {
50 /* TLB match */ 50 /* TLB match */
51 n = (address >> 12) & 1; 51 n = (address >> 12) & 1;
52 /* Check access rights */ 52 /* Check access rights */
@@ -167,10 +167,15 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, @@ -167,10 +167,15 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
167 int ret = 0; 167 int ret = 0;
168 168
169 if (logfile) { 169 if (logfile) {
  170 +#if 0
170 cpu_dump_state(env, logfile, fprintf, 0); 171 cpu_dump_state(env, logfile, fprintf, 0);
  172 +#endif
171 fprintf(logfile, "%s pc %08x ad %08x rw %d is_user %d smmu %d\n", 173 fprintf(logfile, "%s pc %08x ad %08x rw %d is_user %d smmu %d\n",
172 __func__, env->PC, address, rw, is_user, is_softmmu); 174 __func__, env->PC, address, rw, is_user, is_softmmu);
173 } 175 }
  176 +
  177 + rw &= 1;
  178 +
174 /* data access */ 179 /* data access */
175 /* XXX: put correct access by using cpu_restore_state() 180 /* XXX: put correct access by using cpu_restore_state()
176 correctly */ 181 correctly */
@@ -226,7 +231,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, @@ -226,7 +231,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
226 /* Raise exception */ 231 /* Raise exception */
227 env->CP0_BadVAddr = address; 232 env->CP0_BadVAddr = address;
228 env->CP0_Context = (env->CP0_Context & 0xff800000) | 233 env->CP0_Context = (env->CP0_Context & 0xff800000) |
229 - ((address >> 8) & 0x007ffff0); 234 + ((address >> 9) & 0x007ffff0);
230 env->CP0_EntryHi = 235 env->CP0_EntryHi =
231 (env->CP0_EntryHi & 0x000000FF) | (address & 0xFFFFF000); 236 (env->CP0_EntryHi & 0x000000FF) | (address & 0xFFFFF000);
232 env->exception_index = exception; 237 env->exception_index = exception;
@@ -276,11 +281,12 @@ void do_interrupt (CPUState *env) @@ -276,11 +281,12 @@ void do_interrupt (CPUState *env)
276 env->CP0_Debug |= 1 << CP0DB_DDBL; 281 env->CP0_Debug |= 1 << CP0DB_DDBL;
277 goto set_DEPC; 282 goto set_DEPC;
278 set_DEPC: 283 set_DEPC:
279 - if (env->hflags & MIPS_HFLAG_DS) { 284 + if (env->hflags & MIPS_HFLAG_BMASK) {
280 /* If the exception was raised from a delay slot, 285 /* If the exception was raised from a delay slot,
281 * come back to the jump 286 * come back to the jump
282 */ 287 */
283 env->CP0_DEPC = env->PC - 4; 288 env->CP0_DEPC = env->PC - 4;
  289 + env->hflags &= ~MIPS_HFLAG_BMASK;
284 } else { 290 } else {
285 env->CP0_DEPC = env->PC; 291 env->CP0_DEPC = env->PC;
286 } 292 }
@@ -316,8 +322,7 @@ void do_interrupt (CPUState *env) @@ -316,8 +322,7 @@ void do_interrupt (CPUState *env)
316 env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) | 322 env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
317 (1 << CP0St_NMI); 323 (1 << CP0St_NMI);
318 set_error_EPC: 324 set_error_EPC:
319 - env->hflags = MIPS_HFLAG_ERL;  
320 - if (env->hflags & MIPS_HFLAG_DS) { 325 + if (env->hflags & MIPS_HFLAG_BMASK) {
321 /* If the exception was raised from a delay slot, 326 /* If the exception was raised from a delay slot,
322 * come back to the jump 327 * come back to the jump
323 */ 328 */
@@ -325,6 +330,7 @@ void do_interrupt (CPUState *env) @@ -325,6 +330,7 @@ void do_interrupt (CPUState *env)
325 } else { 330 } else {
326 env->CP0_ErrorEPC = env->PC; 331 env->CP0_ErrorEPC = env->PC;
327 } 332 }
  333 + env->hflags = MIPS_HFLAG_ERL;
328 pc = 0xBFC00000; 334 pc = 0xBFC00000;
329 break; 335 break;
330 case EXCP_MCHECK: 336 case EXCP_MCHECK:
@@ -366,7 +372,7 @@ void do_interrupt (CPUState *env) @@ -366,7 +372,7 @@ void do_interrupt (CPUState *env)
366 goto set_EPC; 372 goto set_EPC;
367 case EXCP_CpU: 373 case EXCP_CpU:
368 cause = 11; 374 cause = 11;
369 - /* XXX: fill in the faulty unit number */ 375 + env->CP0_Cause = (env->CP0_Cause & ~0x03000000) | (env->error_code << 28);
370 goto set_EPC; 376 goto set_EPC;
371 case EXCP_OVERFLOW: 377 case EXCP_OVERFLOW:
372 cause = 12; 378 cause = 12;
@@ -391,12 +397,13 @@ void do_interrupt (CPUState *env) @@ -391,12 +397,13 @@ void do_interrupt (CPUState *env)
391 env->hflags |= MIPS_HFLAG_EXL; 397 env->hflags |= MIPS_HFLAG_EXL;
392 pc += offset; 398 pc += offset;
393 env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2); 399 env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
394 - if (env->hflags & MIPS_HFLAG_DS) { 400 + if (env->hflags & MIPS_HFLAG_BMASK) {
395 /* If the exception was raised from a delay slot, 401 /* If the exception was raised from a delay slot,
396 * come back to the jump 402 * come back to the jump
397 */ 403 */
398 env->CP0_EPC = env->PC - 4; 404 env->CP0_EPC = env->PC - 4;
399 env->CP0_Cause |= 0x80000000; 405 env->CP0_Cause |= 0x80000000;
  406 + env->hflags &= ~MIPS_HFLAG_BMASK;
400 } else { 407 } else {
401 env->CP0_EPC = env->PC; 408 env->CP0_EPC = env->PC;
402 env->CP0_Cause &= ~0x80000000; 409 env->CP0_Cause &= ~0x80000000;
target-mips/op.c
@@ -207,7 +207,7 @@ void op_addo (void) @@ -207,7 +207,7 @@ void op_addo (void)
207 tmp = T0; 207 tmp = T0;
208 T0 += T1; 208 T0 += T1;
209 if ((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31)) { 209 if ((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31)) {
210 - CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW); 210 + CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
211 } 211 }
212 RETURN(); 212 RETURN();
213 } 213 }
@@ -225,7 +225,7 @@ void op_subo (void) @@ -225,7 +225,7 @@ void op_subo (void)
225 tmp = T0; 225 tmp = T0;
226 T0 = (int32_t)T0 - (int32_t)T1; 226 T0 = (int32_t)T0 - (int32_t)T1;
227 if (!((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31))) { 227 if (!((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31))) {
228 - CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW); 228 + CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
229 } 229 }
230 RETURN(); 230 RETURN();
231 } 231 }
@@ -364,7 +364,7 @@ static inline void set_HILO (uint64_t HILO) @@ -364,7 +364,7 @@ static inline void set_HILO (uint64_t HILO)
364 364
365 void op_mult (void) 365 void op_mult (void)
366 { 366 {
367 - set_HILO((int64_t)T0 * (int64_t)T1); 367 + set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
368 RETURN(); 368 RETURN();
369 } 369 }
370 370
@@ -378,7 +378,7 @@ void op_madd (void) @@ -378,7 +378,7 @@ void op_madd (void)
378 { 378 {
379 int64_t tmp; 379 int64_t tmp;
380 380
381 - tmp = ((int64_t)T0 * (int64_t)T1); 381 + tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
382 set_HILO((int64_t)get_HILO() + tmp); 382 set_HILO((int64_t)get_HILO() + tmp);
383 RETURN(); 383 RETURN();
384 } 384 }
@@ -396,7 +396,7 @@ void op_msub (void) @@ -396,7 +396,7 @@ void op_msub (void)
396 { 396 {
397 int64_t tmp; 397 int64_t tmp;
398 398
399 - tmp = ((int64_t)T0 * (int64_t)T1); 399 + tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
400 set_HILO((int64_t)get_HILO() - tmp); 400 set_HILO((int64_t)get_HILO() - tmp);
401 RETURN(); 401 RETURN();
402 } 402 }
@@ -595,11 +595,16 @@ void op_pmon (void) @@ -595,11 +595,16 @@ void op_pmon (void)
595 void op_trap (void) 595 void op_trap (void)
596 { 596 {
597 if (T0) { 597 if (T0) {
598 - CALL_FROM_TB1(do_raise_exception, EXCP_TRAP); 598 + CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
599 } 599 }
600 RETURN(); 600 RETURN();
601 } 601 }
602 602
  603 +void op_debug (void)
  604 +{
  605 + CALL_FROM_TB1(do_raise_exception_direct, EXCP_DEBUG);
  606 +}
  607 +
603 void op_set_lladdr (void) 608 void op_set_lladdr (void)
604 { 609 {
605 env->CP0_LLAddr = T2; 610 env->CP0_LLAddr = T2;
@@ -654,3 +659,8 @@ void op_exit_tb (void) @@ -654,3 +659,8 @@ void op_exit_tb (void)
654 EXIT_TB(); 659 EXIT_TB();
655 } 660 }
656 661
  662 +void op_wait (void)
  663 +{
  664 + env->halted = 1;
  665 + CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
  666 +}
target-mips/op_helper.c
@@ -22,6 +22,8 @@ @@ -22,6 +22,8 @@
22 22
23 #define MIPS_DEBUG_DISAS 23 #define MIPS_DEBUG_DISAS
24 24
  25 +#define GETPC() (__builtin_return_address(0))
  26 +
25 /*****************************************************************************/ 27 /*****************************************************************************/
26 /* Exceptions processing helpers */ 28 /* Exceptions processing helpers */
27 void cpu_loop_exit(void) 29 void cpu_loop_exit(void)
@@ -46,6 +48,21 @@ void do_raise_exception (uint32_t exception) @@ -46,6 +48,21 @@ void do_raise_exception (uint32_t exception)
46 do_raise_exception_err(exception, 0); 48 do_raise_exception_err(exception, 0);
47 } 49 }
48 50
  51 +void do_restore_state (void *pc_ptr)
  52 +{
  53 + TranslationBlock *tb;
  54 + unsigned long pc = (unsigned long) pc_ptr;
  55 +
  56 + tb = tb_find_pc (pc);
  57 + cpu_restore_state (tb, env, pc, NULL);
  58 +}
  59 +
  60 +void do_raise_exception_direct (uint32_t exception)
  61 +{
  62 + do_restore_state (GETPC ());
  63 + do_raise_exception_err (exception, 0);
  64 +}
  65 +
49 #define MEMSUFFIX _raw 66 #define MEMSUFFIX _raw
50 #include "op_helper_mem.c" 67 #include "op_helper_mem.c"
51 #undef MEMSUFFIX 68 #undef MEMSUFFIX
@@ -73,7 +90,7 @@ static inline void set_HILO (uint64_t HILO) @@ -73,7 +90,7 @@ static inline void set_HILO (uint64_t HILO)
73 90
74 void do_mult (void) 91 void do_mult (void)
75 { 92 {
76 - set_HILO((int64_t)T0 * (int64_t)T1); 93 + set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
77 } 94 }
78 95
79 void do_multu (void) 96 void do_multu (void)
@@ -85,7 +102,7 @@ void do_madd (void) @@ -85,7 +102,7 @@ void do_madd (void)
85 { 102 {
86 int64_t tmp; 103 int64_t tmp;
87 104
88 - tmp = ((int64_t)T0 * (int64_t)T1); 105 + tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
89 set_HILO((int64_t)get_HILO() + tmp); 106 set_HILO((int64_t)get_HILO() + tmp);
90 } 107 }
91 108
@@ -101,7 +118,7 @@ void do_msub (void) @@ -101,7 +118,7 @@ void do_msub (void)
101 { 118 {
102 int64_t tmp; 119 int64_t tmp;
103 120
104 - tmp = ((int64_t)T0 * (int64_t)T1); 121 + tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
105 set_HILO((int64_t)get_HILO() - tmp); 122 set_HILO((int64_t)get_HILO() - tmp);
106 } 123 }
107 124
@@ -353,6 +370,9 @@ void do_mtc0 (int reg, int sel) @@ -353,6 +370,9 @@ void do_mtc0 (int reg, int sel)
353 val = T0 & 0xFFFFF0FF; 370 val = T0 & 0xFFFFF0FF;
354 old = env->CP0_EntryHi; 371 old = env->CP0_EntryHi;
355 env->CP0_EntryHi = val; 372 env->CP0_EntryHi = val;
  373 + /* If the ASID changes, flush qemu's TLB. */
  374 + if ((old & 0xFF) != (val & 0xFF))
  375 + tlb_flush (env, 1);
356 rn = "EntryHi"; 376 rn = "EntryHi";
357 break; 377 break;
358 case 11: 378 case 11:
@@ -525,11 +545,25 @@ static void invalidate_tb (int idx) @@ -525,11 +545,25 @@ static void invalidate_tb (int idx)
525 addr = tlb->PFN[0]; 545 addr = tlb->PFN[0];
526 end = addr + (tlb->end - tlb->VPN); 546 end = addr + (tlb->end - tlb->VPN);
527 tb_invalidate_page_range(addr, end); 547 tb_invalidate_page_range(addr, end);
  548 + /* FIXME: Might be faster to just invalidate the whole "tlb" here
  549 + and refill it on demand from our simulated TLB. */
  550 + addr = tlb->VPN;
  551 + while (addr < tlb->end) {
  552 + tlb_flush_page (env, addr);
  553 + addr += TARGET_PAGE_SIZE;
  554 + }
528 } 555 }
529 if (tlb->V[1]) { 556 if (tlb->V[1]) {
530 addr = tlb->PFN[1]; 557 addr = tlb->PFN[1];
531 end = addr + (tlb->end - tlb->VPN); 558 end = addr + (tlb->end - tlb->VPN);
532 tb_invalidate_page_range(addr, end); 559 tb_invalidate_page_range(addr, end);
  560 + /* FIXME: Might be faster to just invalidate the whole "tlb" here
  561 + and refill it on demand from our simulated TLB. */
  562 + addr = tlb->end;
  563 + while (addr < tlb->end2) {
  564 + tlb_flush_page (env, addr);
  565 + addr += TARGET_PAGE_SIZE;
  566 + }
533 } 567 }
534 } 568 }
535 569
@@ -545,6 +579,7 @@ static void fill_tb (int idx) @@ -545,6 +579,7 @@ static void fill_tb (int idx)
545 size = env->CP0_PageMask >> 13; 579 size = env->CP0_PageMask >> 13;
546 size = 4 * (size + 1); 580 size = 4 * (size + 1);
547 tlb->end = tlb->VPN + (1 << (8 + size)); 581 tlb->end = tlb->VPN + (1 << (8 + size));
  582 + tlb->end2 = tlb->end + (1 << (8 + size));
548 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; 583 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
549 tlb->V[0] = env->CP0_EntryLo0 & 2; 584 tlb->V[0] = env->CP0_EntryLo0 & 2;
550 tlb->D[0] = env->CP0_EntryLo0 & 4; 585 tlb->D[0] = env->CP0_EntryLo0 & 4;
@@ -601,6 +636,12 @@ void do_tlbr (void) @@ -601,6 +636,12 @@ void do_tlbr (void)
601 int size; 636 int size;
602 637
603 tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)]; 638 tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
  639 +
  640 + /* If this will change the current ASID, flush qemu's TLB. */
  641 + /* FIXME: Could avoid flushing things which match global entries... */
  642 + if ((env->CP0_EntryHi & 0xFF) != tlb->ASID)
  643 + tlb_flush (env, 1);
  644 +
604 env->CP0_EntryHi = tlb->VPN | tlb->ASID; 645 env->CP0_EntryHi = tlb->VPN | tlb->ASID;
605 size = (tlb->end - tlb->VPN) >> 12; 646 size = (tlb->end - tlb->VPN) >> 12;
606 env->CP0_PageMask = (size - 1) << 13; 647 env->CP0_PageMask = (size - 1) << 13;
@@ -664,8 +705,10 @@ void do_pmon (int function) @@ -664,8 +705,10 @@ void do_pmon (int function)
664 705
665 #if !defined(CONFIG_USER_ONLY) 706 #if !defined(CONFIG_USER_ONLY)
666 707
  708 +static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
  709 +
667 #define MMUSUFFIX _mmu 710 #define MMUSUFFIX _mmu
668 -#define GETPC() (__builtin_return_address(0)) 711 +#define ALIGNED_ONLY
669 712
670 #define SHIFT 0 713 #define SHIFT 0
671 #include "softmmu_template.h" 714 #include "softmmu_template.h"
@@ -679,6 +722,13 @@ void do_pmon (int function) @@ -679,6 +722,13 @@ void do_pmon (int function)
679 #define SHIFT 3 722 #define SHIFT 3
680 #include "softmmu_template.h" 723 #include "softmmu_template.h"
681 724
  725 +static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
  726 +{
  727 + env->CP0_BadVAddr = addr;
  728 + do_restore_state (retaddr);
  729 + do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
  730 +}
  731 +
682 void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) 732 void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
683 { 733 {
684 TranslationBlock *tb; 734 TranslationBlock *tb;
target-mips/op_helper_mem.c
1 -void glue(do_lwl, MEMSUFFIX) (void) 1 +void glue(do_lwl, MEMSUFFIX) (uint32_t tmp)
2 { 2 {
3 #if defined (DEBUG_OP) 3 #if defined (DEBUG_OP)
4 target_ulong sav = T0; 4 target_ulong sav = T0;
5 #endif 5 #endif
6 - uint32_t tmp;  
7 6
8 - tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);  
9 /* XXX: this is valid only in big-endian mode 7 /* XXX: this is valid only in big-endian mode
10 * should be reverted for little-endian... 8 * should be reverted for little-endian...
11 */ 9 */
@@ -32,14 +30,12 @@ void glue(do_lwl, MEMSUFFIX) (void) @@ -32,14 +30,12 @@ void glue(do_lwl, MEMSUFFIX) (void)
32 RETURN(); 30 RETURN();
33 } 31 }
34 32
35 -void glue(do_lwr, MEMSUFFIX) (void) 33 +void glue(do_lwr, MEMSUFFIX) (uint32_t tmp)
36 { 34 {
37 #if defined (DEBUG_OP) 35 #if defined (DEBUG_OP)
38 target_ulong sav = T0; 36 target_ulong sav = T0;
39 #endif 37 #endif
40 - uint32_t tmp;  
41 38
42 - tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);  
43 /* XXX: this is valid only in big-endian mode 39 /* XXX: this is valid only in big-endian mode
44 * should be reverted for little-endian... 40 * should be reverted for little-endian...
45 */ 41 */
@@ -66,14 +62,12 @@ void glue(do_lwr, MEMSUFFIX) (void) @@ -66,14 +62,12 @@ void glue(do_lwr, MEMSUFFIX) (void)
66 RETURN(); 62 RETURN();
67 } 63 }
68 64
69 -void glue(do_swl, MEMSUFFIX) (void) 65 +uint32_t glue(do_swl, MEMSUFFIX) (uint32_t tmp)
70 { 66 {
71 #if defined (DEBUG_OP) 67 #if defined (DEBUG_OP)
72 target_ulong sav; 68 target_ulong sav;
73 #endif 69 #endif
74 - uint32_t tmp;  
75 70
76 - tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);  
77 #if defined (DEBUG_OP) 71 #if defined (DEBUG_OP)
78 sav = tmp; 72 sav = tmp;
79 #endif 73 #endif
@@ -94,7 +88,6 @@ void glue(do_swl, MEMSUFFIX) (void) @@ -94,7 +88,6 @@ void glue(do_swl, MEMSUFFIX) (void)
94 tmp = (tmp & 0xFFFFFF00) | (T1 >> 24); 88 tmp = (tmp & 0xFFFFFF00) | (T1 >> 24);
95 break; 89 break;
96 } 90 }
97 - glue(stl, MEMSUFFIX)(T0 & ~3, tmp);  
98 #if defined (DEBUG_OP) 91 #if defined (DEBUG_OP)
99 if (logfile) { 92 if (logfile) {
100 fprintf(logfile, "%s: %08x - %08x %08x => %08x\n", 93 fprintf(logfile, "%s: %08x - %08x %08x => %08x\n",
@@ -102,16 +95,15 @@ void glue(do_swl, MEMSUFFIX) (void) @@ -102,16 +95,15 @@ void glue(do_swl, MEMSUFFIX) (void)
102 } 95 }
103 #endif 96 #endif
104 RETURN(); 97 RETURN();
  98 + return tmp;
105 } 99 }
106 100
107 -void glue(do_swr, MEMSUFFIX) (void) 101 +uint32_t glue(do_swr, MEMSUFFIX) (uint32_t tmp)
108 { 102 {
109 #if defined (DEBUG_OP) 103 #if defined (DEBUG_OP)
110 target_ulong sav; 104 target_ulong sav;
111 #endif 105 #endif
112 - uint32_t tmp;  
113 106
114 - tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);  
115 #if defined (DEBUG_OP) 107 #if defined (DEBUG_OP)
116 sav = tmp; 108 sav = tmp;
117 #endif 109 #endif
@@ -132,7 +124,6 @@ void glue(do_swr, MEMSUFFIX) (void) @@ -132,7 +124,6 @@ void glue(do_swr, MEMSUFFIX) (void)
132 tmp = T1; 124 tmp = T1;
133 break; 125 break;
134 } 126 }
135 - glue(stl, MEMSUFFIX)(T0 & ~3, tmp);  
136 #if defined (DEBUG_OP) 127 #if defined (DEBUG_OP)
137 if (logfile) { 128 if (logfile) {
138 fprintf(logfile, "%s: %08x - %08x %08x => %08x\n", 129 fprintf(logfile, "%s: %08x - %08x %08x => %08x\n",
@@ -140,4 +131,5 @@ void glue(do_swr, MEMSUFFIX) (void) @@ -140,4 +131,5 @@ void glue(do_swr, MEMSUFFIX) (void)
140 } 131 }
141 #endif 132 #endif
142 RETURN(); 133 RETURN();
  134 + return tmp;
143 } 135 }
target-mips/op_mem.c
@@ -67,28 +67,35 @@ void glue(op_sw, MEMSUFFIX) (void) @@ -67,28 +67,35 @@ void glue(op_sw, MEMSUFFIX) (void)
67 RETURN(); 67 RETURN();
68 } 68 }
69 69
70 -/* "half" load and stores */ 70 +/* "half" load and stores. We must do the memory access inline,
  71 + or fault handling won't work. */
71 void glue(op_lwl, MEMSUFFIX) (void) 72 void glue(op_lwl, MEMSUFFIX) (void)
72 { 73 {
73 - CALL_FROM_TB0(glue(do_lwl, MEMSUFFIX)); 74 + uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
  75 + CALL_FROM_TB1(glue(do_lwl, MEMSUFFIX), tmp);
74 RETURN(); 76 RETURN();
75 } 77 }
76 78
77 void glue(op_lwr, MEMSUFFIX) (void) 79 void glue(op_lwr, MEMSUFFIX) (void)
78 { 80 {
79 - CALL_FROM_TB0(glue(do_lwr, MEMSUFFIX)); 81 + uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
  82 + CALL_FROM_TB1(glue(do_lwr, MEMSUFFIX), tmp);
80 RETURN(); 83 RETURN();
81 } 84 }
82 85
83 void glue(op_swl, MEMSUFFIX) (void) 86 void glue(op_swl, MEMSUFFIX) (void)
84 { 87 {
85 - CALL_FROM_TB0(glue(do_swl, MEMSUFFIX)); 88 + uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
  89 + tmp = CALL_FROM_TB1(glue(do_swl, MEMSUFFIX), tmp);
  90 + glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
86 RETURN(); 91 RETURN();
87 } 92 }
88 93
89 void glue(op_swr, MEMSUFFIX) (void) 94 void glue(op_swr, MEMSUFFIX) (void)
90 { 95 {
91 - CALL_FROM_TB0(glue(do_swr, MEMSUFFIX)); 96 + uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
  97 + tmp = CALL_FROM_TB1(glue(do_swr, MEMSUFFIX), tmp);
  98 + glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
92 RETURN(); 99 RETURN();
93 } 100 }
94 101
target-mips/translate.c
@@ -338,17 +338,25 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) @@ -338,17 +338,25 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
338 } 338 }
339 } 339 }
340 340
341 -static inline void generate_exception (DisasContext *ctx, int excp) 341 +static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
342 { 342 {
343 #if defined MIPS_DEBUG_DISAS 343 #if defined MIPS_DEBUG_DISAS
344 if (loglevel & CPU_LOG_TB_IN_ASM) 344 if (loglevel & CPU_LOG_TB_IN_ASM)
345 fprintf(logfile, "%s: raise exception %d\n", __func__, excp); 345 fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
346 #endif 346 #endif
347 save_cpu_state(ctx, 1); 347 save_cpu_state(ctx, 1);
348 - gen_op_raise_exception(excp); 348 + if (err == 0)
  349 + gen_op_raise_exception(excp);
  350 + else
  351 + gen_op_raise_exception_err(excp, err);
349 ctx->bstate = BS_EXCP; 352 ctx->bstate = BS_EXCP;
350 } 353 }
351 354
  355 +static inline void generate_exception (DisasContext *ctx, int excp)
  356 +{
  357 + generate_exception_err (ctx, excp, 0);
  358 +}
  359 +
352 #if defined(CONFIG_USER_ONLY) 360 #if defined(CONFIG_USER_ONLY)
353 #define op_ldst(name) gen_op_##name##_raw() 361 #define op_ldst(name) gen_op_##name##_raw()
354 #define OP_LD_TABLE(width) 362 #define OP_LD_TABLE(width)
@@ -1020,14 +1028,14 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, @@ -1020,14 +1028,14 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1020 case OPC_BLEZ: /* 0 <= 0 */ 1028 case OPC_BLEZ: /* 0 <= 0 */
1021 case OPC_BLEZL: /* 0 <= 0 likely */ 1029 case OPC_BLEZL: /* 0 <= 0 likely */
1022 /* Always take */ 1030 /* Always take */
1023 - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; 1031 + ctx->hflags |= MIPS_HFLAG_B;
1024 MIPS_DEBUG("balways"); 1032 MIPS_DEBUG("balways");
1025 break; 1033 break;
1026 case OPC_BGEZAL: /* 0 >= 0 */ 1034 case OPC_BGEZAL: /* 0 >= 0 */
1027 case OPC_BGEZALL: /* 0 >= 0 likely */ 1035 case OPC_BGEZALL: /* 0 >= 0 likely */
1028 /* Always take and link */ 1036 /* Always take and link */
1029 blink = 31; 1037 blink = 31;
1030 - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; 1038 + ctx->hflags |= MIPS_HFLAG_B;
1031 MIPS_DEBUG("balways and link"); 1039 MIPS_DEBUG("balways and link");
1032 break; 1040 break;
1033 case OPC_BNE: /* rx != rx */ 1041 case OPC_BNE: /* rx != rx */
@@ -1053,21 +1061,21 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, @@ -1053,21 +1061,21 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1053 gen_goto_tb(ctx, 0, ctx->pc + 4); 1061 gen_goto_tb(ctx, 0, ctx->pc + 4);
1054 return; 1062 return;
1055 case OPC_J: 1063 case OPC_J:
1056 - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; 1064 + ctx->hflags |= MIPS_HFLAG_B;
1057 MIPS_DEBUG("j %08x", btarget); 1065 MIPS_DEBUG("j %08x", btarget);
1058 break; 1066 break;
1059 case OPC_JAL: 1067 case OPC_JAL:
1060 blink = 31; 1068 blink = 31;
1061 - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; 1069 + ctx->hflags |= MIPS_HFLAG_B;
1062 MIPS_DEBUG("jal %08x", btarget); 1070 MIPS_DEBUG("jal %08x", btarget);
1063 break; 1071 break;
1064 case OPC_JR: 1072 case OPC_JR:
1065 - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR; 1073 + ctx->hflags |= MIPS_HFLAG_BR;
1066 MIPS_DEBUG("jr %s", regnames[rs]); 1074 MIPS_DEBUG("jr %s", regnames[rs]);
1067 break; 1075 break;
1068 case OPC_JALR: 1076 case OPC_JALR:
1069 blink = rt; 1077 blink = rt;
1070 - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR; 1078 + ctx->hflags |= MIPS_HFLAG_BR;
1071 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]); 1079 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1072 break; 1080 break;
1073 default: 1081 default:
@@ -1144,14 +1152,14 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, @@ -1144,14 +1152,14 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1144 blink = 31; 1152 blink = 31;
1145 MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget); 1153 MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1146 not_likely: 1154 not_likely:
1147 - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BC; 1155 + ctx->hflags |= MIPS_HFLAG_BC;
1148 break; 1156 break;
1149 case OPC_BLTZALL: 1157 case OPC_BLTZALL:
1150 gen_op_ltz(); 1158 gen_op_ltz();
1151 blink = 31; 1159 blink = 31;
1152 MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget); 1160 MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1153 likely: 1161 likely:
1154 - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BL; 1162 + ctx->hflags |= MIPS_HFLAG_BL;
1155 break; 1163 break;
1156 } 1164 }
1157 gen_op_set_bcond(); 1165 gen_op_set_bcond();
@@ -1178,7 +1186,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) @@ -1178,7 +1186,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1178 if (loglevel & CPU_LOG_TB_IN_ASM) { 1186 if (loglevel & CPU_LOG_TB_IN_ASM) {
1179 fprintf(logfile, "CP0 is not usable\n"); 1187 fprintf(logfile, "CP0 is not usable\n");
1180 } 1188 }
1181 - gen_op_raise_exception_err(EXCP_CpU, 0); 1189 + generate_exception_err (ctx, EXCP_CpU, 0);
1182 return; 1190 return;
1183 } 1191 }
1184 switch (opc) { 1192 switch (opc) {
@@ -1236,7 +1244,15 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) @@ -1236,7 +1244,15 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1236 ctx->bstate = BS_EXCP; 1244 ctx->bstate = BS_EXCP;
1237 } 1245 }
1238 break; 1246 break;
1239 - /* XXX: TODO: WAIT */ 1247 + case OPC_WAIT:
  1248 + opn = "wait";
  1249 + /* If we get an exception, we want to restart at next instruction */
  1250 + ctx->pc += 4;
  1251 + save_cpu_state(ctx, 1);
  1252 + ctx->pc -= 4;
  1253 + gen_op_wait();
  1254 + ctx->bstate = BS_EXCP;
  1255 + break;
1240 default: 1256 default:
1241 if (loglevel & CPU_LOG_TB_IN_ASM) { 1257 if (loglevel & CPU_LOG_TB_IN_ASM) {
1242 fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n", 1258 fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
@@ -1292,7 +1308,7 @@ static void gen_blikely(DisasContext *ctx) @@ -1292,7 +1308,7 @@ static void gen_blikely(DisasContext *ctx)
1292 int l1; 1308 int l1;
1293 l1 = gen_new_label(); 1309 l1 = gen_new_label();
1294 gen_op_jnz_T2(l1); 1310 gen_op_jnz_T2(l1);
1295 - gen_op_save_state(ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS)); 1311 + gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
1296 gen_goto_tb(ctx, 1, ctx->pc + 4); 1312 gen_goto_tb(ctx, 1, ctx->pc + 4);
1297 gen_set_label(l1); 1313 gen_set_label(l1);
1298 } 1314 }
@@ -1304,8 +1320,7 @@ static void decode_opc (DisasContext *ctx) @@ -1304,8 +1320,7 @@ static void decode_opc (DisasContext *ctx)
1304 uint16_t op, op1; 1320 uint16_t op, op1;
1305 int16_t imm; 1321 int16_t imm;
1306 1322
1307 - if ((ctx->hflags & MIPS_HFLAG_DS) &&  
1308 - (ctx->hflags & MIPS_HFLAG_BL)) { 1323 + if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
1309 /* Handle blikely not taken case */ 1324 /* Handle blikely not taken case */
1310 MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4); 1325 MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
1311 gen_blikely(ctx); 1326 gen_blikely(ctx);
@@ -1361,9 +1376,16 @@ static void decode_opc (DisasContext *ctx) @@ -1361,9 +1376,16 @@ static void decode_opc (DisasContext *ctx)
1361 case 0x05: /* Pmon entry point */ 1376 case 0x05: /* Pmon entry point */
1362 gen_op_pmon((ctx->opcode >> 6) & 0x1F); 1377 gen_op_pmon((ctx->opcode >> 6) & 0x1F);
1363 break; 1378 break;
1364 -#if defined (MIPS_HAS_MOVCI) 1379 +
1365 case 0x01: /* MOVCI */ 1380 case 0x01: /* MOVCI */
  1381 +#if defined (MIPS_HAS_MOVCI)
  1382 + /* XXX */
  1383 +#else
  1384 + /* Not implemented */
  1385 + generate_exception_err (ctx, EXCP_CpU, 1);
1366 #endif 1386 #endif
  1387 + break;
  1388 +
1367 #if defined (TARGET_MIPS64) 1389 #if defined (TARGET_MIPS64)
1368 case 0x14: /* MIPS64 specific opcodes */ 1390 case 0x14: /* MIPS64 specific opcodes */
1369 case 0x16: 1391 case 0x16:
@@ -1438,7 +1460,7 @@ static void decode_opc (DisasContext *ctx) @@ -1438,7 +1460,7 @@ static void decode_opc (DisasContext *ctx)
1438 gen_cp0(ctx, op1 | EXT_CP0, rt, rd); 1460 gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
1439 break; 1461 break;
1440 default: 1462 default:
1441 - gen_cp0(ctx, (ctx->opcode & 0x1F) | EXT_CP0, rt, rd); 1463 + gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd);
1442 break; 1464 break;
1443 } 1465 }
1444 break; 1466 break;
@@ -1467,23 +1489,35 @@ static void decode_opc (DisasContext *ctx) @@ -1467,23 +1489,35 @@ static void decode_opc (DisasContext *ctx)
1467 break; 1489 break;
1468 case 0x3F: /* HACK */ 1490 case 0x3F: /* HACK */
1469 break; 1491 break;
  1492 +
  1493 + /* Floating point. */
  1494 + case 0x31: /* LWC1 */
  1495 + case 0x35: /* LDC1 */
  1496 + case 0x39: /* SWC1 */
  1497 + case 0x3D: /* SDC1 */
  1498 + case 0x11: /* CP1 opcode */
1470 #if defined(MIPS_USES_FPU) 1499 #if defined(MIPS_USES_FPU)
1471 - case 0x31 ... 0x32: /* Floating point load/store */  
1472 - case 0x35 ... 0x36:  
1473 - case 0x3A ... 0x3B:  
1474 - case 0x3D ... 0x3E:  
1475 - /* Not implemented */  
1476 /* XXX: not correct */ 1500 /* XXX: not correct */
  1501 +#else
  1502 + generate_exception_err(ctx, EXCP_CpU, 1);
1477 #endif 1503 #endif
1478 - case 0x11: /* CP1 opcode */  
1479 - /* Not implemented */  
1480 - /* XXX: not correct */ 1504 + break;
  1505 +
  1506 + /* COP2. */
  1507 + case 0x32: /* LWC2 */
  1508 + case 0x36: /* LDC2 */
  1509 + case 0x3A: /* SWC2 */
  1510 + case 0x3E: /* SDC2 */
1481 case 0x12: /* CP2 opcode */ 1511 case 0x12: /* CP2 opcode */
1482 /* Not implemented */ 1512 /* Not implemented */
1483 - /* XXX: not correct */ 1513 + generate_exception_err(ctx, EXCP_CpU, 2);
  1514 + break;
  1515 +
1484 case 0x13: /* CP3 opcode */ 1516 case 0x13: /* CP3 opcode */
1485 /* Not implemented */ 1517 /* Not implemented */
1486 - /* XXX: not correct */ 1518 + generate_exception_err(ctx, EXCP_CpU, 3);
  1519 + break;
  1520 +
1487 #if defined (TARGET_MIPS64) 1521 #if defined (TARGET_MIPS64)
1488 case 0x18 ... 0x1B: 1522 case 0x18 ... 0x1B:
1489 case 0x27: 1523 case 0x27:
@@ -1497,21 +1531,15 @@ static void decode_opc (DisasContext *ctx) @@ -1497,21 +1531,15 @@ static void decode_opc (DisasContext *ctx)
1497 #endif 1531 #endif
1498 case 0x1E: 1532 case 0x1E:
1499 /* ASE specific */ 1533 /* ASE specific */
1500 -#if defined (MIPS_HAS_LSC)  
1501 - case 0x31: /* LWC1 */  
1502 - case 0x32: /* LWC2 */  
1503 - case 0x35: /* SDC1 */  
1504 - case 0x36: /* SDC2 */  
1505 -#endif  
1506 default: /* Invalid */ 1534 default: /* Invalid */
1507 MIPS_INVAL(""); 1535 MIPS_INVAL("");
1508 generate_exception(ctx, EXCP_RI); 1536 generate_exception(ctx, EXCP_RI);
1509 break; 1537 break;
1510 } 1538 }
1511 - if (ctx->hflags & MIPS_HFLAG_DS) { 1539 + if (ctx->hflags & MIPS_HFLAG_BMASK) {
1512 int hflags = ctx->hflags; 1540 int hflags = ctx->hflags;
1513 /* Branches completion */ 1541 /* Branches completion */
1514 - ctx->hflags &= ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS); 1542 + ctx->hflags &= ~MIPS_HFLAG_BMASK;
1515 ctx->bstate = BS_BRANCH; 1543 ctx->bstate = BS_BRANCH;
1516 save_cpu_state(ctx, 0); 1544 save_cpu_state(ctx, 0);
1517 switch (hflags & MIPS_HFLAG_BMASK) { 1545 switch (hflags & MIPS_HFLAG_BMASK) {
@@ -1557,16 +1585,20 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -1557,16 +1585,20 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
1557 uint16_t *gen_opc_end; 1585 uint16_t *gen_opc_end;
1558 int j, lj = -1; 1586 int j, lj = -1;
1559 1587
  1588 + if (search_pc && loglevel)
  1589 + fprintf (logfile, "search pc %d\n", search_pc);
  1590 +
1560 pc_start = tb->pc; 1591 pc_start = tb->pc;
1561 gen_opc_ptr = gen_opc_buf; 1592 gen_opc_ptr = gen_opc_buf;
1562 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 1593 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1563 gen_opparam_ptr = gen_opparam_buf; 1594 gen_opparam_ptr = gen_opparam_buf;
1564 nb_gen_labels = 0; 1595 nb_gen_labels = 0;
1565 ctx.pc = pc_start; 1596 ctx.pc = pc_start;
  1597 + ctx.saved_pc = -1;
1566 ctx.tb = tb; 1598 ctx.tb = tb;
1567 ctx.bstate = BS_NONE; 1599 ctx.bstate = BS_NONE;
1568 - /* Restore delay slot state */  
1569 - ctx.hflags = env->hflags; 1600 + /* Restore delay slot state from the tb context. */
  1601 + ctx.hflags = tb->flags;
1570 ctx.saved_hflags = ctx.hflags; 1602 ctx.saved_hflags = ctx.hflags;
1571 if (ctx.hflags & MIPS_HFLAG_BR) { 1603 if (ctx.hflags & MIPS_HFLAG_BR) {
1572 gen_op_restore_breg_target(); 1604 gen_op_restore_breg_target();
@@ -1588,42 +1620,65 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -1588,42 +1620,65 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
1588 #ifdef DEBUG_DISAS 1620 #ifdef DEBUG_DISAS
1589 if (loglevel & CPU_LOG_TB_CPU) { 1621 if (loglevel & CPU_LOG_TB_CPU) {
1590 fprintf(logfile, "------------------------------------------------\n"); 1622 fprintf(logfile, "------------------------------------------------\n");
  1623 + /* FIXME: This may print out stale hflags from env... */
1591 cpu_dump_state(env, logfile, fprintf, 0); 1624 cpu_dump_state(env, logfile, fprintf, 0);
1592 } 1625 }
1593 #endif 1626 #endif
1594 #if defined MIPS_DEBUG_DISAS 1627 #if defined MIPS_DEBUG_DISAS
1595 if (loglevel & CPU_LOG_TB_IN_ASM) 1628 if (loglevel & CPU_LOG_TB_IN_ASM)
1596 - fprintf(logfile, "\ntb %p super %d cond %04x %04x\n",  
1597 - tb, ctx.mem_idx, ctx.hflags, env->hflags); 1629 + fprintf(logfile, "\ntb %p super %d cond %04x\n",
  1630 + tb, ctx.mem_idx, ctx.hflags);
1598 #endif 1631 #endif
1599 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { 1632 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
  1633 + if (env->nb_breakpoints > 0) {
  1634 + for(j = 0; j < env->nb_breakpoints; j++) {
  1635 + if (env->breakpoints[j] == ctx.pc) {
  1636 + save_cpu_state(ctxp, 1);
  1637 + ctx.bstate = BS_BRANCH;
  1638 + gen_op_debug();
  1639 + goto done_generating;
  1640 + }
  1641 + }
  1642 + }
  1643 +
1600 if (search_pc) { 1644 if (search_pc) {
1601 j = gen_opc_ptr - gen_opc_buf; 1645 j = gen_opc_ptr - gen_opc_buf;
1602 - save_cpu_state(ctxp, 1);  
1603 if (lj < j) { 1646 if (lj < j) {
1604 lj++; 1647 lj++;
1605 while (lj < j) 1648 while (lj < j)
1606 gen_opc_instr_start[lj++] = 0; 1649 gen_opc_instr_start[lj++] = 0;
1607 - gen_opc_pc[lj] = ctx.pc;  
1608 - gen_opc_instr_start[lj] = 1;  
1609 } 1650 }
  1651 + gen_opc_pc[lj] = ctx.pc;
  1652 + gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
  1653 + gen_opc_instr_start[lj] = 1;
1610 } 1654 }
1611 ctx.opcode = ldl_code(ctx.pc); 1655 ctx.opcode = ldl_code(ctx.pc);
1612 decode_opc(&ctx); 1656 decode_opc(&ctx);
1613 ctx.pc += 4; 1657 ctx.pc += 4;
  1658 +
  1659 + if (env->singlestep_enabled)
  1660 + break;
  1661 +
1614 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) 1662 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1615 break; 1663 break;
  1664 +
1616 #if defined (MIPS_SINGLE_STEP) 1665 #if defined (MIPS_SINGLE_STEP)
1617 break; 1666 break;
1618 #endif 1667 #endif
1619 } 1668 }
1620 - if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) { 1669 + if (env->singlestep_enabled) {
  1670 + save_cpu_state(ctxp, ctx.bstate == BS_NONE);
  1671 + gen_op_debug();
  1672 + goto done_generating;
  1673 + }
  1674 + else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
1621 save_cpu_state(ctxp, 0); 1675 save_cpu_state(ctxp, 0);
1622 gen_goto_tb(&ctx, 0, ctx.pc); 1676 gen_goto_tb(&ctx, 0, ctx.pc);
1623 } 1677 }
1624 gen_op_reset_T0(); 1678 gen_op_reset_T0();
1625 /* Generate the return instruction */ 1679 /* Generate the return instruction */
1626 gen_op_exit_tb(); 1680 gen_op_exit_tb();
  1681 +done_generating:
1627 *gen_opc_ptr = INDEX_op_end; 1682 *gen_opc_ptr = INDEX_op_end;
1628 if (search_pc) { 1683 if (search_pc) {
1629 j = gen_opc_ptr - gen_opc_buf; 1684 j = gen_opc_ptr - gen_opc_buf;