Fun with Cog Special Purpose Registers
hippy
Posts: 1,981
There's a comment in the thread on "what do people want for the Prop II" from Chip about executing code held in a Cog's Special Purpose Registers ($1F0-$1FF) which I hadn't paid much attention to or appreciated before, but is quite interesting. Maybe it's not news to everyone but some people may find it useful or at least interesting as well. If not, just ignore this post
Providing nothing is written to the SPR which affects the physical configuration of the Cog ( for example writing DIRA with non-zero will create an output pin ), code can be written and then executed. What's executed is whatever was written, not what would be read if that SPR were used as a source register in an instruction. That makes $1F0 to $1F5 available for use.
Code has to be moved into the SPR because it cannot be loaded as a part of CogNew which is a shame, but it may have some use somewhere. The following runs in SPR and increments a long in Hub memory ...
Note how the rdlong at $1F0 is executed as a rdlong not the instruction the value passed in as PAR represents, yet when PAR is used in that rdlong the actual PAR register is used to get the address which should be read.
Post Edited (hippy) : 3/11/2008 5:20:30 AM GMT
Providing nothing is written to the SPR which affects the physical configuration of the Cog ( for example writing DIRA with non-zero will create an output pin ), code can be written and then executed. What's executed is whatever was written, not what would be read if that SPR were used as a source register in an instruction. That makes $1F0 to $1F5 available for use.
Code has to be moved into the SPR because it cannot be loaded as a part of CogNew which is a shame, but it may have some use somewhere. The following runs in SPR and increments a long in Hub memory ...
CON _CLKMODE = XTAL1 + PLL16x _XINFREQ = 5_000_000 TV_PIN = 12 OBJ tv : "TV_Text" VAR long counter PUB Main tv.Start( TV_PIN ) CogNew( @IncHub, @counter ) repeat tv.Out( 1 ) tv.Dec( counter ) DAT IncHub org $000 mov $1F0,x1F0 mov $1F1,x1F1 mov $1F2,x1F2 mov $1F3,x1F3 mov $1F4,x1F4 mov $1F5,x1F5 jmp #$1F0 tmp long 0 x1F0 rdlong tmp,PAR ' $1F0 - PAR x1F1 add tmp,#1 ' $1F1 - CNT x1F2 wrlong tmp,PAR ' $1F2 - INA x1F3 nop ' $1F3 - INB x1F4 nop ' $1F4 - OUTA x1F5 jmp #$1F0 ' $1F5 - OUTB
Note how the rdlong at $1F0 is executed as a rdlong not the instruction the value passed in as PAR represents, yet when PAR is used in that rdlong the actual PAR register is used to get the address which should be read.
Post Edited (hippy) : 3/11/2008 5:20:30 AM GMT
Comments
Very popular are things as:
MOV INA, NN
....
DJNZ INA,...
Note that this double use affects the 6 "Read Only Registsters" (which obviously is a mis-nomer) only: PAR, CNT, INA, INB, PHSA, PHSB.
Here's a 'zero-footprint' LMM implementation which runs entirely in SPR ( the loading code can be zeroed as part of Cog initialisation ). Once LMM is running the LMM code has unrestricted use of all 496 registers, SPR and I/O ( except on Prop II because OUTB is used ).
Being kernel-less means jumps, calls and loads of values over $1FF have to be handled somewhat convolutedly in the LMM itself so it's not necessarily practical but could have possibilities.
This uses LMM to increment the long at $7FFC ...