またしても自分用備忘録。
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




テーブル
グローバルなテーブル! ランキング!