📄 xvectors.s
字号:
#ifdef __GNUC__
/* $Id: xvectors.S,v 1.1 2002/09/16 21:19:30 prabhu Exp $ */
/*****************************************************************************
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
* SOLUTIONS FOR XILINX DEVICES. 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.
*
* (c) Copyright 2002 Xilinx Inc.
* All rights reserved.
*
*****************************************************************************/
/****************************************************************************/
/**
*
* @file xvectors.S
*
* This file contains low-level functions for the PowerPC exception handler.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a ch 06/18/02 First release
* </pre>
*
*****************************************************************************/
/*-----------------------------------------------------------------------------
//
// Documentation:
//
// This is the structure of the PPC 405 interrupt stack frame that is
// pushed onto the stack during an exception.
//
// This interrupt frame only saves the User Model register sets that
// could be used/genterated by compiler generated code. Any usage of
// registers in an ISR beyond this set must be save/restored by the
// ISR routine.
//
// In general, this interrupt frame conforms to a standard PPC EABI
// Stack Call Frame. The entire frame is 160 bytes (40 words) in size,
// which is an exact multible of 8 bytes as required the PPC EABI.
// And by using the standard EABI frame header, debuggers should still
// be able to display the Stack Call Chain even for break points in an
// exception handler function.
//
// However, there are a few exceptions to EABI conventions :
//
// 1. The frame saves ALL registers instead of just registers that
// will be modified. Exceptions can occur at any point instead
// of just at function call branch points. Hence, saving the entire
// context means an exception will never disturb the interrupted
// code's register usage.
//
// 2. The current LR register contents is NOT save in the previous
// Stack Frame as in standard EABI conventions. Rather, it is
// saved in the local frame. This done to avoid corrupting the
// previous Stack Frame's LR field, when the exception occurs
// during an interrupted function's entry prologue process.
//
// 3. Unlike standard EABI frames, the interrupted PC location, and
// MSR state is also saved to the frame. This may seem unnecessary
// since registers SRR0 - SRR3 in the 405 are used exclusively to
// save the PC and MSR during exceptions. However, always saving
// the PC and MSR prepares this code for use in a multi-threaded
// environment.
//
// 4. The USPRG0 register is also saved even though compilers will
// never generate code to use it. Once again, this prepares the
// way for use in a multi-threaded environment. This register
// would be used to contain a pointer to the TCB (Task Control
// Block) for the current task that is being interrupted.
// Subsequent system code could then switch the memory map/context
// from the TCB; such as the PID register.
//
// +------------+
// | r31 | +156
// | . |
// | . |
// | . |
// | r3 | +44
// +------------+
// | r2 | +40
// +------------+
// | r0 | +36
// +------------+
// | USPRG0 | +32
// +------------+
// | CR | +28
// +------------+
// | XER | +24
// +------------+
// | CTR | +20
// +------------+
// | LR | +16
// +------------+
// | PC | +12
// +------------+
// | MSR | +8
// +------------+
// | Next LR | +4
// +------------+
// | Back Chain | +0
// +------------+
//
//---------------------------------------------------------------------------*/
#endif
#include "xreg405.h"
.file "xvectors.S"
.section ".vectors","ax"
#ifdef __DCC__
#define // ;
#define MACRO0(name)name: .macro
#define MACRO1(name, param1)name: .macro param1
#define MACRO2(name, param1, param2)name: .macro param1, param2
#define CONCAT(left, right) left##&&##right
#define CONCAT3(left, parammiddle, right) left##&&##parammiddle##right
#define PARAM(param) param
#else
#include <ppc-asm.h>
#define r1 1
#define r2 2
#define MACRO0(name) .macro name
#define MACRO1(name, param1) .macro name param1
#define MACRO2(name, param1, param2) .macro name param1 param2
#define CONCAT(left, right) left##\##right
#define CONCAT3(left, parammiddle, right) left##\##parammiddle##right
#define PARAM(param) \##param
#endif
//---------------------------------------------------------------------
//
// Define interrupt frame structure offsets.
//
//---------------------------------------------------------------------
.set BChainField, 0
.set NextLRField, BChainField + 4
.set MSRField, NextLRField + 4
.set PCField, MSRField + 4
.set LRField, PCField + 4
.set CTRField, LRField + 4
.set XERField, CTRField + 4
.set CRField, XERField + 4
.set USPRG0Field, CRField + 4
.set r0Field, USPRG0Field + 4
.set r2Field, r0Field + 4
.set r3r31Field, r2Field + 4
.set IFrameSize, r3r31Field + ( ( 31 - 3 ) + 1 ) * 4
//---------------------------------------------------------------------
//
// Macro for the interrupt frame prologue.
//
//---------------------------------------------------------------------
MACRO1(int_prologue, base)
.org _vectorbase + CONCAT(0x, base)
.globl CONCAT(_vector, base)
CONCAT3(_vector, base, :)
stwu XREG_GPR1,-IFrameSize(XREG_GPR1) // Save Back chain and move SP
// Save r0 and r2.
stw XREG_GPR0, r0Field(XREG_GPR1)
stw XREG_GPR2, r2Field(XREG_GPR1)
stmw XREG_GPR3, r3r31Field(XREG_GPR1) // Save the remaining GPR registers r3-r31
// Save current Link register
mflr XREG_GPR0
stw XREG_GPR0, LRField(XREG_GPR1)
// Save Counter register
mfctr XREG_GPR0
stw XREG_GPR0,CTRField(XREG_GPR1)
// Save Fixed Point Exception register
mfxer XREG_GPR0
stw XREG_GPR0,XERField(XREG_GPR1)
// Save Condition register
mfcr XREG_GPR0
stw XREG_GPR0,CRField(XREG_GPR1)
// Save USPRG0 register
mfspr XREG_GPR0,0x100
stw XREG_GPR0,USPRG0Field(XREG_GPR1)
.endm
//---------------------------------------------------------------------
//
// Macro for the interrupt frame epilogue.
//
//---------------------------------------------------------------------
MACRO0(int_epilogue)
// Save USPRG0 register
lwz XREG_GPR0,USPRG0Field(XREG_GPR1)
mtspr 0x100,XREG_GPR0
// Restore Condition register
lwz XREG_GPR0,CRField(XREG_GPR1)
mtcr XREG_GPR0
// Restore Fixed Point Exception register
lwz XREG_GPR0,XERField(XREG_GPR1)
mtxer XREG_GPR0
// Restore Counter register
lwz XREG_GPR0,CTRField(XREG_GPR1)
mtctr XREG_GPR0
// Restore Link register
lwz XREG_GPR0,LRField(XREG_GPR1)
mtlr XREG_GPR0
// Restore remaining GPR registers.
lmw XREG_GPR3,r3r31Field(XREG_GPR1)
// Restore r0 and r2.
lwz XREG_GPR0,r0Field(XREG_GPR1)
lwz XREG_GPR2,r2Field(XREG_GPR1)
// Remove frame from stack
addi XREG_GPR1,XREG_GPR1,IFrameSize
.endm
//---------------------------------------------------------------------
//
// Macro for vector handler calling.
//
//---------------------------------------------------------------------
MACRO1(call_vector_hander, int_num)
// Pass the exception ordinal for this exception.
li XREG_GPR3, PARAM(int_num)
// Get address of the vector table in r9.
lis XREG_GPR9,XExc_VectorTable@ha
la XREG_GPR9,XExc_VectorTable@l(XREG_GPR9)
// Multiply vectorNumber (from r3) by 16 into r0.
mr XREG_GPR11,XREG_GPR3
slwi XREG_GPR0,XREG_GPR11,4
//mulli r0,r11,12
// Get the Nth vector element at r9 + r0 into r9.
add XREG_GPR9,XREG_GPR9,XREG_GPR0
// Get the vector address into r11.
lwz XREG_GPR11,0(XREG_GPR9)
// Get the user data value into r4.
lwz XREG_GPR3,4(XREG_GPR9)
// Get the read only small data area pointer into r2.
lwz XREG_GPR2,8(XREG_GPR9)
// Get the read/write small data area pointer into r13.
lwz XREG_GPR13,12(XREG_GPR9)
// NOT! Pass exception ordinal parameter in r3.
// Pass user data value parameter in r4.
// Move the vector address to the LR and call it.
mtlr XREG_GPR11
blrl
.endm
//---------------------------------------------------------------------
//
// Macro for critical interrupts vector code.
//
//---------------------------------------------------------------------
MACRO2(critical_interrupt, base, int_num)
int_prologue PARAM(base)
// Save MSR register from SRR3.
mfsrr3 XREG_GPR0
stw XREG_GPR0,MSRField(XREG_GPR1)
// Save current PC location from SRR2.
mfsrr2 XREG_GPR0
stw XREG_GPR0,PCField(XREG_GPR1)
// Call the vector handler for this exception.
call_vector_hander PARAM(int_num)
// Restore MSR register to SRR3.
lwz XREG_GPR0,MSRField(XREG_GPR1)
mtsrr3 XREG_GPR0
// Restore current PC location to SRR2.
lwz XREG_GPR0,PCField(XREG_GPR1)
mtsrr2 XREG_GPR0
int_epilogue
// Return to the interrupted code
rfci
.endm
//---------------------------------------------------------------------
//
// Macro for non-critical interrupts vector code.
//
//---------------------------------------------------------------------
MACRO2(non_critical_interrupt, base, int_num)
int_prologue PARAM(base)
// Save MSR register from SRR1.
mfsrr1 XREG_GPR0
stw XREG_GPR0,MSRField(XREG_GPR1)
// Save current PC location from SRR0.
mfsrr0 XREG_GPR0
stw XREG_GPR0,PCField(XREG_GPR1)
// Call the vector handler for this exception.
call_vector_hander PARAM(int_num)
// Restore MSR register to SRR1.
lwz XREG_GPR0,MSRField(XREG_GPR1)
mtsrr1 XREG_GPR0
// Restore current PC location to SRR0.
lwz XREG_GPR0,PCField(XREG_GPR1)
mtsrr0 XREG_GPR0
int_epilogue
// Return to the interrupted code
rfi
.endm
//---------------------------------------------------------------------
//
// Vector table.
//
// Define the vector table for all exceptions. The code for each
// exception is assembled inline at each vector entry point. Most
// PPC exceptions are 0x100 bytes apart, so there is 256 bytes of
// code space to handle an exception. The current exception code
// spans about 160 bytes, this code size fits.
//
// NOTE:
//
// Vectors 0x1010 (fixed interval timer) and 0x1020 (watchdog timer)
// are only 16 bytes apart and don't have enough room for the exception
// handling code to fit between them. Fortunately, there is a hole in
// the exception location sequence. Vectors 0x1100 through 0x1F00 are
// not used in the 405. So as a work-around, relocate the exception
// code for vectors 0x1010 and 0x1020 (where there isn't space) to
// the unused locations 0x1300 and 0x1400 (where the is room).
// Locations 0x1010 and 0x1020 merely contain a branch to the proper
// reloacated exception code; which fits within the 16 bytes of space
// of these "special" vector locations.
//
// If in the future this code is used for a different PPC processor,
// this vector table may need to be changed.
//
//---------------------------------------------------------------------
.globl _vectorbase
_vectorbase:
// Vector 0x0000, Jump to zero.
critical_interrupt 0000, 0
// Vector 0x0100, Critical interrupt.
critical_interrupt 0100, 1
// Vector 0x0200, Machine Check interrupt.
critical_interrupt 0200, 2
// Vector 0x0300, Data Storage interrupt.
non_critical_interrupt 0300, 3
// Vector 0x0400, Instruction Storage interrupt.
non_critical_interrupt 0400, 4
// Vector 0x0500, External interrupt.
non_critical_interrupt 0500, 5
// Vector 0x0600, Alignment interrupt.
non_critical_interrupt 0600, 6
// Vector 0x0700, Program interrupt.
non_critical_interrupt 0700, 7
// Vector 0x0800, FPU Unavailable interrupt.
non_critical_interrupt 0800, 8
// Vector 0x0C00, System Call interrupt.
non_critical_interrupt 0C00, 9
// Vector 0x0F20, APU Available interrupt.
non_critical_interrupt 0F20, 10
// Vector 0x1000, PIT interrupt.
// This vector need the workaround described above
.org _vectorbase + 0x1000
b _vector1300
// Vector 0x1010, FIT interrupt.
// This vector need the workaround described above
.org _vectorbase + 0x1010
b _vector1400
// Vector 0x1020, Watchdog Timer interrupt.
.org _vectorbase + 0x1020
critical_interrupt 1020, 13
// Vector 0x1100, Data TLB Miss interrupt.
non_critical_interrupt 1100, 14
// Vector 0x1200, Instruction TLB Miss interrupt.
non_critical_interrupt 1200, 15
// Work-around!!! Real vector 0x1000, PIT
// interrupt exception code. This gets around
// the vector space/span problem. See title
// block above.
non_critical_interrupt 1300, 11
// Work-around!!! Real vector 0x1010, FIT
// interrupt exception code. This gets
// around the vector space/span problem. See
// title block above.
non_critical_interrupt 1400, 12
// Vector 0x2000, Debug interrupt.
critical_interrupt 2000, 16
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -