Chip: "Absolute jumps can be forced by using \ before the address. "
Is this new? I don't remember this...
Is this only to within cog/lut?
It must be still limited to +/- 256, right?
It's been in the instructions.txt file, all along. For S-field immediate addresses, they are all relative (DJNZ, etc), and their range is -256..+255 instructions. In hub memory, they are left-shifted by two bits, since an instruction spans 4 byte addresses.
I'm afraid I have to agree with Mike here... we have a new feature that's useful for one application (the Spin interpreter) but which nobody, not even the designer, seems to completely understand! How much time in testing and fixing issues is it worth spending on this?
SKIP is cool, but so are lots of other things... there comes a point where we have to say "OK, this is too risky", not to mention "OK, this is done now". Honestly, is the performance of the Spin2 interpreter going to be a major selling point for P2? People that need to squeeze all the performance they can will be writing their code in PASM or in a compiled language anyway. And frankly, nobody will be buying the P2 for its high speed calculations. They'll be getting it for the smart pins, the large number of I/Os, and the number of cores. Those are its strengths. A chip that actually exists in silicon will always be a better solution than one that exists only in a constantly changing FPGA image .
Sorry to sound negative, but it seems to me that it's easy to lose sight of the forest for the trees.
Eric
Your rationale for someone choosing the Prop2 is probably 90% correct, but I still want to be able to deliver a really efficient version of Spin for it, with a very small runtime overhead. This EXECF instruction is going to collapse the code size of the interpreter. Who knows, between the cog registers and LUT, it might fit completely inside the cog. And it should be, within an order of magnitude, as fast as PASM, but with fractional user code size. I know code size doesn't matter much in the world, anymore, but a good foundation is always a strong starting point.
Why is the P2 interpreter so much bigger than the P1 interpreter that it can't fit in twice the space (COG+LUT)?
It does a few more things, but not many, like instruction pointers, for example.
.. suppose what might help CMM mode is an instruction that would automatically expand the compressed format that Eric used in CMM.
Isn't the EXECF form more generally useful, for table jumps, and you do not have to use the SKIP mask there ?
From a general language angle, I see SKIP as useful where you have many types (eg 8,16,32,64 fetches).
Some languages have trended to one type, to simplify the user-end, but that comes at the cost of speed, and embedded usefulness.
At the embedded end of the scale, there tend to be more types, and P2 surely targets mainly that end ?
You could use EXECF for table jumps, but it would only jump from $000..$3FF in cog/LUT memory. If the upper bits were 0's, it would be just a jump instruction.
To clarify SKIPF timing, every time 8 instructions in a row are skipped, one NOP executes.
The only difference between v17 and my own current version is that SKIPF becomes SKIP during hub execution. This is probably not anything anyone wants to play with now, but when there's greater occasion for another release, the updated SKIPF behavior will be in there.
Chip: "Absolute jumps can be forced by using \ before the address. "
Is this new? I don't remember this...
Is this only to within cog/lut?
It must be still limited to +/- 256, right?
from the instructions_v17.txt file (and earlier versions too) that comes with FPGA files.
For immediate-branch and LOC address operands, "#" is used before the
address. In cases where there is an option between absolute and relative
addressing, the assembler will choose absolute addressing when the branch
crosses between cog and hub domains, or relative addressing when the
branch stays in the same domain. Absolute addressing can be forced by
following "#" with "\".
I'm mostly lurking now, have been for the past year or more due to time constraints of full-time work and my consulting business.
That said, SKIP has made this very interesting again, it makes me want to make some time to get actively involved again.
I understand the desire of some to just get it done, and acknowledge that my current lack of available time makes me more forgiving of any delays this may bring.
I think we are very fortunate to have not only a ringside view to Chip's work on this project, but to also be able to be actively engaged and have input in the design. SPIN is an important part of the Propeller ecosystem and I understand Chip's desire to improve it's performance and features by making these changes. I also see SKIP being of benefit in many cases where fitting more functionality into a COG or even less space in HUB is important.
We also need to keep in mind that we are watching this in real-time, comments about the designer not fully understanding their design seem to me to be a bit harsh. We get to watch Chip work out ideas, and even have a hand in testing and improving them, that's cool.
Most, if not all of us, watching and participating don't have the time or resources to take on a project of this magnitude. I'm glad that Chip, Ken and the team at Parallax have been successful enough to take on this project and I appreciate being able to observe and take part in it.
C.W.
Making something that is fun and interesting to program, even at the lowest level, means improving the life of the people who use it. When you pick a technology to work with, it's like getting married, almost. If it has any lasting utility, you're going to become vested in it, so it should be worthwhile. I feel like much technology these days just gets uglier and more duplicitous, the more I use it, with me eventually realizing that I married a psycho - one that's like the wife of Schwarzenegger's character in Total Recall (she pretended to be his wife, but really worked for the evil Cohagen who ran the mining company).
For immediate-branch and LOC address operands, "#" is used before the
address. In cases where there is an option between absolute and relative
addressing, the assembler will choose absolute addressing when the branch
crosses between cog and hub domains, or relative addressing when the
branch stays in the same domain. Absolute addressing can be forced by
following "#" with "\".
I read that, but suddenly feel lost... There's a "JMP" and a "JMPREL" instruction.
I guess the compiler usually turns a JMP into a JMPREL for me in cogexec?
But, the plain JMP doesn't have an immediate option, just jumps to the address in the register specified by D, right?
So, using "JMP #\somewhere" doesn't make any sense to me right now...
Maybe it means it's going to insert an "ALTD somewhere" before the JMP?
Can I use this to JMP more than 256 instructions away within a cog?
For immediate-branch and LOC address operands, "#" is used before the
address. In cases where there is an option between absolute and relative
addressing, the assembler will choose absolute addressing when the branch
crosses between cog and hub domains, or relative addressing when the
branch stays in the same domain. Absolute addressing can be forced by
following "#" with "\".
I read that, but suddenly feel lost... There's a "JMP" and a "JMPREL" instruction.
I guess the compiler usually turns a JMP into a JMPREL for me in cogexec?
But, the plain JMP doesn't have an immediate option, just jumps to the address in the register specified by D, right?
So, using "JMP #\somewhere" doesn't make any sense to me right now...
If you look at the 20-bit immediate instructions, there's an 'R' bit in them. That R bit is 0 for absolute, where the 20-bit field is used verbatim, or 1 for relative, where the 20-bit field is ADDED to the PC. This done was to allow code which used R=1 jumps internally to be relocatable within hub memory.
I remember this discussion has occurred before - because the Prop1, only having 512 executable space, uses absolute branching addresses.
On the Prop2, for a loop that is larger than 256 longs, I'm guessing, since DJNZ is listed as relative branching only, that if a #\xxx is used then PNut will embed an AUGS in front of the DJNZ, correct?
I also presume the faster loop execution would be to preload a sacrificial register with the relative 32-bit branch address.
I remember this discussion has occurred before - because the Prop1, only having 512 executable space, uses absolute branching addresses.
On the Prop2, for a loop that is larger than 256 longs, I'm guessing, since DJNZ is listed as relative branching only, that if a #\xxx is used then PNut will embed an AUGS in front of the DJNZ, correct?
I also presume the faster loop execution would be to preload a sacrificial register with the relative 32-bit branch address.
If you use ##address in DJNZ, it will assemble an AUGS, but it will still be a relative branch, just with a 20-bit relative address, instead of a 9-bit one.
If you use ##address in DJNZ, it will assemble an AUGS, but it will still be a relative branch, just with a 20-bit relative address, instead of a 9-bit one.
Okay it has to be relative. Would #\address in a DJNZ generate the exact same machine code by prefixing with an AUGS?
You want to use relative where you can so you can move the code between cog/lug/hub
Using absolute would break that...
Recompiling usually sorts such things. But there is now a bunch of branching instructions that are exclusively relative only - Chip just drummed that detail into me. So, PNut just uses relative by default.
I read that, but suddenly feel lost... There's a "JMP" and a "JMPREL" instruction.
I guess the compiler usually turns a JMP into a JMPREL for me in cogexec?
But, the plain JMP doesn't have an immediate option, just jumps to the address in the register specified by D, right?
So, using "JMP #\somewhere" doesn't make any sense to me right now...
JMP does have a JMP ToAddressLabel option, which is used above, but the quirky PASM syntax is currently
JMP #ToAddressLabel
That is confusing, as what looks absolute (via the #) can assemble to relative/short...
So yes it can be confusing to read, which is why I've suggested before that PASM gets a clean-up pass to make it more consistent with industry practice & remove clutter chars...
In most MCUs you can code Assembler along these lines :
Note absence of any #Label, or #/Label crypto-semantics. The word clearly indicates what you get.
Label:
JMP Label ;Auto-Assembles smallest jump, usually that's short/relative, but uses larger when needed
; often simpler 1-2 pass assemblers will use larger opcodes for forward jumps, because they do not know 'how far'
AJMP Label ;forces Absolute jump
; and some also have
FJMP Label ;forces Far Jump (largest opcode)
; or
LJMP Label ;forces Far Jump (largest opcode)
; or
SJMP Label ;forces short Jump (smallest opcode)
I feel like much technology these days just gets uglier and more duplicitous, the more I use it, with me eventually realizing that I married a psycho - one that's like the wife of Schwarzenegger's character in Total Recall (she pretended to be his wife, but really worked for the evil Cohagen who ran the mining company).
Are you sure SKIP and its friends haven't turned P2 into one of these?
I feel like much technology these days just gets uglier and more duplicitous, the more I use it, with me eventually realizing that I married a psycho - one that's like the wife of Schwarzenegger's character in Total Recall (she pretended to be his wife, but really worked for the evil Cohagen who ran the mining company).
Are you sure SKIP and its friends haven't turned P2 into one of these?
I feel like much technology these days just gets uglier and more duplicitous, the more I use it, with me eventually realizing that I married a psycho - one that's like the wife of Schwarzenegger's character in Total Recall (she pretended to be his wife, but really worked for the evil Cohagen who ran the mining company).
Are you sure SKIP and its friends haven't turned P2 into one of these?
No, that's interrupts.
Well, interrupts may be new to P2 but they aren't new to processor design. This SKIP instruction is. I suppose everyone here will claim that gives P2 a big advantage. I hope that's true. It just seems ugly to me. P1 was so clean and P2 seems to be going far in the opposite direction.
Ok, I think I'm back to having a handle on JMP.
Few weeks ago, was thinking about DJNZ where there is no absolute option and had to put the far away (>256) address into a register to make it work...
But now, I think I see that I could have "SUB it,#1 wz" followed by an "if_nz JMP #\somewhere".
Either way wouldn't be relocatable to hub though, I think...
I see it as a systems type instruction. Drivers, really performance code.
It won't need to be in general use.
What happened to the claim that a big advantage to the Propeller is that it is possible to understand everything about it? I guess that excludes things like SKIP and interrupts when talking about P2. Those get buried in the opaque infrastructure just like the obscure hardware features of any other processor.
On the other hand, I was trying to make a graphic for the egg-beater the other day but gave up. It's as much a visual tangle as it is to imagine. It'll need an animation I suspect.
Comments
It's been in the instructions.txt file, all along. For S-field immediate addresses, they are all relative (DJNZ, etc), and their range is -256..+255 instructions. In hub memory, they are left-shifted by two bits, since an instruction spans 4 byte addresses.
It does a few more things, but not many, like instruction pointers, for example.
You could use EXECF for table jumps, but it would only jump from $000..$3FF in cog/LUT memory. If the upper bits were 0's, it would be just a jump instruction.
The only difference between v17 and my own current version is that SKIPF becomes SKIP during hub execution. This is probably not anything anyone wants to play with now, but when there's greater occasion for another release, the updated SKIPF behavior will be in there.
Does it mean jump to HUB instead of cog/lut?
from the instructions_v17.txt file (and earlier versions too) that comes with FPGA files.
Making something that is fun and interesting to program, even at the lowest level, means improving the life of the people who use it. When you pick a technology to work with, it's like getting married, almost. If it has any lasting utility, you're going to become vested in it, so it should be worthwhile. I feel like much technology these days just gets uglier and more duplicitous, the more I use it, with me eventually realizing that I married a psycho - one that's like the wife of Schwarzenegger's character in Total Recall (she pretended to be his wife, but really worked for the evil Cohagen who ran the mining company).
Teams are needed for huge things, but often the result isn't totally cohesive...
I read that, but suddenly feel lost... There's a "JMP" and a "JMPREL" instruction.
I guess the compiler usually turns a JMP into a JMPREL for me in cogexec?
But, the plain JMP doesn't have an immediate option, just jumps to the address in the register specified by D, right?
So, using "JMP #\somewhere" doesn't make any sense to me right now...
Maybe it means it's going to insert an "ALTD somewhere" before the JMP?
Can I use this to JMP more than 256 instructions away within a cog?
If you look at the 20-bit immediate instructions, there's an 'R' bit in them. That R bit is 0 for absolute, where the 20-bit field is used verbatim, or 1 for relative, where the 20-bit field is ADDED to the PC. This done was to allow code which used R=1 jumps internally to be relocatable within hub memory.
On the Prop2, for a loop that is larger than 256 longs, I'm guessing, since DJNZ is listed as relative branching only, that if a #\xxx is used then PNut will embed an AUGS in front of the DJNZ, correct?
I also presume the faster loop execution would be to preload a sacrificial register with the relative 32-bit branch address.
If you use ##address in DJNZ, it will assemble an AUGS, but it will still be a relative branch, just with a 20-bit relative address, instead of a 9-bit one.
There's also another immediate address only version of JMP down the bottom of the instructions.txt.
You want to use relative where you can so you can move the code between cog/lug/hub
Using absolute would break that...
JMPREL can be used as a table jump instruction
for example
And relocatable definitely makes sense now, where on P1 it didn't matter.
JMP #ToAddressLabel
That is confusing, as what looks absolute (via the #) can assemble to relative/short...
So yes it can be confusing to read, which is why I've suggested before that PASM gets a clean-up pass to make it more consistent with industry practice & remove clutter chars...
In most MCUs you can code Assembler along these lines :
Note absence of any #Label, or #/Label crypto-semantics. The word clearly indicates what you get.
P2 SPIN uses a 32bit jump/skip table for each of the 256 bytecodes. This resides in LUT and uses half of the LUT.
This is similar to what I did in the Faster Spin Interpreter in P1, except of course the table was in HUB.
So this is where the cog/lut space is being used in P2 Spin.
Few weeks ago, was thinking about DJNZ where there is no absolute option and had to put the far away (>256) address into a register to make it work...
But now, I think I see that I could have "SUB it,#1 wz" followed by an "if_nz JMP #\somewhere".
Either way wouldn't be relocatable to hub though, I think...
It won't need to be in general use.
On the other hand, I was trying to make a graphic for the egg-beater the other day but gave up. It's as much a visual tangle as it is to imagine. It'll need an animation I suspect.