H8300用クロスコンパイラの作成
コンパイラテストツールが 16bitコンパイラでも使用できるか
ということを確かめたかったので作って見ました。
基本的にその他のクロスコンパイラと同様です。
以下とほとんど同じです。
v850用クロス開発環境の構築 - Life is very short
Binutilsの作成
% tar xf binutils-2.21.1.tar.bz2 % cd buinutils-2.21.1 % mkdir build && cd build % ../configure --target=h8300-linux-elf --prefix=/home/syohei/local/h8300 \ --disable-nls % make % make install % export PATH=/home/syohei/local/h8300/bin:$PATH
GCCの作成
% tar xf gcc-4.6.1.tar.bz2 % tar xf newlib-1.19.0.tar.gz % ln -s ../newlib-1.19.0/newlib . % ln -s ../newlib-1.19.0/libgross . % cd gcc-4.6.1 % mkdir build && cd build % ../configure --target=h8300-linux-elf --prefix=/home/syohei/local/h8300 \ --enable-languages=c --with-gmp=/usr/local --with-mpfr=/usr/local \ --with-mpc=/usr/local --with-cloog=/usr/local --disable-nls \ --disable-multilib --disable-libssp --with-newlib \ --with-headers=/home/syohei/src/newlib-1.19.0/newlib/libc/include % make % make -j2
newlibの作成
% cd newlib-1.19.0 % mkdir build && cd build % ../configure --target=h8300-linux-elf --prefix=/home/syohei/local/h8300 \ --disable-nls % make % make install
gdbの作成
% tar xf gdb-7.3.tar.bz2 % cd gdb-7.3 % mkdir build && cd build % ../configure --target=h8300-linux-elf --prefix=/home/syohei/local/h8300 \ --disable-nls % make % make install
チェック
以下のコードで各データ型のサイズを見てみます。
#include <stdio.h> int main (void) { printf("size of char = %d\n", sizeof(char)); printf("size of short = %d\n", sizeof(short)); printf("size of int = %d\n", sizeof(int)); printf("size of long = %d\n", sizeof(long)); printf("size of long long = %d\n", sizeof(long long)); printf("size of pointer = %d\n", sizeof(void*)); return 0; }
以下で確認
% h8300-linux-elf-gcc size.c % h8300-linux-elf-run a.out size of char = 1 size of short = 2 size of int = 2 size of long = 4 size of long long = 8 size of pointer = 2
intが 2バイト、ポインタが2バイトということがわかります。
今時の携帯電話のような高性能な機器であれば、32ビットが
普通ですが、組み込みではまだこういうのが使われています。
機器によっては 8ビット CPUというのも未だ現役で使われて
います。
PCばっかりでやってると気づきませんが、このように各型の
サイズはアーキテクチャによりよりまちまちであるので、
データ長が保証されたサイズ(C99のstdint.hに定義される型)を
使うことが望ましいわけです。
テスト
Testgenを使ってテストして見ました。
最新の Testgenは以下にあります。
コンフィギュレーションファイル
以下のようにしました。
+{ compiler => 'h8300-linux-elf-gcc', simulator => 'h8300-linux-elf-run', c_flags => [ '-g', '-Dunix' ], ld_flags => [ '' ], options => [ '-O0', '-O2' ], testdir => 'testsuite_h8300', compile_only => 0, size => { char => 8, short => 16, int => 16, long => 32, pointer => 16, }, timeout => 10, parallels => 2, }
テストの実行
% perl bin/tgen.pl --config=h8300_cross.cnf template/*.tt % cd testsuite_8300 % ./runtest.pl
テスト結果
c89.4-2-05/lt2906.cを '-O2'オプションでコンパイルしたときのみ
失敗しています。該当のプログラムは以下のとおり。
long dummy1(unsigned (*) (unsigned), unsigned); unsigned divide4(long); long dummy2(long (*) (long), unsigned); long divide2(long); short statusFlag = NoMistake; int main(void) /* * test class: simple arithmatic expression ( case 2 ) instance : linear tree structure, return value, legal pointer to * function returning a long */ { unsigned i = 3; i = dummy1(divide4, i *= 4); if (i != 3L) statusFlag++; if (statusFlag == NoMistake) printok(); else printno(); return 0; } long dummy1(unsigned (*func) (unsigned), unsigned Long) { long i = (long) Long; i = (*func) (i % 100); if (i != 3L) statusFlag++; return i; } unsigned divide4(long Long) { return dummy2(divide2, (unsigned) Long) / 2; } long dummy2(long (*func) (long), unsigned Long) { long i; i = (*func) ((long) Long); if (i != 6L) statusFlag++; return i; } long divide2(long Long) { return Long / 2; }
逆アセンブルで確認したところ、dummy1が呼ばれていないことが
原因のようです。インライン展開されているわけでもないのに、
divide4の方にいきなり飛んで、引数に値が正しく設定されていない
という現象が発生しています。
特殊なオプションをつけたわけでもないただの O2でこんなことが
起こるとなると、信頼度は低いと言わざるをえないですね。
商用でこのバージョンを使うというのは難しいのではないかと
思います。
最後に
h8300クロスコンパイラの作成方法について示しました。