page Introductions DBUGMain idnt ttl 'DBUG' llen 116 maximum list width opt d symbol table in object module opt -c don't show all assembled bytes in dc.b opt -m do not list macro expansion opt -t do not list symbol table opt x do not list XREF **************************************************************************** * * * DBug is a 68000 debugger. It allows downloading, examining/changing * * memory, disassembling, single-stepping, tracing, breakpointing, * * and examining/changing registers. It was originally called VuBug. * * * * This is its history: * * * * 1) Vubug was written by Edward M. Carter at Vanderbilt University. * * See the copyright notice below. * * * * 2) Mark Isfeld and Dave Conroy modified VuBug for work on the SCC * * project. The modifications they made were: * * -- * * * * 3) Jim Battle took VuBug and modified it in these ways: * * -- made syntax checking stronger and error reporting better * * -- added the Lookup subroutine to allow word commands instead of * * single letter commands * * -- added text substitute to substitute memory (SM) command * * -- changed copy to allow bigger than 64k blocks * * -- rewrote register (R) command * * -- added ability to evaluate expressions and changed all commands to * * allow expressions for parameters * * -- added disassembly capability * * -- added symbol managment and changed the load command to read * * symbols. * * -- added ascii, asm, bsr, clear, clearsym, dis, fill, help, set, * * setsym, and = (calc) commands * * -- changed I/O dependent routines (especially the TERM command) * * * **************************************************************************** ******************************************* * * ******** VUBUG ********* * * * Copyright (C) 1983 * * Vanderbilt Univ. * * Comp. Sci. Dept. * * PO Box 1679 * * Station B * * Nashville, Tenn. * * 37235 * * * * Author: * * Edward M. Carter * * * ******************************************* * * * Although the information contained here-* * in, as well as any information provided * * relative thereto, has been carefully re-* * viewed and is believed correct, Vander- * * bilt University assumes no liability * * arising out of its application or use, * * neither does it convey any license under* * its patent rights nor the rights of * * others. * * * ******************************************* page External References and Definitions * * E X T E R N A L R E F E R E N C E S * * From module 'uart.asm68k': xref In_Char_A,In_Char_B,Out_Char_A,Out_Char_B,writ xref Reset_Uart,Uart_Dfault,Uart_trap xref Send_BreakB,Stop_BreakB,Stop_Clock * From module 'disassem.asm68k': xref dis_one * From module 'asm.asm68k': xref asm_oneline * * E X T E R N A L D E F I N I T I O N S * xdef Break_A,RxRDY_A,RxRDY_B,Timeout,ctrls xdef CommonErr,ExpectHexErr,Err_char xdef writb,writw,writl,writs,writAddr xdef Upper_case,CRLF,GetNonSpace,Back_up xdef GetValue,GetLine,GetByte xdef Match_Sym,Add_sym,GetSymbol,Print_sym,Match_val xdef Buff_sym,Save_place,Restore_ln xdef azm_address,Output_buff,Sym_name,Prompt_len xdef CR,LF page Definitions * * Character Definitions * Bell equ $07 CR equ $0D Carriage Return LF equ $0A Line Feed BackSpace equ $08 Control H cntrl_q equ $11 resume sender cntrl_s equ $13 freeze sender cntrl_x equ $18 cancel line cntrl_y equ $19 exit term mode * Status register definitions ssri equ $2000 supervisor SR ssrn equ $2700 same w/o interrupts noInts equ $0700 OR mask to turn off interrupts Ints equ $F8FF AND mask to enable all interrupts * Hex conversion parameter HexFound equ $8 bit 8 is set if hexadecimal char found * Margin is the margin of safty the receive buffer has. If the buffer * has fewer than 'Margin' bytes left, a control-s (halt output) is * sent to the remote host. If the buffer then goes below half empty, a * control-q (resume output) is sent to the remote host. Margin equ 25 Buff_size_A equ 256 # bytes of input buffer (user) Buff_size_B equ 256 # bytes of input buffer (remote host) page Misc Data Structures ; ;Breakpoint structure ; org $0 instr ds.w $1 iloc ds.l $1 BPLen equ * page User Process Vars sect RamVars * * User Process Status Area * USR ds.w 1 register save area SRTrace equ $8000 trace bit SRNoTrace equ $7FFF mask to clear trace bit in SR UPC ds.l 1 UD0 ds.l 1 UD1 ds.l 1 UD2 ds.l 1 UD3 ds.l 1 UD4 ds.l 1 UD5 ds.l 1 UD6 ds.l 1 UD7 ds.l 1 UA0 ds.l 1 UA1 ds.l 1 UA2 ds.l 1 UA3 ds.l 1 UA4 ds.l 1 UA5 ds.l 1 UA6 ds.l 1 UA7 ds.l 1 SSP ds.l 1 supervisor stack pointer page Monitor Data Definitions NumBP equ 5 number of break points allowed bktab ds.w (BPLen/2)*NumBP breakpoint table LastBP ds.l 1 holds address of breakpoint that was hit exam ds.l 1 memory examination pointer BkPtF ds.b 1 breakpoint flag Break_flagA ds.b 1 toggle flag for start/end of break signal OldBkPtF ds.b 1 store an old copy if break point flag BreakPBit equ 0 set if Breakpoint has been hit SStepBit equ 1 set when doing single steps TraceBit equ 2 set when in trace mode EmModeBit equ 3 set when in terminal emulator mode UsrRunning equ 4 set when the user is running StepBit equ 5 set when user does a "step" command SteppedBit equ 6 set when JSR/BSR has been stepped over Users_ret ds.l 1 place to save users return address when * a STEP command is given Break_mode ds.b 1 indicates where to go on a break Brk_restart equ 1 do a "cold" start Brk_comm equ 2 go to command handler Brk_term equ 3 go to term break repeater t1 ds.w 1 temporary stack for writ routine t2 ds.w 1 t3 ds.w 1 t4 ds.w 1 t5 ds.w 1 * this variable stores how long the user prompt is. This is so the * Mark_err routine knows how far to indent when it flags input errors. prompt_len ds.w 1 length of prompt string FileName ds.b 12+1+6+1+12+1+6+1 holds acct:filename for download FileNameSize equ *-FileName number of bytes for max filename * UART interrupt handler vectors. These are in RAM so they may be * changed later. CharInProcA ds.l 1 address of UART char in handler, chan A CharInProcB ds.l 1 address of UART char in handler, chan B BreakInA ds.l 1 address of UART break hanler, channel A TimeProc ds.l 1 address of UART timer handler BkIn equ $4afc instruction constant for breakpoint * (Motorola guarantees this opcode to remain illegal for future 680xx uP) EFC ds.w 1 Exception FC Bits EAddr ds.l 1 Exception memory Address EIR ds.w 1 Exception Instruction Register ESR ds.w 1 Exception Status Register EPC ds.l 1 Exception Program Counter * Output_buff is used to disassemble 1 line of code Output_buff ds.b 256 output buffer * azm_address is the address of where to stuff assembled instructions azm_address ds.l 1 azm_start ds.l 1 address of start of opcode * line_buffer holds the most recent complete command line line_ptr ds.l 1 pointer to next unread character line_marker ds.l 1 for remembering an important char line_size equ 256 line_buffer ds.b line_size keyboard input buffer * Buff_begn_A to Buff_end_A-1 is the channel A (user input) type-ahead buffer Buff_get_A ds.l 1 pointer to next unread char in buffer Buff_save_A ds.l 1 pointer to where to store next char Buff_left_A ds.w 1 # bytes left in buffer Buff_begn_A ds.b Buff_size_A actual input buffer for channel A Buff_end_A equ * * Buff_begn_B to Buff_end_B-1 is the channel B (remote) receive buffer Buff_get_B ds.l 1 pointer to next unread char in buffer Buff_save_B ds.l 1 pointer to where to store next char Buff_left_B ds.w 1 # bytes left in buffer Buff_begn_B ds.b Buff_size_B actual input buffer for channel B Buff_end_B equ * * The variables We_Choke_B, He_Choke_B and ctrls are used in XON/XOFF * processing. CTRLS is 00 when output is allowed to channel A (user terminal) * and non-zero otherwise. Since ctrl-s and ctrl-q may be sent by the user * to the remote host or by the character interrupt handler, some intelligence * must be applied to decide when to send it. If the input buffer is about * to be overrun, a CTRL-S is sent to halt the flow and We_Choke_B is set to * non-00 to remember this. When the user sends a CTRL-S the He_Choke_B flag * is set and is cleared by the user typing a CTRL_Q. The CTRL_Q isn't sent * by the user if the buffer is still in danger of being overrun and the * buffer manager doesn't send a CTRL_Q if the user has sent a CTRL_S. We_Choke_B ds.b 1 if non-0 then we have throttled B He_Choke_B ds.b 1 if non-0 user has sent cntrl_s ctrls ds.b 1 ctrl-s,ctrl-q flag * Storage to remember the time (tenths of seconds since midnight) Tenths ds.l 1 # tenths of seconds since midnight * Symbol table info MaxSym equ 32 maximum # characters in symbol name Sym_name ds.w 1 length word ds.w MaxSym/2 ds.w 1 to allow pad byte if it's long as MaxSym Sym_table equ $22000 start of the symbol table page System and User Stack Defs * System Stack Area sect SystemStack put this in a sect by itself stack equ * the linker will set this address * User's Stack Area sect UserStack put this in a page by itself ustckSSP equ * ustckA7 equ *-1024 give the SSP 1k to breathe page vector table sect Vect_Table dc.l Stack initial supervisor stack dc.l Progstart initial program counter dc.l Berr_trap bus error handler dc.l Addr_trap address error trap dc.l Instr_trap illegal instruction trap dc.l Bad_Vect zero divide trap dc.l Bad_Vect bounds check trap dc.l Bad_Vect overflow trap dc.l Priv_viol priviledge violation dc.l Trace_trap instruction trace handler dc.l texit $Axxx opcode trap dc.l Instr_trap $Fxxx opcode trap dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect uninitialized vector trap dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect spurious interrupt trap dc.l Bad_Vect Autovector 1 dc.l Bad_Vect Autovector 2 dc.l Bad_Vect Autovector 3 dc.l Bad_Vect Autovector 4 dc.l Bad_Vect Autovector 5 dc.l Bad_Vect Autovector 6 dc.l Bad_Vect Autovector 7 dc.l Bad_Vect TRAP #$0 dc.l Bad_Vect TRAP #$1 dc.l Bad_Vect TRAP #$2 dc.l Bad_Vect TRAP #$3 dc.l Bad_Vect TRAP #$4 dc.l Bad_Vect TRAP #$5 dc.l Bad_Vect TRAP #$6 dc.l Bad_Vect TRAP #$7 dc.l Bad_Vect TRAP #$8 dc.l Bad_Vect TRAP #$9 dc.l Bad_Vect TRAP #$A dc.l Bad_Vect TRAP #$B dc.l Bad_Vect TRAP #$C dc.l Bad_Vect TRAP #$D dc.l Bad_Vect TRAP #$E dc.l Bad_Vect TRAP #$F dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Bad_Vect reserved vectors dc.l Uart_trap user vector for Uart page Initialization * * I N I T I A L I Z A T I O N * sect PromProg Place code in Prom howdy dc.b CR,LF,'DBug M68000 Monitor, Version 5/14/86',CR,LF,0 * Set up UART interrupt handler vectors ProgStart or.w #noInts,SR make sure we don't get interrupted move.l #HRxRDY_A,CharInProcA initialize channel A char vector move.l #HRxRDY_B,CharInProcB initialize channel B char vector move.l #HBreak_A,BreakInA initialize break vector move.l #Inc_Time,TimeProc initialize timer vector bsr ClrFileName clear file name buffer for download clr.l exam initialize control variables clr.b ctrls clr.b bkptf clr.b He_Choke_B clr.b Break_flagA moveq #NumBp-1,D0 clear breakpoint table lea bktab,A1 slp clr.l (A1)+ clr.w (A1)+ dbf D0,slp clr.w USR clear register save area moveq #16,D0 clear 8 data and 8 addr registers lea UPC,A0 + the PC slpl clr.l (A0)+ dbf D0,slpl lea ustckA7,A0 set the user's move.l A0,UA7 ... user and lea ustckSSP,A0 set the user's move.l A0,SSP ... supervisor stack pointers clr.w Sym_table make symbol table empty bsr Init_fifos set up input fifos move.b #Brk_restart,Break_mode bsr Reset_Uart freeze the uart bsr Uart_Dfault reset the uart to defaults done and.w #Ints,SR enable interrupts at CPU bsr CRLF lea howdy,A0 say hello bsr writs bsr start_time get current time bra comm enter command loop page Diagnostics DM1 dc.b CR,LF,'Buff_Save_A=',0 DM2 dc.b CR,LF,'Buff_Get_A=',0 DM3 dc.b CR,LF,'Buff_Save_B=',0 DM4 dc.b CR,LF,'Buff_Get_B=',0 diagnose lea DM1,a0 bsr writs move.l Buff_Save_A,d0 bsr writl bsr CRLF lea DM2,a0 bsr writs move.l Buff_Get_A,d0 bsr writl bsr CRLF lea DM3,a0 bsr writs move.l Buff_Save_B,d0 bsr writl bsr CRLF lea DM4,a0 bsr writs move.l Buff_Get_B,d0 bsr writl bsr CRLF rts page Main command loop prompt dc.b 'DBUG>',0 Comm_len equ 5 # of chars in prompt Junk_mess dc.b 'Command not recognized',CR,LF,0 Comm move.b #Brk_restart,Break_mode lea prompt,a0 bsr writs write prompt move.w #comm_len,Prompt_len save length of prompt bsr GetLine get a command line bsr GetNonSpace bsr Back_up now at first non-space lea Cmnd_table,a1 bsr Lookup see if command is in table cmp.l #-1,d0 bad command beq.s junk move.l d0,a3 move.b #Brk_comm,Break_mode go back to comm on a break jsr (a3) do command bra Comm junk lea Junk_mess,a0 bsr writs bra Comm NewNoCmnd rts Cmnd_table dc.w 27 # entries dc.b 'ASM',0 assemble instruction dc.l asm dc.b 'STEP',0,0 single step over breakpoints dc.l step dc.b 'TIME',0,0 set/read time of day dc.l time dc.b 'CLEARSYM',0,0 clear one or all symbol(s) dc.l clearsym dc.b 'SETSYM',0,0 set/change a symbol value dc.l setsym dc.b 'PROTO',0 dc.l proto dc.b 'BSR',0 branch to subroutine dc.l Fake_bsr dc.b 'CLS',0 clear screen dc.l cls dc.b 'ASCII',0 print table of ascii values dc.l ascii dc.b 'SM',0,0 substitute memory dc.l mem dc.b 'LOAD',0,0 load from host dc.l load dc.b 'DUMP',0,0 dump block of memory dc.l dump dc.b '.',0 single step dc.l SingleStep dc.b 'TRACE',0 trace on/off dc.l trace dc.b 'GO',0,0 run user program dc.l go dc.b 'TERM',0,0 enter interactive terminal mode dc.l term dc.b 'COPY',0,0 copy a block of memory dc.l copy dc.b 'HELP',0,0 command summary dc.l help dc.b 'DIS',0 disassemble instructions dc.l disassemble dc.b 'FILL',0,0 fill memory dc.l fill dc.b 'SET',0 set register/flag bit command dc.l Set dc.b 'CLEAR',0 clear flag bit command dc.l Clear dc.b 'R',0 print all register values dc.l regs dc.b 'B',0 breakpoint dc.l bkpt dc.b '?',0 find symbol dc.l findsym dc.b '=',0 calculate dc.l calc dc.b CR,0 no command dc.l NewNoCmnd page help command processor **************************************************** * * * Help is invoked as follows: * * * * h - to get a brief command summary * * * * h- to get help on a particular * * command * * * **************************************************** Help bsr GetNonSpace bsr Back_up skip all leading spaces lea H_table,a1 pointer to valid command table bsr Lookup find if text matches a subject entry cmp.l #-1,d0 was there a match beq.s Hbad jump if not move.l d0,a0 move message pointer bsr writs rts go back to command loop Hbad lea no_help,A0 say it's bad and return bsr writs rts Help_sum dc.b 'These commands are currently implemented:',CR,LF * '123456789*123456789*123456789*123456789*1234' dc.b 'Ascii -- print ASCII table ' dc.b 'Load -- download from remote host ' dc.b CR,LF dc.b 'Asm -- enter line assemlber mode ' dc.b 'Proto -- execute test at $30000 ' dc.b CR,LF dc.b 'B -- set/remove breakpoints ' dc.b 'R -- display all registers ' dc.b CR,LF dc.b 'Bsr -- jump to subroutine ' dc.b 'Set -- set register/flag values ' dc.b CR,LF dc.b 'Clear -- clear flag values ' dc.b 'Setsym -- define value of a symbol ' dc.b CR,LF dc.b 'Clearsym -- clear one/all symbol(s) ' dc.b 'SM -- show/substitute memory ' dc.b CR,LF dc.b 'Cls -- clear the screen ' dc.b 'Step -- step over subroutines ' dc.b CR,LF dc.b 'Copy -- copy memory ' dc.b 'Term -- interactive terminal mode ' dc.b CR,LF dc.b 'Dis -- disassemble instructions ' dc.b 'Time -- print/set current time ' dc.b CR,LF dc.b 'Dump -- memory dump ' dc.b 'Trace -- follow program path ' dc.b CR,LF dc.b 'Fill -- fill memory ' dc.b '. -- single step ' dc.b CR,LF dc.b 'Go -- go ' dc.b '= -- calculate a value ' dc.b CR,LF dc.b 'Help -- help, of course ' dc.b CR,LF dc.b 'Type "help " to get detailed help.',CR,LF,0 Help_Asm dc.b LF dc.b 'The Asm command is invoked as follows:',CR,LF,LF dc.b ' Asm
',CR,LF,LF dc.b 'This command will allow you to enter 68000 assembly language',CR,LF dc.b 'in symbolic form, assembling them starting at the address',CR,LF dc.b 'specified.',CR,LF,LF,0 Help_Ascii dc.b LF dc.b 'The Ascii command is invoked as follows:',CR,LF,LF dc.b ' Ascii',CR,LF,LF dc.b 'This command will print out a table of the ASCII characters',CR,LF dc.b 'and their numeric equivalents.',CR,LF,LF,0 Help_B dc.b LF dc.b 'Breakpoint is invoked as follows:',CR,LF,LF dc.b ' b - display all breakpoints',CR,LF dc.b ' b+aaaaaa - add a breakpoint at aaaaaa',CR,LF dc.b ' b-aaaaaa - remove a breakpoint at aaaaaa',CR,LF dc.b ' b# - remove all breakpoints',CR,LF,LF,0 Help_Bsr dc.b LF dc.b 'Bsr (branch to subroutine) is invoked as follows:',CR,LF,LF dc.b ' Bsr aaaaaa - branch to subroutine, starting at aaaaaa',CR,LF,LF dc.b 'You will go back to the monitor after the final rts',CR,LF,LF,0 Help_Calc dc.b LF dc.b 'Calc is invoked as follows:',CR,LF,LF dc.b ' = ',CR,LF,LF dc.b 'The will be evaluated and printed out as a',CR,LF dc.b '32-bit hex number. Expressions may contain these operators:',CR,LF dc.b ' (), ',$5E,', - (unary), ',$7E,', *, +, -, &, #, ' dc.b $7C,CR,LF dc.b 'Operands can be one of these forms:',CR,LF dc.b ' %, $, , ' dc.b CR,LF,LF,0 Help_Clear dc.b LF dc.b 'The Clear command is invoked as:',CR,LF,LF dc.b ' Clear ',CR,LF,LF dc.b 'where is S,X,N,Z,V, or C',CR,LF,LF,0 Help_Cls dc.b LF dc.b 'Clear screen is invoked as follows:',CR,LF,LF dc.b ' CLS',CR,LF,LF dc.b 'NOTE: this only works for H1510 terminals',CR,LF,LF,0 Help_Clearsym dc.b LF dc.b 'Clearsym is invoked as follows:',CR,LF,LF dc.b ' Clearsym -- erases particular symbol',CR,LF dc.b ' Clearsym * -- erases all symbols',CR,LF,LF,0 Help_Copy dc.b LF dc.b 'The form for the copy command is:',CR,LF,LF dc.b ' Copy xxxxxx=yyyyyy,zzzzzz',CR,LF,LF dc.b 'This will copy locations yyyyyy through zzzzzz to',CR,LF dc.b 'location xxxxx and upward.',CR,LF,LF,0 Help_Dis dc.b LF dc.b 'Disassemble is invoked as follows:',CR,LF,LF dc.b ' Dis - disassembles the instruction pointed' dc.b ' to by the user PC',CR,LF dc.b ' Dis aaaaaa,nnnn - disassembles nnnn instructions' dc.b ' starting at address aaaaaa',CR,LF dc.b ' Dis aaaaaa - disassembles 1 instruction starting' dc.b ' at address aaaaaa',CR,LF,LF,0 Help_Dot dc.b LF dc.b 'Single stepping is invoked by:',CR,LF,LF dc.b ' . - will execute 1 instruction',CR,LF,LF,0 Help_Dump dc.b LF dc.b 'Memory dump is invoked as follows:',CR,LF,LF dc.b ' Dump - dump the next 64 bytes from last' dc.b ' examined address',CR,LF dc.b ' Dump aaaaaa - dump the next 64 bytes' dc.b ' from address xxxxxx',CR,LF dc.b ' Dump aaaaaa,bbbbbb- dump memory from aaaaaa to bbbbbb' dc.b CR,LF,LF,0 Help_Fill dc.b LF dc.b 'Fill is invoked as follows:',CR,LF,LF dc.b ' Fill aaaaaa,bbbbbb=nnnnnnnn',CR,LF dc.b ' Fill aaaaaa,bbbbbb=nnnnnnnn.L - will force a size of long',CR,LF dc.b ' Fill aaaaaa,bbbbbb=nnnn.W - will force a size of word',CR,LF dc.b ' Fill aaaaaa,bbbbbb=nn.B - will force a size of byte',CR,LF,LF dc.b 'NOTE: the smallest operand size which will hold the specified',CR,LF dc.b ' value will be used if a size qualifier is not given.',CR,LF dc.b ' Any partial word at the end of the range will not' dc.b ' be',CR,LF dc.b ' filled. For size word and long, aaaaaa and bbbbbb' dc.b ' must be',CR,LF dc.b ' aligned on a word. Finally, aaaaaa must be less' dc.b ' than bbbbbb.',CR,LF,LF,0 Help_Go dc.b LF dc.b 'Go is invoked as follows:',CR,LF,LF dc.b ' Go - go from start address in last load',CR,LF dc.b ' Go aaaaaa - go from address aaaaaa',CR,LF,LF,0 Help_Help dc.b LF dc.b 'If you are reading this, you know how to use help' dc.b CR,LF,LF,0 Help_Load dc.b LF dc.b 'The Load command is invoked as follows:',CR,LF,LF dc.b ' Load - load from host with same filename',CR,LF dc.b ' Load Filename - load from host',CR,LF,LF,0 Help_Proto dc.b LF dc.b 'The Proto command is invoked as follows:',CR,LF,LF dc.b ' Proto ',CR,LF,LF dc.b 'Proto will jsr to $30000 where a test program is located.',CR,LF dc.b 'This test program should terminate with a RTS.' dc.b CR,LF,LF,0 Help_R dc.b LF dc.b 'The Regs command is invoked as:',CR,LF,LF dc.b ' R',CR,LF,LF dc.b 'This will print out the entire uP state',CR,LF,LF,0 Help_Set dc.b LF dc.b 'The Set command is invoked as:',CR,LF,LF dc.b ' Set ',CR,LF dc.b ' Set ',CR,LF,LF dc.b 'where is D0-D7,A0-A7,A7'',SP,SP'',SR, or PC',CR,LF dc.b ' is S,X,N,Z,V, or C',CR,LF,LF,0 Help_Setsym dc.b LF dc.b 'Setsym is invoked as follows:',CR,LF dc.b ' Setsym =',CR,LF dc.b 'NOTE: can be any mathematical expression' dc.b CR,LF,LF,0 Help_SM dc.b LF dc.b 'Show/substitute commands are as follows:',CR,LF,LF dc.b ' SM - enter show/substitute mode',CR,LF dc.b ' SM aaaaaa - start show/substitute mode' dc.b ' at location aaaaaa',CR,LF dc.b ' sub commands:',CR,LF dc.b ' /aaaaaa - set pointer to location aaaaaa',CR,LF dc.b ' :xx - update current location to xx',CR,LF dc.b ' " - enter ascii starting at current location.',CR,LF dc.b ' + - advance current location',CR,LF dc.b ' - - back up current location',CR,LF dc.b ' - print next location and value',CR,LF dc.b LF,0 Help_Step dc.b LF dc.b 'Step is invoked as follows:',CR,LF,LF dc.b ' Step',CR,LF,LF dc.b 'This command allows you to singlestep the program',CR,LF dc.b 'without tracing through the intermediate instructions',CR,LF dc.b 'of a subroutine.',CR,LF,LF,0 Help_Term dc.b LF dc.b 'Terminal mode is invoked as follows:',CR,LF,LF dc.b ' Term',CR,LF,LF dc.b 'NOTE: any character typed will be sent through to the',CR,LF dc.b ' host except control-y, which is the escape.',CR,LF,LF,0 Help_Time dc.b LF dc.b 'Time is invoked as follows:',CR,LF,LF dc.b ' Time - to see time',CR,LF dc.b ' Time hh:mm:ss - to set time',CR,LF,LF dc.b 'NOTE: time is specified in 24-hour format, e.g.,',CR,LF dc.b ' 6:13 p.m. is specified as 18:13:00',CR,LF,LF,0 Help_Trace dc.b LF dc.b 'Program trace is invoked as follows:',CR,LF,LF dc.b ' Trace + - turn on trace',CR,LF dc.b ' Trace - - turn off trace',CR,LF,LF,0 No_help dc.b LF dc.b 'I do not know anything about it.',CR,LF,LF,0 h_table dc.w 26 number of commands in table dc.b 'ASCII',0 print ascii table dc.l Help_Ascii dc.b 'ASM',0 enter assembler mode dc.l Help_Asm dc.b 'BSR',0 branch to subroutine dc.l Help_BSR dc.b 'CLEAR',0 clear a flag dc.l Help_Clear dc.b 'CLEARSYM',0,0 erase a symbol dc.l Help_Clearsym dc.b 'CLS',0 clear terminal screen dc.l Help_Cls dc.b 'COPY',0,0 copy memory dc.l Help_Copy dc.b 'DIS',0 disassemble memory dc.l Help_Dis dc.b 'DUMP',0,0 memory dump dc.l Help_Dump dc.b 'FILL',0,0 fill memory dc.l Help_Fill dc.b 'GO',0,0 start user program dc.l Help_Go dc.b 'HELP',0,0 command summary dc.l Help_Help dc.b 'LOAD',0,0 load from host (S-format) dc.l Help_Load dc.b 'PROTO',0 execute prototype command dc.l Help_Proto dc.b 'SET',0 set a register or flag dc.l Help_Set dc.b 'SETSYM',0,0 set a symbol value dc.l Help_Setsym dc.b 'SM',0,0 show memory dc.l Help_SM dc.b 'STEP',0,0 singlestep over subroutine dc.l Help_Step dc.b 'TERM',0,0 enter terminal mode dc.l Help_Term dc.b 'TIME',0,0 set/see time dc.l Help_Time dc.b 'TRACE',0 trace a programs path dc.l Help_Trace dc.b '=',0 calculate dc.l Help_Calc dc.b '.',0 . - Single Step dc.l Help_Dot dc.b 'B',0 B - set/remove breakpoints dc.l Help_B dc.b 'R',0 R - display/modify registers dc.l Help_R dc.b CR,0 - no command dc.l Help_sum page asm ******************************************** * The Asm command is invoked as: * * Asm
- to enter assembly mode * ******************************************** asm bsr GetValue find where to begin assembling btst #0,d0 odd address? bne Bndry_err bsr CheckEOL make sure no extra junk move.l d0,azm_address remember where to put it asm_loop move.l azm_address,azm_start bsr Asm_oneline assemble one line of text tst.b d0 see if we should quit yet beq.s asm_exit move.l azm_start,a0 disassemble what we just assembled bsr Dis_print bra asm_loop asm_exit rts back to command processor page time *********************************************** * * * The TIME command is invoked as follows: * * TIME -- to see current time * * TIME hh:mm:ss -- to set current time * * * *********************************************** TimePrompt dc.b 'Current time (hh:mm:ss): ',0 BT_mess dc.b 'Time in bad format: hh:mm:ss expected',0 Start_Time clr.l Tenths default to midnight (00:00:00) lea TimePrompt,a0 jsr writs print time prompt jsr GetLine read one line of input Time jsr GetNonSpace cmp.b #CR,d0 beq PrintTime jsr Back_up put back char we just got jsr GetValue tst.l d0 bmi.s Bad_time <0? cmp.l #24,d0 24 hrs or more? bge.s Bad_time mulu #(60*60*10),d0 # tenths of second in an hour move.l d0,d3 remember hours jsr GetNonSpace cmp.b #':',d0 proper separator? bne.s Bad_time jsr GetValue tst.l d0 bmi.s Bad_time <0? cmp.l #60,d0 60 mins or more? bge.s Bad_time mulu #(60*10),d0 # tenths of second in a minute add.l d0,d3 jsr GetNonSpace cmp.b #':',d0 proper separator? bne.s Bad_time jsr GetValue tst.l d0 bmi.s Bad_time <0? cmp.l #60,d0 60 secs or more? bge.s Bad_time mulu #10,d0 # tenths of second in a second add.l d0,d3 jsr CheckEOL make sure nothing after value move.l d3,Tenths set new time rts Bad_time lea BT_mess,a1 jmp CommonErr * This routine is much more complicated than it has to be. This is * because the 68000 can only do 16 bit multiplies and divides. PrintTime move.l Tenths,d0 get # tenths of second since midnight moveq #10,d1 divisor jsr Div_32 d0/d1 -> d7 = # seconds since midnight cmp.l #(20*60*60),d7 <20 hours? bmi.s prt1 sub.l #(20*60*60),d7 moveq #'2',d0 bra.s prt3 prt1 cmp.l #(10*60*60),d7 <10 hours? bmi.s prt2 sub.l #(10*60*60),d7 moveq #'1',d0 bra.s prt3 prt2 moveq #'0',d0 prt3 jsr Out_Char_A print tens of hours divu #(60*60),d7 d7 upper = remainder, d7 lower = # hours moveq #'0',d0 add.b d7,d0 jsr Out_Char_A print hours moveq #':',d0 jsr Out_Char_A print separator swap d7 ext.l d7 zero out upper 16 bits divu #(60*10),d7 figure tens of minutes moveq #'0',d0 add.b d7,d0 jsr Out_Char_A swap d7 ext.l d7 zero out upper 16 bits divu #60,d7 figure minutes moveq #'0',d0 add.b d7,d0 jsr Out_Char_A print minutes moveq #':',d0 jsr Out_Char_A swap d7 ext.l d7 zero out upper 16 bits divu #10,d7 figure tens of seconds moveq #'0',d0 add.b d7,d0 jsr Out_Char_A swap d7 moveq #'0',d0 add.b d7,d0 jsr Out_Char_A print seconds jsr CRLF rts page find symbol ***************************************************** * Find symbol is invoked as follows: * * ? * * * * The first symbol matching this value will be * * displayed. If more than one symbol has this * * value, a count of how many do will be displayed. * ***************************************************** Nomatchmess dc.b 'No symbol matches that value',CR,LF,0 Manymatch dc.b ' others have this value',CR,LF,0 findsym bsr GetValue see what number we're matching bsr CheckEOL make sure that there is no extra bsr Match_val tst.w d1 d1 has count of how many matched beq.s findsym_no bsr Print_sym print symbol name bsr CRLF cmp.w #1,d1 beq.s findsymexit move.w d1,d0 print out how many matched subq.w #1,d0 print how many others, not how many bsr writb assume less than 257 matched lea Manymatch,a0 bsr writs findsymexit rts findsym_no lea Nomatchmess,a0 bsr writs rts page clearsym command handler ************************************************* * * * The clearsym command is invoked as follows: * * clearsym * -- to forget all symbols * * clearsym -- to forget one symbol * * * ************************************************* clearsym bsr GetNonSpace cmp.b #'*',d0 kill all symbols? bne.s Not_all bsr CheckEOL make sure no other junk at end clr.w Sym_table a 0000 is end-of-table marker rts Not_all bsr Back_up put back the character we just grabbed bsr GetSymbol bsr CheckEOL make sure there is no junk at end bsr Delete_sym bcc Undef_Err carry bit=0 if not found lea clear_mess,a0 bsr writs rts clear_mess dc.b 'Symbol deleted',CR,LF,0 page setsym command handler ************************************************* * * * The setsym command is invoked as follows: * * setsym = * * * ************************************************* setsym bsr GetSymbol get symbol name bsr GetNonSpace check syntax for a "=" cmp.b #'=',d0 bne ExpectEqual bsr Match_sym see if the symbol is in the table yet bcs.s In_already bsr Add_sym new entry <-- a0 move.l a0,a1 In_already bsr GetValue bsr CheckEOL see that no garbage is at end move.l d0,(a1) update the symbol value rts page calculate ********************************************** * * * calc is invoked as follows: * * = * * * * The result will be printed out as a * * 32-bit hex number. * * * ********************************************** calc_mess dc.b 'The result is $',0 calc bsr GetValue parse rest of command line for value bsr CheckEOL make sure there is no garbage at end lea calc_mess,a0 bsr writs bsr writl print value bsr CRLF advance to start of next line rts page proto proto_1 dc.b 'Entering proto routine',CR,LF,0 proto_mess dc.b 'Returned from routine',CR,LF,0 proto lea proto_1,a0 bsr writs jsr $30000 lea proto_mess,a0 bsr writs rts page fake_bsr ******************************************************* * The BSR command is invoked as follows: * * bsr
* * The user's program will run until executes one more * * rts than bsr. * ******************************************************* Bsr_mess dc.b 'Jumped to subroutine',CR,LF,0 Ret_mess dc.b 'Returned from subroutine',CR,LF,0 fake_bsr bsr GetValue get branch address btst #0,d0 see if an odd address bne Bndry_err bsr CheckEOL make sure no extra garbage at end lea Bsr_mess,a0 bsr writs move.l d0,UPC prepare to go btst #5,USR see if user is in supervisor mode beq.s fab_user * construct a return address on user's supervisor stack move.l SSP,a6 user's supervisor stack pointer move.l #Fake_ret,-(a6) put return address on stack move.l a6,SSP put it back for Go handler bra GNoM take off * construct a return address on user stack fab_user move.l UA7,a6 user stack pointer move.l #Fake_ret,-(a6) put return address on stack move.l a6,UA7 put it back for Go handler bra GNoM take off Fake_ret dc.w BkIn breakpoint instruction * (this will get us into supervisor mode if we weren't already) page clear screen ********************************** * This command clears the screen.* * It only works for H1510s * ********************************** cls move.b #27,d0 escape character bsr Out_Char_A move.b #28,d0 ^\ character bsr Out_Char_A rts page print ASCII table ******************************************* * The ASCII command is invoked as follows:* * ASCII * * The 128 character Ascii set will be * * printed out with character, hex, and * * decimal equivalents. * ******************************************* ascii bsr CheckEOL make sure no extra input after command lea Ascii_table,a0 bsr writs print the ascii table rts * The assembler doesn't like certain characters. They are expressed as numbers * \ = $2F (although the microtek manual says backslash is OK) * [ = $5B * ] = $5D * ^ = $5E * ` = $60 * { = $7B * | = $7C * } = $7D * ~ = $7E * Ascii_table dc.b ' 0x 1x 2x ' dc.b ' 3x 4x 5x 6x 7x',CR,LF dc.b ' +-----------+-----------+-------+-' dc.b '-----+------+------+-------+--------+',CR,LF dc.b 'x0 ',$7C,' 0 NUL ',$5E,'@ ',$7C,' 16 DLE ',$5E,'P ' dc.b $7C,' 32 SPC',$7C,' ' dc.b '48 0 ',$7C,' 64 @ ',$7C,' 80 P ',$7C,' 96 ',$60,' ' dc.b $7C,' 112 p ',$7C,CR,LF dc.b 'x1 ',$7C,' 1 SOH ',$5E,'A ',$7C,' 17 DC1 ',$5E,'Q ' dc.b $7C,' 33 ! ',$7C,' ' dc.b '49 1 ',$7C,' 65 A ',$7C,' 81 Q ',$7C,' 97 a ',$7C dc.b ' 113 q ',$7C,CR,LF dc.b 'x2 ',$7C,' 2 STX ',$5E,'B ',$7C,' 18 DC2 ',$5E,'R ' dc.b $7C,' 34 " ',$7C,' ' dc.b '50 2 ',$7C,' 66 B ',$7C,' 82 R ',$7C,' 98 b ',$7C dc.b ' 114 r ',$7C,CR,LF dc.b 'x3 ',$7C,' 3 ETX ',$5E,'C ',$7C,' 19 DC3 ',$5E,'S ' dc.b $7C,' 35 # ',$7C,' ' dc.b '51 3 ',$7C,' 67 C ',$7C,' 83 S ',$7C,' 99 c ',$7C dc.b ' 115 s ',$7C,CR,LF dc.b 'x4 ',$7C,' 4 EOT ',$5E,'D ',$7C,' 20 DC4 ',$5E,'T ' dc.b $7C,' 36 $ ',$7C,' ' dc.b '52 4 ',$7C,' 68 D ',$7C,' 84 T ',$7C,' 100 d ',$7C dc.b ' 116 t ',$7C,CR,LF dc.b 'x5 ',$7C,' 5 ENQ ',$5E,'E ',$7C,' 21 NAK ',$5E,'Q ' dc.b $7C,' 37 % ',$7C,' ' dc.b '53 5 ',$7C,' 69 E ',$7C,' 85 U ',$7C,' 101 e ',$7C dc.b ' 117 u ',$7C,CR,LF dc.b 'x6 ',$7C,' 6 ACK ',$5E,'F ',$7C,' 22 SYN ',$5E,'V ' dc.b $7C,' 38 & ',$7C,' ' dc.b '54 6 ',$7C,' 70 F ',$7C,' 86 V ',$7C,' 102 f ',$7C dc.b ' 118 v ',$7C,CR,LF dc.b 'x7 ',$7C,' 7 BEL ',$5E,'G ',$7C,' 23 ETB ',$5E,'W ' dc.b $7C,' 39 '' ',$7C,' ' dc.b '55 7 ',$7C,' 71 G ',$7C,' 87 W ',$7C,' 103 g ',$7C dc.b ' 119 w ',$7C,CR,LF dc.b ' +-----------+-----------+-------+-' dc.b '-----+------+------+-------+--------+',CR,LF dc.b 'x8 ',$7C,' 8 BS ',$5E,'H ',$7C,' 24 CAN ',$5E,'X ' dc.b $7C,' 40 ( ',$7C,' ' dc.b '56 8 ',$7C,' 72 H ',$7C,' 88 X ',$7C,' 104 h ',$7C dc.b ' 120 x ',$7C,CR,LF dc.b 'x9 ',$7C,' 9 HT ',$5E,'I ',$7C,' 25 EM ',$5E,'Y ' dc.b $7C,' 41 ) ',$7C,' ' dc.b '57 9 ',$7C,' 73 I ',$7C,' 89 Y ',$7C,' 105 i ',$7C dc.b ' 121 y ',$7C,CR,LF dc.b 'xA ',$7C,' 10 LF ',$5E,'J ',$7C,' 26 SUB ',$5E,'Z ' dc.b $7C,' 42 * ',$7C,' ' dc.b '58 : ',$7C,' 74 J ',$7C,' 90 Z ',$7C,' 106 j ',$7C dc.b ' 122 z ',$7C,CR,LF dc.b 'xB ',$7C,' 11 VT ',$5E,'K ',$7C,' 27 ESC ',$5E,$5B dc.b ' ',$7C,' 43 + ',$7C,' ' dc.b '59 ; ',$7C,' 75 K ',$7C,' 91 ',$5B,' ',$7C,' 107 k ' dc.b $7C,' 123 ',$7B,' ',$7C,CR,LF dc.b 'xC ',$7C,' 12 FF ',$5E,'L ',$7C,' 28 FS ',$5E,$2F dc.b ' ',$7C,' 44 , ',$7C,' ' dc.b '60 < ',$7C,' 76 L ',$7C,' 92 ',$2F,' ',$7C,' 108 l ' dc.b $7C,' 124 ',$7C,' ',$7C,CR,LF dc.b 'xD ',$7C,' 13 CR ',$5E,'M ',$7C,' 29 GS ',$5E,$5D dc.b ' ',$7C,' 45 - ',$7C,' ' dc.b '61 = ',$7C,' 77 M ',$7C,' 93 ',$5D,' ',$7C,' 109 m ' dc.b $7C,' 125 ',$7D,' ',$7C,CR,LF dc.b 'xE ',$7C,' 14 SO ',$5E,'N ',$7C,' 30 RS ',$5E,$5E dc.b ' ',$7C,' 46 . ',$7C,' ' dc.b '62 > ',$7C,' 78 N ',$7C,' 94 ',$5E,' ',$7C,' 110 n ' dc.b $7C,' 126 ',$7E,' ',$7C,CR,LF dc.b 'xF ',$7C,' 15 SI ',$5E,'O ',$7C,' 31 US ',$5E,'_ ' dc.b $7C,' 47 / ',$7C,' ' dc.b '63 ? ',$7C,' 79 O ',$7C,' 95 _ ',$7C,' 111 o ',$7C dc.b ' 128 DEL',$7C,CR,LF dc.b ' +-----------+-----------+-------+-' dc.b '-----+------+------+-------+--------+',CR,LF,0 page regs command handler *********************************************** * The Register command is invoked as follows: * * r * * The 8 data, 8 address, PC, SP', and SR * * registers' contents will be printed out. * *********************************************** * The following defines the order the registers will appear Reg_name dc.b 'd0d4a0a4d1d5a1a5d2d6a2a6d3d7a3a7' Reg_order dc.l UD0,UD4,UA0,UA4 order regs print out dc.l UD1,UD5,UA1,UA5 dc.l UD2,UD6,UA2,UA6 dc.l UD3,UD7,UA3,UA7 Seper dc.b ' ',0 PC_mess dc.b 'PC=',0 SR_mess dc.b ' SR=T_S__III___XNZVC=',0 SPprime_mes dc.b ' SP''=',0 '' comes out as ' Regs bsr CheckEOL see if there was extra input at end lea Reg_name,a2 # of register we are printing lea Reg_order,a4 moveq #15,d2 how many to print out (-1 for dbf) Reg_loop move.b (a2)+,d0 bsr Out_Char_A print out 'A' or 'D' move.b (a2)+,d0 bsr Out_Char_A print register number (0-7) moveq #':',d0 bsr Out_Char_A print seperator move.l (a4)+,a3 get pointer to regiser save area move.l (a3),d0 get register value bsr writl lea Seper,a0 bsr writs print register seperator move.b d2,d6 make a temp and.b #3,d6 see if count is a 0,4,8 or C bne.s RCNT_cont bsr CRLF next line if 4 on current line RCNT_cont dbf d2,Reg_loop lea PC_mess,a0 bsr writs write 'PC=' move.l UPC,d0 bsr writAddr write in 24 bit format lea SR_mess,a0 bsr writs write 'SR=...=' move.w USR,d1 get user status register moveq #'0',d3 moveq #15,d2 # bits (-1) to print out Bit_loop clr.b d0 roxl.w #1,d1 put next ms bit into X bit addx.b d3,d0 put '0' or '1' into d0 bsr Out_Char_A dbf d2,Bit_loop lea SPprime_mes,a1 bsr writs write SP'= move.l SSP,d0 supervisor stack pointer bsr writl print 32-bit value bsr CRLF rts page set command handler ****************************************************** * * * The SET command is invoked as follows: * * * * set = * * set * * * * where is d0-d7,a0-a7,a7',sp,sp',or pc * * is S,X,N,Z,V, or C * ****************************************************** set_mess dc.b 'Register/flag name not recognized',0 Set bsr GetNonSpace bsr Back_up skip all leading spaces lea Reg_names,a1 register name table bsr Lookup find a match cmp.l #-1,d0 beq.s Bad_set bad name if -1 cmp.l #16,d0 see if value is a bit location blt.s Set_flag move.l d0,a3 pointer to storage location bsr GetNonSpace cmp.b #'=',d0 check syntax bne ExpectEqual bsr GetValue get value to set it to bsr CheckEOL see if extra crud at end move.l d0,(a3) store value in register save area rts * have to bring SR into reg and back to SR because BSET can only do 8 bits * if the operand is in memory. Set_flag bsr CheckEOL see if anything after flag name move.w USR,d1 get 16 bits bset d0,d1 set proper bit in saved SR move.w d1,USR rts Bad_set bsr Err_Char lea set_mess,a1 bra CommonErr Reg_names dc.w 27 # of entries in table dc.b 'SR',0,0 dc.l USR dc.b 'PC',0 dc.l UPC dc.b 'D0',0,0 dc.l UD0 dc.b 'D1',0,0 dc.l UD1 dc.b 'D2',0,0 dc.l UD2 dc.b 'D3',0,0 dc.l UD3 dc.b 'D4',0,0 dc.l UD4 dc.b 'D5',0,0 dc.l UD5 dc.b 'D6',0,0 dc.l UD6 dc.b 'D7',0,0 dc.l UD7 dc.b 'A0',0,0 dc.l UA0 dc.b 'A1',0,0 dc.l UA1 dc.b 'A2',0,0 dc.l UA2 dc.b 'A3',0,0 dc.l UA3 dc.b 'A4',0,0 dc.l UA4 dc.b 'A5',0,0 dc.l UA5 dc.b 'A6',0,0 dc.l UA6 dc.b 'A7''',0 A7' (supervisor stack pointer) dc.l SSP dc.b 'SP''',0 SP' (supervisor stack pointer) dc.l SSP dc.b 'A7',0,0 (user stack pointer) dc.l UA7 dc.b 'SP',0,0 (user stack pointer) dc.l UA7 dc.b 'X',0 * these entries are flag bit locations dc.l 4 bit 4 of SR is X flag dc.b 'N',0 dc.l 3 bit 3 of SR dc.b 'Z',0 dc.l 2 bit 2 of SR dc.b 'V',0 dc.l 1 bit 1 of SR dc.b 'C',0 dc.l 0 bit 0 of SR dc.b 'S',0 supervisor bit dc.l 13 page clear command handler ****************************************************** * * * The CLEAR command is invoked as follows: * * * * clear * * * * is S,X,N,Z,V, or C * ****************************************************** Clr_mess dc.b 'Flag name not recognized',0 Clear bsr GetNonSpace bsr Back_up skip all leading spaces lea Flag_names,a1 flag name table bsr Lookup find a match cmp.l #-1,d0 beq.s Bad_clear bad name if -1 * have to bring USR into d1 because BCLR only has an 8 bit range if * the operand is in memory. bsr CheckEOL see if anything after flag name move.w USR,d1 bclr d0,d1 clear proper bit in saved SR move.w d1,USR rts Bad_clear bsr Err_Char lea Clr_mess,a1 bra CommonErr Flag_names dc.w 6 6 flags dc.b 'X',0 dc.l 4 bit 4 of SR is X flag dc.b 'N',0 dc.l 3 bit 3 of SR dc.b 'Z',0 dc.l 2 bit 2 of SR dc.b 'V',0 dc.l 1 bit 1 of SR dc.b 'C',0 dc.l 0 bit 0 of SR dc.b 'S',0 supervisor bit dc.l 13 page disassem command handler *********************************************************************** * * * Disassemble is invoked as follows: * * * * Dis - disassemble instruction at current user PC * * Dis aaaaaa,nnnn - disassemble nnnn instructions starting * * at aaaaaa * * Dis aaaaaa - disassemble 1 instruction at aaaaaa * * at aaaaaa * * * *********************************************************************** Disassemble bsr GetNonSpace see if just a D was entered cmp.b #CR,d0 beq.s Dis_PC bsr Back_up back up over char just read bsr GetValue get address to disassemble in d0 btst #0,d0 see if address given is odd bne Bndry_err move.l d0,a0 pointer to instruction to disassemble bsr GetNonSpace check syntax cmp.b #CR,d0 end of line? beq.s Dis_just1 cmp.b #',',d0 bne ExpectComma bsr GetValue get how many instructions to disassem. bsr CheckEOL any input after command? subq.l #1,d0 to satisfy dbf blt.s Dis_limit if < 1 then make it upper limit cmp.l #1000,d0 mistake or way too many? ble.s Dis_loop Dis_limit move.w #1000,d0 bra.s Dis_loop Dis_PC move.l UPC,a0 disassemble from current user PC Dis_just1 clr.w d0 will cause just 1 instr. to disassemble Dis_loop bsr Dis_print disassemble next dbf d0,Dis_loop rts page fill command processor ********************************************************** * * * The Fill command is invoked as follows: * * * * Fill aaaaaa,bbbbbb=xxxxxxxx * * Fill aaaaaa,bbbbbb=xxxxxxxx.L * * Fill aaaaaa,bbbbbb=xxxx.W * * Fill aaaaaa,bbbbbb=xx.B * * * * If a length specifier (.L/.W/.B) is given, memory will * * filled with that type of value. If no length is given,* * then the smallest type which will hold the value will * * be used. The start address must be word aligned for * * lengths of word and long word. Any partial word at * * the end of the range will not be filled. Finally, * * aaaaaa must be less than bbbbbb. * * * ********************************************************** Fmess_1 dc.b 'Filled memory starting at ',0 Fmess_2 dc.b ' with ',0 Fmess_3 dc.b ' for ',0 Fmess_4 dc.b ' long words',CR,LF,0 Fmess_5 dc.b ' words',CR,LF,0 Fmess_6 dc.b ' bytes',CR,LF,0 Fill bsr GetValue get start address move.l d0,a6 move.l d0,a4 bsr GetNonSpace cmp.b #',',d0 check syntax bne ExpectComma branch on error bsr GetValue get end address sub.l a6,d0 get #of bytes to fill blt Range_err move.l d0,d6 save fill length addq.l #1,d6 a to b inclusive means (b-a)+1 bytes bsr GetNonSpace cmp.b #'=',d0 check syntax bne ExpectEqual bsr GetValue get fill value move.l d0,d7 bsr GetNonSpace see if a length specifier is there cmp.b #CR,d0 beq.s No_qual cmp.b #'.',d0 check syntax bne Expect_qual bsr GetNonSpace bsr CheckEOL make sure no extra input bsr Upper_case make sure upper case if a letter cmp.b #'B',d0 see if valid qualifier beq Fill_B cmp.b #'W',d0 beq.s Fill_W cmp.b #'L',d0 beq.s Fill_L bra Expect_qual bad qualifier if not B, W, or L * find the smallest size the value will fit in No_qual cmp.l #$100,d7 blt Fill_B cmp.l #$10000,d7 blt.s Fill_W * fill with long word size Fill_L lsr.l #2,d6 turn #bytes to fill into #of words to fill move.l d6,d4 move.l d6,d5 btst #0,d5 see if address is odd bne Bndry_err swap d5 put #of 64k blocks in d5 bra.s Fill_L2 decrease by one & check for zero Fill_L1 move.l d7,(a6)+ fill 'er up! Fill_L2 dbf d6,Fill_L1 dbf d5,Fill_L1 do next block of 64k long words lea Fmess_1,a0 bsr writs write 'Filled memory starting at ' move.l a4,d0 bsr writl write start address lea Fmess_2,a0 bsr writs write ' with ' move.l d7,d0 bsr writl fill value lea Fmess_3,a0 bsr writs write ' for ' move.l d4,d0 bsr writl long word count lea Fmess_4,a0 bsr writs write ' long words' rts * fill with word size Fill_W lsr.l #1,d6 turn #bytes to fill into #of words to fill move.l d6,d4 move.l d6,d5 see if address is odd btst #0,d5 bne Bndry_err cmp.l #$10000,d7 see if number is long word bge Size_err swap d5 put # of 64k blocks in d5 bra.s Fill_L4 decrease by one & check for zero Fill_L3 move.w d7,(a6)+ fill 'er up! Fill_L4 dbf d6,Fill_L3 dbf d5,Fill_L3 do next 64k block lea Fmess_1,a0 bsr writs write 'Filled memory starting at ' move.l a4,d0 bsr writl write start address lea Fmess_2,a0 bsr writs write ' with ' move.w d7,d0 bsr writw fill value lea Fmess_3,a0 bsr writs write ' for ' move.l d4,d0 bsr writl word count lea Fmess_5,a0 bsr writs write ' words' rts * fill with byte size Fill_B move.l d6,d4 cmp.l #$100,d7 see if fill value is bigger than byte bge Size_err move.l d6,d5 swap d5 put # of 64k blocks in d5.w bra.s Fill_L6 decrease by one & check for zero Fill_L5 move.b d7,(a6)+ fill 'er up! Fill_L6 dbf d6,Fill_L5 dbf d5,Fill_L5 do next 64k block lea Fmess_1,a0 bsr writs write 'Filled memory starting at ' move.l a4,d0 bsr writl write start address lea Fmess_2,a0 bsr writs write ' with ' move.b d7,d0 bsr writb fill value lea Fmess_3,a0 bsr writs write ' for ' move.l d4,d0 bsr writl byte count lea Fmess_6,a0 bsr writs write ' bytes' rts page copy command handler ******************************************* * * * Copy is invoked as follows: * * * * Copy aaaaaa=bbbbbb,cccccc * * * * Copy locations bbbbbb thru cccccc to * * locations aaaaaa and upward. * * bbbbbb must not be less than cccccc. * * * ******************************************* cdmes dc.b 'Copied ',0 ctom dc.b ' to ',0 cform dc.b ' for ',0 cbyt dc.b ' bytes',CR,LF,0 Copy bsr GetValue get dest address for comm buff move.l D0,D2 save it move.l D0,A2 bsr GetNonSpace get next character cmp.b #'=',D0 see if = bne ExpectEqual error if not bsr GetValue get start address move.l D0,D3 save it move.l D0,A3 again bsr GetNonSpace cmp.b #',',D0 should be a comma bne ExpectComma bsr GetValue get ending source address sub.l D3,D0 calculate byte count blt Range_Err if bbbbbb>cccccc bsr CheckEOL make sure no extra input at end move.l D0,D4 save byte count move.l d0,d5 swap d5 d5.w now has # of 64k blocks addq #$1,D4 co1p move.b (A3)+,(A2)+ start moving dbf d0,co1p dbf d5,co1p copy next 64k block lea cdmes,A0 print 'Copied ' bsr writs move.l D3,D0 bsr WritAddr print source address lea ctom,A0 bsr writs print ' to ' move.l D2,D0 bsr WritAddr print destination address lea cform,A0 bsr writs print ' for ' move.l D4,D0 bsr writl print length of transfer lea cbyt,A0 bsr writs print ' bytes' rts page show/substitute memory command handler ************************************************** * * * Show/substitute sub-commands are as follows: * * * * SM - start memory mode * * SM xxxxxx - start m mode at location * * xxxxxx * * /xxxxxx - set pointer to location * * xxxxxx * * " - enter a string of text * * starting at current location * * (note no trailing quote) * * :xx - update current location * * to xx * * + - increment location * * - - decrement location * * - increment location * * * ************************************************** mtab dc.b '/' / dc.l MSlash MTabEntry equ *-MTab dc.b ':' dc.l MColon dc.b '"' dc.l MQuote dc.b '+' dc.l mplu dc.b LF Line feed dc.l MPlu dc.b '-' dc.l mmin MTabLen equ (*-MTab)/MTabEntry mmes dc.b 'Show/substitute memory mode',CR,LF,0 meqm dc.b ' = ',0 M_len equ 12 length of prompt Mem move.w #M_len,prompt_len bsr GetNonSpace see what if CR or address cmp.b #CR,D0 beq MNoAd bsr Back_up backup the pointer bsr GetValue get the address bsr CheckEOL make sure no input after address bra.s mplp set the address MNoAd move.l Exam,D0 start with old address mplp move.l D0,exam set the address lea mmes,A0 load message bsr writs bsr MLoc write out location and contents MemLoop bsr GetLine get next sub command bsr GetNonSpace get operator move #MTabLen-1,D2 set for search lea mtab-6,A1 mmlp addq.l #$6,A1 search loop cmp.b (A1),D0 dbeq D2,mmlp bne mexit exit if not found movea.l 2(A1),A1 get routine address jsr (A1) go to it bra MemLoop stay in memory loop mexit rts MQuote move.l Exam,a1 get pointer to next storage location MQ_loop bsr GetByte get next byte literally cmp.b #CR,d0 end of text? beq.s MQ_exit move.b d0,(a1)+ move.l a1,Exam update pointer bra MQ_loop MQ_exit bsr mloc rts MSlash bsr GetNonSpace see if we have an address cmp.b #CR,D0 beq MSlashEnd if no address jump bsr Back_up backup command pointer bsr GetValue get address bsr CheckEOL any input after address? move.l D0,exam set in pointer bsr mloc print address and value MSlashEnd rts MColon bsr GetValue get what to fill with movea.l exam,A1 set address move.b D0,(A1)+ move new value bsr GetNonSpace get terminator cmp.b #CR,D0 see if a carriage return beq.s MColonEnd if not just end move.l a1,exam advance exam pointer MColonEnd bsr mloc write new value rts Mplu addq.l #$1,exam increment pointer bsr mloc write val rts mmin subq.l #$1,exam decrement pointer bsr mloc rts mloc move.l exam,D0 write address and value bsr WritAddr lea meqm,A0 bsr writs movea.l exam,A0 move.b (A0),D0 write value bsr writb moveq #' ',d0 bsr writ put in a space rts page load command handler ********************************************** * * * Load is invoked as follows: * * Load - load from host with * * same filename as last * * Load Filename - load from * * host * * * ********************************************** Load bsr GetNonSpace get first non space from comm buff cmp.b #CR,D0 if CR then use old filename beq StartLoad * get filename bsr ClrFileName clean out the old lea FileName,A3 A3 = pointer to buffer move #FileNameSize-1,D3 Set up loop counter bra.s LNameLoop1 store character we already read LNameLoop bsr GetByte get a character LNameLoop1 move.b D0,(A3)+ move char into buffer cmp.b #CR,D0 see if we have a terminator dbeq D3,LNameLoop loop if not term and not end of buffer beq.s EndFileName if last char was CR then branch lea OverFlow,A1 else we set up for overflow error bra CommonErr and jump to error routine EndFileName clr.b (A3) put a string terminator at end of buffer StartLoad lea lmes,A0 print starting message bsr writs lea StartLoadMes,A0 bsr WritSSys start download lea FileName,A0 bsr WritSSys send filename bsr GetLine_B get the echoed command line bsr GetLine_B get first record bsr GetByte get first char of first record cmp.b #'I',d0 start of 'INPUT:' error message? beq bad_file cmp.b #'$',d0 any symbol records? bne LLp_ent Sym_rec bsr GetLine_B read next symbol record Sym_scan bsr GetNonSpace cmp.b #CR,d0 end of line? beq Sym_rec read next symbol record cmp.b #'$',d0 end of symbol records? beq LLp bsr Back_up put back what we just got bsr GetSymbol get name of symbol bsr GetNonSpace cmp.b #'$',d0 check format of record bne Bad_record moveq #8,d0 # of digits to read bsr GetNum read 8 hex digits bsr Match_Sym see if symbol we just read is in table bcs.s In_table bsr Add_sym a0-->new entry value field move.l a0,a1 In_table move.l d0,(a1) associate value with symbol entry bra Sym_scan LLp bsr GetLine_B get 1 record from remote host bsr GetByte see if this is an S-record LLp_ent cmp.b #'S',D0 bne llp No - get next record bsr GetByte get 1,2,8 or 9 cmp.b #'9',D0 9 - then done beq S9Rec cmp.b #'2',D0 see if S2 record beq S2Rec cmp.b #'8',D0 beq S8Rec see if S8 record cmp.b #'1',D0 1 - then another record bne llp loop if none of the above S1Rec move.l #2,D0 get 2 characters bsr GetNum get 2 nibbles move D0,D1 sub.w #2+1+1,D1 remove count for check move.l #4,D0 bsr GetNum get address movea D0,A1 save starting address LBLp move.l #2,D0 bsr GetNum get next byte move.b D0,(A1)+ move to memory dbf D1,lblp loop for count move.l #2,D0 bsr GetNum get the bcc bra llp try another record S2Rec move.l #2,D0 get 2 nibbles bsr GetNum of byte count move D0,D1 sub #3+1+1,D1 loop counter for data bytes move.l #6,D0 get address bsr GetNum move.l D0,A1 A1 = load address pointer bra LBLP jump to load loop S8Rec move.l #2,D0 get 2 nibles of byte count bsr GetNum cmp.b #4,D0 count should be 6 bne S8RecErr if not its an error move.l #6,D0 bsr GetNum get starting address bra LoadDone go to ending routine S9Rec bsr GetByte bsr GetByte gobble up byte count move.l #4,D0 bsr GetNum get 4 nibbles of address LoadDone move.l D0,D1 save it move.l D0,UPC set starting address for go move #$2000,USR set status register to Supervisor move #$10,D0 clear 8 D regs, 8 A regs, and SSP lea UD0,A1 lreg clr.l (A1)+ dbf D0,lreg lea ustckA7,A0 move.l A0,UA7 set user stack pointer lea ustckSSP,A0 move.l A0,SSP set supervisor stack pointer bsr CRLF write CR and LF to TTY lea slmes,A0 write message bsr writs move.l D1,D0 bsr writAddr write starting address move #$03,D1 gobble up last four bytes ll2 bsr GetByte dbf D1,ll2 bsr CRLF write CR and LF to TTY lea elmes,A0 send last message bsr writs rts S8ErrMes dc.b 'Bad Byte Count Received in S8 Record',0 S8RecErr lea S8ErrMes,A1 bra CommonErr go to common error routine BadBCCMes dc.b 'Byte Check Error on Load',0 BadBCC lea BadBCCMes,A1 bra CommonErr Bad_record lea BR_mess,a1 bra CommonErr bad_file lea BF_mess,a1 bra CommonErr lmes dc.b 'Load. . . ',0 slmes dc.b 'User PC = ',0 elmes dc.b 'Load done. . . ',CR,LF,0 StartLoadMes dc.b '+Copy O=2 I=',0 OverFlow dc.b 'Filename too long',0 BR_mess dc.b 'Bad symbol record format',0 BF_mess dc.b 'Bad file name or file not found',0 page terminal emulator command handler ************************************************ * * * Invoke emulator mode as follows: * * * * Term * * * * NOTE: That in this mode any char- * * except a ctrl-y may be sent to the * * host. Ctrl-y is the escape sequence * * for getting out of terminal emulator * * mode. * * * ************************************************ emmes dc.b 'Exit terminal mode',CR,LF,0 enmes dc.b 'Terminal mode',CR,LF,0 term bsr CheckEOL make sure there is no extra input lea enmes,A0 write message bsr writs bset #EmModeBit,bkptf set emulator mode moveq #Cntrl_y,d7 save termination character move.b #Brk_term,Break_mode echo breaks term_A bsr Scan_next_A see if A fifo has any new input btst #8,d0 beq.s term_B if not then reverse directions cmp.b d7,d0 if user wants to exit term mode beq.s term_exit ...do it cmp.b #Cntrl_Q,d0 if user wants to unfreeze beq.s term_nochok ...remote host cmp.b #Cntrl_S,d0 if user sends freeze to remote then beq.s term_freeze ...save this fact so we don't undo it bsr Out_Char_B send whatever came in to remote host bra.s term_B term_nochok clr.b He_Choke_B ...clear user freeze flag tst.b We_Choke_B see if we should really send it bne.s term_B don't if queue choke flag is set bsr Out_Char_B send cntrl_Q bra.s term_B term_freeze st He_Choke_B set user freeze flag bsr Out_Char_B send ctrl-s term_B bsr Scan_next_B see if B fifo has any new input btst #8,d0 beq term_A if not then reverse directions bsr Out_Char_A if so, then send to A bra term_A Term_exit bclr #EmModeBit,bkptf clear term emulation mode bit bsr CRLF lea emmes,A0 bsr writs rts page breakpoint command handler ************************************************* * * * Breakpoint is invoked as follows: * * * * B - display breakpoints * * B+xxxx - add a breakpoint at xxxx * * B-xxxx - delete breakpoint at xxxx * * B# - delete all breakpoints * * * ************************************************* brmes dc.b 'Breakpoints removed',CR,LF,0 bdmes dc.b 'Breakpoints at:',CR,LF,0 bpmes dc.b 'Breakpoint added at ',0 bmmes dc.b 'Breakpoint deleted at ',0 ExistsMes dc.b 'Breakpoint already exists',0 BPNFMes dc.b 'Breakpoint not found',0 BPOVMes dc.b 'No more room in breakpoint table',0 BadCommMes dc.b 'Bad command',0 BkPt bsr GetNonSpace get terminator or operator cmpi.b #CR,D0 if than print all bkpts beq.s bdis cmpi.b #'+',D0 if + then add a bkpt beq.s bpls cmpi.b #'-',D0 if - then delete a bkpt beq bmin cmpi.b #'#',D0 if #$ then delete all bkpts bne BadComm else its a bad message * remove all breakpoints bsr CheckEOL make sure no extra input at end moveq #NumBP-1,D1 lea bktab-BPLen,A1 set for loop blp1 adda #BPLen,A1 clr.l ILoc(A1) clean out table entry clr.w Instr(A1) clean out instruction dbf D1,blp1 loop lea brmes,A0 say done bsr writs bra brts * display all breakpoints bdis lea bdmes,A0 handle display all bkpts bsr writs print 'Breakpoints at:' lea bktab-BPLen,A1 set loop moveq #NumBP-1,D1 bd1p adda #BPLen,A1 loop move.l iloc(A1),D0 get bkpt beq.s be1p if 0 then not an entry bsr writaddr bsr CRLF be1p dbf D1,bd1p loop bra brts * add a breakpoint bpls lea bktab-BPLen,A1 add a bkpt move #NumBP-1,D1 set for loop bsr GetValue bsr CheckEOL make sure no extra input after address btst #0,d0 see if address given is odd bne Bndry_err b12 adda #BPLen,A1 loop cmp.l iloc(A1),D0 found entry already in table beq.s BPexists exit if found move.l iloc(A1),D2 move to set condition codes dbeq D1,b12 exit if 0 entry found bne BPOV if exit is on count and not move.l D0,iloc(A1) move in address movea.l D0,A2 point at location move (A2),instr(A1) get instruction into table lea bpmes,A0 load message bsr writs move.l A2,D0 bsr WritAddr bsr CRLF bra brts * remove a breakpoint bmin lea bktab-BPLen,A1 delete a breakpoint entry move #NumBP-1,D1 setup for search bsr GetValue bsr CheckEOL extra garbage after address? b13 adda #BPLen,A1 loop cmp.l iloc(A1),D0 Is this the one? dbeq D1,b13 if yes then exit else loop bne.s BPNotFound Exit on count? movea.l D0,A2 no, so get address clr.w instr(A1) clear table entry clr.l ILoc(A1) lea bmmes,A0 load message bsr writs move.l A2,D0 print address bsr WritAddr bsr CRLF bra brts brts rts BPexists lea ExistsMes,a1 bra CommonErr BPNotFound lea BPNFMes,A1 bra CommonErr BPOV lea BPOVMes,A1 bra CommonErr BadComm lea BadCommMes,A1 bra CommonErr page memory dump command handler ************************************************* * * * Memory dump is invoked as follows: * * * * Dump - dump the next 64 bytes from * * last examined location * * Dump xxxxxx - dump the next 64 bytes * * from address xxxxxx * * Dump xxxxxx,yyyyyy - dump the bytes between * * xxxxxx and yyyyyy * * * ************************************************* dhed dc.b ' 0 1 2 3' dc.b ' 4 5 6 7 8 9 A' dc.b ' B C D E F',CR,LF dcr dc.b 0 Dump bsr GetNonSpace see what kind of dump to do cmp.b #CR,D0 if then dump from point bne.s dexam else get address movea.l exam,A1 get exam movea.l A1,A2 save it for ending address adda #$40,A2 add 64 for length of dump bra dgo go do it DExam bsr Back_up backup the command line pointer bsr GetValue get starting value movea.l D0,A1 bsr GetNonSpace get delimiter or terminator cmp.b #CR,d0 beq.s dcom bsr GetValue get ending address move.l D0,A2 save it bsr CheckEOL make sure there is no extra input at end bra dgo go dump dcom move.l A1,A2 default to 64 byte dump adda.l #$40,A2 dgo lea dhed,A0 print header bsr writs move.l A1,D0 set starting address at 16 and.b #$f0,D0 movea.l D0,A1 move.l A2,D0 round ending address to boundary or.b #$0f,D0 movea.l D0,A2 move #$0f,D1 move byte count to register dl1 move.l A1,D0 write starting address bsr WritAddr move.l A1,A3 save starting address dflp move #' ',D0 write a space bsr writ move.b (A1)+,D0 get next byte bsr writb write it dbf D1,dflp loop move #$0f,D1 reset byte count move.l A3,A1 refetch starting address move #' ',D0 write a space bsr writ dslp move.b (A1)+,D0 write the byte representation cmp.b #' ',D0 if not printable then a dot bge dok move.b #'.',D0 move in the dot bra dwrt dok cmp.b #$7f,D0 printable again? blt dwrt yes move.b #'.',D0 no, move in a dot dwrt bsr writ write it dbf D1,dslp line done? bsr CRLF write CR and LF to TTY move #$f,D1 reset byte count cmp.l A1,A2 done? bge dl1 NO, so loop move.l A1,exam yes, so update exam rts page trace command handler ********************************************* * * * Invoke trace as follows: * * * * Trace+ - trace a program's path * * Trace- - turn off trace * * * ********************************************* tonm dc.b 'Trace on',0 toffm dc.b 'Trace off',0 trace_mess dc.b 'Expecting + or -',0 Trace bsr GetNonSpace get + or - cmp.b #'+',d0 Is is a +? beq.s ton yes cmp.b #'-',d0 is it a -? beq.s Tr_min lea trace_mess,a1 bra Err_char display character in error Tr_min bsr CheckEOL make sure no extra input after - bclr #TraceBit,BkPtF turn-off in-trace flag lea toffm,A0 load off message bra tdone exit TOn bsr CheckEOL make sure no extra input after + bset #TraceBit,BkPtF set in-trace flag lea tonm,A0 write message tdone bsr writs bsr CRLF rts page single-step command handler *************************************** * * * Invoke single step as follows: * * * * . - will execute 1 instruction * * * *************************************** SingleStep bset #SStepBit,BkPtF set breakpoint flag bra GNoM start user process page step command handler ************************************************************************* * Step will execute one instruction without showing intermediate * * instructions. It is invoked by: * * * * Step * * * ************************************************************************* * This routine will examine the current instruction. If it is a normal * * (non subroutine call) instruction we will do a normal single-step. * * If it is a JSR or BSR we set the StepBit in the breakpoint flag. * * The JSR/BSR will be executed. The trace handler will save away the * * real return address in "users_ret" and replace it with a return to * * our breakpoint instruction. We then stop and set the PC to what the * * real return address should have been. * ************************************************************************* Step move.l UPC,a0 get current user PC move.w (a0),d0 see what we are sitting on and.w #$FF00,d0 see if it is a BSR cmp.w #$6100,d0 beq.s Step_bsr move.w (a0),d0 and.w #$FFC0,d0 cmp.w #$4E80,d0 see if it is a JSR bne SingleStep no, just an ordinary instruction Step_bsr bset #StepBit,BkPtF indicate in "step" mode bclr #SteppedBit,BkPtF indicate to step the first instruct bra GNoM Step_ret dc.w BkIn breakpoint instruction * (this will get us into supervisor mode if we weren't already) page go command handler ***************************************** * * * Invoke go as follows: * * * * Go - go from start address in * * last load * * Go xxxx - go from address xxxx * * * ***************************************** gmes dc.b 'Program:',CR,LF,0 Go bsr GetNonSpace see if address or CR cmpi.b #CR,D0 if CR then beq ggo start from default bsr Back_up backup command line pointer bsr GetValue get address to start from bsr CheckEOL make sure no extra input after address move.l D0,UPC set for return GGo lea gmes,A0 write message bsr writs * place entered to start a program with no header message GNoM lea BkTab-BPLen,A6 A6 = pointer into break point table move.w #NumBp-1,D6 D6 = loop counter LdBpLoop add.l #BpLen,A6 increment pointer in table move.l ILoc(A6),A5 A5 = address of breakpoint cmp.l #0,A5 see if this really a BP dbne D6,LdBpLoop loop if address is 0 (no breakpoint) beq ChkBkPtF jump if done cmp.l LastBp,A5 See if we just hit this break point bne.s LdBpLoop1 if no then jump clr.l LastBp bset #BreakPBit,BkPtF if so then set step over instr flag or #SRTrace,USR set trace bit on bra.s LdBPLoop2 jump to end of loop LdBpLoop1 move.w #BkIn,(A5) set instruction to a break point LdBpLoop2 dbf D6,LdBpLoop see if done ChkBkPtF btst #SStepBit,BkPtF see if doing a single step beq.s TestTrace or.w #SRTrace,USR set trace bit TestTrace btst #TraceBit,BkPtF see if doing trace beq.s test_step btst #StepBit,BkPtF don't trace if in "step" mode bne.s test_step or.w #SRTrace,USR test_step btst #StepBit,BkPtF see if doing a "step" beq.s GNoM1 btst #SteppedBit,BkPtF see if we've stepped the BSR/JSR bne.s GNoM1 or.w #SRTrace,USR bset #SteppedBit,BkPtF indicate we've stepped GNoM1 move.l UA7,A6 get user stack pointer move.l A6,USP put it away movem.l UD0,d0-d7/a0-a6 load all registers except sp move.l SSP,sp load supervisor stack pointer move.l UPC,-(sp) set up return pc move.w USR,-(sp) set up return sr bset #UsrRunning,BkPtF Indicate user is running rte Start User Running page common error messages ********************************************************************** * This subroutine prints which character was actually received * by a routine when it expected something else. * The character it prints is in d0.b. ********************************************************************** Undef_mess dc.b 'Symbol not found',0 EC_mess dc.b ' received',CR,LF,0 CommaErrMes dc.b 'Expected comma',0 EqualErrMes dc.b 'Expected equal',0 Size_mess dc.b 'Value too large',0 Bndry_mess dc.b 'Address should be word aligned',0 Qual_mess dc.b 'Size qualifier not recognized',0 Range_mess dc.b 'Range error: second address smaller than first',0 HexErrMes dc.b 'Expecting a Hex Value',0 Undef_Err lea Undef_mess,a1 bra Err_Char Expect_qual lea Qual_mess,a1 bra Err_char ExpectComma lea CommaErrMes,A1 bra Err_char ExpectEqual lea EqualErrMes,A1 bra Err_char ExpectHexErr lea HexErrMes,A1 bra Err_char Size_err lea Size_mess,a1 bra.s CommonErr Range_err lea Range_mess,a1 bra.s CommonErr Bndry_err lea Bndry_mess,a1 bra.s CommonErr *************************************************************************** * CheckEOL subroutine * * This subroutine checks to see if there is any input after the current * buffer position. If there is, an 'Expected end of command' message is * printed out, otherwise it returns to the caller. *************************************************************************** Check_mess dc.b 'End of command expected',0 CheckEOL move.w d0,-(sp) bsr GetNonSpace skip any trailing blanks tst.b d0 is it a null (in case past CR)? beq.s Check_xit cmp.b #CR,d0 end of line? bne.s Check_fail Check_xit move.w (sp)+,d0 rts return if end of line Check_fail lea Check_mess,a1 bra Err_char *************************************************************************** * Common Error routine * * This routine will write a common error message plus the one pointed to * by A1. The stack will then be reset and the routine will branch to the * command interpreter. *************************************************************************** CommErrMes dc.b '**** Error **** ',0 CommonErr lea CommErrMes,A0 bsr WritS move.l A1,A0 move pointer passed to routine bsr WritS bra Error_reset *************************************************************************** * This routine will print a carret under the character in error in the * input line. This character will be one character before the current * position. A message passed by a pointer in a1 will be printed on the * next line. *************************************************************************** Mark_mess dc.b $5E,' ** ERROR **',CR,LF,0 $5E = "^" Err_char moveq #' ',d0 used for tabbing move.w Prompt_len,d1 subq.w #2,d1 sub 1 for dbf and 1 because we have tab_loop bsr Out_Char_A ...read 1 char past char in error dbf d1,tab_loop lea line_buffer,a0 mark_loop cmp.l line_ptr,a0 beq.s mark_found addq.l #1,a0 bsr Out_Char_A tab over 1 more space bra mark_loop mark_found lea Mark_mess,a0 mark the position in error bsr writs move.l a1,a0 bsr writs * bra Error_reset *************************************************************************** * This code will reestablish the stack and return to the command handler *************************************************************************** Error_reset or.w #noInts,SR turn off any interrupts move.l #Stack,SP reset stack pointer clr.b ctrls allow output clr.b He_Choke_B bsr Init_fifos set up input fifos and.w #Ints,SR enable interrupts at CPU clr.b bkptf bsr CRLF bra Comm jump to command interpreter page Subroutines ********************************************************************** * This routine does an signed 32x32 multiply, with a 32 bit result. * Enter: Multiplier and multiplicand in d0 and d1. * Exit : 32-bit signed product in d7. * Changed: d7 and flags ********************************************************************** Mult_32 movem.l d0-d2,-(sp) move.l d0,d2 eor.l d1,d2 get product sign in d2 (bit 31) tst.l d0 d0 := abs(d0) bpl Mult_pos_d0 neg.l d0 Mult_pos_d0 tst.l d1 d1 := abs(d1) bpl Mult_pos_d1 neg.l d1 Mult_pos_d1 clr.l d7 result move.w #31,d2 # of bits to do (-1 for dbf) Mult_32_lup ror.l #1,d1 shift out next ms multiplier bit bcc.s Mult_cont add.l d0,d7 add to total Mult_cont rol.l #1,d0 double multiplicand dbf d2,Mult_32_lup tst.l d2 see if result should be negated bpl.s Mult_exit neg.l d7 make negative Mult_exit movem.l (sp)+,d0-d2 rts ********************************************************************** * This routine does an signed 32x32 divide, with a 32 bit result. * Enter: Divisor in d1 and dividend in d0. * Exit : 32-bit signed product in d7 (d7 <-- d0/d1) * Changed: d7 and flags ********************************************************************** Div_32 movem.l d0-d3,-(sp) move.l d0,d2 eor.l d1,d2 get product sign in d2 (bit 31) tst.l d0 d0 := abs(d0) = dividend bpl Div_pos_d0 neg.l d0 Div_pos_d0 tst.l d1 d1 := abs(d1) = divisor bpl Div_pos_d1 neg.l d1 Div_pos_d1 clr.l d7 result clr.l d3 d3 has first n bits of dividend move.w #31,d2 # of bits to do (-1 for dbf) Div_loop add.l d7,d7 left shift partial quotient addq.w #1,d7 assume subtract works and set ls bit add.l d0,d0 put ms bit of d0 roxl.l #1,d3 ... into ls bit of d3 sub.l d1,d3 this is a test subtraction bcc.s Sub_ok add.l d1,d3 restore partial dividend subq.w #1,d7 clear ls bit of d7 Sub_ok dbf d2,Div_loop tst.l d2 see if result should be negated bpl.s Div_exit neg.l d7 make negative Div_exit movem.l (sp)+,d0-d3 rts ************************************************************************ * This routine will remove a byte from the line_buffer, as indexed by * the line_ptr pointer. The byte is returned in d0.b. ************************************************************************ GetByte move.l a0,-(sp) move.l line_ptr,a0 pointer to next unread character move.b (a0)+,d0 move.l a0,line_ptr move.l (sp)+,a0 rts ************************************************************************ * This routine undoes the action of GetByte by backing up the line_buffer * pointer by one byte. ************************************************************************ Back_up subq.l #1,line_ptr back up pointer to line_buffer rts ************************************************************************ * GetNonSpace Subroutine * * This routine will get the first non space character out of the * line_buffer. The character will be returned in d0.b. ************************************************************************ GetNonSpace bsr GetByte get next character cmp.b #' ',d0 see if space beq GetNonSpace rts ************************************************************************ * This subroutine will store the current position in the line buffer. ************************************************************************ Save_place move.l line_ptr,line_marker rts ************************************************************************ * This subroutine will restore the position in the line buffer. ************************************************************************ Restore_ln move.l line_marker,line_ptr rts ************************************************************************ * Generalized routine to write a string which * must terminate in a null ************************************************************************ Writs move.l D0,-(SP) save D0 writsloop move.b (A0)+,D0 A0 is address of string beq.s dwrts bsr Out_Char_A print d0 out bra writsloop dwrts move.l (SP)+,D0 rts ************************************************************************ * Generalized routine to write a word, byte, or long word ************************************************************************ writb move #1,t1 t1 is the number of nibbles-1 bra.s wr writw move #3,t1 bra.s wr WritAddr move #5,t1 write 6 characters of address bra.s wr writl move #7,t1 wr movem.l d0-d2/a0,-(A7) save registers move t1,D2 set count clr.b t5+1 set a null at end lea t5+1,A0 use temps as a stack alp move D0,D1 make each hex digit a and.b #$0f,D1 writable ascii byte cmp.b #$0a,D1 check for abcdef blt.s or3 add.b #'A'-'9'-1,D1 or3 add.b #'0',D1 ascii-ize move.b D1,-(A0) put on stack lsr.l #4,D0 get next hex digit dbf D2,alp Loop D2 times bsr writs write the stack with writs movem.l (A7)+,d0-d2/a0 restore registers rts page ************************************************************************ * Write String to System port (which is now same as channel B) ************************************************************************ WritSSys move.b (A0)+,D0 move a byte beq.s EndWritSSys if we hit terminator branch bsr Out_Char_B else output it bra WritSSys and jump back EndWritSSys rts go home page ************************************************************************ * CRLF - write a carriage return and * line feed. ************************************************************************ CF dc.b CR,LF,0 CRLF move.l A0,-(SP) save A0 lea cf,A0 bsr writs move.l (SP)+,A0 restore A0 rts ************************************************************************ * GetHex Subroutine * * This routine will get characters from the line_buffer and * convert them to a number in D0 until a non-Hex character is found. ************************************************************************ GetHex move.l d1,-(sp) clr.l d1 bsr GetNonSpace get 1st non space character bsr ASCIIToHex convert ascii to binary btst #HexFound,d0 see if hex beq ExpectHexErr if not then jump AddToHex lsl.l #4,d1 shift up 1 nibble add.b d0,d1 add new nibble in bsr GetByte get a new byte bsr ASCIIToHex convert it btst #HexFound,d0 see if it was a hex char bne AddToHex if so then loop bsr Back_up if not then back up the pointer move.l d1,d0 move return value to d0 move.l (sp)+,d1 rts page ************************************************************************ * GetNum Subroutine * * This routine will convert d0 characters from the line_buffer * from ASCII to hex. The converted number will be returned in D0. ************************************************************************ GetNum movem.l d1/d7,-(sp) clr.w d7 move.b d0,d7 d7 = number of chars to convert subq.w #1,d7 set up for loop counter clr.l d1 GetNumLoop bsr GetByte get next byte from buffer bsr ASCIIToHex convert to hex btst #HexFound,d0 see if hex found beq ExpectHexErr if not jump lsl.l #4,d1 shift left a nibble add.b d0,d1 add new nibble dbf d7,GetNumLoop loop till done move.l d1,d0 d0 = return parameter movem.l (sp)+,d1/d7 restore regs rts page ************************************************************************ * ASCIIToHex Subroutine * * This routine will take a character passed in D0 and will convert it * to a hexadecimal number and return it in D0. If it is hexadecimal then * the HexFound bit will also be set in D0. If it is not a hex character then * the original char will be returned in D0 with the HexFound bit cleared. ************************************************************************ ASCIIToHex move.w d0,-(sp) save in case we want it again cmp.b #'0',D0 see if below 0 blt.s NotHex if so no go cmp.b #'9',D0 see if between 0 and 9 ble.s Hex1To9 if so then go convert it bsr Upper_case its not a number so capitalize it cmp.b #'A',D0 see if below A blt.s NotHex cmp.b #'F',D0 see if between A and F bgt.s NotHex if not jump sub.b #'A'-'9'-1,D0 Hex1To9 and.w #$0F,D0 mask off top nibble bset #HexFound,D0 set found bit addq.l #2,sp forget that we saved d0 initially rts NotHex move.w (sp)+,d0 move original back and.w #$FF,d0 clear top byte (incl. HexFound bit) rts ************************************************************************ * Upper_case * * Enter with a character in d0.b * Exit with the same character if d0.b is not a lower case character * or with the upper case version of the lower case character * * Changes: flags, (possibly) d0.b ************************************************************************ Upper_case cmp.b #'a',d0 is 'a' <= d0.b <= 'a' blt.s Upper_exit cmp.b #'z',d0 bgt.s Upper_exit bclr #5,d0 turn it into an upper case letter Upper_exit rts ************************************************************************ * ClrFileName Subroutine - This routine will fill the buffer FileName * with all blanks plus a 0 at the end ************************************************************************ ClrFileName movem.l d0/a0,-(SP) lea FileName,A0 get address of buffer move #FileNameSize-2,D0 set loop counter to do all but 1 ClrNameLoop move.b #' ',(A0)+ fill with spaces dbf D0,ClrNameLoop loop clr.b (A0) put a 0 in the last byte movem.l (SP)+,d0/a0 rts page ************************************************************************ * This routine will read in a whole line from the remote host port (B) * and stuff it in line_buffer. If the first character is a LF it is * ignored (because it probably follows a previous CR). * The line is terminated with a CR and then a 00 byte, even if the * line is too long. ************************************************************************ GetLine_B movem.l d0-d1/a0,-(sp) lea line_buffer,a0 move.w line_size-2,d1 # bytes length max bsr Get_Next_B cmp.b #LF,d0 swallow the first character bne.s GLB_stuff ...if it is a LF GLB_loop bsr Get_Next_B GLB_stuff move.b d0,(a0)+ store next received char in buffer cmp.b #CR,d0 dbeq d1,GLB_loop move.b #CR,-1(a0) make sure buffer ends with a CR clr.b (a0) ... and a 00 move.l #line_buffer,line_ptr make sure pointer points to start movem.l (sp)+,d0-d1/a0 rts page ************************************************************************ * This routine will get consecutive characters from the keyboard and * assemble them in the 'line_buffer'. It exits after getting one line of * text. The line is terminated when a carriage return (CR) is entered or * a period (.) is entered as the first character of the line. ************************************************************************ GetLine movem.l d0-d1/a0,-(sp) lea line_buffer,a0 start of keyboard buffer clr.w d1 offset into buffer Get_L_Loop bsr Get_next_A get next char in user input queue and.b #$7F,d0 kill MS bit cmp.b #cntrl_x,d0 cancel line? beq.s Can_it cmp.b #$08,d0 is it a backspace? bne.s Full_check tst.w d1 see if nothing has been entered beq Get_L_Loop bsr Out_Char_A back up on char move.b #' ',d0 bsr Out_Char_A erase what was there move.b #$08,d0 bsr Out_Char_A back up over space we just put out subq.w #1,d1 bra Get_L_Loop go on for more input Can_loop moveq #$08,d0 erase previous character bsr Out_Char_A moveq #' ',d0 bsr Out_Char_A moveq #$08,d0 bsr Out_Char_A Can_it dbf d1,Can_loop erase d1 characters in all clr.w d1 bra Get_L_Loop Full_check cmp.w #line_size-2,d1 see if we have filled the buffer bne.s Store_it move.b #7,d0 ascii for 'Beeeeeep' bsr Out_Char_A bra Get_L_Loop Store_it move.b d0,0(a0,d1.w) store it in next buffer location addq.w #1,d1 advance buffer pointer cmp.b #LF,d0 beq.s Handle_LF bsr Out_Char_A echo it cmp.b #CR,d0 beq.s Get_Term terminator found? cmp.b #'.',d0 see if it is period bne Get_L_Loop ...and cmp.w #1,d1 ...if it is first character of line bne Get_L_Loop bra.s Get_term Handle_LF move.b #CR,0(a0,d1.w) turn LF into a LF/CR pair addq.w #1,d1 advance buffer pointer Get_Term clr.b 0(a0,d1.w) store a 00 at end of buffer bsr CRLF advance to start of next line move.l a0,line_ptr make sure pointer points to start movem.l (sp)+,d0-d1/a0 rts page ************************************************************************* * This subroutine will dissassemble one line of text and print it out. * ENTRY: A0 points to where the instruction is to be disassembled * EXIT: A0 points to first byte after instruction. * AFFECTED: A0, flags ************************************************************************* DP_mess dc.b ' ',0 Dis_print movem.l d0-d1/a2,-(sp) movea.l a0,a2 disassemble subroutine wants it here move.l a0,d0 try to find symbol bsr Match_val cmp.w #1,d1 see if we have a unique matching label bne.s DP_cont bsr Print_sym print as : moveq #':',d0 bsr Out_Char_A bsr CRLF DP_cont bsr Dis_one disassemble into buffer lea DP_mess,a0 bsr writs indent a little lea Output_buff,a0 bsr writs print out disassembled line bsr CRLF movea.l a2,a0 movem.l (sp)+,d0-d1/a2 rts ************************************************************************* * This routine scans the table pointed to by a1 and * tries to find an entry that matches text at the current * position in line_buffer. * The table (a1) is in the format * table dc.w # entries * dc.b '',0 * dc.l value1 * dc.b ',0 * dc.l value2 * etc. * If the text has an even number of bytes, it * must be terminated with two 0s. Additionally, should be * upper case since the line_buffer bytes will be converted to upper case. * * On exit, d0.l will contain -1 if a match wasn't found * or will contain the value corresponding to the match. * Line_ptr will point the the first character after the match string * if there is a match. * * Changes : flags, d0. ************************************************************************* Lookup movem.l d1/a0-a1/a5,-(sp) move.l line_ptr,a0 current position in line_buffer move.l a0,a5 save for later scans move.w (a1)+,d1 get the # of entries subq.w #1,d1 for dbf Look_loop tst.b (a1) see if we have reached end of match string beq.s Look_match move.b (a0)+,d0 bsr Upper_case make d0.b upper case if it isn't cmp.b (a1)+,d0 beq Look_loop * this entry does not match, so scan to the end of this entry skip_2_next tst.b (a1)+ bne skip_2_next find the next 00 byte move.l a1,d0 can't do math in addr regs addq.l #1,d0 inc bit 1 if bit 0 is set bclr #0,d0 get rid of bit 0 if now odd move.l d0,a1 now it is word boundary aligned addq.l #4,a1 skip past value field move.l a5,a0 pointer to start of string dbf d1,Look_loop moveq #-1,d0 flag that there was no match bra.s Lookup_exit * there was a match so load in the value (after boundary alignment) Look_match move.l a1,d0 can't do math in addr regs addq.l #2,d0 skip 00 (and second 00 if aligned) bclr #0,d0 get rid of bit 0 if now odd (which * means only 1 needed to be added above) move.l d0,a1 now it is word boundary aligned move.l (a1),d0 get return value Lookup_exit move.l a0,line_ptr now points to next char movem.l (sp)+,d1/a0-a1/a5 rts page evaluate expression GetValue movem.l d1-d7/a0-a6,-(sp) can't be too sure about these things bsr Conv_E get a value move.l d7,d0 d0 is return variable movem.l (sp)+,d1-d7/a0-a6 rts ****************************************************************************** * This routine scans the input and retrieves a long value for the given * expression following this grammar: (it's left recursive, but so what) * * F := (E) (Fundamental) * | $Hexnumber * | %Binarynumber * | Decimalnumber * | Symbol * * U := - F | ~ F | F (Unary) * * P := U^P | U (Power) * * T := T*P | T/P | P (Term) * * S := S+T | S-T | T (Sum) * * E := E&S | E|S | E#S | S (Expression) * ****************************************************************************** page ****************************************************************************** * Conv_E gets an expression of one of these forms: * E := E&S | E|S | E#S | S * The resulting value is returned in d7.l. ***************************************************************************** Conv_E bsr Conv_S get a sum move.l d7,d6 keep a running result Conv_E_ent bsr GetNonSpace cmp.b #'&',d0 check for first form beq.s Form_E1 cmp.b #$7C,d0 check for second form ( | ) beq.s Form_E2 cmp.b #'#',d0 check for third form bne.s Form_E4 Form_E3 move.l d6,-(sp) Logical EOR (exclusive or) bsr Conv_E get next operand move.l (sp)+,d6 recall running result eor.l d7,d6 bra Conv_E_ent Form_E1 move.l d6,-(sp) Logical AND bsr Conv_E get next operand move.l (sp)+,d6 recall running result and.l d7,d6 bra Conv_E_ent Form_E2 move.l d6,-(sp) Logical OR bsr Conv_E get next operand move.l (sp)+,d6 recall running result or.l d7,d6 bra Conv_E_ent Form_E4 move.l d6,d7 use running result as final result bsr Back_up put back char we just got rts must be fourth form page ****************************************************************************** * Conv_S gets an expression of one of these forms: * S := S+T | S-T | T * The resulting value is returned in d7.l. ***************************************************************************** Conv_S bsr Conv_T get next (only?) operand move.l d7,d6 keep a running total Conv_S_ent bsr GetNonSpace cmp.b #'+',d0 check for first form beq.s Form_S1 cmp.b #'-',d0 check for second form bne.s Form_S3 Form_S2 move.l d6,-(sp) save running total bsr Conv_T get next operand move.l (sp)+,d6 recall total sub.l d7,d6 bra Conv_S_ent Form_S1 move.l d6,-(sp) save total bsr Conv_T get next operand move.l (sp)+,d6 recall total add.l d7,d6 add to running total bra Conv_S_ent Form_S3 move.l d6,d7 use running total as answer bsr Back_up put back character we just got rts must be third form by default page ****************************************************************************** * Conv_T gets an expression of one of these forms: * T := T*P | T/P | P * The resulting value is returned in d7.l. ***************************************************************************** Conv_T bsr Conv_P get first (only?) power term move.l d7,d6 keep a running product Conv_T_ent bsr GetNonSpace cmp.b #'*',d0 check for first form beq.s Form_T1 cmp.b #'/',d0 check for second form bne.s Form_T3 Form_T2 move.l d6,-(sp) save running product bsr Conv_P get second operand move.l d7,d1 to satisfy Div_32 beq Div_by_0 move.l (sp)+,d0 recall running product bsr Div_32 d0 / d1 --> d7 (signed 32 bits) move.l d7,d6 update current running product bra Conv_T_ent Form_T1 move.l d6,-(sp) save running product bsr Conv_P get second operand move.l d7,d1 to satisfy Mult_32 move.l (sp)+,d0 recall running product bsr Mult_32 d0 * d1 --> d7 (signed 32 bits) move.l d7,d6 update current running product bra Conv_T_ent Form_T3 bsr Back_up put back character we just read rts page ****************************************************************************** * Conv_P gets an expression of one of these forms: * P := U^P | U * The resulting value is returned in d7.l. ***************************************************************************** Conv_P bsr Conv_U can't tell which form it is yet bsr GetNonSpace see if * or not cmp.b #$5E,d0 $5E ='^' bne.s Form_P2 Form_P1 move.l d7,-(sp) save first operand bsr Conv_P get second operand tst.l d7 see if exponent is negative bmi.s Sign_Err move.l (sp)+,d0 recall first operand move.w d7,d3 to keep count of power (assume 16 bit) moveq #1,d7 partial product bra.s Form_P1_x Form_P1_lup move.l d7,d1 bsr Mult_32 d7 = d0 * d1 (signed 32-bits) Form_P1_x dbf d3,Form_P1_lup do next power rts Form_P2 bsr Back_up put back character we just read rts SE_mess dc.b 'Sign of power < 0',0 Sign_Err lea SE_mess,a1 bra CommonErr page ****************************************************************************** * Conv_U gets an expression of one of these forms: * U := - F | ~ F | F * The resulting value is returned in d7.l. ***************************************************************************** Conv_U bsr GetNonSpace try to determine which form it is cmp.b #'-',d0 check for first form beq.s Form_U1 cmp.b #$7E,d0 check for second form '~' beq.s Form_U2 Form_U3 bsr Back_up put back character we just got bsr Conv_F rts Form_U1 bsr Conv_F get operand neg.l d7 do two's complement rts Form_U2 bsr Conv_F get operand eor.l #-1,d7 do one's complement rts page ****************************************************************************** * Conv_F gets an expression of one of these forms: * F := (E) * | $Hexnumber * | %Binarynumber * | Decimalnumber * | Symbol * The resulting value is returned in d7.l. ***************************************************************************** Conv_F bsr GetNonSpace cmp.b #'(',d0 see if first form beq Form_C1 moveq #16,d1 d1=base cmp.b #'$',d0 see if value is hex beq.s Conv_first moveq #2,d1 cmp.b #'%',d0 see if value is binary beq.s Conv_first moveq #10,d1 cmp.b #'0',d0 blt.s Form_C5 not a number if <'0' cmp.b #'9',d0 bgt.s Form_C5 non a number if > '9' bsr Back_up put back 0-9 digit **** It is a number (binary, decimal, or hex) Conv_first bsr GetByte get first digit bsr ASCIItoHex convert single digit to binary btst #HexFound,d0 see if at all valid (0-9, a-f) beq BadDigit cmp.b d0,d1 see if digit is too big for base ble BadDigit clr.l d7 move.b d0,d7 set d7.l up with first digit Conv_N_loop bsr GetByte get first digit bsr ASCIItoHex btst #HexFound,d0 beq.s Conv_exit ext.w d0 leave only digit in d0 ext.l d0 cmp.b d0,d1 see if digit is too big for base ble BadDigit move.l d7,d3 perform a poor man's multiply move.w d1,d2 subq.w #2,d2 1 for dbf and 1 because d7=1*d7 already Conv_mult add.l d3,d7 add d7 together d1 times dbf d2,Conv_mult ...with the result in d7 add.l d0,d7 add next digit in with partial total bra Conv_N_loop Conv_exit bsr Back_up put back non-digit that got us here rts return with result in d7 **** It must be a symbol or an error Form_C5 bsr Back_up put back non-digit that got us here bsr GetSymbol get symbol name bsr Match_sym bcc Undef_Err move.l (a1),d7 get value associated with symbol rts **** It is of the form (E) Form_C1 bsr Conv_E bsr GetNonSpace check syntax for ) cmp.b #')',d0 bne.s ExpectRightP rts ExpectRightP lea ExpR_mess,a1 bra Err_char BadDigit lea BD_mess,a1 bra Err_char Div_by_0 lea Div_mess,a1 bra CommonErr ExpR_mess dc.b 'Expected a )',0 Div_mess dc.b 'Division by 0',0 BD_Mess dc.b 'Bad digit',0 page symbol management * Format of symbols : 1st character is alphabetic * other characters are from { a...z, 0...9, _ } * Upper/lower case characters are treated as upper case. ***************************************************************************** * This procedure scans the input and builds the name of the symbol in the * buffer 'Sym_name'. If the first character is illegal an error is flagged. * The line buffer pointer will be left at the first non-symbol character * on exit. Only flags are affected. * Format of buffer: * word #1 : number of words (=#chars/2) in symbol name * word #2 : first two chars of name * word #3 : next two chars of name, etc * A 00 byte is stored after the last character of the name if it has odd length ***************************************************************************** BS_Err dc.b 'Bad symbol',0 GetSymbol movem.l d0-d1/a0,-(sp) bsr GetNonSpace get first character of symbol in d0 bsr Upper_case cmp.b #'A',d0 see if it is a valid first character bcs Bad_symbol cmp.b #'Z',d0 bhi Bad_symbol lea Sym_name,a0 move.b d0,2(a0) store first character moveq #1,d1 length of symbol name = 1 GS_loop bsr GetByte get next byte even if it is a space bsr Upper_case cmp.b #'0',d0 check for 0-9 range bcs GS_exit cmp.b #'9',d0 bls GS_store cmp.b #'A',d0 check for A-Z range bcs GS_exit cmp.b #'Z',d0 bls GS_store cmp.b #'_',d0 check for _ (underscore) bne GS_exit GS_store cmp.w #MaxSym,d1 don't save this character if it beq GS_loop ...occurs after the max symbol length move.b d0,2(a0,d1.w) put it in sym_name buffer addq.w #1,d1 add 1 to length count bra GS_loop GS_exit bsr Back_up put back char we just got clr.b 2(a0,d1.w) pad with a 0 in case of odd length addq.w #1,d1 round up if odd length and.w #$fffe,d1 make even again if it was already lsr.w #1,d1 # bytes --> # words move.w d1,(a0) store how long name is movem.l (sp)+,d0-d1/a0 rts Bad_symbol lea BS_err,a1 pointer to error message bra Err_char mark character in error * Symbol table structure: * word #1 : number of words (=#chars/2, rounded up) in symbol name * word #2 : first two chars of name * word #3 : next two chars of name, etc * If the symbol has an odd (i.e. non-even) number of characters in its name * it will be padded with a single 0 byte at the end to preserve boundary. * word #n : ms word of value associated with symbol * word #n+1 : ls word of value associated with symbol **************************************************************************** * This routine tries to find the a match in the symbol table to the symbol * stored in 'Sym_name'. * It returns with carry cleared if it doesn't find a match. * It returns with carry set and a pointer to the symbol entry in a0 * and a pointer to the symbol value in a1 if there is a match. * a0,a1, and flags are the only registers affected. **************************************************************************** Match_sym movem.l d0/a2,-(sp) lea Sym_table,a1 start of symbol table Next_entry move.l a1,a0 in case we need where entry began lea Sym_name,a2 what we are trying to find move.w (a1)+,d0 # of words in symbol name beq.s Match_miss at end of table if 0000 cmp.w (a2)+,d0 bne.s point2_next go to next symbol if lengths don't match subq.w #1,d0 for dbne Match_byte cmp.w (a1)+,(a2)+ do corresponing positions match? dbne d0,Match_byte try to match for entire length beq.s Match_match found it if = * start of next sym = current addr + # chars left in label (rounded up) * + 4 bytes for value field point2_next add.w d0,d0 # words left --> # bytes to skip lea 4(a1,d0.w),a1 go to start of next symbol bra Next_entry Match_match move #1,CCR leave only carry bit set bra.s Match_exit Match_miss move #0,CCR clear all flags Match_exit movem.l (sp)+,d0/a2 rts **************************************************************** * Subroutine Add_sym * * This routine will add an entry at the end of the symbol table. * The entry will be what is stored in 'Sym_name'. * * Just for an extra margin of safety, the last thing done is to * replace the old end of table marker after making sure the next * entry has been build properly. This will prevent a badly timed * break or having table overflow from corrupting the table. * * On exit, A0 will be a pointer to the symbol's value field. * Only a0 and flags will be affected. **************************************************************** Add_sym movem.l d0/a1-a2,-(sp) lea Sym_table,a0 start of symbol table Skip_entry move.w (a0),d0 # of words in symbol name beq.s End_of_tabl at end of table if 00 * start of next sym = current addr + 2 bytes for length count * + # words in label (=#chars/2, rounded up) * + 4 bytes for value field add.w d0,d0 #words in name --> #bytes lea 6(a0,d0.w),a0 go to start of next symbol bra Skip_entry End_of_tabl lea Sym_name,a1 movea.l a0,a2 remember where start of entry is in table move.w (a1)+,d0 get length of symbol lea 2(a0),a0 point to first letters of symbol subq.w #1,d0 for dbf Xfer_sym move.w (a1)+,(a0)+ move next 2 characters of name dbf d0,Xfer_sym clr.w 4(a0) store 0000 to indicate end of table move.w Sym_name,(a2) now put symbol length where 0000 was movem.l (sp)+,d0/a1-a2 rts **************************************************************************** * This routine will delete an entry from the symbol table. * The entry will be what is stored in 'Sym_name'. * If the symbol was found and deleted, the carry bit will be set on exit. * If the symbol isn't found, the carry bit will be cleared. * Only the flags will be affected. **************************************************************************** Delete_sym movem.l d0/a0-a1,-(sp) bsr Match_sym try to find symbol. Entry <-- a0 bcc DS_exit move.w (a0),d0 get size of entry name add.w d0,d0 # words --> # bytes in name lea 6(a0,d0.w),a1 a1 --> next entry DS_loop move.w (a1)+,d0 get size of entry name move.w d0,(a0)+ beq.s DS_done 0000 is end of table symbol addq.w #1,d0 move entry back DS_move move.w (a1)+,(a0)+ dbf d0,DS_move bra DS_loop do next entry DS_done move #1,CCR indicate success DS_exit movem.l (sp)+,d0/a0-a1 rts **************************************************************************** * This subroutine will find any symbols which match a given value. * ENTRY: d0.l, the value we are trying to match * EXIT: a0.l points to the length field of the last symbol which matches. * d1.w has a count of how many symbols matched the value. * AFFECTED: d1, a0, flags **************************************************************************** Match_val movem.l d2/a2,-(sp) clr.w d1 count of how many lea Sym_table,a2 pointer to scan table MV_loop move.w (a2),d2 get symbol length beq.s MV_exit check for end of table add.w d2,d2 two bytes per word cmp.l 2(a2,d2.w),d0 see if value field matches bne.s MV_endloop movea.l a2,a0 a0 points to length field addq.w #1,d1 one more has matched MV_endloop lea 6(a2,d2.w),a2 point to next entry bra MV_loop MV_exit movem.l (sp)+,d2/a2 rts **************************************************************************** * This subroutine will print the name of the symbol pointed to by a0. * ENTRY: a0.l points to the length field of a symbol * EXIT: a0.l points to the value field of the symbol * AFFECTED: a0, flags **************************************************************************** Print_sym movem.w d0-d1,-(sp) move.w (a0)+,d1 get a count of how many words long add.w d1,d1 2 chars per word bra.s ps_loop ps_top bsr Out_Char_A print next char of symbol name ps_loop move.b (a0)+,d0 ...until we either hit a 0 or dbeq d1,ps_top ...we go through all the words bne.s ps_exit addq.l #1,a0 ended on an odd byte (00 terminator) ps_exit movem.w (sp)+,d0-d1 rts **************************************************************************** * This subroutine will move the name of the symbol pointed to by a0 * into the buffer pointed to by a1. * ENTRY: a0.l points to the length field of a symbol * EXIT: a0.l points to the value field of the symbol * AFFECTED: a0, a1, flags **************************************************************************** Buff_sym movem.w d0-d1,-(sp) move.w (a0)+,d1 get a count of how many words long add.w d1,d1 2 chars per word bra.s bs_loop bs_top move.b d0,(a1)+ store next char of symbol name bs_loop move.b (a0)+,d0 ...until we either hit a 0 or dbeq d1,bs_top ...we go through all the words bne.s bs_exit addq.l #1,a0 ended on an odd byte (00 terminator) bs_exit movem.w (sp)+,d0-d1 rts page fifo handling **************************************************************************** * Init_fifos will clear the input fifos for channel A (user) * and channel B (remote). **************************************************************************** * clear the input buffer for channel A Init_fifos lea Buff_begn_A,a0 move.l a0,Buff_save_A pointer to next place to store input move.l a0,Buff_get_A pointer to next unread char move.w #Buff_size_A,Buff_left_A * clear the input buffer for channel B lea Buff_begn_B,a0 move.l a0,Buff_save_B pointer to next place to store input move.l a0,Buff_get_B pointer to next unread char move.w #Buff_size_B,Buff_left_B clr.b We_Choke_B clear cntrl-s flag rts page **************************************************************************** * Subroutine Get_Next_A reads the channel A fifo for the next character. * If there are no characters ready, it waits until there is one. * When it has a character, it returns it in d0.b. * Only d0 and flags are affected. **************************************************************************** Get_Next_A bsr.s Scan_next_A tst.w d0 beq Get_Next_A rts **************************************************************************** * Subroutine Scan_Next_A reads the channel A fifo for the next character. * If there are no characters ready, it returns with d0.w all zero. * If there is a character, the character will be in d0.b and bit 8 of * d0 will also be set. **************************************************************************** Scan_next_A or.w #noInts,SR turn off interrupts for now move.l a1,-(sp) clr.w d0 move.l Buff_get_A,a1 pointer to next unread input byte cmp.l Buff_save_A,a1 if there are no characters to be had beq.s Scan_end_A ...then leave with 0 in d0.w move.b (a1)+,d0 fetch next unread character from buffer addq.w #1,Buff_left_A one more space open now that one is gone bset #8,d0 indicate a successful buffer read cmp.l #Buff_end_A,a1 ...if Buff_get_A pointer is about bcs.s Scan_cont_A ...to wrap around then lea Buff_begn_A,a1 ...move it to beginning of buffer Scan_cont_A move.l a1,Buff_get_A Scan_end_A move.l (sp)+,a1 and.w #Ints,SR enable interrupts rts page **************************************************************************** * Subroutine Get_Next_B reads the channel B fifo for the next character. * If there are no characters ready, it waits until there is one. * When it has a character, it returns it in d0.b. * Only d0 and flags are affected. **************************************************************************** Get_Next_B bsr.s Scan_next_B tst.w d0 beq Get_Next_B rts **************************************************************************** * Subroutine Scan_Next_B reads the channel B fifo for the next character. * If there are no characters ready, it returns with d0.w all zero. * If there is a character, the character will be in d0.b and bit 8 of * d0 will also be set. **************************************************************************** Scan_next_B or.w #noInts,SR turn off interrupts for now move.l a1,-(sp) clr.w d0 move.l Buff_get_B,a1 pointer to next unread input byte cmp.l Buff_save_B,a1 if there are no characters to be had beq.s Scan_cont_B ...then leave with 0 in d0.w move.b (a1)+,d0 fetch next unread character from buffer addq.w #1,Buff_left_B one more space open now that one is gone bset #8,d0 indicate a successful buffer read cmp.l #Buff_end_B,a1 if Buff_get_B pointer is about bcs.s Scan_cont_B ...to wrap around then lea Buff_begn_B,a1 ...move it to beginning of buffer Scan_cont_B move.l a1,Buff_get_B * one char has been removed from the buffer. IF we have frozen the remote * sender (with cntrl-s) AND we now have at least half of the buffer left AND * the user hasn't sent cntrl-s himself THEN send a resume char (cntrl-q). tst.b He_Choke_B see if we sent cntrl-s and user didn't bne.s Scan_end_B tst.b We_Choke_B beq.s Scan_end_B cmp.w #Buff_size_B/2,Buff_left_B bcs.s Scan_end_B swap d0 an ugly trick move.b #Cntrl_Q,d0 bsr Out_Char_B send resume character swap d0 character back in d0 clr.b We_Choke_B clear cntrl-s flag Scan_end_B move.l (sp)+,a1 and.w #Ints,SR enable interrupts rts page save user state ****************************************************************************** * * Save User State Subroutine * * If the User is running then save the registers on * the user register area. * * In all cases use the pointer on the stack below this * subroutine's return address to access the stack frame. * Pretend that this points to the SR in the stack frame * of a Bus Error. Then save all info in the Exception * register data area. If this wasn't a bus error then we * will have garbage in some of those locations. * ****************************************************************************** SaveUsrState btst #UsrRunning,BkPtF See if user is running beq NoSaveUsrState If not then don't save state bclr #UsrRunning,BkPtF clear user running flag movem.l d0-d7/a0-a6,UD0 save most of the registers move.l USP,A6 get user Stack Pointer move.l A6,UA7 and save it away move.l 4(SP),A6 get stack frame pointer move.w (A6),USR save Status Register move.l 2(A6),UPC save Program Counter lea 6(A6),A5 get address where Supervisor Stack * should go if the program is a Supervisor move.l A5,SSP save correct Stack Pointer * clean up USR and BkPtF bclr #SStepBit,BkPtF clear single step bit if set and #SRNoTrace,USR clear trace bit if set bclr #BreakPBit,BkPtF clear step over break point bit * take out breakpoints lea BkTab-BpLen,A6 A6 = pointer into break point table move #NumBp-1,D6 D6 = loop counter RemBpLoop add.l #BpLen,A6 move pointer move.l ILoc(A6),A5 A5 = address of breakpoint cmp.l #0,A5 see if this is a BP dbne D6,RemBpLoop jump if A5=0 (no breakpoint) cmp #-1,D6 see if done with loop beq.s NoSaveUsrState jump if so move.w Instr(A6),(A5) move instruction back in dbf D6,RemBpLoop loop NoSaveUsrState move.l 4(SP),A6 get stack frame pointer lea -8(A6),A4 lea EFC,A5 get pointer to save area moveq #6,D0 save 7 words in case this is a SaveBEstat move.w (A4)+,(A5)+ ...bus error we are processing dbf d0,SaveBEstat move.l (SP),A6 save our return address move.l #Stack,sp reset to monitor's supervisor stack jmp (A6) return to our caller page * * Get Vector Information * GetVectInfo move.b (SP),D0 get vector number clr.b (SP) Reset to zero rts page Interrupt Handlers *========================================================================= * Uart interrupts *========================================================================= Break_A move.l a0,-(sp) move.l BreakInA,a0 get vector jmp (a0) RxRDY_A move.l a0,-(sp) move.l CharInProcA,a0 get vector jmp (a0) RxRDY_B move.l a0,-(sp) move.l CharInProcB,a0 get vector jmp (a0) Timeout move.l a0,-(sp) move.l TimeProc,a0 get vector jmp (a0) * NOTE: the uart routines are exited by rts, not rte! * This is because they are actually called by a 'bsr' in the Uart * interrupt routine in another module. After rts here, the * calling routine does the rte. This is to prevent having to * declare a bunch of UART dependent routines through xref and xdef. HBreak_A move.l (sp)+,a0 bchg #0,Break_flagA mark start/end of break beq.s Brk_startA if bit was 0, then start of break * We know it is end of break. See what we should do with it. cmp.b #Brk_term,Break_mode beq.s In_Term_em cmp.b #Brk_comm,Break_mode beq Error_reset * If not one of the above then do a "cold" restart. reset now simulate a system reset move.l $0,SP move.l $4,a0 jmp (a0) to initial program counter * we know it is end of break in remote host mode In_Term_em bsr Stop_breakB pass on end-of-break to remote host rts * we know it is start of break Brk_startA btst #3,bkptf are we in terminal emulator mode? bne.s Brk_remote * we know it start of break in normal mode rts can't do anything until end of break * we know it is start of break in remote host mode Brk_remote bsr Send_breakB pass on break to remote host rts **************************************************************************** * Uart channel A has received a character * This routine is called by the uart interrupt handler when a character * is received on channel A (user terminal) **************************************************************************** HRxRDY_A move.l d0,-(sp) be careful -- interrupt servicing bsr In_Char_A fetch actual byte received btst #EmModeBit,bkptf terminal emulation mode? bne.s Term_em pass ctrl-S&Q literally if so cmp.b #Cntrl_S,d0 beq.s Do_ctrl_S cmp.b #Cntrl_Q,d0 bne.s Term_em clr.b ctrls control-q cancels control-s bra RxRA_exit Do_ctrl_S st ctrls indicate freeze to user output bra RxRA_exit Term_em cmp.w #3,Buff_left_A almost no space left? blt.s RxRA_exit move.l Buff_save_A,a0 pointer to next character move.b d0,(a0)+ store character subq.w #1,Buff_left_A cmp.l #Buff_end_A,a0 see if pointer is wrapping bcs.s RxRA_finish around past end lea Buff_begn_A,a0 RxRA_finish move.l a0,Buff_save_A RxRA_exit movem.l (sp)+,d0/a0 rts **************************************************************************** * Uart channel B has received a character * This routine is called by the uart interrupt handler when a character * is received on channel B (remote host) **************************************************************************** HRxRDY_B move.l d0,-(sp) be careful -- interrupt servicing move.l Buff_save_B,a0 pointer to next character bsr In_Char_B fetch actual byte received move.b d0,(a0)+ store character subq.w #1,Buff_left_B cmp.l #Buff_end_B,a0 see if pointer is wrapping bcs.s RxRB_finish around past end lea Buff_begn_B,a0 RxRB_finish move.l a0,Buff_save_B cmp.w #Margin,Buff_left_B almost none left? bgt.s RxRB_exit move.b #Cntrl_S,d0 tell remote to stop st We_Choke_B indicate the freeze is on bsr Out_Char_B RxRB_exit movem.l (sp)+,d0/a0 rts * Uart time interrupt * This routine keeps track of the number of tenths of seconds since midnight. * If the time goes past 24 hours, it is reset to midnight. Inc_Time bsr Stop_clock reset TIMER interrupt bit addq.l #1,Tenths cmp.l #(10*60*60*24),Tenths blt.s Inc_exit clr.l Tenths back to midnight Inc_exit move.l (sp)+,a0 a0 was stacked by interrupt handler rts return from interrupt page *========================================================================= * Generic trap handler *========================================================================= ghmes1 dc.b 'Trap #',0 ghmes2 dc.b ' A PC=$',0 ghlr clr.b ctrls allow output if frozen pea 0(SP) save pointer to Stack frame bclr #SStepBit,BkPtF clear flag bsr SaveUsrState if user is running then save state bsr GetVectInfo Get Vector Information from PC ghpr bsr CRLF write CR and LF to TTY lea ghmes1,A0 write message bsr writs bsr writb write vector number lea ghmes2,A0 ghpr1 bsr writs movea.l EPC,a1 get assumed error address move.w EIR,d0 get instruction in error * When we get an illegal opcode the PC has usually advanced from there. * We will look back for that opcode until we find it. lea 2(a1),a0 a0=a1+2 (because we predecrement first) moveq #6,d2 don't go back more than 7 words gh_loop cmp.w -(a0),d0 see if this word matches opcode dbeq d2,gh_loop bne.s gh_cont movea.l a0,a1 point to where it really is gh_cont move.l a1,d0 bsr writAddr 24 bit format bsr CRLF move.l a1,a0 bsr Dis_print disassemble the instruction in error pea comm set for return to comm move #ssri,-(A7) enable interrupts on return rte *========================================================================= * Illegal instruction trap. *========================================================================= II_mess1 dc.b 'Illegal opcode ',0 II_mess2 dc.b ' trapped. PC=$',0 Instr_trap move.w #ssrn,SR turn off interrupts clr.b ctrls allow output if frozen move.l a1,-(sp) tuck user's a1 away for a moment move.l 6(sp),a1 address of bad instruction cmp.w #BkIn,(a1) was it actually a breakpoint? beq bhlr go to breakpoint handler addq.l #4,sp forget that we saved a1 lea II_mess1,a0 bsr writs write 'Illegal opcode ' move.w (a1),d0 fetch opcode bsr writw write opcode of bad instruction * When we get an illegal opcode the PC has usually advanced from there. * We will look back for that opcode until we find it. lea 2(a1),a0 a0=a1+2 (because we predecrement first) moveq #6,d2 don't go back more than 7 words IT_loop cmp.w -(a0),d0 see if this word matches opcode dbeq d2,IT_loop bne.s IT_cont movea.l a0,a1 point to where it really is IT_cont lea II_mess2,a0 bsr writs write ' trapped. PC=$' move.l a1,d0 bsr writAddr 24 bit format bsr CRLF bra Error_reset reset stack and go to comm page *========================================================================= * Breakpoint handler *========================================================================= bhmes dc.b 'Breakpoint at $',0 bhlr move.l (sp)+,a1 recall user's a1 pea 0(SP) push pointer to stack frame bsr SaveUsrState if user is running then save state pea comm set for return to comm move #ssri,-(A7) enable interrupts on return movea.l EPC,A0 get pc on interrupt * see if this was actually caused by a rts following a BSR command cmp.l #Fake_ret,UPC bne.s check_step lea Ret_mess,a0 return from subroutine message bsr writs bra.s bhrte * see if this was actually caused by a rts following a STEP command check_step cmp.l #Step_ret,UPC bne.s check_table bclr #StepBit,BkPtF move.l Users_ret,UPC make the program think it saw a RTS btst #TraceBit,BkPtF should we disassemble this? beq.s bhrte movea.l UPC,a0 address of instruction to disassemble bsr Dis_print disassemble and print instruction bra.s bhrte * see if this break is in the break point table check_table lea BkTab-BPLen,A6 A6 = pointer into table move #NumBp-1,D6 D6 = loop counter BrFindLoop add #BpLen,A6 move pointer cmp.l Iloc(A6),A0 see if this is correct instruction dbeq D6,BrFindLoop jump if not and not end of loop bne BadBp jump if breakpoint not in table bsr CRLF write CR and LF to TTY lea bhmes,A0 write bkpt message bsr writs move.l EPC,D0 bsr WritAddr bsr CRLF move.l EPC,LastBP bhrte rte BadBPMes dc.b 'Breakpoint not found in table',CR,LF,0 BadBP bsr CRLF lea BadBPMes,A0 bsr WritS send out message rte page *========================================================================= * Trace interrupt handler *========================================================================= * A trace trap can happen for 4 legitimate reasons; Trace, single step, * stepping over a breakpoint, or on the first instruction of a "STEP" command. * The trace exception should only happen when a user is running and at least 1 * of the above types of processing is being done. If no user is running or not * tracing, single stepping or stepping past a breakpoint then an error is * displayed. Trace_trap move #SSRN,SR turn off interrupts clr.b ctrls allow output if frozen btst #UsrRunning,BkPtF see if a user was running beq TraceNoUser if not then jump move.b BkPtF,OldBkPtF save break point flag pea (SP) push stack frame pointer bsr SaveUsrState move.b OldBkPtf,D7 * See if trace, single step, step or break point is on btst #StepBit,d7 bne.s SBit_set btst #TraceBit,D7 bne.s TBit_set btst #SStepBit,D7 bne.s SSBit_set btst #BreakPBit,D7 bne TBit_set bra NoBitsSet none were set; it's an error SBit_set lea UA7,a0 btst #13,USR see if in supervisor or user mode beq SB_mode lea SSP,a0 SB_mode movea.l (a0),a1 get SP location move.l (a1),d0 get actual return address move.l d0,Users_ret save it to fool user later move.l #Step_ret,(a1) set up our fake return address bra GNoM start running again * Hit trace because we are in trace mode TBit_set movea.l UPC,a0 address of instruction to disassemble bsr Dis_print disassemble and print instruction btst #SStepBit,D7 test single step bit beq GNoM if not set then jump to Go routine * ending a single step SSBit_set pea Comm set up for return to Comm move #SSRI,-(A7) turn on interrupts upon return rte NoBitsMes dc.b 'Unexpected Trace Exception while running' dc.b 'user program',0 NoBitsSet lea NoBitsMes,A1 bra CommonErr TraceErr dc.b 'Trace Exception while no User program running',0 TraceNoUser lea TraceErr,A1 bra CommonErr page *========================================================================= * Privilege Violation Handler *========================================================================= * See generic handler for details prmes dc.b 'Privilege Error at $',0 Priv_viol pea (SP) bsr SaveUsrState clr.b ctrls allow output if frozen bsr CRLF write CR and LF to TTY lea prmes,A0 bra ghpr1 page *========================================================================= * Address error/bus error trap *========================================================================= ames dc.b 'Address error : ',0 bmes dc.b 'Bus error : ',0 BEAt dc.b ' @ ',0 BEInstr dc.b ' Instr=$',0 BESr dc.b ' SR=$',0 BEPC dc.b ' PC=$',0 * Table Must have exactly 16 bytes per entry AccessType dc.b 'User Data Write',0 dc.b 'User Data Read ',0 dc.b 'User Prog Write',0 dc.b 'User Prog Read ',0 dc.b 'Sup Data Write ',0 dc.b 'Sup Data Read ',0 dc.b 'Sup Prog Write ',0 dc.b 'Sup Prog Read ',0 Addr_trap pea 8(SP) bsr SaveUsrState clr.b ctrls allow output if frozen bsr CRLF write CR and LF to TTY lea ames,A0 bsr writs write 'Address Error' bra abhlr Berr_trap pea 8(SP) bsr SaveUsrState clr.b ctrls allow output if frozen bsr CRLF write CR and LF to TTY lea bmes,A0 bsr writs write 'Bus Error' abhlr move.w EFC,D1 Get Access Status btst #$4,D1 Check for Read/Write bit Sne D2 and.w #$01,D2 and.l #06,D1 Mask Everything but User,Data,R/W bits or.w D2,D1 rol.l #4,D1 Multiply By 16 lea AccessType,A0 load base of table add D1,A0 Add offset bsr writs write String lea BEAt,A0 bsr writs move.l EAddr,D0 bsr WritAddr write Access Address lea BEInstr,A0 bsr writs move.w EIR,D0 bsr writw write Instruction Word lea BESr,A0 bsr writs move.w ESR,D0 bsr writw write Status Register lea BEPC,A0 bra GHPR1 Send message and write PC page * Exit UsrDone dc.b CR,LF,'Program Terminated normally at $',0 texit pea (SP) save pointer to stack frame clr.b ctrls allow output if frozen bsr SaveUsrState save user state lea UsrDone,A0 bra ghpr1 send message,print PC page *========================================================================= * Bad_Vect Routine *========================================================================= BadVectMes dc.b 'Bad Interrupt Vector #',0 Bad_Vect pea (SP) save pointer to stack frame clr.b ctrls allow output if frozen bsr SaveUsrState save user state bsr GetVectInfo get vector number in D0 bsr CRLF write CR and LF to TTY lea BadVectMes,A0 write message bsr writs bsr writb write vector number lea BEPC,A0 bsr writs write 'PC = $' pea comm set for return to comm move #ssri,-(A7) enable interrupts on return rte end ProgStart