📄 vectors.s
字号:
/* Before branching to common code, load a value to translate the */
/* vector table offset to the ISR table offset. The ISR vector table */
/* contains the autovectors (0-6) followed by the interrupt vectors */
/* (7-198). */
.equ int_pres_regs_sz,((2+3)*4)
.macro int_pres_regs
lea.l -int_pres_regs_sz(%sp),%sp
movem.l %d0-%d2/%a0-%a1,(%sp)
.endm
.macro int_rest_regs
movem.l (%sp),%d0-%d2/%a0-%a1
lea.l int_pres_regs_sz(%sp),%sp
.endm
.text
.balign 4
hw_vsr_interrupt:
int_pres_regs /* Preserve all registers */
/* that this ISR routine needs */
/* to preserve. The C code */
/* will preserve all other */
/* registers. */
move.l #(-64+7)*4,%d0 /* Adding this value to the */
/* vector table offset will */
/* result in the corresponding */
/* offset into the ISR table. */
/* Fall through to common code. */
hw_vsr_int_common: /* Common code. */
/* d0.l: Contains a value to translate the vector table offset to */
/* the ISR table offset. */
move.w int_pres_regs_sz(%sp),%d1 /* Calculate the vector */
and.l #0x000003fc,%d1 /* offset. The format/vector */
/* word on the stack contains */
/* the vector number. Mask off */
/* all unused bits. The bit */
/* position of the vector */
/* number field makes it */
/* automatically multiplied by */
/* four. */
add.l %d1,%d0 /* Calculate the ISR table */
/* offset. Add the vector */
/* table offset to the */
/* translation value. */
asr.l #2,%d1 /* Calculate the vector */
/* number using the vector */
/* table offset. */
/* d0.l: Contains the offset into the ISR table. */
/* d1.l: Contains the vector number. */
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
.extern cyg_scheduler_sched_lock /* Lock the scheduler if */
addq.l #1,cyg_scheduler_sched_lock /* we are using the kernel. */
#endif /* CYGFUN_HAL_COMMON_KERNEL_SUPPORT */
/* We need to call the following routines. The isr address, data, and */
/* intr are all from the ISR table. interrupt_end is a C routine and is */
/* only called if we are using the kernel. regs points to the saved */
/* registers on the stack. isr_ret is the return address from isr. vector */
/* is the vector number. */
/*
static cyg_uint32 isr(CYG_ADDRWORD vector,
CYG_ADDRWORD data)
externC void interrupt_end(cyg_uint32 isr_ret,
Cyg_Interrupt *intr,
HAL_SavedRegisters *regs)
*/
pea (%sp) /* Push the regs pointer. */
.extern cyg_hal_interrupt_objects /* Push the intr object */
lea cyg_hal_interrupt_objects,%a0 /* pointer from the table. */
move.l (%a0,%d0.l),-(%sp)
.extern cyg_hal_interrupt_data /* Push the data value */
lea cyg_hal_interrupt_data,%a0 /* from the table. */
move.l (%a0,%d0.l),-(%sp)
.extern cyg_hal_interrupt_handlers /* Get the address of the */
lea cyg_hal_interrupt_handlers,%a0 /* ISR from the table. */
move.l (%a0,%d0.l),%a0
move.l %d1,-(%sp) /* Push the vector number */
/* parameter. */
jbsr (%a0) /* Call the ISR. */
addq.l #4*1,%sp /* Remove the vector */
/* parameter from the stack. */
move.l %d0,(%sp) /* d0.l contains the return */
/* value from the ISR. */
/* Overwrite the data parameter */
/* with the ISR return value to */
/* pass as a parameter */
/* (isr_ret) to interrupt_end. */
/* The intr object and regs */
/* parameters are still on the */
/* stack. */
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
/* We only need to call interrupt_end() when there is a kernel */
/* present to do any tidying up. */
/* The interrupt_end routine will call the DSRs and do */
/* rescheduling when it decrements the scheduler lock from 1 to */
/* zero. In this case, we do not want to have interrupts masked */
/* while the DSRs run. Restore the interrupt mask to the value */
/* prior to this interrupt. Do not completely unmask all */
/* interrupts because this interrupt may be a nested interrupt. We */
/* do not want to lower the interrupt mask on the lower priority */
/* interrupt. */
move.w (4*3)+int_pres_regs_sz+2(%sp),%d2
move.w %d2,%sr
/* If the interrupt mask was not previously zero, we want to make */
/* sure that the DSRs to not run and no preemption occurs. Add the */
/* value of the previous interrupt mask to the scheduler lock. If */
/* the previous mask was zero, the scheduler lock will remain at */
/* one and the interrupt end function will decrement it to zero. */
/* Otherwise, we want to prevent the interrupt end function from */
/* unlocking the scheduler. We do this because there is a chance */
/* that someone had interrupts masked with the scheduler lock at */
/* zero. If a higher priority interrupt occurs, we could be */
/* running DSRs and doing preemption with the interrupts masked! */
and.l #0x0700,%d2
lsr.l #8,%d2
add.l %d2,cyg_scheduler_sched_lock
.extern interrupt_end /* Call the interrupt_end C */
jbsr interrupt_end /* routine. This routine might */
/* preempt the currently */
/* running thread. */
/* Now that interrupt end is complete, subtract the previous */
/* interrupt level back out of the scheduler lock. */
sub.l %d2,cyg_scheduler_sched_lock
#endif
lea (4*3)(%sp),%sp /* Remove the isr_ret, intr, */
/* and regs parameters from the */
/* stack. */
int_rest_regs /* Restore the preserved */
/* registers for the current */
/* thread. */
rte /* Restore the SR and PC. */
/****************************************************************************/
/* Autovector interrupt vector handler. */
/* Control is transferred here from an interrupt autovector (#25-31). */
/* Before branching to common code, load a value to translate the */
/* vector table offset to the ISR table offset. The ISR vector table */
/* contains the autovectors (0-6) followed by the interrupt vectors */
/* (7-198). */
.text
.balign 4
hw_vsr_autovec:
int_pres_regs /* Preserve all registers */
/* that this ISR routine needs */
/* to preserve. The C code */
/* will preserve all other */
/* registers. */
move.l #(-25+0)*4,%d0 /* Adding this value to the */
/* vector table offset will */
/* result in the corresponding */
/* offset into the ISR table. */
jra hw_vsr_int_common /* Branch into common code. */
/****************************************************************************/
/* hw_vsr_reset -- Hardware Reset Vector */
/* We assume that most of the chip selects are configured by the boot */
/* loader. */
.text
.balign 4
.globl hw_vsr_reset
hw_vsr_reset:
.globl __exception_reset /* Define the entry point for */
__exception_reset: /* the linker. */
move.w #0x2700,%sr /* Make sure that all */
/* interrupts are masked. */
lea hw_vsr_stack,%sp /* Load the reset and */
/* interrupt stack pointer. */
lea 0,%fp /* Set up the initial frame */
link %fp,#0 /* pointer. */
.extern hal_reset /* Call the C routine to */
jbsr hal_reset /* complete the reset process. */
9: stop #0x2000 /* If we return, stop. */
jra 9b
/****************************************************************************/
/* Interrupt and reset stack */
/* WARNING: Do not put this in any memory section that gets */
/* initialized. Doing so may cause the C code to initialize its own stack. */
.section ".uninvar","aw",@nobits
.balign 16
.global hw_vsr_stack_bottom
hw_vsr_stack_bottom:
.skip 0x2000
.balign 16
.global hw_vsr_stack
hw_vsr_stack:
.skip 0x10
/****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -