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

17.11 アドレッシングモード

この節では、アドレッシングモードについて説明する。

HAVE_POST_INCREMENT

マシンがポストインクリメントのアドレッシングをサポートしている 場合は、ゼロでない値を取る C の式である。

HAVE_PRE_INCREMENT
HAVE_POST_DECREMENT
HAVE_PRE_DECREMENT

HAVE_POST_INCREMENT に同様である。

CONSTANT_ADDRESS_P (x)

RTX x がアドレスとして有効な定数であれば、1 となる C の式を 定義する。多くのマシンでは、CONSTANT_P (x) として 定義すれば良いが、幾つかのマシンではアドレスとして使える定数に 制限がある。

CONSTANT_P は、明示的には未知である値を持つ、整数値の式を 受け付ける。そのような式としては、例えば、 symbol_reflabel_refhigh といった式、 const 算術式、const_intconst_double 式 がある。

MAX_REGS_PER_ADDRESS

有効なメモリアドレスに現れることができるレジスタ数の最大値を表す数である。 GO_IF_LEGITIMATE_ADDRESS が受け付ける最大数に等しい値を 指定するかどうかは読者の責任であることに注意。

GO_IF_LEGITIMATE_ADDRESS (mode, x, label)

条件付きの goto label; を含む一個の C の複文。 この goto は、x(ある RTX) がターゲット機種で、モード mode のメモリオペランドとして正しいメモリアドレスである場合に実行される。

普通は、幾つかの単純なマクロを定義して、このマクロのサブルーチンと する。そうしないと、大変複雑になりがちで理解するのが難しくなるからである。

このマクロは二種類なければならない。厳密な版と厳密でない版である。 厳密な版は再ロード・パスで使われる。これは、ハードレジスタが割り当て られていない疑似レジスタはすべてメモリ参照であると考えられるように 定義しなければならない。なにかの種類のレジスタを必要とする文脈では、 ハードレジスタが割り当てられていない疑似レジスタは拒絶しなければ ならない。

厳密でない版は他のパスで使われる。こちらは、なにかの種類のレジスタが 必要とされる、あらゆる文脈で全ての疑似レジスタを受け付けるように 定義しなければならない。

GNU CC のソースファイルで、このマクロの厳密版を使いたいところでは、 マクロを REG_OK_STRICT を定義する。 条件文 #ifdef REG_OK_STRICT を使って、厳密版を使いたいところでは 厳密版を定義し、それ以外のところでは厳密でない版を定義するべきである。

色々な目的(ベースレジスタ向けや、インデックスレジスタ向けなど)に 受付可能なレジスタを検査するサブルーチン群は、普通は GO_IF_LEGITIMAITE_ADDRESS を定義するのに使われるサブルーチン群の 中にある。これらのサブルーチンマクロだけが二つの変種を必要とする。 高レベルのマクロは厳密であってもなくても同じで良い。

通常、symbol_ref と整数の和である定数アドレスは、 const RTX の内側に格納され、定数であるという印が付けられる。 このため、このような和を正当なアドレスとして特別に認識する必要はない。 普通は、単に const は全て正当であるとして認識すれば良い。

通常、PRINT_OPERAND_ADDRESS は、const が付いていない 定数和を扱う準備はしていない。単体の plus があると、 インデックスすることを想定している。 もしそうなら、そのような単体の定数和は不正なアドレスとして拒絶 して、PRINT_OPERAND_ADDRESS に渡らないようにしなければならない。

機種によっては、シンボリックなアドレスが正当かどうかは そのアドレスが参照しているセクションに依存する。 そういう機種では、マクロ ENCODE_SECTION_INFO を定義して、 その情報を symbol_ref に格納し、そこで検査を行なうようにする。 const があった場合は、その中を見て symbol_ref を 探し、セクションを決定する必要がある。 See section 出力アセンブリ言語の定義

名前の文字列を修正する最善の方法は、文字列の前にテキストを追加し、 さらに適当な区切り文字を付けて、曖昧さをなくすことである。 ASM_OUTPUT_LABELREF を修正して、追加テキストを消去してデコードし、 かつ、その名前を適切に出力し、さらに STRIP_NAME_ENCODING を 定義して、元の名前の文字列を参照するようにする必要がある。

ここで symbol_ref に貯えた情報を、マクロ GO_IF_LEGITIMATE_ADDRESSPRINT_OPERAND_ADDRESS の 定義の中で検査することができる。

REG_OK_FOR_BASE_P (x)

一個の C の式。この式は、x (reg RTX と仮定される) がベースレジスタとして使うのに適していれば、ゼロでない値となる。 ハードレジスタの場合には、常に、ハードウェアが許すものは受け付けて、 それ以外は拒絶すべきである。 このマクロが疑似レジスタを受け付けるか拒絶するかは、上記の REG_OK_STRICT により制御されなければならない。 普通、これには二種類の定義が必要になる。REG_OK_STRICT が 実際に使われるものを選ぶ。

REG_MODE_OK_FOR_BASE_P (x, mode)

一個の C の式。REG_OK_FOR_BASE_P にほとんど同じであるが、 その式が mode のメモリ参照のモードを調べるという点が異なる。 そのメモリ参照のモードが、あるレジスタがベースレジスタとして使えるかどうか に影響するなら、このマクロを定義すべきである。 このマクロを定義すると、GNU CC は REG_OK_FOR_BASE_P の代わりに こちらを使う。

REG_OK_FOR_INDEX_P (x)

一個の C の式で、その値は、x (reg RTX と仮定される)が インデックスレジスタとして使うのが有効なら、ゼロでない値となる。

インデックスレジスタとベースレジスタの違いは、インデックスレジスタは スケーリングされることである。 あるアドレスが二つのレジスタの和を含んでいて、そのどちらもスケーリング されないのであれば、どちらか一つが「ベース」となり、他方は「インデックス」 というラベルが貼られる。だが、どちらのラベル付が使われても、レジスタが それぞれの役割を果たす、その機種の制約に収まらなければならない。 コンパイラは両方のラベル付を試して、有効なものを一つ見つけ出し、 どちらのラベル付も動作しない場合にのみ、一方のレジスタ、あるいは両方の レジスタを再ロードする。

LEGITIMIZE_ADDRESS (x, oldx, mode, win)

一個の C の複文。この文は、x をモード mode のオペランドの 有効なメモリアドレスで置き換えることを試みる。win は、 コード中のどこか別のところにある 一個の C のラベルである。 このマクロ定義は、

 
GO_IF_LEGITIMATE_ADDRESS (mode, x, win);

を使って、アドレスが正当なものになっている場合には、それ以上の 処理を避ける。

x は、常に break_out_memory_refs の呼び出しの結果であり、 oldx は、その関数に与えられて x を生成したオペランドである。

このマクロにより生成されたコードは x の下位構造を変えてはならない。 このコードがx をより正しい形に変換するなら、 x(これは常に、ある C の変数になる)に新しい値を割り当てるべきである。

このマクロが正しいアドレスを提示する必要はない。 コンパイラには全ての場合に正しいアドレスにする標準的な方法がいくつかある。 だが、機種依存の戦略を取ると生成されるコードが良くなることも多い。

LEGITIMIZE_RELOAD_ADDRESS (x, mode, opnum, type, ind_levels, win)

C の複文。この複文は、再ロードを必要とするアドレスである x を、 モード mode のオペランドに対する有効なメモリ参照で 置き換えることを試みる。win はコードのどこか別の場所にある、 C の文ラベルになる。このマクロを定義するのは必須ではないが、 実行速度の点から有用である。

例えば、i386 では、二つの疑似レジスタの和を一個のレジスタに再ロード することにより、二つの再ロードレジスタの代わりに一つの再ロードレジスタを 使用することが可能なことがときどきある。一方、多くの RISC プロセッサ のオフセットは限られているので、スタックスロットをアドレスために 中間のアドレスを生成する必要があることが多い。 LEGITIMIZE_RELOAD_ADDRESS を適切に定義すると、近くにまとまっている 幾つかのスタックスロット用に生成される中間アドレスを同じものにする 事ができるので、共有が可能にある。

注意。このマクロを使うには注意が必要である。これを効率良く 使うためには再ロードの仕組みをいくらか知っている必要がある。 そして、再ロードの内部についての知識をたくさん詰め込んだマクロを 生成するのはきわめて簡単である。

注意。このマクロは、前回のこのマクロの呼出しにより作られた アドレスを再ロードできなければならない。そういうアドレスの取扱いに 失敗すると、GCC は正しくないコードを生成したり、異常終了したりする。

このマクロの定義では、push_reload を使って、 再ロードが必要な部分を示す必要がある。numtypeind_ldevels は普通は変更無しで push_reload に渡すのに 適している。

このマクロが生成したコードは、x の下位構造を変更してはならない。 これが x をさらに正統な形に変換するなら、x (これは 常に C の変数である)に新しい値を割り当てる必要がある。 これは、push_reload を呼び出すことで間接的に変更した部分にも 適用される。

このマクロは、strict_memory_address_p を使って、 アドレスが正統になるかどうかを検査しても良い。

x の一部だけ変更したいときの標準的な方法の一つは、copy_rtx を 使うことである。ただし、共有しないのは RTL の一つのレベルだけである。 つまり、変更される部分がトップのレベルにないときは、まずトップレベルを 置き換える必要がある。このマクロが正統なアドレスを出す必要はない。 だが、機種依存の戦略がより良いコードを生成可能な事が多い。

GO_IF_MODE_DEPENDENT_ADDRESS (addr, label)

一個の C の文か複文であり、条件付きの goto label; を 含む。この goto は、メモリアドレス x (一個の RTX)が それに使われるメモリ参照のマシンモードによって意味が違ったり、 そのアドレスがあるモードでは有効だがその他のモードでは有効ではないという 場合に実行される。

自動インクリメントと自動デクリメントのアドレスには、普通モードに 依存した効果がある。なぜなら、インクリメントとデクリメントの量は 対象のオペランドの大きさだからである。機種によっては、その他に モード依存のアドレスを持つものもある。 多くの RISC 機種にはモード依存のアドレスがない。

addr がその機種の有効なアドレスであると仮定して良い。

LEGITIMATE_CONSTANT_P (x)

一個の C の式。この式は、x がターゲット機種の即値オペランドとして 正しい定数ならゼロでない値となる。xCONSTANT_P を 満たすと仮定して良いので、その検査は必要ない。 実際、 CONSTANT_P が有効な機種では、‘1’ がこのマクロの 適切な定義になる。


This document was generated using texi2html 1.78.