Mercurial > hg > Members > kono > nitros9-code
view 3rdparty/p2mods/noice/noice.asm @ 3215:195c09cade21
Updated MMC Driver makefile so it will have place holders for
dsk, dskclean, and dskcopy so that make does not error out when
chaining into the driver tree to build disk images where applicable.
author | David Ladd <drencor-xeen@users.sourceforge.net> |
---|---|
date | Wed, 20 Dec 2017 16:07:36 -0600 |
parents | 51a12746307c |
children |
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. * * 3 2006/03/02 Boisy G. Pitre * NoICE now displays user or system information in Level 2 with the * addition of a system state system call and the ssflag variable. * * 4 2006/03/04 Boisy G. Pitre * Memory now allocated upon first encounter of system call. * * 5 2006/03/05 Boisy G. Pitre * User and system call entry points for F$Debug now part of both * NitrOS-9 Level 1 and Level 2. NAM KrnP3 TTL NoICE Serial Debugger for 6809/6309 IFP1 USE defsfile ENDC IFGT Level-1 tylg SET Systm+Objct ELSE tylg SET Prgrm+Objct ENDC atrv SET ReEnt+rev rev SET $00 edition SET 5 * If an MPI is being used, set DEVICESLOT to slot value - 1 and set MPI to 1 DEVICESLOT 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 syssp RMB 2 ssflag RMB 1 IFNE MPI slot RMB 1 ENDC combuff RMB cbsize size EQU . L0000 MOD eom,name,tylg,atrv,start,size name EQU * IFGT Level-1 FCS /KrnP3/ ELSE FCS /noice/ ENDC FCB edition IFGT Level-1 nextname FCC /KrnP4/ next module name to link to FCB C$CR ENDC svctabl FCB F$Debug FDB dbgent-*-2 FCB F$Debug+$80 FDB dbgentss-*-2 FCB $80 start IFEQ Level-1 leax name,pcr clra os9 F$Link link module into memory (Level 1) ENDC leay svctabl,pcr os9 F$SSvc install F$Debug service bcs ex@ clra clrb std >D.DbgMem set pointer to $0000 so it will be allocated later IFEQ Level-1 ex@ os9 F$Exit ELSE 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 * Called to get debugger memory getmem tfr u,x put regs ptr in X ldu <D.DbgMem get pointer to our statics in X bne retok ldd #$0100 os9 F$SRqMem allocate memory bcs ret stu <D.DbgMem save our allocated memory * Set 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 > $00 retok stx callregs,u save pointer to caller's regs clrb ret rts * User State Debugger Entry Point * * We enter here when a process or the system makes an os9 F$Debug call from * user state. dbgent bsr getmem bcs ret clra bra usernext * System State Debugger Entry Point * * We enter here when a process or the system makes an os9 F$Debug call from * system state. dbgentss bsr getmem bcs ret lda #$01 * Interesting trick here... I cannot see where the kernel stores the stack * register when processing a system call in system state. I observed that * the actual value of S was some constant from where S is when entering the * system call. We'll see how this holds up during system state debugging, * and whether changes to the kernel will affect this offset. IFEQ Level-1 stackoff equ $12 ELSE stackoff equ $15 ENDC leas stackoff,s sts syssp,u leas -stackoff,s usernext sta ssflag,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 ioinit 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 ioread 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 ioread get command byte sta ,x+ save in comm buffer and inc X addb -1,x compute checksum lbsr ioread 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 ioread 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 ioread 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 clrb rts * 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 IFGT Level-1 ldu 4,s get original U tst ssflag,u bne ss@ ldu <D.Proc ldb P$Task,u os9 F$LDABX sta ,s save original ,X value on stack for now lda 3,y get byte to store os9 F$STABX * Re-read current data at byte location in process' space os9 F$LDABX bra p@ ENDC ss@ lda ,x 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 sta ,x lda ,x p@ 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 IFGT Level-1 tst ssflag-combuff-2,u bne ss@ * User state ldx <D.Proc get current process pointer lda P$Task,x get source task # ldb <D.SysTsk get destination task # puls x restore source pointer os9 F$Move move 'em out! bra p@ ENDC * System state ss@ 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 p@ 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 IFGT Level-1 tst ssflag,u bne ss@ * User state tfr d,u and put source in U 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! bra p@ ENDC * System state ss@ tfr d,u and put source in U 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 p@ 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 iowrite 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 iowrite 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 leax 2,x skip PC for now 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 IFNE H6309 * All this code is necessary to get the value of MD * Note: bits 2-5 are unused ldb <D.MDREG get shadow register from sysglobs * bitmd #%00000001 * beq md1 * incb set bit 0 *md1 bitmd #%00000010 * beq md6 * orb #%00000010 set bit 1 md6 bitmd #%01000000 beq md7 orb #%01000000 md7 bitmd #%10000000 beq tfrmd orb #%10000000 tfrmd stb ,x+ MD * V register tfr v,d exg a,b std ,x++ V ENDC ldd R$PC,y exg a,b std ,x PC tst ssflag,u system state? beq us@ ldd syssp,u bra cmn@ us@ ldy <D.Proc get SP from proc desc ldd P$SP,y cmn@ exg a,b std combuff+4,u lbsr _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 IFNE H6309 * Note: because the only way to write to the MD register is via immediate mode, * we must build a "ldmd #XX; rts" instruction on the stack then execute it in order * to avoid "self modifying" code. * ldd #$113D "ldmd" instruction * std -6,s lda ,x+ MD register * ldb #$39 "rts" instruction * std -4,s * jsr -6,s call code on stack to modify MD ldd ,x++ exg a,b tfr d,v V register ENDC ldd ,x++ exg a,b std R$PC,y ldd combuff+4,u exg a,b tst ssflag,u beq us@ std syssp,u bra cmn@ us@ ldy <D.Proc std P$SP,y cmn@ 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 * ioinit - Initialize the low-level I/O * Exit: Carry = 0: Init success; Carry = 1; Init failed ioinit IFNE MPI pshs a lda MPI.Slct sta slot,u lda #DEVICESLOT sta MPI.Slct 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 MPI.Slct puls a ENDC rts * ioread - Read one character from 6551 * * Entry: None * Exit: A = character that was read * * Note, this routine currently doesn't timeout ioread IFNE MPI lda MPI.Slct sta slot,u lda #DEVICESLOT 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 MPI.Slct puls b,pc ELSE rts ENDC * iowrite - Write one character to 6551 * * Entry: A = character to write * Exit: None iowrite IFNE MPI pshs d ldb MPI.Slct stb slot,u ldb #DEVICESLOT stb MPI.Slct 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 MPI.Slct ELSE puls a get byte sta A_TXD save to ACIA data port ENDC rts * ioterm - Terminate *ioterm * rts IFNE 0 * iowout - Write an entire string * iowerr - Write an entire string iowerr iowout 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