2012-05-09 56 views
0

我正在使用基于GNU的工具链编写内联汇编语句,并且内联汇编中有三条指令用于更新系统寄存器的单个位。的步骤将是:(GNU内联汇编)如何使用未从C语言赋值或复制到C变量的寄存器?

  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是REGI我想将OV_TMP的值转换为。

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

回答

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,所以编译器不能简单地删除书面,但是不被使用的寄存器。

mfsrmtsr看起来像powerpc指令给我,我可能会在C代码中执行and步骤(请参阅脚注);但下面应该一般工作:

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组件的点点),没有必要保持 mfsrmtsr指令离开特定距离,不像某些锁步其他处理器上的序列。如果是这样,我会写更类似这样的东西:

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 */