在iOS上使用NEON代码的奇怪结果,跳转到__ARCLite__load?

时间:2013-07-02 00:24:30

标签: iphone arm neon

我正在尝试编写一些NEON代码,以便在iPhone / iPad上最佳地填充字阵列。这个问题非常奇怪的是,当NEON指令为q3赋值时,代码似乎会跳转到名为_ ARCLite _load的函数中。有没有人见过这样的事情:

(使用xcode 4.6编译的test_time_asm.s和-no-integrated-as标志)

.section __TEXT,__text,regular
.section __TEXT,__textcoal_nt,coalesced
.section __TEXT,__const_coal,coalesced
.section __TEXT,__picsymbolstub4,symbol_stubs,none,16
.text   
.align 2
.globl _fill_neon_loop1
.private_extern _fill_neon_loop1
_fill_neon_loop1:
  push {r4, r5, r6, r7, lr}
  // r0 = wordPtr
  // r1 = inWord
  // r2 = numWordsToFill
  mov   r2, #1024
  // Load r1 (inWord) into NEON registers
  vdup.32 q0, r1
  vdup.32 q1, r1
  vdup.32 q2, r1
  vdup.32 q3, r1 (Stepping into this instruction jumps into __ARCLite__load)

NEONFILL16_loop1:
  vstm r0!, {d0-d7}
  sub r2, r2, #16
  cmp r2, #15
  bgt NEONFILL16_loop1

  mov   r0, #0
  pop {r4, r5, r6, r7, pc}
  .subsections_via_symbols

单步执行ASM指令直到分配给q3的指令为止。当我跳过那条指令时,代码似乎跳到了这里:

(gdb) bt
#0  0x0009a568 in __ARCLite__load () at /SourceCache/arclite_iOS/arclite-31/source/arclite.m:529
#1  0x0007b050 in test_time_run_cases () at test_time.h:147

这真的很奇怪,我真的很难理解为什么分配给NEON寄存器会导致这种情况。 NEON是否将q3用于我不知道的特殊事物?

我还尝试使用dN(64位regs)加载寄存器,并在分配给d7时得到相同的结果。

  vdup.32 d0, r1
  vdup.32 d1, r1
  vdup.32 d2, r1
  vdup.32 d3, r1
  vdup.32 d4, r1
  vdup.32 d5, r1
  vdup.32 d6, r1
  vdup.32 d7, r1

(稍后) 在搞清楚建议的更改之后,我找到了问题的根本原因。这是分支标签:

NEONFILL16_loop1:
  vstm r0!, {d0-d7}
  sub r2, r2, #16
  cmp r2, #15
  bgt NEONFILL16_loop1

由于某种原因,分支标签导致跳转到代码中的另一个位置。用以下内容替换上面的标签解决了问题:

1:
  vstm r0!, {d0-d7}
  sub r2, r2, #16
  cmp r2, #15
  bgt 1b

对于使用xcode 4.6提供的clang中的ASM解析器版本,这可能是一些奇怪的事情,但无论如何只需更改标签即可修复它。

2 个答案:

答案 0 :(得分:0)

q3既没有分配给某些特殊角色,也没有需要保留。别担心。

我认为auselen的猜测是正确的。只是看一下反汇编就会说清楚。

请尝试以下方法:

.section __TEXT,__text,regular
.section __TEXT,__textcoal_nt,coalesced
.section __TEXT,__const_coal,coalesced
.section __TEXT,__picsymbolstub4,symbol_stubs,none,16
.text   
.align 2
.globl _fill_neon_loop1
.private_extern _fill_neon_loop1
_fill_neon_loop1:
  // r0 = wordPtr
  // r1 = inWord
  // r2 = numWordsToFill
  mov   r2, #1024
  // Load r1 (inWord) into NEON registers
  vdup.32 q0, r1
  vdup.32 q1, r1
  vdup.32 q2, r1
  vdup.32 q3, r1
  subs r2, r2, #16
  bxmi lr

NEONFILL16_loop1:
  vstm r0!, {d0-d7}
  subs r2, r2, #16
  bpl NEONFILL16_loop1

  mov   r0, #0
  bx lr
  .subsections_via_symbols

除了循环中的cmp之外,我还删除了完全保留的过时寄存器。 (你知道,我必须优化一切:))

如果auselen的猜测是正确的,这可能会改变跟踪时间,并且稍后会进入ARClite。

答案 1 :(得分:0)

几乎每次我在手写的ARM代码中跳到某个奇怪的地方都是因为我弄错了拇指交互操作并且函数一直在错误模式下执行 - 因此指令流看起来像垃圾到CPU,并且它会随机跳跃,直到它自身受伤并摔倒。

对于作为函数入口点的所有标签,您应该具有此程序集指令:

.type _fill_neon_loop1, %function

这告诉链接器当它修复BL指令时,或者当它计算函数的地址时,它应该进行适当的调整以确保它以正确的模式执行。