GCC内联汇编常量(ARM)

时间:2015-06-03 00:27:01

标签: c gcc inline-assembly

是否有一种很好的方法可以将常量内联汇编代码作为"参数"? 我试图建立一个协处理器访问功能。 我尝试了两种方法:宏替换和扩展。

用法是这样的:

unsigned int read_ID_PFR1()
{
    READ_CP15(0, 0, 1, 1);
    return cp_reg_val;
}

宏观方法:

#define READ_CP15(opc, crn, crm, opc2) \
asm volatile (\
    "push {r0, r1}\n\t"\
    "mrc p15, opc, r0, crn, crm, opc2\n\t"\
    "ldr r1, =cp_reg_val\n\t"\
    "str r0, [r1]\n\t"\
    "pop {r0, r1}\n\t"\
    )

我认为参数(opc,crn,...)没有扩展,因为它们是 在引号内使用。

扩展方法如下所示:

#define WRITE_CP15(opc, crn, crm, opc2) \
    asm volatile (\
        "push {r0, r1}\n\t"\
        "ldr r1, =cp_reg_val\n\t"\
        "ldr r0, [r1]\n\t"\
        "mcr p15, %[op], r0, c%[rn], c%[rm], %[op2]\n\t"\
        "pop {r0, r1}\n\t"\
        ::[op]"I"(opc), [rn]"I"(crn), [rm]"I"(crm), [op2]"I"(opc2):\
    )

除了'#' -marks之外,这似乎做得更好。 (c%[rn]扩展为c#0)

3 个答案:

答案 0 :(得分:0)

不要将push / pop放在内联asm中。这不仅意味着你在asm中写下了比你应该更多的垃圾;它还排除了使用"m"类型输入/输出约束,因为有效地址可能是堆栈指针相对的。而是使用类似的东西:

asm volatile ("mrc p15, opc, %0, crn, crm, opc2" : "=r"(cp_reg_val));

答案 1 :(得分:0)

清理了一下:

#define READ_CP15(retvar, opc, crn, crm, opc2) \
    asm volatile (\
        "mrc p15, %c[op], %[reg], c%c[rn], c%c[rm], %c[op2]\n\t"\
        :[reg] "=r" (retvar)\
        :[op]"I"(opc), [rn]"I"(crn), [rm]"I"(crm), [op2]"I"(opc2):\
    )

那些opc,crn,crm和opc2需要在那里。它们是常数。 输出程序集是:

@ 252 "../instr_comm.c" 1
    mrc p15, 0, r0, c0, c1, 1

答案 2 :(得分:-1)

McMurphy再次中风。我花了几个小时搞清楚,但是现在我发了一个问题,我发现'%'和'[name]'之间的'c'就是这样做了 - 丢掉了'#'。

这有效:

#define READ_CP15(opc, crn, crm, opc2) \
    asm volatile (\
        "push {r0, r1}\n\t"\
        "mrc p15, %c[op], r0, c%c[rn], c%c[rm], %c[op2]\n\t"\
        "ldr r1, =cp_reg_val\n\t"\
        "str r0, [r1]\n\t"\
        "pop {r0, r1}\n\t"\
        ::[op]"I"(opc), [rn]"I"(crn), [rm]"I"(crm), [op2]"I"(opc2):\
    )

从(临时).s文件中检查。