ÿþ'' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '' % ClusoDebugger: Zero Footprint Propeller PASM & SPIN Debugger v0.275 % '' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$% '' % Author: "Cluso99" (Ray Rodrick) % '' % Copyright (c) 2008 "Cluso99" (Ray Rodrick) % '' % License MIT License - See end of file for terms of use % '' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$% '' % Acknowledgements: % '' % Many thanks to Hippy (AiChip Industries) for his original program % '' % using the shadow ram $1F0-1F3 in the cog for debugging and his % '' % program on hacking the interpreter. % '' % Some remnants of that code are used here and is % '' % Copyright (c) 2008 AiChip Industries under MIT License % '' % Thanks to Chip Gracey (Parallax) for publishing his Spin Interpreter. % '' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '' RR20080728 Debugger used for debugging ClusoInterpreter, but can be used generally. '' Uses PST (Propeller Serial Terminal) for debugging '' RR20080908 Release v0.250 '' RR20080909 v0.251 Fix jmpret/call '' v260C_004 Add Spin debug section ' v260C_006 Fix jmp/jmpret/tj../dj.. src indirect '' RR2080909 v0.252 Fix jmp/jmpret/tj../dj.. src indirect '' RR20080920 v0.270S Spin debugger (ClusoDebuggerDemo.spin, ClusoDebuggerSpin.spin, ClusoDebugger.spin) ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' % Top Object for testing ClusoDebugger (reference Rom & Ram Interpreter % ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' ' RR20080728 Debugger used for debugging ClusoInterpreter, but can be used generally. ' Uses PST (Propeller Serial Terminal) for debugging ' Uses Hub Ram $0000_7000 onwards for debugging buffer ' RR20080904 v200C_1 check the cogs being loaded and their parameters ' RR20080905 v200C_2 add coginit to load RamInterpreter #1 or RamInterpreter #2 (ClusoInterpreter) if cog #7 ' v200C_4 working 2 versions: cog 5 = working version, cog 7 = test version ' v200C_5 sqr disabled both working & test versions, waitcnt diff for each, clkset etc all enabled (exc sqr) ' v200C_7 cog 5 = RomInterpreter(control), cog 6 = RamInterpreter(works), cog 7 = ClusoInterpreter(test) ' v200C_8 start integrating ClusoInterpreter mods into ClusoInterpreter_200C_600 ' RR20080908 rename ClusoDebugger_250 --> ClusoDebugger_260C_000 & add ClusoDebugger_200C_8 code ' RR20080909 cog7 not started (ClusoInterpreter not working yet) ' RR20080909 v260C_001 add PUB GetPasmAddr to both Ram & Cluso Interpreters, change PUB Start -> Init & parameters ' RR20080910 fixes to ClusoInterpreter v260C_001 ' v260C_010 add code for compare/timing (timing needs sync to be accurate) ' RR20080911 revert to 260C_010 (015 has bugs) & fix PUB/PRI, use ClusoInterpreter_260C_002 (debug working again) ' fix ClusoInterpreter v003 ' RR20080912 v260C_034 mod to use cog 5/6/7 Rom/Chip/Cluso (part done) for timing comparisons, etc ' RR20080915 v260C_036 working but needs tidyup ' RR20080916 v260C_037 spin debug - show stack items 'ªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ð ' RR20080919 v270S_040 separate spin debug section ' RR20080920 _047 bug "O" spin display fails ' RR20080920 v270S_048 separate ClusoDebuggerSpin, ClusoDebugger and ClusoDebuggerDemo files ' _053 (par parameters seem incorrect, add keyboard features 'ªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ð '' RR20080920 v0.270S Spin debugger (ClusoDebuggerDemo.spin, ClusoDebuggerSpin.spin, ClusoDebugger.spin) 'ªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ð ' RR20080921 v271S_054 incorporate back into ClusoDebugger_260C_038 (debugging ClusoInterpreter) ' _055 change calling parameters, display cog par+ ' _056 combined pasm & spin version ' RR20080922 v275_061 Release version 0.275 ' RR20081011 v276_062 fix wrxxxx nr not displaying written values ' add instructions for show cog and hub memory (Bxxx>, BxxxH) ' ' OBJ fdx : "FullDuplexSerial" CON ' opcode zcri cond 876543210 876543210 OP_MOV = %101000_0010_1111_000000000_000000000 OP_RDLONG_IMM = %000010_0011_1111_000000000_000000000 OP_TEST_IWC = %011000_0101_1111_000000000_000000000 OP_TEST_IWZ = %011000_1001_1111_000000000_000000000 OP_WRLONG_IMM = %000010_0001_1111_000000000_000000000 OP_WRLONG_IFC = %000010_0001_1100_000000000_000000000 OP_WRLONG_IFZ = %000010_0001_1010_000000000_000000000 OP_COGID = %000011_0011_1111_000000000_000000001 OP_I = %000000_0001_0000_000000000_000000000 ERROR_DBLK = -1 ERROR_EXEC = -2 ERROR_POKE = -3 ERROR_MODE = -4 ERROR_COGADR = -5 ' Spin parameters in the cog S_LSB = $1E8 S_ID = $1E9 S_DCALL = $1EA S_PBASE = $1EB S_VBASE = $1EC S_DBASE = $1ED S_PCURR = $1EE 'code pointer (pc) S_DCURR = $1EF 'stack pointer (local) S_PAR = $1F0 'PAR register X_ENTER = $1F0 'debug code loop in shadow ram $1F0-1F3 VAR long cog_pc 'cog program counter (addr of next instruction) long dst_data 'destination data before executing the opcode long dst_addr 'destination address before executing the opcode long last_opc 'last opcode long stacktop 'set to top of stack at start long pasm_flag 'display pasm ? long spin_flag 'display spin ? long loops 'no. of loops to execute long break 'break on address long pline 'instruction counter of pasm code being executed long sline 'instruction counter of spin code being executed long debugstack[$80] 'stack for the debug cog long debugcog 'cog+1 of the debug cog long debugmode '\ -1 = Pasm debug '| -2 = Spin debug (at Interpreter Launch) '/ -3 = Spin debug (interrupt Interpreter) ' LMM code: pointers to hub memory ( DEBUG_BLOCK[32] must be <= $1FF ) long D_LMM '\ D_LMM_EXEC SUB X_ENTER, #4-0 'normally #4 (set to #0 by "execute") long D_OPC '| D_OPC_EXEC NOP 'the instruction to execute long D_VAL '/ D_VAL1_EXEC LONG 0 'data value for cog to hub store/load long D_BOOT '\ D_LMM_BOOT rdlong X_ENTER, #DB+@z_ENTER ' copies Debug code CON ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' % Start ClusoDebugger (Spin & Pasm) % ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PUB StartDebugger(dbgMode, atDebug_Block, atPasmCode, cogadr) : okay 'get start parameters ' Validate parameters if atDebug_Block > $1FF - 32 'must be in lower hub ram $0000-01FF abort ERROR_DBLK debugMode := dbgMode 'save the mode case debugMode -1 : ' -1 = Pasm debug if atPasmCode =< $20 'must be in hub ram... abort ERROR_COGADR 'Configure the DEBUG_BLOCK longmove (atDebug_Block, atPasmCode, 4) '\ save what we're overwriting (cog $000-003 presently in hub) longmove (atPasmCode, atDebug_Block + 96, 4) '/ & replace with bootloader code (cog $000-003 presently in hub) pasm_flag := true '\ set default flag setting spin_flag := false '/ okay := debugcog := cognew(StartDebugging (atDebug_Block, $000), @debugstack) + 1 'start ClusoDebugger (pasm) -2 : ' -2 = Spin debug (at Interpreter Launch) if atPasmCode =< $20 'must be in hub ram... abort ERROR_COGADR 'Configure the DEBUG_BLOCK longmove (atDebug_Block, atPasmCode, 4) 'save what we're overwriting (cog $000-003 presently in hub) longmove (atPasmCode, atDebug_Block + 96, 4) ' & replace with bootloader code (cog $000-003 presently in hub) pasm_flag := false '\ set default flag setting spin_flag := true '/ okay := debugcog := cognew(StartDebugging (atDebug_Block, $000), @debugstack) + 1 'start ClusoDebugger (pasm) -3 : ' -3 = Spin debug (interrupt Interpreter) 'we are tracing spin and the shadow ram has been already copied by a ClusoDebuggerSpin.spin !!! pasm_flag := false '\ set default flag setting spin_flag := true '/ okay := debugcog := cognew(StartDebugging (atDebug_Block, $1E4), @debugstack) + 1 'start ClusoDebugger (spin) other : abort ERROR_MODE PUB StopDebugger ' Shutdown cogs if debugcog > 0 fdx.stop 'stop fdx cogstop (debugcog~ - 1) 'stop debug cog PRI StartDebugging (atDebug_Block, cogadr) ' Set the hub pointers for the LMM code D_LMM := atDebug_Block + 52 '@D_LMM_EXEC 'HARDCODED !!! D_OPC := atDebug_Block + 56 '@D_OPC_EXEC D_VAL := atDebug_Block + 68 '@D_VAL1_EXEC D_BOOT := atDebug_Block + 16 '@D_LMM_BOOT ' D_bENT := atDebug_Block + 96 '@B_ENTER (used in StartDebugger above!) fdx.start(31,30,0,115200) 'start serial DebugHdr (cogadr) 'display options and wait for 'enter' DebugLoop 'go debugging StopDebugger 'stop routine when done PRI PauseMs( ms ) waitcnt( CLKFREQ / 1000 * ms + CNT ) CON ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' % Debug Routines % ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PRI DebugHdr (cogadr) PauseMs(100) 'small delay repeat 'wait for a serial character fdx.Str(string("ClusoDebugger: Press Enter to start.",13,10)) PauseMs(500) while fdx.rxcheck == -1 fdx.tx($00) 'clear screen fdx.Str(string("ClusoDebugger v0.276",13,10,13,10)) fdx.str(string(" S = Skip 1 instruction {no trace} c/C = Clear/Set C ", 13,10)) fdx.str(string(" nnS = Skip nn instructions z/Z = Clear/Set Z ", 13,10)) fdx.str(string(" T = Trace 1 instruction (or Enter) O = Toggle Spin debug ", 13,10)) fdx.str(string(" nnT = Trace nn instructions P = Toggle Pasm debug ", 13,10)) fdx.str(string(" BxxxS = Skip until Break $xxx address ", 13,10)) fdx.str(string(" BxxxT = Trace until Break $xxx address ", 13,10)) fdx.str(string(" Bxxx> = Show COG memory R = Reboot ", 13,10)) fdx.str(string(" BxxxH = Show HUB memory X = exit debugger ", 13,10)) fdx.str(string(13,10)) cog_pc := cogadr 'set cog pc address (debug address) (pasm=$000, spin=$1E4) dst_addr := -1 'no last dest address break := -1 loops := 0 pline := 0 sline := 0 DisplayCogHdr 'cog par details DisplayPasmHdr 'heading DisplayHdr 'underlines PRI DebugLoop | chr, data ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' % Commence debugging % ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DisplayLine 'display next line (instruction to execute) repeat chr := fdx.rx if break <> -1 case chr "0".."9" : break := (break << 4) + (chr & $0F) chr := $FF "A".."F" : break := (break << 4) + (chr - "A" + 10) chr := $FF "a".."f" : break := (break << 4) + (chr - "a" + 10) chr := $FF case chr "O","o" : spin_flag := !spin_flag "P","p" : pasm_flag := !pasm_flag "C" : SetC "c" : ClrC "Z" : SetZ "z" : ClrZ $FF : 'special case - ignore "B","b" : 'BREAK (address follows) break := 0 "S","s" : 'SKIP single step nn instructions DoLoops ("S") 'step/display "T","t", $0D : 'TRACE single step nn instructions (no display) DoLoops ("T") 'step/display "0".."9" : loops := (loops * 10) + (chr & $0F) "R","r" : DisplayHdr PauseMs(50) REBOOT ">","." : 'show cog memory Bxxx> data := Peek(break) fdx.str(string(13,10,"Cog (")) fdx.hex(break,3) fdx.str(string(") ")) fdx.hex(data,8) fdx.str(string(13,10)) break := -1 "H","h" : 'show hub memory BxxxH data := long[break] fdx.str(string(13,10,"Hub (")) fdx.hex(break,4) fdx.str(string(") ")) fdx.hex(data,8) fdx.str(string(13,10)) break := -1 "J","j" : 'jump to cog addr BxxxJ if break < $1F0 cog_pc := break dst_addr := -1 break := -1 fdx.str(string(13,10)) DisplayLine other : loops := 0 break := -1 while chr <> "X" and chr <> "x" and chr <> $1B ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' % Finished debugging % ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DisplayHdr PauseMs (100) PRI DoLoops (show) if loops == 0 loops++ if break <> -1 'Break/Trace ? fdx.str(string(13,10," Break $")) fdx.hex(break, 3) fdx.str(string(" ")) repeat SingleStep 'single step 1 instruction (execute it) if show == "T" DisplayLine 'display next line (instruction to execute) if fdx.rxcheck <> -1 'any character will stop the loop fdx.str(string(13,10," interrupted ")) break := cog_pc while cog_pc <> break and loops > 0 'break address or loops done ? if show <> "T" DisplayLine 'if skipping, show the current line loops := 0 break := -1 CON ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' % Display Routines % ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PRI DisplayLine if dst_addr <> -1 'skip first time or if not displaying DisplayPasmEOL 'display updated pasm data at end of line if spin_flag == true and cog_pc == $008 'display spin ? DisplaySpin if pasm_flag == true 'display pasm ? DisplayPasm PRI DisplayCogHdr | ptr, i fdx.str(string("Cog ")) fdx.dec(GetID) 'display cogID (S_ID may not be set yet) fdx.str(string(", Par ")) ptr := GetReg(S_PAR) 'get PAR register fdx.hex(ptr, 4) 'display PAR fdx.str(string(": ")) ptr := ptr repeat i from 0 to 10 step 2 'display xxx, pbase, vbase, dbase, pcurr, dcurr case debugmode -2, -3 : case i 2 : fdx.str(string("pb")) 4 : fdx.str(string("vb")) 6 : fdx.str(string("db")) 8 : fdx.str(string("pc")) 10 : fdx.str(string("sp")) fdx.hex(word[ptr + i],4) fdx.tx(" ") stacktop := word[ptr + 10] 'save dcurr (top of stack at start if spin) fdx.str(string(13,10)) PRI DisplayHdr fdx.str(string(13,10)) fdx.str(string("------------------------------------------------------------------------------------")) fdx.str(string(13,10)) PRI DisplaySpin | dcall, pbase, vbase, dbase, pcurr, dcurr, i, j, c pcurr := Peek(S_PCURR) 'code pointer (byte) dcurr := Peek(S_DCURR) 'stack pointer (word) 'display the bytecodes fdx.str(string("spin: pc(")) fdx.hex(pcurr,4) fdx.str(string(") ")) repeat i from 0 to 4 'display the next 5 bytecodes fdx.hex(byte[pcurr + i],2) fdx.tx(" ") 'display the stack fdx.str(string(" sp")) fdx.tx("+") c := (dcurr - stacktop) / 4 'count of items on stack fdx.hex(c, 2) fdx.tx("(") fdx.hex(dcurr, 4) fdx.str(string(") ")) repeat i from 0 to 3 'display stack items (max 4) if c > i 'only display valid stack entries fdx.hex(long[dcurr - 4 - (i * 4)],8) fdx.tx(" ") else fdx.str(string("-------- ")) fdx.str(string(" (")) 'display instruction counts fdx.dec(sline) fdx.tx(",") fdx.dec(pline +1) fdx.tx(")") fdx.str(string(13,10)) PRI DisplayPasmHdr fdx.str(string("adr conds op wc wz nr dst src : cz dst_data src_data : new_dst ")) PRI DisplayPasm | adr, opc ' Display the instruction data adr := cog_pc 'get the debug address fdx.tx("$") fdx.hex( adr, 3) 'display current cog pc address fdx.tx(" ") opc := Peek (adr) 'get the opcode last_opc := opc 'save this opcode 'decode the conditional execution bits case ( opc >> 18) & $0F %0000 : fdx.str(string("-nop- . . ")) %0001 : fdx.str(string("if_nc_and_nz ")) %0010 : fdx.str(string("if_nc_and_z ")) %0011 : fdx.str(string("if_nc ")) %0100 : fdx.str(string("if_c_and_nz ")) %0101 : fdx.str(string("if_nz ")) %0110 : fdx.str(string("if_c_ne_z ")) %0111 : fdx.str(string("if_nc_or_nz ")) %1000 : fdx.str(string("if_c_and_z ")) %1001 : fdx.str(string("if_c_eq_z ")) %1010 : fdx.str(string("if_z ")) %1011 : fdx.str(string("if_nc_or_z ")) %1100 : fdx.str(string("if_c ")) %1101 : fdx.str(string("if_c_or_nz ")) %1110 : fdx.str(string("if_c_or_z ")) %1111 : fdx.str(string(". . . . ")) 'decode the op case ( opc >> 26) & $3F %000000 : if opc == 0 'special case "nop" fdx.str(string("nop ")) else case ( opc >> 23) & $01 'nr 0 : fdx.str(string("wrbyte ")) 1 : fdx.str(string("rdbyte ")) %000001 : case ( opc >> 23) & $01 'nr 0 : fdx.str(string("wrword ")) 1 : fdx.str(string("rdword ")) %000010 : case ( opc >> 23) & $01 'nr 0 : fdx.str(string("wrlong ")) 1 : fdx.str(string("rdlong ")) %000011 : 'hubop case opc & $07 'src bits 2..0 0 : fdx.str(string("clkset ")) 1 : fdx.str(string("cogid ")) 2 : fdx.str(string("coginit ")) 3 : fdx.str(string("cogstop ")) 4 : fdx.str(string("locknew ")) 5 : fdx.str(string("lockret ")) 6 : fdx.str(string("lockset ")) 7 : fdx.str(string("lockclr ")) %000100 : fdx.str(string("?mul ")) %000101 : fdx.str(string("?muls ")) %000110 : fdx.str(string("?enc ")) %000111 : fdx.str(string("?ones ")) %001000 : fdx.str(string("ror ")) %001001 : fdx.str(string("rol ")) %001010 : fdx.str(string("shr ")) %001011 : fdx.str(string("shl ")) %001100 : fdx.str(string("rcr ")) %001101 : fdx.str(string("rcl ")) %001110 : fdx.str(string("sar ")) %001111 : fdx.str(string("rev ")) %010000 : fdx.str(string("mins ")) %010001 : fdx.str(string("maxs ")) %010010 : fdx.str(string("min ")) %010011 : fdx.str(string("max ")) %010100 : fdx.str(string("movs ")) %010101 : fdx.str(string("movd ")) %010110 : fdx.str(string("movi ")) %010111 : case ( opc >> 23) & $01 'nr 0 : fdx.str(string("jmp ")) 1 : fdx.str(string("jmpret ")) %011000 : fdx.str(string("and ")) %011001 : fdx.str(string("andn ")) %011010 : fdx.str(string("or ")) %011011 : fdx.str(string("xor ")) %011100 : fdx.str(string("muxc ")) %011101 : fdx.str(string("muxnc ")) %011110 : fdx.str(string("muxz ")) %011111 : fdx.str(string("muxnz ")) %100000 : fdx.str(string("add ")) %100001 : fdx.str(string("sub ")) %100010 : fdx.str(string("addabs ")) %100011 : fdx.str(string("subabs ")) %100100 : fdx.str(string("sumc ")) %100101 : fdx.str(string("sumnc ")) %100110 : fdx.str(string("sumz ")) %100111 : fdx.str(string("sumnz ")) %101000 : fdx.str(string("mov ")) %101001 : fdx.str(string("neg ")) %101010 : fdx.str(string("abs ")) %101011 : fdx.str(string("absneg ")) %101100 : fdx.str(string("negc ")) %101101 : fdx.str(string("negnc ")) %101110 : fdx.str(string("negz ")) %101111 : fdx.str(string("negnz ")) %110000 : fdx.str(string("cmps ")) %110001 : fdx.str(string("cmpsx ")) %110010 : fdx.str(string("addx ")) %110011 : fdx.str(string("subx ")) %110100 : fdx.str(string("adds ")) %110101 : fdx.str(string("subs ")) %110110 : fdx.str(string("addsx ")) %110111 : fdx.str(string("subsx ")) %111000 : fdx.str(string("cmpsub ")) %111001 : fdx.str(string("djnz ")) %111010 : fdx.str(string("tjnz ")) %111011 : fdx.str(string("tjz ")) %111100 : fdx.str(string("waitpeq ")) %111101 : fdx.str(string("waitpne ")) %111110 : fdx.str(string("waitcnt ")) %111111 : fdx.str(string("waitvid ")) fdx.tx(" ") case ( opc >> 24) & $01 'wc 0 : fdx.str(string(". ")) 1 : fdx.str(string("wc ")) case ( opc >> 25) & $01 'wz 0 : fdx.str(string(". ")) 1 : fdx.str(string("wz ")) case ( opc >> 23) & $01 'nr 0 : fdx.str(string("nr ")) 1 : fdx.str(string(". ")) fdx.tx("$") fdx.hex( (opc >> 9) & $1FF, 3) 'dst fdx.tx(",") case ( opc >> 22) & $01 'immediate 0 : fdx.tx(" ") 1 : fdx.tx("#") fdx.tx("$") fdx.hex( opc & $1FF, 3) 'src fdx.str(string(" : ")) case (GetC) true : fdx.tx("C") other: fdx.tx("-") case (GetZ) true : fdx.tx("Z") other: fdx.tx("-") fdx.tx(" ") 'display the cog data at both dest and src dst_data := Peek( (opc >> 9) & $1FF) 'dst_data fdx.str(string(" $")) fdx.Hex( dst_data, 8 ) case ( opc >> 22) & $01 'immediate 0 : fdx.str(string(" $")) fdx.Hex( Peek( opc & $1FF ), 8 ) 'src_data 1 : fdx.str(string(" $")) fdx.Hex( opc & $1FF, 3 ) '#src_data 'save last destination address (for next loop) dst_addr := (opc >> 9) & $1FF PRI DisplayPasmEOL 'display the new dst data (after last instruction execution) case ( last_opc >> 26) & $3F %000000, %000001, %000010 : fdx.str(string(" : $")) 'display rd/wr byte/work/long fdx.hex( Peek (dst_addr), 8) other : if Peek (dst_addr) == dst_data 'has it changed? fdx.str(string(" : ")) 'no: else fdx.str(string(" : $")) 'yes: display it fdx.hex( Peek (dst_addr), 8) dst_addr := -1 'set EOL data displayed fdx.tx(" ") 'display instruction counts fdx.tx("(") if debugmode <> -1 fdx.dec(sline) fdx.tx(",") fdx.dec(pline) fdx.tx(")") fdx.str(string(13,10)) CON ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' % Single Step Routine % ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PRI SingleStep | adr, opc, exec, jump, jumpret, dest, c, nc, z, nz ' Get the next adr & instruction adr := cog_pc 'get the debug address opc := Peek (adr) 'get the opcode 'Increment the next adr (will be modified if a valid jmp) cog_pc ++ 'decode the conditional execution bits nc := not ( c := GetC ) nz := not ( z := GetZ ) case ( opc >> 18) & $0F %0000 : exec := false 'NEVER (we report NEVER for wrbyte but it works anyway!) %0001 : exec := nc and nz 'if_nc_and_nz %0010 : exec := nc and z 'if_nc_and_z %0011 : exec := nc 'if_nc %0100 : exec := c and nz 'if_c_and_nz %0101 : exec := nz 'if_nz %0110 : exec := nc <> nz 'if_c_ne_z %0111 : exec := nc or nz 'if_nc_or_nz %1000 : exec := c and z 'if_c_and_z %1001 : exec := c == z 'if_c_eq_z %1010 : exec := z 'if_z %1011 : exec := nc or z 'if_nc_or_z %1100 : exec := c 'if_c %1101 : exec := c or nz 'if_c_or_nz %1110 : exec := c or z 'if_c_or_z %1111 : exec := true 'ALWAYS 'if we are going to execute this instruction, check if it can jump (jmp.../tj../dj.)? if exec == true 'decode the op (only interested in jump versions) ' (ignore hubops!! even tho' we could lose control; ignore waitcnt/waitp../waitvid) jump := false jumpret := -1 case ( opc >> 26) & $3F %010111 : 'jmp/jmpret/ret/call jump := true case ( opc >> 23) & $01 'nr 1 : jumpret := cog_pc 'jmpret so save cog_pc address for below %111001 : jump := Peek(( opc >> 9 ) & $1FF ) <> 1 'djnz (we test before it decrements) %111010 : jump := Peek(( opc >> 9 ) & $1FF ) <> 0 'tjnz %111011 : jump := Peek(( opc >> 9 ) & $1FF ) == 0 'tjz 'if we are going to jump, then set the new cog pc address, and mod the src to keep debug control if jump == true 'collect new next address case ( opc >> 22) & $01 'immediate? 0 : cog_pc := Peek( opc & $1FF ) & $1FF 'src_data 1 : cog_pc := opc & $1FF '#src_data 'set src = #X_ENTER ($1F0) to keep control opc := opc | OP_I '# opc := (opc & !$1FF) | X_ENTER '#X_ENTER ($1F0) Execute( opc, 0 , 0 ) 'execute the opc (may have been modified) If jump == true and jumpret <> -1 'jmpret/call dest := Peek(( opc >> 9 ) & $1FF ) 'get the destination data Poke((( opc >> 9 ) & $1FF ), (dest & !$1FF) | jumpret) 'store the new return address in dest ' Increment the instruction counters pline++ if cog_pc == 8 sline++ ' Decrement the loop counter if pasm_flag == true 'decrement loop counter by pasm or spin? loops-- else if cog_pc == 8 loops-- CON ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' % Debug Support Routines % ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PRI Execute( opc, dst, src ) if byte[ D_LMM ] <> 4 abort ERROR_EXEC ' Execute 1 loop of hub LMM code long[ D_OPC ] := opc | ( dst << 9 ) | src 'copy instruction to be executed into LMM byte[ D_LMM ] := 0 'signal opcode ready (allows LMM hub pointer to increment) repeat while byte[ D_LMM ] <> 4 'wait for cog to signal loop done long[ D_OPC ] := 0 'clear opcode (not required, but nice) PRI Peek( cogAdr ) Execute( OP_WRLONG_IMM, cogAdr, D_VAL ) result := long[ D_VAL ]~ PRI Poke( cogAdr, num ) if cogAdr => $1F0 and cogAdr =< $1F3 abort ERROR_POKE long[ D_VAL ] := num Execute( OP_RDLONG_IMM, cogAdr, D_VAL ) long[ D_VAL ] := 0 PRI GetC long[ D_VAL ] := 0 Execute( OP_WRLONG_IFC, X_ENTER , D_VAL ) result := ( long[ D_VAL ]~ <> 0 ) PRI GetZ long[ D_VAL ] := 0 Execute( OP_WRLONG_IFZ, X_ENTER , D_VAL ) result := ( long[ D_VAL ]~ <> 0 ) PRI SetC Execute( OP_TEST_IWC, D_OPC, 1 ) PRI ClrC Execute( OP_TEST_IWC, D_OPC, 0 ) PRI SetZ Execute( OP_TEST_IWZ, D_OPC, 0 ) PRI ClrZ Execute( OP_TEST_IWZ, D_OPC, 1 ) PRI GetReg( cogReg ) | id id := Peek(S_ID) 'save cog data Execute( OP_MOV, S_ID, cogReg) 'read cog register Result := Peek(S_ID) Poke(S_ID, id) 'restore cog data PRI GetID | id id := Peek(S_ID) 'save cog data Execute( OP_COGID, S_ID, 0) 'get cogid Result := Peek(S_ID) Poke(S_ID, id) 'restore cog data (in case it was different 'ªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ðªð©ð {{ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TERMS OF USE: MIT License % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$% %Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation % %files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, % %modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software% %is furnished to do so, subject to the following conditions: % % % %The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.% % % %THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE % %WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR % %COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, % %ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% }}