GCC 4.6 MIPS クロスコンパイラを作る

4.6でMIPSロスコンパイラを作ってみたので、そのメモです。

環境

Ubuntu 10.10 x64 GCC 4.4.5

バージョン

Binutils - 2.21
GCC - 4.6.0 RC
newlib - 1.18.0
GDB - 7.2

Binutils

(追記) export PATHを追加

  % cd binutils-2.21
  % mkdir build_mips && cd build_mips
  % ../configure --target=mipsel-linux-elf \
    --prefix=/home/syohei/local/mipsel_gcc46 --disable-nls
  % make 2>&1 | tee build_mips.log
  % make install
  % export PATH=/home/syohei/local/mipsel_gcc46/bin:$PATH

GCC

GCCをビルドする際は newlibも展開しておいてください。
そして newlibディレクトリと libglossディレクトリへの
シンボリックリンクGCCのソースツリーのトップに作成します。

  % cd gcc-4.6.0-RC
  % ln -s /home/syohei/gnu/newlib-1.18.0/newlib .
  % ln -s /home/syohei/gnu/newlib-1.18.0/libgloss .
  % mkdir build_mips && cd build_mips
  % ../configure --target=mipsel-linux-elf --enable-languages=c \
    --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local \
    --with-ppl=/usr/local --with-cloog=/usr/local \
    --prefix=/home/syohei/local/mipsel_gcc46 --disable-nls \
    --disable-multilib --disable-libssp --with-newlib \
    --with-headers=/home/syohei/gnu/gcc-4.6.0-RC-20110314/newlib/libc/include
    % make
    % make install

newlib

  % cd newlib-1.18.0
  % ../configure --target=mipsel-linux-elf \
    --prefix=/home/syohei/local/mipsel_tools --disable-nls
  % make 2>&1 | tee build_mips.log
  % make install

GDB

シミュレータ runのために GDBを作成します。

  % cd gdb-7.2
  % mkdir build_mips && cd build_mips
  % ../configure --target=mipsel-linux-elf \
    --prefix=/home/syohei/local/mipsel_tools --disable-nls
  % make 2>&1 | tee build_mips.log
  % make install

テスト

#include <stdio.h>
#include <stdlib.h>

static int func(int a)
{
    int array[1024];
    int i, sum = 0;

    for (i = 0; i < a; i++) {
        sum += array[i];
    }

    return sum;
}

int main (int argc, char *argv[])
{
    int a;
    if (argc >= 2) {
        a = atoi(argv[1]);
    } else {
        a = 1024;
    }

    return func(a);
}

コンパイルします。バイナリは作れたんですが、実行できなかったので
アセンブリとスタック使用量だけ確認します。分かりやすいように最適化なしです。

  % mipsel-linux-elf-gcc -S -O0 -fstack-usage stack_usage.c

スタック使用量は以下の通りです。

stack_usage.c:4:12:func 4112    static
stack_usage.c:16:5:main 32      static

アセンブリで確認してみます。
すごく割愛していますが、スタックを伸ばしているサイズ(spレジスタの操作)
と同じであることがわかります。

func:
	.frame	$fp,4112,$31		# vars= 4104, regs= 1/0, args= 0, gp= 0
	.mask	0x40000000,-4
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	addiu	$sp,$sp,-4112           # ここでスタックを伸ばす
	sw	$fp,4108($sp)
	move	$fp,$sp
        ....

main:
	.frame	$fp,32,$31		# vars= 8, regs= 2/0, args= 16, gp= 0
	.mask	0xc0000000,-4
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	addiu	$sp,$sp,-32             # ここでスタックを伸ばす
	sw	$31,28($sp)
	sw	$fp,24($sp)
	move	$fp,$sp
        ......

まとめ

GCC 4.6 MIPSのクロスコンパイラの作成方法を示しました。
fstack-usageはどちらかというと組み込み向けなので、
ロスコンパイラ(場合によってはネイティブ)で使っていければと思います。