; DMONT -- DMON6 modified for ISUAL ; Version 7.0 -- 10-Jun-2002 ; ;======================================= * MON85: A software debugger for the 8080/8085 processor * * Copyright 1979-1997 Dave Dunfield * All rights reserved. ; include ioports.i ; this is at address 0000 jmp prom_start ; RST_0 ds 5 jmp entry ; RST_1 ds 5 jmp entry ; RST_2 ds 5 jmp entry ; RST_3 ds 5 jmp entry ; RST_4 ds 1 jmp entry ; TRAP ds 1 jmp entry ; RST_5 ds 1 jmp entry ; RST_55 ds 1 jmp entry ; RST_6 ds 1 jmp entry ; RST_65 ds 1 jmp entry ; RST_7 ds 1 jmp entry ; RST_75 ds 1 * Curt's Debug Pod Serial Interface UART_IN equ 0E4h UART_OUT equ 0E4h UART_SETUP equ 0E5h UART_STATUS equ 0E5h * ; copy PROM code into RAM, then switch from PROM to RAM PROM_START: lxi sp,0 ; when starting in PROM, a store in 0000-3FFF goes into ; underlying RAM lxi h,0 ; *** 44h ; start after RST vectors cpylp: mov a,M ; read PROM mov M,a ; write RAM inx h mov a,h cpi 40h ; 4000h is after 3FFF jnz cpylp ; ; the switch has to execute outside of PROM space ; copy a little bit of code up to 8000 lxi d,8000h lxi h,switchcode mvi c,eswc-switchcode cpys: mov a,M stax d inx d inx h dcr c jnz cpys ; execute at 8000h jmp 8000h switchcode: mvi a,0 out PROM_ENBL_O ; switch to RAM nop ; wait at least 2 microsecs nop nop jmp rom_start eswc: ds 1Ch ; Modifications to original Dunfield Debugger: ; ; DTP serial port; watchdog kick while polling I/O ; ; DRAM at EF00h ; ; command "*' added for direct binary upload ; from "U" program into low memory, then switch off PROM ; DRAM EQU 0EF00h Monitor RAM (96 bytes required) * * Debugger data area (in RAM) * * UBASE equ DRAM ; DS 2 Base address of user program HL equ DRAM+2 ; DS 2 Saved HL register pair DE equ DRAM+4 ; DS 2 Saved DE register pair BC equ DRAM+6 ; DS 2 Saved BC register pair PSW equ DRAM+8 ; DS 2 Saved PSW (A + CC) SP equ DRAM+10 ; DS 2 Saved Stack Pointer PC equ DRAM+12 ; DS 2 Saved Program Counter OFLAG equ DRAM+14 ; DS 1 Output suspended flag TFLAG equ DRAM+15 ; DS 1 Flag to enable TRACING SFLAG equ DRAM+16 ; DS 1 Flag to enable SUBROUTINE tracing AFLAG equ DRAM+17 ; DS 1 Flag to enable AUTO REGISTER DISPLAY BRKTAB equ DRAM+18 ; DS 24 Breakpoint table INST equ DRAM+42 ; DS 6 Save area for "faking" instructions BUFFER equ DRAM+48 ; DS 48 Input/temp buffer & stack DSTACK EQU DRAM+96 ; Debugger stack ; ; ; * Startup code... Kick off the monitor * ROM_START: lxi h,0 shld ubase ; ; where control is received after restart LXI SP,DSTACK Set up initial stack pointer JMP TEST Execute main program * Register -> text translation tables used by the disassembler. These tables * go here (near beginning) so that we can be sure the high address will not * cross a page boundary allowing us to index by modifying low address only. * RTAB ASC "BCDEHLMA" Table of register names RPTAB ASC "BDHS" Table of register pairs * * Entry point for breakpoints & program tracing * * Save the user program registers ENTRY SHLD HL Save HL XCHG Get DE SHLD DE Save DE POP H Get RET addrss DCX H Backup to actual SHLD PC Save PC PUSH B Copy BC POP H And get it SHLD BC Save PC PUSH PSW Copy PSW POP H And get it SHLD PSW Save PSW LXI H,0 Start with zero DAD SP Get SP SHLD SP Save SP LXI SP,DSTACK Move to our stack LHLD PC Get instruction back LXI D,BRKTAB Point to breakpoint table MVI B,'0' Assume breakpoint #0 * Search breakpoint table & see if this is a breakpoint TRYBRK LDAX D Get HIGH byte from table INX D Advance CMP H Does it match? LDAX D Get LOW byte from table INX D Advance JNZ NOTBRK No, try next CMP L Does it match? JZ FOUND Yes, we have an entry NOTBRK INX D Skip saved code byte INR B Advance breakpoint number MOV A,B Get breakpoint number CPI '0'+8 Table exausted JC TRYBRK No, keep looking * This interrupt is NOT a breakpoint JMP NOBK Enter with no breakpoint * This interrupt is a breakpoint, display the message FOUND CALL PRTMSG Output message ASC "** Breakpoint " db 0 MOV A,B Get breakpoint number CALL OUTBYTE Output it CALL LFCR New line * Reenter monitor, first, restore all breakpoint opcodes NOBK LXI H,BRKTAB Point to breakpoint table MVI B,8 8 breakpoints FIXL MOV D,M Get HIGH address INX H Advance MOV E,M Get LOW address INX H Advance MOV A,D Get high ORA E Test for ZERO JZ NOFIX Breakpoint is not set MOV A,M Get opcode STAX D And patch user code NOFIX INX H Skip opcode DCR B Reduce count JNZ FIXL Not finished, keep going LDA AFLAG Get auto register display flag ANA A Is it enabled? CNZ REGDIS Yes, display the registers LDA TFLAG Get trace mode flag ANA A Is it enabled? JZ REST No, enter monitor * Prompt for and handle trace mode commands TRTB CALL PRTMSG Output message ASC "T> " Trace mode prompt db 0 TRL CALL INCHR Get a command character CPI ' ' Execute command? JZ NOADR Yes, handle it CPI 1Bh ESCAPE? JZ RECR Yes, abort CPI '?' Register display? JNZ TRL No, ignore it CALL REGDIS Display the registers JMP TRTB And go again * * Main entry point for the 8080 debugger * TEST CALL INIT Set up hardware CALL PRTMSG Output herald message DB 0Ah,0Dh ASC "DMONT - Dunfield Debugger with SSL mods" DB 0Ah,0Dh asc " rev 7.0 - June 10, 2002 - Steve Geller" DB 0Ah,0Dh ASC "original 'MON85' Copyright 1979-1997 Dave Dunfield" DB 0Ah,0Dh asc "All rights reserved." DB 0Ah,0 LXI H,UBASE Point to start of reserved RAM MVI C,DSTACK-UBASE Number of bytes to zero INIL1 MVI M,0 Clear a byte INX H Advance DCR C Reduce count JNZ INIL1 Clear em all LXI H,0FFFFh Set flags SHLD SFLAG Turn on SUBTRACE & AUTOREG LXI H,UBASE Default user stack (below monitor RAM) SHLD SP Set user SP ; display "DMONT" in the LCDs call SHOW_LCD * Newline and prompt for command RECR CALL LFCR Output a newline * Prompt for an input command REST LXI SP,DSTACK Reset stack pointer CALL PRTMSG Output message asc 'D> ' Command prompt db 0 CALL INPT Get command character cpi '*' jz uload * Look up command in table MOV B,A Save for later LXI H,CTABLE Point to command table REST1 MOV A,M Get char INX H Advance CMP B Do it match? JZ REST2 Yes, go for it INX H Skip HIGH address INX H Skip LOW address ANA A end of table? JNZ REST1 Its OK * Error has occured, issue message & return for command ERROR MVI A,'?' Error indicator CALL OUTBYTE Display JMP RECR And wait for command * We have command, execute it REST2 INX D Skip command character MOV A,M Get low address INX H Skip to next MOV H,M Get HIGH address MOV L,A Set LOW CALL SKIP Set 'Z' of no operands PCHL And execute * Table of commands to execute CTABLE DB 'A' Set AUTOREG flag DW AUTO DB 'B' Set/Display breakpoint DW SETBRK DB 'C' Copy memory DW COPY DB 'D' Disassemble DW GODIS DB 'E' Edit memory DW EDIT DB 'F' Fill memory DW FILL DB 'G' Go (begin execution) DW GO DB 'I' Input from port DW INPUT DB 'L' Load from serial port DW LOAD DB 'M' Memory display DW MEMRY DB 'O' Output to port DW OUTPUT DB 'R' Set/Display Registers DW REGIST DB 'S' Set SUBTRACE flag DW SUBON DB 'T' Set TRACE mode DW TRACE DB 'U' Set/Display user base DW USRBASE DB '?' Help command DW HELP DB 0 End of table DW REST Handle NULL command * * Help command * HELP LXI H,HTEXT Point to help text SUB A Get a zero STA OFLAG Clear the output flag * Output each line HELP1 MVI C,25 Column counter HELP2 MOV A,M Get character INX H Advance to next ANA A End of line? JZ HELP4 Yes, terminate CPI '!' Separator? JZ HELP3 Yes, output CALL OUTBYTE Write character DCR C Reduce count JMP HELP2 Keep going * Fill with spaces to discription column HELP3 CALL SPACE Output a space DCR C Reduce count JNZ HELP3 Do them all MVI A,'-' Spperator CALL OUTBYTE Display CALL SPACE And space over JMP HELP2 Output rest of line * End of line encountered... HELP4 CALL CHKSUS New line MOV A,M Get next byte ANA A End of text? JNZ HELP1 Do them all JMP RECR And go home * * Input from port * INPUT CALL CALC Get port number MVI A,0DBh 'IN' instruction MVI H,0C9h 'RET' instruction STA INST Set RAM instruction SHLD INST+1 Set RAM instruction CALL PRTMSG Output message asc 'DATA=' db 0 CALL INST Perform the read CALL HPR Output it JMP RECR Newline & EXIT * * Output to port * OUTPUT CALL CALC Get port number MVI A,0D3h 'OUT' instruction MVI H,0C9h 'RET' instruction STA INST Set RAM instruction SHLD INST+1 Set RAM instruction CALL CALC Get data byte MOV A,L Copy to ACC for out CALL INST Output the data JMP REST Back to command prompt * * Set breakpoint command * SETBRK JZ DISBRK No operands, display breakpoints * Set a breakpoint CALL CALC Get hex operand MOV A,L Get low value of operand CPI 8 In range? JNC ERROR No, invalud LXI H,BRKTAB-3 Point to breakpoint table LXI B,3 Offset for a breakpoint SBRLP DAD B Advance to next breakpoint DCR A Reduce count JP SBRLP Go until we are there PUSH H Save table address CALL CALC Get address POP D Restore address XCHG D=brkpt address, H=table address MOV M,D Set HIGH address in table INX H Advance MOV M,E Set LOW address in table INX H Advance LDAX D Get opcode from memory MOV M,A Save in table JMP REST And get next command * Display breakpoints DISBRK LXI D,BRKTAB Point to breakpoint table MVI B,'0' Begin with breakpoint zero DISLP MVI A,'B' Lead in character CALL OUTBYTE Output MOV A,B Get breakpoint number CALL OUTBYTE Output MVI A,'=' Seperator character CALL OUTBYTE Output LDAX D Get HIGH address MOV H,A Copy INX D Advance LDAX D Get LOW address MOV L,A Copy ORA H Is breakpoint set? JZ NOTSET No, don't display CALL HLOUT Output in hex JMP GIVLF And proceed * Breakpoint is not set NOTSET CALL PRTMSG Output message asc '****' Indicate not set db 0 GIVLF MVI A,' ' Get a space CALL OUTBYTE Output CALL OUTBYTE Output MOV A,B Get breakpoint address CPI '0'+3 Halfway through? CZ LFCR Yes, new line INX D Skip low byte INX D Skip opcode INR B Advance breakpoint number MOV A,B Get number again CPI '0'+8 All done? JC DISLP No, keep going CALL LFCR New line LXI H,AUTMSG Message for AFLAG LDA AFLAG Get flag state CALL DISON Display ON/OFF indication LXI H,SUBMSG Message for SFLAG LDA SFLAG Get flag state CALL DISON Display ON/OFF indication LXI H,TRCMSG Message for TFLAG LDA TFLAG Get flag state CALL DISON Display ON/OFF indication CALL LFCR New line JMP REST Back for another command * Display ON/OFF flag state DISON PUSH PSW Save A CALL PRTSTR Output message POP PSW Restore A LXI H,OFF Assume OFF ANA A Test A JZ PRTSTR Yes, display OFF LXI H,ON Convert to ON JMP PRTSTR And display ON * * GO command, Begin program execution * GO JZ NOHEX Address not given, assume default CALL CALC Get argument SHLD PC Save new PC value NOHEX LDA TFLAG Get trace flag ANA A Enabled? JNZ TRTB Yes, wait for prompt * Single-step one instruction... * Used for first instruction even when NOT tracing, so * that we can insert breakpoints NOADR SUB A Get NOP MOV H,A Set high MOV L,A Set LOW STA INST Set first byte SHLD INST+1 Set second & third LHLD PC Get PC XCHG Set DE to PC CALL LOOK Lookup instruction MOV B,A Save the TYPE/LENGTH byte ANI 03 Mask TYPE, save LENGTH MOV C,A Save for count * Copy instruction into "faking" area LXI H,INST Point to saved instruction GOSET LDAX D Get byte from code MOV M,A Save in instruction INX H Advance output INX D Advance input DCR C Reduce count JNZ GOSET Copy it all XCHG HL = addrss to execute MVI A,0C3h Get a JMP instruction STA INST+3 Set up a JUMP instruction SHLD INST+4 Set target address LDA TFLAG Get trace flag ANA A Are we tracing? JZ NOTRC No, we are not PUSH B Save TYPE/LENGTH LHLD PC Get PC address XCHG Set up 'DE' as operand pointer CALL DINST Disassemble the instruction CALL LFCR New line LHLD INST+4 Get termination address INX H Skip this one SHLD BUFFER Save for "fake" handling LXI H,FAKE Point to FAKE routine SHLD INST+4 Save new addres POP B Restore TYPE/LENGTH * Simulate any control transfer instruction LDA INST Get instruction CPI 0E9h Is it PCHL? JNZ NOPCHL No, its ok LHLD HL Get user HL value JMP HLJMP And simulate a jump NOPCHL MOV A,B Get TYPE back CPI 0Bh Is it a 'JUMP' JZ GOJMP Yes, handle it CPI 05h Is it a 'RETURN' JZ CALRET Yes, handle it ANI 0F8h Save only conditional bits JZ NOTRC Not conditional, always execute instruction ANI 08 Does this test require COMPLEMENTED flags LDA PSW Get status flags JZ NOCOM No need to complement CMA Invert for NOT tests NOCOM MOV C,A Save PSW bits MOV A,B Get conditon back RAL Is it SIGN flag? JC SIGN Yes, handle it RAL Is it ZERO flag? JC ZERO Yes, handle it RAL Is it PARITY flag? JC PARITY Yes, handle it * This instruction is conditional on the CARRY flag CARRY MOV A,C Get flag bits ANI 01h Test CARRY flag JMP ENFLG And proceed * This instruction is conditional on the SIGN flag SIGN MOV A,C Get flag bits ANI 80h Test SIGN flag JMP ENFLG And proceed * This instruction is conditional on the ZERO flag ZERO MOV A,C Get flag bits ANI 40h Test ZERO flag JMP ENFLG And proceed * This instruction is conditional on the PARITY flag PARITY MOV A,C Get flag bits ANI 04 Test PARITY flag * Execute conditional instruction ENFLG JZ NOTRC Not executed MOV A,B Get type back ANI 04 Is it JUMP JNZ CALRET No, try next * Simulate a JUMP instruction GOJMP LDA INST Get instruction CPI 0CDh Is it a CALL JZ PADR Yes ANI 0C7h Mask conditional CPI 0C4h Conditional call? JNZ NOPSH No, its a jump * Simulate a subroutine trace PADR LDA SFLAG Get subroutine tracing flag ANA A Is it set? JZ NOTRC No, simulate as one instruction LHLD BUFFER Get termination address DCX H Backup XCHG D = address LHLD SP Get user SP DCX H Backup MOV M,D Set HIGH return address DCX H Backup MOV M,E Set LOW return address SHLD SP Resave user SP * Continue simulation of a JUMP type instruction NOPSH LHLD INST+1 Get target address JMP HLJMP And proceed * Handle simulation of RETURN instruction CALRET LHLD SP Get sser SP MOV E,M Get LOW return address INX H Advance MOV D,M Get HIGH return address INX H Advance SHLD SP Resave user SP XCHG Set HL = address * Simulate a jump to the address in HL HLJMP INX H Advance SHLD BUFFER Save new target address SUB A Get NOP MOV H,A Set HIGH MOV L,A Set LOW STA INST NOP first byte SHLD INST+1 NOP second byte * Dispatch the user program * First, insert any breakpoints into the object code NOTRC LXI D,BRKTAB Point to breakpoint table MVI C,8 Size of table (in entries) RESBP LDAX D Get a HIGH address MOV H,A Save for later INX D Advance LDAX D Get low address MOV L,A Save for later INX D Advance ORA H Is breakpoint enabled? JZ NORES No, its not MVI M,0CFh Set up a RST 1 breakpoint NORES INX D Skip opcode DCR C Reduce count JNZ RESBP Do them all * Restore the user applications registers LHLD SP Get stack pointer SPHL Set stack pointer LHLD BC Get BC PUSH H Save POP B And set LHLD PSW Get PSW PUSH H Save POP PSW And set LHLD DE Get DE XCHG Set DE LHLD HL Get HL JMP INST Execute "faked" instruction * Trace routine: simulate a breakpoint interrupt FAKE PUSH H Save HL on stack LHLD BUFFER Get address to execute XTHL Restore HL, [SP] = address JMP ENTRY Display the registers * * Display/Change registers * REGIST JNZ CHG1 Register name to change is given * Display registers CALL REGDIS Display registers JMP REST And exit * Set register value CHG1 MOV B,A Save command char CALL GETCHI Get char (in upper case) MOV C,A Save for later JZ OKCH End of string * Drop extra characters incase 'PSW' CHG2 CALL GETCHR Get next JNZ CHG2 Clean them out * Get new value for register OKCH CALL CALC Get new value MOV A,B Get first char CPI 'H' Is it HL pair JNZ CDE No, try next SHLD HL Set HL value JMP REST And proceed CDE CPI 'D' Is it DE pair? JNZ CBC No, try next SHLD DE Set DE value JMP REST And proceed CBC CPI 'B' Is it BC pair? JNZ CSP No, try next SHLD BC Set BC value JMP REST And proceed CSP CPI 'S' Is it SP? JNZ CP No, try next SHLD SP Set SP value JMP REST And proceed CP CPI 'P' Is it PS or PC JNZ ERROR No, error MOV A,C Get low character CPI 'S' Is it PSW? JNZ CPC No, try next SHLD PSW Set new PSW JMP REST And proceed CPC CPI 'C' Is it PC? JNZ ERROR No, error SHLD PC Set new PC JMP REST And proceed * Process an ON/OFF operand ONOFF CALL SKIP Get next char CPI 'O' Must begin with ON JNZ ERROR Invalid CALL GETCHI Get next char MVI B,0 Assume OFF CPI 'F' OFF? JZ RETON Yes, set it CPI 'N' ON? JNZ ERROR No, error DCR B Convert to FF RETON MOV A,B Save new value RET * * Turn automatic register display ON or OFF * AUTO CALL ONOFF Get ON/OFF value STA AFLAG Set AUTOREG flag JMP REST And proceed * * Turn SUBROUTINE tracing ON or OFF * SUBON CALL ONOFF Get ON/OFF value STA SFLAG Set SUBTRACE flag JMP REST And proceed * * Set TRACE mode ON or OFF * TRACE CALL ONOFF Get ON/OFF value STA TFLAG Set TRACE flag JMP REST And proceed * * Edit memory contents * EDIT CALL CALC Get address EDIT1 CALL HLOUT Display address CALL SPACE Separator MOV A,M Get contents CALL HPR Output MVI A,'-' Prompt CALL OUTBYTE Output PUSH H Save address CALL INPT Get a value POP H Restore address INX H Assume advance JZ EDIT1 Null, advance DCX H Fix mistake DCX H Assume backup CPI '-' Backup? JZ EDIT1 Yes, backup a byte INX H Fix mistake CPI 27h Single quote? JNZ EDIT3 No, try hex value * Handle quoted ASCII text INX D Skip the quote EDIT2 LDAX D Get char INX D Advance input ANA A End of loop? JZ EDIT1 Yes, exit MOV M,A Save it INX H Advance output JMP EDIT2 And proceed * Handle HEXIDECIMAL values EDIT3 PUSH H Save address CALL CALC Get HEX value MOV A,L Get value POP H HL = address MOV M,A Set value INX H Advance to next CALL SKIP More operands? JNZ EDIT3 Get then all JMP EDIT1 And continue * * FIll memory with a value * FILL CALL CALC Get starting address PUSH H Save for later CALL CALC Get ending address MOV B,H BC = End address MOV C,L CALL CALC Get value XCHG DE = value POP H HL = Starting address FILL1 MOV M,E Save one byte CALL COMP16 Test for match INX H Advance JC FILL1 And proceed JMP REST Back for next * 16 bit compare of HL to BC COMP16 MOV A,H Get HIGH CMP B Match? RNZ No, we are done MOV A,L Get LOW CMP C Match? RET * * Copy a block of memory * COPY CALL CALC Get SOURCE address PUSH H Save for later CALL CALC Get DEST Address MOV B,H BC = Dest address MOV C,L CALL CALC Get size XCHG DE = Size POP H HL = Source COPY1 MOV A,D Get HIGH size ORA E More to go? JZ REST No, exit MOV A,M Get byte from source STAX B Write to dest INX H Advance source INX B Advance dest DCX D Reduce count JMP COPY1 And proceed * * Display a block of memory * MEMRY CALL CALC Get operand SUB A Get a ZERO STA OFLAG Clear output flag ALOOP CALL HLOUT2 Display address (in hex) with 2 spaces MVI D,16 16 bytes/line PUSH H Save address ALP1 MOV A,M Get byte CALL HPR Output in hex CALL SPACE Space over MOV A,D Get count CPI 9 At boundary? CZ SPACE Yes, extra space MOV A,D Get count ANI 7 Mask for low bits CPI 5 At boundary? CZ SPACE Extra space INX H Advance address DCR D Reduce count JNZ ALP1 Do them all MVI D,4 # separating spaces AL2 CALL SPACE Output a space DCR D Reduce count JNZ AL2 And proceed POP H MVI D,16 16 chars/display AL3 MOV A,M Get data byte CALL OUTP Display (if printable) INX H Advance to next DCR D Reduce count JNZ AL3 Do them all CALL CHKSUS Handle output suspension JMP ALOOP And continue * * Perform disassembly to console * GODIS CALL CALC Get starting address PUSH H Save address POP D Copy to D SUB A Get a zero STA OFLAG Clear output flag VLOOP CALL DINST Display one instruction CALL CHKSUS Handle output JMP VLOOP And proceed * * Set/display user base address * USRBASE JNZ USRB1 Address is given, set it CALL PRTMSG Output message asc 'BASE=' db 0 LHLD UBASE Get address CALL HLOUT Output JMP RECR New line & exit USRB1 CALL CALC Get operand SHLD UBASE Set the address JMP REST and return * * Download command * LOAD MVI A,0Fh Get default initial state JZ LOAD1 Address not given... CALL CALC Get operand value SHLD BUFFER+3 Save for later calulation MVI A,0FFh Set new initial state * Setup the offset calculator LOAD1 LXI H,0 Assume no offset STA BUFFER Set mode flag SHLD BUFFER+1 Assume offset is ZERO * Download the records LOAD2 CALL DLREC Get a record JNZ DLBAD Report error JNC LOAD2 Get them all JMP DLWAIT And back to monitor * Error in receiving download record DLBAD CALL PRTMSG Output message asc '?Load error' DB 0Ah,0Dh,0 * Wait till incoming data stream stops DLWAIT MVI C,0 Initial count DLWAIT1 CALL INBYTE Test for input ANA A Any data JNZ DLWAIT Reset count DCR C Reduce counter JNZ DLWAIT1 Keep looking JMP REST Back to monitor * * Download a record from the serial port * DLREC CALL INCHR Read a character CPI ':' Start of record? JZ DLINT Download INTEL format CPI 'S' Is it MOTOROLA? JNZ DLREC No, keep looking * Download a MOTOROLA HEX format record DLMOT CALL INCHR Get next character CPI '0' Header record? JZ DLREC Yes, skip it CPI '9' End of file? JZ DLEOF Yes, report EOF CPI '1' Type 1 (code) record JNZ DLERR Report error CALL GETBYT Get length MOV C,A Start checksum SUI 3 Convert for overhead MOV B,A Save data length CALL GETBYT Get first byte of address MOV H,A Set HIGH address ADD C Include in checksum MOV C,A And re-save CALL GETBYT Get next byte of address MOV L,A Set LOW address ADD C Include in checksum MOV C,A And re-save CALL SETOFF Handle record offsets DMOT1 CALL GETBYT Get a byte of data MOV M,A Save in memory INX H Advance ADD C Include in checksum MOV C,A And re-save DCR B Reduce length JNZ DMOT1 Keep going CALL GETBYT Get record checksum ADD C Include calculated checksum INR A Adjust for test ANA A Clear carry set Z RET * Download a record in INTEL hex format DLINT CALL GETBYT Get length ANA A End of file? JZ DLEOF Yes, handle it MOV C,A Begin Checksum MOV B,A Record length CALL GETBYT Get HIGH address MOV H,A Set HIGH address ADD C Include in checksum MOV C,A Re-save CALL GETBYT Get LOW address MOV L,A Set LOW address ADD C Include in checksum MOV C,A Re-save CALL SETOFF Handle record offsets CALL GETBYT Get type byte ADD C Include in checksum MOV C,A Re-save DLINT1 CALL GETBYT Get data byte MOV M,A Save in memory INX H Advance to next ADD C Include in checksum MOV C,A Resave checksum DCR B Reduce count JNZ DLINT1 Do entire record CALL GETBYT Get record checksum ADD C Add to computed checksum ANA A Clear carry, set Z RET * End of file on download DLEOF STC Set carry, EOF RET * * Process record offsets for download records * SETOFF LDA BUFFER Get flag ANA A Test flag JNZ SETOF1 Special case * Not first record, adjust for offset & proceed XCHG DE = address LHLD BUFFER+1 Get offset DAD D HL = address + offset RET * First record, set USER BASE & calculate offset (if any) SETOF1 MVI A,0 Get zero (NO CC) STA BUFFER Clear flag SHLD UBASE Set user program base RP No more action * Calculate record offset to RAM area XCHG DE = address LHLD BUFFER+3 Get operand MOV A,L Subtract SUB E Record MOV L,A From MOV A,H Operand SBB D To get MOV H,A Offset SHLD BUFFER+1 Set new offset DAD D Get address RET * * Gets a byte of HEX data from serial port. * GETBYT CALL GETNIB Get first nibble RLC Shift into RLC Upper nibble RLC Of result RLC To make room for lower MOV E,A Keep high digit CALL GETNIB Get second digit ORA E Insert high digit RET * GETS A NIBBLE FROM THE TERMINAL (IN ASCII HEX) GETNIB CALL INCHR Get a character SUI '0' Is it < '0'? JC GETN1 Yes, invalid CPI 10 0-9? RC Yes, its OK SUI 7 Convert CPI 10 9-A? JC GETN1 Yes, invalid CPI 16 A-F? RC Yes, its OK GETN1 POP D Remove GETNIB RET addr POP D Remove GETBYT RET addr * Error during download record DLERR ORI 0FFh Error indicator RET ;shit3: nop * * Read an input line from the console * INPT LXI H,BUFFER Point to input buffer INPT1 CALL INCHR Get a char CPI 1Bh ESCAPE? JZ RECR Back for command CPI 0Dh Carriage return? JZ INPT4 Yes, exit MOV D,A Save for later * Test for DELETE function CPI 05Fh Is it delete? JZ INPT3 Yes, it is CPI 08h Backspace? JZ INPT3 Yes, it is * Insert character in buffer MOV A,L Get low address CPI BUFFER+30 Beyond end? MVI A,7 Assume error JZ INPT2 Yes, report error MOV A,D Get char back MOV M,A Save in memory INX H Advance INPT2 CALL OUTBYTE Echo it JMP INPT1 And proceed * Delete last character from buffer INPT3 MOV A,L Get char CPI BUFFER At begining MVI A,7 Assume error JZ INPT2 Report error PUSH H Save H CALL PRTMSG Output message ;*** DB 8,' ',8,0 Wipe away character db 8 db 20h db 8,0 POP H Restore H DCX H Backup JMP INPT1 And proceed * Terminate the command INPT4 MVI M,0 Zero terminate CALL LFCR New line LXI D,BUFFER Point to input buffer ;shit2: nop * Advance to next non-blank in buffer SKIP LDAX D Get char from buffer INX D Advance CPI ' ' Space? JZ SKIP Yes, keep looking DCX D Backup to it JMP TOCAP And convert to upper * * Read next character from command & convert to upper case * GETCHI INX D Skip next character GETCHR LDAX D Get char from command line ANA A End of line? RZ Yes, return with it INX D Advance command pointer * * Convert character in A to uppercase, set Z if SPACE or EOL * TOCAP CPI 61h Lower case? JC TOCAP1 Yes, its ok ANI 5Fh Convert to UPPER TOCAP1 CPI ' ' Space RZ Yes, indicate ANA A Set 'Z' if EOL RET * * Get HEX operands to command * CALC PUSH B Save B-C CALL SKIP Find start of operand LXI H,0 Begin with zero value MOV C,H Clear flag CALC1 CALL GETCHR Get next char JZ CALC3 End of number CALL VALHEX Is it valid hex? JC ERROR No, report error DAD H HL = HL*2 DAD H HL = HL*4 DAD H HL = HL*8 DAD H HL = HL*16 (Shift over 4 bits) SUI '0' Convert to ASCII CPI 10 Decimal number? JC CALC2 Yes, its ok SUI 7 Convert to HEX CALC2 ORA L Include in final value MOV L,A Resave low bute MVI C,0FFh Set flag & indicate we have char JMP CALC1 And continue * End of input string was found CALC3 MOV A,C Get flag POP B Restore B-C ANA A Was there any digits? JZ ERROR No, invalid RET * Test for character in A as valid hex VALHEX CPI '0' < '0' RC Too low CPI 'G' >'F' CMC Set C state RC Too high CPI 3Ah <='9' CMC Set C state RNC Yes, its OK CPI 'A' Set C if < 'A' RET * * Display the user process registers * REGDIS LHLD BC Get saved BC pair ; LXI B,'BC' And register names mvi b,'B' mvi c,'C' CALL OUTPT Output LHLD DE Get saved DE pair ; LXI B,'DE' And register names mvi b,'D' mvi c,'E' CALL OUTPT Output LHLD HL Get saved HL pair ; LXI B,'HL' And register names mvi b,'H' mvi c,'L' CALL OUTPT Output LHLD SP Get saved SP ; LXI B,'SP' And register name mvi b,'S' mvi c,'P' CALL OUTPT Output LHLD PC Get saved PC ; LXI B,'PC' And regsiter name mvi b,'P' mvi c,'C' CALL OUTPT Output CALL PRTMSG Output message asc ' PSW=' db 0 LHLD PSW Get saved PSW CALL HLOUT2 Output value (with two spaces) CALL PRTMSG Output asc ' FLAGS=' db 0 LHLD PSW Get PSW again MVI B,'S' 'S' flag CALL OUTB Display MVI B,'Z' 'Z' flag CALL OUTB Display DAD H Skip next MVI B,'A' 'A' flag CALL OUTB Display DAD H Skip next MVI B,'P' 'P' flag CALL OUTB Display DAD H Skip next MVI B,'C' 'C' flag CALL OUTB Display JMP LFCR New line & exit * Display contents of a register pair OUTPT MOV A,B Get first char of name CALL OUTBYTE Output MOV A,C Get second char of name CALL OUTBYTE Output MVI A,'=' Get separator CALL OUTBYTE Output HLOUT2 CALL HLOUT Output value CALL SPACE Output a space * Display a space on the console SPACE MVI A,' ' Get a spave JMP OUTBYTE Display it * Display an individual flag bit B=title, L[7]=bit OUTB MOV A,L Get flag bits RLC Shift L[7] into carry MOV L,A Resave it RNC Do not display MOV A,B Get character JMP OUTBYTE And display ;shit: nop * * Display an instruction in disassembly format * DINST PUSH D Save address MOV A,D Get high value CALL HPR Output MOV A,E Get low address CALL HPR Output CALL SPACE Output a space CALL LOOK Lookup instruction ANI 03 Save length PUSH PSW Save length PUSH H Save table address MVI B,4 4 spaces total MOV C,A Save count DCX D Backup address * Display the opcode bytes in HEX VLP1 INX D Advance LDAX D Get opcode CALL HPR Output in HEX CALL SPACE Separator DCR B Reduce count DCR C Reduce count of opcodes JNZ VLP1 Do them all * Fill in to boundary VLP2 CALL SPACE Space over CALL SPACE Space over CALL SPACE Spave over DCR B Reduce count JNZ VLP2 Do them all * DISPLAY ASCII equivalent of opcodes POP B Restore table address POP PSW Restore type/length POP D Restore instruction address PUSH D Resave PUSH PSW Resave MVI H,8 8 spaces/field ANI 0Fh Save only length MOV L,A Save for later PCHR LDAX D Get byte from opcode INX D Advance CALL OUTP Display (if printable) DCR H Reduce field count DCR L Reduce opcode count JNZ PCHR Do them all * Space over to instruction address SPLP CALL SPACE Output a space DCR H Reduce count JNZ SPLP Do them all MVI D,6 Field width VLP3 LDAX B Get char from table ANA A End of string? JZ VOUT1 Yes, exit CALL OUTBYTE Output it INX B Advance to next DCR D reduce count CPI ' ' end of name? JNZ VLP3 no, keep going * Fill in name field with spaces VOUT DCR D reduce count JZ VLP3 Keep going CALL SPACE Output a space JMP VOUT And proceed * Output operands for the instruction VOUT1 POP PSW Restore type POP D Restore instruction address DCR A Is it type1? JZ T1 Yes, handle it * Type 2 - One byte immediate date T2 PUSH PSW Save type MVI A,'$' Get HEX indicator CALL OUTBYTE Output POP PSW Restore type DCR A Type 2? JNZ T3 No, try next INX D Advance to data LDAX D Get data CALL HPR Output in HEX * Type 1 - No operand T1 INX D RET * Type 3 - Two bytes immediate data T3 INX D Skip to low INX D Skip to high LDAX D Get HIGH CALL HPR Output DCX D Backup to low LDAX D Get LOW CALL HPR Output INX D Advance to high INX D RET * * Look up instruction in table & return TYPE/LENGTH[A], and string[HL] * LOOK PUSH D Save DE LDAX D Get opcode MOV B,A Save for later LXI H,ITABLE Point to table LOOK1 MOV A,B Get Opcode ANA M Mask INX H Skip mask CMP M Does it match INX H Skip opcode JZ LOOK3 Yes, we found it * This wasn't it, advance to the next LOOK2 MOV A,M Get byte INX H Advance to next ANA A End of string? JNZ LOOK2 No, keep looking JMP LOOK1 And continue * We found the instruction, copy over the text description LOOK3 MOV C,M Save type INX H Skip type LXI D,BUFFER Point to text buffer LOOK4 MOV A,M Get char from source INX H Advance to next * Insert a RESTART vector number CPI 'v' Restart vector JNZ LOOK5 No, its OK MOV A,B Get opcode RRC Shift it RRC Over RRC To low digit ANI 07h Remove trash ADI '0' Convert to digit JMP LOOK10 And set the character * Insert a register pair name LOOK5 CPI 'p' Register PAIR? JNZ LOOK6 No, try next MOV A,B Get opcode RRC Shift RRC Over into RRC Low digit RRC For lookup ANI 03h Save only RP PUSH H Save HL LXI H,RPTAB Point to pair table JMP LOOK9 And proceed * Insert destination register name LOOK6 CPI 'd' Set destination? JNZ LOOK7 No, try next MOV A,B Get opcode RRC Shift RRC Into low RRC digit JMP LOOK8 And proceed * Insert source register name LOOK7 CPI 's' Source register? JNZ LOOK10 No, its OK MOV A,B Get opcode * Lookup a general processor register LOOK8 ANI 07h Save only source PUSH H Save HL LXI H,RTAB Point to table * Lookup register in table LOOK9 ADD L Offset to value MOV L,A Resave address MOV A,M Get character POP H Restore HL * Save character in destination string LOOK10 STAX D Save value INX D Advance to next ANA A End of list? JNZ LOOK4 No, keep copying * End of LIST LXI H,BUFFER Point to description MOV A,C Get length POP D Restore DE RET * * Opcode disassembly table: MASK, OPCODE, TYPE/LENGTH, STRINGZ * ITABLE DB 0FFh,0FEh,02h asc 'CPI ' db 0 DB 0FFh,3Ah,03h db 0 asc 'LDA ' db 0 DB 0FFh,32h,03h ASC 'STA ' db 0 DB 0FFh,2Ah,03h ASC 'LHLD ' db 0 DB 0FFh,22h,03h ASC 'SHLD ' db 0 DB 0FFh,0F5h,01h ASC 'PUSH PSW' db 0 DB 0FFh,0F1h,01h ASC 'POP PSW' db 0 DB 0FFh,27h,01h ASC 'DAA' db 0 DB 0FFh,76h,01h ASC 'HLT' db 0 DB 0FFh,0FBh,01h ASC 'EI' db 0 DB 0FFh,0F3h,01h ASC 'DI' db 0 DB 0FFh,37h,01h ASC 'STC' db 0 DB 0FFh,3Fh,01h ASC 'CMC' db 0 DB 0FFh,2Fh,01h ASC 'CMA' db 0 DB 0FFh,0EBh,01h ASC 'XCHG' db 0 DB 0FFh,0E3h,01h ASC 'XTHL' db 0 DB 0FFh,0F9h,01h ASC 'SPHL' db 0 DB 0FFh,0E9h,01h ASC 'PCHL' db 0 DB 0FFh,0DBh,02 ASC 'IN ' db 0 DB 0FFh,0D3h,02 ASC 'OUT ' db 0 DB 0FFh,07,01h ASC 'RLC' db 0 DB 0FFh,0Fh,01h ASC 'RRC' db 0 DB 0FFh,17h,01h ASC 'RAL' db 0 DB 0FFh,1Fh,01h ASC 'RAR' db 0 DB 0FFh,0C6h,02 ASC 'ADI ' db 0 DB 0FFh,0CEh,02 ASC 'ACI ' db 0 DB 0FFh,0D6h,02 ASC 'SUI ' db 0 DB 0FFh,0DEh,02 ASC 'SBI ' db 0 DB 0FFh,0E6h,02 ASC 'ANI ' db 0 DB 0FFh,0F6h,02 ASC 'ORI ' db 0 DB 0FFh,0EEh,02 ASC 'XRI ' db 0 DB 0FFh,00,01h ASC 'NOP' db 0 * 8085 specific instructions DB 0FFh,20h,01h ASC 'RIM' db 0 DB 0FFh,30h,01h ASC 'SIM' db 0 * Jumps, Calls & Returns DB 0FFh,0C3h,0Bh ASC 'JMP ' db 0 DB 0FFh,0CAh,43h ASC 'JZ ' db 0 DB 0FFh,0C2h,4Bh ASC 'JNZ ' db 0 DB 0FFh,0DAh,13h ASC 'JC ' db 0 DB 0FFh,0D2h,1Bh ASC 'JNC ' db 0 DB 0FFh,0EAh,23h ASC 'JPE ' db 0 DB 0FFh,0E2h,2Bh ASC 'JPO ' db 0 DB 0FFh,0FAh,83h ASC 'JM ' db 0 DB 0FFh,0F2h,8Bh ASC 'JP ' db 0 DB 0FFh,0CDh,0Bh ASC 'CALL ' db 0 DB 0FFh,0CCh,43h ASC 'CZ ' db 0 DB 0FFh,0C4h,4Bh ASC 'CNZ ' db 0 DB 0FFh,0DCh,13h ASC 'CC ' db 0 DB 0FFh,0D4h,1Bh ASC 'CNC ' db 0 DB 0FFh,0ECh,23h ASC 'CPE ' db 0 DB 0FFh,0E4h,2Bh ASC 'CPO ' db 0 DB 0FFh,0FCh,83h ASC 'CM ' db 0 DB 0FFh,0F4h,8Bh ASC 'CP ' db 0 DB 0FFh,0C9h,05h ASC 'RET' db 0 DB 0FFh,0C8h,45h ASC 'RZ' db 0 DB 0FFh,0C0h,4Dh ASC 'RNZ' db 0 DB 0FFh,0D8h,15h ASC 'RC' db 0 DB 0FFh,0D0h,1Dh ASC 'RNC' db 0 DB 0FFh,0E8h,25h ASC 'RPE' db 0 DB 0FFh,0E0h,2Dh ASC 'RPO' db 0 DB 0FFh,0F8h,85h ASC 'RM' db 0 DB 0FFh,0F0h,8Dh ASC 'RP' db 0 * Register based instructions DB 0C0h,40h,01h ASC 'MOV d,s' db 0 DB 0C7h,06h,02h ASC 'MVI d,' db 0 DB 0F8h,90h,01h ASC 'SUB s' db 0 DB 0F8h,98h,01h ASC 'SBB s' db 0 DB 0F8h,80h,01h ASC 'ADD s' db 0 DB 0F8h,88h,01h ASC 'ADC s' db 0 DB 0F8h,0A0h,01h ASC 'ANA s' db 0 DB 0F8h,0B0h,01h ASC 'ORA s' db 0 DB 0F8h,0A8h,01h ASC 'XRA s' db 0 DB 0F8h,0B8h,01h ASC 'CMP s' db 0 DB 0C7h,04,01h ASC 'INR d' db 0 DB 0C7h,05,01h ASC 'DCR d' db 0 * Register pair instructions DB 0CFh,01h,03h ASC 'LXI p,' db 0 DB 0EFh,0Ah,01h ASC 'LDAX p' db 0 DB 0EFh,02,01h ASC 'STAX p' db 0 DB 0CFh,03h,01h ASC 'INX p' db 0 DB 0CFh,0Bh,01h ASC 'DCX p' db 0 DB 0CFh,09h,01h ASC 'DAD p' db 0 DB 0CFh,0C5h,01h ASC 'PUSH p' db 0 DB 0CFh,0C1h,01h ASC 'POP p' db 0 * Restart instruction DB 0C7h,0C7h,01h ASC 'RST v' db 0 * This entry always matches invalid opcodes DB 00,00,01h asc 'DB ' db 0 * Misc Strings and messages ON asc 'ON ' db 0 OFF ASC 'OFF' db 0 AUTMSG ASC 'AUTOREG=' db 0 SUBMSG ASC ' SUBTRACE=' db 0 TRCMSG ASC ' TRACE=' db 0 HTEXT asc 'DMONT Commands:' DB 0Ah,0Dh,0 asc 'A ON|OFF!Enable/Disable Automatic register display' db 0 asc 'B [bp address]!Set/Display breakpoints' db 0 asc 'C !Copy memory' db 0 asc 'D
!Display memory in assembly format' db 0 asc 'E
!Edit memory' db 0 asc 'F !Fill memory' db 0 asc 'G [address]!Begin/Resume execution' db 0 asc 'I !Input from port' db 0 asc 'L [address]!Load image into memory' db 0 asc 'M
!Display memory in hex dump format' db 0 asc 'O !Output to port' db 0 asc 'R [rp value]!Set/Display program registers' db 0 asc 'S ON|OFF!Enable/Disable Subroutine traceing' db 0 asc 'T ON|OFF!Enable/Disable Trace mode' db 0 asc 'U [address]!Set/Display program base address' db 0 db 0 * * Read a character, and wait for it * INCHR CALL INBYTE Check for a character ANA A Is there any data? JZ INCHR Wait for it RET * * Display HL in hexidecimal * HLOUT MOV A,H Get HIGH byte CALL HPR Output MOV A,L Get LOW byte * * Display A in hexidecimal * HPR PUSH PSW Save low digit RRC Shift RRC high RRC digit RRC into low CALL HOUT Display a single digit POP PSW Restore low digit HOUT ANI 0Fh Remove high digit ADI '0' Convert to ASCII CPI 3Ah Numeric digit JC HOK Yes, display it ADI 7 Convert to ALPHA HOK JMP OUTBYTE And output it * * Display message [PC] * PRTMSG: POP H Get address CALL PRTSTR Output message PCHL And return * * Display message [HL] * PRTSTR: MOV A,M Get byte from message INX H Advance to next ANA A End of message? RZ Yes, exit CALL OUTBYTE Output the character JMP PRTSTR And proceed * * Handle output suspension * CHKSUS: CALL LFCR New line LDA OFLAG Is output suspended? ANA A Test flag JNZ CHKS1 Yes it is CALL INBYTE Test for CONTROL-C interrupt CPI 1Bh ESCAPE? JZ REST Abort CPI ' ' SPACE - Suspend command RNZ STA OFLAG Set the flag * Output is suspended, wait for command CHKS1 CALL INCHR Get char CPI ' ' One line? RZ Allow it CPI 1Bh ESCAPE? JZ REST Abort CPI 0Dh Resume? JNZ CHKS1 Keep going SUB A Reset flag STA OFLAG Write it RET * Display a character if its printable OUTP CPI ' ' < ' ' JC OUTP1 Invalid, exchange it CPI 7Fh Printable? JC OUTBYTE Ok to display OUTP1 MVI A,'.' Set to DOT to indicate invalid JMP OUTBYTE And display * * Write a Line-Feed and Carriage-Return to console * LFCR MVI A,0Ah Line-feed CALL OUTBYTE Output MVI A,0Dh Carriage return * * User supplied I/O routines. * These are for the IMAGE/FUV debug serial port * * NOTE: "OUT" must appear first because "LFCR" falls into it. * * * Write character in A to console (uart) ; OUTBYTE: nop PUSH PSW Save char out UART_OUT OUT1 IN UART_STATUS out 3 ; kick watchdog timer ani 1 jz OUT1 POP PSW Restore char RET * Check for a character from the console INbyte: nop IN UART_STATUS out 3 ; kick watchdog timer ani 2 ; input ready? rz ; no char in UART_IN RET * * Initialize the timer & uart * INIT: mvi a,0 out UART_SETUP RET ; send display byte LCD push psw lc_bsy: in DTP_LCD_STS_I ani 80h jnz lc_bsy pop psw out DTP_LCD_DAT_O ret ; Display "DMONT" in LCD show_LCD ; Initialize LCD mvi a,0E6h ; LCD init wait loop (1.64ms) call dly8 ; mvi a,30h out DTP_LCD_CTL_O mvi a,05h ; 40 us call dly8 ; mvi a,0Fh out DTP_LCD_CTL_O mvi a,05h ; 40 us call dly8 ; mvi a,01h out DTP_LCD_CTL_O mvi a,0E6h ; 1.74ms call dly8 ; Display "DMONT" mvi a,'D' call LCD mvi a,'M' call LCD mvi a,'O' call LCD mvi a,'N' call LCD mvi a,'T' call LCD ; display ACTEL revs mvi a,' ' call LCD in 77h ; ISDPGLU adi 'A' dcr a call LCD mvi a,' ' call LCD in 80h ; ISDPPWR adi 'A' dcr a call LCD mvi a,' ' call LCD mvi a,'7' ; Rev 7.0 call LCD ret dly8: dcr a jnz dly8 ret uget call inbyte jz uget call outbyte ret ; load code from serial port uload lhld ubase ; start loading here mov a,h ora l jnz gold ; if ubase>0, keep running in RAM ; if ubase==0, switch back to PROM ; the switch has to execute outside of PROM space ; copy "PROM-on" code up to 8000 lxi d,8000h lxi h,promoncode mvi c,pend-promoncode kpys: mov a,M stax d inx d inx h dcr c jnz kpys ; execute at 8000h jmp 8000h promoncode: mvi a,1 out PROM_ENBL_O ; switch PROM on nop nop lxi h,0 ; load starts at 0000 jmp gold pend ds 1 gold: ; echo '*' command as '$' -- tells U we're ready to go mvi a,'$' call outbyte ; read groups of bytes ; preceded by a count umore call uget ; get count cpi 0 ; U saying no more to load jz udone mov c,a ; set count ; byte-load loop uloop call uget ; get byte mov M,a ; store inx h ; incr store-pointer dcr c ; decr count jnz uloop ; not zero yet ; next group jmp umore ; switch off PROM promoff mvi a,0 ; disable out 6 ; PROM_POWER ; wait a few microseconds nop nop ; restart in RAM rst 0 udone ; copy "PROM-off" code to 8000 lxi h,promoff lxi d,8000h mvi c,12 kloop: mov a,M stax d inx h inx d dcr c jnz kloop ; switch off PROM ; If ubase==0, go to loaded code ; else return to debugger lhld ubase mov a,h ora l jz 8000h jmp entry