add(a, b) int a, b; { a += b; return a; }Z8000アセンブリ
.data .text .globl _add _add: call csv sub r15,#F1 ld r2,4(r14) add r2,6(r14) ld 4(r14),r2 ld r2,4(r14) jp cret jp cret .F1 = 0. .data最適化は全くされていないので無駄が多いコードですが、正しくアセンブリを出力できるようになってきています。
add(a, b) int a, b; { a += b; return a; }Z8000アセンブリ
.data .text .globl _add _add: call csv sub r15,#F1 ld r2,4(r14) add r2,6(r14) ld 4(r14),r2 ld r2,4(r14) jp cret jp cret .F1 = 0. .data最適化は全くされていないので無駄が多いコードですが、正しくアセンブリを出力できるようになってきています。
Z8530 SCCを制御するコードも上げておきます。
先ずは初期化のコードです。送受信の割り込みが処理できるように初期化しています。この石もかなり曲者で初期化手順を間違うとうまく動きません。
発生させる割り込み込みベクタは0x10からで、チャンネルAの送信が0x18で、受信が0x1cになります。
.equ SCCAC, 0x0009 .equ SCCAD, 0x000D init_scc: ld r2, #(scccmde - scccmds) ! initialize Z8530 ld r3, #SCCAC ld r4, #scccmds otirb @r3, @r4, r2 ret scccmds: .byte 9, 0xc0 ! Reset .byte 4, 0x44 ! x16, 1stop-bit, non-parity .byte 3, 0xe0 ! Receive 8bit/char, rts auto .byte 5, 0xe2 ! Send 8bit/char, dtr rts .byte 2, 0x10 ! Interrupt vector .byte 1, 0x12 ! Interruprt on Rx All character and Tx Int .byte 9, 0x09 ! MIE, VIS, Status=Low .byte 11, 0x50 ! BG use for receiver and transmiter .byte 12, 30 ! 4800bps at 5MHz clock .byte 13, 00 .byte 14, 0x02 ! PCLK for BG .byte 14, 0x03 ! BG enable .byte 3, 0xe1 ! Receiver enable .byte 5, 0xea ! Transmiter enable scccmde:
割り込みハンドラーは、次のようなコードです。リングバッファ処理部分は端折ってあります。Z8536と同じで割り込み処理の終了処理を正しく行わないと、優先順位の低い割り込みがかからなくなったりします。
scc_rxint: ! Rx InterruptHandler push @r15, r0 push @r15, r1 1: inb rl0, #SCCAC andb rl0, #0x01 jr z, 1b inb rh0, #SCCAD ! Read a data from Rx buffer ! ! ldb rl0, #0x38 ! Enable IUS outb #SCCAC, rl0 pop r1, @r15 pop r0, @r15 iret scc_txint: ! Tx Interrupt Handler push @r15, r0 push @r15, r1 ! ! outb #SCCAD, rl0 ! Write a data to Tx buffer ldb rl0, #0x28 ! Clear Tx interrupt pendinng outb #SCCAC, rl0 ldb rl0, #0x38 ! Enable IUS outb #SCCAC, rl0 pop r1, @r15 pop r0, @r15 iret
Z8536の初期化手順と割込み処理のメモです。カウンタタイマ3で10mS周期の割り込みをかけます。
Z8536にはRESETピンがなく、ハードウェアリセットはRDピンとWRピンを同時にLにすることで行います。今回はハードウェアを手抜きしているので、ソフトウェアでリセットしています。A0, A1ピンをHにしてリードし、つづいて、レジスタ0に1を書き込んだのちレジスタ0に0を書き込みます。これで初期化されます。
レジスタのアクセスは、A0, A1ピンをHにしアクセスするレジスタ番号を書き込み、つづいて目的のレジスタに書き込みか読み込みをします。Z8536を初期化するのにレジスタ設定の順番を変えたりすると、なぜか動かなくなったりします。正しい手順はよく理解できていないのですが、手探りで見つけた手順が下のコードです。
.equ CIOPRTC, 0x0011 .equ CIOPRTB, 0x0015 .equ CIOPRTA, 0x0019 .equ CIOCTRL, 0x001d init_cio: ld r1, #CIOCTRL inb rl0, #CIOCTRL lda r2, ciocmds ld r3, #(ciocmde - ciocmds) otirb @r1, @r2, r3 ret ciointr: push @r15, r0 ! レジスタ保存 push @r15, r1 ! 割り込み処理 ! ! ldb rl0, #0x0c outb #CIOCTRL, rl0 ldb rl0, #0x24 outb #CIOCTRL, rl0 ! Clear IP and IUS pop r1, @r15 ! レジスタ復帰 pop r0, @r15 iret !------------------------------------------------------------------------------ ciocmds: .byte 0x00, 0x01 ! Reset .byte 0x00, 0x00 ! Clear reset .byte 0x01, 0x00 ! Reset PortC and C/T3 .byte 0x01, 0x10 ! Enable PortC and C/T3 .byte 0x1e, 0xc2 ! Continuous, Ext Output, Square wave .byte 0x1a, 0x30 ! Set timer constant .byte 0x1b, 0xd4 ! Set timer constant .byte 0x00, 0x84 ! MIE and VIS .byte 0x04, 0x00 ! Set Interupt vector .byte 0x0c, 0xc0 ! Set Interupt Enable bit .byte 0x0c, 0x06 ! Gate and Triger ciocmde:
割り込み処理は、最後にレジスタ12のIPとIUSをクリアして戻れば、続けて割り込みが発生します。これを忘れると、割り込みが単発になったり、他のチップからの割り込みが発生しなくなります。
Z8530もそうでしたが、Zilogの周辺チップはプログラムが難しい印象です。さらにデータシートが不親切で、読んだだけでは理解できないことが多々あります。ネット上にもあまり情報がないので、手探りがで動かすことになるのですが、動いた時の高揚感は格別です。
IOREQ = ST0 # !ST1 # ST2 # ST3; DI = !ST3; MMUSEL = !A15 # !A14 # IOREQ; MAPSEL = MMUENA & MMUSEL; MMUBUFE = MMUSEL # DS; MAPRD = (MMUSEL # !RW # DS) & !IOREQ; MAPWR = MMUSEL # RW # DS;
I/O Addr | N/S | D/I | Page No. |
C001 | S | I | 0 |
: | : | : | : |
C01F | S | I | F |
C021 | N | I | 0 |
: | : | : | : |
C03F | N | I | F |
C041 | S | D | 0 |
: | : | : | : |
C05F | S | D | F |
C061 | N | D | 0 |
: | : | : | : |
C07F | N | D | F |
$ go build xout2coff $ go build xarchとコマンドを打つと、それぞれビルドされて xoututils/ にコマンドができます。
$ xarch libXXX.aで、ライブラリの展開。
$ xout2coff XXX.relで、COFFへのファイル変換ができます。