Commit 39d51eb8bcc603c02342d8f5e1f7a569e5f17e06

Authored by ths
1 parent 36f69651

Fix BD flag handling, cause register contents, implement some more bits

for R2 interrupt handling.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2493 c046a42c-6fe2-441c-8c8c-71466251a162
hw/mips_int.c
... ... @@ -20,20 +20,15 @@ void cpu_mips_update_irq(CPUState *env)
20 20  
21 21 void cpu_mips_irq_request(void *opaque, int irq, int level)
22 22 {
23   - CPUState *env = first_cpu;
24   -
25   - uint32_t mask;
  23 + CPUState *env = (CPUState *)opaque;
26 24  
27   - if (irq >= 16)
  25 + if (irq < 0 || irq > 7)
28 26 return;
29 27  
30   - mask = 1 << (irq + CP0Ca_IP);
31   -
32 28 if (level) {
33   - env->CP0_Cause |= mask;
  29 + env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
34 30 } else {
35   - env->CP0_Cause &= ~mask;
  31 + env->CP0_Cause &= ~(1 << (irq +CP0Ca_IP));
36 32 }
37 33 cpu_mips_update_irq(env);
38 34 }
39   -
... ...
hw/mips_timer.c
... ... @@ -28,6 +28,9 @@ static void cpu_mips_update_count (CPUState *env, uint32_t count,
28 28 uint64_t now, next;
29 29 uint32_t tmp;
30 30  
  31 + if (env->CP0_Cause & (1 << CP0Ca_DC))
  32 + return;
  33 +
31 34 tmp = count;
32 35 if (count == compare)
33 36 tmp++;
... ... @@ -57,6 +60,8 @@ void cpu_mips_store_count (CPUState *env, uint32_t value)
57 60 void cpu_mips_store_compare (CPUState *env, uint32_t value)
58 61 {
59 62 cpu_mips_update_count(env, cpu_mips_get_count(env), value);
  63 + if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
  64 + env->CP0_Cause &= ~(1 << CP0Ca_TI);
60 65 cpu_mips_irq_request(env, 7, 0);
61 66 }
62 67  
... ... @@ -71,6 +76,8 @@ static void mips_timer_cb (void *opaque)
71 76 }
72 77 #endif
73 78 cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
  79 + if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
  80 + env->CP0_Cause |= 1 << CP0Ca_TI;
74 81 cpu_mips_irq_request(env, 7, 1);
75 82 }
76 83  
... ...
target-mips/helper.c
... ... @@ -295,9 +295,12 @@ void do_interrupt (CPUState *env)
295 295 /* If the exception was raised from a delay slot,
296 296 come back to the jump. */
297 297 env->CP0_DEPC = env->PC - 4;
  298 + if (!(env->hflags & MIPS_HFLAG_EXL))
  299 + env->CP0_Cause |= (1 << CP0Ca_BD);
298 300 env->hflags &= ~MIPS_HFLAG_BMASK;
299 301 } else {
300 302 env->CP0_DEPC = env->PC;
  303 + env->CP0_Cause &= ~(1 << CP0Ca_BD);
301 304 }
302 305 enter_debug_mode:
303 306 env->hflags |= MIPS_HFLAG_DM;
... ... @@ -318,9 +321,12 @@ void do_interrupt (CPUState *env)
318 321 /* If the exception was raised from a delay slot,
319 322 come back to the jump. */
320 323 env->CP0_ErrorEPC = env->PC - 4;
  324 + if (!(env->hflags & MIPS_HFLAG_EXL))
  325 + env->CP0_Cause |= (1 << CP0Ca_BD);
321 326 env->hflags &= ~MIPS_HFLAG_BMASK;
322 327 } else {
323 328 env->CP0_ErrorEPC = env->PC;
  329 + env->CP0_Cause &= ~(1 << CP0Ca_BD);
324 330 }
325 331 env->hflags |= MIPS_HFLAG_ERL;
326 332 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
... ... @@ -364,7 +370,8 @@ void do_interrupt (CPUState *env)
364 370 goto set_EPC;
365 371 case EXCP_CpU:
366 372 cause = 11;
367   - env->CP0_Cause = (env->CP0_Cause & ~0x03000000) | (env->error_code << 28);
  373 + env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
  374 + (env->error_code << CP0Ca_CE);
368 375 goto set_EPC;
369 376 case EXCP_OVERFLOW:
370 377 cause = 12;
... ... @@ -385,11 +392,12 @@ void do_interrupt (CPUState *env)
385 392 /* If the exception was raised from a delay slot,
386 393 come back to the jump. */
387 394 env->CP0_EPC = env->PC - 4;
388   - env->CP0_Cause |= 0x80000000;
  395 + if (!(env->hflags & MIPS_HFLAG_EXL))
  396 + env->CP0_Cause |= (1 << CP0Ca_BD);
389 397 env->hflags &= ~MIPS_HFLAG_BMASK;
390 398 } else {
391 399 env->CP0_EPC = env->PC;
392   - env->CP0_Cause &= ~0x80000000;
  400 + env->CP0_Cause &= ~(1 << CP0Ca_BD);
393 401 }
394 402 if (env->CP0_Status & (1 << CP0St_BEV)) {
395 403 env->PC = (int32_t)0xBFC00200;
... ...
target-mips/op.c
... ... @@ -1397,7 +1397,12 @@ void op_mtc0_srsmap (void)
1397 1397  
1398 1398 void op_mtc0_cause (void)
1399 1399 {
1400   - env->CP0_Cause = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
  1400 + uint32_t mask = 0x00C00300;
  1401 +
  1402 + if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
  1403 + mask |= 1 << CP0Ca_DC;
  1404 +
  1405 + env->CP0_Cause = (env->CP0_Cause & 0xFCC0FF7C) | (T0 & mask);
1401 1406  
1402 1407 /* Handle the software interrupt as an hardware one, as they
1403 1408 are very similar */
... ...