Z8S180/TMPZ84C015/(Z80+8251+8255)/(Z80+SIO+PIO)に移植した同じ「最初のモニタ」をKL5C80B12Cにも移植したいと思います。

今回、モード設定は、ノーマルモードで動作させるので、MODE0(27pin)/MODE1(26pin)の端子は、Hレベル(Vcc)に設定します。

MMUの設定は、内部RAMは使用せず、M1CSにチップセレクトされるRAMを使用します。このRAMは、0xe0000から配置されます。

では早速、モニタプログラムを確認していきます。
KL5C80B12C特有のレジスタを定義していきます。
ここでは、コントロールレジスタSCR0/1、MMUレジスタBBR1~4/BR1~4、シリアル通信用レジスタUART_D/C、パラレルポートPP2~4D/PPBCを定義しました。

;;KL5C80 System control register

SCR0	.equ	0x3a	
SCR1	.equ	0x3b

;;KL5C80 Memory management unit

BBR1	.equ	0x00
BR1	.equ	0x01
BBR2	.equ	0x02
BR2	.equ	0x03
BBR3	.equ	0x04
BR3	.equ	0x05
BBR4	.equ	0x06
BR4	.equ	0x07

;;KL5C80 UART 

UART_D	.equ	0x38
UART_C	.equ	0x39

;;KL5C80 Parallel port B

PP2D	.equ	0x30
PP3D	.equ	0x31
PP4D	.equ	0x32
PPBC	.equ	0x33

続いて、コントールレジスタで、RxC/TxC(シリアル用クロック入力)及びHALT端子等を汎用ポートから各専用ポートに切り替えました。

Port0のP20~P27を確認用に出力に設定していますが、ここではコメントしています。SDCARDに接続するポートと同じなので、出力ポートが衝突してしまいます。SDCRADを未接続のとき、P20~P27で出力するときのみ、コメントを外してください。

start:                          ;cold start

	ld	a,0b00000001	;RxC,TxC Port set
	out	(SCR0),a
	ld	a,0b00001111	;NMI,BREQ,BACK,HALT,M1 set Active mode : 1 wait set
	out	(SCR1),a

;	ld	a,0b00000011	;Parallel port B 2x OutPut Mode
;	out	(PPBC),a

続いて、MMUの設定をします。
内蔵RAMを無効にするために、BBR4には0x3fを設定しています。
RAMは、64Kエリアの論理アドレス0x8000から0xffffまでに物理アドレス0xe0000~0xe0e7fffまでを割り当てます。
この設定をBBR3及びBR3に対して設定します。

まずは、論理アドレス(0x8000)を0x400で割り、0x01引きます。

 0x8000/0x400-1=0x1f (0b00011111)

この値が、BBRレジスタの5-0bitの値となります。

次に物理アドレス(0xe0000)を0x400で割り、先ほどのBBRレジスタに0x01を足した値を引きます。

0xe0000/0x400-(0x1f+0x01)=0x360 (10bit= 9-0bit)(0b1101100000)

この値がBRレジスタの7-0bit(計算した結果の9-2bit)、BBRレジスタ7-6bit(計算した結果の1-0bit)の値となります

したがって、BBR、BRの値を2進で表し16進に直すと次のようになります。

BBR=0b00111110 = 0x1f
BR =0b11011000 = 0xd8

	ld	a,0x3f		;Built-in ram non set 0xfe00-0xffff
	out	(BBR4),a
	ld	a,0x1f		;MMU 0xe0000-0xe7ffff setting 0x8000
	out	(BBR3),a
;	out	(BBR2),a
;	out	(BBR1),a
	ld	a,0xf0		;mmu 0xffe00 mode0
	out	(BR4),a
	ld	a,0xd8		;mmu 0xe0000 mode0
	out	(BR3),a
;	out	(BR2),a
;	out	(BR1),a

続いて、スタックポインタを0x0000に設定したのち、シリアル通信用レジスタを初期化します。初期化した後は、オープニングメッセージを表示し、プロンプト表示したのちコマンド入力待ちになります。

        ld      sp,0x0000       ;stack pointer set
        call    com_init        ;serial channel initialize
        ld      hl,msg_op       ;opening message display
        call    msgout
prompt: ld      a,">"           ;main  routine
        call    putchar         ;prompt display
        call    getchar
        call    putchar

シリアル通信の初期化は、8ビット、ノンパリティー、1ストップビットで、RxC/TxC入力クロックを 1/16に設定しています。(38400pbs)

com_init:
	ld	a,0b01001110	;8bit NonParity 1StopBit 1/16Portrait
	out	(UART_C),a
	ld	a,0b00000101	;Rx or Tx Enable
	out	(UART_C),a	
	ret 

シリアル入出力はUART_Cをチェックした後、Aレジスタに入力データ、または、Aレジスタの内容を出力します。

getchar:
	in	a,(UART_C)	;Rx status in
	bit	1,a		;RxRdy ?
	jr	z,getchar
	in	a,(UART_D)	;Rx data in
	ret

putchar:push	af
putchar01:
	in	a,(UART_C)	;Tx status in
	bit	0,a		;TxRdy ?
	jr	z,putchar01
	pop	af
	out	(UART_D),a	;Tx data out
	ret

RAM領域をモニタで読み書きしてみました。
とりあえず、0x8000で確認。
書き換えはOKのようです。

Monitor KL5C80 CPU ver0.71  by Pinecone 2020/10/16
>?
? Help
d MemoryDump
m MemoryChange
l HexFileLoad
j jump
i I/oRegister
c Call
>d 8000
addr  +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
8000  A8 AA 55 55 55 75 AA AA A2 AA 55 55 27 54 AA AA 
>m 8000 A8 00
>m 8000 00 ff
>d 8000
addr  +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
8000  FF AA 55 55 55 75 AA AA A2 AA 55 55 27 54 AA AA 
>

以下に、ソースプログラムとHEXファイルを提示しています。
次回は、64K化RAMモニタ、およびSDCARDの読み書き、CP/Mへのブートコマンドを組み込んだモニタを作成していきたいと思います。

; KL5C80 monitor ver0.71 by Pinecone 2020/10/16
;
; KL5C80 cpu
; rom 0000h -- 7fffh
; ram fe00h -- ffffh(MMU setting)
; Clock 10MHz (ext.clock 20MHz)
;
; KL5C80 cpu mode setting
; mode: Normal mode (M1CS or M0CS Activity)
;   MODE0(27pin):H(Vcc)
;   MODE1(26pin):H(Vcc)

; serial communication
; extemal Clock 614.4KHz(4.9152MHz TC74HC4040 1/8 Frequency division)
; Band Rate:38400  8bits 1Stopbits none Parity (81N)


; assembler
;  program start 0000H
;  main          0100H
;
; assemblers  ASxxxx and ASlink V5.10
; file name KL5C80_moni.asm
; $ asz80 -l -s -o KL5C80_moni.asm
; $ aslink -i KL5C80_moni
; $ UV-EPROM writer (TL866(2)PLUS KL5C80_moni.ihx
;

        .z80
 
        .area TEST(ABS)
 
;;KL5C80 System control register

SCR0	.equ	0x3a	
SCR1	.equ	0x3b

;;KL5C80 Memory management unit

BBR1	.equ	0x00
BR1	.equ	0x01
BBR2	.equ	0x02
BR2	.equ	0x03
BBR3	.equ	0x04
BR3	.equ	0x05
BBR4	.equ	0x06
BR4	.equ	0x07

;;KL5C80 UART 

UART_D	.equ	0x38
UART_C	.equ	0x39

;;KL5C80 Parallel port B

PP2D	.equ	0x30
PP3D	.equ	0x31
PP4D	.equ	0x32
PPBC	.equ	0x33


        .org    0x0000
        jp      start
 
        .org    0x100

start:                          ;cold start

	ld	a,0b00000001	;RxC,TxC Port set
	out	(SCR0),a
	ld	a,0b00001111	;NMI,BREQ,BACK,HALT,M1 set Active mode : 1 wait set
	out	(SCR1),a

;	ld	a,0b00000011	;Parallel port B 2x OutPut Mode
;	out	(PPBC),a

	ld	a,0x3f		;Built-in ram non set 0xfe00-0xffff
	out	(BBR4),a
	ld	a,0x1f		;MMU 0xe0000-0xe7ffff setting 0x8000
	out	(BBR3),a
;	out	(BBR2),a
;	out	(BBR1),a
	ld	a,0xf0		;mmu 0xffe00 mode0
	out	(BR4),a
	ld	a,0xd8		;mmu 0xe0000 mode0
	out	(BR3),a
;	out	(BR2),a
;	out	(BR1),a


        ld      sp,0x0000       ;stack pointer set
        call    com_init        ;serial channel initialize
        ld      hl,msg_op       ;opening message display
        call    msgout
prompt: ld      a,">"           ;main  routine
        call    putchar         ;prompt display
        call    getchar
        call    putchar
        cp      "?"             ;help ?
        call    z,help
        cp      "d"             ;memory display?
        call    z,dump
        cp      "m"             ;memory rewrite ?
        call    z,memory
        cp      "l"             ;hex file load?
        call    z,loadhex       
        cp      "j"             ;address jump?
        call    z,jump
        cp	"i"		;i/o register rewite
        call	z,ioreg
        cp	"c"
        call	z,calling	;address call
        cp      0x0d
        jr	z,prompt
        cp 	0x00
        jr	z,prompt
        call	cr
        jr      prompt

help:   ld      hl,help_msg     ;help ?
        call    msgout
        ret
cr:
        ld	a,0x0d
        call	putchar
        ret

jump:                           ;address jump?
        ld      a," "
        call    putchar
        call    input_hl        ;dump address input
        cp      0x00
        jr      nz,crret
        ld      a," "
        call    putchar
        ld      a,"y"
        call    putchar
        ld      a,":"

        call    putchar
        call    getchar
        cp      "y"
        jr      nz,crret
        call    cr
        jp      (HL)       
crret:
        call    cr
        ret

calling:                         ;address call?
        ld      a," "
        call    putchar
        call    input_hl       	 ;call address input
        cp      0x00
        jr      nz,crret
        ld      a," "
        call    putchar
        ld      a,"y"
        call    putchar
        ld      a,":"
        call    putchar
        call    getchar
        cp      "y"
        jr      nz,crret
        call	cr
        ld	de,callret
        push	de
        jp	(HL)
callret:
        ret


loadhex:
        call    loadhexline     ;load 1line Hex file
        cp      0xff            ;hex file read err
        jr      z,loadhexerr
        cp      0x01            ;hex file end?
        jr      nz,loadhex
        ld      a,0x0d
        call    putchar
        ld      a,"O"
        call    putchar
        ld      a,"K"
        call    putchar
        ld      a,0x0d
        call    putchar
        ret

loadhexerr:
        ld      a,0x0d          ;hex file read skip
        call    putchar
        ld      a,"E"
        call    putchar
        ld      a,"R"
        call    putchar
        ld      a,"R"
        call    putchar
        ld      a,0x0d
        call    putchar
        ret
        
loadhexline:
        ld      a,0x0d
        call    putchar
        ld      d,0x00          ;checksum count clr
        call    getchar         ;record mark is ":"
        cp      ":"
        jr      nz,loadhexlineerr
        call    input_l         ;data size 1byte
        ld      b,l             ;checksum = checksum + data size
        ld      a,d
        add     b
        ld      d,a
        call    input_hl        ;offset address 2byte
        push    hl
        pop     ix              ;offset address HLreg >> IXreg
        ld      a,d             ;checksum = checksum + address Low      
        add     l               
        add     h               ;checksum = checksum + address Hi
        ld      d,a
        call    input_l         ;record type
        ld      a,l
        cp      0x00            ;data record
        jr      nz,checkrecord

        ;; *** data record job ****
data_hex:
        call    input_l         ;read hex 1byte in Lreg(hex)
        ld      (ix),l          ;offset address < hex data
        inc     ix              ;offset address +1
        ld      a,l
        add     d               ;cheksum Dreg = Dreg + Lreg
        ld      d,a
        djnz    data_hex        ;Breg(data size) == 0?
        call    input_l         ;chechsum OK?
        ld      a,d
        add     l
        cp      0x00
        jr      nz,loadhexlineerr
        call    getchar
        cp      0x0a            ;load 1line hex LF?
        jr      nz,loadhexlineerr
        ld      a,0x00
        ret

checkrecord:                    ;end record ?
        cp      0x01
        jr      nz,loadhexlineerr
        call    input_l
        ld      a,l
        cp      0xff
        jr      nz,loadhexlineerr
        ld      a,0x01
        ret

loadhexlineerr:
        ld      a,0xff          ;read record err (no support)
        ret     

dump:                           ;memory dump
        ld      a," "
        call    putchar
        call    input_hl        ;dump address input
        cp      0x00
        jr      z,dump1
        push    iy              ;memory dump address set
        pop     hl
dump1:
        call    dump_hl         ;memory dump
        push    hl              ;memory address IY set
        pop     iy
        ret

memory:                         ;memory change
        ld      a," "           ;space
        call    putchar         
        call    input_hl        ;change memory address 
        cp      0x00
        jr      z,memory1       ;no address hex code 
        ld      a,0x0d
        call    putchar
        ret
memory1:
        ld      a," "           ;current memory display
        call    putchar
        ld      a,(HL)
        call    hex_a_disp
        ld      a," "
        call    putchar
        push    hl
        call    input_l         ;new memory conntents input
        cp      0x00
        jr      z,memory2
        pop     hl
        xor	a
        ret
memory2:
        ld      c,l             ;memory contents update
        pop     hl
        ld      (hl),c
        ld      a,0x0d
        call    putchar
        ret

ioreg:                         ;ioreg change
        ld      a," "           ;space
        call    putchar
        call    input_l        ;change i/o register
        cp      0x00
        jr      z,ioreg1       ;no address hex code
        ld      a,0x0d
        call    putchar
        ret
ioreg1:
        ld      a," "           ;current i/o address display
        call    putchar
        ld	b,0x00
        ld	c,l
        in      a,(c)
        call    hex_a_disp
        ld      a," "
        call    putchar
        call    input_l         ;new i/o conntents address input
        cp      0x00
        jr      z,ioreg2
        xor	a
        ret
ioreg2:
        ld      a,l             ;new i/o address update
        out     (c),a
        ld      a,0x0d
        call    putchar
        ret


input_l:                        ;input Lreg hex (1byte)
        push    bc
        ld      b,0x02
        jr      input_loop

input_hl:                       ;input HLreg hex (2byte)
        push    bc
        ld      b,0x04
input_loop:
        ld      hl,0x0000       ;HL reg cler
        jr      input_hl2
shift_hl:
        add     hl,hl           ;HL reg shift left 4bit
        add     hl,hl
        add     hl,hl
        add     hl,hl
input_hl2:
        call    getchar         ;input ascii hex 1char
        call    putchar
        call    ascii_hex       ;ascii hex 1char >> Areg
        cp      0xff
        jr      z,input_hl_err
        and     0x0f            ;Areg low order 4bit >> Lreg
        or      l
        ld      l,a
        djnz    shift_hl
input_hl_end:
        pop     bc
        xor     a               ;OK >> Areg 0x00
        ret
input_hl_err:
        ld      a,0xff          ;NG >> Areg 0xff
        pop     bc
        ret

dump_hl:                        ;memory dump 1line(+0 -- +f)
        ld      a,0x0d
        call    putchar
        push    hl
        ld      hl,dump_msg     ;dump address msg output
        call    msgout
        pop     hl

        ld      a,h             ;dump address HLreg
        call    hex_a_disp      ;dump address output
        ld      a,l
        call    hex_a_disp
        ld      a," "
        call    putchar
        call    putchar
        ld      b,0x10          ;address --> address +0f
hl_disp:
        ld      a,(HL)          ;dump addres data (HL)
        inc     HL
        call    hex_a_disp
        ld      a," "
        call    putchar
        djnz    hl_disp

        ld      a,0x0d
        call    putchar
        ret

hex_a_disp:                     ;Areg(HEX) >> putchar(areg)
        push    af
        rrca                    ;7-4bit Right shift
        rrca
        rrca
        rrca
        call    hex_ascii       ;3-0bit Hex >> Hex ascii(0-F)
        call    putchar         ;7-4bit putchar
        pop     af
        call    hex_ascii       ;3-0bit Hex >> Hex ascii(0-F)
        call    putchar         ;3-0bit putchar
        ret


ascii_hex:
        sub     0x30
        jr      c,err_hex
        cp      0x0A            ;0-9
        jr      c,hex_1_9
        sub     0x11
        cp      0x06            ;A-F
        jr      c,hex_A_F
        sub     0x20
        cp      0x06            ;a-f
        jr      nc,err_hex
hex_A_F:
        add     0x0a
hex_1_9:
        ret
err_hex:ld      a,0xff
        ret

hex_ascii:                      ;Areg(HEX) >> Areg(ascii code)  
        and     a,0x0f
        cp      0x0a
        jr      c,ascii0_9
        add     0x37
        ret
ascii0_9:
        add     0x30
        ret

                        
        
msgout:
        ld      a,(hl)          ;(HL)reg is output disp at 0x00
        cp      0x00
        ret     z
        call    putchar
        inc     hl
        jr      msgout


getchar:
	in	a,(UART_C)	;Rx status in
	bit	1,a		;RxRdy ?
	jr	z,getchar
	in	a,(UART_D)	;Rx data in
	ret

putchar:push	af
putchar01:
	in	a,(UART_C)	;Tx status in
	bit	0,a		;TxRdy ?
	jr	z,putchar01
	pop	af
	out	(UART_D),a	;Tx data out
	ret

;

com_init:
	ld	a,0b01001110	;8bit NonParity 1StopBit 1/16Portrait
	out	(UART_C),a
	ld	a,0b00000101	;Rx or Tx Enable
	out	(UART_C),a	
	ret 
;


msg_op: .str    "Monitor KL5C80 CPU ver0.71  by Pinecone 2020/10/16"
        .db     0x0d
        .db     0x00
help_msg:
        .db     0x0d    
        .str    "? Help"
        .db     0x0d
        .str    "d MemoryDump"
        .db     0x0d
        .str    "m MemoryChange"
        .db     0x0d
        .str    "l HexFileLoad"
        .db     0x0d
        .str    "j jump"
        .db     0x0d
        .str	"i I/oRegister"
        .db	0x0d
        .str	"c Call"
        .db	0x0d	
        .db     0x00
dump_msg:
        .str    "addr  +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F"
        .db     0x0d
        .db     0x00

	.end

HEXファイル

:03000000C3000139
:200100003E01D33A3E0FD33B3E3FD3063E1FD3043EF0D3073ED8D305310000CD870321907F
:2001200003CD69033E3ECD7C03CD7303CD7C03FE3FCC5F01FE64CC5402FE6DCC6A02FE6C32
:20014000CCC101FE6ACC6C01FE69CC9E02FE63CC9601FE0D28CEFE0028CACD660118C521B6
:20016000C403CD6903C93E0DCD7C03C93E20CD7C03CDD902FE00201A3E20CD7C033E79CD9E
:200180007C033E3ACD7C03CD7303FE792004CD6601E9CD6601C93E20CD7C03CDD902FE00D4
:2001A00020F03E20CD7C033E79CD7C033E3ACD7C03CD7303FE7920DACD660111C001D5E946
:2001C000C9CDFB01FEFF2819FE0120F53E0DCD7C033E4FCD7C033E4BCD7C033E0DCD7C035F
:2001E000C93E0DCD7C033E45CD7C033E52CD7C033E52CD7C033E0DCD7C03C93E0DCD7C0321
:200200001600CD7303FE3A2048CDD402457A8057CDD902E5DDE17A858457CDD4027DFE0069
:200220002020CDD402DD7500DD237D825710F3CDD4027A85FE002019CD7303FE0A20123E9C
:2002400000C9FE01200BCDD4027DFEFF20033E01C93EFFC93E20CD7C03CDD902FE002803E2
:20026000FDE5E1CDFF02E5FDE1C93E20CD7C03CDD902FE0028063E0DCD7C03C93E20CD7CDC
:20028000037ECD30033E20CD7C03E5CDD402FE002803E1AFC94DE1713E0DCD7C03C93E20CC
:2002A000CD7C03CDD402FE0028063E0DCD7C03C93E20CD7C0306004DED78CD30033E20CD36
:2002C0007C03CDD402FE002802AFC97DED793E0DCD7C03C9C506021803C506042100001829
:2002E0000429292929CD7303CD7C03CD4303FEFF2809E60FB56F10E9C1AFC93EFFC1C93E36
:200300000DCD7C03E5211304CD6903E17CCD30037DCD30033E20CD7C03CD7C0306107E23A7
:20032000CD30033E20CD7C0310F43E0DCD7C03C9F50F0F0F0FCD5D03CD7C03F1CD5D03CD1A
:200340007C03C9D6303813FE0A380ED611FE063806D620FE063003C60AC93EFFC9E60FFECE
:200360000A3803C637C9C630C97EFE00C8CD7C032318F6DB39CB4F28FADB38C9F5DB39CBF2
:200380004728FAF1D338C93E4ED3393E05D339C94D6F6E69746F72204B4C3543383020439D
:2003A000505520766572302E3731202062792050696E65636F6E6520323032302F31302F56
:2003C00031360D000D3F2048656C700D64204D656D6F727944756D700D6D204D656D6F727A
:2003E000794368616E67650D6C2048657846696C654C6F61640D6A206A756D700D6920494E
:200400002F6F52656769737465720D632043616C6C0D006164647220202B30202B31202BE3
:2004200032202B33202B34202B35202B36202B37202B38202B39202B41202B42202B43203C
:0A0440002B44202B45202B460D0015
:00000001FF
おすすめの記事