mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-02 22:20:55 +11:00
Compare commits
No commits in common. "7410891ad1bc1189874404e694fae2ea10f373ab" and "98ca338aba486ab5e33545d2833b7c26d50da73b" have entirely different histories.
7410891ad1
...
98ca338aba
@ -224,6 +224,7 @@ basPRINT:
|
|||||||
ex de, hl
|
ex de, hl
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .parseError
|
jr nz, .parseError
|
||||||
|
push ix \ pop de
|
||||||
ld hl, SCRATCHPAD
|
ld hl, SCRATCHPAD
|
||||||
call fmtDecimalS
|
call fmtDecimalS
|
||||||
call printstr
|
call printstr
|
||||||
@ -253,6 +254,7 @@ basGOTO:
|
|||||||
ex de, hl
|
ex de, hl
|
||||||
call parseExpr
|
call parseExpr
|
||||||
ret nz
|
ret nz
|
||||||
|
push ix \ pop de
|
||||||
call bufFind
|
call bufFind
|
||||||
jr nz, .notFound
|
jr nz, .notFound
|
||||||
push ix \ pop de
|
push ix \ pop de
|
||||||
@ -315,7 +317,7 @@ basINPUT:
|
|||||||
call rdSep
|
call rdSep
|
||||||
call stdioReadLine
|
call stdioReadLine
|
||||||
call parseExpr
|
call parseExpr
|
||||||
ld (VAR_TBL), de
|
ld (VAR_TBL), ix
|
||||||
call printcrlf
|
call printcrlf
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
ret
|
ret
|
||||||
|
@ -42,6 +42,7 @@ parseTruth:
|
|||||||
.simple:
|
.simple:
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .end
|
jr nz, .end
|
||||||
|
push ix \ pop de
|
||||||
ld a, d
|
ld a, d
|
||||||
or e
|
or e
|
||||||
jr .success
|
jr .success
|
||||||
@ -131,12 +132,12 @@ parseTruth:
|
|||||||
; place their corresponding values in HL and DE.
|
; place their corresponding values in HL and DE.
|
||||||
.parseLeftRight:
|
.parseLeftRight:
|
||||||
; let's start with HL
|
; let's start with HL
|
||||||
push de ; --> lvl 1
|
|
||||||
call parseExpr
|
call parseExpr
|
||||||
pop hl ; <-- lvl 1, orig DE
|
|
||||||
ret nz
|
ret nz
|
||||||
push de ; --> lvl 1. save HL value in stack.
|
push ix ; --> lvl 1. save (HL) value in stack.
|
||||||
; Now, for DE. (DE) is now in HL
|
ex de, hl
|
||||||
call parseExpr ; DE in place
|
call parseExpr
|
||||||
pop hl ; <-- lvl 1. restore saved HL
|
ret nz
|
||||||
|
push ix \ pop de
|
||||||
|
pop hl ; <-- lvl 1. restore.
|
||||||
ret
|
ret
|
||||||
|
@ -85,13 +85,11 @@ rdWord:
|
|||||||
; Read word from HL in SCRATCHPAD and then intepret that word as an expression.
|
; Read word from HL in SCRATCHPAD and then intepret that word as an expression.
|
||||||
; Put the result in IX.
|
; Put the result in IX.
|
||||||
; Z for success.
|
; Z for success.
|
||||||
; TODO: put result in DE
|
|
||||||
rdExpr:
|
rdExpr:
|
||||||
ld de, SCRATCHPAD
|
ld de, SCRATCHPAD
|
||||||
call rdWord
|
call rdWord
|
||||||
push hl
|
push hl
|
||||||
ex de, hl
|
ex de, hl
|
||||||
call parseExpr
|
call parseExpr
|
||||||
push de \ pop ix
|
|
||||||
pop hl
|
pop hl
|
||||||
ret
|
ret
|
||||||
|
@ -52,9 +52,10 @@ varTryAssign:
|
|||||||
call rdWord
|
call rdWord
|
||||||
ex de, hl
|
ex de, hl
|
||||||
; Now, evaluate that expression now in (HL)
|
; Now, evaluate that expression now in (HL)
|
||||||
call parseExpr ; --> number in DE
|
call parseExpr ; --> number in IX
|
||||||
jr nz, .exprErr
|
jr nz, .exprErr
|
||||||
pop af ; <-- lvl 4
|
pop af ; <-- lvl 4
|
||||||
|
push ix \ pop de ; send number to DE
|
||||||
call varAssign
|
call varAssign
|
||||||
xor a ; ensure Z
|
xor a ; ensure Z
|
||||||
.end:
|
.end:
|
||||||
|
@ -11,18 +11,19 @@
|
|||||||
;
|
;
|
||||||
; *** Code ***
|
; *** Code ***
|
||||||
;
|
;
|
||||||
|
; Parse expression in string at (HL) and returns the result in IX.
|
||||||
; Parse expression in string at (HL) and returns the result in DE.
|
|
||||||
; **This routine mutates (HL).**
|
; **This routine mutates (HL).**
|
||||||
; We expect (HL) to be disposable: we mutate it to avoid having to make a copy.
|
; We expect (HL) to be disposable: we mutate it to avoid having to make a copy.
|
||||||
; Sets Z on success, unset on error.
|
; Sets Z on success, unset on error.
|
||||||
|
; TODO: the IX output register is a bit awkward. Nearly everywhere, I need
|
||||||
|
; to push \ pop that thing. See if we could return the result in DE
|
||||||
|
; instead.
|
||||||
parseExpr:
|
parseExpr:
|
||||||
push ix
|
push de
|
||||||
push hl
|
push hl
|
||||||
call _parseExpr
|
call _parseExpr
|
||||||
push ix \ pop de
|
|
||||||
pop hl
|
pop hl
|
||||||
pop ix
|
pop de
|
||||||
ret
|
ret
|
||||||
|
|
||||||
_parseExpr:
|
_parseExpr:
|
||||||
@ -96,29 +97,25 @@ _findAndSplit:
|
|||||||
; parse expression on the left (HL) and the right (DE) and put the results in
|
; parse expression on the left (HL) and the right (DE) and put the results in
|
||||||
; HL (left) and DE (right)
|
; HL (left) and DE (right)
|
||||||
_resolveLeftAndRight:
|
_resolveLeftAndRight:
|
||||||
ld a, (hl)
|
|
||||||
or a
|
|
||||||
jr z, .noleft
|
|
||||||
; Parse left operand in (HL)
|
|
||||||
push de ; --> lvl 1
|
|
||||||
call parseExpr
|
|
||||||
pop hl ; <-- lvl 1, orig DE
|
|
||||||
ret nz ; return immediately if error
|
|
||||||
.parseright:
|
|
||||||
; Now we have parsed everything to the left and we have its result in
|
|
||||||
; DE. What we need to do now is the same thing on (DE) and then apply
|
|
||||||
; the + operator. Let's save DE somewhere and parse this.
|
|
||||||
push de ; --> lvl 1
|
|
||||||
; right expr in (HL)
|
|
||||||
call parseExpr ; DE is set
|
|
||||||
pop hl ; <-- lvl 1. left value
|
|
||||||
ret ; Z is parseExpr's result
|
|
||||||
.noleft:
|
|
||||||
; special case: is (HL) zero? If yes, it means that our left operand
|
; special case: is (HL) zero? If yes, it means that our left operand
|
||||||
; is empty. consider it as 0
|
; is empty. consider it as 0
|
||||||
ex de, hl ; (DE) goes in (HL) for .parseright
|
ld ix, 0 ; pre-set to 0
|
||||||
ld de, 0
|
ld a, (hl)
|
||||||
jr .parseright
|
or a
|
||||||
|
jr z, .skip
|
||||||
|
; Parse left operand in (HL)
|
||||||
|
call parseExpr
|
||||||
|
ret nz ; return immediately if error
|
||||||
|
.skip:
|
||||||
|
; Now we have parsed everything to the left and we have its result in
|
||||||
|
; IX. What we need to do now is the same thing on (DE) and then apply
|
||||||
|
; the + operator. Let's save IX somewhere and parse this.
|
||||||
|
ex de, hl ; right expr now in HL
|
||||||
|
push ix ; --> lvl 1
|
||||||
|
call parseExpr
|
||||||
|
pop hl ; <-- lvl 1. left
|
||||||
|
push ix \ pop de ; right
|
||||||
|
ret ; Z is parseExpr's result
|
||||||
|
|
||||||
; Routines in here all have the same signature: they take two numbers, DE (left)
|
; Routines in here all have the same signature: they take two numbers, DE (left)
|
||||||
; and IX (right), apply the operator and put the resulting number in DE.
|
; and IX (right), apply the operator and put the resulting number in DE.
|
||||||
|
@ -643,15 +643,14 @@ _readK8:
|
|||||||
jr _readExpr
|
jr _readExpr
|
||||||
|
|
||||||
_readDouble:
|
_readDouble:
|
||||||
push de
|
push ix
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .end
|
jr nz, .end
|
||||||
ld b, d
|
push ix \ pop bc
|
||||||
ld c, e
|
|
||||||
; BC is already set. For good measure, let's set A to BC's MSB
|
; BC is already set. For good measure, let's set A to BC's MSB
|
||||||
ld a, b
|
ld a, b
|
||||||
.end:
|
.end:
|
||||||
pop de
|
pop ix
|
||||||
ret
|
ret
|
||||||
|
|
||||||
_readk7:
|
_readk7:
|
||||||
@ -664,12 +663,13 @@ _readk7:
|
|||||||
; truncation checks might falsely fail.
|
; truncation checks might falsely fail.
|
||||||
call zasmIsFirstPass
|
call zasmIsFirstPass
|
||||||
jr z, .end
|
jr z, .end
|
||||||
; DE contains an absolute value. Turn this into a -64/+63 relative
|
; IX contains an absolute value. Turn this into a -64/+63 relative
|
||||||
; value by subtracting PC from it. However, before we do that, let's
|
; value by subtracting PC from it. However, before we do that, let's
|
||||||
; add 0x7f to it, which we'll remove later. This will simplify bounds
|
; add 0x7f to it, which we'll remove later. This will simplify bounds
|
||||||
; checks. (we use 7f instead of 3f because we deal in bytes here, not
|
; checks. (we use 7f instead of 3f because we deal in bytes here, not
|
||||||
; in words)
|
; in words)
|
||||||
ld hl, 0x7f
|
push ix \ pop hl
|
||||||
|
ld de, 0x7f
|
||||||
add hl, de ; Carry cleared
|
add hl, de ; Carry cleared
|
||||||
ex de, hl
|
ex de, hl
|
||||||
call zasmGetPC ; --> HL
|
call zasmGetPC ; --> HL
|
||||||
@ -706,7 +706,6 @@ _readR4:
|
|||||||
; read a rXX argument and return register number in A.
|
; read a rXX argument and return register number in A.
|
||||||
; Set Z for success.
|
; Set Z for success.
|
||||||
_readR5:
|
_readR5:
|
||||||
push de
|
|
||||||
push ix
|
push ix
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
call upcase
|
call upcase
|
||||||
@ -715,44 +714,43 @@ _readR5:
|
|||||||
inc hl
|
inc hl
|
||||||
call parseDecimal
|
call parseDecimal
|
||||||
jr nz, .end
|
jr nz, .end
|
||||||
push ix \ pop de
|
|
||||||
ld a, 31
|
ld a, 31
|
||||||
call _DE2A
|
call _IX2A
|
||||||
.end:
|
.end:
|
||||||
pop ix
|
pop ix
|
||||||
pop de
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Put DE's LSB into A and, additionally, ensure that the new value is <=
|
; Put IX's LSB into A and, additionally, ensure that the new value is <=
|
||||||
; than what was previously in A.
|
; than what was previously in A.
|
||||||
; Z for success.
|
; Z for success.
|
||||||
_DE2A:
|
_IX2A:
|
||||||
cp e
|
push ix \ pop hl
|
||||||
jp c, unsetZ ; A < E
|
cp l
|
||||||
ld a, d
|
jp c, unsetZ ; A < L
|
||||||
|
ld a, h
|
||||||
or a
|
or a
|
||||||
ret nz ; should be zero
|
ret nz ; should be zero
|
||||||
ld a, e
|
ld a, l
|
||||||
; Z set from "or a"
|
; Z set from "or a"
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Read expr and return success only if result in under number given in A
|
; Read expr and return success only if result in under number given in A
|
||||||
; Z for success
|
; Z for success
|
||||||
_readExpr:
|
_readExpr:
|
||||||
push de
|
push ix
|
||||||
push bc
|
push bc
|
||||||
ld b, a
|
ld b, a
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .end
|
jr nz, .end
|
||||||
ld a, b
|
ld a, b
|
||||||
call _DE2A
|
call _IX2A
|
||||||
jr nz, .end
|
jr nz, .end
|
||||||
or c
|
or c
|
||||||
ld c, a
|
ld c, a
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
.end:
|
.end:
|
||||||
pop bc
|
pop bc
|
||||||
pop de
|
pop ix
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Parse one of the following: X, Y, Z, X+, Y+, Z+, -X, -Y, -Z.
|
; Parse one of the following: X, Y, Z, X+, Y+, Z+, -X, -Y, -Z.
|
||||||
|
@ -40,7 +40,6 @@ dirHandlers:
|
|||||||
.dw handleBIN
|
.dw handleBIN
|
||||||
|
|
||||||
handleDB:
|
handleDB:
|
||||||
push de
|
|
||||||
push hl
|
push hl
|
||||||
.loop:
|
.loop:
|
||||||
call readWord
|
call readWord
|
||||||
@ -50,19 +49,18 @@ handleDB:
|
|||||||
jr z, .stringLiteral
|
jr z, .stringLiteral
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .badarg
|
jr nz, .badarg
|
||||||
ld a, d
|
push ix \ pop hl
|
||||||
|
ld a, h
|
||||||
or a ; cp 0
|
or a ; cp 0
|
||||||
jr nz, .overflow ; not zero? overflow
|
jr nz, .overflow ; not zero? overflow
|
||||||
ld a, e
|
ld a, l
|
||||||
call ioPutB
|
call ioPutB
|
||||||
jr nz, .ioError
|
jr nz, .ioError
|
||||||
.stopStrLit:
|
.stopStrLit:
|
||||||
call readComma
|
call readComma
|
||||||
jr z, .loop
|
jr z, .loop
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
.end:
|
|
||||||
pop hl
|
pop hl
|
||||||
pop de
|
|
||||||
ret
|
ret
|
||||||
.ioError:
|
.ioError:
|
||||||
ld a, SHELL_ERR_IO_ERROR
|
ld a, SHELL_ERR_IO_ERROR
|
||||||
@ -76,8 +74,9 @@ handleDB:
|
|||||||
.overflow:
|
.overflow:
|
||||||
ld a, ERR_OVFL
|
ld a, ERR_OVFL
|
||||||
.error:
|
.error:
|
||||||
or a ; unset Z
|
call unsetZ
|
||||||
jr .end
|
pop hl
|
||||||
|
ret
|
||||||
|
|
||||||
.stringLiteral:
|
.stringLiteral:
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
@ -90,7 +89,6 @@ handleDB:
|
|||||||
jr .stringLiteral
|
jr .stringLiteral
|
||||||
|
|
||||||
handleDW:
|
handleDW:
|
||||||
push de
|
|
||||||
push hl
|
push hl
|
||||||
.loop:
|
.loop:
|
||||||
call readWord
|
call readWord
|
||||||
@ -98,18 +96,17 @@ handleDW:
|
|||||||
ld hl, scratchpad
|
ld hl, scratchpad
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .badarg
|
jr nz, .badarg
|
||||||
ld a, e
|
push ix \ pop hl
|
||||||
|
ld a, l
|
||||||
call ioPutB
|
call ioPutB
|
||||||
jr nz, .ioError
|
jr nz, .ioError
|
||||||
ld a, d
|
ld a, h
|
||||||
call ioPutB
|
call ioPutB
|
||||||
jr nz, .ioError
|
jr nz, .ioError
|
||||||
call readComma
|
call readComma
|
||||||
jr z, .loop
|
jr z, .loop
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
.end:
|
|
||||||
pop hl
|
pop hl
|
||||||
pop de
|
|
||||||
ret
|
ret
|
||||||
.ioError:
|
.ioError:
|
||||||
ld a, SHELL_ERR_IO_ERROR
|
ld a, SHELL_ERR_IO_ERROR
|
||||||
@ -120,8 +117,9 @@ handleDW:
|
|||||||
.badarg:
|
.badarg:
|
||||||
ld a, ERR_BAD_ARG
|
ld a, ERR_BAD_ARG
|
||||||
.error:
|
.error:
|
||||||
or a ; unset Z
|
call unsetZ
|
||||||
jr .end
|
pop hl
|
||||||
|
ret
|
||||||
|
|
||||||
handleEQU:
|
handleEQU:
|
||||||
call zasmIsLocalPass ; Are we in local pass? Then ignore all .equ.
|
call zasmIsLocalPass ; Are we in local pass? Then ignore all .equ.
|
||||||
@ -151,6 +149,7 @@ handleEQU:
|
|||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .badarg
|
jr nz, .badarg
|
||||||
ld hl, DIREC_SCRATCHPAD
|
ld hl, DIREC_SCRATCHPAD
|
||||||
|
push ix \ pop de
|
||||||
; Save value in "@" special variable
|
; Save value in "@" special variable
|
||||||
ld (DIREC_LASTVAL), de
|
ld (DIREC_LASTVAL), de
|
||||||
call symRegisterConst ; A and Z set
|
call symRegisterConst ; A and Z set
|
||||||
@ -180,17 +179,14 @@ handleEQU:
|
|||||||
jp readWord
|
jp readWord
|
||||||
|
|
||||||
handleORG:
|
handleORG:
|
||||||
push de
|
|
||||||
call readWord
|
call readWord
|
||||||
jr nz, .badfmt
|
jr nz, .badfmt
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .badarg
|
jr nz, .badarg
|
||||||
ex de, hl
|
push ix \ pop hl
|
||||||
ld (DIREC_LASTVAL), hl
|
ld (DIREC_LASTVAL), hl
|
||||||
call zasmSetOrg
|
call zasmSetOrg
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
.end:
|
|
||||||
pop de
|
|
||||||
ret
|
ret
|
||||||
.badfmt:
|
.badfmt:
|
||||||
ld a, ERR_BAD_FMT
|
ld a, ERR_BAD_FMT
|
||||||
@ -198,28 +194,31 @@ handleORG:
|
|||||||
.badarg:
|
.badarg:
|
||||||
ld a, ERR_BAD_ARG
|
ld a, ERR_BAD_ARG
|
||||||
.error:
|
.error:
|
||||||
or a ; unset Z
|
call unsetZ
|
||||||
jr .end
|
ret
|
||||||
|
|
||||||
handleFIL:
|
handleFIL:
|
||||||
call readWord
|
call readWord
|
||||||
jr nz, .badfmt
|
jr nz, .badfmt
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .badarg
|
jr nz, .badarg
|
||||||
ld a, d
|
push bc ; --> lvl 1
|
||||||
|
push ix \ pop bc
|
||||||
|
ld a, b
|
||||||
cp 0xd0
|
cp 0xd0
|
||||||
jr nc, .overflow
|
jr nc, .overflow
|
||||||
.loop:
|
.loop:
|
||||||
ld a, d
|
ld a, b
|
||||||
or e
|
or c
|
||||||
jr z, .loopend
|
jr z, .loopend
|
||||||
xor a
|
xor a
|
||||||
call ioPutB
|
call ioPutB
|
||||||
jr nz, .ioError
|
jr nz, .ioError
|
||||||
dec de
|
dec bc
|
||||||
jr .loop
|
jr .loop
|
||||||
.loopend:
|
.loopend:
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
|
pop bc ; <-- lvl 1
|
||||||
ret
|
ret
|
||||||
.ioError:
|
.ioError:
|
||||||
ld a, SHELL_ERR_IO_ERROR
|
ld a, SHELL_ERR_IO_ERROR
|
||||||
@ -231,11 +230,11 @@ handleFIL:
|
|||||||
ld a, ERR_BAD_ARG
|
ld a, ERR_BAD_ARG
|
||||||
jp unsetZ
|
jp unsetZ
|
||||||
.overflow:
|
.overflow:
|
||||||
|
pop bc ; <-- lvl 1
|
||||||
ld a, ERR_OVFL
|
ld a, ERR_OVFL
|
||||||
jp unsetZ
|
jp unsetZ
|
||||||
|
|
||||||
handleOUT:
|
handleOUT:
|
||||||
push de
|
|
||||||
push hl
|
push hl
|
||||||
; Read our expression
|
; Read our expression
|
||||||
call readWord
|
call readWord
|
||||||
@ -245,9 +244,10 @@ handleOUT:
|
|||||||
ld hl, scratchpad
|
ld hl, scratchpad
|
||||||
call parseExpr
|
call parseExpr
|
||||||
jr nz, .badarg
|
jr nz, .badarg
|
||||||
ld a, d
|
push ix \ pop hl
|
||||||
|
ld a, h
|
||||||
out (ZASM_DEBUG_PORT), a
|
out (ZASM_DEBUG_PORT), a
|
||||||
ld a, e
|
ld a, l
|
||||||
out (ZASM_DEBUG_PORT), a
|
out (ZASM_DEBUG_PORT), a
|
||||||
jr .end
|
jr .end
|
||||||
.badfmt:
|
.badfmt:
|
||||||
@ -256,10 +256,9 @@ handleOUT:
|
|||||||
.badarg:
|
.badarg:
|
||||||
ld a, ERR_BAD_ARG
|
ld a, ERR_BAD_ARG
|
||||||
.error:
|
.error:
|
||||||
or a ; unset Z
|
call unsetZ
|
||||||
.end:
|
.end:
|
||||||
pop hl
|
pop hl
|
||||||
pop de
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
handleINC:
|
handleINC:
|
||||||
|
@ -146,7 +146,7 @@ parseIXY:
|
|||||||
; any argspec (A == 0 means arg is empty). A return value of 0xff means an
|
; any argspec (A == 0 means arg is empty). A return value of 0xff means an
|
||||||
; error.
|
; error.
|
||||||
;
|
;
|
||||||
; If the parsed argument is a number constant, 'N' is returned and DE contains
|
; If the parsed argument is a number constant, 'N' is returned and IX contains
|
||||||
; the value of that constant.
|
; the value of that constant.
|
||||||
parseArg:
|
parseArg:
|
||||||
call strlen
|
call strlen
|
||||||
@ -154,8 +154,13 @@ parseArg:
|
|||||||
ret z ; empty string? A already has our result: 0
|
ret z ; empty string? A already has our result: 0
|
||||||
|
|
||||||
push bc
|
push bc
|
||||||
|
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
|
||||||
@ -176,7 +181,7 @@ parseArg:
|
|||||||
; (HL) has no parens
|
; (HL) has no parens
|
||||||
call .maybeParseExpr
|
call .maybeParseExpr
|
||||||
jr nz, .nomatch
|
jr nz, .nomatch
|
||||||
; We have a proper number in no parens. Number in DE.
|
; We have a proper number in no parens. Number in IX.
|
||||||
ld a, 'N'
|
ld a, 'N'
|
||||||
jr .end
|
jr .end
|
||||||
.withParens:
|
.withParens:
|
||||||
@ -203,20 +208,23 @@ parseArg:
|
|||||||
.parseNumberInParens:
|
.parseNumberInParens:
|
||||||
call .maybeParseExpr
|
call .maybeParseExpr
|
||||||
jr nz, .nomatch
|
jr nz, .nomatch
|
||||||
; We have a proper number in parens. Number in DE
|
; We have a proper number in parens. Number in IX
|
||||||
; is '-' in B? if yes, we need to negate the low part of DE
|
; is '-' in B? if yes, we need to negate the low part of IX
|
||||||
ld a, b
|
ld a, b
|
||||||
cp '-'
|
cp '-'
|
||||||
jr nz, .dontNegateDE
|
jr nz, .dontNegateIX
|
||||||
; we need to negate the low part of DE
|
; we need to negate the low part of IX
|
||||||
; TODO: when parsing routines properly support unary negative numbers,
|
; TODO: when parsing routines properly support unary negative numbers,
|
||||||
; We could replace this complicated scheme below with a nice hack where
|
; We could replace this complicated scheme below with a nice hack where
|
||||||
; we start parsing our displacement number at the '+' and '-' char.
|
; we start parsing our displacement number at the '+' and '-' char.
|
||||||
|
|
||||||
ld a, e
|
; HL isn't needed anymore and can be destroyed.
|
||||||
|
push ix \ pop hl
|
||||||
|
ld a, l
|
||||||
neg
|
neg
|
||||||
ld e, a
|
ld l, a
|
||||||
.dontNegateDE:
|
push hl \ pop ix
|
||||||
|
.dontNegateIX:
|
||||||
ld a, c ; M, x, or y
|
ld a, c ; M, x, or y
|
||||||
jr .end
|
jr .end
|
||||||
.nomatch:
|
.nomatch:
|
||||||
@ -227,13 +235,9 @@ parseArg:
|
|||||||
; found the matching argspec row. Our result is one byte left of DE.
|
; found the matching argspec row. Our result is one byte left of DE.
|
||||||
dec de
|
dec de
|
||||||
ld a, (de)
|
ld a, (de)
|
||||||
|
|
||||||
; When we have non-numerical args, we set DE to zero to have a clean
|
|
||||||
; result.
|
|
||||||
ld de, 0
|
|
||||||
|
|
||||||
.end:
|
.end:
|
||||||
pop hl
|
pop hl
|
||||||
|
pop de
|
||||||
pop bc
|
pop bc
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -243,7 +247,6 @@ parseArg:
|
|||||||
; harmless, but in some cases it causes false failures. For example,
|
; harmless, but in some cases it causes false failures. For example,
|
||||||
; a "-" operator can cause is to falsely overflow and generate
|
; a "-" operator can cause is to falsely overflow and generate
|
||||||
; truncation error.
|
; truncation error.
|
||||||
ld de, 0 ; in first pass, return a clean zero
|
|
||||||
call zasmIsFirstPass
|
call zasmIsFirstPass
|
||||||
ret z
|
ret z
|
||||||
jp parseExpr
|
jp parseExpr
|
||||||
@ -814,18 +817,27 @@ spitUpcode:
|
|||||||
ld (INS_UPCODE+2), a
|
ld (INS_UPCODE+2), a
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Parse argument in (HL) and place it in (IX)
|
; Parse argument in (HL) and place it in (DE)
|
||||||
|
; DE is not preserved
|
||||||
; Sets Z on success, reset on error.
|
; Sets Z on success, reset on error.
|
||||||
processArg:
|
processArg:
|
||||||
call parseArg
|
call parseArg
|
||||||
cp 0xff
|
cp 0xff
|
||||||
jr z, .error
|
jr z, .error
|
||||||
ld (ix), a
|
ld (de), a
|
||||||
; When A is a number, DE is set with the value of that number. Because
|
; When A is a number, IX is set with the value of that number. Because
|
||||||
; We don't use the space allocated to store those numbers in any other
|
; We don't use the space allocated to store those numbers in any other
|
||||||
; occasion, we store DE there unconditonally, LSB first.
|
; occasion, we store IX there unconditonally, LSB first.
|
||||||
ld (ix+1), e
|
inc de
|
||||||
ld (ix+2), d
|
ex (sp), ix ; (SP) is kept in IX and will be restored
|
||||||
|
ex (sp), hl ; old HL is on (SP)
|
||||||
|
ld a, l
|
||||||
|
ld (de), a
|
||||||
|
inc de
|
||||||
|
ld a, h
|
||||||
|
ld (de), a
|
||||||
|
ex (sp), hl ; restore old HL from (SP)
|
||||||
|
ex (sp), ix ; restore old (SP) from IX
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
ret
|
ret
|
||||||
.error:
|
.error:
|
||||||
@ -848,14 +860,14 @@ parseInstruction:
|
|||||||
ld (INS_CURARG2), a
|
ld (INS_CURARG2), a
|
||||||
call readWord
|
call readWord
|
||||||
jr nz, .nomorearg
|
jr nz, .nomorearg
|
||||||
ld ix, INS_CURARG1
|
ld de, INS_CURARG1
|
||||||
call processArg
|
call processArg
|
||||||
jr nz, .end ; A is set to error, Z is unset
|
jr nz, .end ; A is set to error, Z is unset
|
||||||
call readComma
|
call readComma
|
||||||
jr nz, .nomorearg
|
jr nz, .nomorearg
|
||||||
call readWord
|
call readWord
|
||||||
jr nz, .badfmt
|
jr nz, .badfmt
|
||||||
ld ix, INS_CURARG2
|
ld de, INS_CURARG2
|
||||||
call processArg
|
call processArg
|
||||||
jr nz, .end ; A is set to error, Z is unset
|
jr nz, .end ; A is set to error, Z is unset
|
||||||
.nomorearg:
|
.nomorearg:
|
||||||
|
@ -6,15 +6,9 @@
|
|||||||
* until it halts. The return code is the value of the register A at halt time.
|
* until it halts. The return code is the value of the register A at halt time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void iowr_stderr(uint8_t val)
|
|
||||||
{
|
|
||||||
fputc(val, stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Machine *m = emul_init();
|
Machine *m = emul_init();
|
||||||
m->iowr[0] = iowr_stderr;
|
|
||||||
// read stdin in mem
|
// read stdin in mem
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int c = getchar();
|
int c = getchar();
|
||||||
@ -28,7 +22,6 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
emul_loop();
|
emul_loop();
|
||||||
if (m->cpu.R1.wr.HL)
|
|
||||||
return m->cpu.R1.br.A;
|
return m->cpu.R1.br.A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -1,62 +0,0 @@
|
|||||||
; *** requirements ***
|
|
||||||
; ascii.h
|
|
||||||
; core
|
|
||||||
; stdio
|
|
||||||
; lib/ari
|
|
||||||
; lib/fmt
|
|
||||||
|
|
||||||
testNum: .db 1
|
|
||||||
|
|
||||||
STDIO_PUTC:
|
|
||||||
out (0), a
|
|
||||||
cp a
|
|
||||||
ret
|
|
||||||
|
|
||||||
STDIO_GETC:
|
|
||||||
jp unsetZ
|
|
||||||
|
|
||||||
assertZ:
|
|
||||||
ret z
|
|
||||||
ld hl, .msg
|
|
||||||
call printstr
|
|
||||||
jp fail
|
|
||||||
.msg:
|
|
||||||
.db "Z not set", CR, LF, 0
|
|
||||||
|
|
||||||
assertNZ:
|
|
||||||
ret nz
|
|
||||||
ld hl, .msg
|
|
||||||
call printstr
|
|
||||||
jp fail
|
|
||||||
.msg:
|
|
||||||
.db "Z set", CR, LF, 0
|
|
||||||
|
|
||||||
; Assert that HL == DE
|
|
||||||
assertEQW:
|
|
||||||
ld a, h
|
|
||||||
cp d
|
|
||||||
jr nz, .fail
|
|
||||||
ld a, l
|
|
||||||
cp e
|
|
||||||
ret z
|
|
||||||
.fail:
|
|
||||||
call printHexPair
|
|
||||||
call printcrlf
|
|
||||||
ex de, hl
|
|
||||||
call printHexPair
|
|
||||||
call printcrlf
|
|
||||||
ld hl, .msg
|
|
||||||
call printstr
|
|
||||||
jp fail
|
|
||||||
.msg:
|
|
||||||
.db "HL != DE", CR, LF, 0
|
|
||||||
|
|
||||||
nexttest:
|
|
||||||
ld a, (testNum)
|
|
||||||
inc a
|
|
||||||
ld (testNum), a
|
|
||||||
ret
|
|
||||||
|
|
||||||
fail:
|
|
||||||
ld a, (testNum)
|
|
||||||
halt
|
|
@ -11,7 +11,7 @@ APPS="${BASE}/apps"
|
|||||||
|
|
||||||
chk() {
|
chk() {
|
||||||
echo "Running test $1"
|
echo "Running test $1"
|
||||||
if ! ${ZASM} "${KERNEL}" "${APPS}" common.asm < $1 | ${RUNBIN}; then
|
if ! ${ZASM} "${KERNEL}" "${APPS}" < $1 | ${RUNBIN}; then
|
||||||
echo "failed with code ${PIPESTATUS[1]}"
|
echo "failed with code ${PIPESTATUS[1]}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@ -22,7 +22,7 @@ if [ ! -z $1 ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for fn in test_*.asm; do
|
for fn in *.asm; do
|
||||||
chk "${fn}"
|
chk "${fn}"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
jp test
|
jp test
|
||||||
|
|
||||||
.inc "ascii.h"
|
|
||||||
.inc "core.asm"
|
.inc "core.asm"
|
||||||
.inc "str.asm"
|
.inc "str.asm"
|
||||||
.inc "lib/util.asm"
|
.inc "lib/util.asm"
|
||||||
@ -9,9 +8,6 @@ jp test
|
|||||||
.equ EXPR_PARSE parseLiteral
|
.equ EXPR_PARSE parseLiteral
|
||||||
.inc "lib/expr.asm"
|
.inc "lib/expr.asm"
|
||||||
.inc "basic/parse.asm"
|
.inc "basic/parse.asm"
|
||||||
.inc "lib/fmt.asm"
|
|
||||||
.inc "stdio.asm"
|
|
||||||
.inc "common.asm"
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
ld sp, 0xffff
|
ld sp, 0xffff
|
||||||
@ -59,21 +55,21 @@ testParseThruth:
|
|||||||
|
|
||||||
.true:
|
.true:
|
||||||
call parseTruth
|
call parseTruth
|
||||||
call assertZ
|
jp nz, fail
|
||||||
or a
|
or a
|
||||||
call assertNZ
|
jp z, fail
|
||||||
jp nexttest
|
jp nexttest
|
||||||
|
|
||||||
.false:
|
.false:
|
||||||
call parseTruth
|
call parseTruth
|
||||||
call assertZ
|
jp nz, fail
|
||||||
or a
|
or a
|
||||||
call assertZ
|
jp nz, fail
|
||||||
jp nexttest
|
jp nexttest
|
||||||
|
|
||||||
.error:
|
.error:
|
||||||
call parseTruth
|
call parseTruth
|
||||||
call assertNZ
|
jp z, fail
|
||||||
jp nexttest
|
jp nexttest
|
||||||
|
|
||||||
.t1: .db "42", 0
|
.t1: .db "42", 0
|
||||||
@ -92,4 +88,17 @@ testParseThruth:
|
|||||||
.f6: .db "2<=1", 0
|
.f6: .db "2<=1", 0
|
||||||
.e1: .db "foo", 0
|
.e1: .db "foo", 0
|
||||||
|
|
||||||
STDIO_RAMSTART:
|
testNum: .db 1
|
||||||
|
|
||||||
|
nexttest:
|
||||||
|
ld a, (testNum)
|
||||||
|
inc a
|
||||||
|
ld (testNum), a
|
||||||
|
ret
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ld a, (testNum)
|
||||||
|
halt
|
||||||
|
|
||||||
|
; used as RAM
|
||||||
|
sandbox:
|
||||||
|
@ -5,14 +5,8 @@
|
|||||||
|
|
||||||
jp test
|
jp test
|
||||||
|
|
||||||
.inc "ascii.h"
|
|
||||||
.inc "core.asm"
|
|
||||||
.inc "lib/ari.asm"
|
|
||||||
.inc "lib/fmt.asm"
|
|
||||||
.inc "stdio.asm"
|
|
||||||
.inc "common.asm"
|
|
||||||
|
|
||||||
dummyLabel:
|
dummyLabel:
|
||||||
|
testNum: .db 1
|
||||||
|
|
||||||
.equ dummyLabel 0x42
|
.equ dummyLabel 0x42
|
||||||
|
|
||||||
@ -43,25 +37,37 @@ test:
|
|||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
; Test that .equ can override label
|
; Test that .equ can override label
|
||||||
ld de, 0x42
|
ld a, 0x42
|
||||||
ld hl, dummyLabel
|
ld hl, dummyLabel
|
||||||
call assertEQW
|
cp l
|
||||||
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
; test that "@" is updated by a .org directive
|
; test that "@" is updated by a .org directive
|
||||||
ld hl, AFTER_ORG
|
ld hl, AFTER_ORG
|
||||||
ld de, 0x1234
|
ld de, 0x1234
|
||||||
call assertEQW
|
or a ; clear carry
|
||||||
|
sbc hl, de
|
||||||
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
; test that AND affects the Z flag
|
; test that AND affects the Z flag
|
||||||
ld a, 0x69
|
ld a, 0x69
|
||||||
and 0x80
|
and 0x80
|
||||||
call assertZ
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
; success
|
; success
|
||||||
xor a
|
xor a
|
||||||
halt
|
halt
|
||||||
|
|
||||||
STDIO_RAMSTART:
|
nexttest:
|
||||||
|
ld a, (testNum)
|
||||||
|
inc a
|
||||||
|
ld (testNum), a
|
||||||
|
ret
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ld a, (testNum)
|
||||||
|
halt
|
||||||
|
|
||||||
|
@ -9,12 +9,10 @@
|
|||||||
|
|
||||||
jp test
|
jp test
|
||||||
|
|
||||||
.inc "ascii.h"
|
|
||||||
.inc "core.asm"
|
.inc "core.asm"
|
||||||
.inc "str.asm"
|
.inc "str.asm"
|
||||||
.inc "lib/util.asm"
|
.inc "lib/util.asm"
|
||||||
.inc "lib/ari.asm"
|
.inc "lib/ari.asm"
|
||||||
.inc "lib/fmt.asm"
|
|
||||||
.inc "zasm/util.asm"
|
.inc "zasm/util.asm"
|
||||||
.inc "zasm/const.asm"
|
.inc "zasm/const.asm"
|
||||||
.inc "lib/parse.asm"
|
.inc "lib/parse.asm"
|
||||||
@ -23,9 +21,6 @@ jp test
|
|||||||
.inc "zasm/symbol.asm"
|
.inc "zasm/symbol.asm"
|
||||||
.equ EXPR_PARSE parseNumberOrSymbol
|
.equ EXPR_PARSE parseNumberOrSymbol
|
||||||
.inc "lib/expr.asm"
|
.inc "lib/expr.asm"
|
||||||
.equ STDIO_RAMSTART SYM_RAMEND
|
|
||||||
.inc "stdio.asm"
|
|
||||||
.inc "common.asm"
|
|
||||||
|
|
||||||
; Pretend that we aren't in first pass
|
; Pretend that we aren't in first pass
|
||||||
zasmIsFirstPass:
|
zasmIsFirstPass:
|
||||||
@ -34,6 +29,8 @@ zasmIsFirstPass:
|
|||||||
zasmGetPC:
|
zasmGetPC:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
testNum: .db 1
|
||||||
|
|
||||||
s1: .db "2+2", 0
|
s1: .db "2+2", 0
|
||||||
s2: .db "0x4001+0x22", 0
|
s2: .db "0x4001+0x22", 0
|
||||||
s3: .db "FOO+BAR", 0
|
s3: .db "FOO+BAR", 0
|
||||||
@ -47,22 +44,29 @@ sBAR: .db "BAR", 0
|
|||||||
test:
|
test:
|
||||||
ld sp, 0xffff
|
ld sp, 0xffff
|
||||||
|
|
||||||
; New-style tests
|
|
||||||
call testParseExpr
|
|
||||||
|
|
||||||
; Old-style tests, not touching them now.
|
; Old-style tests, not touching them now.
|
||||||
ld hl, s1
|
ld hl, s1
|
||||||
call parseExpr
|
call parseExpr
|
||||||
call assertZ
|
jp nz, fail
|
||||||
ld hl, 4
|
push ix \ pop hl
|
||||||
call assertEQW
|
ld a, h
|
||||||
|
or a
|
||||||
|
jp nz, fail
|
||||||
|
ld a, l
|
||||||
|
cp 4
|
||||||
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
ld hl, s2
|
ld hl, s2
|
||||||
call parseExpr
|
call parseExpr
|
||||||
call assertZ
|
jp nz, fail
|
||||||
ld hl, 0x4023
|
push ix \ pop hl
|
||||||
call assertEQW
|
ld a, h
|
||||||
|
cp 0x40
|
||||||
|
jp nz, fail
|
||||||
|
ld a, l
|
||||||
|
cp 0x23
|
||||||
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
; before the next test, let's set up FOO and BAR symbols
|
; before the next test, let's set up FOO and BAR symbols
|
||||||
@ -78,32 +82,54 @@ test:
|
|||||||
|
|
||||||
ld hl, s3
|
ld hl, s3
|
||||||
call parseExpr
|
call parseExpr
|
||||||
call assertZ
|
jp nz, fail
|
||||||
ld hl, 0x4020
|
push ix \ pop hl
|
||||||
call assertEQW
|
ld a, h
|
||||||
|
cp 0x40
|
||||||
|
jp nz, fail
|
||||||
|
ld a, l
|
||||||
|
cp 0x20
|
||||||
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
ld hl, s4
|
ld hl, s4
|
||||||
call parseExpr
|
call parseExpr
|
||||||
call assertZ
|
jp nz, fail
|
||||||
ld hl, 0x60
|
push ix \ pop hl
|
||||||
call assertEQW
|
ld a, h
|
||||||
|
or a
|
||||||
|
jp nz, fail
|
||||||
|
ld a, l
|
||||||
|
cp 0x60
|
||||||
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
ld hl, s5
|
ld hl, s5
|
||||||
call parseExpr
|
call parseExpr
|
||||||
call assertZ
|
jp nz, fail
|
||||||
ld hl, 0x3ffd
|
push ix \ pop hl
|
||||||
call assertEQW
|
ld a, h
|
||||||
|
cp 0x3f
|
||||||
|
jp nz, fail
|
||||||
|
ld a, l
|
||||||
|
cp 0xfd
|
||||||
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
ld hl, s6
|
ld hl, s6
|
||||||
call parseExpr
|
call parseExpr
|
||||||
call assertZ
|
jp nz, fail
|
||||||
ld hl, 0x4080
|
push ix \ pop hl
|
||||||
call assertEQW
|
ld a, h
|
||||||
|
cp 0x40
|
||||||
|
jp nz, fail
|
||||||
|
ld a, l
|
||||||
|
cp 0x80
|
||||||
|
jp nz, fail
|
||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
|
; New-style tests
|
||||||
|
call testParseExpr
|
||||||
; success
|
; success
|
||||||
xor a
|
xor a
|
||||||
halt
|
halt
|
||||||
@ -125,18 +151,20 @@ testParseExpr:
|
|||||||
call .testEQ
|
call .testEQ
|
||||||
ld iy, .t8
|
ld iy, .t8
|
||||||
call .testEQ
|
call .testEQ
|
||||||
ld iy, .t9
|
|
||||||
call .testEQ
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.testEQ:
|
.testEQ:
|
||||||
push iy \ pop hl
|
push iy \ pop hl
|
||||||
inc hl \ inc hl
|
inc hl \ inc hl
|
||||||
call parseExpr
|
call parseExpr
|
||||||
call assertZ
|
jp nz, fail
|
||||||
ld l, (iy)
|
push ix \ pop de
|
||||||
ld h, (iy+1)
|
ld a, e
|
||||||
call assertEQW
|
cp (iy)
|
||||||
|
jp nz, fail
|
||||||
|
ld a, d
|
||||||
|
cp (iy+1)
|
||||||
|
jp nz, fail
|
||||||
jp nexttest
|
jp nexttest
|
||||||
|
|
||||||
.t1:
|
.t1:
|
||||||
@ -163,6 +191,13 @@ testParseExpr:
|
|||||||
.t8:
|
.t8:
|
||||||
.dw 0xffff
|
.dw 0xffff
|
||||||
.db "-1", 0
|
.db "-1", 0
|
||||||
.t9:
|
|
||||||
.dw 10
|
nexttest:
|
||||||
.db "2*3+4", 0
|
ld a, (testNum)
|
||||||
|
inc a
|
||||||
|
ld (testNum), a
|
||||||
|
ret
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ld a, (testNum)
|
||||||
|
halt
|
||||||
|
Loading…
Reference in New Issue
Block a user