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