如何在Xcode LLVM中编写关于LOOP的内联汇编代码?
我正在研究内联汇编。 我想在Xcode 4 LLVM 3.0 Compiler下编写一个简单的例程。 我成功地编写了基本的内联汇编代码。
例如:
int sub(int a, int b)
{
int c;
asm ("sub %0, %1, %2" : "=r" (c) : "r" (a), "r" (b));
return c;
}
我发现它在stackoverflow.com,它工作得很好。 但是,我不知道如何编写关于LOOP的代码。
我需要汇编代码
void brighten(unsigned char* src, unsigned char* dst, int numPixels, int intensity)
{
for(int i=0; i<numPixels; i++)
{
dst[i] = src[i] + intensity;
}
}
看看循环部分 - http://en.wikipedia.org/wiki/ARM_architecture
基本上你会想要像这样的东西:
void brighten(unsigned char* src, unsigned char* dst, int numPixels, int intensity) {
asm volatile (
"t mov r3, #0n"
"Lloop:n"
"t cmp r3, %2n"
"t bge Lendn"
"t ldrb r4, [%0, r3]n"
"t add r4, r4, %3n"
"t strb r4, [%1, r3]n"
"t add r3, r3, #1n"
"t b Lloopn"
"Lend:n"
: "=r"(src), "=r"(dst), "=r"(numPixels), "=r"(intensity)
: "0"(src), "1"(dst), "2"(numPixels), "3"(intensity)
: "cc", "r3", "r4");
}
更新:
这是NEON版本:
void brighten_neon(unsigned char* src, unsigned char* dst, int numPixels, int intensity) {
asm volatile (
"t mov r4, #0n"
"t vdup.8 d1, %3n"
"Lloop2:n"
"t cmp r4, %2n"
"t bge Lend2n"
"t vld1.8 d0, [%0]!n"
"t vqadd.s8 d0, d0, d1n"
"t vst1.8 d0, [%1]!n"
"t add r4, r4, #8n"
"t b Lloop2n"
"Lend2:n"
: "=r"(src), "=r"(dst), "=r"(numPixels), "=r"(intensity)
: "0"(src), "1"(dst), "2"(numPixels), "3"(intensity)
: "cc", "r4", "d1", "d0");
}
所以这个NEON版本一次只能做8个。 但它不检查numPixels
是否可以被8整除,所以你肯定会这样做,否则会出错! 无论如何,这只是向您展示可以做什么的开始。 注意相同数量的指令,但是一次对八个像素数据采取行动。 哦,那里也饱和了,我想你会想要。
虽然这个答案不是直接回答你的问题,但它更多地是关于使用汇编器与现代编译器的一般性建议。
你通常很难打败编译器的C代码优化。 当然,通过巧妙地使用关于数据如何表现的某些知识,您可能会调整它几个百分点。
其中一个原因是现代编译器在处理类似于你所描述的代码时使用了许多技术,例如循环展开,指令重新排序以避免流水线停顿和气泡等。
如果你真的想让这个算法尖叫,你应该考虑重新设计算法,而不是C,所以你避免了最坏的延迟。 例如,与寄存器访问相比,读取和写入内存相当昂贵。
完成此操作的一种方法可能是通过使用unsigned long
一次加载4个字节,然后在将这4个字节写回到一个存储操作之前,在寄存器中对此进行数学运算。
因此,回顾一下,让您的算法更聪明并不困难。
链接地址: http://www.djcxy.com/p/10249.html上一篇: how to write inline assembly codes about LOOP in Xcode LLVM?
下一篇: Session variables sending specific variable from a while loop