📄 excep_s.s
字号:
/************************************************************************
*
* excep_s.S
*
* First level exception handling functions.
*
*
* ######################################################################
*
* Copyright (c) 1999-2000 MIPS Technologies, Inc. All rights reserved.
*
* Unpublished rights reserved under the Copyright Laws of the United States of
* America.
*
* This document contains information that is proprietary to MIPS Technologies,
* Inc. ("MIPS Technologies"). Any copying, modifying or use of this information
* (in whole or in part) which is not expressly permitted in writing by MIPS
* Technologies or a contractually-authorized third party is strictly
* prohibited. At a minimum, this information is protected under unfair
* competition laws and the expression of the information contained herein is
* protected under federal copyright laws. Violations thereof may result in
* criminal penalties and fines.
* MIPS Technologies or any contractually-authorized third party reserves the
* right to change the information contained in this document to improve
* function, design or otherwise. MIPS Technologies does not assume any
* liability arising out of the application or use of this information. Any
* license under patent rights or any other intellectual property rights owned
* by MIPS Technologies or third parties shall be conveyed by MIPS Technologies
* or any contractually-authorized third party in a separate license agreement
* between the parties.
* The information contained in this document constitutes one or more of the
* following: commercial computer software, commercial computer software
* documentation or other commercial items. If the user of this information, or
* any related documentation of any kind, including related technical data or
* manuals, is an agency, department, or other entity of the United States
* government ("Government"), the use, duplication, reproduction, release,
* modification, disclosure, or transfer of this information, or any related
* documentation of any kind, is restricted in accordance with Federal
* Acquisition Regulation 12.212 for civilian agencies and Defense Federal
* Acquisition Regulation Supplement 227.7202 for military agencies. The use of
* this information by the Government is further restricted in accordance with
* the terms of the license agreement(s) and/or applicable contract terms and
* conditions covering this information from MIPS Technologies or any
* contractually-authorized third party.
*
************************************************************************/
/************************************************************************
* Include files
************************************************************************/
#include <sysdefs.h>
#include <mips.h>
#include <gdb_stub.h>
#include <sys_api.h>
/************************************************************************
* Definitions
************************************************************************/
#define CAUSE_EXC 0
#define CAUSE_EJTAG 1
/* Offset to 32 bit word in 64 bit storage area */
#ifdef EB
#define OFS_END 4
#else
#define OFS_END 0
#endif
/************************************************************************
* Public variables
************************************************************************/
BSS
.globl EXCEP_gdb_regs
/* 64 bit align */
.align 3
EXCEP_gdb_regs:
.space EXCEP_SIZE_CONTEXT
/************************************************************************
* Static variables
************************************************************************/
temp_stack:
.space SYS_STACK_SIZE
temp_stack_end :
old_data:
.space 7*4*4 /* 7 exc vector of each 4 words */
scratchpad: /* Storage for s0..s8 */
.space 9*4
registered_exc_handler:
.space 4
cause:
.space 4
/************************************************************************
* Implementation : Public functions
************************************************************************/
.globl EXCEP_return
/************************************************************************
*
* EXCEP_install_exc_in_ram
* Description :
* -------------
*
* Install jump instructions to exc handler at exception vector locations
* Stores/restores old data at exception vector locations depending
* on a0 register (see description of parameters)
*
* Parameters :
* ------------
*
* a0 = 0 -> Install ram handler, store old data
* a0 = 1 -> Restore old data
*
* a1 = exc handler to be called after storing context
* (NULL -> ignore this)
* Return values :
* ---------------
*
* None
*
************************************************************************/
LEAF( EXCEP_install_exc_in_ram )
.set noreorder
/* Install RAM exception vectors */
/* First store s0..s8 since we plan to use them here and
* in setup_vector()
*/
la t0, scratchpad
sw s0, 0(t0)
sw s1, 4(t0)
sw s2, 8(t0)
sw s3, 12(t0)
sw s4, 16(t0)
sw s5, 20(t0)
sw s6, 24(t0)
sw s7, 28(t0)
sw s8, 32(t0)
#define RA s0
#define NEW_HANDLER s1
#define OLD_HANDLER s2
#define STATUS_INT s3
#define ADDR s4
move RA, ra
/* Disable interrupts */
MFC0( STATUS_INT, C0_STATUS )
li t1, ~C0_STATUS_IE_MSK
and t1, STATUS_INT
MTC0( t1, C0_STATUS )
li t1, C0_STATUS_IE_MSK
and STATUS_INT, t1
/* If available, store exception handler to be called after context store */
beq a1, zero, 1f
nop
/* Store default handler */
la t1, registered_exc_handler
sw a1, 0(t1)
1:
/* Determine data to store */
bne a0, zero, restore_old
nop
/**** Install ram handler ****/
la NEW_HANDLER, ram_handler_normal
la OLD_HANDLER, old_data
/* Install the vectors */
jal setup_vector
li ADDR, 0x0 /* TLB refill */
addu OLD_HANDLER, 4*4
jal setup_vector
li ADDR, 0x80 /* XTLB refill */
addu OLD_HANDLER, 4*4
jal setup_vector
li ADDR, 0x100 /* Cache error */
addu OLD_HANDLER, 4*4
jal setup_vector
li ADDR, 0x180 /* General */
/* NMI exception.
* Always uses address 0xbfc00000 (reset vector), but YAMON
* will jump to 0x800000000 + SYS_NMI_RAM_VECTOR_OFS
* if it detects an NMI.
*/
addu OLD_HANDLER, 4*4
jal setup_vector
li ADDR, SYS_NMI_RAM_VECTOR_OFS
la NEW_HANDLER, ram_handler_interrupt
addu OLD_HANDLER, 4*4
jal setup_vector
li ADDR, 0x200 /* Int, CauseIV=1 */
/* EJTAG Debug exception.
* Always uses address 0xbfc00480, but YAMON has installed
* a jump to KSEG0(SYS_EJTAG_RAM_VECTOR) at that vector location.
*/
la NEW_HANDLER, ram_handler_ejtag
addu OLD_HANDLER, 4*4
jal setup_vector
li ADDR, SYS_EJTAG_RAM_VECTOR_OFS
j install_done
nop
restore_old:
/**** Restore old data ****/
la NEW_HANDLER, old_data
move OLD_HANDLER, zero
/* Install the vectors */
jal setup_vector
li ADDR, 0x0 /* TLB refill */
addu NEW_HANDLER, 4*4
jal setup_vector
li ADDR, 0x80 /* XTLB refill */
addu NEW_HANDLER, 4*4
jal setup_vector
li ADDR, 0x100 /* Cache error */
addu NEW_HANDLER, 4*4
jal setup_vector
li ADDR, 0x180 /* General */
/* NMI exception.
* Always uses address 0xbfc00000 (reset vector), but YAMON
* will jump to 0x800000000 + SYS_NMI_RAM_VECTOR_OFS
* if it detects an NMI.
*/
addu NEW_HANDLER, 4*4
jal setup_vector
li ADDR, SYS_NMI_RAM_VECTOR_OFS
addu NEW_HANDLER, 4*4
jal setup_vector
li ADDR, 0x200 /* Int, CauseIV=1 */
/* EJTAG Debug exception.
* Always uses address 0xbf000480, but YAMON has installed
* a jump to KSEG0(SYS_EJTAG_RAM_VECTOR) at that vector location.
*/
addu NEW_HANDLER, 4*4
jal setup_vector
li ADDR, SYS_EJTAG_RAM_VECTOR_OFS
install_done:
/* Clear BEV so that ram handlers are used */
MFC0( a0, C0_STATUS)
li a1, ~C0_STATUS_BEV_BIT
and a0, a1
MTC0( a0, C0_STATUS)
/* Restore interrupt enable state */
MFC0( t1, C0_STATUS )
or t1, STATUS_INT
MTC0( t1, C0_STATUS )
move ra, RA
/* Restore s0..s8 */
la t0, scratchpad
lw s0, 0(t0)
lw s1, 4(t0)
lw s2, 8(t0)
lw s3, 12(t0)
lw s4, 16(t0)
lw s5, 20(t0)
lw s6, 24(t0)
lw s7, 28(t0)
lw s8, 32(t0)
/* Done */
jr ra
move v0, zero
setup_vector:
/* Copy ram handler_start code to exception vector location */
move s5, ra
#define SRC s6
#define OLD s7
#define END_ADDR s8
/* Calc addresses */
KSEG0A( ADDR ) /* Destination */
move SRC, NEW_HANDLER /* Source */
move OLD, OLD_HANDLER /* Old data */
addu END_ADDR, SRC, 4*4 /* copy 4 words */
1:
/* Possibly fetch and Store old data */
beq OLD, zero, 2f
nop
lw a3, 0(ADDR)
sw a3, 0(OLD)
addiu OLD, 4
2:
/* Install new instruction */
lw a3, 0(SRC)
sw a3, 0(ADDR)
/* Whenever an instruction has been stored to KSEG0, we must
* make sure the instruction has been flushed to physical memory
* and invalidate the corresponding I-Cache line.
*/
move a0, ADDR
jal sys_dcache_flush_addr
nop
move a0, ADDR
jal sys_icache_invalidate_addr
nop
/* Loop */
add SRC, 4
bne SRC, END_ADDR, 1b
add ADDR, 4
jr s5
nop
ram_handler_normal:
/* This code is copied to the various ram exception vector
* locations (4 words are copied).
*/
la k0, exc_handler
jr k0
li k0, CAUSE_EXC
nop /* Depending on above la, this may skipped */
ram_handler_ejtag:
/* This code is copied to the exception vector
* location reserved (by YAMON) for EJTAG (i.e. 0x80000300)
* (4 words are copied).
*/
la k0, exc_handler
jr k0
li k0, CAUSE_EJTAG
nop /* Depending on above la, this may skipped */
ram_handler_interrupt:
/* This code is copied to the various ram exception vector
* locations (4 words are copied).
*/
la k0, exc_handler
jr k0
li k0, CAUSE_EXC
nop /* Depending on above la, this may skipped */
exc_handler:
/**** Store context ****/
la k1, sys_64bit
lb k1, 0(k1)
bne k1, zero, store_64bit
nop
/* Store 32 bit CPU Registers */
la k1, EXCEP_gdb_regs
sw $0, (GDB_FR_REG0 + OFS_END)(k1)
.set noat
sw $1, (GDB_FR_REG1 + OFS_END)(k1)
.set at
sw $2, (GDB_FR_REG2 + OFS_END)(k1)
sw $3, (GDB_FR_REG3 + OFS_END)(k1)
sw $4, (GDB_FR_REG4 + OFS_END)(k1)
sw $5, (GDB_FR_REG5 + OFS_END)(k1)
sw $6, (GDB_FR_REG6 + OFS_END)(k1)
sw $7, (GDB_FR_REG7 + OFS_END)(k1)
sw $8, (GDB_FR_REG8 + OFS_END)(k1)
sw $9, (GDB_FR_REG9 + OFS_END)(k1)
sw $10, (GDB_FR_REG10 + OFS_END)(k1)
sw $11, (GDB_FR_REG11 + OFS_END)(k1)
sw $12, (GDB_FR_REG12 + OFS_END)(k1)
sw $13, (GDB_FR_REG13 + OFS_END)(k1)
sw $14, (GDB_FR_REG14 + OFS_END)(k1)
sw $15, (GDB_FR_REG15 + OFS_END)(k1)
sw $16, (GDB_FR_REG16 + OFS_END)(k1)
sw $17, (GDB_FR_REG17 + OFS_END)(k1)
sw $18, (GDB_FR_REG18 + OFS_END)(k1)
sw $19, (GDB_FR_REG19 + OFS_END)(k1)
sw $20, (GDB_FR_REG20 + OFS_END)(k1)
sw $21, (GDB_FR_REG21 + OFS_END)(k1)
sw $22, (GDB_FR_REG22 + OFS_END)(k1)
sw $23, (GDB_FR_REG23 + OFS_END)(k1)
sw $24, (GDB_FR_REG24 + OFS_END)(k1)
sw $25, (GDB_FR_REG25 + OFS_END)(k1)
/* Not k0, k1 = $26, $27 */
sw $28, (GDB_FR_REG28 + OFS_END)(k1)
sw $29, (GDB_FR_REG29 + OFS_END)(k1)
sw $30, (GDB_FR_REG30 + OFS_END)(k1)
sw $31, (GDB_FR_REG31 + OFS_END)(k1)
b store_cp0
nop
store_64bit :
/* Store 64 bit CPU Registers */
la k1, EXCEP_gdb_regs
OPCODE_SD (0, GDB_FR_REG0, SYS_CPUREG_K1 )
OPCODE_SD (1, GDB_FR_REG1, SYS_CPUREG_K1 )
OPCODE_SD (2, GDB_FR_REG2, SYS_CPUREG_K1 )
OPCODE_SD (3, GDB_FR_REG3, SYS_CPUREG_K1 )
OPCODE_SD (4, GDB_FR_REG4, SYS_CPUREG_K1 )
OPCODE_SD (5, GDB_FR_REG5, SYS_CPUREG_K1 )
OPCODE_SD (6, GDB_FR_REG6, SYS_CPUREG_K1 )
OPCODE_SD (7, GDB_FR_REG7, SYS_CPUREG_K1 )
OPCODE_SD (8, GDB_FR_REG8, SYS_CPUREG_K1 )
OPCODE_SD (9, GDB_FR_REG9, SYS_CPUREG_K1 )
OPCODE_SD (10, GDB_FR_REG10, SYS_CPUREG_K1 )
OPCODE_SD (11, GDB_FR_REG11, SYS_CPUREG_K1 )
OPCODE_SD (12, GDB_FR_REG12, SYS_CPUREG_K1 )
OPCODE_SD (13, GDB_FR_REG13, SYS_CPUREG_K1 )
OPCODE_SD (14, GDB_FR_REG14, SYS_CPUREG_K1 )
OPCODE_SD (15, GDB_FR_REG15, SYS_CPUREG_K1 )
OPCODE_SD (16, GDB_FR_REG16, SYS_CPUREG_K1 )
OPCODE_SD (17, GDB_FR_REG17, SYS_CPUREG_K1 )
OPCODE_SD (18, GDB_FR_REG18, SYS_CPUREG_K1 )
OPCODE_SD (19, GDB_FR_REG19, SYS_CPUREG_K1 )
OPCODE_SD (20, GDB_FR_REG20, SYS_CPUREG_K1 )
OPCODE_SD (21, GDB_FR_REG21, SYS_CPUREG_K1 )
OPCODE_SD (22, GDB_FR_REG22, SYS_CPUREG_K1 )
OPCODE_SD (23, GDB_FR_REG23, SYS_CPUREG_K1 )
OPCODE_SD (24, GDB_FR_REG24, SYS_CPUREG_K1 )
OPCODE_SD (25, GDB_FR_REG25, SYS_CPUREG_K1 )
/* Not k0, k1 = $26, $27 */
OPCODE_SD (28, GDB_FR_REG28, SYS_CPUREG_K1 )
OPCODE_SD (29, GDB_FR_REG29, SYS_CPUREG_K1 )
OPCODE_SD (30, GDB_FR_REG30, SYS_CPUREG_K1 )
OPCODE_SD (31, GDB_FR_REG31, SYS_CPUREG_K1 )
store_cp0 :
/* Store CP0 registers */
move a0, k1
jal sys_store_cp0_regs
nop
/* Store cause (CAUSE_EXC/CAUSE_EJTAG) */
la t0, cause
sw k0, 0(t0)
/* A registered exception handler is allowed to call
* EXCEP_return (see below) in case it does not want to
* handle the exception.
* The address of EXCEP_return was returned when the
* exception handler was registered.
* We need to flag whether this is the initial handling
* of an exception or such a return from a registered
* exception handler. This is done using the
* EXCEP_return_flag variable.
*/
/* Clear 'EXCEP_return_flag' */
la t0, EXCEP_return_flag
sb zero, 0(t0)
b 1f
nop
EXCEP_return :
/* Set 'EXCEP_return_flag' */
la t0, EXCEP_return_flag
li t1, 1
sb t1, 0(t0)
nop
1:
/* Get cause (CAUSE_EXC/CAUSE_EJTAG) */
la t0, cause
lw k0, 0(t0)
/* Restore gp and set sp to the exception stack space */
la gp, _gp
la sp, temp_stack_end
addiu sp, -4*4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -