@ or \ addressing - which to use?
Peter Jakacki
Posts: 10,193
I have been led to believe that the @ forces absolute addressing but in modifying code that used @ in the jmp adressing in hub rom it didn't affect anything but when I modified it in my copy in first 64k it responded. Investigating further at the actual machine code generated by PNut I found that the jump was relative $FD9x_xxxx where the lsb of 9 is the Relative addressing mode. However if I use the \ then it becomes $FD8x_xxxx plus also I can see the destination address is absolute. So what is going on? Is it supposed to be @ for relative and \ for absolute?
I have done other tests with and without etc but this is the main point in question. This is hubexec code btw.
Hubexec calling hubexec code where I have now changed it to \ to call Cluso's monitor from TAQOZ.
I have done other tests with and without etc but this is the main point in question. This is hubexec code btw.
Hubexec calling hubexec code where I have now changed it to \ to call Cluso's monitor from TAQOZ.
DEBUGGER setint1 #0 jmp #\_Start_Monitor ' \ forces absolute address '
Comments
NOTE: The #@ and #\ are reversed depending on whether the code is executing from hub or cog!!!
pnut has a bug
I hope this does not cause a ROM compile problem.
To force an absolute jump use "\" (always). Otherwise whether the jump is absolute or relative depends on whether it crosses between COG and HUB. If there's no crossing and no "\" then the jump will be relative, otherwise absolute.
If you really want to force an absolute jump to the hub address of an instruction (even for things that will be loaded into COG memory) use "jmp #\@label".
I think this is consistent with what Cluso saw. In the first example we're jumping from COG to HUB memory, so all the variants had to use an absolute address. In the second "jmp #_cog" is a COG to COG, so relative, but "jmp #@_cog" specifically asks for a HUB address, so it's treated as a COG/HUB crossing and comes out absolute (it'll switch to hubexec mode). In the third example "_hub" is in hub memory, so "jmp #_hub" and "jmp #@_hub" are treated the same; it's a HUB to HUB transfer so relative. Finally the label "_cog" is in COG memory so the jumps to it from HUB are absolute. However, "jmp #@_cog" comes out relative because, again, we're asking for the HUB address and so forcing it to be a HUB to HUB transfer.
So in that case the only error seems to be the second last example instruction.
Eric
I think it's complicated for a number of reasons:
(1) there is HUB memory from 0x0 to 0x3ff, and so there needs to be a way to access that 1K of RAM
(2) data access has to use different instructions depending on which memory is accessed: rdlong/wrlong for hub, rdlut/wrlut for LUT, and mov for COG
(2) is a particular pain for compilers and interpreters, because it means we can't have generic pointers that point anywhere If we were starting from scratch I'd recommend changing this, but it's *way* too late for that I think Besides, even for instructions things get pretty complicated, as we've seen from the discussions above.
The _cog and _hub labels are not really data, they are instructions located in cog and hub respectively.
And the results are opposite depending upon whether the jump/call is currently in cog or Hub.
IMHO this is plainly wrong and may result in our ROM containing incorrect jump/call addresses. We just don't know for sure although it's likely ok.
jmp #\@_cog 'from hub
Got it!
But we cannot always use absolute addresses for a few reasons.
Not all jump/call instructions have enough bits to fully address the entire memory map.
Hub data addresses between $00000-$00400 do exist and overlap cog and LUT space.
We may want the code to be relocatable.
We may want to call a routine that may reside in cog as well as Hub. Yes, I do that now with Chip's booter - I call his routines as hubexec even though he loads them into cog and LUT and runs them from there. His method is faster, but when I call them they may not exist in cog or LUT. My SD and Monitor code runs totally in hubexec mode.
TAQOZ runs in lower Hub and cog. It is compiled for ROM but is copied down to lower Hub.
So you see, these are real instances, not contrived examples.
Currently Chip, Peter and I are using JMP/CALL #@hub to mean an address in HUB ROM. This is compiling correctly (thankfully) for the case where the jump/call is executing from cog. This is how Chip passes control to SD, TAQOZ and the Monitor.
When this was sorted around a week ago, I converted one of my code blocks (IIRC it was SD) from # to #@. It's probably not going to matter either way, but it's not the right way.
We will need a proper resolution and a pnut fix.
Edit: I guess that isn't true. Phew! We just can't execute code from the first 0x400 bytes of hub memory. That seems fine.
An example would be:
PNut and p2asm both handle this the same. fastspin chokes on the #\@, I need to fix that (using #\(@x) does work).
I'm having trouble locating the discussion, but I believe this is correct. Chip said something along the lines of, "Relative jumps COG to HUB, HUB to COG are a bad idea" and discouraged them. Nobody talked about relocatable code that does this back then. Here we are with the ROM, and it's a valid case.
What was discussed was the fact that the instructions permit it, but as a general programming practice, the assembler wouldn't actually do that. Not making a statement on that, just recalling the relevant discussion we had at the time.
Questions:
Is that a general case we need to fix in Pnut? I'm asking, because Chip's reason was the high difficulty and potential for error present when doing this kind of thing.
(Since we are likely to publish this ROM code as part of the chip docs, we should fix this, or at least document how to make it explicit.)
At the time we had the discussion, we did not have the robust debug capability we do now. Does that debug cover doing this well enough?
I guess it depends on what you're talking about, but I think for jump purposes addresses $0-$3ff are treated as cog/lut memory and $400 up are treated as hub memory. That means you cannot do an absolute jump to a hub address below $400. It is (theoretically) possible to do relative jumps to such addresses, but in practice the assembler may give errors because it thinks you'll be crossing between the hub and cog domains, and relative branches are not supposed to do that.
There's also the complication that every label has two values, its "default" value (which may be in COG memory) and its hub value (which definitely is in hub memory). The hub value is accessed via " @ ". The documentation is a little unclear on this whole concept, I'm afraid, and it's easy to think that " @ " signals an absolute jump (it doesn't, only "\" signals an absolute jump.
I posted an example earlier in the thread, but another simple one: Here the default (cog) address of entry is 0 (set by org) and the hub address is $400. "@entry" gives the hub address. "entry" gives just the default address, which in this case is a cog address.
If you take away the "org 0" then both addresses will be the same, that is " @entry " and "entry" will both have the value $400.
It's to do with how to force the compiler to do what the programmer wants, and for this method to be consistent.
We have code in the Hub ROM area commencing at $FC000. This is the code executed when the final silicon P2 boots. It's in hubexec mode. It copies code from, for ease let's say from $FC000 into cog and from FC800 into lut, and then jumps to let's say cog $000. So the same code can be present in both cog and Hub. Similarly LUT and Hub but let's forget that.
So that code has a cog address and a hub address.
If I want my program to jump to that code, I need to tell the compiler which address to use, cog or Hub. Currently I have to know if my code (the code doing the jumping) is currently running in cog or hub, because the method of forcing the compiler to do the jump to cog or hub is reversed depending on whether my jumping code is running from cog or hub. That's a bug because the instruction format should be the same!! See my code results posted above. They are taken from the real pnut output!!
Now, the code that Chip executes in cog also resides in Hub. And when I need to call it, it's no longer available in cog. But it is still in Hub, and it is compatible with hubexec operation (not all code can run in hubexec because some instructions don't work in Hub). So I have to force the compiler to jump/call a routine using its hub address.
The alternative is for each of us to have identical routines in hub which is a waste (and we no longer have the space either).
Eric, sorry you are incorrect. See my top post where I show what pnut produces.
Again, it's not the compiler that has issues with Hub execution addresses below $400 (which I think is actually $400 << 2 = Hub $1000), but rather the P2 silicon PC (program counter) is 20 bits and addresses in the bottom 2KB are interpreted as cog and the next 2KB as lut. When in cog/lut I believe its the bottom 2bits that get discarded as cog and lut are only addressed as longs. Hub is addressed in bytes, and I believe can. execute from odd addresses. Certainly rdlong can fetch from a non-long aligned address.
Potatohead, the ROM of a few versions back has already been published for testing purposes. It may be included with the latest FPGA code - I got mine directly from Chip and it's in the zip file.
If code in hub jumps to a label with " @ " in front of it (and no "\") it will always use a relative jump, since it's hub to hub. If code in cog jumps to a label with " @ " in front of it (and no "\") then it will always use an absolute jump, since it's cog to hub.
So if you really want an absolute jump to a hub address use both "\" and " @ ", namely:
If I'm mistaken, could you explain what I have wrong? I do want to get this right for fastspin.
Whether this is the way the assembler should work is another question, of course. I'm just describing how (I think) it actually does work.
Sorry I wasn't aware until you said today that the #\@label was legitimate. It never crossed my mind.
So what I am saying is pnut is not consistent within the rules that we thought we were using.
With that further explanation, I will need to look again. That's not going to happen for another 18 hrs at least.
Perhaps in the meantime you might test these out with pnut for us?
What was interesting while Peter and I were discussing this problem, we both used our own tools (TAQOZ and the Monitor) to "patch" the ROM.
Not bad eh!!
For symbols that do not have a cog attribute it doesn't matter if the @ symbol is used or not. The result is always a hub address.
Here's the listing output from p2asm when assembling a short snippet of code. The first column shows the hub address, and the second column shows the cog address. Note that the code after the ORGH does not have a cog address. Jumps from cog to cog and hub to hub use relative addresses unless the \ character is present, which forces an absolute jump. Jumps between cog and hub always use an absolute address.
A nice feature of relative addressing is that it allows for position independent code. A snippet of hub code could execute equally starting at location $400 or $FFF0. For a while I supported a position independent code (PIC) mode in p2gcc. The jumps could be done from anywhere in memory. However, I did have to adjust the data addresses to match where the data is located in memory.
I must agree that the documentation is confusing. I was lucky that I already had " @ " in my mind as an operator that acts on labels (like "-") rather than an instruction modifier (like "#" or "\"). So my mental picture agreed with Chip's.
Below is a slightly modified version of your original post. As you can see the " #\@ " form always gives a jump to abs hub. I've checked and p2asm and PNut both produce the same result. fastspin kind of does as well, if you give it the -c option to just extract the DAT. Otherwise fastspin wants to compile a Spin method and optimizes everything away when it doesn't find one . Again, something I will need to fix. This has been very enlightening...
Thanks,
Eric
Keep in mind that "@address" always returns the hub address of the label, even if the label also represents a cog address. The implication of using "@address" in branches is that the assembler sees you branching to a hub address.
I might be missing something, but it seems that the assembler is working correctly. This needs more documentation, though.
It has taken a while to get to the bottom of this.
I am happy that what I am using in my code is working as desired, but it is more by luck than good management.
Now I can clean it up to ensure I use what I want the compiler to do. I will use the #\@label or #@label when I want to jump/call hubexec code. Currently I have no need to jump/call cog or lut code, but that will come later for sure.