(GNU内联汇编)如何使用既不从C变量赋值也不复制到C变量的寄存器?

(GNU内联汇编)如何使用既不从C变量赋值也不复制到C变量的寄存器?,c,gnu,inline-assembly,C,Gnu,Inline Assembly,我正在使用基于GNU的工具链编写内联汇编语句,内联汇编中有三条指令用于更新系统寄存器的单个位。这些步骤将是: 将系统寄存器移(读)到通用寄存器 '和'使用C代码中的变量值 将(写入)移回刚刚读取的系统寄存器 在我使用的指令集中,内联汇编语法如下: unsigned int OV_TMP = 0xffefffff; asm volatile ( "mfsr %0, $PSW\n\t" "and %0, %0, %1\n\t" "mtsr

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

  • 将系统寄存器移(读)到通用寄存器
  • '和'使用C代码中的变量值
  • 将(写入)移回刚刚读取的系统寄存器
  • 在我使用的指令集中,内联汇编语法如下:

    unsigned int OV_TMP = 0xffefffff;
    asm volatile ( "mfsr %0, $PSW\n\t"
                   "and %0, %0, %1\n\t"
                   "mtsr %0, $PSW"
                   :  : "r"(OV_TMP) : );
    
    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 */
    
    %1是我要将OV_TMP的值转发到的寄存器

    %0是我的问题,我的问题是:
    <强>如何在内嵌使用登记器时登记内联汇编代码,而不是在C代码中分配给C变量,也不是复制到C变量。>/P>> P>这里要考虑的是,从编译器的角度来看,寄存器是由内联程序集分配的,即使以后不再使用它。也就是说,您正在生成以下等价物:

    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 */
    
    由于
    易失性
    ,无法移动或组合魔术和/或更多魔术步骤,因此编译器不能简单地删除已写入但未使用的寄存器

    对我来说,
    mfsr
    mtsr
    看起来像powerpc指令,我可能会在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”约束表示在读取输入操作数(
    %1
    )之前写入输出操作数(
    %0
    )。
    脚注:据我所知(这并不遥远,我只做过一点点ppc组装),与其他处理器上的某些锁步序列不同,mfsr和mtsr指令不需要保持特定的距离。如果是这样的话,我会写一些更像这样的东西:

    unsigned int OV_TMP = 0xffefffff;
    asm volatile ( "mfsr %0, $PSW\n\t"
                   "and %0, %0, %1\n\t"
                   "mtsr %0, $PSW"
                   :  : "r"(OV_TMP) : );
    
    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 */