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

16.15.5 insn の長さの計算

多くの機種では、複数のタイプの分岐命令が提供されており、 それぞれ分岐の変位の長さが異なる。 大部分の場合は、アセンブラが正しい命令を選ぶ。 だが、アセンブラが不可能な場合は、特別な属性、‘length’ 属性が 定義されているときは GCC が行なうことができる。 この属性は、define_attr でヌル文字列を指定することで 数値を持つように定義しなければならない。

length’ 属性の場合は、さらに算術項の二つの形式があり、 テスト式で使うことができる。

(match_dup n)

これは、現在の insn のオペランド n のアドレスを参照している。 このアドレスは label_ref でなければならない。

(pc)

現在の insn のアドレスを参照する。 これを次の insn のアドレスとする使い方の方がより一貫性が 保てるのだろうが、そうすると現在の insn の長さを計算するときに 混乱する可能性がある。

通常の insn については、長さは ‘length’ 属性の値により 決まる。addr_vecaddr_diff_vec の insn パターンの 場合は、長さはベクトル数に各ベクトルの大きさを掛けたものとして 計算される。

長さは、アドレス可能な記憶域の単位(バイト)で測る。

以下のマクロを使って長さの計算を洗練されたものにすることができる。

FIRST_INSN_ADDRESS

insn の length 属性が使われているとき、このマクロは ある関数の先頭の insn のアドレスに代入されるべき値を指定する。 これが指定されていないと、0 が使われる。

ADJUST_INSN_LENGTH (insn, length)

定義されていると、命令 insn に、それが使われている文脈の 関数として割り当てられている長さを修正する。 length は左辺値であり、最初に計算した insn の長さが入っている。 これは、その insn の正しい長さに更新する必要がある。

このマクロは通常は必要とされない。 必要となる場合の一つは、ROMP である。 この機種では、addr_vec insn の大きさは、アラインメントが 必要とされるかも知れないという事実を補償するために、2 づつ増加しなければ ならない。

get_attr_length(length 属性の値)を返すルーチンを 出力ルーチンの中で使うと、以下の例が示すように、 書き出すべき分岐命令の形を決めることができる。

可変長分岐の指定の例として、IBM 360 を考える。 あるレジスタに、ある関数の開始アドレスが設定されるという規約を採用したと すると、その開始点から 4k バイト以内のラベルには一個の 4 バイト命令で ジャンプすることが出来る。それ以外の場合は、6バイトの命令列を使って、 メモリからアドレスをロードし、次にそのアドレスに分岐する必要がある。

こういう機種では、分岐命令のパターンは以下のような指定になる。

 
(define_insn "jump"
  [(set (pc)
        (label_ref (match_operand 0 "" "")))]
  ""
  "*
{
   return (get_attr_length (insn) == 4
           ? \"b %l0\" : \"l r15,=a(%l0); br r15\");
}"
  [(set (attr "length") (if_then_else (lt (match_dup 0) (const_int 4096))
                                      (const_int 4)
                                      (const_int 6)))])

This document was generated using texi2html 1.78.