/**************************************************************************
 *									  *
 *		 Copyright (C) 1995, Silicon Graphics, Inc.		  *
 *									  *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
 *  are protected by Federal copyright law.  They  may  not be disclosed  *
 *  to  third  parties  or copied or duplicated in any form, in whole or  *
 *  in part, without the prior written consent of Silicon Graphics, Inc.  *
 *									  *
 **************************************************************************/

/**************************************************************************
 *
 *  $Revision: 1.13 $
 *  $Date: 1997/02/11 08:15:34 $
 *  $Source: /hosts/gate3/exdisk2/cvs/N64OS/Master/cvsmdev2/PR/include/R4300.h,v $
 *
 **************************************************************************/

#ifndef __R4300_H__
#define __R4300_H__

#include <PR/ultratypes.h>

/*
 * Segment base addresses and sizes
 */
#define	KUBASE		0
#define	KUSIZE		0x80000000
#define	K0BASE		0x80000000
#define	K0SIZE		0x20000000
#define	K1BASE		0xA0000000
#define	K1SIZE		0x20000000
#define	K2BASE		0xC0000000
#define	K2SIZE		0x20000000

/*
 * Exception vectors
 */
#define SIZE_EXCVEC	0x80			/* Size of an exc. vec */
#define	UT_VEC		K0BASE			/* utlbmiss vector */
#define	R_VEC		(K1BASE+0x1fc00000)	/* reset vector */
#define	XUT_VEC		(K0BASE+0x80)		/* extended address tlbmiss */
#define	ECC_VEC		(K0BASE+0x100)		/* Ecc exception vector */
#define	E_VEC		(K0BASE+0x180)		/* Gen. exception vector */

/*
 * Address conversion macros
 */
#ifdef _LANGUAGE_ASSEMBLY

#define	K0_TO_K1(x)	((x)|0xA0000000)	/* kseg0 to kseg1 */
#define	K1_TO_K0(x)	((x)&0x9FFFFFFF)	/* kseg1 to kseg0 */
#define	K0_TO_PHYS(x)	((x)&0x1FFFFFFF)	/* kseg0 to physical */
#define	K1_TO_PHYS(x)	((x)&0x1FFFFFFF)	/* kseg1 to physical */
#define	KDM_TO_PHYS(x)	((x)&0x1FFFFFFF)	/* direct mapped to physical */
#define	PHYS_TO_K0(x)	((x)|0x80000000)	/* physical to kseg0 */
#define	PHYS_TO_K1(x)	((x)|0xA0000000)	/* physical to kseg1 */

#else /* _LANGUAGE_C */

#define	K0_TO_K1(x)	((u32)(x)|0xA0000000)	/* kseg0 to kseg1 */
#define	K1_TO_K0(x)	((u32)(x)&0x9FFFFFFF)	/* kseg1 to kseg0 */
#define	K0_TO_PHYS(x)	((u32)(x)&0x1FFFFFFF)	/* kseg0 to physical */
#define	K1_TO_PHYS(x)	((u32)(x)&0x1FFFFFFF)	/* kseg1 to physical */
#define	KDM_TO_PHYS(x)	((u32)(x)&0x1FFFFFFF)	/* direct mapped to physical */
#define	PHYS_TO_K0(x)	((u32)(x)|0x80000000)	/* physical to kseg0 */
#define	PHYS_TO_K1(x)	((u32)(x)|0xA0000000)	/* physical to kseg1 */

#endif	/* _LANGUAGE_ASSEMBLY */

/*
 * Address predicates
 */
#define	IS_KSEG0(x)	((u32)(x) >= K0BASE && (u32)(x) < K1BASE)
#define	IS_KSEG1(x)	((u32)(x) >= K1BASE && (u32)(x) < K2BASE)
#define	IS_KSEGDM(x)	((u32)(x) >= K0BASE && (u32)(x) < K2BASE)
#define	IS_KSEG2(x)	((u32)(x) >= K2BASE && (u32)(x) < KPTE_SHDUBASE)
#define	IS_KPTESEG(x)	((u32)(x) >= KPTE_SHDUBASE)
#define	IS_KUSEG(x)	((u32)(x) < K0BASE)

/*
 * TLB size constants
 */

#define	NTLBENTRIES	31	/* entry 31 is reserved by rdb */

#define	TLBHI_VPN2MASK		0xffffe000
#define	TLBHI_VPN2SHIFT		13
#define	TLBHI_PIDMASK		0xff
#define	TLBHI_PIDSHIFT		0
#define	TLBHI_NPID		255		/* 255 to fit in 8 bits */

#define	TLBLO_PFNMASK		0x3fffffc0
#define	TLBLO_PFNSHIFT		6
#define	TLBLO_CACHMASK		0x38		/* cache coherency algorithm */
#define TLBLO_CACHSHIFT		3
#define TLBLO_UNCACHED		0x10		/* not cached */
#define TLBLO_NONCOHRNT		0x18		/* Cacheable non-coherent */
#define TLBLO_EXLWR		0x28		/* Exclusive write */
#define	TLBLO_D			0x4		/* writeable */
#define	TLBLO_V			0x2		/* valid bit */
#define	TLBLO_G			0x1		/* global access bit */

#define	TLBINX_PROBE		0x80000000
#define	TLBINX_INXMASK		0x3f
#define	TLBINX_INXSHIFT		0

#define	TLBRAND_RANDMASK	0x3f
#define	TLBRAND_RANDSHIFT	0

#define	TLBWIRED_WIREDMASK	0x3f

#define	TLBCTXT_BASEMASK	0xff800000
#define	TLBCTXT_BASESHIFT	23
#define TLBCTXT_BASEBITS	9

#define	TLBCTXT_VPNMASK		0x7ffff0
#define	TLBCTXT_VPNSHIFT	4

#define TLBPGMASK_4K		0x0
#define TLBPGMASK_16K		0x6000
#define TLBPGMASK_64K		0x1e000

/*
 * Status register
 */
#define	SR_CUMASK	0xf0000000	/* coproc usable bits */

#define	SR_CU3		0x80000000	/* Coprocessor 3 usable */
#define	SR_CU2		0x40000000	/* Coprocessor 2 usable */
#define	SR_CU1		0x20000000	/* Coprocessor 1 usable */
#define	SR_CU0		0x10000000	/* Coprocessor 0 usable */
#define	SR_RP		0x08000000	/* Reduced power (quarter speed) */
#define	SR_FR		0x04000000	/* MIPS III FP register mode */
#define	SR_RE		0x02000000	/* Reverse endian */
#define	SR_ITS		0x01000000	/* Instruction trace support */
#define	SR_BEV		0x00400000	/* Use boot exception vectors */
#define	SR_TS		0x00200000	/* TLB shutdown */
#define	SR_SR		0x00100000	/* Soft reset occured */
#define	SR_CH		0x00040000	/* Cache hit for last 'cache' op */
#define	SR_CE		0x00020000	/* Create ECC */
#define	SR_DE		0x00010000	/* ECC of parity does not cause error */

/*
 * Interrupt enable bits
 * (NOTE: bits set to 1 enable the corresponding level interrupt)
 */
#define	SR_IMASK	0x0000ff00	/* Interrupt mask */
#define	SR_IMASK8	0x00000000	/* mask level 8 */
#define	SR_IMASK7	0x00008000	/* mask level 7 */
#define	SR_IMASK6	0x0000c000	/* mask level 6 */
#define	SR_IMASK5	0x0000e000	/* mask level 5 */
#define	SR_IMASK4	0x0000f000	/* mask level 4 */
#define	SR_IMASK3	0x0000f800	/* mask level 3 */
#define	SR_IMASK2	0x0000fc00	/* mask level 2 */
#define	SR_IMASK1	0x0000fe00	/* mask level 1 */
#define	SR_IMASK0	0x0000ff00	/* mask level 0 */

#define	SR_IBIT8	0x00008000	/* bit level 8 */
#define	SR_IBIT7	0x00004000	/* bit level 7 */
#define	SR_IBIT6	0x00002000	/* bit level 6 */
#define	SR_IBIT5	0x00001000	/* bit level 5 */
#define	SR_IBIT4	0x00000800	/* bit level 4 */
#define	SR_IBIT3	0x00000400	/* bit level 3 */
#define	SR_IBIT2	0x00000200	/* bit level 2 */
#define	SR_IBIT1	0x00000100	/* bit level 1 */

#define	SR_IMASKSHIFT	8

#define	SR_KX		0x00000080	/* extended-addr TLB vec in kernel */
#define	SR_SX		0x00000040	/* xtended-addr TLB vec supervisor */
#define	SR_UX		0x00000020	/* xtended-addr TLB vec in user mode */
#define	SR_KSU_MASK	0x00000018	/* mode mask */
#define	SR_KSU_USR	0x00000010	/* user mode */
#define	SR_KSU_SUP	0x00000008	/* supervisor mode */
#define	SR_KSU_KER	0x00000000	/* kernel mode */
#define	SR_ERL		0x00000004	/* Error level, 1=>cache error */
#define	SR_EXL		0x00000002	/* Exception level, 1=>exception */
#define	SR_IE		0x00000001	/* interrupt enable, 1=>enable */

/*
 * Cause Register
 */
#define	CAUSE_BD	0x80000000	/* Branch delay slot */
#define	CAUSE_CEMASK	0x30000000	/* coprocessor error */
#define	CAUSE_CESHIFT	28

/* Interrupt pending bits */
#define	CAUSE_IP8	0x00008000	/* External level 8 pending - COMPARE */
#define	CAUSE_IP7	0x00004000	/* External level 7 pending - INT4 */
#define	CAUSE_IP6	0x00002000	/* External level 6 pending - INT3 */
#define	CAUSE_IP5	0x00001000	/* External level 5 pending - INT2 */
#define	CAUSE_IP4	0x00000800	/* External level 4 pending - INT1 */
#define	CAUSE_IP3	0x00000400	/* External level 3 pending - INT0 */
#define	CAUSE_SW2	0x00000200	/* Software level 2 pending */
#define	CAUSE_SW1	0x00000100	/* Software level 1 pending */

#define	CAUSE_IPMASK	0x0000FF00	/* Pending interrupt mask */
#define	CAUSE_IPSHIFT	8

#define	CAUSE_EXCMASK	0x0000007C	/* Cause code bits */

#define	CAUSE_EXCSHIFT	2

/* Cause register exception codes */

#define	EXC_CODE(x)	((x)<<2)

/* Hardware exception codes */
#define	EXC_INT		EXC_CODE(0)	/* interrupt */
#define	EXC_MOD		EXC_CODE(1)	/* TLB mod */
#define	EXC_RMISS	EXC_CODE(2)	/* Read TLB Miss */
#define	EXC_WMISS	EXC_CODE(3)	/* Write TLB Miss */
#define	EXC_RADE	EXC_CODE(4)	/* Read Address Error */
#define	EXC_WADE	EXC_CODE(5)	/* Write Address Error */
#define	EXC_IBE		EXC_CODE(6)	/* Instruction Bus Error */
#define	EXC_DBE		EXC_CODE(7)	/* Data Bus Error */
#define	EXC_SYSCALL	EXC_CODE(8)	/* SYSCALL */
#define	EXC_BREAK	EXC_CODE(9)	/* BREAKpoint */
#define	EXC_II		EXC_CODE(10)	/* Illegal Instruction */
#define	EXC_CPU		EXC_CODE(11)	/* CoProcessor Unusable */
#define	EXC_OV		EXC_CODE(12)	/* OVerflow */
#define	EXC_TRAP	EXC_CODE(13)	/* Trap exception */
#define	EXC_VCEI	EXC_CODE(14)	/* Virt. Coherency on Inst. fetch */
#define	EXC_FPE		EXC_CODE(15)	/* Floating Point Exception */
#define	EXC_WATCH	EXC_CODE(23)	/* Watchpoint reference */
#define	EXC_VCED	EXC_CODE(31)	/* Virt. Coherency on data read */

/* C0_PRID Defines */
#define	C0_IMPMASK	0xff00
#define	C0_IMPSHIFT	8
#define C0_REVMASK	0xff
#define C0_MAJREVMASK	0xf0
#define	C0_MAJREVSHIFT	4
#define C0_MINREVMASK	0xf

/*
 * Coprocessor 0 operations
 */
#define	C0_READI  0x1		/* read ITLB entry addressed by C0_INDEX */
#define	C0_WRITEI 0x2		/* write ITLB entry addressed by C0_INDEX */
#define	C0_WRITER 0x6		/* write ITLB entry addressed by C0_RAND */
#define	C0_PROBE  0x8		/* probe for ITLB entry addressed by TLBHI */
#define	C0_RFE	  0x10		/* restore for exception */

/*
 * 'cache' instruction definitions
 */

/* Target cache */
#define	CACH_PI		0x0	/* specifies primary inst. cache */
#define	CACH_PD		0x1	/* primary data cache */
#define	CACH_SI		0x2	/* secondary instruction cache */
#define	CACH_SD		0x3	/* secondary data cache */

/* Cache operations */
#define	C_IINV		0x0	/* index invalidate (inst, 2nd inst) */
#define	C_IWBINV	0x0	/* index writeback inval (d, sd) */
#define	C_ILT		0x4	/* index load tag (all) */
#define	C_IST		0x8	/* index store tag (all) */
#define	C_CDX		0xc	/* create dirty exclusive (d, sd) */
#define	C_HINV		0x10	/* hit invalidate (all) */
#define	C_HWBINV	0x14	/* hit writeback inv. (d, sd) */
#define	C_FILL		0x14	/* fill (i) */
#define	C_HWB		0x18	/* hit writeback (i, d, sd) */
#define	C_HSV		0x1c	/* hit set virt. (si, sd) */

/*
 * Cache size definitions
 */
#define	ICACHE_SIZE		0x4000			/* 16K */
#define	ICACHE_LINESIZE		32			/* 8 words */
#define	ICACHE_LINEMASK		(ICACHE_LINESIZE-1)

#define	DCACHE_SIZE		0x2000			/* 8K */
#define	DCACHE_LINESIZE		16			/* 4 words */
#define	DCACHE_LINEMASK		(DCACHE_LINESIZE-1)

/*
 * C0_CONFIG register definitions
 */
#define	CONFIG_CM	0x80000000	/* 1 == Master-Checker enabled */
#define	CONFIG_EC	0x70000000	/* System Clock ratio */
#define	CONFIG_EC_1_1	0x6		/* System Clock ratio 1 :1 */
#define	CONFIG_EC_3_2	0x7		/* System Clock ratio 1.5 :1 */
#define	CONFIG_EC_2_1	0x0		/* System Clock ratio 2 :1 */
#define	CONFIG_EC_3_1	0x1		/* System Clock ratio 3 :1 */
#define	CONFIG_EP	0x0f000000	/* Transmit Data Pattern */
#define	CONFIG_SB	0x00c00000	/* Secondary cache block size */

#define	CONFIG_SS	0x00200000	/* Split scache: 0 == I&D combined */
#define	CONFIG_SW	0x00100000	/* scache port: 0==128, 1==64 */
#define	CONFIG_EW	0x000c0000	/* System Port width: 0==64, 1==32 */
#define	CONFIG_SC	0x00020000	/* 0 -> 2nd cache present */
#define	CONFIG_SM	0x00010000	/* 0 -> Dirty Shared Coherency enabled*/
#define	CONFIG_BE	0x00008000	/* Endian-ness: 1 --> BE */
#define	CONFIG_EM	0x00004000	/* 1 -> ECC mode, 0 -> parity */
#define	CONFIG_EB	0x00002000	/* Block order:1->sequent,0->subblock */

#define	CONFIG_IC	0x00000e00	/* Primary Icache size */
#define	CONFIG_DC	0x000001c0	/* Primary Dcache size */
#define	CONFIG_IB	0x00000020	/* Icache block size */
#define	CONFIG_DB	0x00000010	/* Dcache block size */
#define	CONFIG_CU	0x00000008	/* Update on Store-conditional */
#define	CONFIG_K0	0x00000007	/* K0SEG Coherency algorithm */

#define	CONFIG_UNCACHED		0x00000002	/* K0 is uncached */
#define	CONFIG_NONCOHRNT	0x00000003
#define	CONFIG_COHRNT_EXLWR	0x00000005
#define	CONFIG_SB_SHFT	22		/* shift SB to bit position 0 */
#define	CONFIG_IC_SHFT	9		/* shift IC to bit position 0 */
#define	CONFIG_DC_SHFT	6		/* shift DC to bit position 0 */
#define	CONFIG_BE_SHFT	15		/* shift BE to bit position 0 */

/*
 * C0_TAGLO definitions for setting/getting cache states and physaddr bits
 */
#define SADDRMASK  	0xFFFFE000	/* 31..13 -> scache paddr bits 35..17 */
#define SVINDEXMASK	0x00000380	/* 9..7: prim virt index bits 14..12 */
#define SSTATEMASK	0x00001c00	/* bits 12..10 hold scache line state */
#define SINVALID	0x00000000	/* invalid --> 000 == state 0 */
#define SCLEANEXCL	0x00001000	/* clean exclusive --> 100 == state 4 */
#define SDIRTYEXCL	0x00001400	/* dirty exclusive --> 101 == state 5 */
#define SECC_MASK	0x0000007f	/* low 7 bits are ecc for the tag */
#define SADDR_SHIFT	4		/* shift STagLo (31..13) to 35..17 */

#define PADDRMASK	0xFFFFFF00	/* PTagLo31..8->prim paddr bits35..12 */
#define PADDR_SHIFT	4		/* roll bits 35..12 down to 31..8 */
#define PSTATEMASK	0x00C0		/* bits 7..6 hold primary line state */
#define PINVALID	0x0000		/* invalid --> 000 == state 0 */
#define PCLEANEXCL	0x0080		/* clean exclusive --> 10 == state 2 */
#define PDIRTYEXCL	0x00C0		/* dirty exclusive --> 11 == state 3 */
#define PPARITY_MASK	0x0001		/* low bit is parity bit (even). */

/*
 * C0_CACHE_ERR definitions.
 */
#define	CACHERR_ER		0x80000000	/* 0: inst ref, 1: data ref */
#define	CACHERR_EC		0x40000000	/* 0: primary, 1: secondary */
#define	CACHERR_ED		0x20000000	/* 1: data error */
#define	CACHERR_ET		0x10000000	/* 1: tag error */
#define	CACHERR_ES		0x08000000	/* 1: external ref, e.g. snoop*/
#define	CACHERR_EE		0x04000000	/* error on SysAD bus */
#define	CACHERR_EB		0x02000000	/* complicated, see spec. */
#define	CACHERR_EI		0x01000000	/* complicated, see spec. */
#define	CACHERR_SIDX_MASK	0x003ffff8	/* secondary cache index */
#define	CACHERR_PIDX_MASK	0x00000007	/* primary cache index */
#define CACHERR_PIDX_SHIFT	12		/* bits 2..0 are paddr14..12 */

/* R4000 family supports hardware watchpoints:
 *   C0_WATCHLO:
 *     bits 31..3 are bits 31..3 of physaddr to watch
 *     bit 2:  reserved; must be written as 0.
 *     bit 1:  when set causes a watchpoint trap on load accesses to paddr.
 *     bit 0:  when set traps on stores to paddr;
 *   C0_WATCHHI
 *     bits 31..4 are reserved and must be written as zeros.
 *     bits 3..0 are bits 35..32 of the physaddr to watch
 */
#define WATCHLO_WTRAP           0x00000001
#define WATCHLO_RTRAP           0x00000002
#define WATCHLO_ADDRMASK        0xfffffff8
#define WATCHLO_VALIDMASK       0xfffffffb
#define WATCHHI_VALIDMASK       0x0000000f

/*
 * Coprocessor 0 registers
 */
#ifdef _LANGUAGE_ASSEMBLY
#define	C0_INX		$0
#define	C0_RAND		$1
#define	C0_ENTRYLO0	$2
#define	C0_ENTRYLO1	$3
#define	C0_CONTEXT	$4
#define	C0_PAGEMASK	$5		/* page mask */
#define	C0_WIRED	$6		/* # wired entries in tlb */
#define	C0_BADVADDR	$8
#define	C0_COUNT	$9		/* free-running counter */
#define	C0_ENTRYHI	$10
#define	C0_SR		$12
#define	C0_CAUSE	$13
#define	C0_EPC		$14
#define	C0_PRID		$15		/* revision identifier */
#define	C0_COMPARE	$11		/* counter comparison reg. */
#define	C0_CONFIG	$16		/* hardware configuration */
#define	C0_LLADDR	$17		/* load linked address */
#define	C0_WATCHLO	$18		/* watchpoint */
#define	C0_WATCHHI	$19		/* watchpoint */
#define	C0_ECC		$26		/* S-cache ECC and primary parity */
#define	C0_CACHE_ERR	$27		/* cache error status */
#define	C0_TAGLO	$28		/* cache operations */
#define	C0_TAGHI	$29		/* cache operations */
#define	C0_ERROR_EPC	$30		/* ECC error prg. counter */

# else	/* ! _LANGUAGE_ASSEMBLY */

#define	C0_INX		0
#define	C0_RAND		1
#define	C0_ENTRYLO0	2
#define	C0_ENTRYLO1	3
#define	C0_CONTEXT	4
#define	C0_PAGEMASK	5		/* page mask */
#define	C0_WIRED	6		/* # wired entries in tlb */
#define	C0_BADVADDR	8
#define	C0_COUNT	9		/* free-running counter */
#define	C0_ENTRYHI	10
#define	C0_SR		12
#define	C0_CAUSE	13
#define	C0_EPC		14
#define	C0_PRID		15		/* revision identifier */
#define	C0_COMPARE	11		/* counter comparison reg. */
#define	C0_CONFIG	16		/* hardware configuration */
#define	C0_LLADDR	17		/* load linked address */
#define	C0_WATCHLO	18		/* watchpoint */
#define	C0_WATCHHI	19		/* watchpoint */
#define	C0_ECC		26		/* S-cache ECC and primary parity */
#define	C0_CACHE_ERR	27		/* cache error status */
#define	C0_TAGLO	28		/* cache operations */
#define	C0_TAGHI	29		/* cache operations */
#define	C0_ERROR_EPC	30		/* ECC error prg. counter */

#endif	/* _LANGUAGE_ASSEMBLY */

/*
 * floating-point status register 
 */
#define FPCSR_FS	0x01000000	/* flush denorm to zero */
#define	FPCSR_C		0x00800000	/* condition bit */	
#define	FPCSR_CE	0x00020000	/* cause: unimplemented operation */
#define	FPCSR_CV	0x00010000	/* cause: invalid operation */
#define	FPCSR_CZ	0x00008000	/* cause: division by zero */
#define	FPCSR_CO	0x00004000	/* cause: overflow */
#define	FPCSR_CU	0x00002000	/* cause: underflow */
#define	FPCSR_CI	0x00001000	/* cause: inexact operation */
#define	FPCSR_EV	0x00000800	/* enable: invalid operation */
#define	FPCSR_EZ	0x00000400	/* enable: division by zero */
#define	FPCSR_EO	0x00000200	/* enable: overflow */
#define	FPCSR_EU	0x00000100	/* enable: underflow */
#define	FPCSR_EI	0x00000080	/* enable: inexact operation */
#define	FPCSR_FV	0x00000040	/* flag: invalid operation */
#define	FPCSR_FZ	0x00000020	/* flag: division by zero */
#define	FPCSR_FO	0x00000010	/* flag: overflow */
#define	FPCSR_FU	0x00000008	/* flag: underflow */
#define	FPCSR_FI	0x00000004	/* flag: inexact operation */
#define	FPCSR_RM_MASK	0x00000003	/* rounding mode mask */
#define	FPCSR_RM_RN	0x00000000	/* round to nearest */
#define	FPCSR_RM_RZ	0x00000001	/* round to zero */
#define	FPCSR_RM_RP	0x00000002	/* round to positive infinity */
#define	FPCSR_RM_RM	0x00000003	/* round to negative infinity */

#endif /* __R4300_H */