;;; -*- 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 . ;; ReturnIfConditionalUnsuccessful: ;; ;; Return to caller's caller if there is currently an unsuccessful ;; conditional active (and therefore only conditional instructions ;; should have any effect.) ;; ;; Destroys: ;; - AF ReturnIfConditionalUnsuccessful: ld a,(asmConditionalSkipCount) or a ret z pop af ; GETRETURN ret ;; GetExprLiteralSymbol: ;; ;; Get a literal symbol argument. (Note that literal symbol arguments ;; are big-endian, just as in expressions.) ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Output: ;; - If an anonymous symbol, H = X_PREV_ANON or X_NEXT_ANON ;; - Otherwise, HL = symbol number ;; ;; Destroys: ;; - F GetExprLiteralSymbol: dec c ret z ld h,(ix) inc ix bit 6,h ret nz dec c ret z ld l,(ix) inc ix ret ;; DoALIGN: ;; ;; Align program counter to next multiple of the argument value. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoALIGN: call ReturnIfConditionalUnsuccessful call EvalExprAlways ld a,h or l jq z,Error_DivideBy0_IfNotFirstPass ex de,hl ld hl,(asmLoadPC) call Div_HL_DE ld a,h or l ret z ex de,hl sbc hl,de jr IncreasePC ;; DoASCII: ;; ;; Insert literal character values. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoHEX: DoASCII: call ReturnIfConditionalUnsuccessful DoASCII_Loop: dec c ret z ld a,(ix) inc ix call EmitByte jr DoASCII_Loop ;; DoASCIZ: ;; ;; Insert literal character values plus a zero terminator. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoASCIZ: call ReturnIfConditionalUnsuccessful call DoASCII_Loop xor a jq_ EmitByte ;; DoASSERT: ;; ;; Stop assembly with an error message if the given expression is ;; nonzero. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoASSERT: call ReturnIfConditionalUnsuccessful ld a,(asmPassNumber) dec a ret z call EvalExprAlways ld a,h or l ret nz ld hl,emsg_AssertionFailed call ThrowLineError ;; UNREACHABLE ;; DoBCALL: ;; ;; Insert a B_CALL. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoBCALL: call ReturnIfConditionalUnsuccessful ld a,0EFh call EmitByteExec call EvalExpr jq_ EmitWord ;; DoBLOCK: ;; ;; Skip a block of program addresses without assigning values to them. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoBLOCK: call ReturnIfConditionalUnsuccessful call EvalExprAlways IncreasePC: ex de,hl IncreasePC_DE: ld hl,(asmLoadPC) add hl,de ld (asmLoadPC),hl jr c,IncreasePC_Error ld hl,(asmExecPC) add hl,de ld (asmExecPC),hl ret nc IncreasePC_Error: BCALL _ErrOverflow ;; UNREACHABLE ;; DoBJUMP: ;; ;; Insert a B_JUMP. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoBJUMP: call ReturnIfConditionalUnsuccessful ld a,0CDh call EmitByteExec ld hl,0050h call EmitWord call EvalExpr jq_ EmitWord ;; DoBREAK: ;; ;; Insert a breakpoint. If an expression is supplied, the breakpoint ;; is ignored if the expression evaluates to zero. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoBREAK0: DoBREAK1: ;; not yet implemented ret ;; DoBYTE: ;; ;; Insert argument values into the program as bytes. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoBYTE: call ReturnIfConditionalUnsuccessful DoBYTE_Loop: call EvalExpr ret c call RangeCheckByte ld a,l call EmitByte jr DoBYTE_Loop ;; DoELSE: ;; ;; Invert last conditional. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, HL DoELSE: ld hl,(asmConditionalCount) ;; are we currently in an unsuccessful conditional? ld a,h or a jr z,DoELSE_NoUnsuccessfulConditional ;; if we're in more than one unsuccessful conditional, nothing ;; changes dec h ret nz ;; otherwise, current conditional changes to successful inc l jr DoELSE_SetCount DoELSE_NoUnsuccessfulConditional: ;; are we currently in a successful conditional? or l jr z,Error_UnmatchedELSE ;; current conditional changes to unsuccessful dec l inc h DoELSE_SetCount: ld (asmConditionalCount),hl ret nz jr Error_TooManyConditionals Error_UnmatchedELSE: ld hl,emsg_UnmatchedELSE call ThrowLineError ;; UNREACHABLE ;; DoENDIF: ;; ;; End a conditional. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, HL DoENDIF: ld hl,(asmConditionalCount) ld a,h or a jr nz,DoENDIF_Unsuccessful or l jr z,Error_UnmatchedENDIF dec a ld (asmConditionalCount),a ret DoENDIF_Unsuccessful: dec a ld (asmConditionalSkipCount),a ret Error_UnmatchedENDIF: ld hl,emsg_UnmatchedENDIF call ThrowLineError ;; UNREACHABLE ;; DoEQU: ;; ;; Set a symbol to a given value. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoEQU: call ReturnIfConditionalUnsuccessful call GetExprLiteralSymbol push hl call EvalExprAlways pop de jq_ SetAsmSymbolValue ;; DoIF: ;; ;; Begin a conditional that is successful if the argument value is ;; nonzero. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoIF: call EvalExprAlways ld a,h or l DoIF_Check: jr z,DoIF_Unsuccessful DoIF_Successful: ld hl,asmConditionalSkipCount ld a,(hl) or a jr nz,DoIF_Skipped dec hl inc (hl) ret nz jr Error_TooManyConditionals DoIF_Unsuccessful: ld hl,asmConditionalSkipCount DoIF_Skipped: inc (hl) ret nz Error_TooManyConditionals: ld hl,emsg_TooManyConditionals call ThrowLineError ;; UNREACHABLE ;; DoIFDEF: ;; ;; Begin a conditional that is successful if the argument (which must ;; be a symbol) has been assigned a value. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoIFDEF: call GetExprLiteralSymbol call GetAsmSymbolValue ccf jr DoIFNDEF_Check ;; DoIFNDEF: ;; ;; Begin a conditional that is successful if the argument (which must ;; be a symbol) has not been assigned a value. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoIFNDEF: call GetExprLiteralSymbol call GetAsmSymbolValue DoIFNDEF_Check: sbc a,a jr DoIF_Check ;; DoINCBIN: ;; ;; Insert the contents of a binary file. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoINCBIN: call ReturnIfConditionalUnsuccessful ld de,OP1 push ix pop hl ld b,0 ldir dec de xor a ld (de),a call ChkFindSymVarDataStart jr c,DoINCBIN_Error call Load_DE_AHL bit inFinalPass,(iy + asm_Flag1) jr z,DoINCBIN_Quick ld c,a DoINCBIN_Loop: ld a,d or e ret z ld a,c call Inc_AHL call Load_B_AHL ld c,a ld a,b call EmitByte dec de jr DoINCBIN_Loop DoINCBIN_Quick: ld a,d or e ret z call EmitByte dec de dec de call IncreasePC_DE jq_ EmitByte DoINCBIN_Error: BCALL _OP1ToOP6 ld hl,emsg_FileNotFound ld de,OP6 + 1 call ThrowLineError ;; UNREACHABLE ;; DoJQ1: ;; ;; Insert an unconditional jump to the given location; use either a JR ;; or a JP instruction depending on how far away the target is. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoJQ1: call ReturnIfConditionalUnsuccessful call EvalExpr ld bc,0C318h jr DoJQ_Main ;; DoJQ2: ;; ;; Insert a conditional jump to the given location; use either a JR or ;; a JP instruction depending on how far away the target is. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoJQ2: call ReturnIfConditionalUnsuccessful call EvalExpr push hl call EvalExpr pop bc ; C = condition ld a,c and 7 rlca rlca rlca or 20h ld c,a add a,0C2h - 20h ld b,a DoJQ_Main: ;; HL = target address ;; B = absolute jump opcode ;; C = relative jump opcode call IsRelativeJump jr c,DoJQ_Absolute ld a,c call EmitByteExec ld a,l jq_ EmitByte DoJQ_Absolute: ld a,b call EmitByteExec jq_ EmitWord ;; IsRelativeJump: ;; ;; Check if a jump to address HL can be made with a JR instruction. ;; ;; Input: ;; - HL = address ;; ;; Output: ;; - If a relative jump is possible, NC set and L = delta ;; - If a relative jump is impossible, C set and HL = address ;; ;; Destroys: ;; - AF, DE IsRelativeJump: ;; if in pass 1, always use relative jumps (i.e., start out by ;; assuming the smallest possible program) ld a,(asmPassNumber) cp 1 ret z push hl ;; subtract (execPC) plus 2 (since we haven't written the ;; opcode yet) ld de,(asmExecPC) scf sbc hl,de dec hl ld a,l add a,a ld a,h rla xor h jr nz,IsRelativeJump_No pop de ret IsRelativeJump_No: pop hl scf ret ;; DoORG: ;; ;; Set the current program load and execution addresses. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoORG: call ReturnIfConditionalUnsuccessful call EvalExprAlways ld (asmLoadPC),hl jr DoRORG_Set ;; DoRORG: ;; ;; Set the current program execution address. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL DoRORG: call ReturnIfConditionalUnsuccessful call EvalExprAlways DoRORG_Set ld (asmExecPC),hl ret ;; DoWORD: ;; ;; Insert argument values into the program as words. ;; ;; Input: ;; - IX = argument pointer ;; - C = argument byte count + 1 ;; ;; Destroys: ;; - AF, BC, DE, HL, IX DoWORD: call ReturnIfConditionalUnsuccessful DoWORD_Loop: call EvalExpr ret c call EmitWord jr DoWORD_Loop