Browse Source

zasm: add support for IX/IY with displacement

pull/10/head
Virgil Dupras 5 years ago
parent
commit
056bbde710
3 changed files with 91 additions and 23 deletions
  1. +9
    -0
      apps/zasm/tests/geninstrs.py
  2. +2
    -1
      apps/zasm/tok.asm
  3. +80
    -22
      apps/zasm/zasm.asm

+ 9
- 0
apps/zasm/tests/geninstrs.py View File

@@ -85,6 +85,15 @@ def genargs(argspec):
if argspec in 'mM': if argspec in 'mM':
nbs = [f"({n})" for n in nbs] nbs = [f"({n})" for n in nbs]
return nbs return nbs
if argspec in 'xy':
# IX/IY displacement is special
base = argspecTbl[argspec]
result = [base]
argspec = argspec.upper()
for n in [1, 10, 100, 127]:
result.append(f"(I{argspec}+{n})")
# TODO: support minus
return result
if argspec in argspecTbl: if argspec in argspecTbl:
return [argspecTbl[argspec]] return [argspecTbl[argspec]]
grp = argGrpTbl[argspec] grp = argGrpTbl[argspec]


+ 2
- 1
apps/zasm/tok.asm View File

@@ -7,7 +7,8 @@


; *** Code *** ; *** Code ***
; Parse line in (HL) and place each element in tokInstr, tokArg1, tokArg2. Those ; Parse line in (HL) and place each element in tokInstr, tokArg1, tokArg2. Those
; values are null-terminated and empty if not present.
; values are null-terminated and empty if not present. All letters are
; uppercased.
; Sets Z on success, unsets it on error. Blank line is not an error. ; Sets Z on success, unsets it on error. Blank line is not an error.
; (as of now, we don't have any error condition. We always succeed) ; (as of now, we don't have any error condition. We always succeed)
tokenize: tokenize:


+ 80
- 22
apps/zasm/zasm.asm View File

@@ -4,7 +4,7 @@
; Number of rows in the argspec table ; Number of rows in the argspec table
ARGSPEC_TBL_CNT .equ 28 ARGSPEC_TBL_CNT .equ 28
; Number of rows in the primary instructions table ; Number of rows in the primary instructions table
INSTR_TBL_CNT .equ 77
INSTR_TBL_CNT .equ 79
; size in bytes of each row in the primary instructions table ; size in bytes of each row in the primary instructions table
INSTR_TBL_ROWSIZE .equ 9 INSTR_TBL_ROWSIZE .equ 9


@@ -98,6 +98,17 @@ checkNOrM:
cp 'M' cp 'M'
ret ret


; Checks whether A is 'n', 'm', 'x' or 'y'
checknmxy:
cp 'n'
ret z
cp 'm'
ret z
cp 'x'
ret z
cp 'y'
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.
; ;
@@ -114,20 +125,11 @@ 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 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)
@@ -162,12 +164,37 @@ parseNumber:
.error: .error:
call unsetZ call unsetZ
.end: .end:
ld a, b
pop bc pop bc
pop de pop de
pop hl pop hl
ret ret


; Parse the string at (HL) and check if it starts with IX+, IY+, IX- or IY-.
; Sets Z if yes, unset if no.
parseIXY:
push hl
ld a, (hl)
cp 'I'
jr nz, .end ; Z already unset
inc hl
ld a, (hl)
cp 'X'
jr z, .match1
cp 'Y'
jr z, .match1
jr .end ; Z already unset
.match1:
; Alright, we have IX or IY. Let's see if we have + or - next.
inc hl
ld a, (hl)
cp '+'
jr z, .end ; Z is already set
cp '-'
; The value of Z at this point is our final result
.end:
pop hl
ret

; Returns length of string at (HL) in A. ; Returns length of string at (HL) in A.
strlen: strlen:
push bc push bc
@@ -205,6 +232,10 @@ parseArg:
push de push de
push hl push hl


; We always initialize IX to zero so that non-numerical args end up with
; a clean zero.
ld ix, 0

ld de, argspecTbl ld de, argspecTbl
; DE now points the the "argspec char" part of the entry, but what ; DE now points the the "argspec char" part of the entry, but what
; we're comparing in the loop is the string next to it. Let's offset ; we're comparing in the loop is the string next to it. Let's offset
@@ -219,12 +250,41 @@ parseArg:
call JUMP_ADDDE call JUMP_ADDDE
djnz .loop1 djnz .loop1


; We exhausted the argspecs. Let's see if it's a number. This sets
; A to 'N' or 'M'
; We exhausted the argspecs. Let's see if we're inside parens.
call enterParens
jr z, .withParens
; (HL) has no parens
call parseNumber
jr nz, .nomatch
; We have a proper number in no parens. Number in IX.
ld a, 'N'
jr .end
.withParens:
ld c, 'M' ; C holds the argspec type until we reach
; .numberInParens
; We have parens. First, let's see if we have a (IX+d) type of arg.
call parseIXY
jr nz, .parseNumberInParens ; not I{X,Y}. just parse number.
; We have IX+/IY+/IX-/IY-.
; note: the "-" part isn't supported yet.
inc hl ; (HL) now points to X or Y
ld a, (hl)
inc hl ; advance HL to the number part
inc hl ; this is the number
cp 'Y'
jr nz, .notY
ld c, 'y'
jr .parseNumberInParens
.notY:
ld c, 'x'
.parseNumberInParens:
call parseNumber call parseNumber
jr z, .end ; Alright, we have a parsed number in IX. We're
; done.
; not a number
jr nz, .nomatch
; We have a proper number in parens. Number in IX
ld a, c ; M, x, or y
jr .end
.nomatch:
; We get no match
ld a, 0xff ld a, 0xff
jr .end jr .end
.found: .found:
@@ -473,17 +533,13 @@ getUpcode:
ld hl, curArg1 ld hl, curArg1
call checkNOrM call checkNOrM
jr z, .withWord jr z, .withWord
cp 'n'
jr z, .withByte
cp 'm'
call checknmxy
jr z, .withByte jr z, .withByte
ld a, (ix+5) ; second argspec ld a, (ix+5) ; second argspec
ld hl, curArg2 ld hl, curArg2
call checkNOrM call checkNOrM
jr z, .withWord jr z, .withWord
cp 'n'
jr z, .withByte
cp 'm'
call checknmxy
jr z, .withByte jr z, .withByte
; nope, no number, alright, we're finished here ; nope, no number, alright, we're finished here
ld c, 1 ld c, 1
@@ -698,6 +754,8 @@ instrTBl:
.db "ADD", 0, 'h', 0x3, 4, 0b00001001 , 0 ; ADD HL, ss .db "ADD", 0, 'h', 0x3, 4, 0b00001001 , 0 ; ADD HL, ss
.db "ADD", 0,'X',0x4,0x44, 0xdd, 0b00001001 ; ADD IX, pp .db "ADD", 0,'X',0x4,0x44, 0xdd, 0b00001001 ; ADD IX, pp
.db "ADD", 0,'Y',0x5,0x44, 0xfd, 0b00001001 ; ADD IY, rr .db "ADD", 0,'Y',0x5,0x44, 0xfd, 0b00001001 ; ADD IY, rr
.db "ADD", 0, 'A', 'x', 0, 0xdd, 0x86 ; ADD A, (IX+d)
.db "ADD", 0, 'A', 'y', 0, 0xfd, 0x86 ; ADD A, (IY+d)
.db "AND", 0, 'l', 0, 0, 0xa6 , 0 ; AND (HL) .db "AND", 0, 'l', 0, 0, 0xa6 , 0 ; AND (HL)
.db "AND", 0, 0xb, 0, 0, 0b10100000 , 0 ; AND r .db "AND", 0, 0xb, 0, 0, 0b10100000 , 0 ; AND r
.db "AND", 0, 'n', 0, 0, 0xe6 , 0 ; AND n .db "AND", 0, 'n', 0, 0, 0xe6 , 0 ; AND n


Loading…
Cancel
Save