mirror of
https://github.com/hsoft/collapseos.git
synced 2025-02-17 17:56:00 +11:00
zasm: add support for IX/IY with displacement
This commit is contained in:
parent
14a410b024
commit
056bbde710
@ -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]
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
; We exhausted the argspecs. Let's see if we're inside parens.
|
||||||
; A to 'N' or 'M'
|
call enterParens
|
||||||
|
jr z, .withParens
|
||||||
|
; (HL) has no parens
|
||||||
call parseNumber
|
call parseNumber
|
||||||
jr z, .end ; Alright, we have a parsed number in IX. We're
|
jr nz, .nomatch
|
||||||
; done.
|
; We have a proper number in no parens. Number in IX.
|
||||||
; not a number
|
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
|
||||||
|
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'
|
call checknmxy
|
||||||
jr z, .withByte
|
|
||||||
cp 'm'
|
|
||||||
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'
|
call checknmxy
|
||||||
jr z, .withByte
|
|
||||||
cp 'm'
|
|
||||||
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…
Reference in New Issue
Block a user