Elf2x68k
ELF to X68k executable converter with cross development environment
Install / Use
/learn @yunkya2/Elf2x68kREADME
X680x0 クロス開発環境 elf2x68k
概要
elf2x68k はシャープ X680x0 用実行ファイル(X 形式)を PC の Unix/Linux 系環境や macOS 上で開発するためのクロス開発環境です。m68k 用クロスツールチェイン (gcc, binutils) から出力される ELF ファイルを変換して、 X68k で実行可能な X 形式ファイルを出力します。
更に、X-BASIC から C へのコンバートにも対応しています。クロス環境上で X-BASIC プログラムを変換、コンパイルして X 形式ファイルを出力することができます。
特徴
- 最新の binutils (2.44)、gcc (13.4.0) を用いた X68k のクロス開発が可能です
- binutils, gcc の各コマンド名の頭に
m68k-xelf-が付いたコマンドがクロスツールチェインとなります (例:m68k-xelf-gcc) - コンパイラドライバ (
m68k-xelf-gcc) から直接 X 形式ファイルが出力されます。ネイティブの gcc を使用するのと同様の感覚で X 形式ファイルを得ることができます - ツールチェインから出力される ELF ファイルに含まれるデバッグ情報を利用して、gdbserver-x68k を用いたリモートデバッグが可能です
- X68k 標準の開発環境で用いられているオブジェクトファイルやライブラリファイル (*.o/*.a/*.l) を ELF 形式に変換するスクリプト
x68k2elf.pyを用意しています - 標準 C ライブラリに以下の 2 種類を用意しています。用途によって使い分けが可能です
- Newlib (組み込みシステム等で使われている標準 C ライブラリ)
- C Compiler PRO-68K v2.1 (XC) の 標準 C ライブラリ
- アセンブラには GNU binutils の as を使用します。680x0 アセンブリ言語の書式は、HAS.X などで用いられているモトローラ形式でなく MIT形式 (GASフォーマット) となります
- X-BASIC to C コンバータ
bas2c.pyとそのサポートコマンドm68k-xelf-basにより、X-BASIC で書かれたプログラムを変換、コンパイルして X 形式ファイルを得ることができます
インストール
Linux/MinGW 向け
以下の環境向けバイナリを配布しています
- x86_64 Linux (Windows 11 の WSL2 にインストールした Ubuntu-20.04 で動作確認)
- MSYS2 MinGW 64bit
Release から利用する環境のアーカイブをダウンロードし、任意のディレクトリに展開してください。
m68k-xelf/bin にパスを通すことで使用できるようになります。
アーカイブにはライブラリとして Newlib 環境のみが含まれています。
展開した m68k-xelf ディレクトリにある install-xclib.sh スクリプトを実行することで、無償公開されている C Compiler PRO-68K ver2.1 (XC) をダウンロード、インストールします。
これによって、Newlib に加えて XC のライブラリも利用できるようになります。
- X-BASIC to C コンバータを利用する場合には必ず実行してください。
- インストール後に
m68k-xelfディレクトリを移動した場合はinstall-xclib.shスクリプトを再度実行してください (スクリプト内で実行時の絶対パスを記録する箇所があるため)。
macOS 向け
macOS 向けは Homebrew からインストールできます (M3 Macbook Air / macOS 15.6.1 (Sequoia) で動作確認)。 Homebrew がインストールされている環境でコマンドラインから
brew install yunkya2/tap/elf2x68k
を実行すると、ソースコードをダウンロードしてビルド、インストールを行います (M3 Macbook Air で 30 分程度かかります)。
XC ライブラリのインストールも合わせて行いますので、install-xclib.sh スクリプトは実行不要です。
ソースコードからのビルド
ソースコードからビルドを行う方法は README-elf2x68k.md を参照してください
サンプルコード
C や C++、X-BASIC to C のサンプルコードを elf2x68k-samples リポジトリに用意しています。 サンプルコードの説明は README.md を参照してください。
実行例
テストとして、以下のようなサンプルをコンパイルしてみます。
#include <stdio.h>
int main()
{
printf("Hello world.\n");
return 0;
}
この内容のファイル sample.c を作成し、以下のコマンドを実行します。
m68k-xelf-gcc -o sample.x sample.c
ソースコードがコンパイルされ、sample.x, sample.x.elf の 2 つのファイルが生成されます。
sample.xは X68k の X 形式実行ファイルなので、実機やエミュレータなどの環境で実行できます。sample.x.elfは、X 形式実行ファイルを生成するために使用した ELF ファイルです。m68k-xelf-readelfやm68k-xelf-objdumpなどの ELF ファイルを扱うコマンドはこのファイルに対して実行することができます。
このようにリンク後に X 形式実行ファイルと ELF ファイルが生成されることを除けば、使い方は通常の gcc と同じです。もちろんコンパイルとリンクを分けて実行することも可能ですが、リンクは GNU リンカ m68k-xelf-ld を直接呼び出すことは避けて、コンパイラドライバ m68k-xelf-gcc から実行するようにしてください
(ELF → X 形式の変換を gcc の specs ファイルの記述によって行っているため)。
-o オプションによる出力ファイル名の指定
m68k-xelf-gcc コマンドの -o オプションで出力ファイル名を指定することができます。
通常、このオプションでは最終的に出力する X 形式実行ファイルの名前を指定しますが、指定したファイル名の拡張子が .out や .elf だった場合は中間生成物の ELF ファイルの指定とみなし、最終的な出力ファイルは拡張子を .x に変更したファイルとなります。
-o オプションで指定するファイル名の拡張子とELF ファイル、X 形式ファイルの関係は以下のようになります。
| 拡張子 | ELF ファイル名 | X形式実行ファイル名 | |------------------------|----------------------------|---------------------------------| | .out,.elf 以外<br>(例:ABC.x) | 指定したファイル名.elf<br>(例:ABC.x.elf) | 指定したファイル名<br>(例:ABC.x) | | .out または .elf<br>(例:ABC.out) | 指定したファイル名<br>(例:ABC.out) | ファイル名の拡張子を.xにしたもの<br>(例:ABC.x) | | 拡張子なし<br>(例:ABC) | 指定したファイル名<br>(例:ABC) | 指定したファイル名.x<br>(例:ABC.x) |
-o オプションを指定しなかった場合の出力ファイル名には a.out が使われます。このため、
- ELFファイル名は
a.out - X形式実行ファイル名は
a.x
となります。
リモートデバッガの利用
elf2x68k には m68k 用 GNU デバッガ m68k-xelf-gdb が含まれています。
デバッガからシリアルポートやネットワークを介して X68k 実機やエミュレータ上の gdbserver-x68k に接続することで、ツールチェインが出力するデバッグ情報を利用したリモートデバッグが可能です。
リモートデバッグの手順は gdbserver-x68k のドキュメント を参照してください。
X-BASIC to C コンバータの利用
elf2x68k は m68k-xelf-bas コマンドによる X-BASIC プログラムのコンパイルが可能です。
usage: m68k-xelf-bas [OPTIONS][-o output] input.bas
input.bas で指定された X-BASIC プログラムを C ソースコードに変換し、そのファイルを m68k-xelf-gcc でコンパイルします。コンパイル時には XC の BASIC ライブラリ (libbas) が自動的にリンクされます。
(-specs=xc.specs -lbas オプションがデフォルトで指定されます)
以下のコマンドラインオプション指定が可能です。
-o output: 出力先となる X 形式実行ファイルのファイル名を指定します。省略した場合は入力ファイル名の拡張子を .bas から .x に変えたものになります。-S: X-BASIC から C への変換のみを行い、実行ファイルへのコンパイルは行いません。-Xb [option]: bas2c.py へ渡すオプションを指定します。
その他のオプションは、変換後に実行される m68k-xelf-gcc にそのまま渡されます。
X-BASIC から C への変換には bas2c.py を使用しています。オプションの詳細についてはこちらのドキュメントも参照してください
実行例:
% cat test.bas (X-BASIC プログラム)
10 for i=0 to 100
20 print i
30 next
% m68k-xelf-bas test.bas (test.x と test.x.elf が生成される)
% m68k-xelf-bas -S test.bas (test.c が生成される)
% cat test.c (変換された C ソースコード)
#include <basic0.h>
#include <string.h>
static int i;
/******** program start ********/
void main(int b_argc, char *b_argv[])
{
b_init();
for (i = 0; i <= 100; i++) {
b_iprint(i);
b_sprint(STRCRLF);
}
b_exit(0);
}
ライブラリ環境の選択
elf2x68k は以下の 2 種類のライブラリ環境を用意しています。これらはコンパイル時の -specs= オプションによって使い分けが可能です。
- Newlib環境 (組み込みシステム等で使われている標準 C ライブラリ)
- XC 環境 (C Compiler PRO-68K v2.1 (XC) の 標準 C ライブラリ)
各ライブラリの詳細については 標準 C ライブラリについて を参照してください。
x68k2elf.py スクリプト
X68k 標準のオブジェクトファイルやライブラリファイル (*.o/*.a/*.l) は X68k 独自のファイル形式が用いられていますが、x68k2elf.py スクリプトでこれらを ELF オブジェクト/ライブラリファイルに変換できます。
バイナリ提供されているオブジェクトやライブラリをクロス開発環境上で使いたい場合は、このスクリプトで変換を行うことで m68k-xelf-gcc でのリンクが可能になります。
usage: x68k2elf.py [-h] [-k] [-v] infile [outfile]
- infile で指定した X68k オブジェクトファイルやライブラリファイルを ELF 形式に変換して outfile に出力します。 ライブラリファイルを指定した場合は、そのファイル内に含まれるオブジェクトファイルすべてを ELF 形式に変換し、それらをまとめたアーカイブファイル (*.a) を新規に作成します
-vオプションで変換中のオブジェクトファイルの詳細を表示します。outfile を省略した場合はファイルの出力を行わないので、これと併用することで単にオブジェクトファイルの中を解析するのに使用できます- ELF 変換の際、変換元のファイルのシンボル名は先頭のアンダーバー
'_'が削除されます。-kオプションを指定するとこの変換を行わず、C の関数名や変数名のシンボルはアンダーバーが付いたままになります
ABI の差異について
アプリケーションバイナリが使用する関数の呼び出し規約やデータの配置方法といったインターフェース定義を ABI (Application Binary Interface) と呼びます。 複数のオブジェクトファイルやライブラリをリンクする際、すべてのファイルの ABI は一致している必要がありますが、XC 等 X68k の標準開発環境と 現在の m68k 向け gcc とでは ABI に違いがあります。
主な違いとしては、以下のような点があります。
- XC ABI
- 関数呼び出しの前後では d0,d1,d2,a0,a1,a2 レジスタが破壊される
- C 言語の関数名や変数名がアセンブラのシンボル名になる際、名前の先頭にアンダーバー
_が付いたものが使われる
- gcc ABI
- 関数呼び出しの前後では d0,d1,a0,a1 レジスタが破壊される (d2, a2 は保存される)
- C 言語の関数名や変数名がアセンブラのシンボル名になる際は名前がそのまま使われる
elf2x68k では、gcc ABI をベースにしつつ XC のオブジェクトファイルやライブラリを利用できるようにするため、以下のような ABI を採用しています。
- elf2x68k ABI
- 関数呼び出しの前後では d0,d1,d2,a0,a1,a2 レジスタが破壊される (XC ABI と同じ)
- C 言語の関数名や変数名がアセンブラのシンボル名になる際は名前がそのまま使われる (gcc ABI と同じ)
C 言語のソースコードのみを普通にコンパイルする際は (Newlib 環境、XC 環境とも) この点については特に意識しないで良いのですが、過去のオブジェクトファイルの利用やアセンブラとの連携では以下の点に注意が必要です。
- elf2x68k 内での対応
- C コンパイラ
m68k-xefl-gcc実行時は常にコンパイルオプション-fcall-used-d2 -fcall-used-a2を追加してコンパイルされます。これは gcc のデフォルトの specs ファイルを変更することで対応しているので、通常はユーザーがオプションの追加を意識する必要はありません
- C コンパイラ
- XC 用資産への対応
- XC 用のオブジェクトファイルやライブラリを
x68k2elf.pyで ELF オブジェクトに変換する際、シンボル名先頭のアンダーバー_を削除します - C 言語中に書かれたインラインアセンブラなど、XC ABI で書かれたものをソースコードのままクロス開発環境に持ち込む場合はアンダーバー削除の対象にならないため、ユーザが自分で削除する必要があります
- XC 用のオブジェクトファイルやライブラリを
謝辞
elf2x68k の開発には以下のソースコードを参考にさせていただきました。
- m68k クロスツールチェインのビルドスクリプトは、xdev68k 内のスクリプト build_m68k-toolchain.sh を元にしています。開発された よっしん氏 (@yosshin4004) に感謝いたします。
- Newlib の X68k 対応は、newlib-1.19.0-human68k の human68k対応コード を元にしています。開発された Lyderic Maillet 氏 に感謝いたします。
- macOS ビルド対応については tantan さんの変更内容を参考にさせていただきました。感謝します。
ライセンス
- src/*
BSDライセンスが適用されます。 - scripts/*
元となった xdev68k 内のスクリプト build_m68k-toolchain.sh と同様に、Apache License Version 2.0 が適用されます。 - binutils, gcc, newlib
それぞれの配布元が規定したライセンス条件が適用されます。アーカイブ内の COPYING ファイル等を参照してください。
