【问题标题】:Fast way to get a valid imm num for arm mov?为 arm mov 获取有效 imm num 的快速方法?
【发布时间】:2013-07-19 14:47:02
【问题描述】:

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

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);

【问题讨论】:

  • 那么,你到底在问什么?似乎是一个相当简单的案例,“检查低位中是否有任何东西[可以很容易地添加回来],使用 AND 将其屏蔽掉,看看其余的是否可以向下移动到一个小数字”。跨度>
  • 我的问题是:我想把0x5001移到ip,但是写不出来:mov ip,#0x5001;但我可以写:mov r4, #1; add ip, r4, #0x5000;所以我想找一个算术可以从0x5001得到0x5000。而且我不想写 arm 伪指令......
  • 我了解您将 #5001 加载为“5
  • 将 0x5001 拆分为 0x5000+1 很简单,但是如何拆分 any 32 位数字?
  • 好吧,大概“any”不起作用,因为例如 0x47111723 不能通过移位来实现。但是我上面描述的方法,“屏蔽低部分并移位”适用于 0x4200012 和 0x13ff(假设值是 8 位,移位和另外 8 位)

标签: c++ c assembly arm immediate-operand


【解决方案1】:

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

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

ldr rd,=const

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

mov rd,#const

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

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

【讨论】:

  • 此外,gnu 汇编器 也采用mvn 形式。如果有一条指令,则使用它,如果没有,则使用ldr rd,[pc,#offset]。这比不使用 ALU 单元的多重计算要快。只有 加载单元 忙于获取常量,并且常量与 ARM 指令的大小相同。
  • 是的,你还必须对所有候选人做一个赞美,看看这是否适合 mvn...
【解决方案2】:

没有一个直接的规则或函数来寻找构造值的方法。一旦一个值超过了可以从立即值轻松加载的值,您通常通过在数据部分中定义它并从内存中加载它来加载它,而不是从立即值构造它。

如果您确实想从两个立即数构造一个值,则必须考虑各种操作,包括:

  • 添加两个立即数。
  • 减去两个立即数。
  • 两个立即数相乘。
  • 更深奥的指令,例如一些将 32 位寄存器分成多个通道的“SIMD”指令。

如果你必须去三个立即数,还有更多的组合。人们可以在减少搜索的可能性中找到一些模式,但其中一部分仍然是“蛮力”搜索。一般来说,使用复杂的指令序列是没有意义的,因为您可以简单地从内存中准备好的位置加载数据。

ARM 汇编器有an instruction form to assist this:

LDR Rd, =const

当汇编器看到这一点时,它会将const 值放入文字池中并生成一条指令以从池中加载该值。如果你使用不同的汇编器,它可能没有相同的指令形式,但你可以手动编写必要的代码。

【讨论】:

  • 谢谢。 arm asm 比 x86 更让我头疼
猜你喜欢
  • 1970-01-01
  • 2016-05-29
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
  • 1970-01-01
  • 2013-12-05
  • 2021-08-22
  • 1970-01-01
相关资源
最近更新 更多