|
@@ -1,6 +1,7 @@ |
|
|
; *** Requirements *** |
|
|
; *** Requirements *** |
|
|
; findchar |
|
|
; findchar |
|
|
; multDEBC |
|
|
; multDEBC |
|
|
|
|
|
; callIXI |
|
|
; |
|
|
; |
|
|
; *** Defines *** |
|
|
; *** Defines *** |
|
|
; |
|
|
; |
|
@@ -14,6 +15,9 @@ |
|
|
; **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 de |
|
|
push de |
|
|
push hl |
|
|
push hl |
|
@@ -38,15 +42,16 @@ _parseExpr: |
|
|
; Operator found, string splitted. Left in (HL), right in (DE) |
|
|
; Operator found, string splitted. Left in (HL), right in (DE) |
|
|
call _resolveLeftAndRight |
|
|
call _resolveLeftAndRight |
|
|
; Whether _resolveLeftAndRight was a success, we pop our lvl 1 stack |
|
|
; Whether _resolveLeftAndRight was a success, we pop our lvl 1 stack |
|
|
; out, which contains our operator row. We pop it in HL because we |
|
|
|
|
|
; don't need our string anymore. L-R numbers are parsed, and in DE and |
|
|
|
|
|
; IX. |
|
|
|
|
|
pop hl ; <-- lvl 1 |
|
|
|
|
|
|
|
|
; out, which contains our operator row. We pop it in IX. |
|
|
|
|
|
; L-R numbers are parsed in HL (left) and DE (right). |
|
|
|
|
|
pop ix ; <-- lvl 1 |
|
|
ret nz |
|
|
ret nz |
|
|
; Resolving left and right succeeded, proceed! |
|
|
; Resolving left and right succeeded, proceed! |
|
|
inc hl ; point to routine pointer |
|
|
|
|
|
call intoHL |
|
|
|
|
|
jp (hl) |
|
|
|
|
|
|
|
|
inc ix ; point to routine pointer |
|
|
|
|
|
call callIXI |
|
|
|
|
|
push de \ pop ix |
|
|
|
|
|
cp a ; ensure Z |
|
|
|
|
|
ret |
|
|
|
|
|
|
|
|
; Given a string in (HL) and a separator char in A, return a splitted string, |
|
|
; Given a string in (HL) and a separator char in A, return a splitted string, |
|
|
; that is, the same (HL) string but with the found A char replaced by a null |
|
|
; that is, the same (HL) string but with the found A char replaced by a null |
|
@@ -90,7 +95,7 @@ _findAndSplit: |
|
|
.find: |
|
|
.find: |
|
|
|
|
|
|
|
|
; 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 |
|
|
; DE (left) and IX (right) |
|
|
|
|
|
|
|
|
; HL (left) and DE (right) |
|
|
_resolveLeftAndRight: |
|
|
_resolveLeftAndRight: |
|
|
call parseExpr |
|
|
call parseExpr |
|
|
ret nz ; return immediately if error |
|
|
ret nz ; return immediately if error |
|
@@ -98,12 +103,14 @@ _resolveLeftAndRight: |
|
|
; IX. What we need to do now is the same thing on (DE) and then apply |
|
|
; 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. |
|
|
; the + operator. Let's save IX somewhere and parse this. |
|
|
ex de, hl ; right expr now in HL |
|
|
ex de, hl ; right expr now in HL |
|
|
push ix |
|
|
|
|
|
pop de ; numeric left expr result in DE |
|
|
|
|
|
jp parseExpr |
|
|
|
|
|
|
|
|
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 IX. |
|
|
|
|
|
|
|
|
; and IX (right), apply the operator and put the resulting number in DE. |
|
|
; The table has 3 bytes per row: 1 byte for operator and 2 bytes for routine |
|
|
; The table has 3 bytes per row: 1 byte for operator and 2 bytes for routine |
|
|
; pointer. |
|
|
; pointer. |
|
|
exprTbl: |
|
|
exprTbl: |
|
@@ -130,107 +137,87 @@ exprTbl: |
|
|
.db 0 ; end of table |
|
|
.db 0 ; end of table |
|
|
|
|
|
|
|
|
.plus: |
|
|
.plus: |
|
|
add ix, de |
|
|
|
|
|
cp a ; ensure Z |
|
|
|
|
|
|
|
|
add hl, de |
|
|
|
|
|
ex de, hl |
|
|
ret |
|
|
ret |
|
|
|
|
|
|
|
|
.minus: |
|
|
.minus: |
|
|
push ix |
|
|
|
|
|
pop hl |
|
|
|
|
|
ex de, hl |
|
|
|
|
|
scf \ ccf |
|
|
|
|
|
|
|
|
or a ; clear carry |
|
|
sbc hl, de |
|
|
sbc hl, de |
|
|
push hl |
|
|
|
|
|
pop ix |
|
|
|
|
|
cp a ; ensure Z |
|
|
|
|
|
|
|
|
ex de, hl |
|
|
ret |
|
|
ret |
|
|
|
|
|
|
|
|
.mult: |
|
|
.mult: |
|
|
push ix \ pop bc |
|
|
|
|
|
call multDEBC |
|
|
|
|
|
push hl \ pop ix |
|
|
|
|
|
cp a ; ensure Z |
|
|
|
|
|
|
|
|
ld b, h |
|
|
|
|
|
ld c, l |
|
|
|
|
|
call multDEBC ; --> HL |
|
|
|
|
|
ex de, hl |
|
|
ret |
|
|
ret |
|
|
|
|
|
|
|
|
.div: |
|
|
.div: |
|
|
; divide takes HL/DE |
|
|
; divide takes HL/DE |
|
|
push bc |
|
|
push bc |
|
|
ex de, hl |
|
|
|
|
|
push ix \ pop de |
|
|
|
|
|
call divide |
|
|
call divide |
|
|
push bc \ pop ix |
|
|
|
|
|
|
|
|
ld e, c |
|
|
|
|
|
ld d, b |
|
|
pop bc |
|
|
pop bc |
|
|
cp a ; ensure Z |
|
|
|
|
|
ret |
|
|
ret |
|
|
|
|
|
|
|
|
.mod: |
|
|
.mod: |
|
|
call .div |
|
|
call .div |
|
|
push hl \ pop ix |
|
|
|
|
|
|
|
|
ex de, hl |
|
|
ret |
|
|
ret |
|
|
|
|
|
|
|
|
.and: |
|
|
.and: |
|
|
push ix \ pop hl |
|
|
|
|
|
ld a, h |
|
|
ld a, h |
|
|
and d |
|
|
and d |
|
|
ld h, a |
|
|
|
|
|
|
|
|
ld d, a |
|
|
ld a, l |
|
|
ld a, l |
|
|
and e |
|
|
and e |
|
|
ld l, a |
|
|
|
|
|
push hl \ pop ix |
|
|
|
|
|
cp a ; ensure Z |
|
|
|
|
|
|
|
|
ld e, a |
|
|
ret |
|
|
ret |
|
|
.or: |
|
|
.or: |
|
|
push ix \ pop hl |
|
|
|
|
|
ld a, h |
|
|
ld a, h |
|
|
or d |
|
|
or d |
|
|
ld h, a |
|
|
|
|
|
|
|
|
ld d, a |
|
|
ld a, l |
|
|
ld a, l |
|
|
or e |
|
|
or e |
|
|
ld l, a |
|
|
|
|
|
push hl \ pop ix |
|
|
|
|
|
cp a ; ensure Z |
|
|
|
|
|
|
|
|
ld e, a |
|
|
ret |
|
|
ret |
|
|
|
|
|
|
|
|
.xor: |
|
|
.xor: |
|
|
push ix \ pop hl |
|
|
|
|
|
ld a, h |
|
|
ld a, h |
|
|
xor d |
|
|
xor d |
|
|
ld h, a |
|
|
|
|
|
|
|
|
ld d, a |
|
|
ld a, l |
|
|
ld a, l |
|
|
xor e |
|
|
xor e |
|
|
ld l, a |
|
|
|
|
|
push hl \ pop ix |
|
|
|
|
|
cp a ; ensure Z |
|
|
|
|
|
|
|
|
ld e, a |
|
|
ret |
|
|
ret |
|
|
|
|
|
|
|
|
.rshift: |
|
|
.rshift: |
|
|
push ix \ pop hl |
|
|
|
|
|
ld a, l |
|
|
|
|
|
|
|
|
ld a, e |
|
|
and 0xf |
|
|
and 0xf |
|
|
ret z |
|
|
ret z |
|
|
push bc |
|
|
push bc |
|
|
ld b, a |
|
|
ld b, a |
|
|
.rshiftLoop: |
|
|
.rshiftLoop: |
|
|
srl d |
|
|
|
|
|
rr e |
|
|
|
|
|
|
|
|
srl h |
|
|
|
|
|
rr l |
|
|
djnz .rshiftLoop |
|
|
djnz .rshiftLoop |
|
|
push de \ pop ix |
|
|
|
|
|
|
|
|
ex de, hl |
|
|
pop bc |
|
|
pop bc |
|
|
cp a ; ensure Z |
|
|
|
|
|
ret |
|
|
ret |
|
|
|
|
|
|
|
|
.lshift: |
|
|
.lshift: |
|
|
push ix \ pop hl |
|
|
|
|
|
ld a, l |
|
|
|
|
|
|
|
|
ld a, e |
|
|
and 0xf |
|
|
and 0xf |
|
|
ret z |
|
|
ret z |
|
|
push bc |
|
|
push bc |
|
|
ld b, a |
|
|
ld b, a |
|
|
.lshiftLoop: |
|
|
.lshiftLoop: |
|
|
sla e |
|
|
|
|
|
rl d |
|
|
|
|
|
|
|
|
sla l |
|
|
|
|
|
rl h |
|
|
djnz .lshiftLoop |
|
|
djnz .lshiftLoop |
|
|
push de \ pop ix |
|
|
|
|
|
|
|
|
ex de, hl |
|
|
pop bc |
|
|
pop bc |
|
|
cp a ; ensure Z |
|
|
|
|
|
ret |
|
|
ret |