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 1 #if !defined (__MIPS_CPU_H__)
2 2 #define __MIPS_CPU_H__
3 3  
  4 +#define TARGET_HAS_ICE 1
  5 +
4 6 #include "mips-defs.h"
5 7 #include "cpu-defs.h"
6 8 #include "config.h"
... ... @@ -18,6 +20,7 @@ typedef struct tlb_t tlb_t;
18 20 struct tlb_t {
19 21 target_ulong VPN;
20 22 target_ulong end;
  23 + target_ulong end2;
21 24 uint8_t ASID;
22 25 uint8_t G;
23 26 uint8_t C[2];
... ... @@ -151,18 +154,20 @@ struct CPUMIPSState {
151 154 #define MIPS_HFLAG_DM 0x0008 /* Debug mode */
152 155 #define MIPS_HFLAG_SM 0x0010 /* Supervisor mode */
153 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 166 target_ulong btarget; /* Jump / branch target */
164 167 int bcond; /* Branch condition (if needed) */
165 168  
  169 + int halted; /* TRUE if the CPU is in suspend state */
  170 +
166 171 CPU_COMMON
167 172 };
168 173  
... ... @@ -202,15 +207,15 @@ enum {
202 207 EXCP_IBE,
203 208 EXCP_DBp,
204 209 EXCP_SYSCALL,
205   - EXCP_BREAK,
206   - EXCP_CpU, /* 16 */
  210 + EXCP_BREAK, /* 16 */
  211 + EXCP_CpU,
207 212 EXCP_RI,
208 213 EXCP_OVERFLOW,
209 214 EXCP_TRAP,
210 215 EXCP_DDBS,
211 216 EXCP_DWATCH,
212   - EXCP_LAE, /* 22 */
213   - EXCP_SAE,
  217 + EXCP_LAE,
  218 + EXCP_SAE, /* 24 */
214 219 EXCP_LTLBL,
215 220 EXCP_TLBL,
216 221 EXCP_TLBS,
... ...
target-mips/exec.h
... ... @@ -65,19 +65,19 @@ void do_tlbwi (void);
65 65 void do_tlbwr (void);
66 66 void do_tlbp (void);
67 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 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 81 #endif
82 82 void do_pmon (int function);
83 83  
... ... @@ -88,6 +88,7 @@ void do_interrupt (CPUState *env);
88 88 void cpu_loop_exit(void);
89 89 void do_raise_exception_err (uint32_t exception, int error_code);
90 90 void do_raise_exception (uint32_t exception);
  91 +void do_raise_exception_direct (uint32_t exception);
91 92  
92 93 void cpu_dump_state(CPUState *env, FILE *f,
93 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 46 tlb = &env->tlb[i];
47 47 /* Check ASID, virtual page number & size */
48 48 if ((tlb->G == 1 || tlb->ASID == ASID) &&
49   - tlb->VPN == tag && address < tlb->end) {
  49 + tlb->VPN == tag && address < tlb->end2) {
50 50 /* TLB match */
51 51 n = (address >> 12) & 1;
52 52 /* Check access rights */
... ... @@ -167,10 +167,15 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
167 167 int ret = 0;
168 168  
169 169 if (logfile) {
  170 +#if 0
170 171 cpu_dump_state(env, logfile, fprintf, 0);
  172 +#endif
171 173 fprintf(logfile, "%s pc %08x ad %08x rw %d is_user %d smmu %d\n",
172 174 __func__, env->PC, address, rw, is_user, is_softmmu);
173 175 }
  176 +
  177 + rw &= 1;
  178 +
174 179 /* data access */
175 180 /* XXX: put correct access by using cpu_restore_state()
176 181 correctly */
... ... @@ -226,7 +231,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
226 231 /* Raise exception */
227 232 env->CP0_BadVAddr = address;
228 233 env->CP0_Context = (env->CP0_Context & 0xff800000) |
229   - ((address >> 8) & 0x007ffff0);
  234 + ((address >> 9) & 0x007ffff0);
230 235 env->CP0_EntryHi =
231 236 (env->CP0_EntryHi & 0x000000FF) | (address & 0xFFFFF000);
232 237 env->exception_index = exception;
... ... @@ -276,11 +281,12 @@ void do_interrupt (CPUState *env)
276 281 env->CP0_Debug |= 1 << CP0DB_DDBL;
277 282 goto set_DEPC;
278 283 set_DEPC:
279   - if (env->hflags & MIPS_HFLAG_DS) {
  284 + if (env->hflags & MIPS_HFLAG_BMASK) {
280 285 /* If the exception was raised from a delay slot,
281 286 * come back to the jump
282 287 */
283 288 env->CP0_DEPC = env->PC - 4;
  289 + env->hflags &= ~MIPS_HFLAG_BMASK;
284 290 } else {
285 291 env->CP0_DEPC = env->PC;
286 292 }
... ... @@ -316,8 +322,7 @@ void do_interrupt (CPUState *env)
316 322 env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
317 323 (1 << CP0St_NMI);
318 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 326 /* If the exception was raised from a delay slot,
322 327 * come back to the jump
323 328 */
... ... @@ -325,6 +330,7 @@ void do_interrupt (CPUState *env)
325 330 } else {
326 331 env->CP0_ErrorEPC = env->PC;
327 332 }
  333 + env->hflags = MIPS_HFLAG_ERL;
328 334 pc = 0xBFC00000;
329 335 break;
330 336 case EXCP_MCHECK:
... ... @@ -366,7 +372,7 @@ void do_interrupt (CPUState *env)
366 372 goto set_EPC;
367 373 case EXCP_CpU:
368 374 cause = 11;
369   - /* XXX: fill in the faulty unit number */
  375 + env->CP0_Cause = (env->CP0_Cause & ~0x03000000) | (env->error_code << 28);
370 376 goto set_EPC;
371 377 case EXCP_OVERFLOW:
372 378 cause = 12;
... ... @@ -391,12 +397,13 @@ void do_interrupt (CPUState *env)
391 397 env->hflags |= MIPS_HFLAG_EXL;
392 398 pc += offset;
393 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 401 /* If the exception was raised from a delay slot,
396 402 * come back to the jump
397 403 */
398 404 env->CP0_EPC = env->PC - 4;
399 405 env->CP0_Cause |= 0x80000000;
  406 + env->hflags &= ~MIPS_HFLAG_BMASK;
400 407 } else {
401 408 env->CP0_EPC = env->PC;
402 409 env->CP0_Cause &= ~0x80000000;
... ...
target-mips/op.c
... ... @@ -207,7 +207,7 @@ void op_addo (void)
207 207 tmp = T0;
208 208 T0 += T1;
209 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 212 RETURN();
213 213 }
... ... @@ -225,7 +225,7 @@ void op_subo (void)
225 225 tmp = T0;
226 226 T0 = (int32_t)T0 - (int32_t)T1;
227 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 230 RETURN();
231 231 }
... ... @@ -364,7 +364,7 @@ static inline void set_HILO (uint64_t HILO)
364 364  
365 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 368 RETURN();
369 369 }
370 370  
... ... @@ -378,7 +378,7 @@ void op_madd (void)
378 378 {
379 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 382 set_HILO((int64_t)get_HILO() + tmp);
383 383 RETURN();
384 384 }
... ... @@ -396,7 +396,7 @@ void op_msub (void)
396 396 {
397 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 400 set_HILO((int64_t)get_HILO() - tmp);
401 401 RETURN();
402 402 }
... ... @@ -595,11 +595,16 @@ void op_pmon (void)
595 595 void op_trap (void)
596 596 {
597 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 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 608 void op_set_lladdr (void)
604 609 {
605 610 env->CP0_LLAddr = T2;
... ... @@ -654,3 +659,8 @@ void op_exit_tb (void)
654 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 22  
23 23 #define MIPS_DEBUG_DISAS
24 24  
  25 +#define GETPC() (__builtin_return_address(0))
  26 +
25 27 /*****************************************************************************/
26 28 /* Exceptions processing helpers */
27 29 void cpu_loop_exit(void)
... ... @@ -46,6 +48,21 @@ void do_raise_exception (uint32_t exception)
46 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 66 #define MEMSUFFIX _raw
50 67 #include "op_helper_mem.c"
51 68 #undef MEMSUFFIX
... ... @@ -73,7 +90,7 @@ static inline void set_HILO (uint64_t HILO)
73 90  
74 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 96 void do_multu (void)
... ... @@ -85,7 +102,7 @@ void do_madd (void)
85 102 {
86 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 106 set_HILO((int64_t)get_HILO() + tmp);
90 107 }
91 108  
... ... @@ -101,7 +118,7 @@ void do_msub (void)
101 118 {
102 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 122 set_HILO((int64_t)get_HILO() - tmp);
106 123 }
107 124  
... ... @@ -353,6 +370,9 @@ void do_mtc0 (int reg, int sel)
353 370 val = T0 & 0xFFFFF0FF;
354 371 old = env->CP0_EntryHi;
355 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 376 rn = "EntryHi";
357 377 break;
358 378 case 11:
... ... @@ -525,11 +545,25 @@ static void invalidate_tb (int idx)
525 545 addr = tlb->PFN[0];
526 546 end = addr + (tlb->end - tlb->VPN);
527 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 556 if (tlb->V[1]) {
530 557 addr = tlb->PFN[1];
531 558 end = addr + (tlb->end - tlb->VPN);
532 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 579 size = env->CP0_PageMask >> 13;
546 580 size = 4 * (size + 1);
547 581 tlb->end = tlb->VPN + (1 << (8 + size));
  582 + tlb->end2 = tlb->end + (1 << (8 + size));
548 583 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
549 584 tlb->V[0] = env->CP0_EntryLo0 & 2;
550 585 tlb->D[0] = env->CP0_EntryLo0 & 4;
... ... @@ -601,6 +636,12 @@ void do_tlbr (void)
601 636 int size;
602 637  
603 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 645 env->CP0_EntryHi = tlb->VPN | tlb->ASID;
605 646 size = (tlb->end - tlb->VPN) >> 12;
606 647 env->CP0_PageMask = (size - 1) << 13;
... ... @@ -664,8 +705,10 @@ void do_pmon (int function)
664 705  
665 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 710 #define MMUSUFFIX _mmu
668   -#define GETPC() (__builtin_return_address(0))
  711 +#define ALIGNED_ONLY
669 712  
670 713 #define SHIFT 0
671 714 #include "softmmu_template.h"
... ... @@ -679,6 +722,13 @@ void do_pmon (int function)
679 722 #define SHIFT 3
680 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 732 void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
683 733 {
684 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 3 #if defined (DEBUG_OP)
4 4 target_ulong sav = T0;
5 5 #endif
6   - uint32_t tmp;
7 6  
8   - tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
9 7 /* XXX: this is valid only in big-endian mode
10 8 * should be reverted for little-endian...
11 9 */
... ... @@ -32,14 +30,12 @@ void glue(do_lwl, MEMSUFFIX) (void)
32 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 35 #if defined (DEBUG_OP)
38 36 target_ulong sav = T0;
39 37 #endif
40   - uint32_t tmp;
41 38  
42   - tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
43 39 /* XXX: this is valid only in big-endian mode
44 40 * should be reverted for little-endian...
45 41 */
... ... @@ -66,14 +62,12 @@ void glue(do_lwr, MEMSUFFIX) (void)
66 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 67 #if defined (DEBUG_OP)
72 68 target_ulong sav;
73 69 #endif
74   - uint32_t tmp;
75 70  
76   - tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
77 71 #if defined (DEBUG_OP)
78 72 sav = tmp;
79 73 #endif
... ... @@ -94,7 +88,6 @@ void glue(do_swl, MEMSUFFIX) (void)
94 88 tmp = (tmp & 0xFFFFFF00) | (T1 >> 24);
95 89 break;
96 90 }
97   - glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
98 91 #if defined (DEBUG_OP)
99 92 if (logfile) {
100 93 fprintf(logfile, "%s: %08x - %08x %08x => %08x\n",
... ... @@ -102,16 +95,15 @@ void glue(do_swl, MEMSUFFIX) (void)
102 95 }
103 96 #endif
104 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 103 #if defined (DEBUG_OP)
110 104 target_ulong sav;
111 105 #endif
112   - uint32_t tmp;
113 106  
114   - tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
115 107 #if defined (DEBUG_OP)
116 108 sav = tmp;
117 109 #endif
... ... @@ -132,7 +124,6 @@ void glue(do_swr, MEMSUFFIX) (void)
132 124 tmp = T1;
133 125 break;
134 126 }
135   - glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
136 127 #if defined (DEBUG_OP)
137 128 if (logfile) {
138 129 fprintf(logfile, "%s: %08x - %08x %08x => %08x\n",
... ... @@ -140,4 +131,5 @@ void glue(do_swr, MEMSUFFIX) (void)
140 131 }
141 132 #endif
142 133 RETURN();
  134 + return tmp;
143 135 }
... ...
target-mips/op_mem.c
... ... @@ -67,28 +67,35 @@ void glue(op_sw, MEMSUFFIX) (void)
67 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 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 76 RETURN();
75 77 }
76 78  
77 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 83 RETURN();
81 84 }
82 85  
83 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 91 RETURN();
87 92 }
88 93  
89 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 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 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 343 #if defined MIPS_DEBUG_DISAS
344 344 if (loglevel & CPU_LOG_TB_IN_ASM)
345 345 fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
346 346 #endif
347 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 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 360 #if defined(CONFIG_USER_ONLY)
353 361 #define op_ldst(name) gen_op_##name##_raw()
354 362 #define OP_LD_TABLE(width)
... ... @@ -1020,14 +1028,14 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1020 1028 case OPC_BLEZ: /* 0 <= 0 */
1021 1029 case OPC_BLEZL: /* 0 <= 0 likely */
1022 1030 /* Always take */
1023   - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
  1031 + ctx->hflags |= MIPS_HFLAG_B;
1024 1032 MIPS_DEBUG("balways");
1025 1033 break;
1026 1034 case OPC_BGEZAL: /* 0 >= 0 */
1027 1035 case OPC_BGEZALL: /* 0 >= 0 likely */
1028 1036 /* Always take and link */
1029 1037 blink = 31;
1030   - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
  1038 + ctx->hflags |= MIPS_HFLAG_B;
1031 1039 MIPS_DEBUG("balways and link");
1032 1040 break;
1033 1041 case OPC_BNE: /* rx != rx */
... ... @@ -1053,21 +1061,21 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1053 1061 gen_goto_tb(ctx, 0, ctx->pc + 4);
1054 1062 return;
1055 1063 case OPC_J:
1056   - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
  1064 + ctx->hflags |= MIPS_HFLAG_B;
1057 1065 MIPS_DEBUG("j %08x", btarget);
1058 1066 break;
1059 1067 case OPC_JAL:
1060 1068 blink = 31;
1061   - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
  1069 + ctx->hflags |= MIPS_HFLAG_B;
1062 1070 MIPS_DEBUG("jal %08x", btarget);
1063 1071 break;
1064 1072 case OPC_JR:
1065   - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
  1073 + ctx->hflags |= MIPS_HFLAG_BR;
1066 1074 MIPS_DEBUG("jr %s", regnames[rs]);
1067 1075 break;
1068 1076 case OPC_JALR:
1069 1077 blink = rt;
1070   - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
  1078 + ctx->hflags |= MIPS_HFLAG_BR;
1071 1079 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1072 1080 break;
1073 1081 default:
... ... @@ -1144,14 +1152,14 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1144 1152 blink = 31;
1145 1153 MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1146 1154 not_likely:
1147   - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BC;
  1155 + ctx->hflags |= MIPS_HFLAG_BC;
1148 1156 break;
1149 1157 case OPC_BLTZALL:
1150 1158 gen_op_ltz();
1151 1159 blink = 31;
1152 1160 MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1153 1161 likely:
1154   - ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BL;
  1162 + ctx->hflags |= MIPS_HFLAG_BL;
1155 1163 break;
1156 1164 }
1157 1165 gen_op_set_bcond();
... ... @@ -1178,7 +1186,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1178 1186 if (loglevel & CPU_LOG_TB_IN_ASM) {
1179 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 1190 return;
1183 1191 }
1184 1192 switch (opc) {
... ... @@ -1236,7 +1244,15 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1236 1244 ctx->bstate = BS_EXCP;
1237 1245 }
1238 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 1256 default:
1241 1257 if (loglevel & CPU_LOG_TB_IN_ASM) {
1242 1258 fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
... ... @@ -1292,7 +1308,7 @@ static void gen_blikely(DisasContext *ctx)
1292 1308 int l1;
1293 1309 l1 = gen_new_label();
1294 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 1312 gen_goto_tb(ctx, 1, ctx->pc + 4);
1297 1313 gen_set_label(l1);
1298 1314 }
... ... @@ -1304,8 +1320,7 @@ static void decode_opc (DisasContext *ctx)
1304 1320 uint16_t op, op1;
1305 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 1324 /* Handle blikely not taken case */
1310 1325 MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
1311 1326 gen_blikely(ctx);
... ... @@ -1361,9 +1376,16 @@ static void decode_opc (DisasContext *ctx)
1361 1376 case 0x05: /* Pmon entry point */
1362 1377 gen_op_pmon((ctx->opcode >> 6) & 0x1F);
1363 1378 break;
1364   -#if defined (MIPS_HAS_MOVCI)
  1379 +
1365 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 1386 #endif
  1387 + break;
  1388 +
1367 1389 #if defined (TARGET_MIPS64)
1368 1390 case 0x14: /* MIPS64 specific opcodes */
1369 1391 case 0x16:
... ... @@ -1438,7 +1460,7 @@ static void decode_opc (DisasContext *ctx)
1438 1460 gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
1439 1461 break;
1440 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 1464 break;
1443 1465 }
1444 1466 break;
... ... @@ -1467,23 +1489,35 @@ static void decode_opc (DisasContext *ctx)
1467 1489 break;
1468 1490 case 0x3F: /* HACK */
1469 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 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 1500 /* XXX: not correct */
  1501 +#else
  1502 + generate_exception_err(ctx, EXCP_CpU, 1);
1477 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 1511 case 0x12: /* CP2 opcode */
1482 1512 /* Not implemented */
1483   - /* XXX: not correct */
  1513 + generate_exception_err(ctx, EXCP_CpU, 2);
  1514 + break;
  1515 +
1484 1516 case 0x13: /* CP3 opcode */
1485 1517 /* Not implemented */
1486   - /* XXX: not correct */
  1518 + generate_exception_err(ctx, EXCP_CpU, 3);
  1519 + break;
  1520 +
1487 1521 #if defined (TARGET_MIPS64)
1488 1522 case 0x18 ... 0x1B:
1489 1523 case 0x27:
... ... @@ -1497,21 +1531,15 @@ static void decode_opc (DisasContext *ctx)
1497 1531 #endif
1498 1532 case 0x1E:
1499 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 1534 default: /* Invalid */
1507 1535 MIPS_INVAL("");
1508 1536 generate_exception(ctx, EXCP_RI);
1509 1537 break;
1510 1538 }
1511   - if (ctx->hflags & MIPS_HFLAG_DS) {
  1539 + if (ctx->hflags & MIPS_HFLAG_BMASK) {
1512 1540 int hflags = ctx->hflags;
1513 1541 /* Branches completion */
1514   - ctx->hflags &= ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS);
  1542 + ctx->hflags &= ~MIPS_HFLAG_BMASK;
1515 1543 ctx->bstate = BS_BRANCH;
1516 1544 save_cpu_state(ctx, 0);
1517 1545 switch (hflags & MIPS_HFLAG_BMASK) {
... ... @@ -1557,16 +1585,20 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
1557 1585 uint16_t *gen_opc_end;
1558 1586 int j, lj = -1;
1559 1587  
  1588 + if (search_pc && loglevel)
  1589 + fprintf (logfile, "search pc %d\n", search_pc);
  1590 +
1560 1591 pc_start = tb->pc;
1561 1592 gen_opc_ptr = gen_opc_buf;
1562 1593 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1563 1594 gen_opparam_ptr = gen_opparam_buf;
1564 1595 nb_gen_labels = 0;
1565 1596 ctx.pc = pc_start;
  1597 + ctx.saved_pc = -1;
1566 1598 ctx.tb = tb;
1567 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 1602 ctx.saved_hflags = ctx.hflags;
1571 1603 if (ctx.hflags & MIPS_HFLAG_BR) {
1572 1604 gen_op_restore_breg_target();
... ... @@ -1588,42 +1620,65 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
1588 1620 #ifdef DEBUG_DISAS
1589 1621 if (loglevel & CPU_LOG_TB_CPU) {
1590 1622 fprintf(logfile, "------------------------------------------------\n");
  1623 + /* FIXME: This may print out stale hflags from env... */
1591 1624 cpu_dump_state(env, logfile, fprintf, 0);
1592 1625 }
1593 1626 #endif
1594 1627 #if defined MIPS_DEBUG_DISAS
1595 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 1631 #endif
1599 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 1644 if (search_pc) {
1601 1645 j = gen_opc_ptr - gen_opc_buf;
1602   - save_cpu_state(ctxp, 1);
1603 1646 if (lj < j) {
1604 1647 lj++;
1605 1648 while (lj < j)
1606 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 1655 ctx.opcode = ldl_code(ctx.pc);
1612 1656 decode_opc(&ctx);
1613 1657 ctx.pc += 4;
  1658 +
  1659 + if (env->singlestep_enabled)
  1660 + break;
  1661 +
1614 1662 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1615 1663 break;
  1664 +
1616 1665 #if defined (MIPS_SINGLE_STEP)
1617 1666 break;
1618 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 1675 save_cpu_state(ctxp, 0);
1622 1676 gen_goto_tb(&ctx, 0, ctx.pc);
1623 1677 }
1624 1678 gen_op_reset_T0();
1625 1679 /* Generate the return instruction */
1626 1680 gen_op_exit_tb();
  1681 +done_generating:
1627 1682 *gen_opc_ptr = INDEX_op_end;
1628 1683 if (search_pc) {
1629 1684 j = gen_opc_ptr - gen_opc_buf;
... ...