;;; -*- 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 . ;; NameToSymbolExpr: ;; ;; Convert a string into an expression (either a symbol reference or a ;; builtin constant.) ;; ;; If the name matches a known ROM call or other builtin symbol, then ;; return the corresponding argument type and value of the symbol. ;; Otherwise, the name is resolved to a user symbol number. ;; ;; If the result is a user symbol, then increase the symbol's ;; reference count (or, if the symbol does not exist yet, create a new ;; symbol with a reference count of 1.) Be sure that the expression ;; actually gets stored in the program or that UnrefExpr gets called ;; on it afterwards. ;; ;; Input: ;; - HL = start of symbol name (must be in RAM) ;; - IX = end of symbol name ;; ;; Output: ;; - Expression appended to tempExprBuf ;; - A = first byte of expression ;; - Carry flag set if a builtin symbol (not a normal user symbol or ;; anonymous symbol) ;; ;; Destroys: ;; - AF, BC, DE, HL ;; - OP1-OP6 NameToSymbolExpr: ;; throw error if there's not enough space to add a symbol to ;; the buffer ld a,(tempExprLength) inc a call z,Error_ExpressionOverflow ;; mark end of symbol temporarily with a zero ld a,(ix) push af push ix ld (ix),0 ld (OP1),hl ld hl,NameToSymbolExpr_CatchError call APP_PUSH_ERRORH ld hl,(OP1) call NameToSymbol ex de,hl call AppendExprByteD dec b jr z,NameToSymbolExpr_Done ld a,e call AppendExprByteA dec b ld a,c call nz,AppendExprByteA NameToSymbolExpr_Done: call APP_POP_ERRORH pop hl pop af ld (hl),a ld a,d cp X_BYTE ccf ret NameToSymbolExpr_CatchError: pop hl pop af ld (hl),a BCALL _JErrorNo ;; UNREACHABLE ;; NameToSymbol: ;; ;; Convert a string into an expression (either a symbol reference or a ;; builtin constant.) ;; ;; If the name matches a known ROM call or other builtin symbol, then ;; return the corresponding argument type and value of the symbol. ;; Otherwise, the name is resolved to a user symbol number. ;; ;; If the result is a user symbol, then increase the symbol's ;; reference count (or, if the symbol does not exist yet, create a new ;; symbol with a reference count of 1.) Be sure that the expression ;; actually gets stored in the program or that UnrefExpr gets called ;; on it afterwards. ;; ;; Warning: this routine can throw errors for lots of different reasons. ;; ;; Input: ;; - HL = symbol name (zero-terminated) ;; ;; Output: ;; - If result is a single-byte expression (i.e., system flag name), ;; return B = 1 and H = expression value ;; - If result is a two-byte expression (i.e., user symbol or 8-bit ;; system enumeration), return B = 2, H = first byte, and L = second ;; byte ;; - If result is a three-byte expression (i.e., 16-bit system address), ;; return B = 3, H = first byte, L = second byte, and C = third byte ;; ;; Destroys: ;; - AF, BC, DE ;; - OP1-OP6 NameToSymbol: ld a,(hl) cp Ltheta jr nz,NameToSymbol_NotAnon inc hl ld a,(hl) or a jr z,NameToSymbol_NextAnon ld b,a inc hl ld a,(hl) or a jr nz,NameToSymbol_NotAnon2 ld a,b and ~20h cp 'F' ld c,h NameToSymbol_NextAnon: ld b,1 ld h,X_NEXT_ANON ret z dec h cp 'B' ret z ld h,c NameToSymbol_NotAnon2: dec hl dec hl NameToSymbol_NotAnon: call BuiltinNameToSymbol ; scf ret z push hl push ix ex de,hl ld hl,(curProgHeader + PROGHEADER_SYMBOL_STRING_START) inc hl ; skip sentinel ld bc,(curProgHeader + PROGHEADER_SYMBOL_STRING_END) ld ix,SeekCompare_oI8SStr_pZStr call BSearchS pop ix pop de jr nz,NameToSymbol_New call GetProgramDataByte srl a ; A = low 7 bits of symbol number inc hl ld b,h ld c,l ; BC = offset to symbol string ld l,a ld h,0 NameToSymbol_Loop: push hl call GetProgramSymbolInfo or a sbc hl,bc pop hl jr z,NameToSymbol_Found ld de,128 add hl,de jr nc,NameToSymbol_Loop jq_ Error_Bytecode NameToSymbol_Found: ;; HL = symbol number ld b,2 ; bit refParsedSymbols,(iy + asm_Flag3) ; ret z ;; fall through ;; RefSymbol: ;; ;; Increment a symbol's reference count. ;; ;; Input: ;; - HL = symbol number ;; ;; Destroys: ;; - AF, HL RefSymbol: push hl call GetProgramSymbolPtrWrite inc hl inc hl inc (hl) jr nz,RefSymbol_NoOverflow ;; symbol already has 255 (or more) references - leave ref ;; count at 255 dec (hl) RefSymbol_NoOverflow: pop hl ; or a ret ; NameToSymbol_ErrorDNE: ; ld hl,emsg_SymbolUndefined ; ld de,0FFFFh ; call ThrowLineError ; ;; UNREACHABLE NameToSymbol_New: ;; DE = uncompressed symbol ;; HL = offset where we should insert the new symbol ; bit refParsedSymbols,(iy + asm_Flag3) ; jr z,NameToSymbol_ErrorDNE ld bc,(curProgHeader + PROGHEADER_SYMBOL_STRING_START) xor a sbc hl,bc push hl ; string offset where new string will be stored push de ; uncompressed string ;; Search for a free symbol ld h,a ld l,a ld d,a ld e,a call GetProgramSymbolPtrWrite ; ensure program is in RAM push hl ; HL -> start of symbol table ld hl,(curProgHeader + PROGHEADER_SYMBOL_END) call ProgramOffsetToAddress ld b,h ld c,l ; BC -> end of symbol table pop hl NameToSymbol_NewSearchLoop: xor a sbc hl,bc jr nc,NameToSymbol_NewAlloc add hl,bc inc hl inc hl cp (hl) inc hl inc de jr nz,NameToSymbol_NewSearchLoop ex de,hl jr NameToSymbol_NewOK NameToSymbol_NewAlloc: call AppendProgramSymbol inc de inc de xor a ld (de),a ld hl,(curProgSymbolCount) inc hl ld (curProgSymbolCount),hl NameToSymbol_NewOK: ;; HL = new symbol number plus 1 dec hl ld (OP1),hl ld a,l scf rla ; hint byte = 1 + 2 * symbol number ; (for fast lookup; bit 0 is always ; set so we don't need to worry about ; detecting this byte as the end of a ; string) pop de ; uncompressed symbol string ld hl,OP1 + 2 ld (hl),a push hl inc hl call PackSymbolString pop de or a sbc hl,de ld b,h ld c,l ; BC = length of packed string plus hint byte pop de ; target string offset push de ld hl,(curProgHeader + PROGHEADER_SYMBOL_STRING_START) add hl,de call InsDelProgramStringMem ;; Memory succesfully inserted. Now create our new symbol ld hl,OP1 + 2 ldir pop de ld hl,(OP1) ; symbol number push hl call GetProgramSymbolPtrWrite inc de ld (hl),e inc hl ld (hl),d inc hl inc (hl) pop hl ld b,2 ; or a ret ;; UnrefInstruction: ;; ;; Scan an instruction for references to user symbols, and decrement ;; the reference counts of all such symbols. ;; ;; Input: ;; - HL = address of instruction (in RAM) ;; ;; Destroys: ;; - AF, BC, DE, HL UnrefInstruction: ld a,(hl) ld b,a and 3Fh ld c,a inc c inc hl ld a,b and 0C0h jr z,UnrefInstruction_Normal cp T_LABEL jr z,UnrefInstruction_Label cp T_COMMENT ret z ;; special instruction ld a,(hl) add a,a ret c ; special instrs with bit 7 set ; (S_ASCII, S_ASCIZ, S_HEX, S_INCBIN) ; have binary data as arguments, ; rather than standard expressions jr UnrefInstruction_Normal UnrefInstruction_Label: dec hl inc c UnrefInstruction_Normal: inc hl ;; fall through ;; UnrefExprList: ;; ;; Scan an expression list for references to user symbols, and ;; decrement the reference counts of all such symbols. Note that ;; unlike most expression-manipulating routines, this does not throw ;; an error if the expression is invalid. (It may fail to unref some ;; symbols if the expression uses unsupported future extensions, but ;; this is not a critical error.) ;; ;; Input: ;; - HL = address of expression list (in RAM) ;; - C = expression byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL UnrefExprList: dec c ret z ld a,(hl) inc hl add a,a jr c,UnrefExprList_Dec6OrOperator ;; 0xxxxxxx add a,a jr c,UnrefExprList_Constant ;; 00xxxxxx xxxxxxxx: symbol value dec c ret z push hl rrca rrca ld l,(hl) ld h,a call UnrefSymbol pop hl UnrefExprList_Next: inc hl jr UnrefExprList UnrefExprList_Constant: ;; 01xxxxxx add a,a jr c,UnrefExprList_WordConstant ;; 010xxxxx add a,a jr nc,UnrefExprList ; special constant ;; 0101xxxx: byte constant UnrefExprList_OneByte: dec c ret z jr UnrefExprList_Next UnrefExprList_WordConstant: add a,a ret c ; unknown/invalid expression -> be ; safe and don't unref anything ; further ;; 0110xxxx xxxxxxxx xxxxxxxx: word constant dec c ret z inc hl jr UnrefExprList_OneByte UnrefExprList_Dec6OrOperator: ;; 1xxxxxxx add a,a jr c,UnrefExprList ; dec6 constant ;; 10xxxxxx add a,a jr c,UnrefExprList ; binary operator ;; 100xxxxx add a,a ret nc ; unknown/invalid expression -> be ; safe and don't unref anything ; further ;; 1001xxxx jr UnrefExprList ; unary operator ;; UnrefSymbol: ;; ;; Decrement a symbol's reference count. If the new reference count ;; is zero, delete the symbol. ;; ;; Input: ;; - HL = symbol number ;; ;; Destroys: ;; - AF, DE, HL UnrefSymbol: push hl call GetProgramSymbolPtrWrite pop de inc hl inc hl ;; if ref count is 255, we have no way of knowing how many ;; actual refs there are, so leave it at 255 inc (hl) jr z,UnrefSymbol_MaxRefs dec (hl) call z,Error_Bytecode UnrefSymbol_MaxRefs: dec (hl) ret nz ;; symbol is no longer referenced... push bc xor a dec hl ld d,(hl) ld (hl),a dec hl ld e,(hl) ld (hl),a ld hl,(curProgHeader + PROGHEADER_SYMBOL_STRING_START) add hl,de push hl call ProgramOffsetToAddress ld bc,-1 UnrefSymbol_GetLengthLoop: ld a,(hl) inc hl dec bc and 0Fh jr nz,UnrefSymbol_GetLengthLoop pop hl dec hl call InsDelProgramStringMem pop bc ret