是否有一种很好的方法可以将常量内联汇编代码作为"参数"? 我试图建立一个协处理器访问功能。 我尝试了两种方法:宏替换和扩展。
用法是这样的:
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)
答案 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)
这有效:
#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文件中检查。