From ad7428e471bfff1b81742dda3eb86ccb544b41fd Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Fri, 17 May 2019 14:58:16 -0400 Subject: [PATCH] zasm: make io unit handle PC and output suppression --- apps/zasm/instr.asm | 4 ++-- apps/zasm/io.asm | 25 +++++++++++++++++++++++-- apps/zasm/main.asm | 32 +++++++------------------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/apps/zasm/instr.asm b/apps/zasm/instr.asm index 7b6fb95..171f987 100644 --- a/apps/zasm/instr.asm +++ b/apps/zasm/instr.asm @@ -634,7 +634,7 @@ getUpcode: bit 7, (ix+3) jr z, .absoluteValue ; bit not set? regular byte value, ; Our argument is a relative address ("e" type in djnz and jr). We have - ; to subtract (ZASM_PC) from it. + ; to subtract (IO_PC) from it. ; First, check whether we're on first pass. If we are, skip processing ; below because not having real symbol value makes relative address @@ -645,7 +645,7 @@ getUpcode: ; We're on second pass push de ; Don't let go of this, that's our dest - ld de, (ZASM_PC) + ld de, (IO_PC) call intoHL dec hl ; what we write is "e-2" dec hl diff --git a/apps/zasm/io.asm b/apps/zasm/io.asm index 7fca734..c9bee13 100644 --- a/apps/zasm/io.asm +++ b/apps/zasm/io.asm @@ -4,6 +4,9 @@ ; parameter, two blockdevs: One that we can read and seek and one that we can ; write to (we never seek into it). ; +; This unit also has the responsibility of counting the number of written bytes, +; maintaining IO_PC and of properly disabling output on first pass. +; ; zasm doesn't buffers its reads during tokenization, which simplifies its ; process. However, it also means that it needs, in certain cases, a "putback" ; mechanism, that is, a way to say "you see that character I've just read? that @@ -47,7 +50,8 @@ ; see ioPutBack below .equ IO_PUTBACK_BUF IO_INCLUDE_HDL+FS_HANDLE_SIZE .equ IO_IN_INCLUDE IO_PUTBACK_BUF+1 -.equ IO_RAMEND IO_IN_INCLUDE+1 +.equ IO_PC IO_IN_INCLUDE+1 +.equ IO_RAMEND IO_PC+2 ; *** Code *** @@ -55,7 +59,7 @@ ioInit: xor a ld (IO_PUTBACK_BUF), a ld (IO_IN_INCLUDE), a - ret + jp ioResetPC ioGetC: ld a, (IO_PUTBACK_BUF) @@ -101,8 +105,20 @@ ioPutBack: ret ioPutC: + push hl + ld hl, (IO_PC) + inc hl + ld (IO_PC), hl + pop hl + push af + call zasmIsFirstPass + jr z, .skip + pop af ld ix, (IO_OUT_PUTC) jp (ix) +.skip: + pop af + ret ioSavePos: call _ioTell @@ -117,6 +133,11 @@ ioRewind: ld hl, 0 jr _ioSeek +ioResetPC: + ld hl, 0 + ld (IO_PC), hl + ret + ; always in absolute mode (A = 0) _ioSeek: call ioInInclude diff --git a/apps/zasm/main.asm b/apps/zasm/main.asm index d538298..c1e2a8f 100644 --- a/apps/zasm/main.asm +++ b/apps/zasm/main.asm @@ -43,13 +43,11 @@ ; that when we parse instructions and directive that error out because of a ; missing symbol, we don't error out and just write down a dummy value. .equ ZASM_FIRST_PASS RAMSTART -; The offset where we currently are with regards to outputting opcodes -.equ ZASM_PC ZASM_FIRST_PASS+1 ; whether we're in "local pass", that is, in local label scanning mode. During ; this special pass, ZASM_FIRST_PASS will also be set so that the rest of the ; code behaves as is we were in the first pass. -.equ ZASM_LOCAL_PASS ZASM_PC+2 -; What ZASM_PC was when we started our context +.equ ZASM_LOCAL_PASS ZASM_FIRST_PASS+1 +; What IO_PC was when we started our context .equ ZASM_CTX_PC ZASM_LOCAL_PASS+1 .equ ZASM_RAMEND ZASM_CTX_PC+2 @@ -109,21 +107,11 @@ zasmIsLocalPass: cp 1 ret -; Increase (ZASM_PC) by A -incOutputOffset: - push de - ld de, (ZASM_PC) - call addDE - ld (ZASM_PC), de - pop de - ret - ; Repeatedly reads lines from IO, assemble them and spit the binary code in ; IO. Z is set on success, unset on error. DE contains the last line number to ; be read (first line is 1). zasmParseFile: - ld de, 0 - ld (ZASM_PC), de + call ioResetPC .loop: call parseLine ret nz ; error @@ -142,7 +130,7 @@ zasmParseFile: ret ; Parse next token and accompanying args (when relevant) in I/O, write the -; resulting opcode(s) through ioPutC and increases (ZASM_PC) by the number of +; resulting opcode(s) through ioPutC and increases (IO_PC) by the number of ; bytes written. BC is set to the result of the call to tokenize. ; Sets Z if parse was successful, unset if there was an error. EOF is not an ; error. @@ -166,9 +154,6 @@ _parseInstr: or a ; is zero? jr z, .error ld b, a ; save output byte count - call incOutputOffset - call zasmIsFirstPass - jr z, .success ; first pass, nothing to write ld hl, instrUpcode .loopInstr: ld a, (hl) @@ -189,9 +174,6 @@ _parseDirec: or a ; cp 0 jr z, .success ; if zero, shortcut through ld b, a ; save output byte count - call incOutputOffset - call zasmIsFirstPass - jr z, .success ; first pass, nothing to write ld hl, direcData .loopDirec: ld a, (hl) @@ -233,7 +215,7 @@ _parseLabel: call _endLocalPass jr .success .registerLabel: - ld de, (ZASM_PC) + ld de, (IO_PC) call symRegister jr nz, .error ; continue to .success @@ -248,7 +230,7 @@ _beginLocalPass: ; remember were I/O was call ioSavePos ; Remember where PC was - ld hl, (ZASM_PC) + ld hl, (IO_PC) ld (ZASM_CTX_PC), hl ; Fake first pass ld a, 1 @@ -268,7 +250,7 @@ _endLocalPass: call ioRecallPos ; recall PC ld hl, (ZASM_CTX_PC) - ld (ZASM_PC), hl + ld (IO_PC), hl ; unfake first pass xor a ld (ZASM_FIRST_PASS), a