わふぅ。

わふです。

PowerPC64 アセンブリ課題がつらい

なにこれ

大学の課題で PowerPC64 のアセンブリを書く必要があったけど浮動小数点数の扱いでつらい気持ちになったのでそのときの気持ちを書いた記事です。

適当に書いたので間違ってそう……。

レジスタ幅の確認

  • GPR (整数とか扱うやつ) → 64bit
  • FPR (浮動小数点数とか扱うやつ) → 64bit

GPR から FPR への転送

直接転送できなさそうなのでメモリを経由するしかなさそうです?

  • std rA, d(rM)
    • rA の値を d(rM) から d+7(rM) に書き込む
  • stw rA, d(rM)
    • rA の下位 32bit の値を d(rM) から d+3(rM) に書き込む
  • lfd fA, d(rM)
  • lfs fA, d(rM)
    • d(rM) から d+3(rM) を単精度浮動小数点数とみなして読み込む
    • 適当に倍精度に変換したあと fA に格納される

r3 の下位 32bit に単精度っぽいデータが入っているとして std r3, 0(r1) したあと lfs で読み込もうとするときは、バイトオーダーの関係で lfs f1, 0(r1) ではなく lfs f1, 4(r1) としないと壊れるので注意が必要です。まぁひっかかるひとはそんなにいなさそう……。

定数表現 (がんばるやつ)

FPR に適当な即値を突っ込みたいことがあります。このときも GPR に適当に即値を入れてからメモリ経由で渡すことで実現できます。直接突っ込む方法があるのかもしれないですが調べてないです。

そもそも命令長が 32bit 分しかないので即値として入れられるものは 16bit 幅のものだけです。シフト命令とかを使ってわいわいすることで倍精度 (64bit) とかそこらへんの定数を表現できます。

li %r3, 16384
sldi %r3, %r3, 48

とすると %r3 には倍精度浮動小数点数で 2.0 を表すデータが入るのであとは転送すれば良いです。

定数表現 (data セグメント使うやつ)

data セグメントで

.data
pi:
    .double 3.14

と書いておいてプログラム中で

lis %r4, pi@highest
ori %r4, %r4, pi@higher
sldi %r4, %r4, 32
oris %r4, %r4, pi@h
ori %r4, %r4, pi@l

とすることで %r4 に data セグメント中の pi の先頭アドレスが入るので lfd %f1, 0(%r4) で転送できるというテクニックもあるらしいです。

定数表現 (fcfid するやつ)

  • fcfid fA, fB
    • fB にある値を符号付き整数とみなして double に変換したあと fA に代入する

こういう強い命令があるらしいのであとは上で使っていたメモリ転送などを用いて適当な FPR にいい感じの値を入れておくだけでよさそうです。

参考文献

ふぇぇ

この記事で触れてない色々なことは kivantium プロの活動日記を見るとだいたいなんとかなります。