;;; -*- 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