It's perfectly reasonable to say that ORGH with a value won't work in mixed Spin/PASM code. The compiler could emit a warning or error in this case. Just plain "ORGH" to say "this code should be in HUB, but I don't care where" should work.
My main concern was avoiding the need for triple at, so if a single at gives the absolute hub address that's great. (I wish the forum code weren't so aggressive about messing with @, it makes it hard to be precise in this discussion!)
EDIT: Maybe the independent DAT section could contain global symbols that any object could directly address. That's a feature that would have been useful in Spin1.
I like this idea, but could it be possible to label these global DAT sections (e.g. "DAT label"), so that their symbols don't pollute the global namespace? There could be global CON sections as well, which should be similarly namespaceable.
Chip,
There are specific instances where you needed to know the absolute hub position of compiled code, hence the @ @ @ inclusion in bst and homespun. Sometimes this involved setting many fields with spin before using coginit, but these were not the only cases. And when it was required, there was no other way to calculate the address. There was a lot of discussion at the time and there was no other way to do it.
Chip,
There are specific instances where you needed to know the absolute hub position of compiled code, hence the @ @ @ inclusion in bst and homespun. Sometimes this involved setting many fields with spin before using coginit, but these were not the only cases. And when it was required, there was no other way to calculate the address. There was a lot of discussion at the time and there was no other way to do it.
It seems to me that now, with relative addressing for branches and LOC for relative-to-absolute address resolution, we only need the initial hub address to jump to. A PASM program can reference its code and data without any modification.
Sorry Chip. I cannot recall the precise circumstances as the code requiring this was a number of years ago. There was lots of discussions at the time. I was not the only one needing this and its why Brad and Michael added it to their compilers.
I am fairly sure that LOC will not solve this problem though.
Not everything we do on P1 or P2 fits the usual moulds
Searching for @ @ @ (minus the spaces) discussions is really hard, because the new forum software butchered all the old posts such that the triple @ is now just @ in the old posts.
See this example: https://forums.parallax.com/discussion/149759/operator
It's really hard to figure out the discussion, because all the instances of triple @ or double @ are now just a single @, and so it's very difficult to even parse the discussion.
Seriously, the forum software using the @ symbol to tag names really sucks for many reasons, but especially so because it butchered countless old posts with any discussion of the @, double @, and triple @ in them.
Note that the LOC is running in the COG, not HUB, so the LOC needs to use an absolute addressing form. Well, technically the compiler could cause it to get the address correct in relative mode, but it would still need to know the absolute address of "message" (because the running COG code is located at an absolute address in COG memory).
Yes, there are alternatives (like using the ptrb value passed in at COG startup time to calculate the correct address for message). But those are more complicated and beginners are likely to trip over them. It'd be really nice if the "obvious" code above worked.
The LOC instruction always fills the register with an absolute address. The relative part is only in the opcode encoding. It took a while for this detail to sink in for me.
A notable problem that confounded early efforts was all the assemblers incorrectly encoded the LOC opcode when relative encoding of addresses below $400.
Yes, the attached file contains too much non-relevant stuff. Here's a test I did.
dat
00000 000 org 0
00000 000 fe90002c loc pa, #cog1 'Relative: (address - PC - 1) << 2
00004 001 fe9003f8 loc pa, #hub1 'Relative: (address - PC - 1) << 2
00008 002 fe800430 loc pa, #hub2 'Absolute: address
0000c 003 fe80000c loc pa, #\cog1 'Absolute: address
00010 004 fe800100 loc pa, #\hub1 'Absolute: address
00014 005 fe800430 loc pa, #\hub2 'Absolute: address
00018 006 fe9000a4 loc pa, #@cog1 'Relative: (address - PC - 1) << 2
0001c 007 fe9003e0 loc pa, #@hub1 'Relative: (address - PC - 1) << 2
00020 008 fe800430 loc pa, #@hub2 'Absolute: address
00024 009 fe800030 loc pa, #\@cog1 'Absolute: address
00028 00a fe800100 loc pa, #\@hub1 'Absolute: address
0002c 00b fe800430 loc pa, #\@hub2 'Absolute: address
00030 00c 00000000 cog1 long 0
00100 orgh $100
00100 00000000 hub1 long 0
00400 orgh $400
00400 fe80000c loc pa, #cog1 'Absolute: address
00404 fe800100 loc pa, #hub1 'Absolute: address
00408 fe900024 loc pa, #hub2 'Relative: address - PC - 4
0040c fe80000c loc pa, #\cog1 'Absolute: address
00410 fe800100 loc pa, #\hub1 'Absolute: address
00414 fe800430 loc pa, #\hub2 'Absolute: address
00418 fe800030 loc pa, #@cog1 'Absolute: address
0041c fe800100 loc pa, #@hub1 'Absolute: address
00420 fe90000c loc pa, #@hub2 'Relative: address - PC - 4
00424 fe800030 loc pa, #\@cog1 'Absolute: address
00428 fe800100 loc pa, #\@hub1 'Absolute: address
0042c fe800430 loc pa, #\@hub2 'Absolute: address
00430 00000000 hub2 long 0
I modified p2asm to add the comments at the end of each LOC line. LOC is encoded the same way JMP and CALLx are encoded. It looks like it doing the right thing. Of course some of the encodings aren't that useful, but that's the way the instruction is defined. It seems like "\@" should always be used in practice.
Yes, the attached file contains too much non-relevant stuff. Here's a test I did.
dat
00000 000 org 0
00000 000 fe90002c loc pa, #cog1 'Relative: (address - PC - 1) << 2
00004 001 fe9003f8 loc pa, #hub1 'Relative: (address - PC - 1) << 2
It should not have the <<2.
Consider the instruction
loc pa, #2
After this executes, pa should have the value 2, regardless of whether the loc was executing from COG or HUB RAM. But if you multiply all the relative offsets by 4 in COG mode, that becomes impossible.
This is a case where all 3 assemblers went wrong, I think for the same reason -- we all treated LOC like JMP and friends. But the hardware does not treat the instructions the same.
Here's a program you can use to test this:
DAT
org 0
loc pa, #2
add pa, #56 ' offset from pin 56
loop
drvnot pa
waitx ##10000000
jmp #loop
This should blink pin 58. When compiled with PNut v32i, p2asm 0.010, and fastspin 3.9.24 it blinks pin 61 instead. In fastspin 3.9.25-beta, with the shift removed, it's blinking pin 58 as expected.
The contents in PA register doesn't work out for the first two cases. The first one I think is due to difference from JMP/CALL ie: In cogram, unlike JMP/CALL, LOC needs encoded as longword scaled addressing not byte scaled.
The second one, the encoding has never made sense. Needless to say PA content is garbage as a result. This one more likely to be used in practice.
OK, so the only change would be to remove the "<< 2" that used for the cog mode, correct. Has Chip looked at this, and does he agree with that?
It seems like the relative mode is fairly useless for the LOC instruction. Should we just ignore the relative mode, and only encode absolute addresses?
I understand about half of the discussion. So, well done: everyone.
First, getting rid of the res assignments did solve my problem … So, ORGH is dead to me:)
When I looked back at my legacy code it seems that I added "x long 1" type statements after the res assignments... which breaks the rules but didn't stop me from what I was doing:)
I am a pretty good example of the average user, I don't want to know everything. Half the time, it changes anyway.
I just want to know what I need to know to do what I want to do. I can look at the patterns, follow them and do not really care why they exist.
@Chip: If you like it. Leave it alone. Let the teachers deal with it.
OK, so the only change would be to remove the "<< 2" that used for the cog mode, correct. Has Chip looked at this, and does he agree with that?
It seems like the relative mode is fairly useless for the LOC instruction. Should we just ignore the relative mode, and only encode absolute addresses?
OK, so the only change would be to remove the "<< 2" that used for the cog mode, correct. Has Chip looked at this, and does he agree with that?
It seems like the relative mode is fairly useless for the LOC instruction. Should we just ignore the relative mode, and only encode absolute addresses?
The relative mode is the most valuable because it enables relocatable hub code to always get addresses of its data structures. LOC in absolute mode is just a way to load a 20-bit constant (address) into PA/PB/PTRA/PTRB.
When I looked back at my legacy code it seems that I added "x long 1" type statements after the res assignments... which breaks the rules but didn't stop me from what I was doing:)
I am a pretty good example of the average user, I don't want to know everything. Half the time, it changes anyway.
I think that confusion will be avoided once "objects" are in use. Then the RES definitions will always be placed at the end of each object like they are on the Prop1.
The relative mode is the most valuable because it enables relocatable hub code to always get addresses of its data structures. LOC in absolute mode is just a way to load a 20-bit constant (address) into PA/PB/PTRA/PTRB.
But the relative mode is relative to the PC where the LOC instruction is executed. In order to use the relative address you would need to know the value of the PC at that time. I don't see how that is useful. Now if it was relative to a base address then it might be useful.
Ha! #hub1 isn't supposed to be relative at all. It's crossing domains so should have been encoded as an absolute. That's why that one is so busted.
The rules for hub1 demonstrate where things are broken. The value of the symbol hub1 is it's hub address since it is defined under ORGH. However, it's value is below $400, which is why relative addressing is used when assembling an instruction defined under ORG. I'm not sure how to fix this.
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.
Comments
My main concern was avoiding the need for triple at, so if a single at gives the absolute hub address that's great. (I wish the forum code weren't so aggressive about messing with @, it makes it hard to be precise in this discussion!)
I like this idea, but could it be possible to label these global DAT sections (e.g. "DAT label"), so that their symbols don't pollute the global namespace? There could be global CON sections as well, which should be similarly namespaceable.
There are specific instances where you needed to know the absolute hub position of compiled code, hence the @ @ @ inclusion in bst and homespun. Sometimes this involved setting many fields with spin before using coginit, but these were not the only cases. And when it was required, there was no other way to calculate the address. There was a lot of discussion at the time and there was no other way to do it.
It seems to me that now, with relative addressing for branches and LOC for relative-to-absolute address resolution, we only need the initial hub address to jump to. A PASM program can reference its code and data without any modification.
What, for example, is needed?
I am fairly sure that LOC will not solve this problem though.
Not everything we do on P1 or P2 fits the usual moulds
See this example: https://forums.parallax.com/discussion/149759/operator
It's really hard to figure out the discussion, because all the instances of triple @ or double @ are now just a single @, and so it's very difficult to even parse the discussion.
Seriously, the forum software using the @ symbol to tag names really sucks for many reasons, but especially so because it butchered countless old posts with any discussion of the @, double @, and triple @ in them.
Note that the LOC is running in the COG, not HUB, so the LOC needs to use an absolute addressing form. Well, technically the compiler could cause it to get the address correct in relative mode, but it would still need to know the absolute address of "message" (because the running COG code is located at an absolute address in COG memory).
Yes, there are alternatives (like using the ptrb value passed in at COG startup time to calculate the correct address for message). But those are more complicated and beginners are likely to trip over them. It'd be really nice if the "obvious" code above worked.
I think using labels will work, right?
I think just trying to force the data to a certain spot won't work.
Something like this won't work if you expect it to be at $1000:
A notable problem that confounded early efforts was all the assemblers incorrectly encoded the LOC opcode when relative encoding of addresses below $400.
Fastspin is now fixed - https://forums.parallax.com/discussion/comment/1457051/#Comment_1457051
Here's the updated source code snippet - https://forums.parallax.com/discussion/comment/1468883/#Comment_1468883
Presumably the other assemblers will be fixed soon.
Consider the instruction After this executes, pa should have the value 2, regardless of whether the loc was executing from COG or HUB RAM. But if you multiply all the relative offsets by 4 in COG mode, that becomes impossible.
This is a case where all 3 assemblers went wrong, I think for the same reason -- we all treated LOC like JMP and friends. But the hardware does not treat the instructions the same.
Here's a program you can use to test this:
This should blink pin 58. When compiled with PNut v32i, p2asm 0.010, and fastspin 3.9.24 it blinks pin 61 instead. In fastspin 3.9.25-beta, with the shift removed, it's blinking pin 58 as expected.
The second one, the encoding has never made sense. Needless to say PA content is garbage as a result. This one more likely to be used in practice.
It seems like the relative mode is fairly useless for the LOC instruction. Should we just ignore the relative mode, and only encode absolute addresses?
First, getting rid of the res assignments did solve my problem … So, ORGH is dead to me:)
When I looked back at my legacy code it seems that I added "x long 1" type statements after the res assignments... which breaks the rules but didn't stop me from what I was doing:)
I am a pretty good example of the average user, I don't want to know everything. Half the time, it changes anyway.
I just want to know what I need to know to do what I want to do. I can look at the patterns, follow them and do not really care why they exist.
@Chip: If you like it. Leave it alone. Let the teachers deal with it.
The relative mode is the most valuable because it enables relocatable hub code to always get addresses of its data structures. LOC in absolute mode is just a way to load a 20-bit constant (address) into PA/PB/PTRA/PTRB.
But the relative mode is relative to the PC where the LOC instruction is executed. In order to use the relative address you would need to know the value of the PC at that time. I don't see how that is useful. Now if it was relative to a base address then it might be useful.
The rules for hub1 demonstrate where things are broken. The value of the symbol hub1 is it's hub address since it is defined under ORGH. However, it's value is below $400, which is why relative addressing is used when assembling an instruction defined under ORG. I'm not sure how to fix this.