/**
 * @file sys.h
 * @brief This file contains system dependents definitions
 * 
 */


#ifndef _SYS_H_
#define _SYS_H_

/** 
 * @name MIPS R400 Exception indexes
 * 
 * They are stored in the exccode field of the Cause register.
 * See the exception handler in the exc.c file for more information.
 * 
 * @{
 */
#define EXC_INT		0
#define EXC_MOD		1
#define EXC_TLBL	2
#define EXC_TLBS	3
#define EXC_ADEL	4
#define EXC_ADES	5
#define EXC_IBE		6
#define EXC_DBE		7
#define EXC_SYS		8
#define EXC_BP		9
#define EXC_RI		10
#define EXC_CPU		11
#define EXC_OV		12
#define EXC_TR		13
#define EXC_WATCH	23
/** }@ */

/**
 * @name MIPS R4000 CP0 Registers
 * 
 * read_cp0_*() and write_cp0_*()
 *
 * These functions are used to manipulate the special system registers
 * of the MIPS R4000 processor. These are accessed via special instructions -
 * there is no standard way of doing that in the C language.
 *
 * Functions are implemented as in-line assembler macros.
 * 
 * @{
 */
#define read_cp0_reg(regno) 				\
	({ int __res;					\
	asm volatile (					\
		"	.set	push\n"			\
		"	.set	noreorder\n"		\
		"	nop\n"				\
		"	mfc0	%0, $"#regno"\n" 	\
		"	.set	pop\n"			\
		: "=r" (__res));			\
	__res; })

#define read_cp0_badvaddr()		read_cp0_reg(8)
#define read_cp0_count()		read_cp0_reg(9)
#define read_cp0_compare()		read_cp0_reg(11)
#define read_cp0_status()		read_cp0_reg(12)
#define read_cp0_cause()		read_cp0_reg(13)
#define read_cp0_epc()			read_cp0_reg(14)
#define read_cp0_xcontext()		read_cp0_reg(20)
#define read_cp0_eepc()			read_cp0_reg(30)


#define write_cp0_reg(regno, i)				\
	asm volatile (					\
		"	.set	push\n"			\
		"	.set	noreorder\n"		\
		"	nop\n"				\
		"	mtc0	%0, $"#regno"\n"	\
		"	.set	pop\n"			\
		:: "r" (i) );

#define write_cp0_index(val)		write_cp0_reg(0, val)
#define write_cp0_entrylo0(val)		write_cp0_reg(2, val)
#define write_cp0_entrylo1(val)		write_cp0_reg(3, val)
#define write_cp0_pagemask(val)		write_cp0_reg(5, val)
#define write_cp0_wired(val)		write_cp0_reg(6, val)
#define write_cp0_count(val)		write_cp0_reg(9, val)
#define write_cp0_entryhi(val)		write_cp0_reg(10, val)
#define write_cp0_compare(val)		write_cp0_reg(11, val)
#define write_cp0_status(val)		write_cp0_reg(12, val)
#define write_cp0_cause(val)		write_cp0_reg(13, val)
#define write_cp0_epc(val)		write_cp0_reg(14, val)
#define write_cp0_eepc(val)		write_cp0_reg(30, val)
/** }@ */

/**
 * Inline function write_tlb writes the page specified by entryhi,
 * entrylo0, entrylo1 and pagemask into the TLB. The position is
 * specified by the Index register.
 */
#define TLBWI()				\
	asm volatile (			\
		"	tlbwi\n"	\
		);

/**
 * Inline function write_tlb writes the page specified by entryhi,
 * entrylo0, entrylo1 and pagemask into the TLB. The position is
 * specified by the Random register.
 */
#define TLBWR()				\
	asm volatile (			\
		"	tlbwr\n"	\
		);


/**
 * @name Constants for MIPS R4000 Coprocessor 0 registers
 *
 * All these constants has a following name structure:
 * 	cp0_<register name>_<item name>_{mask,shift}
 * 
 * @{
 */

/**
 * @name Index register
 * 
 * Index register (read-write) is used as a pointer to the TLB for the TLBWI
 * instruction
 * 
 * @{
 */
#define cp0_index_index_mask	0x0000003f
#define cp0_index_res_mask	0x7fffffc0
#define cp0_index_p_mask	0x80000000

#define cp0_index_index_shift	0
#define cp0_index_res_shift	6
#define cp0_index_p_shift	31

#define cp0_index_index(r) \
	(((r) & cp0_index_index_mask) >> cp0_index_index_shift)
#define cp0_index_res(r) \
	(((r) & cp0_index_res_mask) >> cp0_index_res_shift)
#define cp0_index_p(r) \
	(((r) & cp0_index_p_mask) >> cp0_index_p_shift)
/** }@ */

/**
 * @name Random register
 * 
 * Random register is a read-only 6bit pseudo-random index into the TLB used
 * by the TLBWR instruction. This register decrements every cycle. The upper
 * bound is 47 which is the TLB size, the lower bound is defined by the value
 * of Wired register. The Random register is set to its upper bound whenever
 * the Wired register is changed.
 * 
 * @{
 */
#define cp0_random_random_mask	0x0000003f
#define cp0_random_res_mask	0xffffffc0

#define cp0_random_random_shift	0
#define cp0_random_res_shift	6

#define cp0_random_random(r) \
	(((r) & cp0_random_random_mask) >> cp0_random_random_shift)
#define cp0_random_res(r) \
	(((r) & cp0_random_res_mask) >> cp0_random_res_shift)
/** }@ */


/**
 * @name Status register
 * 
 * Status register (read-write) contains system-relevant configuration flags.
 * This register is one of the most important for proper functionality.
 * Relevant fields are listed below.
 *
 * Interrupt Enable (ie) masks all interrupts.
 * Interrupt Mask, im - 8 bits, 1 = interrupt enabled
 * Coprocessor Usability, cu - 4 bits, 1 = usable
 * Kernel-Supervisor-User, ksu - 2 bits
 * 	10 user, 01 supervisor, 00 kernel
 * 	This field selects the processor address mode and privileges.
 * Exception Level, exl
 * 	0 - normal, 1 - error
 * 	The processor sets this field when an exception occurs.
 * 	The exception level starts at concrete address. When this field is set,
 * 	interrupts are disabled.
 * Error Level, erl
 * 	0 - normal, 1 - error
 * 	The processor sets this field when an Reset, Soft Reset or NMI exception
 * 	occurs.
 * 
 * @{
 */
#define cp0_status_ie_mask	0x00000001
#define cp0_status_exl_mask	0x00000002
#define cp0_status_erl_mask	0x00000004
#define cp0_status_ksu_mask	0x00000018
#define cp0_status_ux_mask	0x00000020
#define cp0_status_sx_mask	0x00000040
#define cp0_status_kx_mask	0x00000080
#define cp0_status_im_mask	0x0000ff00
# define cp0_status_im0_mask	0x00000100
# define cp0_status_im1_mask	0x00000200
# define cp0_status_im2_mask	0x00000400
# define cp0_status_im3_mask	0x00000800
# define cp0_status_im4_mask	0x00001000
# define cp0_status_im5_mask	0x00002000
# define cp0_status_im6_mask	0x00004000
# define cp0_status_im7_mask	0x00008000
#define cp0_status_de_mask	0x00010000
#define cp0_status_ce_mask	0x00020000
#define cp0_status_ch_mask	0x00040000
#define cp0_status_res1_mask	0x00080000
#define cp0_status_sr_mask	0x00100000
#define cp0_status_ts_mask	0x00200000
#define cp0_status_bev_mask	0x00400000
#define cp0_status_res2_mask	0x01800000
#define cp0_status_re_mask	0x02000000
#define cp0_status_fr_mask	0x04000000
#define cp0_status_rp_mask	0x08000000
#define cp0_status_cu0_mask	0x10000000
#define cp0_status_cu1_mask	0x20000000
#define cp0_status_cu2_mask	0x40000000
#define cp0_status_cu3_mask	0x80000000
#define cp0_status_cu_mask	0xf0000000

#define cp0_status_ie_shift	0
#define cp0_status_exl_shift	1
#define cp0_status_erl_shift	2
#define cp0_status_ksu_shift	3
#define cp0_status_ux_shift	5
#define cp0_status_sx_shift	6
#define cp0_status_kx_shift	7
#define cp0_status_im_shift	8
#define cp0_status_de_shift	16
#define cp0_status_ce_shift	17
#define cp0_status_ch_shift	18
#define cp0_status_res1_shift	19
#define cp0_status_sr_shift	20
#define cp0_status_ts_shift	21
#define cp0_status_bev_shift	22
#define cp0_status_res2_shift	23
#define cp0_status_re_shift	25
#define cp0_status_fr_shift	26
#define cp0_status_rp_shift	27
#define cp0_status_cu0_shift	28
#define cp0_status_cu1_shift	29
#define cp0_status_cu2_shift	30
#define cp0_status_cu3_shift	31
#define cp0_status_cu_shift	28

#define cp0_status_ie(r) \
	(((r) & cp0_status_ie_mask) >> cp0_status_ie_shift)
#define cp0_status_exl(r) \
	(((r) & cp0_status_exl_mask) >> cp0_status_exl_shift)
#define cp0_status_erl(r) \
	(((r) & cp0_status_erl_mask) >> cp0_status_erl_shift)
#define cp0_status_ksu(r) \
	(((r) & cp0_status_ksu_mask) >> cp0_status_ksu_shift)
#define cp0_status_ux(r) \
	(((r) & cp0_status_ux_mask) >> cp0_status_ux_shift)
#define cp0_status_sx(r) \
	(((r) & cp0_status_sx_mask) >> cp0_status_sx_shift)
#define cp0_status_kx(r) \
	(((r) & cp0_status_kx_mask) >> cp0_status_kx_shift)
#define cp0_status_im(r) \
	(((r) & cp0_status_im_mask) >> cp0_status_im_shift)
#define cp0_status_de(r) \
	(((r) & cp0_status_de_mask) >> cp0_status_de_shift)
#define cp0_status_ce(r) \
	(((r) & cp0_status_ce_mask) >> cp0_status_ce_shift)
#define cp0_status_ch(r) \
	(((r) & cp0_status_ch_mask) >> cp0_status_ch_shift)
#define cp0_status_res1(r) \
	(((r) & cp0_status_res1_mask) >> cp0_status_res1_shift)
#define cp0_status_sr(r) \
	(((r) & cp0_status_sr_mask) >> cp0_status_sr_shift)
#define cp0_status_ts(r) \
	(((r) & cp0_status_ts_mask) >> cp0_status_ts_shift)
#define cp0_status_bev(r) \
	(((r) & cp0_status_bev_mask) >> cp0_status_bev_shift)
#define cp0_status_res2(r) \
	(((r) & cp0_status_res2_mask) >> cp0_status_res2_shift)
#define cp0_status_re(r) \
	(((r) & cp0_status_re_mask) >> cp0_status_re_shift)
#define cp0_status_fr(r) \
	(((r) & cp0_status_fr_mask) >> cp0_status_fr_shift)
#define cp0_status_rp(r) \
	(((r) & cp0_status_rp_mask) >> cp0_status_rp_shift)
#define cp0_status_cu0(r) \
	(((r) & cp0_status_cu0_mask) >> cp0_status_cu0_shift)
#define cp0_status_cu1(r) \
	(((r) & cp0_status_cu1_mask) >> cp0_status_cu1_shift)
#define cp0_status_cu2(r) \
	(((r) & cp0_status_cu2_mask) >> cp0_status_cu2_shift)
#define cp0_status_cu3(r) \
	(((r) & cp0_status_cu3_mask) >> cp0_status_cu3_shift)
#define cp0_status_cu(r) \
	(((r) & cp0_status_cu_mask) >> cp0_status_cu_shift)
/** }@ */

/**
 * @name EntryHi
 * 
 * EntryHi register (read-write) is a part of the TLB entry description.
 * It consists of the vitrual page number (high bits) field and the 8-bit
 * address space identification.
 * 
 * @{
 */
#define cp0_entryhi_asid_mask	0x000000ff
#define cp0_entryhi_res1_mask	0x00001f00
#define cp0_entryhi_vpn2_mask	0xffffe000

#define cp0_entryhi_asid_shift	0
#define cp0_entryhi_res1_shift	8
#define cp0_entryhi_vpn2_shift	13

#define cp0_entryhi_asid(r) 	\
	(((r) & cp0_entryhi_asid_mask) >> cp0_entryhi_asid_shift)
#define cp0_entryhi_res1(r) 	\
	(((r) & cp0_entryhi_res1_mask) >> cp0_entryhi_res1_shift)
#define cp0_entryhi_vpn2(r) 	\
	(((r) & cp0_entryhi_vpn2_mask) >> cp0_entryhi_vpn2_shift)
/** }@ */


/**
 * @name EntryLo
 * 
 * EntryLo(0/1) registers (read/write) consists of the physical page number
 * field and dirty, valid and global bits.
 * 
 * @{
 */
#define cp0_entrylo_g_mask	0x00000001
#define cp0_entrylo_v_mask	0x00000002
#define cp0_entrylo_d_mask	0x00000004
#define cp0_entrylo_c_mask	0x00000038
#define cp0_entrylo_pfn_mask	0x3fffffc0
#define cp0_entrylo_res1_mask	0xc0000000

#define cp0_entrylo_g_shift	0
#define cp0_entrylo_v_shift	1
#define cp0_entrylo_d_shift	2
#define cp0_entrylo_c_shift	3
#define cp0_entrylo_pfn_shift	6
#define cp0_entrylo_res1_shift	30

#define cp0_entrylo0_g(r) 	\
	(((r) & cp0_entrylo_g_mask) >> cp0_entrylo_g_shift)
#define cp0_entrylo0_v(r) 	\
	(((r) & cp0_entrylo_v_mask) >> cp0_entrylo_v_shift)
#define cp0_entrylo0_d(r) 	\
	(((r) & cp0_entrylo_d_mask) >> cp0_entrylo_d_shift)
#define cp0_entrylo0_c(r) 	\
	(((r) & cp0_entrylo_c_mask) >> cp0_entrylo_c_shift)
#define cp0_entrylo0_pfn(r) 	\
	(((r) & cp0_entrylo_pfn_mask) >> cp0_entrylo_pfn_shift)
#define cp0_entrylo0_res1(r) 	\
	(((r) & cp0_entrylo_res1_mask) >> cp0_entrylo_res1_shift)

#define cp0_entrylo1_g 		\
	(((r) & cp0_entrylo_g_mask) >> cp0_entrylo_g_shift)
#define cp0_entrylo1_v 		\
	(((r) & cp0_entrylo_v_mask) >> cp0_entrylo_v_shift)
#define cp0_entrylo1_d 		\
	(((r) & cp0_entrylo_d_mask) >> cp0_entrylo_d_shift)
#define cp0_entrylo1_c 		\
	(((r) & cp0_entrylo_c_mask) >> cp0_entrylo_c_shift)
#define cp0_entrylo1_pfn 	\
	(((r) & cp0_entrylo_pfn_mask) >> cp0_entrylo_pfn_shift)
#define cp0_entrylo1_res1 	\
	(((r) & cp0_entrylo_res1_mask) >> cp0_entrylo_res1_shift)
/** }@ */

/**
 * @name Wired Register
 * 
 * Wired Register (read-write) specifies the limit of the TLBWR random pool.
 * Page entries may be loaded into random TLB slots using the TLBWR
 * instruction. A kernel designer may specify via Wired Register a set of
 * pages which could not be replaced randomly. This is typically useful for
 * heavily used or system pages.
 * 
 * @{
 */
#define cp0_wired_w_mask	0x0000001f
#define cp0_wired_res1_mask	0xffffffe0

#define cp0_wired_w_shift	0
#define cp0_wired_res1_shift	6

#define cp0_wired_w(r) 		\
	(((r) & cp0_wired_w_mask) >> cp0_wired_w_shift)
#define cp0_wired_res1(r) 	\
	(((r) & cp0_wired_res1_mask) >> cp0_wired_res1_shift)
/** }@ */


/**
 * @name Context register
 * 
 * Context is a read-write register which is filled after the TLB exception
 * with a pointer into the page table entry array - this is a operating
 * system structure. This register is similar to BadVAddr except that it is
 * more useful for a software exception handler.
 *
 * BadVPN2 is filled by the hardware when a TBL miss occurs.
 * PTEBase is filled by the operating system.
 * 
 * @{
 */
#define cp0_context_res1_mask		0x0000000f
#define cp0_context_badvpn2_mask	0x007ffff0
#define cp0_context_ptebase_mask	0xff800000

#define cp0_context_res1_shift		0
#define cp0_context_badvpn2_shift	4
#define cp0_context_ptebase_shift	23

#define cp0_context_res1(r) 	\
	(((r) & cp0_context_res1_mask) >> cp0_context_res1_shift)
#define cp0_context_badvpn2(r) 	\
	(((r) & cp0_context_badvpn2_mask) >> cp0_context_badvpn2_shift)
#define cp0_context_ptebase(r) 	\
	(((r) & cp0_context_ptebase_mask) >> cp0_context_ptebase_shift)
/** }@ */

/**
 * @name Pagemask register
 * 
 * Pagemask register is a read-write register used for work with TLB.
 * Typically, the Pagemask register is loaded with appropriate value as a page
 * size of a new TLB item.
 * 
 * @{
 */

#define cp0_pagemask_res1_mask	0x00001fff
#define cp0_pagemask_mask_mask	0x01ffe000
#define cp0_pagemask_res2_mask	0xfe000000

#define cp0_pagemask_res1_shift	0
#define cp0_pagemask_mask_shift	13
#define cp0_pagemask_res2_shift	25

#define cp0_pagemask_res1(r) 	\
	(((r) & cp0_pagemask_res1_mask) >> cp0_pagemask_res1_shift)
#define cp0_pagemask_mask(r) 	\
	(((r) & cp0_pagemask_mask_mask) >> cp0_pagemask_mask_shift)
#define cp0_pagemask_res2(r) 	\
	(((r) & cp0_pagemask_res2_mask) >> cp0_pagemask_res2_shift)

#define	PAGEMASK_4K	(0x000 << cp0_pagemask_mask_shift)
#define	PAGEMASK_16K	(0x003 << cp0_pagemask_mask_shift)
#define	PAGEMASK_64K	(0x00f << cp0_pagemask_mask_shift)
#define	PAGEMASK_256K	(0x03f << cp0_pagemask_mask_shift)
#define	PAGEMASK_1M	(0x0ff << cp0_pagemask_mask_shift)
#define	PAGEMASK_4M	(0x3ff << cp0_pagemask_mask_shift)
#define	PAGEMASK_16M	(0xfff << cp0_pagemask_mask_shift)
/** }@ */


/**
 * @name Count register
 * 
 * Count Register (read-write) is a counter of system ticks. It is also used
 * for timing purposes.
 * 
 * @{
 */
#define cp0_count_count_mask	0xffffffff
#define cp0_count_count_shift	0
#define cp0_count_count(r) 	\
	(((r) & cp0_count_count_mask) >> cp0_count_count_shift)
/** }@ */

/**
 * @ Bad Virtual Address Register
 * 
 * Bad Virtual Address Register contains the virtual address that causes
 * a TLB exception. BadVAddr is read-only.
 * 
 * @{
 */
#define cp0_badvaaddr_badvaaddr_mask	0xffffffff
#define cp0_badvaaddr_badvaaddr_shift	0
#define cp0_badvaaddr_badvaaddr(r) 	\
	(((r) & cp0_badvaaddr_badvaaddr_mask) >> cp0_badvaaddr_badvaaddr_shift)
/** }@ */

/**
 * @name Compare register
 * 
 * Compare is a read-write register which stores the value of ticks.
 *
 * When the values of Compare and Count registers are equal,
 * an interrupt pending no. 7 is assured. These two registers are
 * used as an internal timer.
 *
 * The timer interrupt is deasserted when a new value is written.
 * 
 * @{
 */
#define cp0_compare_compare_mask	0xffffffff
#define cp0_compare_compare_shift	0
#define cp0_compare_compare(r) 		\
	(((r) & cp0_compare_compare_mask) >> cp0_compare_compare_shift)
/** }@ */

/**
 * @name Exception Program Counter
 * 
 * read-write
 *
 * Displays the address at which the exception occurs. If the instruction was
 * in the branch delay, epc points to the jump/branch instruction and the bd
 * field in the Cause register is set to 1.
 *
 * This register is used by the RET instruction.
 * 
 * @{
 */
#define cp0_epc_epc_mask	0xffffffff
#define cp0_epc_epc_shift	0
#define cp0_epc_epc(r) 		\
	(((r) & cp0_epc_epc_mask) >> cp0_epc_epc_shift)
/** }@ */


/**
 * @name Cause Register
 * 
 * read-write
 *
 * The Cause Register contains general information about the last exception.
 * It consists of four fields - exccode, ip, ce and bd.
 *
 * exccode stores the exception type - see exception() in exc.c for more
 * information. The ip field is a bit mask, each bit corresponds to
 * an interrupt specified. It is valid only when the interrupt exception
 * occurs. The ce field stores the coprocessor index which was addressed when
 * the Coprocessor unusable exception occurs. At last, the bd field indicates
 * that the exception occurs at the branch delay. In such a case, the Error
 * Program Counter stores the address of the jump/branch instruction.
 * 
 * @{
 */
#define cp0_cause_res1_mask	0x00000003
#define cp0_cause_exccode_mask	0x0000007c
#define cp0_cause_res2_mask	0x00000080
#define cp0_cause_ip_mask	0x0000ff00
# define cp0_cause_ip0_mask	0x00000100
# define cp0_cause_ip1_mask	0x00000200
# define cp0_cause_ip2_mask	0x00000400
# define cp0_cause_ip3_mask	0x00000800
# define cp0_cause_ip4_mask	0x00001000
# define cp0_cause_ip5_mask	0x00002000
# define cp0_cause_ip6_mask	0x00004000
# define cp0_cause_ip7_mask	0x00008000
#define cp0_cause_res3_mask	0x0fff0000
#define cp0_cause_ce_mask	0x30000000
#define cp0_cause_bd_mask	0x80000000
#define cp0_cause_res4_mask	0x40000000

#define cp0_cause_ce_cu1	0x10000000
#define cp0_cause_ce_cu2	0x20000000
#define cp0_cause_ce_cu3	0x30000000

#define cp0_cause_res1_shift	0
#define cp0_cause_exccode_shift 2
#define cp0_cause_res2_shift	7
#define cp0_cause_ip_shift	8
# define cp0_cause_ip0_shift	8
# define cp0_cause_ip1_shift	9
# define cp0_cause_ip2_shift	10
# define cp0_cause_ip3_shift	11
# define cp0_cause_ip4_shift	12
# define cp0_cause_ip5_shift	13
# define cp0_cause_ip6_shift	14
# define cp0_cause_ip7_shift	15
#define cp0_cause_res3_shift	16
#define cp0_cause_ce_shift	28
#define cp0_cause_res4_shift	30
#define cp0_cause_bd_shift	31

#define cp0_cause_res1(r) 	\
	(((r) & cp0_cause_res1_mask) >> cp0_cause_res1_shift)
#define cp0_cause_exccode(r) 	\
	(((r) & cp0_cause_exccode_mask) >> cp0_cause_exccode_shift)
#define cp0_cause_res2(r) 	\
	(((r) & cp0_cause_res2_mask) >> cp0_cause_res2_shift)
#define cp0_cause_ip(r) 	\
	(((r) & cp0_cause_ip_mask) >> cp0_cause_ip_shift)
#define cp0_cause_res3(r) 	\
	(((r) & cp0_cause_res3_mask) >> cp0_cause_res3_shift)
#define cp0_cause_ce(r) 	\
	(((r) & cp0_cause_ce_mask) >> cp0_cause_ce_shift)
#define cp0_cause_res4(r) 	\
	(((r) & cp0_cause_res4_mask) >> cp0_cause_res4_shift)
#define cp0_cause_bd(r) 	\
	(((r) & cp0_cause_bd_mask) >> cp0_cause_bd_shift)
/** }@ */


/*
 * Config register describes various system configuration options. Some of
 * these options are read-only, other are read-write. The simulator
 * does not reflect these variables so we don't have any definitions.
 */


/**
 * LLAddr register stores an address that was passed by the LL instruction.
 * This address is controlled by the hardware. When the context of the address
 * has been changed, the SC instruction will fail.
 */

#define cp0_lladdr_lladdr	cp0_lladdr
/** }@ */


/**
 * @name MIPS R4000 Memory Operating Modes
 *
 * The CPU uses the three highest bits of a virtual address to choose
 * the type of the address.
 * 
 * @{
 */
#define	OM_USER		0x00000000
#define OM_KSEG0	0x80000000	/* unmapped, cached */
#define OM_KSEG1	0xa0000000	/* unmapped, uncached */
#define OM_KSSEG	0xc0000000	/* mapped */
#define OM_KSEG3	0xe0000000	/* mapped */
/** }@ */


/**
 * @brief Switch_cpu_context
 *
 * Switches processor context from one thread to another. The first argument
 * points to a pointer to the top of the stack of the current thread, the
 * second argument points to a kernel stack of the target thread.
 */
void switch_cpu_context (void **kst1, void *kst2);


/*
 * Interrupt control
 */

/*
 * disable_interrupts
 *
 * Globally disables interrupts on the processor by setting the
 * Interrupt Enable field of the CP0 Status Register to 0.
 */

/*
static inline void disable_interrupts (void) {
		write_cp0_status (read_cp0_status () & ~cp0_status_ie_mask);
}
*/

/*
 * enable_interrupts
 *
 * Globally enables interrupts on the processor by setting the
 * Interrupt Enable field of the CP0 Status Register to 1.
 */

/*
static inline void enable_interrupts (void)
{
	write_cp0_status (read_cp0_status () | cp0_status_ie_mask);
}
*/

#endif /* _SYS_H_ */
