Update: Released new version! - Jump table in graphics.spin
stevenmess2004
Posts: 1,102
The jump table in graphics.spin is made up of 8 bit entries (bytes) but this can only reach half the memory. This is alright for most of the commands but I would have thought that the textmode_ subroutine was more than 255 longs from the jump. It obviously isn't since it works. Interesting example. Can you use the labels in spin so that the jump table is eliminated? So instead of passing the number of the method ie 1-15 you passed the address (using the label) of where to jump to? This would save a fair few longs in the cog and possibly allow for another function.
Steven
Edit - Out of this discussion I developed a new version of graphics.spin that does XOR and can use the ROM font and Clemens font. See last post for latest version.
Post Edited (stevenmess2004) : 4/20/2008 12:18:48 PM GMT
Steven
Edit - Out of this discussion I developed a new version of graphics.spin that does XOR and can use the ROM font and Clemens font. See last post for latest version.
Post Edited (stevenmess2004) : 4/20/2008 12:18:48 PM GMT
Comments
(b) _textmode and _fill are $DA and $DD respectively, ample space upto $FF
---
Edit (ad (a)):
The simplest COG code to utilize this would be:
--
Edit 2:
However this is considered bad non-defensive programming. There is no chance to check for fatal errors any longer.
In case of a nice sequence of numbers you can very simply direct faulty parameters to a graceful exit by the handy MIN and MAX instruction!
Post Edited (deSilva) : 2/9/2008 10:31:24 AM GMT
Now watch some magic!
But as you still need 3 cells it is just fancy humbug ...
---
Edit: You should never start such things...
What about:
Edit2:
This utilizes that we KNOW that bits 9 to 17 are not used in JMP
Post Edited (deSilva) : 2/9/2008 10:58:59 AM GMT
and somewhere else
then won't the word at @otherLabel hold the cog address of someLabel?
rather than the clumbsy expression I gave in my posting
However this is confusing with fast pace postings, which however we do not have so often....
The LONG 0 at address 0 is the intermediate place for the destination address. It was placed there to show the systematic development to the third solution. The third solution was handicapped by the interleaved instruction fetch, so I used the unused slot to add the acknowedge instruction... This is in fact the most compact form.
When it comes to bytes and words even in SPIN, my original suggestion (@.. - @..>>2) when used in a central routine as "setCommand" is shorter than a full word-table for labels... There is a break even point, around 10 entries I should say.
I guess that speed would also be a consideration since @ is calculated at runtime. Looking at the manual you should be able to do
From page 278 of the manual it would seem that you can do this but I get an 'undefined symbol' error when I try to compile it.
Using an address STATICALLY is a diferent thing than COMPUTING this address; although both usages are indicated by the @ symbol.
Although it makes terribly sense to use a DIFFERENCE of adresses, the addresses itself will be known in a later phase of the compilation only, whilst all CONSTANTS must be known in a very early phase.
So the compiler - missing the intelligence to distinguish those both situations - generally forbids to use @name in constant contexts.
But there is an exception - as described on that page 278 you quoted. You can get a RELATIVE value for the later use with the @@ operator.
However this is allowed inside the DAT sections only and only for names defined in DAT sections!! Note you can do things there as:
The other two constant contexts (CON section and constant(...) ) are more limited; funnily there is a minor difference between those as well.
I think I try to find the things I have written about this
Post Edited (deSilva) : 2/9/2008 12:01:30 PM GMT
But the reason is simple: the constants in CON are bound to a name, which can be used in other constant context, e.g. to allocate a vector.... Which will change the address pattern...
The constants computed by constant(....) cannot be bound to a name, they are more "passive" so to speak. Note that constant(...) is allowed in PUB/PRI only!
I always wondered how Chip sorted out all those different situations.
It is fine when you need some feature, but a hack to EXPLAIN all those ad-hoc limitations to someone
Post Edited (deSilva) : 2/9/2008 9:51:26 PM GMT
-Phil
I think that I am going to have to see what I can do with graphics.spin.
BTW: I think there is a common misunderstanding... The # is not a part of the operand, but a part of the opcode. It is situated at the place just in front of the operand in question for simplicity and conveniance.
Post Edited (deSilva) : 2/10/2008 7:55:50 AM GMT
Steven
Post Edited (stevenmess2004) : 2/10/2008 3:02:00 AM GMT
It may not actually faster because I don't think that all constants are byte alligned regardless of length. (Would have to check hippy's spin documentation to be sure)
So to sum up. If you want your program to be as small as possible, it may be best to make your constants fit in a byte or word and then manipulate them to the form you want.
Steven
At the moment all drawing is done with with an opaque pen substituting the color. There are good reasons why "adult" graphics systems have more choice... The thing most often needed is XORing the colors, to make things undone. This will gravely simplify some flicker free updating without double buffering!
I once patched it for it (that was when I found out it was using the complete COG memory upto the last cell ) doing XOR only, but that was not exceptable..
The user interface could be through the colours, there are 4 at the moment 0,1,2,3.
Leaving some spares, an offset of 256 could mean XOR....
---
Edit:
As this is in the central drawing routine it can be done with 4 instructions I think...
Post Edited (deSilva) : 2/10/2008 8:24:16 AM GMT
Another implementation option would be to allocate "constants" in the RAM, just addressing them by indirection with static memory fetch bytecodes - the same as we do in PASM when a constants exceeds 9 bits. The great advantage is that you neither need a set of special bytecodes for constants anymore and you can re-use the same constant value from different places... Hippy will know...
So it looks like you could actually have byte, word, 3 byte and long. Not sure what the compiler does though. So if you constant is bigger than a word and used multiple times then it may be smaller to put something in the DAT section and use that as a constant. May also be quicker as the proper constants may need more hub accesses. Something to consider is the PUSH -1, 0 and 1 opcodes which will really speedup a lot of things.
-Phil
Okay, we have 15 longs in the cog to play with. I think that we could add another 2 commands to set which to do. (commands would be setOverwrite, setXOR).
The code to draw standard pixels is
So to only do the XOR we can just make the andn a nop and change it back when we want to do overwrite.
Where we will have problems is that this will also need changing in the same way
So we would need three instructions + a return so thats 4 instructions for each change plus 2 longs to store the masks in. So that comes to a total of 4+4+2=10 longs which will fit. If you agree with this I'll see if I can get it working.
I have a test program here somewhere for the XOR mode... but where??
@ byte code: I still cannot believe this sophistication... I think I should have needed 10% of the COG alone to implement all those constant push operations
Post Edited (deSilva) : 2/10/2008 9:57:54 AM GMT
What will be your API for doing this dynamically? Pseudocolors (256+c) ? Or a new call? Each long counts, I think
for change to XOR
1. the and to a NOP by doing an AND with a mask that sets the condition bits to 0 - needs 1 long - 1 for instruction a the mask can get passed by the calling function as an argument
2. the OR to an XOR by using a movi - needs 1 longs - needs one for the instruction the new instruction can get passed as an argument
so we need 2 + 1 return = 3 longs to change one position to XOR
to change back
3. the NOP by using an XOR with a mask that sets the condition bits to whatever is needed - needs 1 long - again the mask will get passed as an argument
4. the XOR to an OR by using a movi - needs 1 longs - needs one for the instruction the new instruction can get passed as an argument
so we need 2 + 1 return = 3 longs to change one position back
The spin code can look after doing it 3 times and making sure the correct mask for the condition bits is used.
So we only need 6 longs in the cog. That almost leaves room for something else but someone else can do that.
But you have to do it twice: in wslice AND pixel...
There is no need for doing it "three times" There is a strict order of execution in the COG...
The three times is for the three different places. We need to change it in one place in the pixel and in two places in the wide pixel routines making a total of three. If we pass the cog address of the function as an argument from spin then we don't use any extra instructions in the assembler. I know its not as fast but we need the room.
Steven
So there is no NOP instruction
*Still flushing....*
However the "R" bit is part of the first 9 bits, so action can be avoided by NR!
Post Edited (deSilva) : 2/10/2008 11:51:57 AM GMT