;;; -*- TI-Asm -*-
;;;
;;; Mimas - Assembly language IDE for the TI-83 Plus
;;;
;;; Copyright (C) 2010 Benjamin Moody
;;;
;;; This program is free software: you can redistribute it and/or
;;; modify it under the terms of the GNU General Public License as
;;; published by the Free Software Foundation; either version 3 of the
;;; License, or (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;; General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see .
;; EvalExpr:
;;
;; Retrieve the value of an expression. Note that we don't bother
;; computing expression values during the first assembly pass. (Most
;; special instructions, whose behavior depends on the output value,
;; should use EvalExprAlways instead.)
;;
;; Throw an error if the expression is not constant (i.e., includes
;; one or more X_REGVAL subexpressions.)
;;
;; Input:
;; - IX = expression pointer
;; - C = expression byte count + 1
;;
;; Output:
;; - IX and C updated
;; - Carry flag set if expression incomplete (i.e., no arguments left)
;; - HL = expression value (zero if expression is null; undefined if
;; expression is non-null but incomplete)
;;
;; Destroys:
;; - AF
EvalExpr:
ld hl,0
ld a,(asmPassNumber)
dec a
jr nz,EvalExprAlways
push ix
ex (sp),hl
call SkipExprHL
ex (sp),hl
pop ix
ret
EvalExprAlways:
dec c
scf
ret z
ld a,(ix)
inc ix
ld h,a
add a,a
jr c,EvalExpr_Dec6OrOperator
;; 0xxxxxxx
add a,a
jr c,EvalExpr_Constant
;; 00xxxxxx xxxxxxxx: symbol value
dec c
scf
ret z
ld l,(ix)
inc ix
EvalExpr_Symbol:
push hl
call GetAsmSymbolValue
or a
jr nz,EvalExpr_SymbolOK
;; allow undefined symbols during pass 1
ld hl,0
ld a,(asmPassNumber)
dec a
jr z,EvalExpr_SymbolOK
pop de
ld hl,emsg_SymbolUndefined
call ThrowLineError
;; UNREACHABLE
EvalExpr_SymbolOK:
pop af
or a
ret
EvalExpr_Constant:
;; 01xxxxxx
add a,a
jr c,EvalExpr_WordConstant
;; 010xxxxx
add a,a
jr c,EvalExpr_ByteConstant
;; 0100xxxx: special constant
ld a,h
ld hl,(asmLineExecPC)
ret z
ld hl,(asmLineLoadPC)
cp X_LOADPC
ret z
cp X_NEXT_ANON + 1
call nc,Error_Bytecode
ld h,a
jr EvalExpr_Symbol
EvalExpr_ByteConstant:
;; 0101xxxx xxxxxxxx: byte constant
dec c
scf
ret z
ld l,(ix)
inc ix
ld h,0
or a
ret
EvalExpr_WordConstant:
add a,a
call c,Error_Bytecode
;; 0110xxxx xxxxxxxx xxxxxxxx: word constant
dec c
scf
ret z
dec c
ret z
ld l,(ix)
inc ix
ld h,(ix)
inc ix
or a
ret
EvalExpr_Dec6OrOperator:
;; 1xxxxxxx
add a,a
jr c,EvalExpr_Dec6
;; 10xxxxxx
add a,a
jr c,EvalExpr_Binary
;; 100xxxxx
add a,a
call nc,Error_Bytecode
;; 1001xxxx : unary operator
push hl
call StackCheck
call EvalExprAlways
jr c,EvalExpr_UnaryIncomplete
pop af
and 0Fh
jr z,EvalExpr_UnaryLSB
dec a
jr z,EvalExpr_UnaryMSB
dec a
jr z,EvalExpr_UnaryMinus
dec a
jr z,EvalExpr_UnaryComplement
dec a
jr z,EvalExpr_UnaryNot
dec a
jq z,EvalExpr
dec a
call nz,Error_Bytecode
jq_ Error_ExpressionNotConstant
EvalExpr_UnaryNot: ; !
ld a,h
or l
sub 1
sbc a,a
inc a
ld h,a
EvalExpr_UnaryMSB: ; msb()
ld l,h
EvalExpr_UnaryLSB: ; lsb()
ld h,0
ret
EvalExpr_UnaryComplement: ; ~
inc hl
EvalExpr_UnaryMinus: ; -
NegHL:
xor a
sub l
ld l,a
sbc a,a
sub h
ld h,a
ret
EvalExpr_UnaryIncomplete:
pop hl
ret
EvalExpr_Dec6:
;; 11xxxxxx: small decimal constant
rrca
rrca
ld l,a
ld h,0
ret
EvalExpr_Binary:
;; 101xxxxx : binary operator
push de
push hl
call StackCheck
call EvalExprAlways
jr c,EvalExpr_BinaryIncomplete
push hl
call EvalExprAlways
ex de,hl
pop hl
jr c,EvalExpr_BinaryIncomplete
pop af
; cp X_OR + 1
; call nc,Error_Bytecode
; push hl
; ld h,high(binaryOperatorEvalTable)
; add a,a
; add a,low(binaryOperatorEvalTable - 2 * X_BINARY)
; ld l,a
; call LdHLInd
; ex (sp),hl
; ret ; SPECIALJUMP
SWITCH_BEGIN
SWITCH_CASE X_MUL, EvalExpr_BinaryMul
SWITCH_CASE X_DIV, EvalExpr_BinaryDiv
SWITCH_CASE X_MOD, EvalExpr_BinaryMod
SWITCH_CASE X_ADD, EvalExpr_BinaryAdd
SWITCH_CASE X_SUB, EvalExpr_BinarySub
SWITCH_CASE X_LSHIFT, EvalExpr_BinaryLShift
SWITCH_CASE X_RSHIFT, EvalExpr_BinaryRShift
SWITCH_CASE X_GREATER, EvalExpr_BinaryGreater
SWITCH_CASE X_LESS, EvalExpr_BinaryLess
SWITCH_CASE X_GE, EvalExpr_BinaryGE
SWITCH_CASE X_LE, EvalExpr_BinaryLE
SWITCH_CASE X_EQUAL, EvalExpr_BinaryEqual
SWITCH_CASE X_NE, EvalExpr_BinaryNE
SWITCH_CASE X_AND, EvalExpr_BinaryAnd
SWITCH_CASE X_XOR, EvalExpr_BinaryXor
SWITCH_CASE X_OR, EvalExpr_BinaryOr
SWITCH_END
call Error_Bytecode
;; UNREACHABLE
EvalExpr_BinaryIncomplete:
pop hl
pop de
ret
; binaryOperatorEvalTable:
; dw EvalExpr_BinaryMul, EvalExpr_BinaryDiv
; dw EvalExpr_BinaryMod, EvalExpr_BinaryAdd
; dw EvalExpr_BinarySub, EvalExpr_BinaryLShift
; dw EvalExpr_BinaryRShift, EvalExpr_BinaryGreater
; dw EvalExpr_BinaryLess, EvalExpr_BinaryGE
; dw EvalExpr_BinaryLE, EvalExpr_BinaryEqual
; dw EvalExpr_BinaryNE, EvalExpr_BinaryAnd
; dw EvalExpr_BinaryXor, EvalExpr_BinaryOr
; NO_BYTE_CARRY binaryOperatorEvalTable
;;; Binary operators: in all of the following cases, HL = first arg,
;;; DE = second arg
EvalExpr_BinaryMul: ; *
push bc
call Mul_HL_DE
pop bc
jr EvalExpr_BinaryDone_HL
EvalExpr_BinaryDiv: ; /
call SignedDiv_HL_DE
jr EvalExpr_BinaryDone_HL
EvalExpr_BinaryMod: ; %
call SignedDiv_HL_DE
EvalExpr_BinaryDone_DE:
ex de,hl
jr EvalExpr_BinaryDone_HL
EvalExpr_BinaryAdd: ; +
add hl,de
jr EvalExpr_BinaryDone_HL
EvalExpr_BinarySub: ; -
sbc hl,de
jr EvalExpr_BinaryDone_HL
EvalExpr_BinaryLShift: ; <<
ex de,hl
EvalExpr_BinaryLShift_Loop:
add hl,hl
dec e
jr nz,EvalExpr_BinaryLShift_Loop
jr EvalExpr_BinaryDone_HL
EvalExpr_BinaryRShift: ; >>
EvalExpr_BinaryRShift_Loop:
srl d
rr e
dec l
jr nz,EvalExpr_BinaryRShift_Loop
jr EvalExpr_BinaryDone_DE
EvalExpr_BinaryGreater: ; >
ex de,hl
EvalExpr_BinaryLess: ; <
sbc hl,de
add hl,hl ; C^V if (HL - DE) < 0
EvalExpr_BinaryDone_CxV:
ccf
EvalExpr_BinaryDone_NCxV:
jp po,EvalExpr_BinaryDone_NC
ccf
EvalExpr_BinaryDone_NC:
sbc a,a
inc a
ld h,0
ld l,a
jr EvalExpr_BinaryDone_HL
EvalExpr_BinaryLE: ; <=
ex de,hl
EvalExpr_BinaryGE: ; >=
sbc hl,de
add hl,hl ; NC^V if (HL - DE) >= 0
jr EvalExpr_BinaryDone_NCxV
EvalExpr_BinaryEqual: ; ==
sbc hl,de
ld a,h
or l
add a,-1
jr EvalExpr_BinaryDone_NC
EvalExpr_BinaryNE: ; !=
sbc hl,de
ld a,h
or l
sub 1
jr EvalExpr_BinaryDone_NC
EvalExpr_BinaryAnd: ; &
ld a,l
and e
ld l,a
ld a,h
and d
jr EvalExpr_BinaryDone_AL
EvalExpr_BinaryXor: ; ^
ld a,l
xor e
ld l,a
ld a,h
xor d
jr EvalExpr_BinaryDone_AL
EvalExpr_BinaryOr: ; |
ld a,l
or e
ld l,a
ld a,h
or d
EvalExpr_BinaryDone_AL:
ld h,a
EvalExpr_BinaryUnknown:
EvalExpr_BinaryDone_HL:
pop de
or a
ret