[MIPS] Rewrite all the assembler interrupt handlers to C.

Saves like 1,600 lines of code, is way easier to debug, compilers
frequently do a better job than the cut and paste type of handlers many
boards had.  And finally having all the stuff done in a single place
also means alot of bug potencial for the MT ASE is gone.

The only surviving handler in assembler is the DECstation one; I hope
Maciej will rewrite it.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
index a1edfd1..bf682f5 100644
--- a/arch/mips/au1000/common/Makefile
+++ b/arch/mips/au1000/common/Makefile
@@ -6,7 +6,7 @@
 # Makefile for the Alchemy Au1000 CPU, generic files.
 #
 
-obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \
+obj-y += prom.o irq.o puts.o time.o reset.o \
 	au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
 	sleeper.o cputable.o dma.o dbdma.o gpio.o
 
diff --git a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S
deleted file mode 100644
index 65baa8a..0000000
--- a/arch/mips/au1000/common/int-handler.S
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: ppopov@mvista.com
- *
- * Interrupt dispatcher for Au1000 boards.
- *
- * This program is free software; you can redistribute	it and/or modify it
- * under  the terms of	the GNU General	 Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.set	macro
-	.set	noat
-	.align	5
-
-NESTED(au1000_IRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI				# Important: mark KERNEL mode !
-
-	mfc0	t0,CP0_CAUSE		# get pending interrupts
-	mfc0	t1,CP0_STATUS		# get enabled interrupts
-	and	t0,t1			# isolate allowed ones
-
-	andi	t0,0xff00		# isolate pending bits
-	beqz	t0, 3f			# spurious interrupt
-
-	andi	a0, t0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	move	a0, sp
-	jal	mips_timer_interrupt
-	j	ret_from_irq
-
-1:
-	andi	a0, t0, CAUSEF_IP2	# Interrupt Controller 0, Request 0
-	beq	a0, zero, 2f
-	move	a0,sp
-	jal	intc0_req0_irqdispatch
-	j	ret_from_irq
-2:
-	andi	a0, t0, CAUSEF_IP3	# Interrupt Controller 0, Request 1
-	beq	a0, zero, 3f
-	move	a0,sp
-	jal	intc0_req1_irqdispatch
-	j	ret_from_irq
-3:
-	andi	a0, t0, CAUSEF_IP4	# Interrupt Controller 1, Request 0
-	beq	a0, zero, 4f
-	move	a0,sp
-	jal	intc1_req0_irqdispatch
-	j	ret_from_irq
-4:
-	andi	a0, t0, CAUSEF_IP5	# Interrupt Controller 1, Request 1
-	beq	a0, zero, 5f
-	move	a0, sp
-	jal	intc1_req1_irqdispatch
-	j	ret_from_irq
-
-5:
-	move	a0, sp
-	jal	spurious_interrupt
-	j	ret_from_irq
-END(au1000_IRQ)
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index 1339a09..da61de7 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -66,7 +66,6 @@
 #define EXT_INTC1_REQ1 5 /* IP 5 */
 #define MIPS_TIMER_IP  7 /* IP 7 */
 
-extern asmlinkage void au1000_IRQ(void);
 extern void set_debug_traps(void);
 extern irq_cpustat_t irq_stat [NR_CPUS];
 
@@ -446,7 +445,6 @@
 	extern int au1xxx_ic0_nr_irqs;
 
 	cp0_status = read_c0_status();
-	set_except_vector(0, au1000_IRQ);
 
 	/* Initialize interrupt controllers to a safe state.
 	*/
@@ -661,3 +659,21 @@
 	au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
 }
 #endif /* CONFIG_PM */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+	if (pending & CAUSEF_IP7)
+		mips_timer_interrupt(regs);
+	else if (pending & CAUSEF_IP2)
+		intc0_req0_irqdispatch(regs);
+	else if (pending & CAUSEF_IP3)
+		intc0_req1_irqdispatch(regs);
+	else if (pending & CAUSEF_IP4)
+		intc1_req0_irqdispatch(regs);
+	else if (pending  & CAUSEF_IP5)
+		intc1_req1_irqdispatch(regs);
+	else
+		spurious_interrupt(regs);
+}
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 720e757..225ac8f 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y	 := irq.o int-handler.o reset.o setup.o
+obj-y	 := irq.o reset.o setup.o
 
 obj-$(CONFIG_EARLY_PRINTK)	+= console.o
 
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
deleted file mode 100644
index e75d5e3..0000000
--- a/arch/mips/cobalt/int-handler.S
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
- * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/mach-cobalt/cobalt.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-		.text
-		.align	5
-		NESTED(cobalt_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-
-		PTR_LA	ra, ret_from_irq
-		move	a0, sp
-		j	cobalt_irq
-
-		END(cobalt_handle_int)
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index f9a1088..0b75f4f 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -20,8 +20,6 @@
 
 #include <asm/mach-cobalt/cobalt.h>
 
-extern void cobalt_handle_int(void);
-
 /*
  * We have two types of interrupts that we handle, ones that come in through
  * the CPU interrupt lines, and ones that come in on the via chip. The CPU
@@ -79,7 +77,7 @@
 		do_IRQ(irq, regs);
 }
 
-asmlinkage void cobalt_irq(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	unsigned pending;
 
@@ -122,8 +120,6 @@
 	 */
 	GALILEO_OUTL(0, GT_INTRMASK_OFS);
 
-	set_except_vector(0, cobalt_handle_int);
-
 	init_i8259_irqs();				/*  0 ... 15 */
 	mips_cpu_irq_init(COBALT_CPU_IRQ);		/* 16 ... 23 */
 
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
index 488206b..304c021 100644
--- a/arch/mips/ddb5xxx/ddb5074/Makefile
+++ b/arch/mips/ddb5xxx/ddb5074/Makefile
@@ -3,6 +3,6 @@
 # under Linux.
 #
 
-obj-y			+= setup.o irq.o int-handler.o nile4_pic.o
+obj-y			+= setup.o irq.o nile4_pic.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S
deleted file mode 100644
index a786441..0000000
--- a/arch/mips/ddb5xxx/ddb5074/int-handler.S
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
- *
- *  Based on arch/mips/sgi/kernel/indyIRQ.S
- *
- *  Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        Local IRQ level zero
- *             3        Local IRQ level one
- *             4        8254 Timer zero
- *             5        8254 Timer one
- *             6        Bus Error
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- *                  Local IRQ zero
- *                  Local IRQ one
- *                  Bus Error
- *                  8254 Timer zero
- * Lowest  ----     8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(ddbIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	mfc0	s0, CP0_CAUSE		# get irq mask
-
-#if 1
-	mfc0	t2,CP0_STATUS		# get enabled interrupts
-	and	s0,t2			# isolate allowed ones
-#endif
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one
-
-	/* Wheee, local level zero interrupt. */
-	jal	ddb_local0_irqdispatch
-	 move	a0, sp			# delay slot
-
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error
-
-	/* Wheee, local level one interrupt. */
-	move	a0, sp
-	jal	ddb_local1_irqdispatch
-	 nop
-
-	j	ret_from_irq
-	 nop
-
-1:
-	beq	a0, zero, 1f
-	 nop
-
-	/* Wheee, an asynchronous bus error... */
-	move	a0, sp
-	jal	ddb_buserror_irq
-	 nop
-
-	j	ret_from_irq
-	 nop
-
-1:
-	/* Here by mistake?  This is possible, what can happen
-	 * is that by the time we take the exception the IRQ
-	 * pin goes low, so just leave if this is the case.
-	 */
-	andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
-	beq	a0, zero, 1f
-
-	/* Must be one of the 8254 timers... */
-	move	a0, sp
-	jal	ddb_8254timer_irq
-	 nop
-1:
-	j	ret_from_irq
-	 nop
-	END(ddbIRQ)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
index 45088a1..60c087b 100644
--- a/arch/mips/ddb5xxx/ddb5074/irq.c
+++ b/arch/mips/ddb5xxx/ddb5074/irq.c
@@ -21,8 +21,6 @@
 #include <asm/ddb5xxx/ddb5074.h>
 
 
-extern asmlinkage void ddbIRQ(void);
-
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
 #define M1543_PNP_CONFIG	0x03f0	/* PnP Config Port */
@@ -90,7 +88,7 @@
 
 }
 
-void ddb_local0_irqdispatch(struct pt_regs *regs)
+static void ddb_local0_irqdispatch(struct pt_regs *regs)
 {
 	u32 mask;
 	int nile4_irq;
@@ -118,29 +116,41 @@
 		}
 }
 
-void ddb_local1_irqdispatch(void)
+static void ddb_local1_irqdispatch(void)
 {
 	printk("ddb_local1_irqdispatch called\n");
 }
 
-void ddb_buserror_irq(void)
+static void ddb_buserror_irq(void)
 {
 	printk("ddb_buserror_irq called\n");
 }
 
-void ddb_8254timer_irq(void)
+static void ddb_8254timer_irq(void)
 {
 	printk("ddb_8254timer_irq called\n");
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & CAUSEF_IP2)
+		ddb_local0_irqdispatch(regs);
+	else if (pending & CAUSEF_IP3)
+		ddb_local1_irqdispatch();
+	else if (pending & CAUSEF_IP6)
+		ddb_buserror_irq();
+	else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+		ddb_8254timer_irq();
+}
+
 void __init arch_init_irq(void)
 {
 	/* setup cascade interrupts */
 	setup_irq(NILE4_IRQ_BASE  + NILE4_INT_INTE, &irq_cascade);
 	setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
 
-	set_except_vector(0, ddbIRQ);
-
 	nile4_irq_setup(NILE4_IRQ_BASE);
 	m1543_irq_setup();
 	init_i8259_irqs();
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
index 61eec36..ab0312c 100644
--- a/arch/mips/ddb5xxx/ddb5476/Makefile
+++ b/arch/mips/ddb5xxx/ddb5476/Makefile
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y			+= setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
+obj-y			+= setup.o irq.o nile4_pic.o vrc5476_irq.o
 obj-$(CONFIG_KGDB)	+= dbg_io.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S
deleted file mode 100644
index 0c2bdae..0000000
--- a/arch/mips/ddb5xxx/ddb5476/int-handler.S
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5476
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#include <asm/ddb5xxx/ddb5476.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-	.align	5
-	NESTED(ddb5476_handle_int, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	.set	noreorder
-	mfc0	t0, CP0_CAUSE
-	mfc0	t2, CP0_STATUS
-
-	and	t0, t2
-
-        andi    t1, t0, STATUSF_IP7     /* cpu timer */
-        bnez    t1, ll_cpu_ip7
-        andi    t1, t0, STATUSF_IP2	/* vrc5476 & i8259 */
-        bnez    t1, ll_cpu_ip2
-        andi    t1, t0, STATUSF_IP3
-        bnez    t1, ll_cpu_ip3
-        andi    t1, t0, STATUSF_IP4
-        bnez    t1, ll_cpu_ip4
-        andi    t1, t0, STATUSF_IP5
-        bnez    t1, ll_cpu_ip5
-        andi    t1, t0, STATUSF_IP6
-        bnez    t1, ll_cpu_ip6
-        andi    t1, t0, STATUSF_IP0     /* software int 0 */
-        bnez    t1, ll_cpu_ip0
-        andi    t1, t0, STATUSF_IP1     /* software int 1 */
-        bnez    t1, ll_cpu_ip1
-        nop
-
-	.set	reorder
-
-	/* wrong alarm or masked ... */
-	// jal	spurious_interrupt
-	// j	ret_from_irq
-	move 	a0, sp
-	jal	vrc5476_irq_dispatch
-	j	ret_from_irq
-	nop
-
-	.align	5
-
-ll_cpu_ip0:
-	li	a0, CPU_IRQ_BASE + 0
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip1:
-	li	a0, CPU_IRQ_BASE + 1
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip2:		/* jump to second-level dispatching */
-	move	a0, sp
-	jal	vrc5476_irq_dispatch
-	j	ret_from_irq
-
-ll_cpu_ip3:
-	li	a0, CPU_IRQ_BASE + 3
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip4:
-	li	a0, CPU_IRQ_BASE + 4
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip5:
-	li	a0, CPU_IRQ_BASE + 5
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip6:
-	li	a0, CPU_IRQ_BASE + 6
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip7:
-	li	a0, CPU_IRQ_BASE + 7
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-	END(ddb5476_handle_int)
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
index 5388b58..7583a1f 100644
--- a/arch/mips/ddb5xxx/ddb5476/irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/irq.c
@@ -110,11 +110,36 @@
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
 
-extern asmlinkage void ddb5476_handle_int(void);
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
 extern void mips_cpu_irq_init(u32 irq_base);
 extern void vrc5476_irq_init(u32 irq_base);
 
+extern void vrc5476_irq_dispatch(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(CPU_IRQ_BASE + 7, regs);
+	else if (pending & STATUSF_IP2)
+		vrc5476_irq_dispatch(regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(CPU_IRQ_BASE + 3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(CPU_IRQ_BASE + 4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(CPU_IRQ_BASE + 5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(CPU_IRQ_BASE + 6, regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(CPU_IRQ_BASE, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(CPU_IRQ_BASE + 1, regs);
+
+	vrc5476_irq_dispatch(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	/* hardware initialization */
@@ -137,7 +162,4 @@
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
-
-	/* setup the grandpa intr vector */
-	set_except_vector(0, ddb5476_handle_int);
 }
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
index 581eaba..a3c5e7b 100644
--- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
@@ -77,7 +77,7 @@
 }
 
 
-asmlinkage void
+void
 vrc5476_irq_dispatch(struct pt_regs *regs)
 {
 	u32 mask;
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index b79b43c..ea68815 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,7 @@
 # Makefile for NEC DDB-Vrc5477 board
 #
 
-obj-y	 		+= int-handler.o irq.o irq_5477.o setup.o lcd44780.o
+obj-y	 		+= irq.o irq_5477.o setup.o lcd44780.o
 
 obj-$(CONFIG_RUNTIME_DEBUG) 	+= debug.o
 obj-$(CONFIG_KGDB)		+= kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S
deleted file mode 100644
index 9884874..0000000
--- a/arch/mips/ddb5xxx/ddb5477/int-handler.S
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5477
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/ddb5xxx/ddb5477.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-	.align	5
-	NESTED(ddb5477_handle_int, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	.set	noreorder
-	mfc0	t0, CP0_CAUSE
-	mfc0	t2, CP0_STATUS
-
-	and	t0, t2
-
-	andi	t1, t0, STATUSF_IP7	/* cpu timer */
-	bnez	t1, ll_cputimer_irq
-	andi	t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
-	bnez	t1, ll_vrc5477_irq
-	andi	t1, t0, STATUSF_IP0	/* software int 0 */
-	bnez	t1, ll_cpu_ip0
-	andi	t1, t0, STATUSF_IP1	/* software int 1 */
-	bnez	t1, ll_cpu_ip1
-	nop
-	.set	reorder
-
-	/* wrong alarm or masked ... */
-	jal	spurious_interrupt
-	j	ret_from_irq
-	END(ddb5477_handle_int)
-
-	.align	5
-
-ll_vrc5477_irq:
-	move	a0, sp
-	jal	vrc5477_irq_dispatch
-	j	ret_from_irq
-
-ll_cputimer_irq:
-	li	a0, CPU_IRQ_BASE + 7
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-
-ll_cpu_ip0:
-	li	a0, CPU_IRQ_BASE + 0
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip1:
-	li	a0, CPU_IRQ_BASE + 1
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
index 9ffe1a9..de433cf 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -75,7 +75,6 @@
 
 extern void vrc5477_irq_init(u32 base);
 extern void mips_cpu_irq_init(u32 base);
-extern asmlinkage void ddb5477_handle_int(void);
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
@@ -135,9 +134,6 @@
 	/* setup cascade interrupts */
 	setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
 	setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
-
-	/* hook up the first-level interrupt handler */
-	set_except_vector(0, ddb5477_handle_int);
 }
 
 u8 i8259_interrupt_ack(void)
@@ -159,7 +155,7 @@
  * the first level int-handler will jump here if it is a vrc5477 irq
  */
 #define	NUM_5477_IRQS	32
-asmlinkage void
+static void
 vrc5477_irq_dispatch(struct pt_regs *regs)
 {
 	u32 intStatus;
@@ -197,3 +193,21 @@
 		}
 	}
 }
+
+#define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(CPU_IRQ_BASE + 7, regs);
+	else if (pending & VR5477INTS)
+		vrc5477_irq_dispatch(regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(CPU_IRQ_BASE, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(CPU_IRQ_BASE + 1, regs);
+	else
+		spurious_interrupt(regs);
+}
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 5bafd58..e8ec93e 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -36,7 +36,7 @@
 		.text
 		.set	noreorder
 /*
- * decstation_handle_int: Interrupt handler for DECstations
+ * plat_irq_dispatch: Interrupt handler for DECstations
  *
  * We follow the model in the Indy interrupt code by David Miller, where he
  * says: a lot of complication here is taken away because:
@@ -125,11 +125,7 @@
  * just take another exception, big deal.
  */
 		.align	5
-		NESTED(decstation_handle_int, PT_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI				# TEST: interrupts should be off
-		.set	at
+		NESTED(plat_irq_dispatch, PT_SIZE, ra)
 		.set	noreorder
 
 		/*
@@ -286,7 +282,7 @@
 		 nop
 		j	ret_from_irq
 		 nop
-		END(decstation_handle_int)
+		END(plat_irq_dispatch)
 
 /*
  * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 7c1ca8f..ad5d436 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -48,8 +48,6 @@
 extern void dec_machine_power_off(void);
 extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
 
-extern asmlinkage void decstation_handle_int(void);
-
 unsigned long dec_kn_slot_base, dec_kn_slot_size;
 
 EXPORT_SYMBOL(dec_kn_slot_base);
@@ -744,7 +742,6 @@
 		panic("Don't know how to set this up!");
 		break;
 	}
-	set_except_vector(0, decstation_handle_int);
 
 	/* Free the FPU interrupt if the exception is present. */
 	if (!cpu_has_nofpuex) {
diff --git a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile
index 58c02f9..cd868ec 100644
--- a/arch/mips/galileo-boards/ev96100/Makefile
+++ b/arch/mips/galileo-boards/ev96100/Makefile
@@ -6,4 +6,4 @@
 # Makefile for the Galileo EV96100 board.
 #
 
-obj-y		+= init.o irq.o puts.o reset.o time.o int-handler.o setup.o
+obj-y		+= init.o irq.o puts.o reset.o time.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/int-handler.S b/arch/mips/galileo-boards/ev96100/int-handler.S
deleted file mode 100644
index 0edf1fe..0000000
--- a/arch/mips/galileo-boards/ev96100/int-handler.S
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.set	noat
-	.align	5
-
-NESTED(ev96100IRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI				# Important: mark KERNEL mode !
-
-	mfc0	t0, CP0_CAUSE		# get pending interrupts
-	mfc0	t1, CP0_STATUS		# get enabled interrupts
-	and	t0, t1			# isolate allowed ones
-
-	# FIX ME add R7000 extensions
-	andi	t0,0xff00		# isolate pending bits
-	andi	a0, t0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	move	a0, sp
-	jal	mips_timer_interrupt
-	j	ret_from_irq
-
-1:	beqz	t0, 3f			# spurious interrupt
-
-	move	a0, t0
-	move	a1, sp
-	jal	ev96100_cpu_irq
-	j	ret_from_irq
-
-3:	jal	spurious_interrupt
-	j	ret_from_irq
-	END(ev96100IRQ)
diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c
index 383801d..ee5d672 100644
--- a/arch/mips/galileo-boards/ev96100/irq.c
+++ b/arch/mips/galileo-boards/ev96100/irq.c
@@ -40,8 +40,6 @@
 #include <linux/interrupt.h>
 #include <asm/irq_cpu.h>
 
-extern asmlinkage void ev96100IRQ(void);
-
 static inline unsigned int ffz8(unsigned int word)
 {
 	unsigned long k;
@@ -54,13 +52,26 @@
 	return k;
 }
 
+extern void mips_timer_interrupt(struct pt_regs *regs);
+
 asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
 {
 	do_IRQ(ffz8(pending >> 8), regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (pending & CAUSEF_IP7)
+		mips_timer_interrupt(regs);
+	else if (pending)
+		ev96100_cpu_irq(pending, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, ev96100IRQ);
 	mips_cpu_irq_init(0);
 }
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
index ebe91c5..b2c53a8 100644
--- a/arch/mips/gt64120/ev64120/Makefile
+++ b/arch/mips/gt64120/ev64120/Makefile
@@ -6,6 +6,6 @@
 # Makefile for the Galileo EV64120 board.
 #
 
-obj-y	+= int-handler.o irq.o promcon.o reset.o serialGT.o setup.o
+obj-y	+= irq.o promcon.o reset.o serialGT.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/ev64120/int-handler.S b/arch/mips/gt64120/ev64120/int-handler.S
deleted file mode 100644
index 9dda5b4..0000000
--- a/arch/mips/gt64120/ev64120/int-handler.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * int-handler.S
- *
- * Based on the cobalt handler.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * galileo_handle_int -
- *      We check for the timer first, then check PCI ints A and D.
- *      Then check for serial IRQ and fall through.
- */
-		.align	5
-		.set	reorder
-		.set	noat
-		NESTED(galileo_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0,CP0_CAUSE
-		mfc0	t2,CP0_STATUS
-
-		and	t0,t2
-
-		andi	t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */
-		bnez	t1,ll_gt64120_irq
-		andi	t1,t0,STATUSF_IP2 /* int0 hardware line */
-		bnez	t1,ll_pci_intA
-		andi	t1,t0,STATUSF_IP5 /* int3 hardware line */
-		bnez	t1,ll_pci_intD
-		andi	t1,t0,STATUSF_IP6 /* int4 hardware line */
-		bnez	t1,ll_serial_irq
-		andi	t1,t0,STATUSF_IP7 /* compare int */
-		bnez	t1,ll_compare_irq
-		nop
-
-    /* wrong alarm or masked ... */
-		jal	spurious_interrupt
-		nop
-		j	ret_from_irq
-		END(galileo_handle_int)
-
-
-		.align	5
-		.set	reorder
-ll_gt64120_irq:
-		li	a0,4
-		move	a1,sp
-		jal	do_IRQ
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_compare_irq:
-		li 	a0,7
-		move	a1,sp
-		jal	do_IRQ
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_pci_intA:
-		move	a0,sp
-		jal	pci_intA
-		nop
-		j	ret_from_irq
-		nop
-
-#if 0
-		.align	5
-		.set	reorder
-ll_pci_intB:
-		move 	a0,sp
-		jal	pci_intB
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_pci_intC:
-		move 	a0,sp
-		jal	pci_intC
-		nop
-		j	ret_from_irq
-		nop
-#endif
-
-		.align	5
-		.set	reorder
-ll_pci_intD:
-		move 	a0,sp
-		jal	pci_intD
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_serial_irq:
-		li	a0,6
-		move	a1,sp
-		jal	do_IRQ
-		nop
-		j	ret_from_irq
-		nop
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
index 3b18615..46c468b 100644
--- a/arch/mips/gt64120/ev64120/irq.c
+++ b/arch/mips/gt64120/ev64120/irq.c
@@ -46,14 +46,22 @@
 #include <asm/system.h>
 #include <asm/gt64120.h>
 
-asmlinkage inline void pci_intA(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
-	do_IRQ(GT_INTA, regs);
-}
+	unsigned int pending = read_c0_status() & read_c0_cause();
 
-asmlinkage inline void pci_intD(struct pt_regs *regs)
-{
-	do_IRQ(GT_INTD, regs);
+	if (pending & STATUSF_IP4)		/* int2 hardware line (timer) */
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP2)		/* int0 hardware line */
+		do_IRQ(GT_INTA, regs);
+	else if (pending & STATUSF_IP5)		/* int3 hardware line */
+		do_IRQ(GT_INTD, regs);
+	else if (pending & STATUSF_IP6)		/* int4 hardware line */
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)		/* compare int */
+		do_IRQ(7, regs);
+	else
+		spurious_interrupt(regs);
 }
 
 static void disable_ev64120_irq(unsigned int irq_nr)
@@ -109,16 +117,11 @@
 
 void gt64120_irq_setup(void)
 {
-	extern asmlinkage void galileo_handle_int(void);
-
 	/*
 	 * Clear all of the interrupts while we change the able around a bit.
 	 */
 	clear_c0_status(ST0_IM);
 
-	/* Sets the exception_handler array. */
-	set_except_vector(0, galileo_handle_int);
-
 	local_irq_disable();
 
 	/*
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
index 7b59c65..6f708df 100644
--- a/arch/mips/gt64120/momenco_ocelot/Makefile
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Momentum's Ocelot board.
 #
 
-obj-y	 		+= int-handler.o irq.o prom.o reset.o setup.o
+obj-y	 		+= irq.o prom.o reset.o setup.o
 
 obj-$(CONFIG_KGDB)	+= dbg_io.o
 
diff --git a/arch/mips/gt64120/momenco_ocelot/int-handler.S b/arch/mips/gt64120/momenco_ocelot/int-handler.S
deleted file mode 100644
index 808acef..0000000
--- a/arch/mips/gt64120/momenco_ocelot/int-handler.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-		.align	5
-		NESTED(ocelot_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		 andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
-		bnez	t1, ll_pri_enet_irq
-		 andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
-		bnez	t1, ll_sec_enet_irq
-		 andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
-		bnez	t1, ll_uart1_irq
-		 andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
-		bnez	t1, ll_cpci_irq
-		 andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
-		bnez	t1, ll_galileo_irq
-		 andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_cputimer_irq
-
-                /* now look at the extended interrupts */
-		mfc0	t0, CP0_CAUSE
-		cfc0	t1, CP0_S1_INTCONTROL
-
-		/* shift the mask 8 bits left to line up the bits */
-		 sll	t2, t1, 8
-
-		 and	t0, t2
-		 srl	t0, t0, 16
-
-		 andi	t1, t0, STATUSF_IP8	/* int6 hardware line */
-		bnez	t1, ll_pmc1_irq
-		 andi	t1, t0, STATUSF_IP9	/* int7 hardware line */
-		bnez	t1, ll_pmc2_irq
-		 andi	t1, t0, STATUSF_IP10	/* int8 hardware line */
-		bnez	t1, ll_cpci_abcd_irq
-		 andi	t1, t0, STATUSF_IP11	/* int9 hardware line */
-		bnez	t1, ll_uart2_irq
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(ocelot_handle_int)
-
-		.align	5
-ll_pri_enet_irq:
-		li	a0, 2
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_sec_enet_irq:
-		li	a0, 3
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart1_irq:
-		li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_irq:
-		li	a0, 5
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_galileo_irq:
-		li	a0, 6
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pmc1_irq:
-		li	a0, 8
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pmc2_irq:
-		li	a0, 9
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_abcd_irq:
-		li	a0, 10
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart2_irq:
-		li	a0, 11
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c
index 4f108da..885f67f 100644
--- a/arch/mips/gt64120/momenco_ocelot/irq.c
+++ b/arch/mips/gt64120/momenco_ocelot/irq.c
@@ -48,7 +48,38 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & STATUSF_IP2)		/* int0 hardware line */
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)		/* int1 hardware line */
+		do_IRQ(3, regs);
+	else if (pending & STATUSF_IP4)		/* int2 hardware line */
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)		/* int3 hardware line */
+		do_IRQ(5, regs);
+	else if (pending & STATUSF_IP6)		/* int4 hardware line */
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)		/* cpu timer */
+		do_IRQ(7, regs);
+	else {
+		/*
+		 * Now look at the extended interrupts
+		 */
+		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+		if (pending & STATUSF_IP8)		/* int6 hardware line */
+			do_IRQ(8, regs);
+		else if (pending & STATUSF_IP9)		/* int7 hardware line */
+			do_IRQ(9, regs);
+		else if (pending & STATUSF_IP10)	/* int8 hardware line */
+			do_IRQ(10, regs);
+		else if (pending & STATUSF_IP11)	/* int9 hardware line */
+			do_IRQ(11, regs);
+	}
+}
 
 void __init arch_init_irq(void)
 {
@@ -59,9 +90,6 @@
 	clear_c0_status(ST0_IM);
 	local_irq_disable();
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, ocelot_handle_int);
-
 	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 }
diff --git a/arch/mips/ite-boards/generic/Makefile b/arch/mips/ite-boards/generic/Makefile
index 0e7853f..6343153 100644
--- a/arch/mips/ite-boards/generic/Makefile
+++ b/arch/mips/ite-boards/generic/Makefile
@@ -6,7 +6,7 @@
 # Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
 #
 
-obj-y			+= it8172_setup.o irq.o int-handler.o pmon_prom.o \
+obj-y			+= it8172_setup.o irq.o pmon_prom.o \
 			   time.o lpc.o puts.o reset.o
 
 obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o
diff --git a/arch/mips/ite-boards/generic/int-handler.S b/arch/mips/ite-boards/generic/int-handler.S
deleted file mode 100644
index d190d8a..0000000
--- a/arch/mips/ite-boards/generic/int-handler.S
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.set    macro
-	.set    noat
-	.align	5
-
-NESTED(it8172_IRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI				# Important: mark KERNEL mode !
-
-        /* We're working with 'reorder' set at this point. */
-	/*
-	 * Get pending interrupts
-	 */
-
-	mfc0	t0,CP0_CAUSE		# get pending interrupts
-	mfc0	t1,CP0_STATUS		# get enabled interrupts
-	and	t0,t1			# isolate allowed ones
-
-	andi	t0,0xff00		# isolate pending bits
-        beqz    t0, 3f                  # spurious interrupt
-
-        andi    a0, t0, CAUSEF_IP7
-        beq     a0, zero, 1f
-
-        li	a0, 127			# MIPS_CPU_TIMER_IRQ = (NR_IRQS-1)
-        move    a1, sp
-        jal     ll_timer_interrupt
-	j	ret_from_irq
-        nop
-
-1:
-        andi    a0, t0, CAUSEF_IP2      # the only int we expect at this time
-        beq     a0, zero, 3f
-	move	a0,sp
-	jal	it8172_hw0_irqdispatch
-
-	mfc0	t0,CP0_STATUS		# disable interrupts
-	ori	t0,1
-	xori	t0,1
-	mtc0	t0,CP0_STATUS
-        nop
-        nop
-        nop
-
-	la      a1, ret_from_irq
-	jr	a1
-        nop
-
-3:
-	move a0, sp
-	jal	mips_spurious_interrupt
-        nop
-	la      a1, ret_from_irq
-	jr	a1
-        nop
-
-END(it8172_IRQ)
-
diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
index 8c1cdfc..77be721 100644
--- a/arch/mips/ite-boards/generic/irq.c
+++ b/arch/mips/ite-boards/generic/irq.c
@@ -64,7 +64,6 @@
 
 extern void set_debug_traps(void);
 extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
-extern asmlinkage void it8172_IRQ(void);
 
 struct it8172_intc_regs volatile *it8172_hw0_icregs =
 	(struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
@@ -178,8 +177,6 @@
 	int i;
         unsigned long flags;
 
-        set_except_vector(0, it8172_IRQ);
-
 	/* mask all interrupts */
 	it8172_hw0_icregs->lb_mask  = 0xffff;
 	it8172_hw0_icregs->lpc_mask = 0xffff;
@@ -279,6 +276,18 @@
 	do_IRQ(irq, regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (!pending)
+		mips_spurious_interrupt(regs);
+	else if (pending & CAUSEF_IP7)
+		ll_timer_interrupt(127, regs);
+	else if (pending & CAUSEF_IP2)
+		it8172_hw0_irqdispatch(regs);
+}
+
 void show_pending_irqs(void)
 {
 	fputs("intstatus:  ");
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index 8574924..02bd39a 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the Jazz family specific parts of the kernel
 #
 
-obj-y	 	:= int-handler.o irq.o jazzdma.o reset.o setup.o
+obj-y	 	:= irq.o jazzdma.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S
deleted file mode 100644
index e35f5fc..0000000
--- a/arch/mips/jazz/int-handler.S
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse
- *
- * Jazz family specific interrupt stuff
- *
- * To do: On Jazz machines we remap some non-ISA interrupts to ISA
- *        interrupts.  These interrupts should use their own vectors.
- *        Squeeze the last cycles out of the handlers.  Only a dead
- *        cycle is a good cycle.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * jazz_handle_int: Interrupt handler for the ACER Pica-61 boards
- */
-		.set	noreorder
-
-		NESTED(jazz_handle_int, PT_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI
-		.set	at
-
-		/*
-		 * Get pending interrupts
-		 */
-		mfc0	t0,CP0_CAUSE		# get pending interrupts
-		mfc0	t1,CP0_STATUS		# get enabled interrupts
-		and	t0,t1			# isolate allowed ones
-		andi	t0,0xff00		# isolate pending bits
-		beqz	t0,3f
-		sll	t0,16			# delay slot
-
-		/*
-		 * Find irq with highest priority
-		 * FIXME: This is slow - use binary search
-		 */
-		la	t1,ll_vectors
-1:		bltz	t0,2f			# found pending irq
-		sll	t0,1
-		b	1b
-		subu	t1,PTRSIZE		# delay slot
-
-		/*
-		 * Do the low-level stuff
-		 */
-2:		lw	t0,(t1)
-		jr	t0
-		nop				# delay slot
-		END(jazz_handle_int)
-
-ll_sw0:		li	s1,~IE_SW0
-		mfc0	t0,CP0_CAUSE
-		and	t0,s1
-		mtc0	t0,CP0_CAUSE
-		PANIC("Unimplemented sw0 handler")
-
-ll_sw1:		li	s1,~IE_SW1
-		mfc0	t0,CP0_CAUSE
-		and	t0,s1
-		mtc0	t0,CP0_CAUSE
-		PANIC("Unimplemented sw1 handler")
-
-ll_local_dma:	li	s1,~IE_IRQ0
-		PANIC("Unimplemented local_dma handler")
-
-ll_local_dev:	lbu	t0,JAZZ_IO_IRQ_SOURCE
-#if PTRSIZE == 8	/* True 64 bit kernel */
-		dsll	t0,1
-#endif
-		.set	reorder
-		LONG_L	t0,local_vector(t0)
-		jr	t0
-		.set	noreorder
-
-/*
- * The braindead PICA hardware gives us no way to distinguish if we really
- * received interrupt 7 from the (E)ISA bus or if we just received an
- * interrupt with no findable cause.  This sometimes happens with braindead
- * cards.  Oh well - for all the Jazz boxes slots are more or less just
- * whistles and bells and we're aware of the problem.
- */
-ll_isa_irq:	lw	a0, JAZZ_EISA_IRQ_ACK
-
-		jal	do_IRQ
-		 move	a1,sp
-
-		j	ret_from_irq
-		nop
-
-/*
- * Hmm...  This is not just a plain PC clone so the question is
- * which devices on Jazz machines can generate an (E)ISA NMI?
- * (Writing to nonexistent memory?)
- */
-ll_isa_nmi:	li	s1,~IE_IRQ3
-		PANIC("Unimplemented isa_nmi handler")
-
-/*
- * Timer IRQ - remapped to be more similar to an IBM compatible.
- *
- * The timer interrupt is handled specially to ensure that the jiffies
- * variable is updated at all times.  Specifically, the timer interrupt is
- * just like the complete handlers except that it is invoked with interrupts
- * disabled and should never re-enable them.  If other interrupts were
- * allowed to be processed while the timer interrupt is active, then the
- * other interrupts would have to avoid using the jiffies variable for delay
- * and interval timing operations to avoid hanging the system.
- */
-ll_timer:	lw	zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
-		li	s1,~IE_IRQ4
-
-		li	a0, JAZZ_TIMER_IRQ
-		jal	do_IRQ
-		 move	a1,sp
-
-		mfc0	t0,CP0_STATUS		# disable interrupts again
-		ori	t0,1
-		xori	t0,1
-		mtc0	t0,CP0_STATUS
-
-		j	ret_from_irq
-		 nop
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count:	j	ret_from_irq
-		 mtc0	zero,CP0_COMPARE
-
-#if 0
-/*
- * Call the handler for the interrupt
- * (Currently unused)
- */
-call_real:	/*
-		 * temporarily disable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		and	t2,s1
-		mtc0	t2,CP0_STATUS
-		nor	s1,zero,s1
-		jal	do_IRQ
-
-		/*
-		 * reenable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		or	t2,s1
-		mtc0	t2,CP0_STATUS
-		j	ret_from_irq
-#endif
-
-		.data
-		PTR	ll_sw0			# SW0
-		PTR	ll_sw1			# SW1
-		PTR	ll_local_dma		# Local DMA
-		PTR	ll_local_dev		# Local devices
-		PTR	ll_isa_irq		# ISA IRQ
-		PTR	ll_isa_nmi		# ISA NMI
-		PTR	ll_timer		# Timer
-ll_vectors:	PTR	ll_count		# Count/Compare IRQ
-
-		/*
-		 * Interrupt handlers for local devices.
-		 */
-		.text
-		.set	reorder
-loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
-/*
- * Parallel port IRQ
- */
-loc_parallel:	li	s1,~JAZZ_IE_PARALLEL
-		li	a0,JAZZ_PARALLEL_IRQ
-		b	loc_call
-
-/*
- * Floppy IRQ
- */
-loc_floppy:	li	s1,~JAZZ_IE_FLOPPY
-		li	a0,JAZZ_FLOPPY_IRQ
-		b	loc_call
-
-/*
- * Sound IRQ
- */
-loc_sound:	PANIC("Unimplemented loc_sound handler")
-loc_video:	PANIC("Unimplemented loc_video handler")
-
-/*
- * Ethernet interrupt handler
- */
-loc_ethernet: 	li	s1,~JAZZ_IE_ETHERNET
-		li	a0,JAZZ_ETHERNET_IRQ
-		b	loc_call
-
-/*
- * SCSI interrupt handler
- */
-loc_scsi:	li	s1,~JAZZ_IE_SCSI
-		li	a0,JAZZ_SCSI_IRQ
-		b	loc_call
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard:	li	s1,~JAZZ_IE_KEYBOARD
-		li	a0,JAZZ_KEYBOARD_IRQ
-		b	loc_call
-
-/*
- * Mouse interrupt handler
- */
-loc_mouse:	li	s1,~JAZZ_IE_MOUSE
-		li	a0,JAZZ_MOUSE_IRQ
-		b	loc_call
-
-/*
- * Serial port 1 IRQ
- */
-loc_serial1:	li	s1,~JAZZ_IE_SERIAL1
-		li	a0,JAZZ_SERIAL1_IRQ
-		b	loc_call
-
-/*
- * Serial port 2 IRQ
- */
-loc_serial2:	li	s1,~JAZZ_IE_SERIAL2
-		li	a0,JAZZ_SERIAL2_IRQ
-		b	loc_call
-
-/*
- * Call the interrupt handler for an interrupt generated by a
- * local device.
- */
-loc_call:	/*
-		 * Temporarily disable interrupt source
-		 */
-		lhu	t2,JAZZ_IO_IRQ_ENABLE
-		and	t2,s1
-		sh	t2,JAZZ_IO_IRQ_ENABLE
-
-		nor	s1,zero,s1
-		jal	do_IRQ
-
-		/*
-		 * Reenable interrupt
-		 */
-		lhu	t2,JAZZ_IO_IRQ_ENABLE
-		or	t2,s1
-		sh	t2,JAZZ_IO_IRQ_ENABLE
-
-		j	ret_from_irq
-
-/*
- * "Jump extender" to reach spurious_interrupt
- */
-3:		jal	spurious_interrupt
-		j	ret_from_irq
-
-/*
- * Vectors for interrupts generated by local devices
- */
-		.data
-local_vector:	PTR	loc_no_irq
-		PTR	loc_parallel
-		PTR	loc_floppy
-		PTR	loc_sound
-		PTR	loc_video
-		PTR	loc_ethernet
-		PTR	loc_scsi
-		PTR	loc_keyboard
-		PTR	loc_mouse
-		PTR	loc_serial1
-		PTR	loc_serial2
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index b309b1b..becc9ac 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -15,8 +15,6 @@
 #include <asm/io.h>
 #include <asm/jazz.h>
 
-extern asmlinkage void jazz_handle_int(void);
-
 static DEFINE_SPINLOCK(r4030_lock);
 
 static void enable_r4030_irq(unsigned int irq)
@@ -90,10 +88,82 @@
  */
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, jazz_handle_int);
-
 	init_i8259_irqs();			/* Integrated i8259  */
 	init_r4030_ints();
 
 	change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
 }
+
+static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask)
+{
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
+	do_IRQ(irq, regs);
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
+}
+
+static void ll_local_dev(struct pt_regs *regs)
+{
+	switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
+	case 0:
+		panic("Unimplemented loc_no_irq handler");
+		break;
+	case 4:
+		loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL);
+		break;
+	case 8:
+		loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY);
+		break;
+	case 12:
+		panic("Unimplemented loc_sound handler");
+		break;
+	case 16:
+		panic("Unimplemented loc_video handler");
+		break;
+	case 20:
+		loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET);
+		break;
+	case 24:
+		loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI);
+		break;
+	case 28:
+		loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD);
+		break;
+	case 32:
+		loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE);
+		break;
+	case 36:
+		loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1);
+		break;
+	case 40:
+		loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2);
+		break;
+	}
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (pending & IE_IRQ5)
+		write_c0_compare(0);
+	else if (pending & IE_IRQ4) {
+		r4030_read_reg32(JAZZ_TIMER_REGISTER);
+		do_IRQ(JAZZ_TIMER_IRQ, regs);
+	} else if (pending & IE_IRQ3)
+		panic("Unimplemented ISA NMI handler");
+	else if (pending & IE_IRQ2)
+		do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs);
+	else if (pending & IE_IRQ1) {
+		ll_local_dev(regs);
+	} else if (unlikely(pending & IE_IRQ0))
+		panic("Unimplemented local_dma handler");
+	else if (pending & IE_SW1) {
+		clear_c0_cause(IE_SW1);
+		panic("Unimplemented sw1 handler");
+	} else if (pending & IE_SW0) {
+		clear_c0_cause(IE_SW0);
+		panic("Unimplemented sw0 handler");
+	}
+}
diff --git a/arch/mips/jmr3927/rbhma3100/Makefile b/arch/mips/jmr3927/rbhma3100/Makefile
index 75bf418..baf5077 100644
--- a/arch/mips/jmr3927/rbhma3100/Makefile
+++ b/arch/mips/jmr3927/rbhma3100/Makefile
@@ -2,7 +2,7 @@
 # Makefile for TOSHIBA JMR-TX3927 board
 #
 
-obj-y	 			+= init.o int-handler.o irq.o setup.o
+obj-y	 			+= init.o irq.o setup.o
 obj-$(CONFIG_RUNTIME_DEBUG) 	+= debug.o
 obj-$(CONFIG_KGDB)		+= kgdb_io.o
 
diff --git a/arch/mips/jmr3927/rbhma3100/int-handler.S b/arch/mips/jmr3927/rbhma3100/int-handler.S
deleted file mode 100644
index f85bbf4..0000000
--- a/arch/mips/jmr3927/rbhma3100/int-handler.S
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ahennessy@mvista.com
- *
- * Based on arch/mips/tsdb/kernel/int-handler.S
- *
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/jmr3927/jmr3927.h>
-
-	/* A lot of complication here is taken away because:
-	 *
-	 * 1) We handle one interrupt and return, sitting in a loop
-	 *    and moving across all the pending IRQ bits in the cause
-	 *    register is _NOT_ the answer, the common case is one
-	 *    pending IRQ so optimize in that direction.
-	 *
-	 * 2) We need not check against bits in the status register
-	 *    IRQ mask, that would make this routine slow as hell.
-	 *
-	 * 3) Linux only thinks in terms of all IRQs on or all IRQs
-	 *    off, nothing in between like BSD spl() brain-damage.
-	 *
-	 */
-
-/* Flush write buffer (needed?)
- * NOTE: TX39xx performs "non-blocking load", so explicitly use the target
- * register of LBU to flush immediately.
- */
-#define FLUSH_WB(tmp)	\
-	la	tmp, JMR3927_IOC_REV_ADDR; \
-	lbu	tmp, (tmp); \
-	move	tmp, zero;
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(jmr3927_IRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	jal	jmr3927_irc_irqdispatch
-	 move	a0, sp
-	FLUSH_WB(t0)
-	j	ret_from_irq
-	 nop
-	END(jmr3927_IRQ)
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index 2810727..11304d1 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -77,8 +77,6 @@
 }
 #endif
 
-extern asmlinkage void jmr3927_IRQ(void);
-
 #define irc_dlevel	0
 #define irc_elevel	1
 
@@ -262,7 +260,7 @@
 	       regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
 }
 
-void jmr3927_irc_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	int irq;
 
@@ -398,8 +396,6 @@
 
 	jmr3927_irq_init(NR_ISA_IRQS);
 
-	set_except_vector(0, jmr3927_IRQ);
-
 	/* setup irq space */
 	add_tb_irq_space(&jmr3927_isac_irqspace);
 	add_tb_irq_space(&jmr3927_ioc_irqspace);
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 13f22d1..04418b6 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -122,6 +122,20 @@
 	.set	pop
 	END(except_vec3_r4000)
 
+	__FINIT
+
+	.align  5
+NESTED(handle_int, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+
+	PTR_LA	ra, ret_from_irq
+	move	a0, sp
+	j	plat_irq_dispatch
+	END(handle_int)
+
+	__INIT
+
 /*
  * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
  * This is a dedicated interrupt exception vector which reduces the
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 8573190..61efc61 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -42,6 +42,7 @@
 #include <asm/watch.h>
 #include <asm/types.h>
 
+extern asmlinkage void handle_int(void);
 extern asmlinkage void handle_tlbm(void);
 extern asmlinkage void handle_tlbl(void);
 extern asmlinkage void handle_tlbs(void);
@@ -1296,6 +1297,7 @@
 	if (board_be_init)
 		board_be_init();
 
+	set_except_vector(0, handle_int);
 	set_except_vector(1, handle_tlbm);
 	set_except_vector(2, handle_tlbl);
 	set_except_vector(3, handle_tlbs);
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
index 0d5aec4..99f5046 100644
--- a/arch/mips/lasat/Makefile
+++ b/arch/mips/lasat/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-y	 			+= reset.o setup.o prom.o lasat_board.o \
-				   at93c.o interrupt.o lasatIRQ.o
+				   at93c.o interrupt.o
 
 obj-$(CONFIG_LASAT_SYSCTL)	+= sysctl.o
 obj-$(CONFIG_DS1603)		+= ds1603.o
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index 852a419..2d3472b 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -27,14 +27,13 @@
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/lasat/lasatint.h>
+#include <asm/time.h>
 #include <asm/gdb-stub.h>
 
 static volatile int *lasat_int_status = NULL;
 static volatile int *lasat_int_mask = NULL;
 static volatile int lasat_int_mask_shift;
 
-extern asmlinkage void lasatIRQ(void);
-
 void disable_lasat_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
@@ -109,11 +108,17 @@
 	return int_status;
 }
 
-void lasat_hw0_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	unsigned long int_status;
+	unsigned int cause = read_c0_cause();
 	int irq;
 
+	if (cause & CAUSEF_IP7) {	/* R4000 count / compare IRQ */
+		ll_timer_interrupt(7, regs);
+		return;
+	}
+
 	int_status = get_int_status();
 
 	/* if int_status == 0, then the interrupt has already been cleared */
@@ -147,9 +152,6 @@
 		panic("arch_init_irq: mips_machtype incorrect");
 	}
 
-	/* Now safe to set the exception vector. */
-	set_except_vector(0, lasatIRQ);
-
 	for (i = 0; i <= LASATINT_END; i++) {
 		irq_desc[i].status	= IRQ_DISABLED;
 		irq_desc[i].action	= 0;
diff --git a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S
deleted file mode 100644
index 2a2b0d0..0000000
--- a/arch/mips/lasat/lasatIRQ.S
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Interrupt exception dispatch code.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.set	noreorder
-	.align	5
-	NESTED(lasatIRQ, PT_SIZE, sp)
-	.set	noat
-	SAVE_ALL
-	CLI
-	.set	at
-	.set	noreorder
-
-	mfc0	s0, CP0_CAUSE		# get irq mask
-
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP2	# delay slot, check hw0 interrupt
-
-	/* Wheee, a timer interrupt. */
-	li	a0, 7
-	jal	ll_timer_interrupt
-	 move	a1, sp
-
-	j	ret_from_irq
-	 nop
-
-1:
-	/* Wheee, combined hardware level zero interrupt. */
-	jal	lasat_hw0_irqdispatch
-	 move	a0, sp			# delay slot
-
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	/*
-	 * Here by mistake?  This is possible, what can happen is that by the
-	 * time we take the exception the IRQ pin goes low, so just leave if
-	 * this is the case.
-	 */
-	move	a1,s0
-	mfc0	a1, CP0_EPC
-
-	j	ret_from_irq
-	 nop
-	END(lasatIRQ)
diff --git a/arch/mips/mips-boards/atlas/Makefile b/arch/mips/mips-boards/atlas/Makefile
index 50fec2a..d8dab75 100644
--- a/arch/mips/mips-boards/atlas/Makefile
+++ b/arch/mips/mips-boards/atlas/Makefile
@@ -16,5 +16,5 @@
 # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 #
 
-obj-y			:= atlas_int.o atlas-irq.o atlas_setup.o
+obj-y			:= atlas_int.o atlas_setup.o
 obj-$(CONFIG_KGDB)	+= atlas_gdb.o
diff --git a/arch/mips/mips-boards/atlas/atlas-irq.S b/arch/mips/mips-boards/atlas/atlas-irq.S
deleted file mode 100644
index 31bc99a..0000000
--- a/arch/mips/mips-boards/atlas/atlas-irq.S
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Interrupt exception dispatch code.
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/mips-boards/atlasint.h>
-
-/*
- * Furthermore, the IRQs on the MIPS board look basically (barring software
- * IRQs which we don't use at all and all external interrupt sources are
- * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        Combined hardware interrupt (hw0)
- *             3        Hardware (ignored)
- *             4        Hardware (ignored)
- *             5        Hardware (ignored)
- *             6        Hardware (ignored)
- *             7        R4k timer (what we use)
- *
- * Note: On the SEAD board thing are a little bit different.
- *       Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
- *       wired to UART1.
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- * Lowest  ----     Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(mipsIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-
-	mfc0	s0, CP0_CAUSE		# get irq bits
-	mfc0	s1, CP0_STATUS		# get irq mask
-	andi	s0, ST0_IM		# CAUSE.CE may be non-zero!
-	and	s0, s1
-
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
-	.set	mips32
-	clz	a0, s0
-	.set	mips0
-	negu	a0
-	addu	a0, 31-CAUSEB_IP
-	bltz	a0, spurious
-#else
-	beqz	s0, spurious
-	 li	a0, 7
-
-	and	t0, s0, 0xf000
-	sltiu	t0, t0, 1
-	sll	t0, 2
-	subu	a0, t0
-	sll	s0, t0
-
-	and	t0, s0, 0xc000
-	sltiu	t0, t0, 1
-	sll	t0, 1
-	subu	a0, t0
-	sll	s0, t0
-
-	and	t0, s0, 0x8000
-	sltiu	t0, t0, 1
-	# sll	t0, 0
-	subu	a0, t0
-	# sll	s0, t0
-#endif
-
-	 li	a1, MIPSCPU_INT_ATLAS
-	bne	a0, a1, 1f
-	 addu	a0, MIPSCPU_INT_BASE
-
-	jal	atlas_hw0_irqdispatch
-	 move	 a0, sp
-
-	j	ret_from_irq
-	 nop
-
-1:	jal	do_IRQ
-	 move	a1, sp
-
-	j	ret_from_irq
-	 nop
-
-spurious:
-	j	spurious_interrupt
-	 nop
-	END(mipsIRQ)
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index bc0ebc6..db53950 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -39,8 +39,6 @@
 
 static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
-extern asmlinkage void mipsIRQ(void);
-
 #if 0
 #define DEBUG_INT(x...) printk(x)
 #else
@@ -98,7 +96,7 @@
 	return b;
 }
 
-void atlas_hw0_irqdispatch(struct pt_regs *regs)
+static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
 {
 	unsigned long int_status;
 	int irq;
@@ -116,6 +114,91 @@
 	do_IRQ(irq, regs);
 }
 
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	//t0 = t0 << 2;
+	a0 = a0 - t0;
+	//s0 = s0 << t0;
+
+	return a0;
+#endif
+}
+
+/*
+ * IRQs on the Atlas board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq == MIPSCPU_INT_ATLAS)
+		atlas_hw0_irqdispatch(regs);
+	else if (irq > 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	int i;
@@ -128,9 +211,6 @@
 	 */
 	atlas_hw0_icregs->intrsten = 0xffffffff;
 
-	/* Now safe to set the exception vector. */
-	set_except_vector(0, mipsIRQ);
-
 	for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
 		irq_desc[i].status	= IRQ_DISABLED;
 		irq_desc[i].action	= 0;
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index 3ae8fe6..fd4c143 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -19,4 +19,4 @@
 # under Linux.
 #
 
-obj-y := malta_int.o malta-irq.o malta_setup.o
+obj-y := malta_int.o malta_setup.o
diff --git a/arch/mips/mips-boards/malta/malta-irq.S b/arch/mips/mips-boards/malta/malta-irq.S
deleted file mode 100644
index 6217aff..0000000
--- a/arch/mips/mips-boards/malta/malta-irq.S
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * Interrupt exception dispatch code.
- *
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/mips-boards/maltaint.h>
-
-/*
- * IRQs on the Malta board look basically (barring software IRQs which we
- * don't use at all and all external interrupt sources are combined together
- * on hardware interrupt 0 (MIPS IRQ 2)) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        Combined hardware interrupt (hw0)
- *             3        Hardware (ignored)
- *             4        Hardware (ignored)
- *             5        Hardware (ignored)
- *             6        Hardware (ignored)
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- * Lowest  ----     Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(mipsIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-
-	mfc0	s0, CP0_CAUSE		# get irq bits
-	mfc0	s1, CP0_STATUS		# get irq mask
-	andi	s0, ST0_IM		# CAUSE.CE may be non-zero!
-	and	s0, s1
-
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
- 	.set	mips32
-	clz	a0, s0
-	.set	mips0
-	negu	a0
-	addu	a0, 31-CAUSEB_IP
-	bltz	a0, spurious
-#else
-	beqz	s0, spurious
-	 li	a0, 7
-
-	and	t0, s0, 0xf000
-	sltiu	t0, t0, 1
-	sll	t0, 2
-	subu	a0, t0
-	sll	s0, t0
-
-	and	t0, s0, 0xc000
-	sltiu	t0, t0, 1
-	sll	t0, 1
-	subu	a0, t0
-	sll	s0, t0
-
-	and	t0, s0, 0x8000
-	sltiu	t0, t0, 1
-	# sll	t0, 0
-	subu	a0, t0
-	# sll	s0, t0
-#endif
-
-	 li	a1, MIPSCPU_INT_I8259A
-	bne	a0, a1, 1f
-	 addu	a0, MIPSCPU_INT_BASE
-
-	jal	malta_hw0_irqdispatch
-	 move	 a0, sp
-
-	j	ret_from_irq
-	 nop
-1:
-
-	jal	do_IRQ
-	 move	a1, sp
-
-	j	ret_from_irq
-	 nop
-
-spurious:
-	j	spurious_interrupt
-	 nop
-	END(mipsIRQ)
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index d06dc5ad..1da8c18 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -40,7 +40,6 @@
 #include <asm/mips-boards/msc01_pci.h>
 #include <asm/msc01_ic.h>
 
-extern asmlinkage void mipsIRQ(void);
 extern void mips_timer_interrupt(void);
 
 static DEFINE_SPINLOCK(mips_irq_lock);
@@ -114,7 +113,7 @@
 	return irq;
 }
 
-void malta_hw0_irqdispatch(struct pt_regs *regs)
+static void malta_hw0_irqdispatch(struct pt_regs *regs)
 {
 	int irq;
 
@@ -182,6 +181,92 @@
         die("CoreHi interrupt", regs);
 }
 
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	//t0 = t0 << 2;
+	a0 = a0 - t0;
+	//s0 = s0 << t0;
+
+	return a0;
+#endif
+}
+
+/*
+ * IRQs on the Malta board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq == MIPSCPU_INT_I8259A)
+		malta_hw0_irqdispatch(regs);
+	else if (irq > 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 static struct irqaction i8259irq = {
 	.handler = no_action,
 	.name = "XT-PIC cascade"
@@ -214,7 +299,6 @@
 
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, mipsIRQ);
 	init_i8259_irqs();
 
 	if (!cpu_has_veic)
@@ -245,7 +329,6 @@
 		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
 	}
 	else {
-		set_except_vector(0, mipsIRQ);
 		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
 		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
 	}
diff --git a/arch/mips/mips-boards/sead/Makefile b/arch/mips/mips-boards/sead/Makefile
index 01780b6..224bb84 100644
--- a/arch/mips/mips-boards/sead/Makefile
+++ b/arch/mips/mips-boards/sead/Makefile
@@ -23,4 +23,4 @@
 # under Linux.
 #
 
-obj-y		:= sead_int.o sead-irq.o sead_setup.o
+obj-y		:= sead_int.o sead_setup.o
diff --git a/arch/mips/mips-boards/sead/sead-irq.S b/arch/mips/mips-boards/sead/sead-irq.S
deleted file mode 100644
index d5dea1d..0000000
--- a/arch/mips/mips-boards/sead/sead-irq.S
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * Interrupt exception dispatch code.
- *
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/mips-boards/seadint.h>
-
-/*
- * IRQs on the SEAD board look basically are combined together on hardware
- * interrupt 0 (MIPS IRQ 2)) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        UART0 (hw0)
- *             3        UART1 (hw1)
- *             4        Hardware (ignored)
- *             5        Hardware (ignored)
- *             6        Hardware (ignored)
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- * Lowest  ----     Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(mipsIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-
-	mfc0	s0, CP0_CAUSE		# get irq bits
-	mfc0	s1, CP0_STATUS		# get irq mask
-	andi	s0, ST0_IM		# CAUSE.CE may be non-zero!
-	and	s0, s1
-
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
- 	.set	mips32
-	clz	a0, s0
-	.set	mips0
-	negu	a0
-	addu	a0, 31-CAUSEB_IP
-	bltz	a0, spurious
-#else
-	beqz	s0, spurious
-	 li	a0, 7
-
-	and	t0, s0, 0xf000
-	sltiu	t0, t0, 1
-	sll	t0, 2
-	subu	a0, t0
-	sll	s0, t0
-
-	and	t0, s0, 0xc000
-	sltiu	t0, t0, 1
-	sll	t0, 1
-	subu	a0, t0
-	sll	s0, t0
-
-	and	t0, s0, 0x8000
-	sltiu	t0, t0, 1
-	# sll	t0, 0
-	subu	a0, t0
-	# sll	s0, t0
-#endif
-
-	 addu	a0, MIPSCPU_INT_BASE
-	jal	do_IRQ
-	 move	a1, sp
-
-	j	ret_from_irq
-	 nop
-
-spurious:
-	j	spurious_interrupt
-	 nop
-	END(mipsIRQ)
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index 90fda0d..9168d93 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -24,16 +24,94 @@
 #include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
 #include <asm/system.h>
 
 #include <asm/mips-boards/seadint.h>
 
-extern asmlinkage void mipsIRQ(void);
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	//t0 = t0 << 2;
+	a0 = a0 - t0;
+	//s0 = s0 << t0;
+
+	return a0;
+#endif
+}
+
+/*
+ * IRQs on the SEAD board look basically are combined together on hardware
+ * interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        UART0 (hw0)
+ *             3        UART1 (hw1)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq >= 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+	else
+		spurious_interrupt(regs);
+}
 
 void __init arch_init_irq(void)
 {
 	mips_cpu_irq_init(MIPSCPU_INT_BASE);
-
-	/* Now safe to set the exception vector. */
-	set_except_vector(0, mipsIRQ);
 }
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
index a4d0a2c..2c15c8e 100644
--- a/arch/mips/mips-boards/sim/sim_int.c
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -25,17 +25,71 @@
 
 extern void mips_cpu_irq_init(int);
 
-extern asmlinkage void simIRQ(void);
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
 
-asmlinkage void sim_hw0_irqdispatch(struct pt_regs *regs)
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	//t0 = t0 << 2;
+	a0 = a0 - t0;
+	//s0 = s0 << t0;
+
+	return a0;
+#endif
+}
+
+static inline void sim_hw0_irqdispatch(struct pt_regs *regs)
 {
 	do_IRQ(2, regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq > 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
-	/* Now safe to set the exception vector. */
-	set_except_vector(0, simIRQ);
-
 	mips_cpu_irq_init(MIPSCPU_INT_BASE);
 }
diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile
index 20bbd3e..67372f3 100644
--- a/arch/mips/momentum/jaguar_atx/Makefile
+++ b/arch/mips/momentum/jaguar_atx/Makefile
@@ -6,7 +6,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
 
 obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
 obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/int-handler.S b/arch/mips/momentum/jaguar_atx/int-handler.S
deleted file mode 100644
index 55bc789..0000000
--- a/arch/mips/momentum/jaguar_atx/int-handler.S
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work:
- *   Copyright 2001 MontaVista Software Inc.
- *   Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Jaguar-ATX board.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
-		.align	5
-		NESTED(jaguar_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		andi	t1, t0, STATUSF_IP0	/* sw0 software interrupt */
-		bnez	t1, ll_sw0_irq
-		andi	t1, t0, STATUSF_IP1	/* sw1 software interrupt */
-		bnez	t1, ll_sw1_irq
-		andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
-		bnez	t1, ll_pcixa_irq
-		andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
-		bnez	t1, ll_pcixb_irq
-		andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
-		bnez	t1, ll_pcia_irq
-		andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
-		bnez	t1, ll_pcib_irq
-		andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
-		bnez	t1, ll_uart_irq
-		andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_cputimer_irq
-
-		nop
-		nop
-
-		/* now look at extended interrupts */
-		mfc0	t0, CP0_CAUSE
-		cfc0	t1, CP0_S1_INTCONTROL
-
-		/* shift the mask 8 bits left to line up the bits */
-		sll	t2, t1, 8
-
-		and	t0, t2
-		srl	t0, t0, 16
-
-		andi	t1, t0, STATUSF_IP8	/* int6 hardware line */
-		bnez	t1, ll_mv64340_decode_irq
-
-		nop
-		nop
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(jaguar_handle_int)
-
-		.align	5
-ll_sw0_irq:
-		li	a0, 0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_sw1_irq:
-		li	a0, 1
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_pcixa_irq:
-		li	a0, 2
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pcixb_irq:
-		li	a0, 3
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pcia_irq:
-		li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pcib_irq:
-		li	a0, 5
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart_irq:
-		li	a0, 6
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7
-		move	a1, sp
-		jal	ll_timer_interrupt
-		j	ret_from_irq
-
-ll_mv64340_decode_irq:
-		move	a0, sp
-		jal	ll_mv64340_irq
-		j	ret_from_irq
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
index 15588f9..ec4032b 100644
--- a/arch/mips/momentum/jaguar_atx/irq.c
+++ b/arch/mips/momentum/jaguar_atx/irq.c
@@ -10,7 +10,7 @@
  *   Copyright 2001 MontaVista Software Inc.
  *   Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  *
- *   Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *   Copyright (C) 2000, 01, 06 Ralf Baechle (ralf@linux-mips.org)
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -38,8 +38,37 @@
 #include <linux/types.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
+#include <asm/time.h>
 
-extern asmlinkage void jaguar_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP0)
+		do_IRQ(0, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(1, regs);
+	else if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)
+		ll_timer_interrupt(7, regs);
+	else {
+		/*
+		 * Now look at the extended interrupts
+		 */
+		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+		if (pending & STATUSF_IP8)
+			ll_mv64340_irq(regs);
+	}
+}
 
 static struct irqaction cascade_mv64340 = {
 	no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
@@ -53,8 +82,6 @@
 	 */
 	clear_c0_status(ST0_IM);
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, jaguar_handle_int);
 	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
index aab8fd8..8bcea64 100644
--- a/arch/mips/momentum/ocelot_3/Makefile
+++ b/arch/mips/momentum/ocelot_3/Makefile
@@ -5,4 +5,4 @@
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 #
-obj-y	 += int-handler.o irq.o prom.o reset.o setup.o
+obj-y	 += irq.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/int-handler.S b/arch/mips/momentum/ocelot_3/int-handler.S
deleted file mode 100644
index b120726..0000000
--- a/arch/mips/momentum/ocelot_3/int-handler.S
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- * First-level interrupt dispatcher for Ocelot-3 board.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-3 board
- */
-		.align	5
-		NESTED(ocelot3_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		andi	t1, t0, STATUSF_IP0	/* sw0 software interrupt (IRQ0) */
-		bnez	t1, ll_sw0_irq
-
-		andi	t1, t0, STATUSF_IP1	/* sw1 software interrupt (IRQ1) */
-		bnez	t1, ll_sw1_irq
-
-		andi	t1, t0, STATUSF_IP2	/* int0 hardware line (IRQ2) */
-		bnez	t1, ll_pci0slot1_irq
-
-		andi	t1, t0, STATUSF_IP3	/* int1 hardware line (IRQ3) */
-		bnez	t1, ll_pci0slot2_irq
-
-		andi	t1, t0, STATUSF_IP4	/* int2 hardware line (IRQ4) */
-		bnez	t1, ll_pci1slot1_irq
-
-		andi	t1, t0, STATUSF_IP5	/* int3 hardware line (IRQ5) */
-		bnez	t1, ll_pci1slot2_irq
-
-		andi	t1, t0, STATUSF_IP6	/* int4 hardware line (IRQ6) */
-		bnez	t1, ll_uart_irq
-
-		andi	t1, t0, STATUSF_IP7	/* cpu timer (IRQ7) */
-		bnez	t1, ll_cputimer_irq
-
-                /* now look at extended interrupts */
-                mfc0    t0, CP0_CAUSE
-                cfc0    t1, CP0_S1_INTCONTROL
-
-                /* shift the mask 8 bits left to line up the bits */
-                sll     t2, t1, 8
-
-                and     t0, t2
-                srl     t0, t0, 16
-
-                andi    t1, t0, STATUSF_IP8     /* int6 hardware line (IRQ9) */
-                bnez    t1, ll_mv64340_decode_irq
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		jal	spurious_interrupt
-		nop
-		j	ret_from_irq
-		 nop
-		END(ocelot3_handle_int)
-
-		.align	5
-ll_sw0_irq:
-		li	a0, 0		/* IRQ 1 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_sw1_irq:
-		li	a0, 1		/* IRQ 2 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pci0slot1_irq:
-		li	a0, 2		/* IRQ 3 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pci0slot2_irq:
-		li	a0, 3		/* IRQ 4 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pci1slot1_irq:
-		li	a0, 4		/* IRQ 5 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pci1slot2_irq:
-		li	a0, 5		/* IRQ 6 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart_irq:
-		li	a0, 6		/* IRQ 7 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7		/* IRQ 8 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_mv64340_decode_irq:
-		move	a0, sp
-		jal	ll_mv64340_irq
-		j	ret_from_irq
-
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
index 42464db..87c63c3 100644
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ b/arch/mips/momentum/ocelot_3/irq.c
@@ -53,8 +53,6 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot3_handle_int(void);
-
 static struct irqaction cascade_mv64340 = {
 	no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
 };
@@ -67,9 +65,6 @@
 	 */
 	clear_c0_status(ST0_IM | ST0_BEV);
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, ocelot3_handle_int);
-	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 
 	/* set up the cascading interrupts */
@@ -79,3 +74,36 @@
 	set_c0_status(ST0_IM); /* IE in the status register */
 
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP0)
+		do_IRQ(0, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(1, regs);
+	else if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)
+		do_IRQ(7, regs);
+	else {
+		/*
+		 * Now look at the extended interrupts
+		 */
+		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+		if (pending & STATUSF_IP8)
+			ll_mv64340_irq(regs);
+		else
+			spurious_interrupt(regs);
+	}
+}
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
index 9124077..94802b4 100644
--- a/arch/mips/momentum/ocelot_c/Makefile
+++ b/arch/mips/momentum/ocelot_c/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Momentum Computer's Ocelot-C and -CS boards.
 #
 
-obj-y	 		+= cpci-irq.o int-handler.o irq.o prom.o reset.o \
+obj-y	 		+= cpci-irq.o irq.o prom.o reset.o \
 			   setup.o uart-irq.o
 
 obj-$(CONFIG_KGDB)	+= dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S
deleted file mode 100644
index f778341..0000000
--- a/arch/mips/momentum/ocelot_c/int-handler.S
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Ocelot-CS board.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include "ocelot_c_fpga.h"
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
-		.align	5
-		NESTED(ocelot_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		andi	t1, t0, STATUSF_IP0	/* sw0 software interrupt */
-		bnez	t1, ll_sw0_irq
-		andi	t1, t0, STATUSF_IP1	/* sw1 software interrupt */
-		bnez	t1, ll_sw1_irq
-		andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
-		bnez	t1, ll_scsi_irq
-		andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
-		bnez	t1, ll_uart_decode_irq
-		andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
-		bnez	t1, ll_pmc_irq
-		andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
-		bnez	t1, ll_cpci_decode_irq
-		andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
-		bnez	t1, ll_mv64340_decode_irq
-		andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_cputimer_irq
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		jal	spurious_interrupt
-		nop
-		j	ret_from_irq
-		END(ocelot_handle_int)
-
-		.align	5
-ll_sw0_irq:
-		li	a0, 0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_sw1_irq:
-		li	a0, 1
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_scsi_irq:
-		li	a0, 2
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart_decode_irq:
-		move	a0, sp
-		jal	ll_uart_irq
-		j	ret_from_irq
-
-ll_pmc_irq:
-		li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_decode_irq:
-		move	a0, sp
-		jal	ll_cpci_irq
-		j	ret_from_irq
-
-ll_mv64340_decode_irq:
-		move	a0, sp
-		jal	ll_mv64340_irq
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
index a5764bc..86f61ce 100644
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ b/arch/mips/momentum/ocelot_c/irq.c
@@ -48,7 +48,6 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
 extern void uart_irq_init(void);
 extern void cpci_irq_init(void);
 
@@ -60,6 +59,33 @@
 	no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
 };
 
+extern void ll_uart_irq(struct pt_regs *regs);
+extern void ll_cpci_irq(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP0)
+		do_IRQ(0, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(1, regs);
+	else if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)
+		ll_uart_irq(regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)
+		ll_cpci_irq(regs);
+	else if (pending & STATUSF_IP6)
+		ll_mv64340_irq(regs);
+	else if (pending & STATUSF_IP7)
+		do_IRQ(7, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	/*
@@ -68,8 +94,6 @@
 	 */
 	clear_c0_status(ST0_IM);
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, ocelot_handle_int);
 	mips_cpu_irq_init(0);
 
 	/* set up the cascading interrupts */
diff --git a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile
index e5f1cb0..adb5665 100644
--- a/arch/mips/momentum/ocelot_g/Makefile
+++ b/arch/mips/momentum/ocelot_g/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Momentum Computer's Ocelot-G board.
 #
 
-obj-y	 		+= int-handler.o irq.o gt-irq.o prom.o reset.o setup.o
+obj-y	 		+= irq.o gt-irq.o prom.o reset.o setup.o
 obj-$(CONFIG_KGDB)	+= dbg_io.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/momentum/ocelot_g/int-handler.S b/arch/mips/momentum/ocelot_g/int-handler.S
deleted file mode 100644
index 772e8f7..0000000
--- a/arch/mips/momentum/ocelot_g/int-handler.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-		.align	5
-		NESTED(ocelot_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		 andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
-		bnez	t1, ll_pri_enet_irq
-		 andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
-		bnez	t1, ll_sec_enet_irq
-		 andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
-		bnez	t1, ll_uart_irq
-		 andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
-		bnez	t1, ll_cpci_irq
-		 andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
-		bnez	t1, ll_galileo_p0_irq
-		 andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_cputimer_irq
-
-                /* now look at the extended interrupts */
-		mfc0	t0, CP0_CAUSE
-		cfc0	t1, CP0_S1_INTCONTROL
-
-		/* shift the mask 8 bits left to line up the bits */
-		 sll	t2, t1, 8
-
-		 and	t0, t2
-		 srl	t0, t0, 16
-
-		 andi	t1, t0, STATUSF_IP8	/* int6 hardware line */
-		bnez	t1, ll_galileo_p1_irq
-		 andi	t1, t0, STATUSF_IP9	/* int7 hardware line */
-		bnez	t1, ll_pmc_irq
-		 andi	t1, t0, STATUSF_IP10	/* int8 hardware line */
-		bnez	t1, ll_cpci_abcd_irq
-		 andi	t1, t0, STATUSF_IP11	/* int9 hardware line */
-		bnez	t1, ll_testpoint_irq
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(ocelot_handle_int)
-
-		.align	5
-ll_pri_enet_irq:
-		li	a0, 2
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_sec_enet_irq:
-		li	a0, 3
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart_irq:
-		li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_irq:
-		li	a0, 5
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_galileo_p0_irq:
-		li	a0, 6
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_galileo_p1_irq:
-		li	a0, 8
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pmc_irq:
-		li	a0, 9
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_abcd_irq:
-		li	a0, 10
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_testpoint_irq:
-		li	a0, 11
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
index 5eb85b1..7a4a419 100644
--- a/arch/mips/momentum/ocelot_g/irq.c
+++ b/arch/mips/momentum/ocelot_g/irq.c
@@ -48,7 +48,41 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)
+		do_IRQ(7, regs);
+	else {
+		/*
+		 * Now look at the extended interrupts
+		 */
+		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+		if (pending & STATUSF_IP8)
+			do_IRQ(8, regs);
+		else if (pending & STATUSF_IP9)
+			do_IRQ(9, regs);
+		else if (pending & STATUSF_IP10)
+			do_IRQ(10, regs);
+		else if (pending & STATUSF_IP11)
+			do_IRQ(11, regs);
+		else
+			spurious_interrupt(regs);
+	}
+}
+
 extern void gt64240_irq_init(void);
 
 void __init arch_init_irq(void)
@@ -60,8 +94,6 @@
 	clear_c0_status(ST0_IM);
 	local_irq_disable();
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, ocelot_handle_int);
 	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 
diff --git a/arch/mips/philips/pnx8550/common/Makefile b/arch/mips/philips/pnx8550/common/Makefile
index 6e38f3b..b7c6381 100644
--- a/arch/mips/philips/pnx8550/common/Makefile
+++ b/arch/mips/philips/pnx8550/common/Makefile
@@ -22,6 +22,6 @@
 # under Linux.
 #
 
-obj-y := setup.o prom.o mipsIRQ.o int.o reset.o time.o proc.o platform.o
+obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
index c500e2d..39ee631 100644
--- a/arch/mips/philips/pnx8550/common/int.c
+++ b/arch/mips/philips/pnx8550/common/int.c
@@ -38,8 +38,6 @@
 #include <int.h>
 #include <uart.h>
 
-extern asmlinkage void cp0_irqdispatch(void);
-
 static DEFINE_SPINLOCK(irq_lock);
 
 /* default prio for interrupts */
@@ -55,7 +53,7 @@
 	1			//  70
 };
 
-void hw0_irqdispatch(int irq, struct pt_regs *regs)
+static void hw0_irqdispatch(int irq, struct pt_regs *regs)
 {
 	/* find out which interrupt */
 	irq = PNX8550_GIC_VECTOR_0 >> 3;
@@ -68,7 +66,7 @@
 }
 
 
-void timer_irqdispatch(int irq, struct pt_regs *regs)
+static void timer_irqdispatch(int irq, struct pt_regs *regs)
 {
 	irq = (0x01c0 & read_c0_config7()) >> 6;
 
@@ -88,6 +86,20 @@
 	}
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP7) {
+		if (read_c0_config7() & 0x01c0)
+			timer_irqdispatch(7, regs);
+	}
+
+	spurious_interrupt(regs);
+}
+
 static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
 {
 	unsigned long status = read_c0_status();
@@ -223,9 +235,6 @@
 	int i;
 	int configPR;
 
-	/* init of cp0 interrupts */
-	set_except_vector(0, cp0_irqdispatch);
-
 	for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
 		irq_desc[i].handler = &level_irq_type;
 		pnx8550_ack(i);	/* mask the irq just in case  */
diff --git a/arch/mips/philips/pnx8550/common/mipsIRQ.S b/arch/mips/philips/pnx8550/common/mipsIRQ.S
deleted file mode 100644
index e049a71..0000000
--- a/arch/mips/philips/pnx8550/common/mipsIRQ.S
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2002 Philips, Inc. All rights.
- * Copyright (c) 2002 Red Hat, Inc. All rights.
- *
- * This software may be freely redistributed under the terms of the
- * GNU General Public License.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon arch/mips/galileo-boards/ev64240/int-handler.S
- *
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * cp0_irqdispatch
- *
- *    Code to handle in-core interrupt exception.
- */
-
-		.align	5
-		.set	reorder
-		.set	noat
-		NESTED(cp0_irqdispatch, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0,CP0_CAUSE
-		mfc0	t2,CP0_STATUS
-
-		and	t0,t2
-
-		andi	t1,t0,STATUSF_IP2 /* int0 hardware line */
-		bnez	t1,ll_hw0_irq
-		nop
-
-		andi	t1,t0,STATUSF_IP7 /* int5 hardware line */
-		bnez	t1,ll_timer_irq
-		nop
-
-		/* wrong alarm or masked ... */
-
-		jal	spurious_interrupt
-		nop
-		j	ret_from_irq
-		END(cp0_irqdispatch)
-
-		.align	5
-		.set	reorder
-ll_hw0_irq:
-		li	a0,2
-		move	a1,sp
-		jal	hw0_irqdispatch
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_timer_irq:
-		mfc0	t3,CP0_CONFIG,7
-		andi	t4,t3,0x01c0
-		beqz	t4,ll_timer_out
-		nop
-		li	a0,7
-		move	a1,sp
-		jal	timer_irqdispatch
-		nop
-
-ll_timer_out:	j	ret_from_irq
-		nop
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
index ae96a71..e931e0d 100644
--- a/arch/mips/pmc-sierra/yosemite/Makefile
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the PMC-Sierra Titan
 #
 
-obj-y    += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o
+obj-y    += irq.o i2c-yosemite.o prom.o py-console.o setup.o
 
 obj-$(CONFIG_KGDB)		+= dbg_io.o
 obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S
deleted file mode 100644
index 33b9c40..0000000
--- a/arch/mips/pmc-sierra/yosemite/irq-handler.S
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2003, 04 PMC-Sierra Inc.
- * Author: Manish Lachwani (lachwani@pmc-sierra.com
- * Copyright 2004 Ralf Baechle (ralf@linux-mips.org)
- *
- * First-level interrupt router for the PMC-Sierra Titan board
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Titan supports Hypertransport or PCI but not both. Hence, one interrupt
- * line is shared between the PCI slot A and Hypertransport. This is the
- * Processor INTB #0.
- */
-
-#include <linux/config.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-		.align	5
-		NESTED(titan_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		.set	noreorder
-		la	ra, ret_from_irq
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		andi	t2, t0, STATUSF_IP7	/* INTB5 hardware line */
-		bnez	t2, ll_timer_irq	/* Timer */
-		andi	t1, t0, STATUSF_IP2	/* INTB0 hardware line */
-		bnez	t1, ll_pcia_irq		/* 64-bit PCI */
-		andi	t2, t0, STATUSF_IP3	/* INTB1 hardware line */
-		bnez	t2, ll_pcib_irq		/* second 64-bit PCI slot */
-		andi	t1, t0, STATUSF_IP4	/* INTB2 hardware line */
-		bnez	t1, ll_duart_irq	/* UART	*/
-		andi    t2, t0, STATUSF_IP5	/* SMP inter-core interrupts */
-		bnez    t2, ll_smp_irq
-		andi	t1, t0, STATUSF_IP6
-		bnez	t1, ll_ht_irq		/* Hypertransport */
-
-		move	a0, sp
-		j	do_extended_irq
-		END(titan_handle_int)
-
-		.set	reorder
-		.align	5
-
-ll_pcia_irq:
-		li	a0, 2
-		move	a1, sp
-#ifdef CONFIG_HYPERTRANSPORT
-		j	ll_ht_smp_irq_handler
-#else
-		j	do_IRQ
-#endif
-
-ll_pcib_irq:
-		li	a0, 3
-		move	a1, sp
-		j	do_IRQ
-
-ll_duart_irq:
-		li	a0, 4
-		move	a1, sp
-		j	do_IRQ
-
-ll_smp_irq:
-		li	a0, 5
-		move	a1, sp
-#ifdef CONFIG_SMP
-		j	titan_mailbox_irq
-#else
-		j	do_IRQ
-#endif
-
-ll_ht_irq:
-		li	a0, 6
-		move	a1, sp
-		j	ll_ht_smp_irq_handler
-
-ll_timer_irq:
-		li	a0, 7
-		move	a1, sp
-		j	do_IRQ
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
index f4e2897..a1f524f 100644
--- a/arch/mips/pmc-sierra/yosemite/irq.c
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -2,6 +2,8 @@
  * Copyright (C) 2003 PMC-Sierra Inc.
  * Author: Manish Lachwani (lachwani@pmc-sierra.com)
  *
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
  *  Free Software Foundation;  either version 2 of the  License, or (at your
@@ -55,7 +57,6 @@
 #define HYPERTRANSPORT_INTC     0x7a		/* INTC# */
 #define HYPERTRANSPORT_INTD     0x7b		/* INTD# */
 
-extern asmlinkage void titan_handle_int(void);
 extern void jaguar_mailbox_irq(struct pt_regs *);
 
 /*
@@ -125,6 +126,35 @@
 
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int cause = read_c0_cause();
+	unsigned int status = read_c0_status();
+	unsigned int pending = cause & status;
+
+	if (pending & STATUSF_IP7) {
+		do_IRQ(7, regs);
+	} else if (pending & STATUSF_IP2) {
+#ifdef CONFIG_HYPERTRANSPORT
+		ll_ht_smp_irq_handler(2, regs);
+#else
+		do_IRQ(2, regs);
+#endif
+	} else if (pending & STATUSF_IP3) {
+		do_IRQ(3, regs);
+	} else if (pending & STATUSF_IP4) {
+		do_IRQ(4, regs);
+	} else if (pending & STATUSF_IP5) {
+#ifdef CONFIG_SMP
+		titan_mailbox_irq(regs);
+#else
+		do_IRQ(5, regs);
+#endif
+	} else if (pending & STATUSF_IP6) {
+		do_IRQ(4, regs);
+	}
+}
+
 #ifdef CONFIG_KGDB
 extern void init_second_port(void);
 #endif
@@ -136,7 +166,6 @@
 {
 	clear_c0_status(ST0_IM);
 
-	set_except_vector(0, titan_handle_int);
 	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 	rm9k_cpu_irq_init(12);
diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile
index 6a8e8bc..730f459 100644
--- a/arch/mips/qemu/Makefile
+++ b/arch/mips/qemu/Makefile
@@ -2,6 +2,6 @@
 # Makefile for Qemu specific kernel interface routines under Linux.
 #
 
-obj-y		= q-firmware.o q-int.o q-irq.o q-mem.o q-setup.o
+obj-y		= q-firmware.o q-irq.o q-mem.o q-setup.o
 
 obj-$(CONFIG_SMP) += q-smp.o
diff --git a/arch/mips/qemu/q-int.S b/arch/mips/qemu/q-int.S
deleted file mode 100644
index 6e3dfe5..0000000
--- a/arch/mips/qemu/q-int.S
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Qemu interrupt handler code.
- *
- * Copyright (C) 2005 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.align	5
-	NESTED(qemu_handle_int, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	move	a0, sp
-	PTR_LA	ra, ret_from_irq
-	j	do_qemu_int
-	END(qemu_handle_int)
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index 2c4e070..3352374 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -9,7 +9,7 @@
 
 extern asmlinkage void qemu_handle_int(void);
 
-asmlinkage void do_qemu_int(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 
@@ -29,7 +29,6 @@
 
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, qemu_handle_int);
 	mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK;		/* 100MHz */
 
 	init_i8259_irqs();
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index eb0820f..6aa4c0c 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y	+= ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \
+obj-y	+= ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
 	   ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
 
 obj-$(CONFIG_EISA)	+= ip22-eisa.o
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index d16fb43..fc6a7e2 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -37,7 +37,6 @@
 static char lc2msk_to_irqnr[256];
 static char lc3msk_to_irqnr[256];
 
-extern asmlinkage void indyIRQ(void);
 extern int ip22_eisa_init(void);
 
 static void enable_local0_irq(unsigned int irq)
@@ -224,7 +223,7 @@
 	.end		= end_local3_irq,
 };
 
-void indy_local0_irqdispatch(struct pt_regs *regs)
+static void indy_local0_irqdispatch(struct pt_regs *regs)
 {
 	u8 mask = sgint->istat0 & sgint->imask0;
 	u8 mask2;
@@ -242,7 +241,7 @@
 	return;
 }
 
-void indy_local1_irqdispatch(struct pt_regs *regs)
+static void indy_local1_irqdispatch(struct pt_regs *regs)
 {
 	u8 mask = sgint->istat1 & sgint->imask1;
 	u8 mask2;
@@ -262,7 +261,7 @@
 
 extern void ip22_be_interrupt(int irq, struct pt_regs *regs);
 
-void indy_buserror_irq(struct pt_regs *regs)
+static void indy_buserror_irq(struct pt_regs *regs)
 {
 	int irq = SGI_BUSERR_IRQ;
 
@@ -307,6 +306,56 @@
 #define SGI_INTERRUPTS	SGINT_LOCAL3
 #endif
 
+extern void indy_r4k_timer_interrupt(struct pt_regs *regs);
+extern void indy_8254timer_irq(struct pt_regs *regs);
+
+/*
+ * IRQs on the INDY look basically (barring software IRQs which we don't use
+ * at all) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause();
+
+	/*
+	 * First we check for r4k counter/timer IRQ.
+	 */
+	if (pending & CAUSEF_IP7)
+		indy_r4k_timer_interrupt(regs);
+	else if (pending & CAUSEF_IP2)
+		indy_local0_irqdispatch(regs);
+	else if (pending & CAUSEF_IP3)
+		indy_local1_irqdispatch(regs);
+	else if (pending & CAUSEF_IP6)
+		indy_buserror_irq(regs);
+	else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+		indy_8254timer_irq(regs);
+}
+
 extern void mips_cpu_irq_init(unsigned int irq_base);
 
 void __init arch_init_irq(void)
@@ -369,8 +418,6 @@
 	sgint->cmeimask0 = 0;
 	sgint->cmeimask1 = 0;
 
-	set_except_vector(0, indyIRQ);
-
 	/* init CPU irqs */
 	mips_cpu_irq_init(SGINT_CPU);
 
diff --git a/arch/mips/sgi-ip22/ip22-irq.S b/arch/mips/sgi-ip22/ip22-irq.S
deleted file mode 100644
index 6ccbd9e..0000000
--- a/arch/mips/sgi-ip22/ip22-irq.S
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * ip22-irq.S: Interrupt exception dispatch code for FullHouse and
- *             Guiness.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        Local IRQ level zero
- *             3        Local IRQ level one
- *             4        8254 Timer zero
- *             5        8254 Timer one
- *             6        Bus Error
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- *                  Local IRQ zero
- *                  Local IRQ one
- *                  Bus Error
- *                  8254 Timer zero
- * Lowest  ----     8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(indyIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	mfc0	s0, CP0_CAUSE		# get irq mask
-
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero
-
-	/* Wheee, a timer interrupt. */
-	jal	indy_r4k_timer_interrupt
-	 move	a0, sp			# delay slot
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one
-
-	/* Wheee, local level zero interrupt. */
-	jal	indy_local0_irqdispatch
-	 move	a0, sp			# delay slot
-
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error
-
-	/* Wheee, local level one interrupt. */
-	jal	indy_local1_irqdispatch
-	 move	a0, sp			# delay slot
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)	# delay slot
-
-	/* Wheee, an asynchronous bus error... */
-	jal	indy_buserror_irq
-	 move	a0, sp			# delay slot
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	/* Here by mistake? It is possible, that by the time we take
-	 * the exception the IRQ pin goes low, so just leave if this
-	 * is the case.
-	 */
-	beq	a0, zero, 1f
-	 nop			  	# delay slot
-
-	/* Must be one of the 8254 timers... */
-	jal	indy_8254timer_irq
-	 move	a0, sp			# delay slot
-1:
-	j	ret_from_irq
-	 nop				# delay slot
-	END(indyIRQ)
diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile
index 4ba3407..686ba14 100644
--- a/arch/mips/sgi-ip27/Makefile
+++ b/arch/mips/sgi-ip27/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the IP27 specific kernel interface routines under Linux.
 #
 
-obj-y	:= ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+obj-y	:= ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o \
 	   ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \
 	   ip27-timer.o ip27-hubio.o ip27-xtalk.o
 
diff --git a/arch/mips/sgi-ip27/TODO b/arch/mips/sgi-ip27/TODO
index 3210613..19f1512 100644
--- a/arch/mips/sgi-ip27/TODO
+++ b/arch/mips/sgi-ip27/TODO
@@ -9,10 +9,6 @@
 in irix?
 6. Investigate why things do not work without the setup_test() call
 being invoked on all nodes in ip27-memory.c.
-7. Too many CLIs in the locore handlers :
-For the low level handlers set up by set_except_vector(),
-__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror,
-investigate whether the code should do CLI, STI or KMODE.
 8. Too many do_page_faults invoked - investigate.
 9. start_thread must turn off UX64 ... and define tlb_refill_debug.
 10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable
diff --git a/arch/mips/sgi-ip27/ip27-irq-glue.S b/arch/mips/sgi-ip27/ip27-irq-glue.S
deleted file mode 100644
index c304df7..0000000
--- a/arch/mips/sgi-ip27/ip27-irq-glue.S
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999 Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.align	5
-NESTED(ip27_irq, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-
-	mfc0	s0, CP0_CAUSE
-	mfc0	t0, CP0_STATUS
-	and	s0, t0
-	move	a0, sp
-	PTR_LA	ra, ret_from_irq
-
-	/* First check for RT interrupt.  */
-	andi	t0, s0, CAUSEF_IP4
-	bnez	t0, ip4
-	andi	t0, s0, CAUSEF_IP2
-	bnez	t0, ip2
-	andi	t0, s0, CAUSEF_IP3
-	bnez	t0, ip3
-	andi	t0, s0, CAUSEF_IP5
-	bnez	t0, ip5
-	andi	t0, s0, CAUSEF_IP6
-	bnez	t0, ip6
-	j	ra
-
-ip2:	j	ip27_do_irq_mask0	# PI_INT_PEND_0 or CC_PEND_{A|B}
-ip3:	j	ip27_do_irq_mask1	# PI_INT_PEND_1
-ip4:	j	ip27_rt_timer_interrupt
-ip5:	j	ip27_prof_timer
-ip6:	j	ip27_hub_error
-
-	END(ip27_irq)
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 2854ac4..2e643d2 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -130,7 +130,7 @@
  * Kanoj 05.13.00
  */
 
-void ip27_do_irq_mask0(struct pt_regs *regs)
+static void ip27_do_irq_mask0(struct pt_regs *regs)
 {
 	int irq, swlevel;
 	hubreg_t pend0, mask0;
@@ -171,7 +171,7 @@
 	LOCAL_HUB_L(PI_INT_PEND0);
 }
 
-void ip27_do_irq_mask1(struct pt_regs *regs)
+static void ip27_do_irq_mask1(struct pt_regs *regs)
 {
 	int irq, swlevel;
 	hubreg_t pend1, mask1;
@@ -196,12 +196,12 @@
 	LOCAL_HUB_L(PI_INT_PEND1);
 }
 
-void ip27_prof_timer(struct pt_regs *regs)
+static void ip27_prof_timer(struct pt_regs *regs)
 {
 	panic("CPU %d got a profiling interrupt", smp_processor_id());
 }
 
-void ip27_hub_error(struct pt_regs *regs)
+static void ip27_hub_error(struct pt_regs *regs)
 {
 	panic("CPU %d got a hub error interrupt", smp_processor_id());
 }
@@ -421,9 +421,26 @@
 	return irq;
 }
 
+extern void ip27_rt_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned long pending = read_c0_cause() & read_c0_status();
+
+	if (pending & CAUSEF_IP4)
+		ip27_rt_timer_interrupt(regs);
+	else if (pending & CAUSEF_IP2)	/* PI_INT_PEND_0 or CC_PEND_{A|B} */
+		ip27_do_irq_mask0(regs);
+	else if (pending & CAUSEF_IP3)	/* PI_INT_PEND_1 */
+		ip27_do_irq_mask1(regs);
+	else if (pending & CAUSEF_IP5)
+		ip27_prof_timer(regs);
+	else if (pending & CAUSEF_IP6)
+		ip27_hub_error(regs);
+}
+
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, ip27_irq);
 }
 
 void install_ipi(void)
diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile
index 470898f..530bf84 100644
--- a/arch/mips/sgi-ip32/Makefile
+++ b/arch/mips/sgi-ip32/Makefile
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y	+= ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-reset.o \
+obj-y	+= ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \
 	   crime.o ip32-memory.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S
deleted file mode 100644
index 200924e..0000000
--- a/arch/mips/sgi-ip32/ip32-irq-glue.S
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Harald Koerfgen
- * Copyright (C) 2001 Keith M Wesolowski
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/addrspace.h>
-
-		.text
-		.set    noreorder
-		.set    noat
-		.align  5
-		NESTED(ip32_handle_int, PT_SIZE, ra)
-		.set    noat
-		SAVE_ALL
-		CLI			# TEST: interrupts should be off
-		.set    at
-		.set    noreorder
-
-		mfc0	s0,CP0_CAUSE
-
-		andi	t1, s0, IE_IRQ0
-		bnez	t1, handle_irq0
-		 andi	t1, s0, IE_IRQ1
-		bnez	t1, handle_irq1
-		 andi	t1, s0, IE_IRQ2
-		bnez	t1, handle_irq2
-		 andi	t1, s0, IE_IRQ3
-		bnez	t1, handle_irq3
-		 andi	t1, s0, IE_IRQ4
-		bnez	t1, handle_irq4
-		 andi	t1, s0, IE_IRQ5
-		bnez	t1, handle_irq5
-		 nop
-
-		/* Either someone has triggered the "software interrupts"
-		 * or we lost an interrupt somehow.  Ignore it.
-		 */
-		j	ret_from_irq
-		 nop
-
-handle_irq0:
-		jal	ip32_irq0
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq1:
-		jal	ip32_irq1
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq2:
-		jal	ip32_irq2
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq3:
-		jal	ip32_irq3
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq4:
-		jal	ip32_irq4
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq5:
-		jal	ip32_irq5
-		move	a0, sp
-		j	ret_from_irq
-		 nop
-
-		END(ip32_handle_int)
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index 2eb22d69..22a6df9 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -130,8 +130,6 @@
 struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT,
 			CPU_MASK_NONE, "CRIME CPU error", NULL, NULL };
 
-extern void ip32_handle_int(void);
-
 /*
  * For interrupts wired from a single device to the CPU.  Only the clock
  * uses this it seems, which is IRQ 0 and IP7.
@@ -503,7 +501,7 @@
 
 /* CRIME 1.1 appears to deliver all interrupts to this one pin. */
 /* change this to loop over all edge-triggered irqs, exception masked out ones */
-void ip32_irq0(struct pt_regs *regs)
+static void ip32_irq0(struct pt_regs *regs)
 {
 	uint64_t crime_int;
 	int irq = 0;
@@ -520,31 +518,49 @@
 	do_IRQ(irq, regs);
 }
 
-void ip32_irq1(struct pt_regs *regs)
+static void ip32_irq1(struct pt_regs *regs)
 {
 	ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq2(struct pt_regs *regs)
+static void ip32_irq2(struct pt_regs *regs)
 {
 	ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq3(struct pt_regs *regs)
+static void ip32_irq3(struct pt_regs *regs)
 {
 	ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq4(struct pt_regs *regs)
+static void ip32_irq4(struct pt_regs *regs)
 {
 	ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq5(struct pt_regs *regs)
+static void ip32_irq5(struct pt_regs *regs)
 {
 	ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause();
+
+	if (likely(pending & IE_IRQ0))
+		ip32_irq0(regs);
+	else if (unlikely(pending & IE_IRQ1))
+		ip32_irq1(regs);
+	else if (unlikely(pending & IE_IRQ2))
+		ip32_irq2(regs);
+	else if (unlikely(pending & IE_IRQ3))
+		ip32_irq3(regs);
+	else if (unlikely(pending & IE_IRQ4))
+		ip32_irq4(regs);
+	else if (likely(pending & IE_IRQ5))
+		ip32_irq5(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	unsigned int irq;
@@ -556,7 +572,6 @@
 	crime->soft_int = 0;
 	mace->perif.ctrl.istat = 0;
 	mace->perif.ctrl.imask = 0;
-	set_except_vector(0, ip32_handle_int);
 
 	for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
 		hw_irq_controller *controller;
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
index 538d5a5..7b36ff3 100644
--- a/arch/mips/sibyte/bcm1480/Makefile
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
 
 obj-$(CONFIG_SMP)			+= smp.o
 
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 9cf7d71..e61760b 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -187,9 +187,6 @@
 #endif
 
 
-/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
-extern void bcm1480_irq_handler(void);
-
 /*****************************************************************************/
 
 static unsigned int startup_bcm1480_irq(unsigned int irq)
@@ -422,7 +419,6 @@
 #endif
 	/* Enable necessary IPs, disable the rest */
 	change_c0_status(ST0_IM, imask);
-	set_except_vector(0, bcm1480_irq_handler);
 
 #ifdef CONFIG_KGDB
 	if (kgdb_flag) {
@@ -473,3 +469,76 @@
 }
 
 #endif 	/* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+	int lz;
+
+	__asm__ (
+	"	.set	push						\n"
+	"	.set	mips64						\n"
+	"	dclz	%0, %1						\n"
+	"	.set	pop						\n"
+	: "=r" (lz)
+	: "r" (x));
+
+	return lz;
+}
+
+extern void bcm1480_timer_interrupt(struct pt_regs *regs);
+extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
+extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+	/* Set compare to count to silence count/compare timer interrupts */
+	write_c0_compare(read_c0_count());
+#endif
+
+	pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+	if (pending & CAUSEF_IP7)	/* Cpu performance counter interrupt */
+		sbprof_cpu_intr(exception_epc(regs));
+#endif
+
+	if (pending & CAUSEF_IP4)
+		bcm1480_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+	if (pending & CAUSEF_IP3)
+		bcm1480_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+	if (pending & CAUSEF_IP6)
+		bcm1480_kgdb_interrupt(regs);		/* KGDB (uart 1) */
+#endif
+
+	if (pending & CAUSEF_IP2) {
+		unsigned long long mask_h, mask_l;
+		unsigned long base;
+
+		/*
+		 * Default...we've hit an IP[2] interrupt, which means we've
+		 * got to check the 1480 interrupt registers to figure out what
+		 * to do.  Need to detect which CPU we're on, now that
+		 * smp_affinity is supported.
+		 */
+		base = A_BCM1480_IMR_MAPPER(smp_processor_id());
+		mask_h = __raw_readq(
+			IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
+		mask_l = __raw_readq(
+			IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
+
+		if (!mask_h) {
+			if (mask_h ^ 1)
+				do_IRQ(63 - dclz(mask_h), regs);
+			else
+				do_IRQ(127 - dclz(mask_l), regs);
+		}
+	}
+}
diff --git a/arch/mips/sibyte/bcm1480/irq_handler.S b/arch/mips/sibyte/bcm1480/irq_handler.S
deleted file mode 100644
index 408db88..0000000
--- a/arch/mips/sibyte/bcm1480/irq_handler.S
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * bcm1480_irq_handler() is the routine that is actually called when an
- * interrupt occurs.  It is installed as the exception vector handler in
- * init_IRQ() in arch/mips/sibyte/bcm1480/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that
- * to call the dispatcher, which will take care of actually calling
- * registered handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/bcm1480_regs.h>
-#include <asm/sibyte/bcm1480_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call.  Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
-	.text
-	.set	push
-	.set	noreorder
-	.set	noat
-	.set	mips64
-	#.set	mips4
-	.align	5
-	NESTED(bcm1480_irq_handler, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
-	/* Set compare to count to silence count/compare timer interrupts */
-	mfc0	t1, CP0_COUNT
-	mtc0	t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
-	/* Read cause */
-	mfc0	s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
-	/* Cpu performance counter interrupt is routed to IP[7] */
-	andi	t1, s0, CAUSEF_IP7
-	beqz	t1, 0f
-	 srl	t1, s0, (CAUSEB_BD-2)	/* Shift BD bit to bit 2 */
-	and	t1, t1, 0x4		/* mask to get just BD bit */
-#ifdef CONFIG_MIPS64
-	dmfc0	a0, CP0_EPC
-	daddu	a0, a0, t1		/* a0 = EPC + (BD ? 4 :	0) */
-#else
-	mfc0	a0, CP0_EPC
-	addu	a0, a0, t1		/* a0 = EPC + (BD ? 4 :	0) */
-#endif
-	jal	sbprof_cpu_intr
-	 nop
-	j	ret_from_irq
-	 nop
-0:
-#endif
-
-	/* Timer interrupt is routed to IP[4] */
-	andi	t1, s0, CAUSEF_IP4
-	beqz	t1, 1f
-	 nop
-	jal	bcm1480_timer_interrupt
-	 move	a0, sp			/* Pass the registers along */
-	j	ret_from_irq
-	 nop				/* delay slot  */
-1:
-
-#ifdef CONFIG_SMP
-	/* Mailbox interrupt is routed to IP[3] */
-	andi	 t1, s0, CAUSEF_IP3
-	beqz	 t1, 2f
-	 nop
-	jal	 bcm1480_mailbox_interrupt
-	 move	 a0, sp
-	j	 ret_from_irq
-	 nop				/* delay slot  */
-2:
-#endif
-
-#ifdef CONFIG_KGDB
-	/* KGDB (uart 1) interrupt is routed to IP[6] */
-	andi	 t1, s0, CAUSEF_IP6
-	beqz	 t1, 3f
-	 nop				/* delay slot  */
-	jal	 bcm1480_kgdb_interrupt
-	 move	 a0, sp
-	j	 ret_from_irq
-	 nop				/* delay slot  */
-3:
-#endif
-
-	and	 t1, s0, CAUSEF_IP2
-	beqz	 t1, 9f
-	 nop
-
-	/*
-	 * Default...we've hit an IP[2] interrupt, which means we've got
-	 * to check the 1480 interrupt registers to figure out what to do
-	 * Need to detect which CPU we're on, now that smp_affinity is
-	 * supported.
-	 */
-	PTR_LA	 v0, CKSEG1 + A_BCM1480_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
-	lw	 t1, TI_CPU($28)
-	sll	 t1, t1, BCM1480_IMR_REGISTER_SPACING_SHIFT
-	addu	 v0, v0, t1
-#endif
-
-	/* Read IP[2] status (get both high and low halves of status) */
-	ld	 s0, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H(v0)
-	ld	 s1, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L(v0)
-
-	move	 s2, zero	/* intr number  */
-	li	 s3, 64
-
-	beqz	 s0, 9f		/* No interrupts.  Return.  */
-	 move	 a1, sp
-
-	xori	 s4, s0, 1	/* if s0 (_H) == 1, it's a low intr, so...  */
-	movz	 s2, s3, s4	/* start the intr number at 64, and  */
-	movz	 s0, s1, s4	/* look at the low status value.  */
-
-	dclz	 s1, s0		/* Find the next interrupt.  */
-	dsubu	 a0, zero, s1
-	daddiu	 a0, a0, 63
-	jal	 do_IRQ
-	 daddu	 a0, a0, s2
-
-9:	j	 ret_from_irq
-	 nop
-
-	.set pop
-	END(bcm1480_irq_handler)
diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile
index a8af846..a2fdbd6 100644
--- a/arch/mips/sibyte/sb1250/Makefile
+++ b/arch/mips/sibyte/sb1250/Makefile
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
 
 obj-$(CONFIG_SMP)			+= smp.o
 obj-$(CONFIG_SIBYTE_TBPROF)		+= bcm1250_tbprof.o
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 589537b..0f6e54d 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -163,10 +163,6 @@
 }
 #endif
 
-
-/* Defined in arch/mips/sibyte/sb1250/irq_handler.S */
-extern void sb1250_irq_handler(void);
-
 /*****************************************************************************/
 
 static unsigned int startup_sb1250_irq(unsigned int irq)
@@ -379,7 +375,6 @@
 #endif
 	/* Enable necessary IPs, disable the rest */
 	change_c0_status(ST0_IM, imask);
-	set_except_vector(0, sb1250_irq_handler);
 
 #ifdef CONFIG_KGDB
 	if (kgdb_flag) {
@@ -409,7 +404,7 @@
 #define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 #define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 
-void sb1250_kgdb_interrupt(struct pt_regs *regs)
+static void sb1250_kgdb_interrupt(struct pt_regs *regs)
 {
 	/*
 	 * Clear break-change status (allow some time for the remote
@@ -424,3 +419,74 @@
 }
 
 #endif 	/* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+	int lz;
+
+	__asm__ (
+	"	.set	push						\n"
+	"	.set	mips64						\n"
+	"	dclz	%0, %1						\n"
+	"	.set	pop						\n"
+	: "=r" (lz)
+	: "r" (x));
+
+	return lz;
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+	/* Set compare to count to silence count/compare timer interrupts */
+	write_c0_count(read_c0_count());
+#endif
+
+	/*
+	 * What a pain. We have to be really careful saving the upper 32 bits
+	 * of any * register across function calls if we don't want them
+	 * trashed--since were running in -o32, the calling routing never saves
+	 * the full 64 bits of a register across a function call.  Being the
+	 * interrupt handler, we're guaranteed that interrupts are disabled
+	 * during this code so we don't have to worry about random interrupts
+	 * blasting the high 32 bits.
+	 */
+
+	pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+	if (pending & CAUSEF_IP7) { /* Cpu performance counter interrupt */
+		sbprof_cpu_intr(exception_epc(regs));
+	}
+#endif
+
+	if (pending & CAUSEF_IP4)
+		sb1250_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+	if (pending & CAUSEF_IP3)
+		sb1250_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+	if (pending & CAUSEF_IP6)			/* KGDB (uart 1) */
+		sb1250_kgdb_interrupt(regs);
+#endif
+
+	if (pending & CAUSEF_IP2) {
+		unsigned long long mask;
+
+		/*
+		 * Default...we've hit an IP[2] interrupt, which means we've
+		 * got to check the 1250 interrupt registers to figure out what
+		 * to do.  Need to detect which CPU we're on, now that
+		 ~ smp_affinity is supported.
+		 */
+		mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
+		                              R_IMR_INTERRUPT_STATUS_BASE)));
+		if (mask)
+			do_IRQ(63 - dclz(mask), regs);
+	}
+}
diff --git a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S
deleted file mode 100644
index 60edc8f..0000000
--- a/arch/mips/sibyte/sb1250/irq_handler.S
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * sb1250_handle_int() is the routine that is actually called when an interrupt
- * occurs.  It is installed as the exception vector handler in arch_init_irq()
- * in arch/mips/sibyte/sb1250/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that to
- * call the dispatcher, which will take care of actually calling registered
- * handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call.  Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
-	.text
-	.set	push
-	.set	noreorder
-	.set	noat
-	.set	mips64
-	.align	5
-	NESTED(sb1250_irq_handler, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
-	/* Set compare to count to silence count/compare timer interrupts */
-	mfc0	t1, CP0_COUNT
-	mtc0	t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
-	/* Read cause */
-	mfc0	s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
-	/* Cpu performance counter interrupt is routed to IP[7] */
-	andi	t1, s0, CAUSEF_IP7
-	beqz	t1, 0f
-	 srl	t1, s0, (CAUSEB_BD-2)  /* Shift BD bit to bit 2 */
-	and	t1, t1, 0x4		/* mask to get just BD bit */
-	mfc0	a0, CP0_EPC
-	jal	sbprof_cpu_intr
-	 addu	a0, a0, t1		/* a0 = EPC + (BD ? 4 :	0) */
-	j	ret_from_irq
-	 nop
-0:
-#endif
-
-	/* Timer interrupt is routed to IP[4] */
-	andi	t1, s0, CAUSEF_IP4
-	beqz	t1, 1f
-	 nop
-	jal	sb1250_timer_interrupt
-	 move	a0, sp			/* Pass the registers along */
-	j	ret_from_irq
-	 nop				# delay slot
-1:
-
-#ifdef CONFIG_SMP
-	/* Mailbox interrupt is routed to IP[3] */
-	andi	 t1, s0, CAUSEF_IP3
-	beqz	 t1, 2f
-	 nop
-	jal	 sb1250_mailbox_interrupt
-	 move    a0, sp
-	j	ret_from_irq
-	 nop				# delay slot
-2:
-#endif
-
-#ifdef CONFIG_KGDB
-	/* KGDB (uart 1) interrupt is routed to IP[6] */
-	andi	t1, s0, CAUSEF_IP6
-	beqz	t1, 1f
-	nop                            # delay slot
-	jal	sb1250_kgdb_interrupt
-         move	a0, sp
-	j	ret_from_irq
-	nop                            # delay slot
-1:
-#endif
-
-	and      t1, s0, CAUSEF_IP2
-	beqz     t1, 4f
-	 nop
-
-	/*
-	 * Default...we've hit an IP[2] interrupt, which means we've got to
-	 * check the 1250 interrupt registers to figure out what to do
-	 * Need to detect which CPU we're on, now that smp_affinity is supported.
-	 */
-	PTR_LA	v0, CKSEG1 + A_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
-	lw	t1, TI_CPU($28)
-	sll	t1, IMR_REGISTER_SPACING_SHIFT
-	addu	v0, t1
-#endif
-	ld	s0, R_IMR_INTERRUPT_STATUS_BASE(v0)	/* read IP[2] status */
-
-	beqz	s0, 4f		/* No interrupts.  Return */
-	 move	a1, sp
-
-3:	dclz	s1, s0		/* Find the next interrupt */
-	dsubu	a0, zero, s1
-	daddiu	a0, a0, 63
-	jal	 do_IRQ
-	 nop
-
-4:	j        ret_from_irq
-	 nop
-
-	.set pop
-	END(sb1250_irq_handler)
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index 1e5676e..9c7eaa5 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the SNI specific part of the kernel
 #
 
-obj-y	 	+= int-handler.o irq.o pcimt_scache.o reset.o setup.o
+obj-y	 	+= irq.o pcimt_scache.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
deleted file mode 100644
index 2cdc09f..0000000
--- a/arch/mips/sni/int-handler.S
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SNI RM200 PCI specific interrupt handler code.
- *
- * Copyright (C) 1994, 95, 96, 97, 98, 1999, 2000, 01 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/sni.h>
-#include <asm/stackframe.h>
-
-/*
- * The PCI ASIC has the nasty property that it may delay writes if it is busy.
- * As a consequence from writes that have not graduated when we exit from the
- * interrupt handler we might catch a spurious interrupt.  To avoid this we
- * force the PCI ASIC to graduate all writes by executing a read from the
- * PCI bus.
- */
-		.set	noreorder
-		.set	noat
-		.align	5
-		NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		/* Blinken light ...  */
-		lb	t0, led_cache
-		addiu	t0, 1
-		sb	t0, led_cache
-		sb	t0, PCIMT_CSLED			# write only register
-		.data
-led_cache:	.byte	0
-		.text
-
-		mfc0	t0, CP0_STATUS
-		mfc0	t1, CP0_CAUSE
-		and	t0, t1
-
-		 andi	t1, t0, 0x0800			# hardware interrupt 1
-		bnez	t1, _hwint1
-		 andi	t1, t0, 0x4000			# hardware interrupt 4
-		bnez	t1, _hwint4
-		 andi	t1, t0, 0x2000			# hardware interrupt 3
-		bnez	t1, _hwint3
-		 andi	t1, t0, 0x1000			# hardware interrupt 2
-		bnez	t1, _hwint2
-		 andi	t1, t0, 0x8000			# hardware interrupt 5
-		bnez	t1, _hwint5
-		 andi	t1, t0, 0x0400			# hardware interrupt 0
-		bnez	t1, _hwint0
-		 nop
-
-		j	restore_all			# spurious interrupt
-		 nop
-
- ##############################################################################
-
-/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
-   button interrupts.  */
-_hwint0:	jal	pciasic_hwint0
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-/*
- * hwint 1 deals with EISA and SCSI interrupts
- */
-_hwint1:	jal	pciasic_hwint1
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-
-/*
- * This interrupt was used for the com1 console on the first prototypes;
- * it's unsed otherwise
- */
-_hwint2:	jal	pciasic_hwint2
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-/*
- * hwint 3 are the PCI interrupts A - D
- */
-_hwint3:	jal	pciasic_hwint3
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-/*
- * hwint 4 is used for only the onboard PCnet 32.
- */
-_hwint4:	jal	pciasic_hwint4
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-/* hwint5 is the r4k count / compare interrupt  */
-_hwint5:	jal	pciasic_hwint5
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-		END(sni_rm200_pci_handle_int)
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 952038a..7365b48 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -19,8 +19,6 @@
 
 DEFINE_SPINLOCK(pciasic_lock);
 
-extern asmlinkage void sni_rm200_pci_handle_int(void);
-
 static void enable_pciasic_irq(unsigned int irq)
 {
 	unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
@@ -71,20 +69,20 @@
  * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
  * button interrupts.  Later ...
  */
-void pciasic_hwint0(struct pt_regs *regs)
+static void pciasic_hwint0(struct pt_regs *regs)
 {
 	panic("Received int0 but no handler yet ...");
 }
 
 /* This interrupt was used for the com1 console on the first prototypes.  */
-void pciasic_hwint2(struct pt_regs *regs)
+static void pciasic_hwint2(struct pt_regs *regs)
 {
 	/* I think this shouldn't happen on production machines.  */
 	panic("hwint2 and no handler yet");
 }
 
 /* hwint5 is the r4k count / compare interrupt  */
-void pciasic_hwint5(struct pt_regs *regs)
+static void pciasic_hwint5(struct pt_regs *regs)
 {
 	panic("hwint5 and no handler yet");
 }
@@ -105,7 +103,7 @@
  *
  * The EISA_INT bit in CSITPEND is high active, all others are low active.
  */
-void pciasic_hwint1(struct pt_regs *regs)
+static void pciasic_hwint1(struct pt_regs *regs)
 {
 	u8 pend = *(volatile char *)PCIMT_CSITPEND;
 	unsigned long flags;
@@ -135,7 +133,7 @@
 /*
  * hwint 3 should deal with the PCI A - D interrupts,
  */
-void pciasic_hwint3(struct pt_regs *regs)
+static void pciasic_hwint3(struct pt_regs *regs)
 {
 	u8 pend = *(volatile char *)PCIMT_CSITPEND;
 	int irq;
@@ -150,13 +148,34 @@
 /*
  * hwint 4 is used for only the onboard PCnet 32.
  */
-void pciasic_hwint4(struct pt_regs *regs)
+static void pciasic_hwint4(struct pt_regs *regs)
 {
 	clear_c0_status(IE_IRQ4);
 	do_IRQ(PCIMT_IRQ_ETHERNET, regs);
 	set_c0_status(IE_IRQ4);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+	static unsigned char led_cache;
+
+	*(volatile unsigned char *) PCIMT_CSLED = ++led_cache;
+
+	if (pending & 0x0800)
+		pciasic_hwint1(regs);
+	else if (pending & 0x4000)
+		pciasic_hwint4(regs);
+	else if (pending & 0x2000)
+		pciasic_hwint3(regs);
+	else if (pending & 0x1000)
+		pciasic_hwint2(regs);
+	else if (pending & 0x8000)
+		pciasic_hwint5(regs);
+	else if (pending & 0x0400)
+		pciasic_hwint0(regs);
+}
+
 void __init init_pciasic(void)
 {
 	unsigned long flags;
@@ -176,8 +195,6 @@
 {
 	int i;
 
-	set_except_vector(0, sni_rm200_pci_handle_int);
-
 	init_i8259_irqs();			/* Integrated i8259  */
 	init_pciasic();
 
diff --git a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile
index 8fa126b..9cb9535 100644
--- a/arch/mips/tx4927/common/Makefile
+++ b/arch/mips/tx4927/common/Makefile
@@ -6,7 +6,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y	+= tx4927_prom.o tx4927_setup.o tx4927_irq.o tx4927_irq_handler.o
+obj-y	+= tx4927_prom.o tx4927_setup.o tx4927_irq.o
 
 obj-$(CONFIG_TOSHIBA_FPCIB0)	   += smsc_fdc37m81x.o
 obj-$(CONFIG_KGDB)                 += tx4927_dbgio.o
diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c
index 5ab2e2b..8ca6801 100644
--- a/arch/mips/tx4927/common/tx4927_irq.c
+++ b/arch/mips/tx4927/common/tx4927_irq.c
@@ -525,8 +525,6 @@
  */
 void __init tx4927_irq_init(void)
 {
-	extern asmlinkage void tx4927_irq_handler(void);
-
 	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n");
 
 	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n");
@@ -535,16 +533,12 @@
 	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n");
 	tx4927_irq_pic_init();
 
-	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT,
-			   "=Calling set_except_vector(tx4927_irq_handler)\n");
-	set_except_vector(0, tx4927_irq_handler);
-
 	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n");
 
 	return;
 }
 
-int tx4927_irq_nested(void)
+static int tx4927_irq_nested(void)
 {
 	int sw_irq = 0;
 	u32 level2;
@@ -582,3 +576,25 @@
 
 	return (sw_irq);
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & STATUSF_IP7)			/* cpu timer */
+		do_IRQ(TX4927_IRQ_CPU_TIMER, regs);
+	else if (pending & STATUSF_IP2) {		/* tx4927 pic */
+		unsigned int irq = tx4927_irq_nested();
+
+		if (unlikely(irq == 0)) {
+			spurious_interrupt(regs);
+			return;
+		}
+		do_IRQ(irq, regs);
+	} else if (pending & STATUSF_IP0)		/* user line 0 */
+		do_IRQ(TX4927_IRQ_USER0, regs);
+	else if (pending & STATUSF_IP1)			/* user line 1 */
+		do_IRQ(TX4927_IRQ_USER1, regs);
+	else
+		spurious_interrupt(regs);
+}
diff --git a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S
deleted file mode 100644
index 0b2ea02..0000000
--- a/arch/mips/tx4927/common/tx4927_irq_handler.S
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * linux/arch/mips/tx4927/common/tx4927_irq_handler.S
- *
- * Primary interrupt handler for tx4927 based systems
- *
- * Author: MontaVista Software, Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *         source@mvista.com
- *
- * Copyright 2001-2002 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4927/tx4927.h>
-
-		.align	5
-		NESTED(tx4927_irq_handler, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		mfc0	t0, CP0_CAUSE
-		mfc0	t1, CP0_STATUS
-		and	t0, t1
-
-		andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_ip7
-
-		/* IP6..IP3 multiplexed -- do not use */
-
-		andi	t1, t0, STATUSF_IP2	/* tx4927 pic */
-		bnez	t1, ll_ip2
-
-		andi	t1, t0, STATUSF_IP0	/* user line 0 */
-		bnez	t1, ll_ip0
-
-		andi	t1, t0, STATUSF_IP1	/* user line 1 */
-		bnez	t1, ll_ip1
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		jal	spurious_interrupt
-		nop
-		j	ret_from_irq
-		END(tx4927_irq_handler)
-
-		.align	5
-
-
-ll_ip7:
-		li	a0, TX4927_IRQ_CPU_TIMER
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_ip2:
-		jal	tx4927_irq_nested
-		nop
-		beqz 	v0, goto_spurious_interrupt
-		nop
-		move	a0, v0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-goto_spurious_interrupt:
-	j spurious_interrupt
-	nop
-
-ll_ip1:
-		li	a0, TX4927_IRQ_USER1
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_ip0:
-		li	a0, TX4927_IRQ_USER0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
index 74c95c5..2033ae7 100644
--- a/arch/mips/tx4938/common/Makefile
+++ b/arch/mips/tx4938/common/Makefile
@@ -6,6 +6,6 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y	+= prom.o setup.o irq.o irq_handler.o rtc_rx5c348.o
+obj-y	+= prom.o setup.o irq.o rtc_rx5c348.o
 obj-$(CONFIG_KGDB) += dbgio.o
 
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c
index 4f90d7f..8738051 100644
--- a/arch/mips/tx4938/common/irq.c
+++ b/arch/mips/tx4938/common/irq.c
@@ -392,11 +392,8 @@
 void __init
 tx4938_irq_init(void)
 {
-	extern asmlinkage void tx4938_irq_handler(void);
-
 	tx4938_irq_cp0_init();
 	tx4938_irq_pic_init();
-	set_except_vector(0, tx4938_irq_handler);
 
 	return;
 }
@@ -422,3 +419,21 @@
 	wbflush();
 	return (sw_irq);
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(TX4938_IRQ_CPU_TIMER, regs);
+	else if (pending & STATUSF_IP2) {
+		int irq = tx4938_irq_nested();
+		if (irq)
+			do_IRQ(irq, regs);
+		else
+			spurious_interrupt(regs);
+	} else if (pending & STATUSF_IP1)
+		do_IRQ(TX4938_IRQ_USER1, regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(TX4938_IRQ_USER0, regs);
+}
diff --git a/arch/mips/tx4938/common/irq_handler.S b/arch/mips/tx4938/common/irq_handler.S
deleted file mode 100644
index 1b2f72b..0000000
--- a/arch/mips/tx4938/common/irq_handler.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * linux/arch/mips/tx4938/common/handler.S
- *
- * Primary interrupt handler for tx4938 based systems
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4938/rbtx4938.h>
-
-
-		.align	5
-		NESTED(tx4938_irq_handler, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		mfc0	t0, CP0_CAUSE
-		mfc0	t1, CP0_STATUS
-		and	t0, t1
-
-		andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_ip7
-
-		/* IP6..IP3 multiplexed -- do not use */
-
-		andi	t1, t0, STATUSF_IP2	/* tx4938 pic */
-		bnez	t1, ll_ip2
-
-		andi	t1, t0, STATUSF_IP1	/* user line 1 */
-		bnez	t1, ll_ip1
-
-		andi	t1, t0, STATUSF_IP0	/* user line 0 */
-		bnez	t1, ll_ip0
-
-		.set	reorder
-
-		nop
-		END(tx4938_irq_handler)
-
-		.align	5
-
-
-ll_ip7:
-		li	a0, TX4938_IRQ_CPU_TIMER
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-
-ll_ip2:
-		jal	tx4938_irq_nested
-		nop
-		beqz	v0, goto_spurious_interrupt
-		nop
-		move	a0, v0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-goto_spurious_interrupt:
-		j	ret_from_irq
-
-ll_ip1:
-		li	a0, TX4938_IRQ_USER1
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_ip0:
-		li	a0, TX4938_IRQ_USER0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index 9096302..aa37397 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -2,7 +2,7 @@
 # Makefile for common code of the NEC VR4100 series.
 #
 
-obj-y				+= bcu.o cmu.o icu.o init.o int-handler.o irq.o pmu.o type.o
+obj-y				+= bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
 obj-$(CONFIG_VRC4173)		+= vrc4173.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
deleted file mode 100644
index e865234..0000000
--- a/arch/mips/vr41xx/common/int-handler.S
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * FILE NAME
- *	arch/mips/vr41xx/common/int-handler.S
- *
- * BRIEF MODULE DESCRIPTION
- *	Interrupt dispatcher for the NEC VR4100 series.
- *
- * Author: Yoichi Yuasa
- *         yyuasa@mvista.com or source@mvista.com
- *
- * Copyright 2001 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
- * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4100 series are supported.
- *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
- *  - Coped with INTASSIGN of NEC VR4133.
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
-		.text
-		.set	noreorder
-
-		.align	5
-		NESTED(vr41xx_handle_interrupt, PT_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI
-		.set	at
-		.set	noreorder
-
-		/*
-		 * Get the pending interrupts
-		 */
-		mfc0	t0, CP0_CAUSE
-		mfc0	t1, CP0_STATUS
-		andi	t0, 0xff00
-		and	t0, t0, t1
-
-		andi	t1, t0, CAUSEF_IP7	# MIPS timer interrupt
-		bnez	t1, handle_irq
-		li	a0, 7
-
-		andi	t1, t0, 0x7800		# check for Int1-4
-		beqz	t1, 1f
-
-		andi	t1, t0, CAUSEF_IP3	# check for Int1
-		bnez	t1, handle_int
-		li	a0, 3
-
-		andi	t1, t0, CAUSEF_IP4	# check for Int2
-		bnez	t1, handle_int
-		li	a0, 4
-
-		andi	t1, t0, CAUSEF_IP5	# check for Int3
-		bnez	t1, handle_int
-		li	a0, 5
-
-		andi	t1, t0, CAUSEF_IP6	# check for Int4
-		bnez	t1, handle_int
-		li	a0, 6
-
-1:
-		andi	t1, t0, CAUSEF_IP2	# check for Int0
-		bnez	t1, handle_int
-		li	a0, 2
-
-		andi	t1, t0, CAUSEF_IP0	# check for IP0
-		bnez	t1, handle_irq
-		li	a0, 0
-
-		andi	t1, t0, CAUSEF_IP1	# check for IP1
-		bnez	t1, handle_irq
-		li	a0, 1
-
-		jal	spurious_interrupt
-		nop
-		j	ret_from_irq
-		 nop
-
-handle_int:
-		jal	irq_dispatch
-		move	a1, sp
-		j	ret_from_irq
-		nop
-
-handle_irq:
-		jal	do_IRQ
-		move	a1, sp
-		j	ret_from_irq
-		END(vr41xx_handle_interrupt)
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 61aa264..86796bb 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -59,7 +59,7 @@
 
 EXPORT_SYMBOL_GPL(cascade_irq);
 
-asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
+static void irq_dispatch(unsigned int irq, struct pt_regs *regs)
 {
 	irq_cascade_t *cascade;
 	irq_desc_t *desc;
@@ -84,11 +84,32 @@
 		do_IRQ(irq, regs);
 }
 
-extern asmlinkage void vr41xx_handle_interrupt(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (pending & CAUSEF_IP7)
+		do_IRQ(7, regs);
+	else if (pending & 0x7800) {
+		if (pending & CAUSEF_IP3)
+			irq_dispatch(3, regs);
+		else if (pending & CAUSEF_IP4)
+			irq_dispatch(4, regs);
+		else if (pending & CAUSEF_IP5)
+			irq_dispatch(5, regs);
+		else if (pending & CAUSEF_IP6)
+			irq_dispatch(6, regs);
+	} else if (pending & CAUSEF_IP2)
+		irq_dispatch(2, regs);
+	else if (pending & CAUSEF_IP0)
+		do_IRQ(0, regs);
+	else if (pending & CAUSEF_IP1)
+		do_IRQ(1, regs);
+	else
+		spurious_interrupt(regs);
+}
 
 void __init arch_init_irq(void)
 {
 	mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
-
-	set_except_vector(0, vr41xx_handle_interrupt);
 }