2012-05-09 92 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 */