获取arm mov的有效imm编号的快速方法
Fast way to get a valid imm num for arm mov?
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 as已经做到了这一点,gas是开源的,所以如果你愿意,你可以去获取他们的代码。当你使用加载地址技巧:
ldr rd,=const
如果该常量可以在单个移动立即指令中解析,则它将其编码为
mov rd,#const
如果它不能,那么它会试图找到一个放置单词的位置,并将其编码为pc相对负载:
ldr rd,[pc,#offset]
...
.word const
没有一个简单的规则或函数来寻找构造值的方法。一旦一个值超过了可以从立即值轻松加载的值,通常通过在数据段中定义它并从内存加载它来加载它,而不是从立即值构建它。
如果您确实想从两个立即值构造一个值,则必须考虑各种操作,包括:
- 添加两个即时消息
- 减去两个直接数
- 两个直接数的乘积
- 更深奥的指令,例如一些将32位寄存器拆分为多个通道的"SIMD"指令
如果必须使用三个直接值,则会有更多的组合。人们可以在减少搜索的可能性中找到一些模式,但其中一部分仍然是"蛮力"搜索。一般来说,使用复杂的指令序列是没有意义的,因为您可以简单地从内存中准备好的位置加载数据。
ARM汇编程序有一个指令表来帮助实现这一点:
LDR Rd, =const
当汇编程序看到这一点时,它将const
值放在文字池中,并生成一条从池中加载该值的指令。如果您使用不同的汇编程序,它可能没有相同的指令形式,但您可以手动编写必要的代码。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 是否有任何方法可以将两个boost :: multipRecision :: cpp_int编号乘以
- 获取arm mov的有效imm编号的快速方法