c++ - 为 arm mov 获取有效 imm num 的快速方法?

标签 c++ c assembly arm immediate-operand

Arm mov 有一个限制,即立即数必须是 8 位旋转 2 的倍数,我们可以这样写:

mov ip, #0x5000

但是我们不能这样写:

mov ip, #0x5001

0x5000 可以拆分为 0x5000 + 1,我的意思是,一个有效的立即数和一个小数的和。

那么对于给定的 32 位数字,如何快速找到最接近的有效立即数呢?像这样:

uint32 find_imm(uint32 src, bool less_than_src) {
...
}

// x is 0x5000
uint32 x = find_imm(0x5001, true);

最佳答案

其实很简单,看他们之间的距离。 0x5001 = 0b101000000000001。 15 位有效数字,因此它会以 8 位立即数为您提供两条指令。还要记住在测试中进行旋转,如果有足够的零 0x80000001 并且你将它旋转到 0x88000000 或 0x00000003 周围,这与测量值之间的距离只有两位有效数字。因此,采取立即行动,执行类型测试之间的距离,旋转一步,再次执行测试,然后重复直到发生所有可能的(反向)旋转,并使用指令数量最少的一个/立即数。

gnu 已经这样做了,gas 是开源的,所以如果你愿意,你可以去获取他们的代码。当您使用加载地址技巧时:

ldr rd,=const

如果该 const 可以在单个移动立即指令中解析,则它将其编码为

mov rd,#const

如果它不能,那么它会尝试找到一个放置单词的位置并将其编码为 pc 相对负载:

ldr rd,[pc,#offset]
...
.word const

关于c++ - 为 arm mov 获取有效 imm num 的快速方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17760944/

相关文章:

c - 如何在c中对字符和数字进行排序?

c - 在 C 中相互定义结构体

c++ - 中断来自并行线程的阻塞调用

linux - 在汇编中调用printf时如何设置颜色

C++ 转换为基数和 "overwriting"vptr 问题

c++ - 如何在没有安装 CUDA 工具包的机器上运行编译后的 CUDA 代码?

macos - Mac 上的汇编编程

c - C结构如何传递给汇编函数?

c++ - 读取此文件行的最短方法?

c++ 类是从特定类派生的吗?