Linux异常体系之vector_stub宏解析

 ARM-Linux汇编的宏定义语法说明如下:

使用注意:

1.宏定义以.macro开始,以.endm结束

2.可带参数,参数可有默认值

3.直接使用参数的名字\arg

 

vector_stub宏的功能:

计算处理完异常的返回地址;

保存寄存器(r0,lr,spsr)

进入管理模式;

最后根据进入异常前的模式跳转到相应的某个分支。

 1 /*
 2  * Vector stubs.
 3  *
 4  * This code is copied to 0xffff0200 so we can use branches in the
 5  * vectors, rather than ldr's.  Note that this code must not
 6  * exceed 0x300 bytes.
 7  *
 8  * Common stub entry macro:
 9  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
10  *
11  * SP points to a minimal amount of processor-private memory, the address
12  * of which is copied into r0 for the mode specific abort handler.
13  */
14     .macro    vector_stub, name, mode, correction=0
15     .align    5
16 
17 vector_\name:
18     .if \correction
19     sub    lr, lr, #\correction
20     .endif
21 
22     @
23     @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
24     @ (parent CPSR)
25     @
26     stmia    sp, {r0, lr}        @ save r0, lr
27     mrs    lr, spsr
28     str    lr, [sp, #8]        @ save spsr
29 
30     @
31     @ Prepare for SVC32 mode.  IRQs remain disabled.
32     @
33     mrs    r0, cpsr
34     eor    r0, r0, #(\mode ^ SVC_MODE)
35     msr    spsr_cxsf, r0
36 
37     @
38     @ the branch table must immediately follow this code
39     @
40     and    lr, lr, #0x0f
41     mov    r0, sp
42     ldr    lr, [pc, lr, lsl #2]
43     movs    pc, lr            @ branch to handler in SVC mode
44     .endm

 展开

 1 /*
 2  * Interrupt dispatcher
 3  */
 4     vector_stub    irq, IRQ_MODE, 4
 5 
 6     .long    __irq_usr            @  0  (USR_26 / USR_32)
 7     .long    __irq_invalid            @  1  (FIQ_26 / FIQ_32)
 8     .long    __irq_invalid            @  2  (IRQ_26 / IRQ_32)
 9     .long    __irq_svc            @  3  (SVC_26 / SVC_32)
10     .long    __irq_invalid            @  4
11     .long    __irq_invalid            @  5
12     .long    __irq_invalid            @  6
13     .long    __irq_invalid            @  7
14     .long    __irq_invalid            @  8
15     .long    __irq_invalid            @  9
16     .long    __irq_invalid            @  a
17     .long    __irq_invalid            @  b
18     .long    __irq_invalid            @  c
19     .long    __irq_invalid            @  d
20     .long    __irq_invalid            @  e
21     .long    __irq_invalid            @  f

后得到

 1 /*
 2  * Interrupt dispatcher
 3  */
 4     .align    5
 5 
 6 vector_irq:
 7     sub    lr, lr, #4               //保存irq返回地址
 8 
 9     @
10     @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
11     @ (parent CPSR)
12     @
13     stmia    sp, {r0, lr}        @ save r0, lr
14     mrs    lr, spsr
15     str    lr, [sp, #8]        @ save spsr
16 
17     @
18     @ Prepare for SVC32 mode.  IRQs remain disabled.
19     @
20     mrs    r0, cpsr
21     eor    r0, r0, #(\mode ^ SVC_MODE)
22     msr    spsr_cxsf, r0 //对spsr的所有控制位进行写操作,将r0的值全部注入spsr,进入svc模式
23 
24     @
25     @ the branch table must immediately follow this code
26     @
27     and    lr, lr, #0x0f  //根据进入中断前的模式跳转到相应的中断处理函数
28     mov    r0, sp
29     ldr    lr, [pc, lr, lsl #2]
30     movs    pc, lr            @ branch to handler in SVC mode
31 
32 
33     .long    __irq_usr            @  0  (USR_26 / USR_32)
34     .long    __irq_invalid            @  1  (FIQ_26 / FIQ_32)
35     .long    __irq_invalid            @  2  (IRQ_26 / IRQ_32)
36     .long    __irq_svc            @  3  (SVC_26 / SVC_32)
37     .long    __irq_invalid            @  4
38     .long    __irq_invalid            @  5
39     .long    __irq_invalid            @  6
40     .long    __irq_invalid            @  7
41     .long    __irq_invalid            @  8
42     .long    __irq_invalid            @  9
43     .long    __irq_invalid            @  a
44     .long    __irq_invalid            @  b
45     .long    __irq_invalid            @  c
46     .long    __irq_invalid            @  d
47     .long    __irq_invalid            @  e
48     .long    __irq_invalid            @  f

 

posted @ 2017-10-05 20:33  bluebluebluesky  阅读(1254)  评论(0编辑  收藏  举报