32bitのAlphaのコードがどのようなものか見たくなり、Windows NT/Alpha用のクロスgccをビルドしてみました。ビルドに成功したのはgcc-3.0.4です。binutilsはビルドできるバージョンが見つからなかったため、PEバイナリは出力できません。gcc -Sでアセンブリコードを出力することはできます。
ソースにパッチを当て、ソースの外にディレクトリを作ってビルドします。
$ tar xvzf gcc-core-3.0.4.tar.gz $ patch -p0 < gcc-3.0.4-alpha-winnt.diff $ mkdir alpha-winnt $ cd alpha-winnt $ ../gcc-3.0.4/configure --target=alpha-winnt --disable-nls $ make $ make install
- ビルド用のディレクトリの名前は何でも良いです。
- MSYSではconfigureを絶対パスで呼ぶとWindowsパスへの変換に失敗するため、相対パスで呼ぶ必要があります。
- --disable-nlsを指定しているのは、日本語でメッセージが出るのを避けるためよりも、バイナリ配布したときにlibintlのバージョン違いで動かなかったことがあるためです。
サンプル
64bit用のalpha-elf-gccとの違いを比べてみます。alpha-elf-gccのビルドはパッチが必要です。
簡単なプログラムをアセンブリ出力して結果を比べてみます。
64bit (alpha-elf)
gccからアセンブリを出力します。プロローグやエピローグを簡略化するため最適化を掛けます。
$ alpha-elf-gcc -O -S -o alpha-elf.s alpha.c
binutilsが使えるので、逆アセンブルも試します。C言語との対応関係が分かります。
$ alpha-elf-gcc -nostdlib -O -g -o alpha-elf.x alpha.c $ alpha-elf-objdump -S alpha-elf.x > alpha-elf.txt
レジスタが番号ではなく名前で示されるため読みやすいです。擬似命令が展開されるため、実際のバイナリが確認できます。
比較
両者を見比べると以下のことが分かります。
- CPUに32bit/64bitのモードがあるわけではなく、コンパイラの出力でデータモデルを表現している。
- 32bit(alpha-winnt)はILP32
lda $16,4 # sizeof(int) lda $16,4 # sizeof(long) lda $16,4 # sizeof(void *)
- 64bit(alpha-elf)はI32LP64
lda a0,4 # sizeof(int) lda a0,8 # sizeof(long) lda a0,8 # sizeof(void *)
lda $1,global => ldq t0,-32760(gp)
- 32bitではbinutilsが使えないため確認できない。GPレジスタを操作しないことから、絶対アドレスが2命令に分割された上で即値として埋め込まれると思われる。
- よく似ているMIPS(mipsel-pe-gcc)で例示(←ビルド方法など)
sw $4,global => lui at,0x40; sw a0,8192(at) # [0x402000] = a0
おまけ
gcc-3.0.4にはalpha-interixのコンフィギュレーションもあります。出力するコードはalpha-winntとほぼ同じようです。こちらも対応するbinutilsが見つかりませんでした。
Alpha版のInterixは存在すら知らなかったので驚きました。WikipediaにはInterix 2.2までは対応していたような記述があります。
現物は見たことも聞いたこともないので詳細不明です。