zasm: Add support for (NN) constants

This commit is contained in:
Virgil Dupras 2019-04-17 16:04:24 -04:00
parent e1d6178457
commit c5c8369ce9

View File

@ -4,7 +4,7 @@
; Number of rows in the argspec table ; Number of rows in the argspec table
ARGSPEC_TBL_CNT .equ 27 ARGSPEC_TBL_CNT .equ 27
; Number of rows in the primary instructions table ; Number of rows in the primary instructions table
INSTR_TBLP_CNT .equ 56 INSTR_TBLP_CNT .equ 58
; size in bytes of each row in the primary instructions table ; size in bytes of each row in the primary instructions table
INSTR_TBLP_ROWSIZE .equ 8 INSTR_TBLP_ROWSIZE .equ 8
@ -33,6 +33,45 @@ rlaX:
djnz .loop djnz .loop
ret ret
; If string at (HL) starts with ( and ends with ), "enter" into the parens
; (advance HL and put a null char at the end of the string) and set Z.
; Otherwise, do nothing and reset Z.
enterParens:
ld a, (hl)
cp '('
ret nz ; nothing to do
push hl
ld a, 0 ; look for null char
; advance until we get null
.loop:
cpi
jp z, .found
jr .loop
.found:
dec hl ; cpi over-advances. go back to null-char
dec hl ; looking at the last char before null
ld a, (hl)
cp ')'
jr nz, .doNotEnter
; We have parens. While we're here, let's put a null
xor a
ld (hl), a
pop hl ; back at the beginning. Let's advance.
inc hl
cp a ; ensure Z
ret ; we're good!
.doNotEnter:
pop hl
call unsetZ
ret
; Checks whether A is 'N' or 'M'
checkNOrM:
cp 'N'
ret z
cp 'M'
ret
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the ; Parse the decimal char at A and extract it's 0-9 numerical value. Put the
; result in A. ; result in A.
; ;
@ -49,10 +88,20 @@ parseDecimal:
; Parses the string at (HL) and returns the 16-bit value in IX. ; 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 ; 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. ; number is invalid. If the number is valid, Z is set, otherwise, unset.
; If (HL) contains a number inside parens, we properly enter into it.
; Upon successful return, A is set to 'N' for a parens-less number, 'M' for
; a number inside parens.
parseNumber: parseNumber:
push hl push hl
push de push de
push bc
; Let's see if we have parens and already set the A result in B.
ld b, 'N' ; if no parens
call enterParens
jr nz, .noparens
ld b, 'M' ; we have parens and entered it.
.noparens:
ld ix, 0 ld ix, 0
.loop: .loop:
ld a, (hl) ld a, (hl)
@ -87,6 +136,8 @@ parseNumber:
.error: .error:
call unsetZ call unsetZ
.end: .end:
ld a, b
pop bc
pop de pop de
pop hl pop hl
ret ret
@ -262,13 +313,12 @@ parseArg:
call JUMP_ADDDE call JUMP_ADDDE
djnz .loop1 djnz .loop1
; We exhausted the argspecs. Let's see if it's a number ; We exhausted the argspecs. Let's see if it's a number. This sets
; A to 'N' or 'M'
call parseNumber call parseNumber
jr nz, .notanumber jr z, .end ; Alright, we have a parsed number in IX. We're
; Alright, we have a parsed number in IX. We're done. ; done.
ld a, 'N' ; not a number
jr .end
.notanumber:
ld a, 0xff ld a, 0xff
jr .end jr .end
.found: .found:
@ -375,16 +425,18 @@ matchArg:
cp a, (hl) cp a, (hl)
ret z ret z
; not an exact match, let's check for numerical constants. ; not an exact match, let's check for numerical constants.
call JUMP_UPCASE
cp 'N' cp 'N'
jr z, .expectsNumber jr z, .expectsNumber
cp 'n' cp 'M'
jr z, .expectsNumber jr z, .expectsNumber
jr .notNumber jr .notNumber
.expectsNumber: .expectsNumber:
ld a, (hl) ld a, (hl)
cp 'N' ; In parsed arg, we don't have 'n', only 'N' call checkNOrM ; In parsed arg, we don't have 'n' or 'm', only
ret ; whether we match or not, the result of Z is the good ; 'N' and 'M'
; one ret ; whether we match or not, the result of Z is
; the good one.
.notNumber: .notNumber:
; A bit of a delicate situation here: we want A to go in H but also ; A bit of a delicate situation here: we want A to go in H but also
; (HL) to go in A. If not careful, we overwrite each other. EXX is ; (HL) to go in A. If not careful, we overwrite each other. EXX is
@ -516,16 +568,20 @@ parseLine:
push hl ; we use HL to point to the currently read arg push hl ; we use HL to point to the currently read arg
ld a, (ix+4) ; first argspec ld a, (ix+4) ; first argspec
ld hl, curArg1 ld hl, curArg1
cp 'N' call checkNOrM
jr z, .withWord jr z, .withWord
cp 'n' cp 'n'
jr z, .withByte jr z, .withByte
cp 'm'
jr z, .withByte
ld a, (ix+5) ; second argspec ld a, (ix+5) ; second argspec
ld hl, curArg2 ld hl, curArg2
cp 'N' call checkNOrM
jr z, .withWord jr z, .withWord
cp 'n' cp 'n'
jr z, .withByte jr z, .withByte
cp 'm'
jr z, .withByte
; nope, no number, aright, only one opcode ; nope, no number, aright, only one opcode
ld a, 1 ld a, 1
jr .end jr .end
@ -653,6 +709,7 @@ instrTBlPrimary:
.db "EX",0,0, 'd', 'h', 0, 0xeb ; EX DE, HL .db "EX",0,0, 'd', 'h', 0, 0xeb ; EX DE, HL
.db "EXX", 0, 0, 0, 0, 0xd9 ; EXX .db "EXX", 0, 0, 0, 0, 0xd9 ; EXX
.db "HALT", 0, 0, 0, 0x76 ; HALT .db "HALT", 0, 0, 0, 0x76 ; HALT
.db "IN",0,0, 'A', 'm', 0, 0xdb ; IN A, (n)
.db "INC", 0, 'l', 0, 0, 0x34 ; INC (HL) .db "INC", 0, 'l', 0, 0, 0x34 ; INC (HL)
.db "INC", 0, 0xb, 0, 3, 0b00000100 ; INC r .db "INC", 0, 0xb, 0, 3, 0b00000100 ; INC r
.db "INC", 0, 0x3, 0, 4, 0b00000011 ; INC s .db "INC", 0, 0x3, 0, 4, 0b00000011 ; INC s
@ -671,6 +728,7 @@ instrTBlPrimary:
.db "NOP", 0, 0, 0, 0, 0x00 ; NOP .db "NOP", 0, 0, 0, 0, 0x00 ; NOP
.db "OR",0,0, 'l', 0, 0, 0xb6 ; OR (HL) .db "OR",0,0, 'l', 0, 0, 0xb6 ; OR (HL)
.db "OR",0,0, 0xb, 0, 0, 0b10110000 ; OR r .db "OR",0,0, 0xb, 0, 0, 0b10110000 ; OR r
.db "OUT", 0, 'm', 'A', 0, 0xd3 ; OUT (n), A
.db "POP", 0, 0x1, 0, 4, 0b11000001 ; POP qq .db "POP", 0, 0x1, 0, 4, 0b11000001 ; POP qq
.db "PUSH", 0x1, 0, 4, 0b11000101 ; PUSH qq .db "PUSH", 0x1, 0, 4, 0b11000101 ; PUSH qq
.db "RET", 0, 0xa, 0, 3, 0b11000000 ; RET cc .db "RET", 0, 0xa, 0, 3, 0b11000000 ; RET cc