投稿人:Jacob Bramley,2010 年 9 月 30 日
Thumb-2 可利用ARM 指令集提供的相同条件执行功能。在有条件执行一两条指令时,这种机制与(更为传统的)条件分支机制相比,具备代码大小和性能方面的优势。
我在本系列博文上一篇的结尾处提到,Thumb 中并不直接提供这一机制。相反,Thumb-2 具有一个指令 : it 。它可提供与 ARM 条件执行相同的功能。在本文中,我将介绍 it 指令,也将说明 Thumb-2 中条件设置指令的一些注意事项。请注意,it 指令仅在 Thumb-2 中可用,因此本文大部分内容与旧版 Thumb 指令集 1 无关。
除了简单的条件分支外,Thumb-2 没有大多数 ARM 指令拥有的 4 位条件代码字段。相反,Thumb-2 具有 it 指令,它可以有条件地执行最多 4 条后续指令。受 it 指令影响的指令处于所谓的 it 块中。
助记符 it 代表 if-then 结构。如果条件代码(作为指令的参数提供)评估为 true,则执行下一条指令。最多可再添加三条 t (then) 或 e (else)代码,以控制后续指令的执行。例如,ite 读为 if-then-else,ittee 读为 if-then-then-else-else.下列代码可递增 r0,或者将它重置为 0(如果其大于或等于 10):
.syntax unified @ 别忘了这行
.syntax unified @
别忘了这行
.thumb
[...]
cmp r0, #10
ite lo @ if r0 is lower than 10 ...
addlo r0, #1 @ ... then r0 = r0 + 1
movhs r0, #0 @ ... else r0 = 0
请注意,依然必须像 ARM 汇编语言中一样,向 it 块中有条件执行指令提供条件代码。汇编程序将检查提供给 it 的条件是否与个别指令上的一致。then 条件必须与条件代码相符,而任何 else 条件则必须是相反的条件。在示例中, else 条件是 hs (大于或等于) — 于lo (小于)相反。下表列出了条件代码及其对立面:
hs
条件代码
对立面
代码
说明
eq
等于
ne
不等于。
hs (or cs)
cs
无符号大于或等于(或设置进位)。
lo (or cc)
lo
cc
无符号小于(或清除进位)。
mi
负值。
pl
正数或零。
vs
有符号溢出。
vc
无符号溢出。
hi
无符号大于。
ls
无符号小于或等于。
ge
有符号大于或等于。
lt
有符号小于。
gt
有符号大于。
le
有符号小于或等于。
al (or omitted)
al
始终执行。
al 没有对立面。
虽然将条件代码 al 提供给 it 是有效的,它没有对立面,因为不存在 never 代码。在使用 else 语句 的 it 指令中指定 al 条件代码是无效的。
正如其他指令一样,Thumb-2 的分支也可使用 it 有条件地执行。相反,有些指令无法在不使用 it 块的前提下有条件执行。但是,it 块中的任何分支必须是这个块中的最后一条指令。例如,如下所列是不正常的:
ite eq
blxeq some_label @ UNPREDICTABLE during an IT block.
movne r0, #0
实施上述代码的正确方式是将 mov 放到 blx 之前,如下所示:
ite ne
blxeq some_label @ Ok at the end of an IT block.
it 指令在 ARM 汇编语言中有效,尽管它不会生成任何代码。这是为了与 Thumb-2 汇编语言兼容,并允许大多数汇编语言序列同时为 ARM 和 Thumb-2 汇编。
正如 ARM 代码一样,可以通过添加适当的条件代码后缀,使简单的 Thumb b 指令变为条件指令。事实上,我的上一篇文章中提供的 if/else 示例可以像为 ARM 汇编一样为 Thumb 汇编。
Thumb 算法指令的 16 位形式通常设置条件标志。不过,在 it 块中时,16 位形式不设置这些标志。在与条件代码 al 组合时,这一属性很有用处。请思考以下代码序列:
@ Instruction Size
add r0, r0, #1 @ 4 bytes
add r1, r1, #1 @ 4 bytes
add r2, r2, #1 @ 4 bytes
add r3, r3, #1 @ 4 bytes
@ Total: 16 bytes
使用 it 块编写功能相当的代码序列可以使代码大小变小:
itttt al @ 2 bytes
addal r0, r0, #1 @ 2 bytes
addal r1, r1, #1 @ 2 bytes
addal r2, r2, #1 @ 2 bytes
addal r3, r3, #1 @ 2 bytes
@ Total: 10 bytes
应当注意,16 位形式具有其他限制,因此以上使用的 it 技巧可能并不总适用。限制可能因各个指令而异,但 16 位指令形式通常只能访问 r0-r7,并且直接常量的范围也有很大限制。如需详细信息,请参见《架构参考指南》。
因为(在 it 块之外)设置标志的大多数运算指令具有 16 位形式,设置标志可以大大改善代码大小,即便在不需要时。这可以尽可能提供最佳(最小)的代码尺寸。不过,根据您的目标处理器,此技巧可能对性能稍有负面影响。或许应建议在性能关键的代码中使用 al 条件技巧或 32 位指令。
您可以添加 .n 后缀,强制汇编程序生成 16 位指令。汇编程序在可以时会这么做,但如果您的指令无法使用 16 位形式进行编码,而您指定了 .n,汇编程序将显示错误消息。
[...] @ Not in an IT block.
adds.n r1, r2, r3 @ Generates a 16-bit instruction.
add.n r1, r2, r3 @ Error: No 16-bit form for this.
有关各个指令的详细信息,以及与 16 位形式限制相关的信息,请参见《架构参考指南》。有许多例外和特别情形,这里就不详细介绍了。
1
Thumb-2 可以在 ARMv6T2 架构及以上版本(包括 ARMv7-A)中使用。基于这些架构的处理器包括 ARM1156 和所有 Cortex 系列处理器,但不包括较旧的处理器或 ARM11 系列中的其他处理器。
本文短链接: http://bit.ly/duqhWT