1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-27 10:18:05 +11:00

zasm: add support for ".db" directive

This commit is contained in:
Virgil Dupras 2019-05-01 11:26:41 -04:00
parent 28e1ba5e26
commit dde5161fc1
7 changed files with 146 additions and 102 deletions

View File

@ -9,6 +9,27 @@ D_BAD .equ 0xff
directiveNames: directiveNames:
.db ".DB", 0 .db ".DB", 0
; This is a list of handlers corresponding to indexes in directiveNames
directiveHandlers:
.dw handleDB
handleDB:
push de
push hl
call toWord
ld de, scratchpad
ld a, 8
call readWord
ld hl, scratchpad
call parseNumber
ld a, ixl
ld (direcData), a
ld a, 1
pop hl
pop de
ret
; Reads string in (HL) and returns the corresponding ID (D_*) in A. Sets Z if ; Reads string in (HL) and returns the corresponding ID (D_*) in A. Sets Z if
; there's a match. ; there's a match.
getDirectiveID: getDirectiveID:
@ -22,6 +43,21 @@ getDirectiveID:
pop bc pop bc
ret ret
; Parse directive specified in A (D_* const) with args in (HL) 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: parseDirective:
xor a push de
ret ; double A to have a proper offset in directiveHandlers
add a, a
ld de, directiveHandlers
call JUMP_ADDDE
ld ixh, d
ld ixl, e
pop de
jp (ix)
; *** Variables ***
direcData:
.fill 2

View File

@ -8,5 +8,5 @@ libz80/libz80.o: libz80/z80.c
kernel.h: glue.asm kernel.h: glue.asm
scas -o - -I ../../../parts/z80 $< | ./bin2c.sh KERNEL | tee $@ > /dev/null scas -o - -I ../../../parts/z80 $< | ./bin2c.sh KERNEL | tee $@ > /dev/null
zasm.h: $(addprefix ../, main.asm instr.asm tok.asm util.asm) zasm.h: $(addprefix ../, main.asm instr.asm directive.asm tok.asm literal.asm util.asm)
scas -o - -I.. $< | ./bin2c.sh ZASM | tee $@ > /dev/null scas -o - -I.. $< | ./bin2c.sh ZASM | tee $@ > /dev/null

View File

@ -89,66 +89,6 @@ getInstID:
pop bc pop bc
ret ret
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the
; result in A.
;
; On success, the carry flag is reset. On error, it is set.
parseDecimal:
; First, let's see if we have an easy 0-9 case
cp '0'
ret c ; if < '0', we have a problem
cp '9'+1
; We are in the 0-9 range
sub a, '0' ; C is clear
ret
; Parses the string at (HL) and returns the 16-bit value in IX.
; As soon as the number doesn't fit 16-bit any more, parsing stops and the
; number is invalid. If the number is valid, Z is set, otherwise, unset.
parseNumber:
push hl
push de
push bc
ld ix, 0
.loop:
ld a, (hl)
cp 0
jr z, .end ; success!
call parseDecimal
jr c, .error
; Now, let's add A to IX. First, multiply by 10.
ld d, ixh ; we need a copy of the initial copy for later
ld e, ixl
add ix, ix ; x2
add ix, ix ; x4
add ix, ix ; x8
add ix, de ; x9
add ix, de ; x10
add a, ixl
jr nc, .nocarry
inc ixh
.nocarry:
ld ixl, a
; We didn't bother checking for the C flag at each step because we
; check for overflow afterwards. If ixh < d, we overflowed
ld a, ixh
cp d
jr c, .error ; carry is set? overflow
inc hl
jr .loop
.error:
call JUMP_UNSETZ
.end:
pop bc
pop de
pop hl
ret
; Parse the string at (HL) and check if it starts with IX+, IY+, IX- or IY-. ; Parse the string at (HL) and check if it starts with IX+, IY+, IX- or IY-.
; Sets Z if yes, unset if no. ; Sets Z if yes, unset if no.
parseIXY: parseIXY:
@ -450,13 +390,13 @@ handleJPIX:
handleJPIY: handleJPIY:
ld a, 0xfd ld a, 0xfd
handleJPIXY: handleJPIXY:
ld (curUpcode), a ld (instrUpcode), a
ld a, (curArg1+1) ld a, (curArg1+1)
cp 0 ; numerical argument *must* be zero cp 0 ; numerical argument *must* be zero
jr nz, .error jr nz, .error
; ok, we're good ; ok, we're good
ld a, 0xe9 ; second upcode ld a, 0xe9 ; second upcode
ld (curUpcode+1), a ld (instrUpcode+1), a
ld c, 2 ld c, 2
ret ret
.error: .error:
@ -481,12 +421,12 @@ handleBITHL:
call handleBIT call handleBIT
ret nz ; error ret nz ; error
ld a, 0xcb ; first upcode ld a, 0xcb ; first upcode
ld (curUpcode), a ld (instrUpcode), a
ld a, (curArg1+1) ; 0-7 ld a, (curArg1+1) ; 0-7
ld b, 3 ; displacement ld b, 3 ; displacement
call rlaX call rlaX
or 0b01000110 ; 2nd upcode or 0b01000110 ; 2nd upcode
ld (curUpcode+1), a ld (instrUpcode+1), a
ld c, 2 ld c, 2
ret ret
@ -496,18 +436,18 @@ handleBITIX:
handleBITIY: handleBITIY:
ld a, 0xfd ld a, 0xfd
handleBITIXY: handleBITIXY:
ld (curUpcode), a ; first upcode ld (instrUpcode), a ; first upcode
call handleBIT call handleBIT
ret nz ; error ret nz ; error
ld a, 0xcb ; 2nd upcode ld a, 0xcb ; 2nd upcode
ld (curUpcode+1), a ld (instrUpcode+1), a
ld a, (curArg2+1) ; IXY displacement ld a, (curArg2+1) ; IXY displacement
ld (curUpcode+2), a ld (instrUpcode+2), a
ld a, (curArg1+1) ; 0-7 ld a, (curArg1+1) ; 0-7
ld b, 3 ; displacement ld b, 3 ; displacement
call rlaX call rlaX
or 0b01000110 ; 4th upcode or 0b01000110 ; 4th upcode
ld (curUpcode+3), a ld (instrUpcode+3), a
ld c, 4 ld c, 4
ret ret
@ -519,7 +459,7 @@ handleBITR:
ld c, a ld c, a
; write first upcode ; write first upcode
ld a, 0xcb ; first upcode ld a, 0xcb ; first upcode
ld (curUpcode), a ld (instrUpcode), a
; get bit value ; get bit value
ld a, (curArg1+1) ; 0-7 ld a, (curArg1+1) ; 0-7
ld b, 3 ; displacement ld b, 3 ; displacement
@ -529,7 +469,7 @@ handleBITR:
or c ; Now we have our ORed value or c ; Now we have our ORed value
or 0b01000000 ; and with the constant value for that byte... or 0b01000000 ; and with the constant value for that byte...
; we're good! ; we're good!
ld (curUpcode+1), a ld (instrUpcode+1), a
ld c, 2 ld c, 2
ret ret
@ -553,9 +493,9 @@ handleIM:
.im2: .im2:
ld a, 0x5e ld a, 0x5e
.proceed: .proceed:
ld (curUpcode+1), a ld (instrUpcode+1), a
ld a, 0xed ld a, 0xed
ld (curUpcode), a ld (instrUpcode), a
ld c, 2 ld c, 2
ret ret
@ -565,13 +505,13 @@ handleLDIXn:
handleLDIYn: handleLDIYn:
ld a, 0xfd ld a, 0xfd
handleLDIXYn: handleLDIXYn:
ld (curUpcode), a ld (instrUpcode), a
ld a, 0x36 ; second upcode ld a, 0x36 ; second upcode
ld (curUpcode+1), a ld (instrUpcode+1), a
ld a, (curArg1+1) ; IXY displacement ld a, (curArg1+1) ; IXY displacement
ld (curUpcode+2), a ld (instrUpcode+2), a
ld a, (curArg2+1) ; N ld a, (curArg2+1) ; N
ld (curUpcode+3), a ld (instrUpcode+3), a
ld c, 4 ld c, 4
ret ret
.error: .error:
@ -584,12 +524,12 @@ handleLDIXr:
handleLDIYr: handleLDIYr:
ld a, 0xfd ld a, 0xfd
handleLDIXYr: handleLDIXYr:
ld (curUpcode), a ld (instrUpcode), a
ld a, (curArg2+1) ; group value ld a, (curArg2+1) ; group value
or 0b01110000 ; second upcode or 0b01110000 ; second upcode
ld (curUpcode+1), a ld (instrUpcode+1), a
ld a, (curArg1+1) ; IXY displacement ld a, (curArg1+1) ; IXY displacement
ld (curUpcode+2), a ld (instrUpcode+2), a
ld c, 3 ld c, 3
ret ret
.error: .error:
@ -597,8 +537,8 @@ handleLDIXYr:
ret ret
; Compute the upcode for argspec row at (DE) and arguments in curArg{1,2} and ; Compute the upcode for argspec row at (DE) and arguments in curArg{1,2} and
; writes the resulting upcode in curUpcode. A is the number if bytes written ; writes the resulting upcode in instrUpcode. A is the number if bytes written
; to curUpcode (can be zero if something went wrong). ; to instrUpcode (can be zero if something went wrong).
getUpcode: getUpcode:
push ix push ix
push de push de
@ -615,14 +555,14 @@ getUpcode:
ld l, (ix+4) ld l, (ix+4)
ld h, (ix+5) ld h, (ix+5)
call callHL call callHL
; We have our result written in curUpcode and C is set. ; We have our result written in instrUpcode and C is set.
jp .end jp .end
.normalInstr: .normalInstr:
; we begin by writing our "base upcode", which can be one or two bytes ; we begin by writing our "base upcode", which can be one or two bytes
ld a, (ix+4) ; first upcode ld a, (ix+4) ; first upcode
ld (curUpcode), a ld (instrUpcode), a
ld de, curUpcode ; from this point, DE points to "where we are" ld de, instrUpcode ; from this point, DE points to "where we are"
; in terms of upcode writing. ; in terms of upcode writing.
inc de ; make DE point to where we should write next. inc de ; make DE point to where we should write next.
ld a, (ix+5) ; second upcode ld a, (ix+5) ; second upcode
@ -667,11 +607,11 @@ getUpcode:
bit 6, (ix+3) bit 6, (ix+3)
jr z, .firstUpcode ; not set: first upcode jr z, .firstUpcode ; not set: first upcode
or (ix+5) ; second upcode or (ix+5) ; second upcode
ld (curUpcode+1), a ld (instrUpcode+1), a
jr .writeExtraBytes jr .writeExtraBytes
.firstUpcode: .firstUpcode:
or (ix+4) ; first upcode or (ix+4) ; first upcode
ld (curUpcode), a ld (instrUpcode), a
jr .writeExtraBytes jr .writeExtraBytes
.writeExtraBytes: .writeExtraBytes:
; Good, we are probably finished here for many primary opcodes. However, ; Good, we are probably finished here for many primary opcodes. However,
@ -679,7 +619,7 @@ getUpcode:
; if that's the case here, we need to write it too. ; if that's the case here, we need to write it too.
; We still have our instruction row in IX and we have DE pointing to ; We still have our instruction row in IX and we have DE pointing to
; where we should write next (which could be the second or the third ; where we should write next (which could be the second or the third
; byte of curUpcode). ; byte of instrUpcode).
ld a, (ix+1) ; first argspec ld a, (ix+1) ; first argspec
ld hl, curArg1 ld hl, curArg1
call checkNOrM call checkNOrM
@ -724,7 +664,7 @@ getUpcode:
ld c, 3 ld c, 3
jr .computeBytesWritten jr .computeBytesWritten
.computeBytesWritten: .computeBytesWritten:
; At this point, everything that we needed to write in curUpcode is ; At this point, everything that we needed to write in instrUpcode is
; written an C is 1 if we have no extra byte, 2 if we have an extra ; written an C is 1 if we have no extra byte, 2 if we have an extra
; byte and 3 if we have an extra word. What we need to do here is check ; byte and 3 if we have an extra word. What we need to do here is check
; if ix+5 is non-zero and increase C if it is. ; if ix+5 is non-zero and increase C if it is.
@ -784,7 +724,7 @@ processArg:
ret ret
; Parse instruction specified in A (I_* const) with args in (HL) and write ; Parse instruction specified in A (I_* const) with args in (HL) and write
; resulting opcode(s) in (curUpcode). Returns the number of bytes written in A. ; resulting opcode(s) in (instrUpcode). Returns the number of bytes written in A.
parseInstruction: parseInstruction:
push bc push bc
push hl push hl
@ -1119,6 +1059,6 @@ curArg1:
curArg2: curArg2:
.db 0, 0, 0 .db 0, 0, 0
curUpcode: instrUpcode:
.db 0, 0, 0, 0 .db 0, 0, 0, 0

59
apps/zasm/literal.asm Normal file
View File

@ -0,0 +1,59 @@
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the
; result in A.
;
; On success, the carry flag is reset. On error, it is set.
parseDecimal:
; First, let's see if we have an easy 0-9 case
cp '0'
ret c ; if < '0', we have a problem
cp '9'+1
; We are in the 0-9 range
sub a, '0' ; C is clear
ret
; Parses the string at (HL) and returns the 16-bit value in IX.
; As soon as the number doesn't fit 16-bit any more, parsing stops and the
; number is invalid. If the number is valid, Z is set, otherwise, unset.
parseNumber:
push hl
push de
push bc
ld ix, 0
.loop:
ld a, (hl)
cp 0
jr z, .end ; success!
call parseDecimal
jr c, .error
; Now, let's add A to IX. First, multiply by 10.
ld d, ixh ; we need a copy of the initial copy for later
ld e, ixl
add ix, ix ; x2
add ix, ix ; x4
add ix, ix ; x8
add ix, de ; x9
add ix, de ; x10
add a, ixl
jr nc, .nocarry
inc ixh
.nocarry:
ld ixl, a
; We didn't bother checking for the C flag at each step because we
; check for overflow afterwards. If ixh < d, we overflowed
ld a, ixh
cp d
jr c, .error ; carry is set? overflow
inc hl
jr .loop
.error:
call JUMP_UNSETZ
.end:
pop bc
pop de
pop hl
ret

View File

@ -20,8 +20,9 @@ main:
ret ret
#include "util.asm" #include "util.asm"
#include "tok.asm" #include "literal.asm"
#include "instr.asm" #include "instr.asm"
#include "tok.asm"
#include "directive.asm" #include "directive.asm"
; Parse line in (HL), write the resulting opcode(s) in (DE) and returns the ; Parse line in (HL), write the resulting opcode(s) in (DE) and returns the
@ -35,11 +36,11 @@ parseLine:
jr nz, .error jr nz, .error
call tokenize call tokenize
ld a, b ; TOK_* ld a, b ; TOK_*
cp TOK_BAD
jr z, .error
cp TOK_INSTR cp TOK_INSTR
jr z, .instr jr z, .instr
jr .error ; directive not supported yet cp TOK_DIRECTIVE
jr z, .direc
jr .error ; token not supported
.instr: .instr:
ld a, c ; I_* ld a, c ; I_*
call parseInstruction call parseInstruction
@ -48,7 +49,18 @@ parseLine:
ld b, 0 ld b, 0
ld c, a ; written bytes ld c, a ; written bytes
push hl push hl
ld hl, curUpcode ld hl, instrUpcode
call copy
pop hl
call JUMP_ADDDE
jr .success
.direc:
ld a, c ; D_*
call parseDirective
ld b, 0
ld c, a ; written bytes
push hl
ld hl, direcData
call copy call copy
pop hl pop hl
call JUMP_ADDDE call JUMP_ADDDE

View File

@ -2,3 +2,4 @@
add a, b ; comment add a, b ; comment
inc a ; comment inc a ; comment
; comment ; comment
.db 42

View File

@ -94,10 +94,6 @@ readWord:
ld (de), a ld (de), a
ld a, 4 ld a, 4
sub a, b sub a, b
jr .end
.error:
xor a
ld (de), a
.end: .end:
pop de pop de
pop bc pop bc