0

GNU ベースのツールチェーンを使用してインライン アセンブリ ステートメントを作成しています。インライン アセンブリ内には、システム レジスタの 1 ビットを更新する 3 つの命令があります。手順は次のとおりです。

  1. システム レジスタを汎用レジスタに移動 (読み取り)
  2. Cコードの変数値と「AND」します
  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 */

magic および/または more_magic ステップは、 のために移動または結合することがvolatileできないため、コンパイラーは、書き込まれたが未使用のレジスターを単純に削除することはできません。

mfsrmtsrは、私には powerpc 命令のように見えます。おそらくandC コードでステップを実行するでしょう (脚注を参照)。しかし、以下は一般的に機能するはずです:

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 アセンブリをほんの少ししか行ったことがありません) 、他のプロセッサの特定のロックステップ シーケンスとは異なり、命令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 */
于 2012-05-09T09:22:29.367 に答える