rabbit2000特有の命令文に変更して、移植した「最初のモニタ」の動作を確認してみました。
最初にHelpメニューを表示してみました。
Monitor Rabbit2000 ver0.71 by Pinecone 2021/2/5
>?
? Help
d memory dump
m memory change address old new
l hex file load
j jump
i i/o register i/o-address old new
c call
>
0x8000番地からRAM領域になっているので、現状の値を読み込み、0xffに変更してみました。
>m 8000 23 00
>d 8000
addr +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
8000 00 53 63 76 25 9C A4 72 61 18 6E 1D FD 3C 6C 6D
>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 53 63 76 25 9C A4 72 61 18 6E 1D FD 3C 6C 6D
>
Data Segment Register(DATASEG=0x12)の現状値を読み込んでみました。
0x40000に設定されているので、上位8bitの0x40が設定値になります。
(変更はしないようにします。)
>i 12 40
>
LED点灯及び消灯の下記プログラムをアセンブルして、lコマンドで読み込みます。
プログラム(0xa000にコールでLED点灯、0xa100にコールでLED消灯)
; rabbit200 GOCR Port LED on/off
;
; rabbit2000 cpu
; rom 0000h -- 7fffh
; ram 8000h -- ffffh
; External clock 19.6608MHz
;
; assemblers ASxxxx and ASlink V5.10
; file name rabbit2000_led.asm
; $ asz80 -l -s -o rabbit2000_led.asm
; $ aslink -i rabbit2000_led
; $ monitor 0.71 l command load rabbit2000_led.ihx c a000 or c a100
;
.r2k
.area TEST(ABS)
;;Global Output Control Register
GOCR .equ 0x0e
.org 0xa000
LED_ON: ld a,0xc0
ioi ld (GOCR),a
ret
.org 0xa100
LED_OFF:
ld a,0x80
ioi ld (GOCR),a
ret
.end
HEXファイル
:07A000003EC0D3320E00C97F
:07A100003E80D3320E00C9BE
:00000001FF
lコマンドで呼び込んだらcコマンドでコールします。
>l
-略-
00000001FF
OK
>c a000 y:
>c a100 y:
>
0x0000にジャンプしてみます。
>j 0000 y:
Monitor Rabbit2000 ver0.71 by Pinecone 2021/2/5
>?
? Help
d memory dump
m memory change address old new
l hex file load
j jump
i i/o register i/o-address old new
c call
>
ちゃんと動作してるようです。
プログラムソースは次の通りです。
; rabbit2000 monitor ver0.71 by Pinecone 2021/2/5
;
; rabbit2000 cpu
; rom 0000h -- 7fffh
; ram 8000h -- ffffh
; External clock 19.6608MHz
; Rabbit2000 serial communication (TXA or RXA :C port)
; system Clock 38400bps
; assembler
; program start 0000H
; main 0100H
;
; assemblers ASxxxx and ASlink V5.10
; file name rabbit2000_moni071.asm
; $ asz80 -l -s -o rabbit2000_moni071.asm
; $ aslink -i rabbit2000_moni071
; $ rom-writer TL866-2 plus rabbit2000_moni071.ihx
;
.r2k
.area TEST(ABS)
;Global Control/Status Register
GCSR .equ 0x00
;;Global Output Control Register
GOCR .equ 0x0e
;;Global Clock Double Register
GCDR .equ 0x0f
;;MMU: MMU Instruction/Data Register
MMIDR .equ 0x10
;;MMU: Data Segment Register(Z180 BBR)
DATASEG .equ 0x12
;;MMU: Segment Size Register(Z180 CBAR)
SEGSIZE .equ 0x13
;;MMU: Stack Segment Register(Z180 CBR)
STACKSEG .equ 0x11
;;MMU: Memory Bank 0 Control Ragister
MB0CR .equ 0x14
;;MMU: Memory Bank 1 Control Ragister
MB1CR .equ 0x15
;;Parallel ports
;;PPA
;;Port A Data Register
PADR .equ 0x30
;;Slave Port Control Ragister
SPCR .equ 0x24
;;PPB
;;Port B Data Register
PBDR .equ 0x40
;;PPC
;;Port C Data Ragister
PCDR .equ 0x50
;;Port C Function Ragister
PCFR .equ 0x55
;;PPD
;;Port D Data Ragister
PDDR .equ 0x60
;;Port D Function Ragister
PDFR .equ 0x65
;;Port D Control Ragister
PDCR .equ 0x64
;;Port D Drive Control Ragister
PDDCR .equ 0x66
;;PPE
;;Port E Data Ragister
PEDR .equ 0x70
;;Port E Function Ragister
PEFR .equ 0x75
;;Port E Control Ragister
PECR .equ 0x74
;;Port E Data Direction Ragister
PEDDR .equ 0x77
;;Timer A
;;Timer A Control/Status Register
TACSR .equ 0xa0
;;Timer A Control Register
TACR .equ 0xa4
;;Timer A1 Constant register
TAT1R .equ 0xA3
;;Timer A4 Constant register
TAT4R .equ 0xA9
;;Serial A port
;;Serial A Port Status Register
SASR .equ 0xc3
;;Serial A port Control Register
SACR .equ 0xc4
;;Serial A port Data Register
SADR .equ 0xc0
;;Serial A port Address Register
SAAR .equ 0xc1
;;Serial A port Long Register
SALR .equ 0xc2
;;Watchdog Timer
;;Watchdog Timer Control Register
WDTCR .equ 0x08
;;Watchdog Timer Test Register
WDTTR .equ 0x09
.org 0x0000
jp start
.org 0x0080
start:
ld a,0b00001000 ;proc=OSC,pclk=osc,periodic interrupt=disable
ioi ld (GCSR),a
; ld a,0x03 ;main clock 19.6608MHz set 3
; ioi ld (GCDR),a
ld a,0x00
ioi ld (MB0CR),a ;0x000000 Use /OE0 Use CS0 (ROM)
ld a,0b00000101
ioi ld (MB1CR),a ;0x400000 Use /OE1 or /WE1 Use CS1 (RAM)
;
ld a,0x01 ;PCLK/2 Timer A Enabled
ioi ld (TACSR),a
ld a,0b00000000 ;Timer A4~A7 Clocked by PCLK/2,interrupts disabled
ioi ld (TACR),a
ld a,0x0f ;PCLK/2/16/38400-1 (19.6608MHz >> 38400bps)
ioi ld (TAT4R),a
ld a,0x00 ;Watchdog timer no effect
ioi ld (WDTCR),a
ld a,0x53 ;Watchdog timer disable
ioi ld (WDTTR),a
ld a,0x54
ioi ld (WDTTR),a
ld a,0x40 ;MMU Data Reg Physics address 0x40000 (CS1)
ioi ld (DATASEG),a
ld a,0x40 ;MMU Stack Reg Physics address 0x40000 (CS1)
ioi ld (STACKSEG),a
ld a,0xa8 ;MMU Segsize logic Data address 0x8000 (CS1:0x48000)
ioi ld (SEGSIZE),a ;MMU Segsize logic Stack address 0xa000 (CS1:0x4a000)
ld a,0x40 ;MMU XPC Physics address 0x40000 (CS1:0x4e000)
ld xpc,a
ld a,0b00000100
ioi ld (SPCR),a ;A Port Bytewide Output
jp main
.org 0x100
main: ;cold start
ld sp,0xe000 ;stack pointer set
call ppi_init ;parallel ports initialize
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 ?
jr nz,prompt01
call help
prompt01:
cp "d" ;memory display?
jr nz,prompt02
call dump
prompt02:
cp "m" ;memory rewrite ?
jr nz,prompt03
call memory
prompt03:
cp "l" ;hex file load?
jr nz,prompt04
call loadhex
prompt04:
cp "j" ;address jump?
jr nz,prompt05
call jump
prompt05:
cp "i" ;i/o register rewite
jr nz,prompt06
call ioreg
prompt06:
cp "c"
jr nz,prompt07
call calling ;address call
prompt07:
cp 0x0d
jr z,prompt
cp 0x00
jr z,prompt
call cr
jr prompt
help: ld hl,help_msg ;help ?
call msgout
ret
cr:
push af
ld a,0x0d
call putchar
pop af
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
ioi ld a,(bc)
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
ioi ld (bc),a
ld a,0x0d
call putchar
ret
input_l: ;input Lreg hex (1byte)
push bc
ld b,0x02
jr input_prompt
input_hl: ;input HLreg hex (2byte)
push bc
ld b,0x04
input_prompt:
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
putchar:
push af
putchar01:
ioi ld a,(SASR) ;Serial A port Status in
bit 3,a
jr nz,putchar01 ;XMIT DATA REG > Full(bit3==1) check
pop af
push af
ioi ld (SADR),a ;no full(Empty) >> TxA data out
putchar_busy:
ioi ld a,(SASR) ;Serial A port Status in
bit 3,a ;XMIT DATA REG > Full(bit3==1) check
jr nz,putchar_busy
pop af ;no full(Empty) >> return
ret
getchar:
ioi ld a,(SASR) ;Serial A port Status in
bit 7,a ;RCV DATA REG > EMPTY(bit7==0) check
jr z,getchar
ioi ld a,(SADR) ;No EMPTY(Full) > RxA data in
push af
getchar01:
ioi ld a,(SASR) ;Serial A port Status in
bit 7,a ;RCV DATA REG >EMPTY(bit7==0) check
jr nz,getchar01
pop af ;EMPTY >> return
ret
ppi_init:
ld a,0x40
ioi ld (PCFR),a ;C Port TxA set
ld a,0x00
ioi ld (PDFR),a ;D Port Bit Normally as I/O
ld a,0x00
ioi ld (PEFR),a ;E Port Bit Normally as I/O
ret
com_init:
ld a,0b00000000
ioi ld (SACR),a ;Asynch mode, C port used, 8bit, Interrupt Disabled
ld a,0b00010000
ioi ld (PDCR),a ;TxA Clock Timer A1
ret
msg_op: .str "Monitor Rabbit2000 ver0.71 by Pinecone 2021/2/5"
.db 0x0d
.db 0x00
help_msg:
.db 0x0d
.str "? Help"
.db 0x0d
.str "d memory dump"
.db 0x0d
.str "m memory change address old new"
.db 0x0d
.str "l hex file load"
.db 0x0d
.str "j jump"
.db 0x0d
.str "i i/o register i/o-address old new"
.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ファイルです。
:03000000C38000BA
:200080003E08D33200003E00D33214003E05D33215003E01D332A0003E00D332A4003E0F49
:2000A000D332A9003E00D33208003E53D33209003E54D33209003E40D33212003E40D332F0
:1500C00011003EA8D33213003E40ED673E04D3322400C300011B
:200100003100E0CD9E03CDB10321BE03CD64033E3ECD6E03CD8703CD6E03FE3F2003CD58F5
:2001200001FE642003CD4F02FE6D2003CD6502FE6C2003CDBC01FE6A2003CD6701FE6920FB
:2001400003CD9902FE632003CD9101FE0D28C0FE0028BCCD5F0118B721F003CD6403C9F57A
:200160003E0DCD6E03F1C93E20CD6E03CDD402FE00201A3E20CD6E033E79CD6E033E3ACDEF
:200180006E03CD8703FE792004CD5F01E9CD5F01C93E20CD6E03CDD402FE0020F03E20CD78
:2001A0006E033E79CD6E033E3ACD6E03CD8703FE7920DACD5F0111BB01D5E9C9CDF601FE18
:2001C000FF2819FE0120F53E0DCD6E033E4FCD6E033E4BCD6E033E0DCD6E03C93E0DCD6ED8
:2001E000033E45CD6E033E52CD6E033E52CD6E033E0DCD6E03C93E0DCD6E031600CD870357
:20020000FE3A2048CDCF02457A8057CDD402E5DDE17A858457CDCF027DFE002020CDCF02F3
:20022000DD7500DD237D825710F3CDCF027A85FE002019CD8703FE0A20123E00C9FE012088
:200240000BCDCF027DFEFF20033E01C93EFFC93E20CD6E03CDD402FE002803FDE5E1CDFA58
:2002600002E5FDE1C93E20CD6E03CDD402FE0028063E0DCD6E03C93E20CD6E037ECD2B031E
:200280003E20CD6E03E5CDCF02FE002803E1AFC94DE1713E0DCD6E03C93E20CD6E03CDCF94
:2002A00002FE0028063E0DCD6E03C93E20CD6E0306004DD30ACD2B033E20CD6E03CDCF02BD
:2002C000FE002802AFC97DD3023E0DCD6E03C9C506021803C5060421000018042929292942
:2002E000CD8703CD6E03CD3E03FEFF2809E60FB56F10E9C1AFC93EFFC1C93E0DCD6E03E5AD
:20030000217404CD6403E17CCD2B037DCD2B033E20CD6E03CD6E0306107E23CD2B033E2056
:20032000CD6E0310F43E0DCD6E03C9F50F0F0F0FCD5803CD6E03F1CD5803CD6E03C9D6306C
:200340003813FE0A380ED611FE063806D620FE063003C60AC93EFFC9E60FFE0A3803C637DA
:20036000C9C630C97EFE00C8CD6E032318F6F5D33AC300CB5F20F8F1F5D332C000D33AC3C0
:2003800000CB5F20F8F1C9D33AC300CB7F28F8D33AC000F5D33AC300CB7F20F8F1C93E40FB
:2003A000D33255003E00D33265003E00D3327500C93E00D332C4003E10D3326400C94D6F77
:2003C0006E69746F72205261626269743230303020766572302E3731202062792050696E26
:2003E00065636F6E6520323032312F322F350D000D3F202048656C700D6420206D656D6FC8
:2004000072792064756D700D6D20206D656D6F7279206368616E67652020206164647265E2
:200420007373206F6C64206E65770D6C20206865782066696C65206C6F61640D6A20206A6E
:20044000756D700D692020692F6F20726567697374657220202020692F6F2D616464726554
:200460007373206F6C64206E65770D63202063616C6C0D006164647220202B30202B3120A2
:200480002B32202B33202B34202B35202B36202B37202B38202B39202B41202B42202B43D1
:0B04A000202B44202B45202B460D0094
:00000001FF
次回は、rabbit2000特有のコマンドを追加していきたいと思います。