Tuesday, 23 November 2010

Intel64 の続き

コンパイラは、大体終りました。簡単かと思ったが、Intel64って、IA32よりは、はるかに、PowerPC に近いアーキテクチャになったのね。なので、PowerPC のコンパイラのコードを大分コピーした。

でも、実は、LP64 なコンパイラを書くのが初めてだったので、そのあたりのバグが多かったです。アドレスの配列なのに、.long とか出力しちゃったり。

Cって、printf みたいな、varargs があるのが面白いんだが、こいつのABIが、面白いくらいバラバラ。レジスタに引数を載せてるのは、まず、スタックに書き出さないと当然実装できない。

ところが、va_arg って、「次は int 取って来て」とか「次は、double ね」とか、そんな感じ。レジスタにlong int と double 載せて「次ってどれだろう?」。

書き込む時に、自分の領域ではなく、呼び出した側に書き込む仕様もある(PowerPC)。ってことは、呼出側で、その領域を確保しておく必要がある。これは、間違えると、printf の中で落ちて、まったく原因がわからない。でも、そうすると、save した register の分と stack につまれば引数の分が連続するので、va_arg が楽。

#define __builtin_va_arg(ap,type) (*((type *)ap)++)

ですみます。連続してない方法だと、va_arg が数十命令取ったりします (MIPS, ARM) type で判断するなんてCレベルでは、できないだと思うが、どっこい、__builtin_types_compatible_p なんてものが GCC にはある。

今回は、varargs が浮動小数点をいく積んだかを、%al にいれておくってことを発見。いや、そんな情報要らないんだが。どうも、最大8x16byte = 128byte 領域を取ってコピーするので、ケチりたいと思った人がいるらしい。たぶん、なんかのベンチマークがあるんだろうな。それを計算するのに16命令ぐらい使っているので意味ない気もしますが。

しかも、xmm register は、関数呼び出しでは保存してくれないらしい。それは寂しいです。いや、16byte だから大きいからなぁ。いや、なんか、xmm は(なんか(dispatchとか)の時に)保存されないとか言う噂(まさか)もあったらしく、その影響かも。ABI だから、これは、どうしようもない。ライブラリから自分で作りなおせば別だが。なので、double に register 宣言しても、関数呼び出しとか挟んだら、まったく意味無。

xmm 系は alignment に凝らないと速くならないはずだが、まぁ、その辺りは良いです。どうせ、そんなに速度重視なコンパイラじゃないし。

あとは、self compile check で終りなんだが、これが難しいんだよな。test は、ほぼ通っているんだが、微妙に通らないです。これも、LP64 関係だろうけど。

gdb に最低限の情報は渡したいのだが、DWARF2 が謎過ぎ。

これが片付いたら、前に破れさった Cell SPU でもやるか。いや、Cell PPU が動かなくなっているなんていう説もあったな。

Post a Comment