mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-17 09:48:05 +11:00
e9244b80ee
Instead of buffering input in memory one line at a time, we go in "just in time" mode and always read contents directly from I/O, without buffering. It forces us to implement a `ioPutback` scheme, but on the other hand it greatly simplifies cases where multiple tokens are on the same line (when a label is directly followed by an instruction). The end result feels much more solid and less hackish.
119 lines
2.0 KiB
NASM
119 lines
2.0 KiB
NASM
; *** CONSTS ***
|
|
|
|
.equ D_DB 0x00
|
|
.equ D_DW 0x01
|
|
.equ D_EQU 0x02
|
|
.equ D_BAD 0xff
|
|
|
|
; *** Variables ***
|
|
.equ DIREC_SCRATCHPAD DIREC_RAMSTART
|
|
.equ DIREC_RAMEND DIREC_SCRATCHPAD+SCRATCHPAD_SIZE
|
|
; *** CODE ***
|
|
|
|
; 4 bytes per row, fill with zero
|
|
directiveNames:
|
|
.db ".DB", 0
|
|
.db ".DW", 0
|
|
.db ".EQU"
|
|
|
|
; This is a list of handlers corresponding to indexes in directiveNames
|
|
directiveHandlers:
|
|
.dw handleDB
|
|
.dw handleDW
|
|
.dw handleEQU
|
|
|
|
handleDB:
|
|
push hl
|
|
call readWord
|
|
ld hl, scratchpad
|
|
call parseLiteral
|
|
ld a, ixl
|
|
ld (direcData), a
|
|
ld a, 1
|
|
pop hl
|
|
ret
|
|
|
|
handleDW:
|
|
push hl
|
|
call readWord
|
|
ld hl, scratchpad
|
|
call parseExpr
|
|
ld a, ixl
|
|
ld (direcData), a
|
|
ld a, ixh
|
|
ld (direcData+1), a
|
|
ld a, 2
|
|
pop hl
|
|
ret
|
|
|
|
handleEQU:
|
|
call zasmIsFirstPass
|
|
jr nz, .begin
|
|
; first pass? .equ are noops Consume args and return
|
|
call readWord
|
|
call readWord
|
|
xor a
|
|
ret
|
|
.begin:
|
|
push hl
|
|
push de
|
|
push bc
|
|
; Read our constant name
|
|
call readWord
|
|
; We can't register our symbol yet: we don't have our value!
|
|
; Let's copy it over.
|
|
ld de, DIREC_SCRATCHPAD
|
|
ld bc, SCRATCHPAD_SIZE
|
|
ldir
|
|
|
|
; Now, read the value associated to it
|
|
call readWord
|
|
ld hl, scratchpad
|
|
call parseExpr
|
|
jr nz, .error
|
|
ld hl, DIREC_SCRATCHPAD
|
|
ld d, ixh
|
|
ld e, ixl
|
|
call symRegister
|
|
jr .end
|
|
.error:
|
|
.end:
|
|
xor a ; 0 bytes written
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
ret
|
|
|
|
; Reads string in (HL) and returns the corresponding ID (D_*) in A. Sets Z if
|
|
; there's a match.
|
|
getDirectiveID:
|
|
push bc
|
|
push de
|
|
ld b, D_EQU+1 ; D_EQU is last
|
|
ld c, 4
|
|
ld de, directiveNames
|
|
call findStringInList
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
; Parse directive specified in A (D_* const) with args in I/O and act in
|
|
; an appropriate manner. If the directive results in writing data at its
|
|
; current location, that data is in (direcData) and A is the number of bytes
|
|
; in it.
|
|
parseDirective:
|
|
push de
|
|
; double A to have a proper offset in directiveHandlers
|
|
add a, a
|
|
ld de, directiveHandlers
|
|
call JUMP_ADDDE
|
|
call JUMP_INTODE
|
|
ld ixh, d
|
|
ld ixl, e
|
|
pop de
|
|
jp (ix)
|
|
|
|
; *** Variables ***
|
|
direcData:
|
|
.fill 2
|