[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.32.1 i386 浮動小数点 asm オペランド

スタック状のレジスタを asm のオペランドで使うには幾つか規則がある。 これらの規則は、スタック状レジスタであるオペランドにのみ適用される。

  1. asm_operands 中で死ぬ入力レジスタの組が与えられた場合、 どれが asm 文により暗黙にポップされて、どれが GCC で明示的に ポップしなければならないかを知る必要がある。

    asm 文により暗黙にポップされる入力kレジスタは、出力オペランドに マッチするように制約が課されていない限り、明示的に破壊しなければ ならない。

  2. asm 文により暗黙にポップされる任意の入力レジスタについて、 ポップした分を補償するためにスタックをどうやって調整するかを 知る必要がある。ポップされない入力レジスタのどれかが、暗黙に ポップされるレジスタよりもレジスタスタックの最上位に近い場合、 スタックがどのように見えるかを知るのは可能ではないだろう。 スタックの残りの部分がどのように「上下」するのか明らかでないのである。

    暗黙にポップされる入力レジスタは全て、暗黙にポップされないどの入力 レジスタよりもレジスタスタックの最上に近くなければならないのである。

    ある入力が insn の中で死ぬのであれば、再ロードでその入力レジスタを 出力再ロード用に使っても良い。次の例を考えてみよう。

     
    asm ("foo" : "=t" (a) : "f" (b));
    

    この asm 文は、入力 B が asm によりポップされないこと、asm が結果を レジスタ・スタックにプッシュする、すなわち、スタックが前より一段 深くなるということを言っている。しかし、入力 B がこの insn で 死ぬのであれば、再ロードは、入力と出力に同じレジスタを使うことが 出来ると考えるだろう。

    入力オペランドのどれかが制約 f を使っていれば、 全ての出力レジスタの制約は早期破壊 & を使用しなければならない。

    上の asm は以下のように書ける。

     
    asm ("foo" : "=&t" (a) : "f" (b));
    
  3. オペランドの幾つかは、スタック上の特定の位置にある必要がある。 出力オペランドは全てこのカテゴリに入る。ユーザが制約で指示しない限り、 どのレジスタに出力が現れるか知る方法がないのである。

    出力オペランドは、asm の後で出力がどのレジスタに現れるかを はっきりと指示しなければならない。=f は許されない。 このオペランド制約は一個のレジスタからなるクラスを選択しなければならない。

  4. 出力オペランドは、存在するスタックレジスタの間に「挿入」してはいけない。 387 のオペコードで読み書きオペランドを使っているものはないので、 全ての出力オペランドは asm_operands の前で死んでおり、 asm_operands によりプッシュされる。 レジスタスタックの一番上以外の場所にプッシュするのは意味がない。

    出力オペランドはレジスタスタックの一番上から始まっていなければ ならない。出力オペランドはレジスタを「スキップ」してはいけない。

  5. asm 文の中には、内部的な計算のためにスタックスペースを余分に必要とする ものがある。これは、入力と出力に関係のないスタックレジスタを 破壊することにより保証することができる。

以下に、書くのが妥当と思われる asm 文を2,3示す。 次の asm 文は入力を一つ取り、この入力は内部的にポップされる。 そして、出力を二つ生成する。

 
asm ("fsincos" : "=t" (cos), "=u" (sin) : "0" (inp));

次の asm 文は、二つの入力を取る。これらは、オペコード fyl2xp1 に よりポップされ、一つの出力に置き換えられる。 ユーザは、reg-stack.c が fyl2xpl が両方の入力をポップするという ことが判るように破壊指定 st(1) を書かなければならない。

 
asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)");

This document was generated using texi2html 1.78.