📄 hw_exception_handler.s
字号:
/*/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2004 Xilinx, Inc. All rights reserved.//// Xilinx, Inc.// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A// COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS// ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY// AND FITNESS FOR A PARTICULAR PURPOSE.//// $Id: hw_exception_handler.S,v 1.6.6.7 2006/04/21 00:45:02 vasanth Exp $////////////////////////////////////////////////////////////////////////////////*//* * Microblaze HW Exception Handler * - Non self-modifying exception handler for the following exception conditions * - Unalignment * - Instruction bus error * - Data bus error * - Illegal instruction opcode * - Divide-by-zero */#include "microblaze_exceptions_g.h" /* Helpful Macros */#define EX_HANDLER_STACK_SIZ (4*19)#define RMSR_OFFSET 0 #define REG_OFFSET(regnum) (4*regnum)#define NUM_TO_REG(num) r ## num#define R3_TO_STACK(regnum) swi r3, r1, REG_OFFSET(regnum)#define R3_FROM_STACK(regnum) lwi r3, r1, REG_OFFSET(regnum) #define PUSH_REG(regnum) swi NUM_TO_REG(regnum), r1, REG_OFFSET(regnum)#define POP_REG(regnum) lwi NUM_TO_REG(regnum), r1, REG_OFFSET(regnum) /* Uses r5 */#define PUSH_MSR \ mfs r5, rmsr; \ swi r5, r1, RMSR_OFFSET;#define PUSH_MSR_AND_ENABLE_EXC \ mfs r5, rmsr; \ swi r5, r1, RMSR_OFFSET; \ ori r5, r5, 0x100; /* Turn ON the EE bit*/ \ mts rmsr, r5; /* Uses r5 */#define POP_MSR \ lwi r5, r1, RMSR_OFFSET; \ mts rmsr, r5; #define LWREG_NOP \ bri ex_handler_unhandled; \ nop;#define SWREG_NOP \ bri ex_handler_unhandled; \ nop; /* r3 is the source */#define R3_TO_LWREG_V(regnum) \ R3_TO_STACK (regnum); \ bri ex_handler_done; /* r3 is the source */#define R3_TO_LWREG(regnum) \ or NUM_TO_REG (regnum), r0, r3; \ bri ex_handler_done; /* r3 is the target */ #define SWREG_TO_R3_V(regnum) \ R3_FROM_STACK (regnum); \ bri ex_sw_tail; /* r3 is the target */ #define SWREG_TO_R3(regnum) \ or r3, r0, NUM_TO_REG (regnum); \ bri ex_sw_tail; /* regnum is the source */ #define FP_EX_OPB_SAVE(regnum) \ swi NUM_TO_REG (regnum), r0, mb_fpex_op_b; \ nop; \ bri handle_fp_ex_opa; /* regnum is the source */ #define FP_EX_OPB_SAVE_V(regnum) \ R3_FROM_STACK (regnum); \ swi r3, r0, mb_fpex_op_b; \ bri handle_fp_ex_opa; /* regnum is the source */ #define FP_EX_OPA_SAVE(regnum) \ swi NUM_TO_REG (regnum), r0, mb_fpex_op_a; \ nop; \ bri handle_fp_ex_done; /* regnum is the source */ #define FP_EX_OPA_SAVE_V(regnum) \ R3_FROM_STACK (regnum); \ swi r3, r0, mb_fpex_op_a; \ bri handle_fp_ex_done; #define FP_EX_UNHANDLED \ bri fp_ex_unhandled; \ nop; \ nop;/* ESR masks */ #define ESR_EXC_MASK 0x0000001F#define ESR_REG_MASK 0x000003E0#define ESR_LW_SW_MASK 0x00000400#define ESR_WORD_MASK 0x00000800#define ESR_DS_MASK 0x00001000 /* Extern declarations */.extern MB_ExceptionVectorTable#ifdef MICROBLAZE_EXCEPTIONS_ENABLED /* If exceptions are enabled in the processor */ /* * hw_exception_handler - Handler for unaligned exceptions * Exception handler notes: * - Does not handle exceptions other than unaligned exceptions * - Does not handle exceptions during load into r17, r1, r0. * - Does not handle exceptions during store from r17 (cannot be done) and r1 (slows down common case) * * Relevant register structures * * EAR - |----|----|----|----|----|----|----|----| * - < ## 32 bit faulting address ## > * * ESR - |----|----|----|----|----| - | - |-----|-----| * - W S REG EXC * * * STACK FRAME STRUCTURE * --------------------- * * +-------------+ + 0 * | MSR | * +-------------+ + 4 * | r1 | * | . | * | . | * | . | * | . | * | r18 | * +-------------+ + 76 * | . | * | . | */ .global _hw_exception_handler .section .text .align 2.ent _hw_exception_handler_hw_exception_handler: addik r1, r1, -(EX_HANDLER_STACK_SIZ); /* Create stack frame */ PUSH_REG(3); PUSH_REG(4); PUSH_REG(5); PUSH_REG(6); PUSH_REG(17); PUSH_MSR_AND_ENABLE_EXC; /* Exceptions enabled here. This will allow nested exceptions */ mfs r3, resr; andi r5, r3, ESR_EXC_MASK; /* Extract ESR[EXC] */#if (! defined (NO_UNALIGNED_EXCEPTIONS) && ! defined (USER_SPEC_UNALIGNED_HANDLER)) xori r6, r5, 1; /* 00001 = Unaligned Exception */ beqi r6, handle_unaligned_ex ; /* Jump to unalignment exception handler*/#endif /* (! defined (NO_UNALIGNED_EXCEPTIONS) && ! defined (USER_SPEC_UNALIGNED_HANDLER)) */#if defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) xori r6, r5, 6; /* 00110 = FPU exception */ beqi r6, handle_fp_ex; /* Go and decode the FP exception */#endif /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */#if (! defined (NO_OTHER_EXCEPTIONS) || (defined(USER_SPEC_UNALIGNED_HANDLER)))handle_other_ex: /* Handle Other exceptions here */ ori r6, r0, 7; cmp r6, r5, r6; /* >= 7 are unknown exceptions. Do not handle these */ blei r6, ex_handler_done;handle_other_ex_tail: PUSH_REG(7); /* Save other volatiles before we make procedure calls below */ PUSH_REG(8); PUSH_REG(9); PUSH_REG(10); PUSH_REG(11); PUSH_REG(12); PUSH_REG(15); PUSH_REG(18); la r4, r0, MB_ExceptionVectorTable; /* Load the Exception vector table base address */ addik r5, r5, -1 /* Interesting exception numbers start range from 1-6. Convert to array index. */ addk r7, r5, r5; /* Calculate exception vector offset = r5 * 8 */ addk r7, r7, r7; addk r7, r7, r7; addk r7, r7, r4; /* Get pointer to exception vector */ lwi r5, r7, 4; /* Load argument to exception handler from table */ lw r7, r7, r0; /* Load vector itself here */ brald r15, r7; /* Branch to handler */ nop; POP_REG(7); /* Restore other volatiles */ POP_REG(8); POP_REG(9); POP_REG(10); POP_REG(11); POP_REG(12); POP_REG(15); POP_REG(18); #endif /* (! defined (NO_OTHER_EXCEPTIONS) || (defined(USER_SPEC_UNALIGNED_HANDLER))) */#if (! defined (NO_UNALIGNED_EXCEPTIONS) && ! defined (USER_SPEC_UNALIGNED_HANDLER)) bri ex_handler_done; /* Complete exception handling */ handle_unaligned_ex: andi r6, r3, ESR_REG_MASK; /* Mask and extract the register operand */ srl r6, r6; /* r6 >> 5 */ srl r6, r6; srl r6, r6; srl r6, r6; srl r6, r6; sbi r6, r0, ex_reg_op; /* Store the register operand in a temporary location */ mfs r4, rear; andi r6, r3, ESR_LW_SW_MASK; /* Extract ESR[S] */ bnei r6, ex_sw;ex_lw: andi r6, r3, ESR_WORD_MASK; /* Extract ESR[W] */ beqi r6, ex_lhw; lbui r5, r4, 0; /* Exception address in r4 */ sbi r5, r0, ex_tmp_data_loc_0; /* Load a word, byte-by-byte from destination address and save it in tmp space */ lbui r5, r4, 1; sbi r5, r0, ex_tmp_data_loc_1; lbui r5, r4, 2; sbi r5, r0, ex_tmp_data_loc_2; lbui r5, r4, 3; sbi r5, r0, ex_tmp_data_loc_3; lwi r3, r0, ex_tmp_data_loc_0; /* Get the destination register value into r3 */ bri ex_lw_tail; ex_lhw: lbui r5, r4, 0; /* Exception address in r4 */ sbi r5, r0, ex_tmp_data_loc_0; /* Load a half-word, byte-by-byte from destination address and save it in tmp space */ lbui r5, r4, 1; sbi r5, r0, ex_tmp_data_loc_1; lhui r3, r0, ex_tmp_data_loc_0; /* Get the destination register value into r3 */ex_lw_tail: lbui r5, r0, ex_reg_op; /* Get the destination register number into r5 */ la r6, r0, lw_table; /* Form load_word jump table offset (lw_table + (8 * regnum)) */ addk r5, r5, r5; addk r5, r5, r5; addk r5, r5, r5; addk r5, r5, r6; bra r5;ex_lw_end: /* Exception handling of load word, ends */ex_sw: lbui r5, r0, ex_reg_op; /* Get the destination register number into r5 */ la r6, r0, sw_table; /* Form store_word jump table offset (sw_table + (8 * regnum)) */ add r5, r5, r5; add r5, r5, r5; add r5, r5, r5; add r5, r5, r6; bra r5;ex_sw_tail: mfs r6, resr; andi r6, r6, ESR_WORD_MASK; /* Extract ESR[W] */ beqi r6, ex_shw; swi r3, r0, ex_tmp_data_loc_0; lbui r3, r0, ex_tmp_data_loc_0; /* Store the word, byte-by-byte into destination address */ sbi r3, r4, 0; lbui r3, r0, ex_tmp_data_loc_1; sbi r3, r4, 1; lbui r3, r0, ex_tmp_data_loc_2; sbi r3, r4, 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -