Commit 39d51eb8bcc603c02342d8f5e1f7a569e5f17e06
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
Showing
4 changed files
with
28 additions
and
13 deletions
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 */ | ... | ... |