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