diff options
author | Edgar E. Iglesias <edgar@axis.com> | 2010-08-06 12:21:16 +0200 |
---|---|---|
committer | Edgar E. Iglesias <edgar.iglesias@gmail.com> | 2010-08-06 12:21:16 +0200 |
commit | 138afb024bbd115553a344e06d93011a283d1316 (patch) | |
tree | ebd809dcf604b85e3099678522c1e43890c4394b /target-mips/helper.c | |
parent | d087bb3e38fbb705ae65c55457b9ef3e0a5d2511 (diff) |
mips: Add support for VInt and VEIC irq modes
Signed-off-by: Edgar E. Iglesias <edgar@axis.com>
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; |