zasm: make symbol registry easily parametrizable
I'm about to split the global registry in two (labels and consts) and the previous state of registry selection made things murky. Now it's much better.
This commit is contained in:
parent
518f12b07f
commit
311d04e9aa
@ -36,20 +36,28 @@
|
|||||||
.equ SYM_LOC_VALUES SYM_NAMES+SYM_BUFSIZE
|
.equ SYM_LOC_VALUES SYM_NAMES+SYM_BUFSIZE
|
||||||
.equ SYM_LOC_NAMES SYM_LOC_VALUES+SYM_LOC_MAXCOUNT*2
|
.equ SYM_LOC_NAMES SYM_LOC_VALUES+SYM_LOC_MAXCOUNT*2
|
||||||
|
|
||||||
; Pointer to the currently selected registry
|
; Pointer to the active registry
|
||||||
.equ SYM_CTX_NAMES SYM_LOC_NAMES+SYM_LOC_BUFSIZE
|
.equ SYM_CTX SYM_LOC_NAMES+SYM_LOC_BUFSIZE
|
||||||
.equ SYM_CTX_NAMESEND SYM_CTX_NAMES+2
|
|
||||||
.equ SYM_CTX_VALUES SYM_CTX_NAMESEND+2
|
|
||||||
; Pointer, in (SYM_CTX_VALUES), to the result of the last symFind
|
|
||||||
.equ SYM_CTX_PTR SYM_CTX_VALUES+2
|
|
||||||
|
|
||||||
|
; Pointer, in the value list, to the result of the last _symFind
|
||||||
|
.equ SYM_CTX_PTR SYM_CTX+2
|
||||||
.equ SYM_RAMEND SYM_CTX_PTR+2
|
.equ SYM_RAMEND SYM_CTX_PTR+2
|
||||||
|
|
||||||
|
; *** Registries ***
|
||||||
|
; A symbol registry is a 6 bytes record with points to names and values of
|
||||||
|
; one of the register.
|
||||||
|
; It's 3 pointers: names, names end, values
|
||||||
|
|
||||||
|
SYM_GLOBAL_REGISTRY:
|
||||||
|
.dw SYM_NAMES, SYM_NAMES+SYM_BUFSIZE, SYM_VALUES
|
||||||
|
|
||||||
|
SYM_LOCAL_REGISTRY:
|
||||||
|
.dw SYM_LOC_NAMES, SYM_LOC_NAMES+SYM_LOC_BUFSIZE, SYM_LOC_VALUES
|
||||||
; *** Code ***
|
; *** Code ***
|
||||||
|
|
||||||
; Advance HL to the beginning of the next symbol name in SYM_NAMES except if
|
; Assuming that HL points in to a symbol name list, advance HL to the beginning
|
||||||
; (HL) is already zero, meaning we're at the end of the chain. In this case,
|
; of the next symbol name except if (HL) is already zero, meaning we're at the
|
||||||
; do nothing.
|
; end of the chain. In this case, do nothing.
|
||||||
; Sets Z if it succeeded, unset it if there is no next.
|
; Sets Z if it succeeded, unset it if there is no next.
|
||||||
_symNext:
|
_symNext:
|
||||||
xor a
|
xor a
|
||||||
@ -73,31 +81,17 @@ symInit:
|
|||||||
; Continue to symSelectGlobalRegistry
|
; Continue to symSelectGlobalRegistry
|
||||||
|
|
||||||
symSelectGlobalRegistry:
|
symSelectGlobalRegistry:
|
||||||
push af
|
|
||||||
push hl
|
push hl
|
||||||
ld hl, SYM_NAMES
|
ld hl, SYM_GLOBAL_REGISTRY
|
||||||
ld (SYM_CTX_NAMES), hl
|
ld (SYM_CTX), hl
|
||||||
ld hl, SYM_NAMES+SYM_BUFSIZE
|
|
||||||
ld (SYM_CTX_NAMESEND), hl
|
|
||||||
ld hl, SYM_VALUES
|
|
||||||
ld (SYM_CTX_VALUES), hl
|
|
||||||
pop hl
|
pop hl
|
||||||
pop af
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
symSelectLocalRegistry:
|
symSelectLocalRegistry:
|
||||||
push af
|
|
||||||
push hl
|
push hl
|
||||||
ld hl, SYM_LOC_NAMES
|
ld hl, SYM_LOCAL_REGISTRY
|
||||||
ld (SYM_CTX_NAMES), hl
|
ld (SYM_CTX), hl
|
||||||
ld hl, SYM_LOC_NAMES+SYM_LOC_BUFSIZE
|
|
||||||
ld (SYM_CTX_NAMESEND), hl
|
|
||||||
ld hl, SYM_LOC_VALUES
|
|
||||||
ld (SYM_CTX_VALUES), hl
|
|
||||||
ld a, h
|
|
||||||
ld a, l
|
|
||||||
pop hl
|
pop hl
|
||||||
pop af
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Sets Z according to whether label in (HL) is local (starts with a dot)
|
; Sets Z according to whether label in (HL) is local (starts with a dot)
|
||||||
@ -106,43 +100,51 @@ symIsLabelLocal:
|
|||||||
cp (hl)
|
cp (hl)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Place HL at the end of (SYM_CTX_NAMES) end (that is, at the point where we
|
; Given a registry in (IX), place HL at the end of its names that is, at the
|
||||||
; have two consecutive null chars and DE at the corresponding position in
|
; point where we have two consecutive null chars and DE at the corresponding
|
||||||
; SYM_CTX_VALUES).
|
; position in its values.
|
||||||
; If we're within bounds, Z is set, otherwise unset.
|
; If we're within bounds, Z is set, otherwise unset.
|
||||||
symNamesEnd:
|
_symNamesEnd:
|
||||||
push ix
|
push iy
|
||||||
push bc
|
push bc
|
||||||
|
|
||||||
ld ix, (SYM_CTX_VALUES)
|
; IY --> values
|
||||||
ld hl, (SYM_CTX_NAMES)
|
ld l, (ix+4)
|
||||||
ld de, (SYM_CTX_NAMESEND)
|
ld h, (ix+5)
|
||||||
|
push hl \ pop iy
|
||||||
|
; HL --> names
|
||||||
|
ld l, (ix)
|
||||||
|
ld h, (ix+1)
|
||||||
|
; DE --> names end
|
||||||
|
ld e, (ix+2)
|
||||||
|
ld d, (ix+3)
|
||||||
.loop:
|
.loop:
|
||||||
call _symNext
|
call _symNext
|
||||||
jr nz, .success ; We've reached the end of the chain.
|
jr nz, .success ; We've reached the end of the chain.
|
||||||
inc ix
|
inc iy
|
||||||
inc ix
|
inc iy
|
||||||
; Are we out of bounds name-wise?
|
; Are we out of bounds name-wise?
|
||||||
call cpHLDE
|
call cpHLDE
|
||||||
jr nc, .outOfBounds ; HL >= DE
|
jr nc, .outOfBounds ; HL >= DE
|
||||||
; are we out of bounds value-wise? check if IX == (SYM_CTX_NAMES)
|
; are we out of bounds value-wise? check if IY == (IX)'s names
|
||||||
; Is is assumed that values are placed right before names
|
; Is is assumed that values are placed right before names
|
||||||
push hl
|
push hl
|
||||||
push ix \ pop bc
|
push iy \ pop bc
|
||||||
ld hl, (SYM_CTX_NAMES)
|
ld l, (ix)
|
||||||
|
ld h, (ix+1)
|
||||||
sbc hl, bc
|
sbc hl, bc
|
||||||
pop hl
|
pop hl
|
||||||
jr z, .outOfBounds ; IX == (SYM_CTX_NAMES)
|
jr z, .outOfBounds ; IY == (IX)'s names
|
||||||
jr .loop
|
jr .loop
|
||||||
.outOfBounds:
|
.outOfBounds:
|
||||||
call unsetZ
|
call unsetZ
|
||||||
jr .end
|
jr .end
|
||||||
.success:
|
.success:
|
||||||
push ix \ pop de ; our values pos goes in DE
|
push iy \ pop de ; our values pos goes in DE
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
.end:
|
.end:
|
||||||
pop bc
|
pop bc
|
||||||
pop ix
|
pop iy
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Register label in (HL) (minus the ending ":") into the symbol registry and
|
; Register label in (HL) (minus the ending ":") into the symbol registry and
|
||||||
@ -150,29 +152,33 @@ symNamesEnd:
|
|||||||
; If successful, Z is set and A is the symbol index. Otherwise, Z is unset and
|
; If successful, Z is set and A is the symbol index. Otherwise, Z is unset and
|
||||||
; A is an error code (ERR_*).
|
; A is an error code (ERR_*).
|
||||||
symRegister:
|
symRegister:
|
||||||
call symFind
|
push ix ; --> lvl 1
|
||||||
|
ld ix, (SYM_CTX)
|
||||||
|
call _symFind
|
||||||
jr z, .alreadyThere
|
jr z, .alreadyThere
|
||||||
|
|
||||||
push hl ; will be used during processing. it's the symbol to add
|
push hl ; --> lvl 2. it's the symbol to add
|
||||||
push de ; will be used during processing. it's our value.
|
push de ; --> lvl 3. it's our value.
|
||||||
|
|
||||||
|
|
||||||
; First, let's get our strlen
|
; First, let's get our strlen
|
||||||
call strlen
|
call strlen
|
||||||
ld c, a ; save that strlen for later
|
ld c, a ; save that strlen for later
|
||||||
|
|
||||||
call symNamesEnd
|
call _symNamesEnd
|
||||||
jr nz, .outOfMemory
|
jr nz, .outOfMemory
|
||||||
|
|
||||||
; Is our new name going to make us go out of bounds?
|
; Is our new name going to make us go out of bounds?
|
||||||
push hl
|
push hl ; --> lvl 4
|
||||||
push de
|
push de ; --> lvl 5
|
||||||
ld de, (SYM_CTX_NAMESEND)
|
ld e, (ix+2)
|
||||||
|
ld d, (ix+3)
|
||||||
|
; DE --> names end
|
||||||
ld a, c
|
ld a, c
|
||||||
call addHL
|
call addHL
|
||||||
call cpHLDE
|
call cpHLDE
|
||||||
pop de
|
pop de ; <-- lvl 5
|
||||||
pop hl
|
pop hl ; <-- lvl 4
|
||||||
jr nc, .outOfMemory ; HL >= DE
|
jr nc, .outOfMemory ; HL >= DE
|
||||||
|
|
||||||
; Success. At this point, we have:
|
; Success. At this point, we have:
|
||||||
@ -183,11 +189,11 @@ symRegister:
|
|||||||
|
|
||||||
; Let's start with the value.
|
; Let's start with the value.
|
||||||
push hl \ pop ix ; save HL for later
|
push hl \ pop ix ; save HL for later
|
||||||
pop hl ; value to register
|
pop hl ; <-- lvl 3. value to register
|
||||||
call writeHLinDE ; write value where it goes.
|
call writeHLinDE ; write value where it goes.
|
||||||
|
|
||||||
; Good! now, the string.
|
; Good! now, the string.
|
||||||
pop hl ; string to register
|
pop hl ; <-- lvl 2. string to register
|
||||||
push ix \ pop de ; string destination
|
push ix \ pop de ; string destination
|
||||||
; Copy HL into DE until we reach null char
|
; Copy HL into DE until we reach null char
|
||||||
call strcpyM
|
call strcpyM
|
||||||
@ -196,15 +202,16 @@ symRegister:
|
|||||||
; list. DE is already correctly placed, A is already zero
|
; list. DE is already correctly placed, A is already zero
|
||||||
ld (de), a
|
ld (de), a
|
||||||
|
|
||||||
|
pop ix ; <-- lvl 1
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
; Nothing to pop. We've already popped our stack in the lines above.
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.outOfMemory:
|
.outOfMemory:
|
||||||
ld a, ERR_OOM
|
ld a, ERR_OOM
|
||||||
call unsetZ
|
call unsetZ
|
||||||
pop de
|
pop de ; <-- lvl 3
|
||||||
pop hl
|
pop hl ; <-- lvl 2
|
||||||
|
pop ix ; <-- lvl 1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.alreadyThere:
|
.alreadyThere:
|
||||||
@ -224,51 +231,61 @@ symRegister:
|
|||||||
; symbol names. So, if we end up in .alreadyThere during first pass,
|
; symbol names. So, if we end up in .alreadyThere during first pass,
|
||||||
; then it's an error condition. If it's not first pass, then we need
|
; then it's an error condition. If it's not first pass, then we need
|
||||||
; to update our value.
|
; to update our value.
|
||||||
|
|
||||||
|
; Let's pop our lvl 1 IX now, we don't need it any more.
|
||||||
|
pop ix ; <-- lvl 1
|
||||||
|
|
||||||
call zasmIsFirstPass
|
call zasmIsFirstPass
|
||||||
jr z, .duplicateError
|
jr z, .duplicateError
|
||||||
; Second pass. Don't error out, just update value
|
; Second pass. Don't error out, just update value
|
||||||
push hl
|
push hl ; --> lvl 1
|
||||||
ld hl, (SYM_CTX_PTR)
|
ld hl, (SYM_CTX_PTR)
|
||||||
ex de, hl
|
ex de, hl
|
||||||
call writeHLinDE
|
call writeHLinDE
|
||||||
pop hl
|
pop hl ; <-- lvl 1
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
ret
|
ret
|
||||||
.duplicateError:
|
.duplicateError:
|
||||||
ld a, ERR_DUPSYM
|
ld a, ERR_DUPSYM
|
||||||
jp unsetZ ; return
|
jp unsetZ ; return
|
||||||
|
|
||||||
; Find name (HL) in (SYM_CTX_NAMES) and make (SYM_CTX_PTR) point to the
|
; Assuming that IX points to a register context, find name HL in its names and
|
||||||
; corresponding entry in (SYM_CTX_VALUES).
|
; make the context pointer point to the corresponding entry in its values.
|
||||||
; If we find something, Z is set, otherwise unset.
|
; If we find something, Z is set, otherwise unset.
|
||||||
symFind:
|
_symFind:
|
||||||
push ix
|
push iy
|
||||||
push hl
|
push hl
|
||||||
push de
|
push de
|
||||||
|
|
||||||
ex de, hl ; it's easier if HL is haystack and DE is
|
ex de, hl ; it's easier if HL is haystack and DE is
|
||||||
; needle.
|
; needle.
|
||||||
ld ix, (SYM_CTX_VALUES)
|
; IY --> values
|
||||||
ld hl, (SYM_CTX_NAMES)
|
ld l, (ix+4)
|
||||||
|
ld h, (ix+5)
|
||||||
|
push hl \ pop iy
|
||||||
|
; HL --> names
|
||||||
|
ld l, (ix)
|
||||||
|
ld h, (ix+1)
|
||||||
.loop:
|
.loop:
|
||||||
call strcmp
|
call strcmp
|
||||||
jr z, .match
|
jr z, .match
|
||||||
; ok, next!
|
; ok, next!
|
||||||
call _symNext
|
call _symNext
|
||||||
jr nz, .nomatch ; end of the chain, nothing found
|
jr nz, .nomatch ; end of the chain, nothing found
|
||||||
inc ix
|
inc iy
|
||||||
inc ix
|
inc iy
|
||||||
jr .loop
|
jr .loop
|
||||||
.nomatch:
|
.nomatch:
|
||||||
call unsetZ
|
call unsetZ
|
||||||
jr .end
|
jr .end
|
||||||
.match:
|
.match:
|
||||||
ld (SYM_CTX_PTR), ix
|
push iy \ pop hl
|
||||||
|
ld (SYM_CTX_PTR), hl
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
.end:
|
.end:
|
||||||
pop de
|
pop de
|
||||||
pop hl
|
pop hl
|
||||||
pop ix
|
pop iy
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; For a given symbol name in (HL), find it in the appropriate symbol register
|
; For a given symbol name in (HL), find it in the appropriate symbol register
|
||||||
@ -277,15 +294,18 @@ symFind:
|
|||||||
; always called when the global registry is selected. Therefore, we always
|
; always called when the global registry is selected. Therefore, we always
|
||||||
; reselect it afterwards.
|
; reselect it afterwards.
|
||||||
symFindVal:
|
symFindVal:
|
||||||
|
push ix
|
||||||
|
ld ix, SYM_GLOBAL_REGISTRY
|
||||||
call symIsLabelLocal
|
call symIsLabelLocal
|
||||||
jp nz, .notLocal
|
jp nz, .notLocal
|
||||||
call symSelectLocalRegistry
|
ld ix, SYM_LOCAL_REGISTRY
|
||||||
.notLocal:
|
.notLocal:
|
||||||
call symFind
|
call _symFind
|
||||||
jr nz, .end
|
jr nz, .end
|
||||||
; Found! let's fetch value
|
; Found! let's fetch value
|
||||||
; Return value that (SYM_CTX_PTR) is pointing at in DE.
|
; Return value that (SYM_CTX_PTR) is pointing at in DE.
|
||||||
ld de, (SYM_CTX_PTR)
|
ld de, (SYM_CTX_PTR)
|
||||||
call intoDE
|
call intoDE
|
||||||
.end:
|
.end:
|
||||||
jp symSelectGlobalRegistry
|
pop ix
|
||||||
|
ret
|
||||||
|
Binary file not shown.
@ -1,21 +0,0 @@
|
|||||||
.equ RAMSTART 0x4000
|
|
||||||
.equ ACIA_CTL 0x80 ; Control and status. RS off.
|
|
||||||
.equ ACIA_IO 0x81 ; Transmit. RS on.
|
|
||||||
|
|
||||||
#include "err.h"
|
|
||||||
#include "core.asm"
|
|
||||||
#include "parse.asm"
|
|
||||||
.equ ACIA_RAMSTART RAMSTART
|
|
||||||
#include "acia.asm"
|
|
||||||
|
|
||||||
.equ BLOCKDEV_RAMSTART ACIA_RAMEND
|
|
||||||
.equ BLOCKDEV_COUNT 1
|
|
||||||
#include "blockdev.asm"
|
|
||||||
.dw aciaGetC, aciaPutC, 0, 0
|
|
||||||
|
|
||||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
|
||||||
#include "stdio.asm"
|
|
||||||
|
|
||||||
.equ SHELL_RAMSTART STDIO_RAMEND
|
|
||||||
.equ SHELL_EXTRA_CMD_COUNT 0
|
|
||||||
#include "shell.asm"
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user