GCC扩展asm区分文本与寄存器

GCC扩展asm区分文本与寄存器,gcc,embedded,inline-assembly,microchip,xc16,Gcc,Embedded,Inline Assembly,Microchip,Xc16,我发现自己广泛使用内联asm,并且经常希望能够在给定的asm位中使用寄存器或文本,但是我看不出如何在Microchip XC16套件中实现这一点 据我所知,您需要手动编码文字符号#,这与前缀不兼容。这意味着以下代码无法编译: asm("MOV %1, %0" : "=r" (res) : "i" (1)); Invalid operands specified ('mov 1,w0'). 但以下情况确实如此: asm("MOV #%1, %0" : "=r" (res) : "i" (1));

我发现自己广泛使用内联asm,并且经常希望能够在给定的asm位中使用寄存器或文本,但是我看不出如何在Microchip XC16套件中实现这一点

据我所知,您需要手动编码文字符号
#
,这与前缀不兼容。这意味着以下代码无法编译:

asm("MOV %1, %0" : "=r" (res) : "i" (1));
Invalid operands specified ('mov 1,w0').
但以下情况确实如此:

asm("MOV #%1, %0" : "=r" (res) : "i" (1));
这当然与寄存器不兼容:

asm("MOV #%1, %0" : "=r" (res) : "ri" (x));
Invalid operands specified ('mov #w0,w0').
因此,在我看来,微芯片并没有遵循GCC惯例,我认为文字符号应该嵌入到操作数中,这使得使用它特别困难

我在想这个不可能的机会。。有人对如何解决这个问题有什么好主意吗

现在,我把
\uu内置常量\u p
作为一个附加参数传递,然后我将
.if
在asm中按如下方式打开,但说它很快变得笨拙是轻描淡写的

asm(".if %[isk]  \n"
    "MOV #%1, %0 \n"
    ".elseif     \n"
    "MOV %1, %0  \n"
    ".endif      \n"
    : "=r" (res)
    : "ri" (x), [isk] "i" (__builtin_constant_p(x));
而且我甚至不相信GCC保证如果
isk
为真,那么
%1
将是一个文本,这意味着必须在C端阻止它。。。唉


阐明
MOV
只是一个示例指令。这些处理器(DSPIC33E)具有零开销的单指令循环和多指令循环,需要asm加以利用,其语法如下所示:

/* this code demonstrates compilation failure if cnt is a constant
 * as there is no # prefix before the %[cnt] */
asm("REPEAT %[cnt]        \n"
    "  MOV [%0++], [%1++] \n"
    : "+r" (src), "+r" (dst), "=m" (*dst)
    : "m" (*src), [cnt] "ri" (cnt));

这个memcpy循环需要
cnt+1
个周期来执行,这是因为管道实际上是完全展开循环的两倍,比每次迭代分支快6倍。除了它们的多指令DO循环变体之外,它们对于充分利用这些处理器非常重要。

我发现了一种在asm中检测给定参数是否为文本的方法,这远不理想,但似乎有效

首先,在asm头文件中,为每个寄存器标记一个符号:

.irp r,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  .set _IS_REG_w&r&, 1 ; mark all registers as "REGs"
  .set _IS_REG_W&r&, 1
.endr
然后使用:

.ifdecl _IS_REG_%0
  REPEAT %0
.else
  REPEAT #%0
.endif
可以包装在asm宏中:

.macro REPEATN cnt
    .ifdecl _IS_REG_&cnt&
        REPEAT \cnt
    .else
        REPEAT #\cnt
    .endif
.endm
为便于嵌入内联asm:

void DelayCycles(int count)
{
    asm("REPEATN %[cnt]    \n"
        "    NOP           \n"
        :
        : [cnt] "ri" (count));
}

你真正想解决的问题是什么?我确信您没有试图编写一条
MOV
语句。也许有一种方法可以完全避免
MOV
asm(“MOV%1,%0”:“=r”(res):“i”(1))应该编译,并在GCC中针对x86执行。这显然是编译器中的一个bug。不过,正如Florian所说,奇怪的是,您需要在内联汇编中编写
MOV
指令,或者在内联asm中编写大量代码。为什么你发现自己“广泛使用内联asm?”@CodyGray,x86是不同的,因为直接操作数不需要前缀。啊,我现在明白你的意思了。它看起来确实像是一个编译器错误/缺少功能。@CodyGray,我最初考虑的是
intel
语法。但是您是对的,GCC根据需要为
att
合成
$
。如果这个目标没有做到这一点,肯定看起来像一个编译器错误。看起来Microchip并没有向公众提供编译器的源代码,所以我无法快速查看它们来确认。