diff options
Diffstat (limited to 'target-mips/helper.c')
-rw-r--r-- | target-mips/helper.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/target-mips/helper.c b/target-mips/helper.c index de2ed7d2c7..bdc1e53669 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -478,6 +478,33 @@ void do_interrupt (CPUState *env) cause = 0; if (env->CP0_Cause & (1 << CP0Ca_IV)) offset = 0x200; + + if (env->CP0_Config3 & ((1 << CP0C3_VInt) | (1 << CP0C3_VEIC))) { + /* Vectored Interrupts. */ + unsigned int spacing; + unsigned int vector; + unsigned int pending = (env->CP0_Cause & CP0Ca_IP_mask) >> 8; + + /* Compute the Vector Spacing. */ + spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & ((1 << 6) - 1); + spacing <<= 5; + + if (env->CP0_Config3 & (1 << CP0C3_VInt)) { + /* For VInt mode, the MIPS computes the vector internally. */ + for (vector = 0; vector < 8; vector++) { + if (pending & 1) { + /* Found it. */ + break; + } + pending >>= 1; + } + } else { + /* For VEIC mode, the external interrupt controller feeds the + vector throught the CP0Cause IP lines. */ + vector = pending; + } + offset = 0x200 + vector * spacing; + } goto set_EPC; case EXCP_LTLBL: cause = 1; |