我正在尝试使用内联汇编创建一个
这是一个简单的示例:
但这样会削弱很多灵活性,可能会使生成的代码不够优化。
gcc(4.8)是否支持
编辑:
由于建议使用“更高级”的构造...我想要解决的问题是将32位字的20位打包(例如,输入为8个字,输出为5个字)。伪代码如下:
ldm
(或stm
)指令,但在表达操作数时遇到了问题(特别是它们的顺序)。这是一个简单的示例:
void *ptr;
unsigned int a;
unsigned int b;
__asm__("ldm %0!,{%1,%2}" : "+&r"(ptr), "=r"(a), "=r"(b));
代码无法正常工作,因为它可能会将a
放入r1
,而将b
放入r0
:
ldm ip!, {r1, r0}
ldm
要求寄存器按升序排列 (因为它们在位域中编码),所以我需要一种方法来表明用于 a
的寄存器低于 b
的寄存器。
一种简单的方法是固定分配寄存器:
register unsigned int a asm("r0");
register unsigned int b asm("r1");
__asm__("ldm %0!,{%1,%2}" : "+&r"(ptr), "=r"(a), "=r"(b));
但这样会削弱很多灵活性,可能会使生成的代码不够优化。
gcc(4.8)是否支持
ldm/stm
的特殊约束条件?或者,是否有更好的解决方法(例如某些__builtin
函数)?编辑:
由于建议使用“更高级”的构造...我想要解决的问题是将32位字的20位打包(例如,输入为8个字,输出为5个字)。伪代码如下:
asm("ldm %[in]!,{ %[a],%[b],%[c],%[d] }" ...)
asm("ldm %[in]!,{ %[e],%[f],%[g],%[h] }" ...) /* splitting of ldm generates better code;
gcc gets out of registers else */
/* do some arithmetic on a - h */
asm volatile("stm %[out]!,{ %[a],%[b],%[c],%[d],%[e] }" ...)
这里速度很重要,ldm
比 ldr
快50%。由于算法比较棘手,而且 gcc
生成的代码比我好得多 ;) 我想用内联汇编来解决问题,并提供一些关于优化内存访问的提示。