Subject: [PATCH] Bring back R4600 V1.7 support

From: Jan-Benedict Glaw <[email-masked]>
Date: Sun, 18 Aug 2002 02:28:34 +0200

Hi!

Here's my current patch to bring back R4600 V1.7 support.

MfG, JBG

Index: include/asm-mips/war.h
===================================================================
RCS file: /usr/src/packages/foreign_CVS_reps/oss.sgi.com/linux/include/asm-mips/war.h,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 war.h
--- include/asm-mips/war.h	5 Aug 2002 23:53:38 -0000	1.1.2.3
+++ include/asm-mips/war.h	17 Aug 2002 23:53:01 -0000
@@ -65,6 +65,24 @@
  */
 #define	R5432_CP0_INTERRUPT_WAR
 
-#endif
+#endif /* CONFIG_CPU_R5432 */
+
+#ifdef R4600_V1_HIT_DCACHE_WAR
+#define r4600_v1_7_cache_war_disable_irq(CACHE_FLAGS)	\
+	do {						\
+		__save_and_cli(CACHE_FLAGS);		\
+	} while (0)
+#define r4600_v1_7_cache_war_enable_irq(CACHE_FLAGS)	\
+	do {						\
+		__restore_flags(CACHE_FLAGS);		\
+	} while (0)
+#else
+#define r4600_v1_7_cache_war_disable_irq(CACHE_FLAGS)	\
+	do {} while (0)
+#define r4600_v1_7_cache_war_enable_irq(CACHE_FLAGS)	\
+	do {} while (0)
+#endif /* R4600_V1_HIT_DCACHE_WAR */
+			
+	
 
 #endif /* _ASM_WAR_H */
Index: arch/mips/mm/c-r4k.c
===================================================================
RCS file: /usr/src/packages/foreign_CVS_reps/oss.sgi.com/linux/arch/mips/mm/c-r4k.c,v
retrieving revision 1.3.2.6
diff -u -r1.3.2.6 c-r4k.c
--- arch/mips/mm/c-r4k.c	9 Aug 2002 06:04:48 -0000	1.3.2.6
+++ arch/mips/mm/c-r4k.c	17 Aug 2002 23:55:53 -0000
@@ -77,47 +77,83 @@
 
 static inline void r4k_flush_cache_all_s16d16i16(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache16(); blast_icache16(); blast_scache16();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static inline void r4k_flush_cache_all_s32d16i16(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache16(); blast_icache16(); blast_scache32();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static inline void r4k_flush_cache_all_s64d16i16(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache16(); blast_icache16(); blast_scache64();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static inline void r4k_flush_cache_all_s128d16i16(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache16(); blast_icache16(); blast_scache128();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static inline void r4k_flush_cache_all_s32d32i32(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache32(); blast_icache32(); blast_scache32();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static inline void r4k_flush_cache_all_s64d32i32(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache32(); blast_icache32(); blast_scache64();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static inline void r4k_flush_cache_all_s128d32i32(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache32(); blast_icache32(); blast_scache128();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static inline void r4k_flush_cache_all_d16i16(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache16(); blast_icache16();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static inline void r4k_flush_cache_all_d32i32(void)
 {
+	unsigned long flags;
+
+	r4600_v1_7_cache_war_disable_irq(flags);
 	blast_dcache32(); blast_icache32();
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void
@@ -126,6 +162,7 @@
                                 unsigned long end)
 {
 	struct vm_area_struct *vma;
+	unsigned long flags;
 
 	if (mm->context == 0)
 		return;
@@ -143,6 +180,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_v1_7_cache_war_disable_irq(flags);
 			while (start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -152,6 +190,7 @@
 					blast_scache16_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_v1_7_cache_war_enable_irq(flags);
 		}
 	}
 }
@@ -162,6 +201,7 @@
                                 unsigned long end)
 {
 	struct vm_area_struct *vma;
+	unsigned long flags;
 
 	if (mm->context == 0)
 		return;
@@ -179,6 +219,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_v1_7_cache_war_disable_irq(flags);
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -188,6 +229,7 @@
 					blast_scache32_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_v1_7_cache_war_enable_irq(flags);
 		}
 	}
 }
@@ -197,6 +239,7 @@
 					    unsigned long end)
 {
 	struct vm_area_struct *vma;
+	unsigned long flags;
 
 	if (mm->context == 0)
 		return;
@@ -214,6 +257,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_v1_7_cache_war_disable_irq(flags);
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -223,6 +267,7 @@
 					blast_scache64_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_v1_7_cache_war_enable_irq(flags);
 		}
 	}
 }
@@ -232,6 +277,7 @@
 					     unsigned long end)
 {
 	struct vm_area_struct *vma;
+	unsigned long flags;
 
 	if (mm->context == 0)
 		return;
@@ -249,6 +295,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_v1_7_cache_war_disable_irq(flags);
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -258,6 +305,7 @@
 					blast_scache128_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_v1_7_cache_war_enable_irq(flags);
 		}
 	}
 }
@@ -267,6 +315,7 @@
 					    unsigned long end)
 {
 	struct vm_area_struct *vma;
+	unsigned long flags;
 
 	if (mm->context == 0)
 		return;
@@ -284,6 +333,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_v1_7_cache_war_disable_irq(flags);
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -293,6 +343,7 @@
 					blast_scache32_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_v1_7_cache_war_enable_irq(flags);
 		}
 	}
 }
@@ -302,6 +353,7 @@
 					    unsigned long end)
 {
 	struct vm_area_struct *vma;
+	unsigned long flags;
 
 	if (mm->context == 0)
 		return;
@@ -319,6 +371,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_v1_7_cache_war_disable_irq(flags);
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -328,6 +381,7 @@
 					blast_scache64_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_v1_7_cache_war_enable_irq(flags);
 		}
 	}
 }
@@ -337,6 +391,7 @@
 					     unsigned long end)
 {
 	struct vm_area_struct *vma;
+	unsigned long flags;
 
 	if (mm->context == 0)
 		return;
@@ -354,6 +409,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_v1_7_cache_war_disable_irq(flags);
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -363,6 +419,7 @@
 					blast_scache128_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_v1_7_cache_war_enable_irq(flags);
 		}
 	}
 }
@@ -371,11 +428,15 @@
 					 unsigned long start,
 					 unsigned long end)
 {
+	unsigned long flags;
+
 	if (mm->context != 0) {
 #ifdef DEBUG_CACHE
 		printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
 #endif
+		r4600_v1_7_cache_war_disable_irq(flags);
 		blast_dcache16(); blast_icache16();
+		r4600_v1_7_cache_war_enable_irq(flags);
 	}
 }
 
@@ -383,11 +444,15 @@
 					 unsigned long start,
 					 unsigned long end)
 {
+	unsigned long flags;
+
 	if (mm->context != 0) {
 #ifdef DEBUG_CACHE
 		printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
 #endif
+		r4600_v1_7_cache_war_disable_irq(flags);
 		blast_dcache32(); blast_icache32();
+		r4600_v1_7_cache_war_enable_irq(flags);
 	}
 }
 
@@ -490,6 +555,7 @@
 					   unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -504,6 +570,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -533,12 +600,14 @@
 	} else
 		blast_scache16_page(page);
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma,
 					   unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -553,6 +622,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -581,12 +651,14 @@
 	} else
 		blast_scache32_page(page);
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma,
 					   unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -601,6 +673,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -629,12 +702,14 @@
 	} else
 		blast_scache64_page(page);
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma,
 					    unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -649,6 +724,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -678,12 +754,14 @@
 	} else
 		blast_scache128_page(page);
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma,
 					   unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -698,6 +776,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -727,12 +806,14 @@
 	} else
 		blast_scache32_page(page);
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma,
 					   unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -747,6 +828,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -776,12 +858,14 @@
 	} else
 		blast_scache64_page(page);
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma,
 					    unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -796,6 +880,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -824,12 +909,14 @@
 	} else
 		blast_scache128_page(page);
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma,
 					unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -844,6 +931,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -872,12 +960,14 @@
 		blast_dcache16_page_indexed(page);
 	}
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma,
 					unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -892,6 +982,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -921,12 +1012,14 @@
 		blast_dcache32_page_indexed(page);
 	}
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma,
 					      unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
@@ -941,6 +1034,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_v1_7_cache_war_disable_irq(flags);
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -970,6 +1064,7 @@
 		blast_dcache32_page_indexed(page ^ dcache_waybit);
 	}
 out:
+	r4600_v1_7_cache_war_enable_irq(flags);
 }
 
 /* If the addresses passed to these routines are valid, they are
@@ -1063,7 +1158,7 @@
 		flush_cache_all();
 	} else {
 #ifdef R4600_V2_HIT_CACHEOP_WAR
-		/* Workaround for R4600 bug.  See comment in <asm/war>. */
+		/* Workaround for R4600 bug.  See comment in <asm/war.h>. */
 		__save_and_cli(flags);
 		*(volatile unsigned long *)KSEG1;
 #endif

-- 
Jan-Benedict Glaw   .   [email-masked]   .   +49-172-7608481
	 -- New APT-Proxy written in shell script --
	   http://lug-owl.de/~jbglaw/software/ap2/

---

From: Jan-Benedict Glaw <[email-masked]>
Date: Tue, 20 Aug 2002 13:33:29 +0200

On Sun, 2002-08-18 02:28:34 +0200, Jan-Benedict Glaw <[email-masked]>
> Here's my current patch to bring back R4600 V1.7 support.
[snip]

Hi Ralf!

Please accept the patch (from my previous mail). I'm using it now for
two days, and I've got one mail telling me that it works for its sender.
No mails about crashed systems so far...

MfG, JBG

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 20 Aug 2002 15:30:22 +0200 (MET DST)

> two days, and I've got one mail telling me that it works for its sender.

 Ugh, this should be a separate set of functions selected at the run time. 
It should be fairly trivial to rewrite it this way (best done with
processor-specific functions expanded from common templates for ease of
maintenance), but the size of the resulting interrupt masking window is
unacceptable.  A more finegrained implementation is really desireable,
with an interrupt enable window every page or so, but your proposal should
be fair enough for the sake of usability once rewritten as I suggested.

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 20 Aug 2002 15:55:34 +0200 (MET DST)

> be fair enough for the sake of usability once rewritten as I suggested.

 An additional thought that just came to my mind: it might be possible to
avoid masking interrupts with a dummy ll/sc pair only checking if an
interrupt happened within the critical code.  It should be easy to
validate since only a single mask of a processor would make use of the
code.  The real question is: "Do the affected cache operations corrupt any
state or do they only work on wrong lines?"  If the latter, the approach
should work for all operations except from "Hit_Invalidate_D" that
corrupts state by definition (but it isn't used by any R4k processor, so
it may simply be replaced with a panic()).  Unfortunately, the knowledge
does no longer exist within IDT, but maybe someone else knows?

---

From: Jan-Benedict Glaw <[email-masked]>
Date: Tue, 20 Aug 2002 16:10:13 +0200

On Tue, 2002-08-20 15:30:22 +0200, Maciej W. Rozycki <[email-masked]>
> processor-specific functions expanded from common templates for ease of

Actually, I had written all that using separate functions before, but
neither I nor Ralf liked this approach (because it adds hundreds LOC to
.../c-r4k.c). Ralf then suggested writing it using macros, so I did.

-*- Proposal -*-
There are IMHO two goals, one for near future, one for following day
(after first goal has reached):

	1. There are many (equally looking) functions in c-r4k.c . It
	   would be nice to not have the (more-or-less) function body 10
	   times there.
	2. it would be nice to not have like 50 functions around, but to
	   better have a flexible way to do what needs to be done.
	   Something like an (initdata) array containing PRId and
	   function pointers (or other info) on "what needs to be
	   done".

The first one seems quite easy. Looking eg. at Alphas, they have a macro
defining a whole function (which inserts a correct function name by
supplied arguments etc.). This way, 

..

could go away by: (there _will_ be bugs. 100% untested, and I'm a bad
preprocessor coder:-)

#define FUNC_R4K_FLUSH_CACHE_ALL(NAME, SC, DC, IC)		\
	static inline void					\
	r4k_flush_cache_all_##NAME(void)			\
	{							\
		blast_dcache##DC();				\
		blast_icache##IC();				\
		blase_scache##SC();				\
	}

and then writing:

FUNC_R4K_FLUSH_CACHE_ALL(s128d16i16, 128, 16, 16)
FUNC_R4K_FLUSH_CACHE_ALL(s32d32i32,   32, 32, 32)
FUNC_R4K_FLUSH_CACHE_ALL(s64d32i32,   64, 32, 32)
...

instead. The __save_and_cli()/__restore_flags() functions could be done
as well as all the remaining others. That would pollute namespace like
it does today, but the .c file will be 80% smaller or so:

$ wc -l c-r4k.c 
   2422 c-r4k.c

MfG, JBG

---

From: Ralf Baechle <[email-masked]>
Date: Tue, 20 Aug 2002 16:03:11 +0200

> does no longer exist within IDT, but maybe someone else knows? 

I was thinking about that already but the erratas don't provide enough
details.  The only problem I can see is that ll/sc are fairly slow on some
architectures.  They're supposed to be quite light according to the docs
but in reality I benchmarked ~ 13 cycles for a spinlock on a R10000 and
~ 44 on a more recent chip.

  Ralf

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 20 Aug 2002 16:36:55 +0200 (MET DST)

> details.  The only problem I can see is that ll/sc are fairly slow on some

 Well, IDT didn't seem much mobilized with my single query.  Maybe if
there was more interest expressed, someone would go digging through old
resources for real.

> ~ 44 on a more recent chip.

 Well, the code would only execute on an R4600 V1.7...

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 20 Aug 2002 16:46:33 +0200 (MET DST)

> .../c-r4k.c). Ralf then suggested writing it using macros, so I did.

 Obviously you'd put all the R4600 stuff in a separate file (the second
and the third being the regular R4k stuff and the template macros sourced
by the first and the second one).  That would aid diffing as well. 

> supplied arguments etc.). This way, 
[...]

 Definitely.  The other one is done by Alphas as well since RTH wrote
generic kernel support.  I consider such a feature one of goals for MIPS
as well, so such a rewrite would be a necessary part of the design sooner
or later anyway.