Go to the source code of this file.
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 |
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) |
#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) |
#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) |
#define | TLBWI() |
#define | TLBWR() |
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) |
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) |
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) |
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) |
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) |
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) |
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) |
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) |
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) |
#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) |
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) |
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) |
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) |
#define | cp0_lladdr_lladdr cp0_lladdr |
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 |
#define | OM_KSEG1 0xa0000000 |
#define | OM_KSSEG 0xc0000000 |
#define | OM_KSEG3 0xe0000000 |
void | switch_cpu_context (void **kst1, void *kst2) |
Switch_cpu_context. |
#define cp0_badvaaddr_badvaaddr_mask 0xffffffff |
@ Bad Virtual Address Register
Bad Virtual Address Register contains the virtual address that causes a TLB exception. BadVAddr is read-only.
#define cp0_lladdr_lladdr cp0_lladdr |
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 read_cp0_reg | ( | regno | ) |
Value:
({ int __res; \ asm volatile ( \ " .set push\n" \ " .set noreorder\n" \ " nop\n" \ " mfc0 %0, $"#regno"\n" \ " .set pop\n" \ : "=r" (__res)); \ __res; })
#define TLBWI | ( | ) |
Value:
asm volatile ( \ " tlbwi\n" \ );
#define TLBWR | ( | ) |
Value:
asm volatile ( \ " tlbwr\n" \ );
#define write_cp0_reg | ( | regno, | |||
i | ) |
Value:
asm volatile ( \ " .set push\n" \ " .set noreorder\n" \ " nop\n" \ " mtc0 %0, $"#regno"\n" \ " .set pop\n" \ :: "r" (i) );
void switch_cpu_context | ( | void ** | kst1, | |
void * | kst2 | |||
) |
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.