ここで考慮すべきことは、コンパイラの観点からは、後で再度使用しなくても、インライン アセンブリによってレジスタが割り当てられるということです。つまり、次のものと同等のものを生成しています。
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 */
magic および/または more_magic ステップは、 のために移動または結合することがvolatile
できないため、コンパイラーは、書き込まれたが未使用のレジスターを単純に削除することはできません。
mfsr
とmtsr
は、私には powerpc 命令のように見えます。おそらく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 アセンブリをほんの少ししか行ったことがありません) 、他のプロセッサの特定のロックステップ シーケンスとは異なり、命令
mfsr
と
mtsr
命令を特定の距離に保つ必要はありません。もしそうなら、私は次のようにもっと書くでしょう:
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 */