Z80-COREのプログラミングツールとして、CコンパイラSDCCを紹介します。

SDCCは昔から存在は知っていたのですが、SDCCがサポートするPICのプログラミングでは、Microchipの開発環境とコンパイラを使っていますし、Z80などのプログラミングをやってたのは40年も前のことなので、SDCCを使ったことはありませんでした。(多分)

また、小さなプロセッサ用のCコンパイラにはずっと興味があって、SDCCにはちょこちょこと目が行っていたのですが、生成コードの質が良くないとか、ツールに安定性がないとか、結構批判的な意見が目についたのであえて時間を割く必要もないかなと思っていました。

しかしここにきて、Z80-COREのCコンパイラを確保する現実的な要求が突き付けられたので、使ってみることにしました。

結論から言えば、十分使えるという感じです。十分楽しませてもらっています。

まあ、問題はいくつかありますが、それも含めてのホビーですから。

特徴としては、データ型としてlong(32ビット整数), long long(64ビット整数), float(4バイトIEEE形式)などが使えます。ただし、printf()関数で%fを使ってfloat値を表示できなかったり、scanf()関数がなかったりということで、コンソールとのやり取りをするプログラムを作成するにはいくつか制約があります。

インストール

SDCCのサイトを以下に示します。

ダウンロードサイトからは、バイナリパッケージをダウンロードできるので、それをダウンロードしてインストールします。私は例のごとく、Windows64用のパッケージを使用します。

インストール先は、下記のディレクトリに書き換えてインストールしました。

  • C:\XENESIS\SDCC

コードのコンパイル用に以下のようなバッチファイルsdccz80.batを作成しました。

xcore0.relは、Z80-CORE用に作成したcrt0ファイルです。

PATH=C:\XENESIS\SDCC\bin
sdcc -mz80 --no-std-crt0 --code-loc 0x4020 --data-loc 0  xcore0.rel %1

コンソール入力を単純に画面にエコーバックするプログラムです。

まだ、ライブラリなど整備していないので、Z80-CORE固有の文字入出力は、モニタのサブルチンを呼ぶようにしました。

/*
	echomon.c
*/

#define CTRLC   0x03

void (*wexit)() = (void *)0x0083 ;
char (*conin)(void) = (void *)0x0098 ;
char (*conoutlf)(char) = (void *)0x008F ;

void main (void)
{
	char c ;
	while (1) {
		c = conin() ;
		if (c == CTRLC)
			wexit() ;
		conoutlf(c) ;
	}
}

コンパイルはバッチファイルを使用して以下の様に実行します。

sdccz80 echomon.c

プログラムがコンパイルされたらechomon.ihxというHEXファイルができるので、Z80-COREにダウンロードします。

ダウンロードできたら、モニタのGコマンドで実行します。入力は、Gもしくは、G4000で実行できます。

プログラムを実行しても何も起きないのでドキッとしますが、キーボードから文字を入力すると画面に表示され、CTRL-Cを入力するモニタに帰ります。

SDCCがどのようなコードを出すか、確認しました。以下にechomon.lstに出力されたコードの一部を示します。

      000000                         56 _main::
                                     57 ;echomon.c:17: while (1) {
      000000                         58 00104$:
                                     59 ;echomon.c:18: c = conin() ;
      000000 2Ar02r00         [16]   60 	ld	hl, (_conin)
      000003 CDr00r00         [17]   61 	call	___sdcc_call_hl
                                     62 ;echomon.c:19: if (c == CTRLC)
      000006 4F               [ 4]   63 	ld	c, a
      000007 D6 03            [ 7]   64 	sub	a, #0x03
      000009 20 08            [12]   65 	jr	NZ, 00102$
                                     66 ;echomon.c:20: wexit() ;
      00000B C5               [11]   67 	push	bc
      00000C 2Ar00r00         [16]   68 	ld	hl, (_wexit)
      00000F CDr00r00         [17]   69 	call	___sdcc_call_hl
      000012 C1               [10]   70 	pop	bc
      000013                         71 00102$:
                                     72 ;echomon.c:21: conoutlf(c) ;
      000013 79               [ 4]   73 	ld	a, c
      000014 2Ar04r00         [16]   74 	ld	hl, (_conoutlf)
      000017 CDr00r00         [17]   75 	call	___sdcc_call_hl
                                     76 ;echomon.c:23: }
      00001A 18 E4            [12]   77 	jr	00104$
                                     78 	.area _CODE
                                     79 	.area _INITIALIZER
      000000                         80 __xinit__wexit:
      000000 83 FF                   81 	.dw #0xff83
      000002                         82 __xinit__conin:
      000002 98 FF                   83 	.dw #0xff98
      000004                         84 __xinit__conoutlf:
      000004 8F FF                   85 	.dw #0xff8f