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 +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 */ |