From: Will Sowerbutts Date: Sat, 17 Jan 2015 12:15:24 +0000 (+0000) Subject: Kernel: Simple monitor program for Z80 and Z180, useful for inspecting X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=971aa930bdf1e266527fbb4e99e926d68de20778;p=FUZIX.git Kernel: Simple monitor program for Z80 and Z180, useful for inspecting machine state. Platform must provide an "inchar" routine which waits for a character on the console and returns it in A. This patch also implements the monitor on the p112 and n8vem-mark4 platforms. --- diff --git a/Kernel/lib/monitor-z80.s b/Kernel/lib/monitor-z80.s new file mode 100644 index 00000000..75fa047f --- /dev/null +++ b/Kernel/lib/monitor-z80.s @@ -0,0 +1,286 @@ +; 2015-01-15 William R Sowerbutts +; A simple Z80 monitor program, mainly useful for inspecting machine state +; +; Based on the the socz80 ROM monitor program, and the UZI-180 monitor +; program, itself based on YM.MAC and M580 monitor. +; +; Commands: +; D arg1 [arg2] - display memory at address arg1 (to arg2) +; I arg1 - input from port address arg1 +; O arg1 arg2 - output arg2 to port address arg1 + + .module monitor-z80 + .z80 + + ; exported symbols + .globl _trap_monitor + + ; imported symbols + .globl inchar + .globl outchar + .globl outcharhex + .globl outhl + .globl outnewline + .globl outstring + + .area _COMMONMEM + +; expect to arrive here with return PC on stack +_trap_monitor: di ; turn off pesky interrupts + ld hl, #0 + add hl, sp ; save SP + pop bc ; save PC + ld sp, #monitor_stack + push bc ; orig PC + ex de,hl ; orig SP -> DE + ld hl, #entrystr1 + call outstring + ex de,hl ; orig SP -> HL + call outhl + ld hl, #entrystr2 + call outstring + pop hl + call outhl +monitor_loop: call outnewline + ld hl, #prompt + call outstring + ld hl, #linebuffer + ld b, #(linebuffer_end-linebuffer) ; length + call instring + call outnewline + call parse_args + ld hl, #monitor_loop + push hl ; return address + ld hl,(arg1) + ld de,(arg2) + ;ld bc,(arg3) + ld a, (linebuffer) + cp #'D' + jr z, dump + cp #'I' + jp z, inport + cp #'O' + jp z, outport +badinput: ld a, #'?' + jp outchar ; ret back to monitor_loop + +parse_args: ld hl, #0 + ld (arg1), hl + ld (arg2), hl + ;ld (arg3), hl + ld de, #linebuffer+1 + call gethex + ld (arg1), hl + ld (arg2), hl + ret c + call gethex + ld (arg2), hl + ret c + ;call gethex + ;ld (arg3), hl + ;ret c + ; more?! + jr badinput + +; D addr1,addr2 +; Dump region addr1...addr2 + +dump: call out_addr + push hl +dmph: ld a,(hl) + call outbyte + call hl_eq_de + jr z,enddmp + inc hl + ld a,l + and #0x0F + jr nz,dmph + pop hl + call dumpl + jr dump +enddmp: pop hl +dumpl: ld a,#'|' + call outchar + ld a,#' ' + call outchar +dumpln: ld a,(hl) + cp #0x20 + jr c,outdot + cp #0x7f + jr c,char +outdot: ld a,#'.' +char: call outchar + call hl_eq_de + ret z + inc hl + ld a,l + and #0x0F + jr nz,dumpln + ret + +hl_eq_de: ld a,h + cp d + ret nz + ld a,l + cp e + ret + +; I port +; Input from port + +inport: push hl + ld a,l + call outcharhex + ld a,#'=' + call outchar + pop hl + ld c,l + ld b,h + in a,(c) + call outcharhex + ret + +; O port,byte +; Output to port + +outport: ld c,l + ld b,h + ld a,e + out (c),a + ret + +out_addr: call outnewline + call outhl + ld a,#':' + call outchar + ld a,#' ' + jp outchar + +outbyte: call outcharhex + ld a,#' ' + jp outchar + +;cmd_debug: +; ld hl, (arg1) +; call outhl +; call outnewline +; ld hl, (arg2) +; call outhl +; call outnewline +; ld hl, (arg3) +; call outhl +; call outnewline +; jp monitor_loop + + +; parse 16-bit hex number at (DE) into HL +; return with carry flag set if end of string +gethex: ld hl,#0 +ghskip: ld a,(de) + cp #' ' + jr nz, gh1 + inc de + jr ghskip +gh1: ld a,(de) + inc de + or a + jp z,aend + cp #',' + ret z + cp #' ' + ret z + sub #'0' + jp m,badinput + cp #10 + jp m,dig + cp #0x11 + jp m,badinput + cp #0x17 + jp p,badinput + sub #7 +dig: ld c,a + ld b,#0 + add hl,hl + add hl,hl + add hl,hl + add hl,hl + jp c,badinput + add hl,bc + jp gh1 +aend: scf + ret + +; instring (from socz80, added buffer length checking, added case conversion) +; reads a string from terminal to memory. HL=buffer address, B=buffer length. +; Returns length of string (excluding 0 terminator) in C +instring: ld c, #0 ; we use C to remember our string length +instringloop: call inchar + ; test for cr/lf + cp #0x0d + jr z, cr + cp #0x0a + jr z, cr + ; test for backspace + cp #0x08 + jr z, backspace + cp #0x7f + jr z, backspace + ; test for non-printing characters + cp #0x20 ; < 0x20? + jp c, instringloop + cp #0x7e ; > 0x7e? + jp nc, instringloop + cp #'a' + jr c, storechar + cp #'z'+1 + jr nc, storechar + and #0x5f ; uppercase: characters from a-z are now A-Z +storechar: ; store the character in the buffer + ld (hl), a + inc hl + inc c + call outchar ; echo back the character typed + ; test buffer length + ld a, c + sub b + jr nz, instringloop ; space remains - next character + ld a, #7 + call outchar ; ring the bell + ; buffer full - fall through to backspace +backspace: ld a, c + cp #0 + jr z, instringloop ; cannot backspace past the start + dec hl + dec c + ld a, #0x08 ; move back + call outchar + ld a, #0x20 ; print space + call outchar + ld a, #0x08 ; move back again + call outchar + jr instringloop +cr: ld a, #0 + ld (hl), a + ret + + +; strings +entrystr1: .ascii "monitor: SP=" + .db 0 +entrystr2: .ascii ", PC=" + .db 0 +prompt: .ascii ":( " + .db 0 + +; arguments +arg1: .ds 2 +arg2: .ds 2 +;arg3: .ds 2 + +; input buffer +linebuffer: .ds 20 +linebuffer_end: + +; stack + .ds 40 +monitor_stack: diff --git a/Kernel/platform-n8vem-mark4/Makefile b/Kernel/platform-n8vem-mark4/Makefile index 84942f99..bfde7f22 100644 --- a/Kernel/platform-n8vem-mark4/Makefile +++ b/Kernel/platform-n8vem-mark4/Makefile @@ -1,6 +1,6 @@ CSRCS += devices.c main.c devtty.c devsdspi.c DSRCS = ../dev/devide.c ../dev/devsd.c ../dev/mbr.c ../dev/blkdev.c ../dev/ds1302.c -ASRCS = crt0.s z180.s commonmem.s mark4.s ds1302-mark4.s +ASRCS = crt0.s z180.s commonmem.s mark4.s ds1302-mark4.s monitor.s AOBJS = $(ASRCS:.s=.rel) COBJS = $(CSRCS:.c=.rel) diff --git a/Kernel/platform-n8vem-mark4/fuzix.lnk b/Kernel/platform-n8vem-mark4/fuzix.lnk index dcce1857..37a10c91 100644 --- a/Kernel/platform-n8vem-mark4/fuzix.lnk +++ b/Kernel/platform-n8vem-mark4/fuzix.lnk @@ -39,4 +39,5 @@ platform-n8vem-mark4/mbr.rel platform-n8vem-mark4/blkdev.rel platform-n8vem-mark4/ds1302.rel platform-n8vem-mark4/ds1302-mark4.rel +platform-n8vem-mark4/monitor.rel -e diff --git a/Kernel/platform-n8vem-mark4/kernel.def b/Kernel/platform-n8vem-mark4/kernel.def index cabb2a9a..96be4779 100644 --- a/Kernel/platform-n8vem-mark4/kernel.def +++ b/Kernel/platform-n8vem-mark4/kernel.def @@ -13,4 +13,5 @@ Z180_IO_BASE .equ 0x40 MARK4_IO_BASE .equ 0x80 ; No standard clock speed for the Mark IV board, but this is a common choice. +USE_FANCY_MONITOR .equ 1 ; disabling this saves around approx 0.5KB CPU_CLOCK_KHZ .equ 36864 ; 18.432MHz * 2 diff --git a/Kernel/platform-n8vem-mark4/mark4.s b/Kernel/platform-n8vem-mark4/mark4.s index f10b51ef..7043e8dc 100644 --- a/Kernel/platform-n8vem-mark4/mark4.s +++ b/Kernel/platform-n8vem-mark4/mark4.s @@ -7,10 +7,9 @@ ; exported symbols .globl init_early .globl init_hardware + .globl inchar .globl outchar - .globl outcharhex .globl platform_interrupt_all - .globl _trap_monitor ; imported symbols .globl z180_init_hardware @@ -75,26 +74,14 @@ ocloop: in0 a, (ASCI_STAT0) pop bc ret -platform_interrupt_all: +; inchar: Wait for character on UART, return in A +; destroys: AF +inchar: + in0 a, (ASCI_STAT0) + rlca + jr nc, inchar + in0 a, (ASCI_RDR0) ret -_trap_monitor: - di - call outnewline - pop hl - call outhl - call outnewline - pop hl - call outhl - call outnewline - pop hl - call outhl - call outnewline - pop hl - call outhl - call outnewline - pop hl - call outhl - call outnewline - halt - jr _trap_monitor +platform_interrupt_all: + ret diff --git a/Kernel/platform-n8vem-mark4/monitor.s b/Kernel/platform-n8vem-mark4/monitor.s new file mode 100644 index 00000000..656d6506 --- /dev/null +++ b/Kernel/platform-n8vem-mark4/monitor.s @@ -0,0 +1,24 @@ +; 2015-01-17 William R Sowerbutts + .module monitor + .include "kernel.def" + +.ifne USE_FANCY_MONITOR + .include "../lib/monitor-z80.s" +.else + .globl outchar + .globl outnewline + .globl outhl + .globl _trap_monitor + + ; micro monitor - + ; just dumps a few words from the stack +_trap_monitor: di + call outnewline + ld b, #50 +stacknext: pop hl + call outhl + ld a, #' ' + call outchar + djnz stacknext + halt +.endif diff --git a/Kernel/platform-p112/Makefile b/Kernel/platform-p112/Makefile index 9f195fd4..03e76567 100644 --- a/Kernel/platform-p112/Makefile +++ b/Kernel/platform-p112/Makefile @@ -1,6 +1,6 @@ CSRCS += devices.c main.c devtty.c DSRCS = ../dev/blkdev.c ../dev/devide.c ../dev/mbr.c ../dev/ds1302.c -ASRCS = crt0.s z180.s commonmem.s p112.s ds1302-p112.s +ASRCS = crt0.s z180.s commonmem.s p112.s ds1302-p112.s monitor.s AOBJS = $(ASRCS:.s=.rel) COBJS = $(CSRCS:.c=.rel) diff --git a/Kernel/platform-p112/fuzix.lnk b/Kernel/platform-p112/fuzix.lnk index 00fe4cfc..880d89fd 100644 --- a/Kernel/platform-p112/fuzix.lnk +++ b/Kernel/platform-p112/fuzix.lnk @@ -37,4 +37,5 @@ platform-p112/blkdev.rel platform-p112/mbr.rel platform-p112/ds1302.rel platform-p112/ds1302-p112.rel +platform-p112/monitor.rel -e diff --git a/Kernel/platform-p112/kernel.def b/Kernel/platform-p112/kernel.def index 024c6b08..4bf522f7 100644 --- a/Kernel/platform-p112/kernel.def +++ b/Kernel/platform-p112/kernel.def @@ -13,4 +13,5 @@ Z80_TYPE .equ 2 ; Believe most P112 kits shipped with 16MHz oscillators, I have tried faster ; (18.432MHz) but this made the machine unstable. +USE_FANCY_MONITOR .equ 1 ; disabling this saves around 0.5KB CPU_CLOCK_KHZ .equ 16000 ; 16MHz is the stock crystal diff --git a/Kernel/platform-p112/monitor.s b/Kernel/platform-p112/monitor.s new file mode 100644 index 00000000..656d6506 --- /dev/null +++ b/Kernel/platform-p112/monitor.s @@ -0,0 +1,24 @@ +; 2015-01-17 William R Sowerbutts + .module monitor + .include "kernel.def" + +.ifne USE_FANCY_MONITOR + .include "../lib/monitor-z80.s" +.else + .globl outchar + .globl outnewline + .globl outhl + .globl _trap_monitor + + ; micro monitor - + ; just dumps a few words from the stack +_trap_monitor: di + call outnewline + ld b, #50 +stacknext: pop hl + call outhl + ld a, #' ' + call outchar + djnz stacknext + halt +.endif diff --git a/Kernel/platform-p112/p112.s b/Kernel/platform-p112/p112.s index 3af2fe6c..c27ca19d 100644 --- a/Kernel/platform-p112/p112.s +++ b/Kernel/platform-p112/p112.s @@ -7,6 +7,7 @@ ; exported symbols .globl init_early .globl init_hardware + .globl inchar .globl outchar .globl outstring .globl outcharhex @@ -99,26 +100,13 @@ ocloop: in0 a, (ESCC_CTRL_A) pop bc ret -platform_interrupt_all: +; inchar: Wait for character on UART, return in A +inchar: + in0 a, (ESCC_CTRL_A) ; bit 0 is "rx ready" (1=ready) + rrca + jr nc, inchar + in0 a, (ESCC_DATA_A) ret -_trap_monitor: - di - call outnewline - pop hl - call outhl - call outnewline - pop hl - call outhl - call outnewline - pop hl - call outhl - call outnewline - pop hl - call outhl - call outnewline - pop hl - call outhl - call outnewline - halt - jr _trap_monitor +platform_interrupt_all: + ret