Z80

FOR文を実装

2012年6月5日

FOR文が使えるようにした。

2012-06-05-FOR.png

幾つか制約があるが、それを踏まえた上でプログラミングすれば、まともに使える(はず)。制約とは、以下のとおり。

・NEXT文では、変数指定の必要はない。
・TOで指定された値と同一にならないと、停止しない。例えば、「FOR A=0 TO 9 STEP 2」などとすると、永久ループになる。
・上記の性質と関係するが、例えば「FOR A=10 TO 9」などと記述すると、ループの中身が65536回実行される。

FOR文、NEXT文のコンパイルルーチンは、次のとおり。
char compileFor(){
	char e;
	int variableAddress, *XX, *YY;
	// init statement
	while ((e=source[0])==' ') source++;
	variableAddress=(int)(&g_variables[(e-'A')*2]);
	e=compileLet();
	if (e) return e;
	// TO statement
	if (strncmp(source,"TO ",3)) return 1;
	source+=3;
	e=compileInt();
	if (e) return e;
	// STEP statement
	while (source[0]==' ') source++;
	if (!strncmp(source,"STEP ",5)) {
		source+=5;
		object[0]=0xD5; // PUSH DE
		object++;
		e=compileInt();
		if (e) return e;
		memcpy(object,"\xED\x53\x00\x00\xE1\x19",6); // LD (yyyy),DE; POP HL; ADD HL,DE
		YY=(int*)(object+2); // See below
		object+=6;
	} else {
		// STEP 1
		YY=0;
		memcpy(object,"\xEB\x23",2); // EX DE,HL; INC HL
		object+=2;
	}
	object[0]=0x22; // LD (xxxx),HL
	XX=(int*)(object+1); // See below
	object+=3;
	// FOR statement main routine follows.
	memcpy(object,
		"\x18\x12"     // JR skip:
		"\x2A\x34\x12" // LD HL,(1234)
		"\x11\x01\x00" // LD DE,0001
		"\x19"         // ADD HL,DE
		"\x22\x34\x12" // LD (1234),HL
		"\xAF"         // XOR A
		"\x11\x34\x12" // LD DE,XXXX
		"\xED\x52"     // SBC HL,DE
		"\xC8"         // RET Z
		"\xE1"         // POP HL
		"\x21\x34\x12" // skip: LD HL,1234
		"\xE5"         // PUSH HL
		,24);
	*XX=(int)object+14;
	if (YY) *YY=(int)object+6;
	object+=3;
	((int*)object)[0]=variableAddress;
	object+=7;
	((int*)object)[0]=variableAddress;
	object+=11;
	((int*)object)[0]=(int)object-19;
	object+=3;
	return 0;
}
char compileNext(){
	memcpy(object,
		"\xE1"         // POP HL
		"\x18\x01"     // JR skip:
		"\xE9"         // back: JP (HL)
		"\xCD\x34\x12" // skip: CALL back:
		,7);
	object+=5;
	((int*)object)[0]=(int)object-2;
	object+=2;
	return 0;
}

離れた場所にあるFOR文とNEXT文の間でのプロセスの移動には、スタックを用いている。なので、FORループの中でGOTOを用いたりRETURNしたりすると、暴走することになる。まぁ、そういう仕様と言うことで。

ちなみに、memcpy()にはZ80のブロック命令が用いられているので、ここの部分は結構高速である。いずれにせよ、一通り使えるようになってから、速度向上とファイルサイズの圧縮のために、記述方法を全体的に見直すつもりにはしている。

出来上がったFOR文で一万回ループを実行してみると、凡そ0.5秒ほどだった。普通のBASICインタープリターの20倍ほどの速度である。

コメント

コメントはありません

コメント送信