270 likes | 467 Views
ARM / Thumb 交互工作. 议程. 交互工作基础 交互子程序 ARM 5T 架构扩展. 交互需求. Thumb 的代码密度和在窄存储器上性能 , 使得它用在很多有大量 C 代码的系统上比较理想 . 然而在很多应用中还是需要在 ARM/Thumb 两种状态之间切换 : 在宽的存储器上 ARM 代码能提供很好的性能 在一个应用中,速度关键的部分用 ARM 代码实现是不错的 一些函数只能用 ARM 指令实现, e.g. 存取 CPSR ( 使能 / 禁止中断和状态的改变) 操作协处理器 异常处理
E N D
议程 • 交互工作基础 交互子程序 ARM 5T 架构扩展
交互需求 • Thumb的代码密度和在窄存储器上性能 ,使得它用在很多有大量C代码的系统上比较理想. 然而在很多应用中还是需要在 ARM/Thumb 两种状态之间切换: • 在宽的存储器上 ARM 代码能提供很好的性能 • 在一个应用中,速度关键的部分用ARM代码实现是不错的 • 一些函数只能用 ARM 指令实现, e.g. • 存取 CPSR (使能/禁止中断和状态的改变) • 操作协处理器 • 异常处理 • 异常处理时自动进入 ARM 状态,但系统要求主程序用 Thumb 代码实现 • 独立的 Thumb 程序也需要一个ARM 的汇编程序头来切换,并调用Thumb 程序
交互指令 • 交互的实现采用跳转交换指令(BX) • 在Thumb状态 BX Rn • 在ARM状态 (支持Thumb的内核) BX<条件> Rn 其中Rn可以是 (r0~r15)中的任何一个. • 这将通过拷贝 Rn 到 PC 来实现在 4GB 空间内的一个绝对跳转. • 其中Rn 的 Bit-0 表明切换到何种状态.
状态切换 1 0 31 1 0 Rn 目的地址 0/1 ARM / Thumb 选择位 0 - ARM state 1 - Thumb state BX 31 PC
分支交换示例 • CODE32 ; Start off in ARM state • ADR r0,Into_Thumb+1; Generate branch target address and set • ; bit 0, hence arrive in Thumb state. • BX r0 ; Branch exchange to Thumb state. • : • CODE16 ; Assemble subsequent code as Thumb. • Into_Thumb • : • ADR r5, Back_to_ARM ; Generate branch target to word aligned • ; address - hence bit 0 is clear. • BX r5 ; Branch exchange back to ARM state. • : • CODE32 ; Assemble subsequent code as ARM. • Back_to_ARM • :
提纲 交互基础 • 交互子程序 ARM 5T 架构扩展
无交互子程序 • 实现一个通常的子程序调用需要如下两步: • 保存返回地址到寄存器(LR) • 跳转到对应的子程序地址 • 调用实现通常只需要一个指令: BL func2 • 返回实现通常只需从 LR 恢复 PC: MOV pc,lr func1 func2 void func1 (void) { : func2(); : } . . BL func2 . . : MOV pc,lr
混合的ARM/Thumb子程序 • 在使用 C / C++ 写程序时,可以自由的编译为 ARM ( 使用armcc/armcpp) 或 Thumb ( 使用tcc/tcpp). • 需要一些编译方法来解决在一种状态下的函数调用另一种状态下的函数的问题. • 涉及到的问题: • BL不能完成状态切换 • 需要使用 BX切换 • BX不能自动保存返回地址到 LR • 需要其它方法来解决这个问题 • 从子程序返回,要使用 BX LR以便返回先前的状态 • BL在 Thumb 状态下可能设置了 LR 的 lsb (bit-0) • 不能使用 MOV PC,LR 返回,因为不能实现状态切换
交互子程序 • 任何包含使用交互调用函数的 C 模块的编译必须使用 -apcs /interwork命令行选项. • 编译器将使用BX实现函数返回来替代 MOV PC,LR. • 连接器生成一小段代码(‘veneers’)来改变状态 • 当发现交互调用时自动加入目标文件 • 使用 armlink -info veneers 可以看到加入的“ veneers”的大小, func1 func2 (compiled for interworking) : BX : BL : : BX 连接程序生成 veneer
ARM 4T架构对交互编译的影响 • leaf function使用BX 返回. • Non_leaf function将被交互编译: • 在入口处( 调用 BL 之前)压栈保护返回地址 • 在入口处保护所有函数使用的寄存器 • 使用BX实现返回操作 (替代弹出 PC). C 源代码 armcc -apcs /interwork tcc -apcs /interwork void func(void) func func { STMFD sp!,{r4-r11,lr} PUSH {r4-r7,lr} : : : sub(); BL sub BL sub : : : : LDMFD sp!,{r4-r11,lr} POP {r4-r7} } BX lr POP {r3} BX r3
汇编程序交互工作和Veneers • 连接程序将会自动加入ARM / Thumb交互 veneers到汇编源代码. • 主调程序需要: • 使用 armasm -apcs /interwork 汇编 • 导出自己的符号, e.g. EXPORT ThumbSub • 使用 BX 实现返回 • 主调程序使用 BL 指令调用子程序. • Note: AREA 将包含:AREA Thumb,CODE,READONLY,INTERWORK 如果如此, armasm 将警告:INTERWORK area directive is obsolete. Continuing as if -apcs /inter selected.
汇编程序交互工作 (1) ; armasm arm.s AREA Arm,CODE,READONLY IMPORT ThumbSub ENTRY CODE32ARMProg MOV r0, #1 BL ThumbSub ;call Thumb subroutine MOV r0, #0x18 LDR r1, =0x20026 SWI 0x123456 ;ARM semihosting SWI END ; armasm thumb.s -apcs /interwork AREA Thumb,CODE,READONLY EXPORT ThumbSub CODE16 ThumbSub MOV r1, #2 BX lr ;return to caller END
汇编程序交互工作 (2) • 使用Debugger反汇编代码: ARMProg 0x00008080: 0xe3a00001 : mov r0,#1 0x00008084: 0xeb000004 : bl 0x809c ; (ThumbSub + 0x4) 0x00008088: 0xe3a00018 : mov r0,#0x18 0x0000808c: 0xe59f1000 : ldr r1,0x8094 ; =#0x00020026 0x00008090: 0xef123456 : swi 0x123456 0x00008094: 0x00020026 : Literal Pool Value ThumbSub 0x00008098: 0x2102 : mov r1,#2 0x0000809a: 0x4770 : bx lr • 交互veeners在下一个字的边界 0x0000809c: 0xe59fc000 : ldr r12,0x80a4 ; =#ThumbSub+0x1 0x000080a0: 0xe12fff1c : bx r12 0x000080a4: 0x00008099 : Literal Pool Value
C / 汇编使用 Veneers交互工作 • 运行在一种状态下的 C 代码可能调用运行在另一种状态下的汇编程序,反之亦然。 • 这时的 veneers 由连接程序自动生成。 • 如果主调函数是 C 函数, 编译时使用-apcs /interwork • 如果主调函数是汇编函数, 汇编时使用 -apcs /interwork且返回使用 BX LR • 任何使用这些的汇编程序必须符合 ATPCS 标准 ,( e.g. 函数参数传递使用 r0-r3 & r12 不受保护的)
交互调用 允许ARM-ARM调用 • 最好使用交互选项build所有的程序 非交互的 Thumb 代码 不可调用 非交互的 ARM 代码 允许Thumb-Thumb调用 允许非交互的调用交互的 允许ARM/Thumb 调用 交互的Thumb 代码 交互的ARM 代码
连接交互工作的目标代码 • 为了顺利连接: • 必须使用统一的 APCS 标准“built”所有的 C/C++/Asm 文件. • 要使用相应的交互工作库 • 连接程序发现任何的不协调就会给出一个错误:Invalid call from THUMB code in thumbmain.o(.text) to ARM symbol arm_function. • 修正编译器/ 汇编器的配置 (e.g. 加上-apcs/interwork),然后重新连编。 • 连接时使用‘-info veneers’来得到增加的veneers的概况, e.g.:Adding AT veneer (12 bytes) for call to '_printf’ from Thumb_to_ARM.o(.text) Adding TA veneer (12 bytes) for call to 'arm_function’ from thumbmain.o(.text) • 小心非法的间接调用 (e.g. 函数指针, 动态跳转表) – 连接器对这种情况在连接时是不会给出警告的。
使用 CodeWarrior 交互工作 • 使用 Thumb /ARM 交互工作工程模板 • 向 ARMDebugRel 目标加入ARM C, C++ & Asm 模块 • 编译 C 模块使用 ‘armcc -apcs /interwork’ • 编译 C++ 模块使用‘armcpp -apcs /interwork’ • 编译 ASM 模块使用‘armasm -32 -apcs /interwork’ • 向 ThumbDebugRel 目标加入Thumb C, C++ & Asm 模块 • 编译 C 模块使用 ‘tcc -apcs /interwork’ • 编译 C++ 模块使用‘tcpp -apcs /interwork’ • 编译 ASM 模块使用‘armasm -16 -apcs /interwork’ • ARMDebugRel 将会被编译连接 (部分连接)成 ThumbDebugRel的一个子目标
提纲 交互工作基础 交互工作子程序 • ARM 5T 架构扩展
Architecture 5T Interworking • ARM 5T 架构增加了对交互工作的支持 • 消除了对veneers的需求 • 兼容ARM 4T 架构的代码 • 改良内容包括 • 新的 BLX 指令 • 修正了加载 PC 的动作
BLX <offset> • ARM • 调用Thumb子程序 • 通常切换到 Thumb 状态 • 32 MB 分支范围 • 返回地址保存在 LR 中 • 使用 BX LR 从子程序返回 • 无条件指令 • Thumb • 调用ARM子程序 • 转化为两个16-bit 指令 • 偏移范围同 Thumb 的 BL 指令 • i.e. +/- 4MB 范围 • 返回地址保存在LR (同时设置LSB) CPSR T bit = 1 : BLX offset : : BX lr ARM Thumb
BLX Rm • 和标准的 BX指令相同,除了保存返回地址到Lr中 • ARM 版本下可条件执行 • Thumb 版本下 • 单一的 16-bit 指令 • LR 的 LSB 将被设置 • 使用 BX LR 从子程序返回 31 1 0 Rm 0/1 目的地址 ARM / Thumb选择位 0 - ARM state 1 - Thumb state BLX Rm 31 1 0 PC 0
送数到 PC • LDM {cond} <addressing mode> Rn, {…,PC} • 增加了对交互的支持表 v4T behaviour with extra support for interworking • 如果 PC 是一个加载寄存器那么 • 加载值的bit[0]将被写入CPSR 的 T-bit (这将可能导致一状态切换) • 用作恢复寄存器同时从子程序返回 • 用来替换 LDMFD sp!,{...,LR} + BX LR • Thumb POP {…,PC}有同样的功能 • LDR PC, [Rn,...]同样依据加载值的0-bit来设置CPSR 的 T-bit • 可以用作跳转表 • 没有相当的 Thumb 指令 0...0 0010 1110 110 1 PC = LDMFD sp!,{…,PC} CPSR = cond T mode
ARM 5T 架构对交互编译的影响 • 叶函数简单使用 BX 来返回. • 非叶函数被编译成交互格式: • 在入口处( 调用 BL 之前)压栈保护返回地址 • 在入口处保护所有函数使用的寄存器 • 弹出 PC来实现返回(可能导致状态切换). C source codearmcc -cpu 5T -apcs /intertcc -cpu 5T -apcs /inter void func(void) func func { STMFD sp!,{r4-r11,lr} PUSH {r4-r7,lr} : : : sub(); BL sub BL sub : : : } LDMFD sp!,{r4-r11,pc} POP {r4-r7,pc} • 连接程序将根据需要修正BX为BLX
更详细的资料 ... ADS Developer Guide, Chapter 4, Interworking ARM and Thumb
Quiz 1) What determines whether a state change occurs when a BX instruction is executed? 2) What are the difference between a BX and a BL instruction? 3) What must you do to interwork C functions? 4) What must you do to interwork assembler functions? 5) What advantage do the Architecture 5T BLX instructions give ?