第4章Thumb指令集

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第4章Thumb指令集
第4章Thumb 指令集
●Thumb 寄存器的使用
●ARM-Thumb 交互
●其它分支指令
●数据处理指令
●单寄存器load-store指令
●多寄存器load-store 指令
●堆栈指令
●软件中断指令
●总结
本章介绍Thumb指令集。

Thumb把32位ARM指令集的一个子集进行编码,成为一个16位的指令集。

在16位外部数据总线宽度下,在ARM处理器上使用Thumb指令的性能要比使用ARM指令的性能更好;而在32位外部数据总线宽度下,使用Thumb指令的性能要比使用ARM指令的性能差。

因此,Thumb指令多用于存储器受限的一些系统中。

相对于ARM指令集,使用Thumb指令集可获得更高的代码密度—一个可执行的程序在内存中所占的空间。

在存储器受限的嵌人式系统中,比如移动电话、PDA等,代码密度是非常重要的;同时,成本压力也会限制存储器的大小、数据宽度和速度。

平均而言,对于同一个程序,使用Thumb指令实现所需的存储空间,要比等效的ARM 指令实现少30%左右,图4. 1显示了对于实现同样的除法运算,使用ARM指令和使用Thumb 指令的汇编代码。

虽然Thumb指令的实现使用了更多的指令,但是它所占的总的存储空间却比较小。

代码密度是Thumb指令集的一个主要优势。

由于Thumb 指令集的设计是面向编译器的,而不是针对手写汇编的,所以推荐使用高级语言如C或者C++语言
来编程,然后用编译器生成Thumb指令的目标代码。

图4.1 代码密度
每一条Thump指令都和一条32位的ARM指令相关。

图4. 2显示了一条Thumb加法指令ADD译码成等效的ARM加法指令,表4. 1给出了在ARMv5TE架构,F的THUMBv2中所有的Thumb指令。

在ThumbISA 中,只有分支指令可被条件执行;同时由于16位空间的限制,桶形移位操作如ASR,LSL,LSR 和RQR,也变成单独的指令。

表4.1 Thumb指令集
续表 4.1
4.1 Thumb 寄存器的使用
在Thumb状态下,不能直接访问所有的寄存器,只有寄存器r0~r7是可以被任意访问的,如表4.2所列。

寄存器r8~r12只能通过MoV, ADD或CMP指令来访问。

CMP指令和所有操作r0~r7的数据处理指令都会影响cpsr中的条件标志。

表4.2Thumb 寄存器的使用
从表4.1和表4.2可以看出,不能直接访问cpsr和spar。

换句话说,没有与MSR和MRS 等价的Thumb指令。

为了改变cpsr或spar的值,必须切换到ARM状态,使用MSR 和MRS来实现。

同样,在Thumb状态下没有协处理器指令,要访问协处理器来配置cache和进行内存管理,也必须在ARM状态下。

ARM- Thumb交互.是指对汇编语言和C/C++语言的ARM和Thumb代码进行连接的方法,它进行两种状态(ARM和Thumb)间的转换。

在进行这种转换时,有时须使用额外的代码,这些代码被称为胶分(veneer).A TPCS定义了ARM和Thumb过程调用的标准。

从一个ARM例程调用一个Thumb例程,内核必须切换状态。

状态的变化由cpsr中的T位来显示。

在跳转到一个例程时,BX和BLX 分支指令可用于ARM和Thumb状态的切换,BX 1r指令从一个例程返回,如果需要,也可以进行状态切换。

BLX指令在ARMv5T中引入。

在ARMv4T核中,连接器在子程序调用时,使用胶合来完成状态的切换。

连接器不是直接调用例程,
而是通过调用胶合,由胶合使用BX指令来切换到Thumb状态。

有2个版本的BX和BLX指令:ARM指令和等效的Thumb指令。

ARM BX指令只有当Rn中地址的最低位为1时,才进人Thumb状态;否则进人ARM状态。

Thumb B指令以同样的方式工作。

语法:
与ARM版本的BX指令不同,Thumb BX指令不能被条件执行。

【例4.1 】显示使用ARM BX和Thumb BX的一个小代码段。

可以看到,进人Thumb的分支地址的最低位是置1的,这将置位cpsr中的T位而进人Thumb状态。

使用BX指令时,返回地址不是自动保留的,因而在跳转指令调用前,通过显式地使用MOV指令来设置返回地址。

;ARM代码
CODE32 ;字对齐
LDR r0,=thumbCode ;+1进入thumb状态
MOV 1r,pc ;设置返回地址
BX r0 ;返回Thumb状态
;继续其它的代码
;Thumb 代码
CODE16 ;半字对齐
thumbCode
ADD r1,#1
BX 1r ;返回ARM状态
如果没有通过位0的强制置1来进行状态转换,那么分支切换指令也可以用作一个绝对跳转指令。

; address(thumbCode)=0x00010000
; cpsr=nzcvqIFT_SVC
; r0=0x00000000
0x00009000 LDR r0, =thumbCode+1
; cpsr=nzcvqIFT_SVC
; r0=0x00010001
0x00009008 BX r0
; cpsr=nzcvqIFT_SVC
; r0=0x00010001
; pc=0x00010000
可以看到,r0的最低位用于置位cpsr中的T位,cpsr从执行BX指令前的IFt变为执行后的IFT, pc指向到Thumb例程的起始地址。

【例4. 2】使用BLS指令代替BX指令简化了Thumb例程的调用,因为BLX指令在链接寄存器}r中自动设置了返回地址。

CODE32
LDR r0,=thumbCode ;进入thumb状态
BLX r0 ;跳到Thumb代码
;其它代码
CODE16
ThumbRoutine
ADD r1,#1
BX r14 ;返回到ARM状态
4.3 其它分支指令
有2个标准分支指令的变体,即B指令;第1个变体与ARM版本指令相似,可条件执行,跳转被限制在有符号8位立即数所表示的范围内.或者是-256~254字节;第2个变体不可条件执行(没有条件码部分),但扩展了有效跳转范围——有符号的11位立即数表示的范围,或-2 048~+-2 046字节。

条件分支指令是Thurnb指令中惟一可以条件执行的指令。

语法:
BL指令不可条件执行,可以在大约+/- 4 MB的范围内跳转,因为BL(和BLX)指令被转换成一对16位的Thumb指令,因而,上述跳转范围是合理的。

这对指令中的第1条包含跳转偏移量的高位部分,第2条包含其低位部分,这些指令必须成对使用。

这里列出了从BL子程序调用返回的不同指令:
MOV pc,1r
BX 1r
POP{pc}
POP堆栈操作指令将在4.7节中详细讨论。

4.4数据处理指令
数据处理指令可以操作寄存器中的数据,包括MOV指令、算术指令、移位指令、逻辑指令、比较指令和乘法指令。

Thump数据处理指令是ARM数据处理指令的一个子集。

语法:
Rd,Rm
Rd,Rn #immediate
Rd,Rn,Rm
ADD Rd,pc, #immediate
ADD Rd,sp, #immediate
sp, #immediate
Rd,Rs
Rn,Rm
CMP Rn,#immediate
MOV Rd,Rn
这些指令与等价的ARM指令使用相同的格式。

大多数的Thumb 数据处理指令操作寄存器r0~r7,同时会更新cpsr。

但是下列指令是例外:
MOV Rd,Rn
ADD Rd,Rn
CMP Rn,Rm
ADD sp,#immediate
SUB sp,#immediate
ADD Rd, sp, #immediate
ADD Rd,pc, #immediate
这些指令可以操作寄存器r8~r14时,除了CMP指令外,其它指令不改变cpsr中的条件标志.CMP指令总是更新cpsr
【例4. 3】一个简单的Thumb ADD指令。

指令带有两个寄存器r1和r2,把它们相加后的结果放到寄存器r0,同时更新cpsr的值。

PRE
cpsr=nzcvIFT_SVC
r1=0x80000000
r2=0x10000000
ADD r0, r1, r2
POST
r0=0x9000000
cpsr=NzcvIFT_SVC
【例4. 4】与ARM方式不同,Thumb的桶形移位操作(ASR,LSL,LSR及RDR)是单独的指令。

这个例子显示了逻辑左移(LSL)指令,把寄存器r2乘以2。

PRE
r2=0x00000002
r4=0x00000001
LSL r2, r4
POST
r2=0x00000004
r4=0x00000001
完整的Thumb数据处理指令列表,请参见附录A.
4.5单寄存器load-store指令
Thumb指令集支持寄存器的装载和存储,即LDR和STR指令。

这些指令使用2种前变址寻址方式:寄存器偏移和立即数偏移。

语法:
{B︱H>}Rd,[Rn,#immediate]
LDR{}Rd,[Rn,Rm]
STR {}Rd,[Rn,Rm]
LDR Rd,[pc,#immediate]
Rd,[sp,#immediate]
表4. 3列出了不同的寻址方式.第1种寻址方式为寄存器偏移使用一个基址寄存器Rn 加上寄存器偏移量Rm;第2种寻址方式使用基址寄存器Rn加上一个5位的立即数或者一个依赖于数据尺寸的值。

5位的偏移在指令中的编码根据8位访问、16位访问及32位访问,分别乘以1,2及4。

表4.3 寻址模式
【例4.5】显示两个使用前变址寻址方式的Thumb指令,它们执行前的条件是一样的。

PRE
Mem32[0x9000]=0x00000001
Mem32[0x9004]=0x00000002
Mem32[0x9008]=0x00000003
r0=0x00000000
r1=0x00090000
r4=0x00000004
LDR r0, [r1,r14] ;register
POST
r0=0x00000002
r1=0x00090000
r4=0x00000004
LDR r0, [r1,#0x4] ;immediate
POST
r0=0x00000002
这2条指令执行同样的操作。

惟一的区别是第2条LDR使用了一个固定偏移,而第1条LDR的偏移依赖于寄存器r4。

4.6多寄存器load-store指令
Thumb指令集的多寄存器load-store指令是ARM指令集的多寄存器load-store指令的简化形式。

在Thumb指令集的多寄存器load-store。

指令只支持后增量(IA)寻址方式。

语法:
IA Rn!,{low register list:r0~r7}
这里N是寄存器列表中寄存器的数目。

从表中可看到,指令执行后总是更新基址寄存器,基址寄存器和可以使用的寄存器列表仅限于r0~r7。

【例4.6】保存r1~r3到内存地址0900~0x900c,并且更新基址寄存器r4。

需要指出的是,这里更新字符“!”不是可选的,这与ARM指令集不同。

PRE
r1=0x00000001
r2=0x00000002
r3=0x00000003
r4=09000
STMIA r4!, {r1,r2,r3}
POST
mem32[0x9000] =0x00000001
mem32[0x9004] =0x00000002
mem32[0x9008] =0x00000003
r4=0x900c
4.7 堆栈指令
Thumb的堆栈操作与等效的ARM指令是不同的,因为它们使用了更传统的POP和push 的概念。

语法:
POP {low_register_list{,pc}}
PUSH{low_register_list{,1r}}
注意:在指令中没有堆栈指针,这是因为在Thumb操作中,寄存器r13是因定作为堆栈指针用的,sP是自动更新的。

可操作的寄存器列表仅限于寄存器r0~r7.
PUSH指令可以操作的寄存器还包括链接寄存器1r,同样POP指令可以操作pc。

这为子程序的进人和退出提供了支持,如例4.7所述。

堆栈指令仅支持递减式满堆栈操作。

【例4.7】使用PUSH和POP指令,子程序Thumb Routine使用带链接的分支指令(BL)来调用。

;调用子程序
BL ThumbRoutine
;其它代码
ThumbRoutine
PUSH {r1, 1r} ;进入子程序
MOV r0, #2
POP{r1, pc} ;从子程序返回
链接寄存器1r和r1被压人堆栈,在返回时,寄存器r1的值被原来的r1出伐恢复,pc 被原来人栈的1r的值覆盖。

这就完成了从子程序返回。

4.8 软件中断指令
与ARM指令集下的软件中断指令相似,Thumb软件中断指令(SWI)也产生一个软件中断异常。

在Thumb状态下,如果有任何中断或者异常标志出现,那么处理器就会自动回到ARM状态去进行异常处理。

语法:
Thumb SW'I指令与等效的ARM指令有同样的作用和几乎完全相同的语法。

区别是
Thumb SWI数目限制在0~255,并且不能条件执行。

【例4. 8】显示Thumb SWI的执行。

注意:在执行该指令后,处理器从Thurnb状态切换到ARM状态。

PRE
cpsr=nzcVqift_USER
pc= 0x00008000
1r=0x003fffff ;1r=r14
r0 =0x12
0x0008000 SWI 0x45
POST
cpsr=nzcVqift_SVC
spsr= nzcVqift_USER
pc= 0x00008000
1r= 0x00008002
4.9 总结
本章主要介绍了Thumb指令集。

所有的Thumb指令长度都是16位的,Thumb代码可以提供比ARM代码高大约30%的代码密度。

大多数Thumb代码都是由C或者C++这样的高级语言编译而成的。

ATPCS定义了ARM和Thumb代码如何相互调用,称为ARM-Thumb交互。

交互使用分支切换指令BLX和带链接的分支切换指令BLX来改变状态,并跳转到特定的例程。

在Thumb指令集中,只有分支指令可以条件执行,桶形移位操作(ASR,LSL,LSR及ROR)是单独的指令。

多寄存器load-store指令只支持后曹量(IA )寻址方式.Thumb指令集包括POP和PUSH 指令,用以进行堆栈操作,这些指令只支持逮减式满堆栈。

Thumb指令不可以访问协处理器、cpsr和spsr。

相关文档
最新文档