Mercurial > hg > Members > kono > nitros9-code
view 3rdparty/p2mods/noice/noice.asm @ 1995:2bb2f8b975b0
additional preliminary changes made by R. Gault
author | boisy |
---|---|
date | Sun, 19 Feb 2006 15:09:42 +0000 |
parents | d5e3d4f5c45a |
children | abf447bacf71 |
line wrap: on
line source
******************************************************************** * KrnP3 - NoICE Serial Debugger for 6809/6309 * * $Id$ * * This module is called by the kernel at boot time and initializes itself * by creating a new system call: os9 F$Debug * * The process that called the F$Debug system call is the one that will * be debugged. * * Using the NoICE serial protocol, the debugger can talk to a host, and can be * driven by simple commands to read/write registers and memory, and continue * execution. * * Notes: * o The NoICE protocol specifies a 'page' byte in addition to the * 16-bit memory address when reading/writing memory. We currently * ignore this page, and I cannot think of a need for this. * * o The 6309 is now a supported processor under the Windows version * of NoICE. Its processor ID is 17. * * Edt/Rev YYYY/MM/DD Modified by * Comment * ------------------------------------------------------------------ * 1 2005/04/03 Boisy G. Pitre * Started * * 2 2006/02/02 Boisy G. Pitre * Added USERSTATE flag to allow module to debug current process or * system. NAM KrnP3 TTL NoICE Serial Debugger for 6809/6309 IFP1 USE defsfile ENDC IFNE KRNMOD tylg SET Systm+Objct ELSE tylg SET Prgrm+Objct ENDC atrv SET ReEnt+rev rev SET $00 edition SET 1 * If an MPI is being used, set RS232SLOT to slot value - 1 and set MPI to 1 MPICTRL EQU $FF7F RS232SLOT EQU 1 slot 2 *MPI EQU 1 FN_ERROR EQU $F0 FN_SET_BYTES EQU $F9 FN_RUN_TARGET EQU $FA FN_WRITE_REGS EQU $FB FN_READ_REGS EQU $FC FN_WRITE_MEM EQU $FD FN_READ_MEM EQU $FE FN_GET_STATUS EQU $FF cbsize EQU 200 * this location is in lo-System RAM. We clear the low bit upon * initialization from the kernel, then on subsequent breakpoints, * we set the low bit * offsets into our on stack storage ORG 0 callregs RMB 2 firsttime RMB 1 IFNE MPI slot RMB 1 ENDC combuff RMB cbsize size EQU . L0000 MOD eom,name,tylg,atrv,start,size name EQU * IFNE KRNMOD FCS /KrnP3/ ELSE FCS /noice/ ENDC FCB edition nextname FCC /krnp4/ next module name to link to FCB C$CR svctabl FCB F$Debug FDB dbgent-*-2 FCB $80 start IFNE KRNMOD leay <svctabl,pcr os9 F$SSvc bcs ex@ ldd #$0100 os9 F$SRqMem allocate memory bcs ex@ stu <D.DbgMem save our allocated memory * clear the firsttime flag so that the first time we get * called at dbgent, we DON'T subtract the SWI from the PC. sta firsttime,u A = $01 * get next KrnP module going lda #tylg get next module type (same as this one!) leax <nextname,pcr get address of next module name os9 F$Link attempt to link to it bcs ex@ no good...skip this jsr ,y else go execute it ex@ rts return ENDC * Debugger Entry Point * * We enter here when a process or the system makes an os9 F$Debug call. dbgent ldx <D.DbgMem get pointer to our statics in X stu callregs,x save pointer to caller's regs exg x,u exchange X and U * If this is a breakpoint (state = 1) then back up PC to point at SWI2 tst firsttime,u bne notbp ldd R$PC,x subd #$03 std R$PC,x * set bit so next time we do the sub on the $PC notbp clr firsttime,u lbsr llinit initialize I/O lda #FN_RUN_TARGET sta combuff,u lbra _readregs * mainloop - processes requests from the server mainloop * ADDITION: We insist on having a "Pre-Opcode" OP_XBUG if we are using * this client in conjunction with DriveWire on the same serial line. * This is because DriveWire's Opcodes conflict with NoICE's. * lbsr llread get command byte * cmpa #OP_XBUG X-Bug Op-Code? * bne mainloop if not, continue waiting clrb clear B (for checksum) leax combuff,u point to comm buffer lbsr llread get command byte sta ,x+ save in comm buffer and inc X addb -1,x compute checksum lbsr llread get byte count of incoming message sta ,x+ save in comm buffer and inc X addb -1,x compute checksum pshs a save count on stack tsta count zero? beq csum@ branch if so n@ lbsr llread read data byte (count on stack) sta ,x+ save in our local buffer addb -1,x compute checksum dec ,s decrement count bne n@ if not zero, get next byte csum@ lbsr llread read checksum byte from host sta ,s save on stack (where count was) negb make 2's complement cmpa ,s+ same as host's? bne mainloop if not, ignore message * Here we have a message with a valid checksum. * Now we evaluate the command byte. processmsg lda combuff,u get command byte bpl _sendstatus command byte hi bit not set cmpa #FN_READ_MEM Read Memory? lbeq _readmem branch if so cmpa #FN_READ_REGS Read Registers? lbeq _readregs branch if so cmpa #FN_WRITE_MEM Write Memory? lbeq _writemem branch if so cmpa #FN_WRITE_REGS Write Registers? lbeq _writeregs branch if so cmpa #FN_GET_STATUS Get Status? lbeq _getstatus branch if so cmpa #FN_SET_BYTES Set Bytes? beq _setbytes branch if so cmpa #FN_RUN_TARGET Run Target? lbeq _runtarget * Here we send an error status _senderror lda #FN_ERROR sta combuff,u lda #1 _sendstatus sta combuff+2,u lda #1 sta combuff+1,u lbsr _sendtohost bra mainloop _runtarget IFNE KRNMOD clrb rts ELSE clrb os9 F$Exit ENDC * This routine is given a list of bytes to change. It must read the current * byte at that location and return it in a packet to the host so that * the host can restore the contents at a later time. _setbytes ldb combuff+1,u get count byte clr combuff+1,u set return count as zero lsrb divide number of bytes by 4 lsrb beq sb9@ pshs u save our statics pointer leau combuff+2,u point U to write outgoing data tfr u,y point Y to first 4 bytes sb1@ pshs b save loop counter ldd 1,y get address to write to exg a,b swap! tfr d,x memory address is now in X * Here, X = memory address to read * Y = 4 byte component in input packet * U = next place in com buffer to write "previous" byte * Read current data at byte location in process' space pshs u,a save byte spot for later and "next" ptr IFNE USERSTATE ldu <D.Proc ldb P$Task,u os9 F$LDABX ELSE lda ,x ENDC sta ,s save original ,X value on stack for now * A now holds the data byte -- insert new data at byte location lda 3,y get byte to store IFNE USERSTATE os9 F$STABX * Re-read current data at byte location in process' space os9 F$LDABX ELSE sta ,x lda ,x ENDC cmpa 3,y compare what we read from what we wrote puls a,u get "original" value and next ptr puls b restore loop count bne sb8@ carry affected by last cmpa * Save target byte in return buffer sta ,u+ ldx ,s get original statics ptr in X for now inc combuff+1,x count one return byte * Loop for next byte leay 4,y step to next byte in specifier cmpb combuff+1,x done? bne sb1@ * Return buffer with data from byte locations sb8@ puls u restore our original statics ptr sb9@ lbsr _sendtohost lbra mainloop sbe@ puls u restore what's on the stack bra _senderror * This routine reads memory from the calling process' address space * using F$Move. _readmem ldd combuff+3,u get source pointer exg a,b byte swap! tfr d,x and put in X clra clear A ldb combuff+5,u get count stb combuff+1,u and store count back in our header tfr d,y put count in Y pshs u,x save source pointer leau combuff+2,u point U to destination IFNE USERSTATE * User state ldx <D.Proc get current process pointer * cmpx <D.SysPrc same as system process? * beq copysys lda P$Task,x get source task # ldb <D.SysTsk get destination task # puls x restore source pointer os9 F$Move move 'em out! ELSE * System state puls x l@ lda ,x+ get byte at source and inc sta ,u+ save byte at dest and inc leay -1,y done? bne l@ branch if not ENDC puls u restore statics pointer bsr _sendtohost lbra mainloop * This routine writes memory from the host to the calling process' * address space using F$Move. _writemem leax combuff+5,u point X to source clra ldb combuff+1,u get count of packet subb #3 subtract 3 -- now we have our write count tfr d,y put count in Y ldd combuff+3,u get destination pointer exg a,b byte swap! pshs u,x save on stack tfr d,u and put source in U IFNE USERSTATE * User state ldx <D.Proc get current process pointer lda <D.SysTsk get source task # ldb P$Task,x get destination task # puls x restore source pointer os9 F$Move move 'em out! ELSE * System state puls x l@ lda ,x+ get byte at source and inc sta ,u+ save byte at dest and inc leay -1,y done? bne l@ branch if not ENDC puls u restore our static pointer ldd #$0100 assume successful write std combuff+1,u bsr _sendtohost lbra mainloop * This data is provided to the NoICE server upon receipt of FN_GET_STATUS. statdata FCB 33 number of bytes to send IFNE H6309 FCB 17 processor type: 6309 ELSE FCB 5 processor type: 6809 ENDC FCB cbsize size of communications buffer FCB %00000000 options flags FDB $0000 target mapped memory low bound FDB $FFFF target mapped memory high bound FCB 3 length of breakpoint instruction FCB $10,$3F,F$Debug breakpoint instruction * target description FCC "NitrOS-9/6" IFNE H6309 FCC "3" ELSE FCC "8" ENDC FCC "09 Level " IFEQ Level-1 FCC "1" ELSE FCC "2" ENDC FCB 0 _getstatus * copy status to our buffer leax statdata,pcr leay combuff+1,u ldb statdata,pcr l@ lda ,x+ sta ,y+ decb bpl l@ bsr _sendtohost lbra mainloop * This routine sends the contents of combuff,u to the communications * hardware. Note that the count that is stored at combuff+1,u is * set by the caller, and reflects the number of data bytes to be sent. * * Also, we compute the checksum as we send the bytes out so that * we don't have to call a separate routine. _sendtohost leax combuff,u point X to communications buffer ldb 1,x get count from header into B addb #2 add header bytes to count var B pshs b save on stack (this is our counter) clrb B is now used for checksum n@ addb ,x compute checksum lda ,x+ get byte from buffer and inc X lbsr llwrite write it out dec ,s decrement count on stack bne n@ if not zero, branch negb make 2's complement * comb make 2's complement * incb tfr b,a put in A lbsr llwrite write it puls b,pc return _readregs ldy callregs,u get pointer to caller's regs leax combuff+1,u IFNE H6309 ldb #21 get number of bytes to send ELSE ldb #16 get number of bytes to send ENDC stb ,x+ save number of bytes lda firsttime,u get first time called flag sta ,x+ write it clr ,x+ clear page reg ldd R$U,y exg a,b std ,x++ ldd R$Y,y exg a,b std ,x++ ldd R$X,y exg a,b std ,x++ IFNE H6309 ldd R$E,y exg a,b std ,x++ ENDC ldd R$A,y exg a,b std ,x++ ldb R$DP,y stb ,x+ DP ldb R$CC,y stb ,x+ CC ldd R$PC,y exg a,b std ,x++ PC ldy <D.Proc get SP from proc desc ldd P$SP,y exg a,b std combuff+4,u bsr _sendtohost lbra mainloop _writeregs ldy callregs,u get caller's reg ptr leax combuff+6,u * lda D.Debug * anda #D_BRKPT * sta <D.Debug ldd ,x++ exg a,b std R$U,y ldd ,x++ exg a,b std R$Y,y ldd ,x++ exg a,b std R$X,y IFNE H6309 ldd ,x++ exg a,b std R$E,y ENDC ldd ,x++ exg a,b std R$A,y ldb ,x+ stb R$DP,y ldb ,x+ stb R$CC,y ldd ,x++ exg a,b std R$PC,y ldd combuff+4,u exg a,b ldy <D.Proc std P$SP,y ldd #$0100 std combuff+1,u lbsr _sendtohost lbra mainloop ********** I/O ROUTINES ********** * 6551 Parameters ADDR EQU $FF68 A_RXD EQU ADDR+$00 A_TXD EQU ADDR+$00 A_STATUS EQU ADDR+$01 A_RESET EQU ADDR+$01 A_CMD EQU ADDR+$02 A_CTRL EQU ADDR+$03 * Baud rates _B2400 EQU $1A 2400 bps, 8-N-1 _B4800 EQU $1C 4800 bps, 8-N-1 _B9600 EQU $1E 9600 bps, 8-N-1 _B19200 EQU $1F 19200 bps, 8-N-1 BAUD EQU _B9600 * llinit - Initialize the low-level I/O * Exit: Carry = 0: Init success; Carry = 1; Init failed llinit IFNE MPI pshs a lda MPICTRL sta slot,u lda #RS232SLOT sta MPICTRL puls a ENDC sta A_RESET soft reset (value not important) * Set specific modes and functions: * - no parity, no echo, no Tx interrupt * - no Rx interrupt, enable Tx/Rx lda #$0B sta A_CMD save to command register lda #BAUD sta A_CTRL select proper baud rate * Read any junk rx byte that may be in the register lda A_RXD IFNE MPI pshs a lda slot,u sta MPICTRL puls a ENDC rts * llread - Read one character from 6551 * * Entry: None * Exit: A = character that was read * * Note, this routine currently doesn't timeout llread IFNE MPI lda MPICTRL sta slot,u lda #RS232SLOT sta $FF7F ENDC r@ lda A_STATUS get status byte anda #$08 mask rx buffer status flag beq r@ loop if rx buffer empty lda A_RXD get byte from ACIA data port IFNE MPI pshs b ldb slot,u stb MPICTRL puls b,pc ELSE rts ENDC * llwrite - Write one character to 6551 * * Entry: A = character to write * Exit: None llwrite IFNE MPI pshs d ldb MPICTRL stb slot,u ldb #RS232SLOT stb MPICTRL ELSE pshs a save byte to write ENDC w@ lda A_STATUS get status byte anda #$10 mask tx buffer status flag beq w@ loop if tx buffer full IFNE MPI puls d get byte sta A_TXD save to ACIA data port lda slot,u sta MPICTRL ELSE puls a get byte sta A_TXD save to ACIA data port ENDC rts * llterm - Terminate *llterm * rts IFNE 0 * llwout - Write an entire string * llwerr - Write an entire string llwerr llwout pshs a l@ lda ,x+ cmpa #C$CR beq e@ leay -1,y beq f@ bsr Write bra l@ e@ bsr Write lda #C$LF bsr Write f@ ldx <buffptr clrb puls a,pc * ReadLine - Read an entire string, up to CR * Entry: X = address to place string being read (CR terminated) * Y = maximum number of bytes to read (including nul byte) ReadLine ldx <buffptr pshs y,x,a ldy #80 l@ bsr Read read 1 character cmpa #C$CR carriage return? beq e@ branch if so... cmpa #$08 backspace? beq bs@ cmpy #$0000 anymore room? beq l@ leay -1,y back up one char sta ,x+ and save in input buffer m@ bsr Write echo back out bra l@ e@ sta ,x bsr Write lda #C$LF bsr Write clrb puls a,x,y,pc bs@ cmpx 1,s are we at start beq l@ if so, do nothing clr ,-x else erase last byte lbsr Write write backspace lda #C$SPAC a space... lbsr Write write it leay 1,y count back up free char lda #$08 another backspace bra m@ ENDC EMOD eom EQU * END