我正在尝试用asm-implementations替换某些方法。目标是iOS(iPhone 5S或更高版本)上的arm64。我要使用专用的汇编器文件,因为内联汇编器会带来额外的开销,而且是cumbersome to use with A64 memory offsets。
互联网上没有太多的文档,因此我不确定该怎么做。因此,我将描述将函数移至ASM所遵循的过程。
此问题的候选函数是256位整数比较函数。
UInt256.h
@import Foundation;
typedef struct {
uint64_t value[4];
} UInt256;
bool eq256(const UInt256 *lhs, const UInt256 *rhs);
Bridging-Header.h
#import "UInt256.h"
Reference implementation (Swift)
let result = x.value.0 == y.value.0
&& x.value.1 == y.value.1
&& x.value.2 == y.value.2
&& x.value.3 == y.value.3
UInt256.s
.globl _eq256
.align 2
_eq256:
ldp x9, x10, [x0]
ldp x11, x12, [x1]
cmp x9, x11
ccmp x10, x12, 0, eq
ldp x9, x10, [x0, 16]
ldp x11, x12, [x1, 16]
ccmp x9, x11, 0, eq
ccmp x10, x12, 0, eq
cset x0, eq
ret
我找到了的资源
问题
我已经使用XCTest测试了代码,创建了两个随机数,在它们上运行了Swift和Asm实现,并验证了两者报告的结果相同。该代码似乎是正确的。
.align
似乎是为了优化-这真的必要吗?如果是,则要对齐的正确值是什么? 一种。我怎么知道输入实际上是通过
x0
和x1
传递的?b。我怎么知道在
x0
中传递输出是正确的?C。我怎么知道掩盖
x9
-x12
和状态寄存器是安全的?d。当我从C而不是Swift调用函数时,是否以相同的方式调用该函数?
r8
寄存器的描述是什么意思? .globl
之外,我还需要其他任何汇编程序指令吗? 最佳答案
.align 2
伪指令是程序正确性所必需的。 A64指令需要在32位边界上对齐。 lhs
和rhs
寄存器存储在X0
和X1
中。由于参数都是指针,因此唯一适用的特定规则是C.7。 我应该说使用内联汇编编写代码的一个优点是,您不必担心任何这些。像下面未经测试的C代码这样的东西应该不会太笨拙:
bool eq256(const UInt256 *lhs, const UInt256 *rhs) {
const __int128 *lv = (__int128 const *) lhs->value;
const __int128 *rv = (__int128 const *) rhs->value;
uint64_t l1, l2, r1, r2, ret;
asm("ldp %1, %2, %5\n\t"
"ldp %3, %4, %6\n\t"
"cmp %1, %3\n\t"
"ccmp %2, %4, 0, eq\n\t"
"ldp %1, %2, %7\n\t"
"ldp %3, %4, %8\r\n"
"ccmp %1, %3, 0, eq\n\t"
"ccmp %2, %4, 0, eq\n\t"
"cset %0, eq\n\t",
: "=r" (ret), "=r" (l1), "=r" (l2), "=r" (r1), "=r" (r2)
: "Ump" (lv[0]), "Ump" (rv[0]), "Ump" (lv[1]), "Ump" (rv[1])
: "cc")
return ret;
}
好吧,也许有点笨拙。
关于ios - 64位iOS(A64)上的汇编器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30947422/