PASM debug with just one long !
hippy
Posts: 1,981
I can feel the after-shock of Cluso99's jaw dropping and I bet he's not alone
Okay, it's not two longs, there's another three used to bootstrap the cog but they can be re-used as variables after bootstrapping and they can even be placed after PASM code with just a jump to that code at the start. I'm sure you get the drift; they aren't really used. Transient. Etc.
So what does it use ? Two longs at $1EE and $1EF.
Edited : Just one long at $1EF now
Okay, it uses four more at $1F0 through $1F3 but as no one uses them for executable code anyway you can consider them not there to start with, so just two longs it is then
So how does it work ? The bootstrap is a micro-LMM which loads another micro-LMM to $1EE through $1F3 which then simply waits for commands and executes them. That's enough to read and write to the Cog and once you can do that you can do anything, such as writing breakpoints ( a jump back into the Micro-LMM ). It can also be told to jump to code and it will execute full-blast until it hits a breakpoint.
To say there's some brain-warping trickery in the code is probably an understatement. No comments, no documentation apart from this - I'm not sure where to even start ! I think it may be possible to remove another long but my brain's given out.
Anyway enjoy. If there was a Propeller programming competition I think it might have been a contender but I don't have it in me to hold it back until there is. I even put a MIT License on the code.
Post Edited (hippy) : 8/31/2008 2:24:39 AM GMT
Okay, it's not two longs, there's another three used to bootstrap the cog but they can be re-used as variables after bootstrapping and they can even be placed after PASM code with just a jump to that code at the start. I'm sure you get the drift; they aren't really used. Transient. Etc.
So what does it use ? Two longs at $1EE and $1EF.
Edited : Just one long at $1EF now
Okay, it uses four more at $1F0 through $1F3 but as no one uses them for executable code anyway you can consider them not there to start with, so just two longs it is then
So how does it work ? The bootstrap is a micro-LMM which loads another micro-LMM to $1EE through $1F3 which then simply waits for commands and executes them. That's enough to read and write to the Cog and once you can do that you can do anything, such as writing breakpoints ( a jump back into the Micro-LMM ). It can also be told to jump to code and it will execute full-blast until it hits a breakpoint.
To say there's some brain-warping trickery in the code is probably an understatement. No comments, no documentation apart from this - I'm not sure where to even start ! I think it may be possible to remove another long but my brain's given out.
Anyway enjoy. If there was a Propeller programming competition I think it might have been a contender but I don't have it in me to hold it back until there is. I even put a MIT License on the code.
Post Edited (hippy) : 8/31/2008 2:24:39 AM GMT
Comments
Maybe there's a way to get it down to just one rdlong ? Hopefully someone will be inspired.
* Doesn't require any extra code adding to the PASM being debugged
* Supports Break Point and Single Stepping
* Doesn't use any "magic numbers"
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
It is a demo example
Just run the code and watch the TV. The first line shows the contents of three registers after loading, next after they've been added together ( actually it may scroll off the screen - remove a tv.out($0D) ).
The next three show the effect of single stepping ( one "add $1x,#1" at a time ) so the first, second then third number changes.
The final lines show running until the "BreakHere" label which executes the three adds at full PASM speed.
So the demo code is the PASM. If I want to set a breakpoint other than @breakhere, I need to know the offset address. The user interface is the spin code. Fair enough. If I want to debug another PASM module, I'll need to add this spin around it, etc....
I can assume that you could produce a spin debugger pretty easily with similar tricks with the spin interpreter still running in ROM. No? Isn't it just a matter of manipulating the spin bytecodes in a similar way? And with your work in making a spin disassembler, connecting that "source" to the debugger should be easy. No?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
However it's done, yes it's then possible to single step the Interpreter or single step per bytecode instruction. I'm not sure it would be simple but certainly not too hard. Turning that into a source level debugger would be more of a challenge.
For ImageCraft LMM-C that should be a doddle.
I've integrated this debugger into my LCC interpreter and it's working well. The same could be done with ICC. The neat thing is being able to break anywhere, including in an LMM so you can single step PASM or single step only executed LMM code. For, say a Basic stamp emulator, you could step every BS token, or every BS statement. I only support a single breakpoint but the sky's the limit.
I'm not planning on doing much more beyond what I have because it was really just another 'bright idea' which flashed up and it's now good enough for what I need.
I've turned it into an object so it's even easier to use and the demo is clearer. Version 005 in the first post. When I get have a useful LCC debugging demo I'll include that as well.
Gee -· go away for a weekend skiing (snow) and I get back to lose my thunder!
Great work hippy · Congratulations!!
I had read articles about the use of the mapped ram in the register space. I'll need to look a little further on this because we need to squeeze that long out of the cog space $000-1EF so that the debugger can be 0 footprint. As you know the spin interpreter uses $1E0-1EF (or thereabouts) and the latter part must remain intact.
I did not use another cog for the basic debugging (although that is how I initially started the Interpreter debugging), rather the cog runs the extra debug code from hub ram in a LMM style.
Maybe there is a mix here to combine both concepts to achieve the zero footprint and no cogs (other than for FDX, TV, VGA).
$1F5 and $1F7 should be usable as pointers which would give 4 instructions for the loop and 2 pointers (variables).
In the Interpreter debugger I used 4 for the loop and 2 pointers without using the flags c and z. With the use of the flags it may be possible to implement the whole debugger (with a lot more complexity) using 4+2.
Regarding the Ram Interpreter, I have a small modification which saves enough longs to implement the debugger to output each bytecode executed. I published it last week.·My sole reason for the debugger was to debug the Ram Interpreter. I can already effectively single-step the spin code (i.e. bytecode) and what I was trying to achieve was to single-step all the interpreter's asm. This led me to PASM and SPIN debuggers. I tried PASD but the problem was I had multiple copies of the interpreter running in different cogs.
@Chip: Is there anyway to use $1F4 as a·"jmp #$1F0" ? I am presuming as soon as a mov OUTA,xxxx (or any such instruction writing to $1F4) it will destroy the shadowed ram.
I'll look at all this in the morning as I have a relatively free day (or two)
The LMM debugger can be put anywhere and Chip's admitted that he might have been able to squeeze more out of the interpreter by keeping the jump tables in Hub; that could be done and the LMM debugger can then live in the freed up area.
Credit for what triggered this side-track goes to Chip speaking on Prop Mk II compatibility - something like, you'd lose "wrlong reg,#$1xx" - and that was enough to make me realise I didn't need an extra pointer register, and it escalated from there. All that talk of pipe-lining played its part subconsciously as well.
I'm about to use it in anger to debug my LCC VM which is playing up with one test program so I guess I'll discover what shortfalls it has !
PASM debug with Zero Footprint· http://forums.parallax.com/showthread.php?p=748420
Enjoy