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 +20,15 @@ void cpu_mips_update_irq(CPUState *env)
20 20
21 void cpu_mips_irq_request(void *opaque, int irq, int level) 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 return; 26 return;
29 27
30 - mask = 1 << (irq + CP0Ca_IP);  
31 -  
32 if (level) { 28 if (level) {
33 - env->CP0_Cause |= mask; 29 + env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
34 } else { 30 } else {
35 - env->CP0_Cause &= ~mask; 31 + env->CP0_Cause &= ~(1 << (irq +CP0Ca_IP));
36 } 32 }
37 cpu_mips_update_irq(env); 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,6 +28,9 @@ static void cpu_mips_update_count (CPUState *env, uint32_t count,
28 uint64_t now, next; 28 uint64_t now, next;
29 uint32_t tmp; 29 uint32_t tmp;
30 30
  31 + if (env->CP0_Cause & (1 << CP0Ca_DC))
  32 + return;
  33 +
31 tmp = count; 34 tmp = count;
32 if (count == compare) 35 if (count == compare)
33 tmp++; 36 tmp++;
@@ -57,6 +60,8 @@ void cpu_mips_store_count (CPUState *env, uint32_t value) @@ -57,6 +60,8 @@ void cpu_mips_store_count (CPUState *env, uint32_t value)
57 void cpu_mips_store_compare (CPUState *env, uint32_t value) 60 void cpu_mips_store_compare (CPUState *env, uint32_t value)
58 { 61 {
59 cpu_mips_update_count(env, cpu_mips_get_count(env), value); 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 cpu_mips_irq_request(env, 7, 0); 65 cpu_mips_irq_request(env, 7, 0);
61 } 66 }
62 67
@@ -71,6 +76,8 @@ static void mips_timer_cb (void *opaque) @@ -71,6 +76,8 @@ static void mips_timer_cb (void *opaque)
71 } 76 }
72 #endif 77 #endif
73 cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare); 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 cpu_mips_irq_request(env, 7, 1); 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,9 +295,12 @@ void do_interrupt (CPUState *env)
295 /* If the exception was raised from a delay slot, 295 /* If the exception was raised from a delay slot,
296 come back to the jump. */ 296 come back to the jump. */
297 env->CP0_DEPC = env->PC - 4; 297 env->CP0_DEPC = env->PC - 4;
  298 + if (!(env->hflags & MIPS_HFLAG_EXL))
  299 + env->CP0_Cause |= (1 << CP0Ca_BD);
298 env->hflags &= ~MIPS_HFLAG_BMASK; 300 env->hflags &= ~MIPS_HFLAG_BMASK;
299 } else { 301 } else {
300 env->CP0_DEPC = env->PC; 302 env->CP0_DEPC = env->PC;
  303 + env->CP0_Cause &= ~(1 << CP0Ca_BD);
301 } 304 }
302 enter_debug_mode: 305 enter_debug_mode:
303 env->hflags |= MIPS_HFLAG_DM; 306 env->hflags |= MIPS_HFLAG_DM;
@@ -318,9 +321,12 @@ void do_interrupt (CPUState *env) @@ -318,9 +321,12 @@ void do_interrupt (CPUState *env)
318 /* If the exception was raised from a delay slot, 321 /* If the exception was raised from a delay slot,
319 come back to the jump. */ 322 come back to the jump. */
320 env->CP0_ErrorEPC = env->PC - 4; 323 env->CP0_ErrorEPC = env->PC - 4;
  324 + if (!(env->hflags & MIPS_HFLAG_EXL))
  325 + env->CP0_Cause |= (1 << CP0Ca_BD);
321 env->hflags &= ~MIPS_HFLAG_BMASK; 326 env->hflags &= ~MIPS_HFLAG_BMASK;
322 } else { 327 } else {
323 env->CP0_ErrorEPC = env->PC; 328 env->CP0_ErrorEPC = env->PC;
  329 + env->CP0_Cause &= ~(1 << CP0Ca_BD);
324 } 330 }
325 env->hflags |= MIPS_HFLAG_ERL; 331 env->hflags |= MIPS_HFLAG_ERL;
326 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); 332 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
@@ -364,7 +370,8 @@ void do_interrupt (CPUState *env) @@ -364,7 +370,8 @@ void do_interrupt (CPUState *env)
364 goto set_EPC; 370 goto set_EPC;
365 case EXCP_CpU: 371 case EXCP_CpU:
366 cause = 11; 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 goto set_EPC; 375 goto set_EPC;
369 case EXCP_OVERFLOW: 376 case EXCP_OVERFLOW:
370 cause = 12; 377 cause = 12;
@@ -385,11 +392,12 @@ void do_interrupt (CPUState *env) @@ -385,11 +392,12 @@ void do_interrupt (CPUState *env)
385 /* If the exception was raised from a delay slot, 392 /* If the exception was raised from a delay slot,
386 come back to the jump. */ 393 come back to the jump. */
387 env->CP0_EPC = env->PC - 4; 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 env->hflags &= ~MIPS_HFLAG_BMASK; 397 env->hflags &= ~MIPS_HFLAG_BMASK;
390 } else { 398 } else {
391 env->CP0_EPC = env->PC; 399 env->CP0_EPC = env->PC;
392 - env->CP0_Cause &= ~0x80000000; 400 + env->CP0_Cause &= ~(1 << CP0Ca_BD);
393 } 401 }
394 if (env->CP0_Status & (1 << CP0St_BEV)) { 402 if (env->CP0_Status & (1 << CP0St_BEV)) {
395 env->PC = (int32_t)0xBFC00200; 403 env->PC = (int32_t)0xBFC00200;
target-mips/op.c
@@ -1397,7 +1397,12 @@ void op_mtc0_srsmap (void) @@ -1397,7 +1397,12 @@ void op_mtc0_srsmap (void)
1397 1397
1398 void op_mtc0_cause (void) 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 /* Handle the software interrupt as an hardware one, as they 1407 /* Handle the software interrupt as an hardware one, as they
1403 are very similar */ 1408 are very similar */