Browse Source

lib/expr: use the IX register a bit less

It's an awkward register to use and avoiding its use allows us to strip the
resulting binary significantly. parseEXPR keeps the same signature though.
pull/85/head
Virgil Dupras 4 years ago
parent
commit
501fe96e07
1 changed files with 44 additions and 57 deletions
  1. +44
    -57
      apps/lib/expr.asm

+ 44
- 57
apps/lib/expr.asm View File

@@ -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

Loading…
Cancel
Save