|  | @@ -665,3 +665,176 @@ do {								\
 | 
	
		
			
				|  |  |  	: "r" (val), "i" (counter));				\
 | 
	
		
			
				|  |  |  } while (0)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Macros to access the system control coprocessor
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __read_32bit_c0_register(source, sel)				\
 | 
	
		
			
				|  |  | +({ int __res;								\
 | 
	
		
			
				|  |  | +	if (sel == 0)							\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			"mfc0\t%0, " #source "\n\t"			\
 | 
	
		
			
				|  |  | +			: "=r" (__res));				\
 | 
	
		
			
				|  |  | +	else								\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips32\n\t"				\
 | 
	
		
			
				|  |  | +			"mfc0\t%0, " #source ", " #sel "\n\t"		\
 | 
	
		
			
				|  |  | +			".set\tmips0\n\t"				\
 | 
	
		
			
				|  |  | +			: "=r" (__res));				\
 | 
	
		
			
				|  |  | +	__res;								\
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __read_64bit_c0_register(source, sel)				\
 | 
	
		
			
				|  |  | +({ unsigned long long __res;						\
 | 
	
		
			
				|  |  | +	if (sizeof(unsigned long) == 4)					\
 | 
	
		
			
				|  |  | +		__res = __read_64bit_c0_split(source, sel);		\
 | 
	
		
			
				|  |  | +	else if (sel == 0)						\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips3\n\t"				\
 | 
	
		
			
				|  |  | +			"dmfc0\t%0, " #source "\n\t"			\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: "=r" (__res));				\
 | 
	
		
			
				|  |  | +	else								\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips64\n\t"				\
 | 
	
		
			
				|  |  | +			"dmfc0\t%0, " #source ", " #sel "\n\t"		\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: "=r" (__res));				\
 | 
	
		
			
				|  |  | +	__res;								\
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __write_32bit_c0_register(register, sel, value)			\
 | 
	
		
			
				|  |  | +do {									\
 | 
	
		
			
				|  |  | +	if (sel == 0)							\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			"mtc0\t%z0, " #register "\n\t"			\
 | 
	
		
			
				|  |  | +			: : "Jr" ((unsigned int)(value)));		\
 | 
	
		
			
				|  |  | +	else								\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips32\n\t"				\
 | 
	
		
			
				|  |  | +			"mtc0\t%z0, " #register ", " #sel "\n\t"	\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: : "Jr" ((unsigned int)(value)));		\
 | 
	
		
			
				|  |  | +} while (0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __write_64bit_c0_register(register, sel, value)			\
 | 
	
		
			
				|  |  | +do {									\
 | 
	
		
			
				|  |  | +	if (sizeof(unsigned long) == 4)					\
 | 
	
		
			
				|  |  | +		__write_64bit_c0_split(register, sel, value);		\
 | 
	
		
			
				|  |  | +	else if (sel == 0)						\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips3\n\t"				\
 | 
	
		
			
				|  |  | +			"dmtc0\t%z0, " #register "\n\t"			\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: : "Jr" (value));				\
 | 
	
		
			
				|  |  | +	else								\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips64\n\t"				\
 | 
	
		
			
				|  |  | +			"dmtc0\t%z0, " #register ", " #sel "\n\t"	\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: : "Jr" (value));				\
 | 
	
		
			
				|  |  | +} while (0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __read_ulong_c0_register(reg, sel)				\
 | 
	
		
			
				|  |  | +	((sizeof(unsigned long) == 4) ?					\
 | 
	
		
			
				|  |  | +	(unsigned long) __read_32bit_c0_register(reg, sel) :		\
 | 
	
		
			
				|  |  | +	(unsigned long) __read_64bit_c0_register(reg, sel))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __write_ulong_c0_register(reg, sel, val)			\
 | 
	
		
			
				|  |  | +do {									\
 | 
	
		
			
				|  |  | +	if (sizeof(unsigned long) == 4)					\
 | 
	
		
			
				|  |  | +		__write_32bit_c0_register(reg, sel, val);		\
 | 
	
		
			
				|  |  | +	else								\
 | 
	
		
			
				|  |  | +		__write_64bit_c0_register(reg, sel, val);		\
 | 
	
		
			
				|  |  | +} while (0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * On RM7000/RM9000 these are uses to access cop0 set 1 registers
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +#define __read_32bit_c0_ctrl_register(source)				\
 | 
	
		
			
				|  |  | +({ int __res;								\
 | 
	
		
			
				|  |  | +	__asm__ __volatile__(						\
 | 
	
		
			
				|  |  | +		"cfc0\t%0, " #source "\n\t"				\
 | 
	
		
			
				|  |  | +		: "=r" (__res));					\
 | 
	
		
			
				|  |  | +	__res;								\
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __write_32bit_c0_ctrl_register(register, value)			\
 | 
	
		
			
				|  |  | +do {									\
 | 
	
		
			
				|  |  | +	__asm__ __volatile__(						\
 | 
	
		
			
				|  |  | +		"ctc0\t%z0, " #register "\n\t"				\
 | 
	
		
			
				|  |  | +		: : "Jr" ((unsigned int)(value)));			\
 | 
	
		
			
				|  |  | +} while (0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * These versions are only needed for systems with more than 38 bits of
 | 
	
		
			
				|  |  | + * physical address space running the 32-bit kernel.  That's none atm :-)
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +#define __read_64bit_c0_split(source, sel)				\
 | 
	
		
			
				|  |  | +({									\
 | 
	
		
			
				|  |  | +	unsigned long long __val;					\
 | 
	
		
			
				|  |  | +	unsigned long __flags;						\
 | 
	
		
			
				|  |  | +									\
 | 
	
		
			
				|  |  | +	local_irq_save(__flags);					\
 | 
	
		
			
				|  |  | +	if (sel == 0)							\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips64\n\t"				\
 | 
	
		
			
				|  |  | +			"dmfc0\t%M0, " #source "\n\t"			\
 | 
	
		
			
				|  |  | +			"dsll\t%L0, %M0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"dsra\t%M0, %M0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"dsra\t%L0, %L0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: "=r" (__val));				\
 | 
	
		
			
				|  |  | +	else								\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips64\n\t"				\
 | 
	
		
			
				|  |  | +			"dmfc0\t%M0, " #source ", " #sel "\n\t"		\
 | 
	
		
			
				|  |  | +			"dsll\t%L0, %M0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"dsra\t%M0, %M0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"dsra\t%L0, %L0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: "=r" (__val));				\
 | 
	
		
			
				|  |  | +	local_irq_restore(__flags);					\
 | 
	
		
			
				|  |  | +									\
 | 
	
		
			
				|  |  | +	__val;								\
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define __write_64bit_c0_split(source, sel, val)			\
 | 
	
		
			
				|  |  | +do {									\
 | 
	
		
			
				|  |  | +	unsigned long __flags;						\
 | 
	
		
			
				|  |  | +									\
 | 
	
		
			
				|  |  | +	local_irq_save(__flags);					\
 | 
	
		
			
				|  |  | +	if (sel == 0)							\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips64\n\t"				\
 | 
	
		
			
				|  |  | +			"dsll\t%L0, %L0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"dsrl\t%L0, %L0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"dsll\t%M0, %M0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"or\t%L0, %L0, %M0\n\t"				\
 | 
	
		
			
				|  |  | +			"dmtc0\t%L0, " #source "\n\t"			\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: : "r" (val));					\
 | 
	
		
			
				|  |  | +	else								\
 | 
	
		
			
				|  |  | +		__asm__ __volatile__(					\
 | 
	
		
			
				|  |  | +			".set\tmips64\n\t"				\
 | 
	
		
			
				|  |  | +			"dsll\t%L0, %L0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"dsrl\t%L0, %L0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"dsll\t%M0, %M0, 32\n\t"			\
 | 
	
		
			
				|  |  | +			"or\t%L0, %L0, %M0\n\t"				\
 | 
	
		
			
				|  |  | +			"dmtc0\t%L0, " #source ", " #sel "\n\t"		\
 | 
	
		
			
				|  |  | +			".set\tmips0"					\
 | 
	
		
			
				|  |  | +			: : "r" (val));					\
 | 
	
		
			
				|  |  | +	local_irq_restore(__flags);					\
 | 
	
		
			
				|  |  | +} while (0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define read_c0_index()		__read_32bit_c0_register($0, 0)
 | 
	
		
			
				|  |  | +#define write_c0_index(val)	__write_32bit_c0_register($0, 0, val)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define read_c0_random()	__read_32bit_c0_register($1, 0)
 | 
	
		
			
				|  |  | +#define write_c0_random(val)	__write_32bit_c0_register($1, 0, val)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define read_c0_entrylo0()	__read_ulong_c0_register($2, 0)
 | 
	
		
			
				|  |  | +#define write_c0_entrylo0(val)	__write_ulong_c0_register($2, 0, val)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define read_c0_entrylo1()	__read_ulong_c0_register($3, 0)
 |