2019-05-11 11:19:34 +10:00
|
|
|
; 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.
|
|
|
|
parseDecimalDigit:
|
|
|
|
; First, let's see if we have an easy 0-9 case
|
|
|
|
cp '0'
|
|
|
|
ret c ; if < '0', we have a problem
|
|
|
|
sub a, '0' ; our value now is valid if it's < 10
|
|
|
|
cp 10 ; on success, C is set, which is the opposite
|
|
|
|
; of what we want
|
|
|
|
ccf ; invert C flag
|
|
|
|
ret
|
2019-05-10 05:55:29 +10:00
|
|
|
|
2019-05-11 11:19:34 +10:00
|
|
|
; Parse string at (HL) as a decimal value and return value in IX under the
|
2019-05-15 03:53:12 +10:00
|
|
|
; same conditions as parseLiteral.
|
2019-05-11 11:19:34 +10:00
|
|
|
parseDecimal:
|
|
|
|
push hl
|
|
|
|
push de
|
|
|
|
push bc
|
2019-05-02 04:19:43 +10:00
|
|
|
|
2019-05-11 11:19:34 +10:00
|
|
|
ld ix, 0
|
|
|
|
.loop:
|
|
|
|
ld a, (hl)
|
|
|
|
cp 0
|
|
|
|
jr z, .end ; success!
|
|
|
|
call parseDecimalDigit
|
|
|
|
jr c, .error
|
2019-05-02 04:19:43 +10:00
|
|
|
|
2019-05-11 11:19:34 +10:00
|
|
|
; 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
|
2019-05-02 04:19:43 +10:00
|
|
|
|
2019-05-11 11:19:34 +10:00
|
|
|
; 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
|
2019-05-02 04:19:43 +10:00
|
|
|
|
2019-05-11 11:19:34 +10:00
|
|
|
inc hl
|
|
|
|
jr .loop
|
|
|
|
|
|
|
|
.error:
|
2019-05-17 23:50:11 +10:00
|
|
|
call unsetZ
|
2019-05-11 11:19:34 +10:00
|
|
|
.end:
|
|
|
|
pop bc
|
|
|
|
pop de
|
|
|
|
pop hl
|
2019-05-02 04:19:43 +10:00
|
|
|
ret
|
|
|
|
|
2019-05-11 11:19:34 +10:00
|
|
|
|
|
|
|
; Parse string at (HL) as a hexadecimal value and return value in IX under the
|
2019-05-15 03:53:12 +10:00
|
|
|
; same conditions as parseLiteral.
|
2019-05-11 11:19:34 +10:00
|
|
|
parseHexadecimal:
|
2019-05-15 03:53:12 +10:00
|
|
|
call hasHexPrefix
|
|
|
|
ret nz
|
2019-05-10 11:21:08 +10:00
|
|
|
push hl
|
2019-05-11 11:19:34 +10:00
|
|
|
xor a
|
|
|
|
ld ixh, a
|
|
|
|
inc hl ; get rid of "0x"
|
2019-05-10 11:21:08 +10:00
|
|
|
inc hl
|
2019-05-11 11:19:34 +10:00
|
|
|
call strlen
|
|
|
|
cp 3
|
|
|
|
jr c, .single
|
|
|
|
cp 5
|
|
|
|
jr c, .double
|
|
|
|
; too long, error
|
|
|
|
jr .error
|
|
|
|
.double:
|
2019-05-17 23:50:11 +10:00
|
|
|
call parseHexPair ; moves HL to last char of pair
|
2019-05-11 11:19:34 +10:00
|
|
|
jr c, .error
|
|
|
|
inc hl ; now HL is on first char of next pair
|
|
|
|
ld ixh, a
|
|
|
|
.single:
|
2019-05-17 23:50:11 +10:00
|
|
|
call parseHexPair
|
2019-05-11 11:19:34 +10:00
|
|
|
jr c, .error
|
|
|
|
ld ixl, a
|
|
|
|
cp a ; ensure Z
|
2019-05-10 11:21:08 +10:00
|
|
|
jr .end
|
2019-05-11 11:19:34 +10:00
|
|
|
.error:
|
2019-05-17 23:50:11 +10:00
|
|
|
call unsetZ
|
2019-05-10 11:21:08 +10:00
|
|
|
.end:
|
|
|
|
pop hl
|
|
|
|
ret
|
|
|
|
|
2019-05-11 11:19:34 +10:00
|
|
|
; Sets Z if (HL) has a '0x' or '0X' prefix.
|
|
|
|
hasHexPrefix:
|
2019-05-02 04:19:43 +10:00
|
|
|
ld a, (hl)
|
2019-05-11 11:19:34 +10:00
|
|
|
cp '0'
|
|
|
|
ret nz
|
|
|
|
push hl
|
2019-05-02 04:19:43 +10:00
|
|
|
inc hl
|
|
|
|
ld a, (hl)
|
2019-05-11 11:19:34 +10:00
|
|
|
cp 'x'
|
2019-05-10 05:55:29 +10:00
|
|
|
pop hl
|
|
|
|
ret
|
2019-05-11 11:19:34 +10:00
|
|
|
|
2019-05-15 03:53:12 +10:00
|
|
|
; Parse string at (HL) and, if it is a char literal, sets Z and return
|
|
|
|
; corresponding value in IXL. Clears IXH.
|
|
|
|
;
|
|
|
|
; A valid char literal starts with ', ends with ' and has one character in the
|
|
|
|
; middle. No escape sequence are accepted, but ''' will return the apostrophe
|
|
|
|
; character.
|
|
|
|
parseCharLiteral:
|
|
|
|
ld a, 0x27 ; apostrophe (') char
|
|
|
|
cp (hl)
|
|
|
|
ret nz
|
|
|
|
|
|
|
|
push hl
|
|
|
|
inc hl
|
|
|
|
inc hl
|
|
|
|
cp (hl)
|
|
|
|
jr nz, .end ; not ending with an apostrophe
|
|
|
|
inc hl
|
|
|
|
ld a, (hl)
|
|
|
|
or a ; cp 0
|
|
|
|
jr nz, .end ; string has to end there
|
|
|
|
; Valid char, good
|
|
|
|
ld ixh, a ; A is zero, take advantage of that
|
|
|
|
dec hl
|
|
|
|
dec hl
|
|
|
|
ld a, (hl)
|
|
|
|
ld ixl, a
|
|
|
|
cp a ; ensure Z
|
|
|
|
.end:
|
|
|
|
pop hl
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Parses the string at (HL) and returns the 16-bit value in IX. The string
|
|
|
|
; can be a decimal literal (1234), a hexadecimal literal (0x1234) or a char
|
|
|
|
; literal ('X').
|
|
|
|
;
|
2019-05-11 11:19:34 +10:00
|
|
|
; 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.
|
2019-05-15 03:53:12 +10:00
|
|
|
parseLiteral:
|
|
|
|
call parseCharLiteral
|
|
|
|
ret z
|
|
|
|
call parseHexadecimal
|
|
|
|
ret z
|
|
|
|
jp parseDecimal
|
2019-05-11 11:19:34 +10:00
|
|
|
|
|
|
|
; Parse string in (HL) and return its numerical value whether its a number
|
|
|
|
; literal or a symbol. Returns value in IX.
|
|
|
|
; Sets Z if number or symbol is valid, unset otherwise.
|
|
|
|
parseNumberOrSymbol:
|
2019-05-15 03:53:12 +10:00
|
|
|
call parseLiteral
|
2019-05-11 11:19:34 +10:00
|
|
|
ret z
|
2019-05-14 06:53:52 +10:00
|
|
|
call zasmIsFirstPass
|
|
|
|
ret z ; first pass? we don't care about the value,
|
|
|
|
; return success.
|
2019-05-11 11:19:34 +10:00
|
|
|
; Not a number. Try symbol
|
2019-05-16 10:07:21 +10:00
|
|
|
call symSelect
|
2019-05-14 06:53:52 +10:00
|
|
|
call symFind
|
|
|
|
ret nz ; not found
|
|
|
|
; Found! index in A, let's fetch value
|
2019-05-11 11:19:34 +10:00
|
|
|
push de
|
|
|
|
call symGetVal
|
2019-05-14 06:53:52 +10:00
|
|
|
; value in DE. We need it in IX
|
2019-05-11 11:19:34 +10:00
|
|
|
ld ixh, d
|
|
|
|
ld ixl, e
|
|
|
|
pop de
|
2019-05-14 06:53:52 +10:00
|
|
|
cp a ; ensure Z
|
2019-05-10 05:55:29 +10:00
|
|
|
ret
|