It always reads in the scratchpad with the same max size. No need for DE-dancing anymore.pull/10/head
@@ -17,11 +17,8 @@ directiveHandlers: | |||
.dw handleDW | |||
handleDB: | |||
push de | |||
push hl | |||
call toWord | |||
ld de, scratchpad | |||
ld a, 8 | |||
call readWord | |||
ld hl, scratchpad | |||
call parseNumber | |||
@@ -29,15 +26,11 @@ handleDB: | |||
ld (direcData), a | |||
ld a, 1 | |||
pop hl | |||
pop de | |||
ret | |||
handleDW: | |||
push de | |||
push hl | |||
call toWord | |||
ld de, scratchpad | |||
ld a, 8 | |||
call readWord | |||
ld hl, scratchpad | |||
call parseNumber | |||
@@ -47,7 +40,6 @@ handleDW: | |||
ld (direcData+1), a | |||
ld a, 2 | |||
pop hl | |||
pop de | |||
ret | |||
; Reads string in (HL) and returns the corresponding ID (D_*) in A. Sets Z if | |||
@@ -8,5 +8,5 @@ libz80/libz80.o: libz80/z80.c | |||
kernel.h: glue.asm | |||
scas -o - -I ../../../parts/z80 $< | ./bin2c.sh KERNEL | tee $@ > /dev/null | |||
zasm.h: $(addprefix ../, main.asm instr.asm directive.asm tok.asm literal.asm util.asm) | |||
zasm.h: $(addprefix ../, main.asm instr.asm directive.asm tok.asm parse.asm literal.asm util.asm) | |||
scas -o - -I.. $< | ./bin2c.sh ZASM | tee $@ > /dev/null |
@@ -688,17 +688,11 @@ getUpcode: | |||
; Parse next argument in string (HL) and place it in (DE) | |||
; Sets Z on success, reset on error. | |||
processArg: | |||
push de | |||
call toWord | |||
xor a | |||
ld de, scratchpad | |||
ld (de), a | |||
ld a, 8 | |||
call readWord | |||
pop de | |||
; Read word is in scratchpad, (DE) is back to initial value, HL is | |||
; properly advanced. Now, let's push that HL value and replace it with | |||
; (scratchpad) so that we can parse that arg. | |||
; Read word is in scratchpad, HL is properly advanced. Now, let's push | |||
; that HL value and replace it with (scratchpad) so that we can parse | |||
; that arg. | |||
push hl | |||
ld hl, scratchpad | |||
@@ -20,6 +20,7 @@ main: | |||
ret | |||
#include "util.asm" | |||
#include "parse.asm" | |||
#include "literal.asm" | |||
#include "instr.asm" | |||
#include "tok.asm" | |||
@@ -76,6 +77,3 @@ parseLine: | |||
pop bc | |||
ret | |||
; *** Variables *** | |||
scratchpad: | |||
.fill 0x20 |
@@ -0,0 +1,128 @@ | |||
; *** Consts *** | |||
.equ SCRATCHPAD_SIZE 0x20 | |||
; *** Variables *** | |||
scratchpad: | |||
.fill SCRATCHPAD_SIZE | |||
; *** Code *** | |||
; Sets Z is A is ';', CR, LF, or null. | |||
isLineEndOrComment: | |||
cp ';' | |||
ret z | |||
; Continues onto isLineEnd... | |||
; Sets Z is A is CR, LF, or null. | |||
isLineEnd: | |||
or a ; same as cp 0 | |||
ret z | |||
cp 0x0d | |||
ret z | |||
cp 0x0a | |||
ret | |||
; Sets Z is A is ' ' '\t' or ',' | |||
isSep: | |||
cp ' ' | |||
ret z | |||
cp 0x09 | |||
ret z | |||
cp ',' | |||
ret | |||
; Sets Z is A is ' ', ',', ';', CR, LF, or null. | |||
isSepOrLineEnd: | |||
call isSep | |||
ret z | |||
call isLineEndOrComment | |||
ret | |||
; read word in (HL) and put it in (scratchpad), null terminated, for a maximum | |||
; of SCRATCHPAD_SIZE-1 characters. As a result, A is the read length. HL is | |||
; advanced to the next separator char. | |||
readWord: | |||
push bc | |||
push de | |||
ld de, scratchpad | |||
ld b, SCRATCHPAD_SIZE-1 | |||
.loop: | |||
ld a, (hl) | |||
call isSepOrLineEnd | |||
jr z, .success | |||
call JUMP_UPCASE | |||
ld (de), a | |||
inc hl | |||
inc de | |||
djnz .loop | |||
.success: | |||
xor a | |||
ld (de), a | |||
ld a, SCRATCHPAD_SIZE-1 | |||
sub a, b | |||
.end: | |||
pop de | |||
pop bc | |||
ret | |||
; (HL) being a string, advance it to the next non-sep character. | |||
; Set Z if we could do it before the line ended, reset Z if we couldn't. | |||
toWord: | |||
.loop: | |||
ld a, (hl) | |||
call isLineEndOrComment | |||
jr z, .error | |||
call isSep | |||
jr nz, .success | |||
inc hl | |||
jr .loop | |||
.error: | |||
call JUMP_UNSETZ | |||
ret | |||
.success: | |||
xor a ; ensure Z | |||
ret | |||
; Advance HL to the beginning of the next line, that is, right after the next | |||
; 0x10 or 0x13 or both. If we reach null, we stop and error out. | |||
; Sets Z on success, unsets it on error. | |||
gotoNextLine: | |||
dec hl ; a bit weird, but makes the looping easier | |||
.loop: | |||
inc hl | |||
ld a, (hl) | |||
call isLineEnd | |||
jr nz, .loop | |||
; (HL) is 0x10, 0x13 or 0 | |||
or a ; is 0? | |||
jr z, .error | |||
; we might have 0x13 followed by 0x10, let's account for this. | |||
; Yes, 0x10 followed by 0x10 will make us skip two lines, but this is of | |||
; no real consequence in our context. | |||
inc hl | |||
ld a, (hl) | |||
call isLineEnd | |||
jr nz, .success | |||
or a ; is 0? | |||
jr z, .error | |||
; There was another line sep. Skip this char | |||
inc hl | |||
; Continue on to .success | |||
.success: | |||
xor a ; ensure Z | |||
ret | |||
.error: | |||
call JUMP_UNSETZ | |||
ret | |||
; Repeatedly calls gotoNextLine until the line in (HL) points to a line that | |||
; isn't blank or 100% comment. Sets Z if we reach a line, Unset Z if we reach | |||
; EOF | |||
gotoNextNotBlankLine: | |||
call toWord | |||
ret z ; Z set? we have a not-blank line | |||
; Z not set? (HL) is at the end of the line or at the beginning of | |||
; comments. | |||
call gotoNextLine | |||
ret nz | |||
jr gotoNextNotBlankLine | |||
@@ -1,7 +1,3 @@ | |||
; tok | |||
; | |||
; Tokenizes an ASM source file into 1, 2 or 3-sized structures. | |||
; | |||
; *** Requirements *** | |||
; JUMP_UPCASE | |||
@@ -17,10 +13,7 @@ TOK_BAD .equ 0xff | |||
; Advance HL to after the read word. | |||
; If no token matches, TOK_BAD is written to B | |||
tokenize: | |||
push de | |||
call toWord | |||
ld a, 4 | |||
ld de, scratchpad | |||
call readWord | |||
push hl ; Save advanced HL for later | |||
ld hl, scratchpad | |||
@@ -39,125 +32,4 @@ tokenize: | |||
.end: | |||
ld c, a | |||
pop hl | |||
pop de | |||
ret | |||
; Sets Z is A is ';', CR, LF, or null. | |||
isLineEndOrComment: | |||
cp ';' | |||
ret z | |||
; Continues onto isLineEnd... | |||
; Sets Z is A is CR, LF, or null. | |||
isLineEnd: | |||
or a ; same as cp 0 | |||
ret z | |||
cp 0x0d | |||
ret z | |||
cp 0x0a | |||
ret | |||
; Sets Z is A is ' ' '\t' or ',' | |||
isSep: | |||
cp ' ' | |||
ret z | |||
cp 0x09 | |||
ret z | |||
cp ',' | |||
ret | |||
; Sets Z is A is ' ', ',', ';', CR, LF, or null. | |||
isSepOrLineEnd: | |||
call isSep | |||
ret z | |||
call isLineEndOrComment | |||
ret | |||
; read word in (HL) and put it in (DE), null terminated, for a maximum of A | |||
; characters. As a result, A is the read length. HL is advanced to the next | |||
; separator char. | |||
readWord: | |||
push bc | |||
push de | |||
ld b, a | |||
.loop: | |||
ld a, (hl) | |||
call isSepOrLineEnd | |||
jr z, .success | |||
call JUMP_UPCASE | |||
ld (de), a | |||
inc hl | |||
inc de | |||
djnz .loop | |||
.success: | |||
xor a | |||
ld (de), a | |||
ld a, 4 | |||
sub a, b | |||
.end: | |||
pop de | |||
pop bc | |||
ret | |||
; (HL) being a string, advance it to the next non-sep character. | |||
; Set Z if we could do it before the line ended, reset Z if we couldn't. | |||
toWord: | |||
.loop: | |||
ld a, (hl) | |||
call isLineEndOrComment | |||
jr z, .error | |||
call isSep | |||
jr nz, .success | |||
inc hl | |||
jr .loop | |||
.error: | |||
call JUMP_UNSETZ | |||
ret | |||
.success: | |||
xor a ; ensure Z | |||
ret | |||
; Advance HL to the beginning of the next line, that is, right after the next | |||
; 0x10 or 0x13 or both. If we reach null, we stop and error out. | |||
; Sets Z on success, unsets it on error. | |||
gotoNextLine: | |||
dec hl ; a bit weird, but makes the looping easier | |||
.loop: | |||
inc hl | |||
ld a, (hl) | |||
call isLineEnd | |||
jr nz, .loop | |||
; (HL) is 0x10, 0x13 or 0 | |||
or a ; is 0? | |||
jr z, .error | |||
; we might have 0x13 followed by 0x10, let's account for this. | |||
; Yes, 0x10 followed by 0x10 will make us skip two lines, but this is of | |||
; no real consequence in our context. | |||
inc hl | |||
ld a, (hl) | |||
call isLineEnd | |||
jr nz, .success | |||
or a ; is 0? | |||
jr z, .error | |||
; There was another line sep. Skip this char | |||
inc hl | |||
; Continue on to .success | |||
.success: | |||
xor a ; ensure Z | |||
ret | |||
.error: | |||
call JUMP_UNSETZ | |||
ret | |||
; Repeatedly calls gotoNextLine until the line in (HL) points to a line that | |||
; isn't blank or 100% comment. Sets Z if we reach a line, Unset Z if we reach | |||
; EOF | |||
gotoNextNotBlankLine: | |||
call toWord | |||
ret z ; Z set? we have a not-blank line | |||
; Z not set? (HL) is at the end of the line or at the beginning of | |||
; comments. | |||
call gotoNextLine | |||
ret nz | |||
jr gotoNextNotBlankLine | |||