aboutsummaryrefslogtreecommitdiff
path: root/target-mips/helper.c
diff options
context:
space:
mode:
authorEdgar E. Iglesias <edgar@axis.com>2010-08-06 12:21:16 +0200
committerEdgar E. Iglesias <edgar.iglesias@gmail.com>2010-08-06 12:21:16 +0200
commit138afb024bbd115553a344e06d93011a283d1316 (patch)
treeebd809dcf604b85e3099678522c1e43890c4394b /target-mips/helper.c
parentd087bb3e38fbb705ae65c55457b9ef3e0a5d2511 (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.c27
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;