0

我正在使用基于 GNU 的工具链编写内联汇编语句,并且内联汇编中有三个指令来更新系统寄存器的单个位。步骤将是:

  1. 将系统寄存器移动(读取)到通用寄存器
  2. 'AND' 它与 C 代码中的变量值
  3. 移动(写)回刚刚读取的系统寄存器

在我使用的指令集中,内联汇编语法是这样的:

unsigned int OV_TMP = 0xffefffff;
asm volatile ( "mfsr %0, $PSW\n\t"
               "and %0, %0, %1\n\t"
               "mtsr %0, $PSW"
               :  : "r"(OV_TMP) : );

%1 是我要将 OV_TMP 的值转发到的寄存器。

%0 对我来说是个问题,我的问题是: 一旦有内部使用的寄存器并且没有从 C 代码中的 C 变量分配或复制到 C 变量,如何编写内联汇编代码?

4

1 回答 1

1

这里要考虑的是,从编译器的角度来看,寄存器由内联汇编分配给的,即使您以后不再使用它。也就是说,您正在生成相当于:

register unsigned int OV_TMP = 0xffefffff, scratch;

scratch = magic() & OV_TMP;
more_magic(scratch);
/* and then don't re-use scratch for anything from here on */

由于 ,魔术和/或 more_magic 步骤无法移动或组合volatile,因此编译器不能简单地删除已写入但未使用的寄存器。

mfsrand看起来像 powerpc 指令,mtsr我可能会and在 C 代码中执行该步骤(见脚注);但以下通常应该有效:

unsigned int OV_TMP = 0xffefffff, scratch;
asm volatile("mfsr %0, $PSW\n\t"
             "and %0, %0, %1\n\t"
             "mtsr %0, $PSW"
             : "=&r"(scratch) : "r"(OV_TMP));

这里的“=&r”约束表示输出操作数 ( %0) 在输入操作数 ( %1) 被读取之前写入。


脚注:据我所知(这不是很远,我只做过一点点 ppc 组装)与其他处理器上的某些锁步序列不同,不需要将mfsrandmtsr指令保持特定距离。如果是这样,我会写一些更像这样的东西:

static inline unsigned int read_psw() {
    unsigned int result;
    asm volatile("mfsr %0, $PSW" : "=r"(result));
    return result;
}
static inline void write_psw(unsigned int value) {
    asm volatile("mtsr %0, $PSW" :: "r"(value));
}
#define PSW_FE0 0x00100000 /* this looks like it's FE0 anyway */
...
    write_psw(read_psw() & ~PSW_FE0); /* some appropriate comment here */
于 2012-05-09T09:22:29.367 回答