SSブログ
English Version

8080/Z80 リロケータブルコードの実験(その2) [Z80]

 Twitter のタイムラインで Z80 の相対コールに関するコメントを見かけました。4年程前に書いた「8080/Z80 リロケータブルコードの実験」の記事が参照されていたので再度相対コールに関して書いてみます。

 上記の記事では相対コールは速度重視の観点から DE 設定と RST 命令 の合計4バイト構成でしたが、DE設定せずに相対アドレス情報だけにすることで3バイト構成の相対コールが提案されていました(遅くはなるけど相対コール自体は短くなる)。

 Z80 の相対ジャンプのように相対アドレス情報を1バイトにして2バイトの相対コールも可能ですが、元々のコール命令が3バイトなので3バイト構成の相対コールは既存のコードとの相性が良さそうです。しかし、DE/HL レジスタを破壊してしまうと既存のプログラムのコール命令を相対コールに置き換えることができません。

 そこで DE/HL 等のレジスタ非破壊の相対コールを考えてみました。
 流石に8バイトには収まらないので次の RST 命令を潰さないようにジャンプ命令で通常のプログラム領域に飛びます(実行ファイルを ZSID でロードできるように JP 命令自体はコメントアウトしています)。

Z80 relocatable call V2
;********************************* ; 8080/Z80 relocatable call test2 ; 2022/08/23 by skyriver ;********************************* 0028 RELRST EQU 028H ; using RST for reloc code ; *** reloc call macro *** rcall macro dest rst RELRST dw dest - $ - 2 endm 0000' ASEG ; ORG RELRST ; ; JP RELOCALL ORG 0100H 0100 test: RCALL PROC 0100 EF + rst RELRST 0101 0003 + dw PROC - $ - 2 0103 C3 0103 JP $ 0106 00 PROC: NOP 0107 C9 RET ORG 0200H 0200 RELOCALL: 0200 22 0213 LD (SAVHL),HL 0203 E1 POP HL 0204 D5 PUSH DE 0205 5E LD E,(HL) 0206 23 INC HL 0207 56 LD D,(HL) 0208 23 INC HL 0209 EB EX DE,HL 020A 19 ADD HL,DE 020B EB EX DE,HL ; DE:call addr, HL:next code 020C E3 EX (SP),HL 020D EB EX DE,HL 020E E5 PUSH HL 020F 2A 0213 LD HL,(SAVHL) 0212 C9 RET 0213 SAVHL: DS 2 END Macros: RCALL Symbols: 0106 PROC 0200 RELOCALL 0028 RELRST 0213 SAVHL 0100 TEST No Fatal error(s)


 SP はインデクス付きでのアクセスができないため HL レジスタをスタック上に保存すると復活するのが難しい(IX 等を使うと処理が更に長くなる)ので、HL はワークエリアに保存しています(DE もワーク保存の方が良かったかも)。このため割込み処理内でもこの相対コールを使う場合は RELOCALL 処理中は割込み禁止にする必要があります。

★追記 2022/08/25 {
 DE をワークに保存した場合、処理は単純になりコード作成は楽ですが速度は 13 ステート遅くなり、サイズは 3 バイト(ワーク分も含めれば 5 バイト)大きくなります。
}

 ZSID を使って動作確認した結果が下記になります。

relocatable call code test
b>a:m80 =reloc/z/l No Fatal error(s) b>a:l80 reloc,reloc/e/n Link-80 3.44 09-Dec-81 Copyright (c) 1981 Microsoft Data 0100 0215 < 277> 53535 Bytes Free [0000 0215 2] b>a: zsid reloc.com ZSID VERS 1.4 NEXT PC END 0280 0100 DBFF #s28 0028 00 c3 0029 00 00 002A 00 02 002B 00 . #l100 0100 RST 28H 0101 INC BC 0102 NOP 0103 JP 0103 0106 NOP 0107 RET 0108 NOP 0109 NOP 010A NOP 010B NOP 010C NOP #xd D=0000 1111 #xh H=0000 2222 #x ----- A=00 B=0000 D=1111 H=2222 S=0100 P=0100 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 RST 28H #t ----- A=00 B=0000 D=1111 H=2222 S=0100 P=0100 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 RST 28H *0028 #t ----- A=00 B=0000 D=1111 H=2222 S=00FE P=0028 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 JP 0200 *0200 #t ----- A=00 B=0000 D=1111 H=2222 S=00FE P=0200 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 LD (0213),HL *0203 #t ----- A=00 B=0000 D=1111 H=2222 S=00FE P=0203 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 POP HL *0204 #t ----- A=00 B=0000 D=1111 H=0101 S=0100 P=0204 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 PUSH DE *0205 #t ----- A=00 B=0000 D=1111 H=0101 S=00FE P=0205 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 LD E,(HL) *0206 #t ----- A=00 B=0000 D=1103 H=0101 S=00FE P=0206 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 INC HL *0207 #t ----- A=00 B=0000 D=1103 H=0102 S=00FE P=0207 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 LD D,(HL) *0208 #t ----- A=00 B=0000 D=0003 H=0102 S=00FE P=0208 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 INC HL *0209 #t ----- A=00 B=0000 D=0003 H=0103 S=00FE P=0209 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 EX DE,HL *020A #t ----- A=00 B=0000 D=0103 H=0003 S=00FE P=020A ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 ADD HL,DE *020B #t ----- A=00 B=0000 D=0103 H=0106 S=00FE P=020B ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 EX DE,HL *020C #t ----- A=00 B=0000 D=0106 H=0103 S=00FE P=020C ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 EX SP,HL *020D #t ----- A=00 B=0000 D=0106 H=1111 S=00FE P=020D ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 EX DE,HL *020E #t ----- A=00 B=0000 D=1111 H=0106 S=00FE P=020E ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 PUSH HL *020F #t ----- A=00 B=0000 D=1111 H=0106 S=00FC P=020F ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 LD HL,(0213) *0212 #t ----- A=00 B=0000 D=1111 H=2222 S=00FC P=0212 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 RET *0106 #t ----- A=00 B=0000 D=1111 H=2222 S=00FE P=0106 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 NOP *0107 #t ----- A=00 B=0000 D=1111 H=2222 S=00FE P=0107 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 RET *0103 #t ----- A=00 B=0000 D=1111 H=2222 S=0100 P=0103 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 JP 0103 *0103 #


 上述のように RST 28H 部のジャンプ命令はコメントアウトしているので S コマンドで設定しています。
 処理内で使用している DE/HL も非破壊でコール先に飛んだ後、コール先のリターン命令でコール直後の命令にリターンしていますね。


★追記 2022/08/23
 HL をスタック上に保存するバージョンを作ってみました。データを積んだままスタックを INC しているので割込み禁止区間が発生します。
 また、ZSID のトレースコマンド(T)は割込み禁止状態でも RST 命令を使ってレジスタをスタック上に保存しているので 正常にステップ動作できませんが G100,210 で正常に動作することを確認しました。

Z80 relocatable call V2 stack version
;********************************* ; 8080/Z80 relocatable call test ; stack version ; 2022/08/23 by skyriver ;********************************* 0028 RELRST EQU 028H ; using RST for reloc code ; *** reloc call macro *** rcall macro dest rst RELRST dw dest - $ - 2 endm 0000' ASEG ; ORG RELRST ; ; JP RELOCALL ORG 0100H 0100 test: RCALL PROC 0100 EF + rst RELRST 0101 0003 + dw PROC - $ - 2 0103 C3 0103 JP $ 0106 00 PROC: NOP 0107 C9 RET ORG 0200H 0200 RELOCALL: 0200 E3 EX (SP),HL 0201 D5 PUSH DE 0202 5E LD E,(HL) 0203 23 INC HL 0204 56 LD D,(HL) 0205 23 INC HL 0206 EB EX DE,HL 0207 19 ADD HL,DE ; DE:next code, HL:call addr 0208 E3 EX (SP),HL 0209 EB EX DE,HL 020A F3 DI 020B 33 INC SP 020C 33 INC SP 020D E3 EX (SP),HL 020E 3B DEC SP 020F 3B DEC SP 0210 C9 RET END Macros: RCALL Symbols: 0106 PROC 0200 RELOCALL 0028 RELRST 0100 TEST No Fatal error(s)



★追記 2022/11/30
 Twitterのタイムラインで 2 バイトアドレスへの相対ジャンプの話題が出ていたので相対ジャンプについて追記します。
 TLにあった IX レジスタ式のものは元々の JP 命令の 10 ステートに比べてずいぶん遅くなるので、更に遅くなりますが下記で IX 非破壊で 2 バイト短縮できます。

E3	EX	(SP),HL
19	ADD	HL,DE
E3	EX	(SP),HL
C9	RET

 元々の JP 命令が 3 バイトなので同じバイト数に収めるのであれば RST を使って下記のようにもできますね(なんの捻りも無いですが)。

Z80 relocatable jump
;********************************* ; 8080/Z80 relocatable jp ; ver 0.01 2022/12/24 skyriver ; ver 0.02 2023/01/21 skyriver ;********************************* 0030 RELRST EQU 030H ; using RST for reloc code ; *** reloc jp macro *** RJP macro adrs rst RELRST dw adrs - $ - 1 endm 0000' ASEG ORG 0100H 0100 21 0111 INIT: LD HL,RSTST 0103 11 0030 LD DE,RELRST 0106 01 0009 LD BC,RSTEN - RSTST 0109 ED B0 LDIR 010B TEST: RJP PROC 010B F7 + rst RELRST 010C 0EF3 + dw PROC - $ - 1 010E 00 NOP 010F 00 NOP 0110 C9 RET ; dummy 0111 RSTST: ; RSTxx code 0111 E3 ex (sp),hl 0112 D5 push DE 0113 5E ld e,(hl) 0114 23 inc hl 0115 56 ld d,(hl) 0116 19 add hl,de 0117 D1 pop de 0118 E3 ex (sp),hl 0119 C9 ret 011A RSTEN EQU $ ORG 1000H 1000 00 PROC: NOP 1001 C3 1000 JP PROC END Macros: RJP Symbols: 0100 INIT 1000 PROC 0030 RELRST 011A RSTEN 0111 RSTST 010B TEST No Fatal error(s)

[history]
・ver 0.01a 2022/12/24 スタックにHLが残っていたので修正
・ver 0.02 2023/01/22 DE非破壊に変更


[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。