LOC is really only useful in hub-exec code, unless you're just exploiting it to load 20-bit constants. That it assembles under ORG is there for the possibility, but it's not practical. LOC was intended only as a mechanism to allow hub code to get addresses of its internal data structures.
Dave, the PC is known at runtime, so LOC can give you an absolute address when your code only knows the relative offset from the PC. By writing hub-exec code which uses relative branches and relative LOC's, you can have an entire PASM application which can sit at any byte offset in hub memory in which it fits, and it will execute without any external pointers being required. You only need to JMP to the start of the code.
Emphasising the PA register content is always resolved to absolute:
Now that I understand how LOC works I can see that it would be useful for position-independent-code. Unfortunately, it can only write to PA, PB, PTRA or PTRB. It would be nice if it could write to a larger range of cog memory, but that would have gobbled up a lot of instruction space. Maybe in the P3 there could be a LOC instruction with a smaller hub address range, and a larger range of destinations.
p2gcc generates code that loads addresses into one of the 15 general purpose registers, such as "mov r3, ##variable". A C source file is compiled into an object file starting at address $400. It must then be relocated to another address by the linker. The linker doesn't have to worry about the calls and jumps since they use relative address, but it does have to adjust variable addresses. With LOC the variable addresses could be relative also.
I would have to move the address from the LOC destination register to a general purpose register, so the generated code would look like this:
loc pb, #variable
mov r3, pb
However, this would take the same number of instructions as I currently use with the with the long source value.
Chip, are you going to change PNut to match the changes in fastspin for the LOC instruction?
You can forge ahead on the two buggy cases as they were unusable for everyone.
The one case that could be improved is hubexec referencing hubram data below $400. Currently, this is getting encoded as absolute when it could be encoded as PC-relative.
Chip, are you going to change PNut to match the changes in fastspin for the LOC instruction?
You can forge ahead on the two buggy cases as they were unusable for everyone.
The one case that could be improved is hubexec referencing hubram data below $400. Currently, this is getting encoded as absolute when it could be encoded as PC-relative.
Looking at Fastspin, even though it resolves fine, there is more PC-relative cases than expected. And I think this carries over to branching instructions too.
Amusingly, all cases could default to PC-relative and you wouldn't know they were unless examining the machine code.
Although I think LOC and all branch long-immediates could all be encoded to PC-relative in all #label and #@label cases. Absolute encoding of those instructions doesn't seem to have a specific purpose. Ah, absolute does have a purpose when an actual piece of PIC wants a hard coded specific address. Won't be common I don't think.
Although I think LOC and all branch long-immediates could all be encoded to PC-relative in all #label and #@label cases.
LOC probably could, in theory, be encoded relative in all cases. But branches are handled differently from LOC and if I recall correctly doing a relative branch that crosses HUB/COG/LUT domains is forbidden by the hardware. (There's internal state about how PCs are handled in relative branches, and I wouldn't want to mess with that.)
There are times when LOC should be absolute and not relative. Examples are using hub tables, and we will probably have some fixed areas for mailboxes.
I would rather always declare absolute or relative. The programmer should have the right to use what they require.
Although I think LOC and all branch long-immediates could all be encoded to PC-relative in all #label and #@label cases.
LOC probably could, in theory, be encoded relative in all cases. But branches are handled differently from LOC and if I recall correctly doing a relative branch that crosses HUB/COG/LUT domains is forbidden by the hardware. (There's internal state about how PCs are handled in relative branches, and I wouldn't want to mess with that.)
Challenge accepted and met! I replaced
jmp #loctesthub
at the end of my cogram code, cogram address $17, with
long $fd900fa0
This successfully jumps to hub address $400 ($1000 at byte scale) and runs the second part of the LOC test code placed there. Calculated as offset = $400 * 4 - ($17 + 1) * 4
It has some peculiar effect on the effective memory map. Still have to get my head around the implication ...
Comments
Emphasising the PA register content is always resolved to absolute:
Chip, are you going to change PNut to match the changes in fastspin for the LOC instruction?
Load Effective Address.
For PC relative, you specified that address mode.
LEA would deliver the effective address 9f any combination of addressing modes into a register.
LEA PC, X
Address = current PC at time of execute, plus X.
Relocatable, reentrant code was straightforward to write. Drop it anywhere, run it, move it, everything just worked.
P2 benefits from this thinking.
p2gcc generates code that loads addresses into one of the 15 general purpose registers, such as "mov r3, ##variable". A C source file is compiled into an object file starting at address $400. It must then be relocated to another address by the linker. The linker doesn't have to worry about the calls and jumps since they use relative address, but it does have to adjust variable addresses. With LOC the variable addresses could be relative also.
I would have to move the address from the LOC destination register to a general purpose register, so the generated code would look like this: However, this would take the same number of instructions as I currently use with the with the long source value.
You can forge ahead on the two buggy cases as they were unusable for everyone.
The one case that could be improved is hubexec referencing hubram data below $400. Currently, this is getting encoded as absolute when it could be encoded as PC-relative.
Yes, I agree.
Amusingly, all cases could default to PC-relative and you wouldn't know they were unless examining the machine code.
EDIT: Updated with easier to read memory data.
Yep, that matches fastspin result.
So that means p2asm and fastspin are now considered 'correct' and pnut is still to be fixed ?
Although I think LOC and all branch long-immediates could all be encoded to PC-relative in all #label and #@label cases. Absolute encoding of those instructions doesn't seem to have a specific purpose. Ah, absolute does have a purpose when an actual piece of PIC wants a hard coded specific address. Won't be common I don't think.
I would rather always declare absolute or relative. The programmer should have the right to use what they require.
It has some peculiar effect on the effective memory map. Still have to get my head around the implication ...
EDIT: New version
EDIT: And to relative jump to cogexec from hubexec Cog address 9 is start of my LOC testing code.