IA64用gasのディレクティブ
@gprel
gpレジスタと足すことにより、引数var変数へのアドレスが得られるようなオフセット値
addl r2 = @gprel(var), gp;; // r2にvar変数のアドレスを入れる
ld4 r3 = [r2] ;; // r3にvarをload
のように使う
しかし、IA64のadd命令で即値を取るものは
add r1 = imm_14, r3
add r1 = imm_22, r3
の二種類しかなく最大4M(±2M)
なので、このgp relative dataは小さいサイズのデータだけに
使う。という紳士協定をつくりデカいデータは以下のltoffを使う
@ltoff
引数big_var変数のアドレスが格納されたテーブルへのオフセットを得る
addl r2 = @ltoff(big_var), gp;; // r2にvar変数のアドレスが格納されたテーブルへのポインタを得る
ld8 r3 = [r2];; // r3にvarのアドレスをload
ld4 r8 = [r3];; // r8にvarをload
これはELF用語でいうところのGOT(global offset table)そのもの。
両方ともPIC(position independent code)に必要
イメージ図
high address
+---------------+
| |
| var | ←+
| | | @gprel
| | |
gp ⇒ | | -+
| | |
| | |
| | | @ltoff
+---------------+ |
| linkage table | |
+- | 0x47f8 | ←+
| | |
| +---------------+
| | |
| | |
0x47f8 +→ | big_var |
| |
+---------------+
low address
グローバルなテーブル! ランキング!