Chip, With PNutVr I'm getting an error with a call to AKPIN (Expression terms must return a single result). Your documentation of this call doesn't seem to imply that there is more than one result.
AKPIN returns nothing, right? It sounds like you are using it as a term which is expected to return a value. AKPIN needs to be used in isolation as an instruction.
In spin1 we only had to define...
_XINFREQ = 5_000_000 + 0000
_CLKMODE = XTAL1 + PLL16X
once, where clkfreq was calculated, and all lower levels inherited this value. eg in FullDuplexSerial we could calculate the baud for the inherited clkfreq thus...
PUB start(rxpin, txpin, mode, baudrate) : okay
bit_ticks := clkfreq / baudrate
In spin1 we only had to define...
_XINFREQ = 5_000_000 + 0000
_CLKMODE = XTAL1 + PLL16X
once, where clkfreq was calculated, and all lower levels inherited this value. eg in FullDuplexSerial we could calculate the baud for the inherited clkfreq thus...
PUB start(rxpin, txpin, mode, baudrate) : okay
bit_ticks := clkfreq / baudrate
Do we have similar capability in spin2?
You can always access the runtime variables at any level, like you are talking about. However, you can't access the hard-coded values from the top level file that were compiled.
By tricking spin2 to setup the serial ROM and call the monitor, I can finally locate where spin2 (pnut v34R) places my code in hub, and get to look at what it compiled.
My serial/monitor/debugger (and SD) p2asm code originally compiled for the P2 ROM (pnut v32i) used this format...
DAT
fca78 orgh
.....
fca88 fdbfffec _Start_Monitor call #@_reset_booter ' reset the booters interrupts and autobaud
Now when this compiles with spin2 and pnut v34R we get this (derived from the monitor hex dump)
DAT
fca78 orgh
01000 byte $3D[$A78]
.....
01a88 fdbffbf4 _Start_Monitor call #@_reset_booter ' reset the booters interrupts and autobaud
Note: There is no realistic/useful listing in pnut. In fact, the code doesn't even reside where the listing (dump) says it is
Now we can finally examine the code to see what is wrong. So here is the snippet just to examine the problem...
01a88 fdbffbf4 _Start_Monitor call #@_reset_booter ' reset the booters interrupts and autobaud
fca78 fd640025 _reset_booter setint1 #0 ' disable int1
Here we can see that both pieces of code
_Start_Monitor call #@_reset_booter
The _reset_booter label is located 5 longs backwards. The original pnut calculated this correctly as -20 bytes $FFFEC but pnut v34R calculates this to be $FFBF4. So Pnut is incorrectly calculating the relative branch offset.
BTW I've wasted many days on this since I was flying blind and wondering why things didn't work!
I accept that there can always be bugs. What gets me so upset is the fact that all of the test basics that we have in the ROM is useless, it's a nightmare toconvert P1PASM, and Spin2 is so different it shouldn't even be called spin2. Everything has been thrown out the window with total disregard to what came before.
By tricking spin2 to setup the serial ROM and call the monitor, I can finally locate where spin2 (pnut v34R) places my code in hub, and get to look at what it compiled.
My serial/monitor/debugger (and SD) p2asm code originally compiled for the P2 ROM (pnut v32i) used this format...
DAT
fca78 orgh
.....
fca88 fdbfffec _Start_Monitor call #@_reset_booter ' reset the booters interrupts and autobaud
Now when this compiles with spin2 and pnut v34R we get this (derived from the monitor hex dump)
DAT
fca78 orgh
01000 byte $3D[$A78]
.....
01a88 fdbffbf4 _Start_Monitor call #@_reset_booter ' reset the booters interrupts and autobaud
Note: There is no realistic/useful listing in pnut. In fact, the code doesn't even reside where the listing (dump) says it is
Now we can finally examine the code to see what is wrong. So here is the snippet just to examine the problem...
01a88 fdbffbf4 _Start_Monitor call #@_reset_booter ' reset the booters interrupts and autobaud
fca78 fd640025 _reset_booter setint1 #0 ' disable int1
Here we can see that both pieces of code
_Start_Monitor call #@_reset_booter
The _reset_booter label is located 5 longs backwards. The original pnut calculated this correctly as -20 bytes $FFFEC but pnut v34R calculates this to be $FFBF4. So Pnut is incorrectly calculating the relative branch offset.
BTW I've wasted many days on this since I was flying blind and wondering why things didn't work!
I accept that there can always be bugs. What gets me so upset is the fact that all of the test basics that we have in the ROM is useless, it's a nightmare toconvert P1PASM, and Spin2 is so different it shouldn't even be called spin2. Everything has been thrown out the window with total disregard to what came before.
Cluso, in your second CALL, try getting rid of the @, since it is returning the offset within the object, not the ORGH address.
Having said this, the documents are going to need to spell out where and how to use the “@“, “/“ and nothing. There was discussion a long time ago. We need to be able to specifically dictate in pasm precisely whether relative or absolute addressing is used. Getting something that has some weird base is not acceptable IMHO.
Having said this, the documents are going to need to spell out where and how to use the “@“, “/“ and nothing. There was discussion a long time ago. We need to be able to specifically dictate in pasm precisely whether relative or absolute addressing is used. Getting something that has some weird base is not acceptable IMHO.
I feel like anything I say might set you off, but you're being very pushy towards a particular programming style.
When Chip has offered to work thru some examples regarding how to convert code, your tone has gotten angrier. Please be willing to accept that what may have taken one instruction on P1 might take 2 or 3 on P2 in certain instances.
... There was discussion a long time ago. We need to be able to specifically dictate in pasm precisely whether relative or absolute addressing is used.
That was only true while the assembler LOC bug persisted. All assemblers are fixed now, Pnut was the last to be sorted.
"\" is the way you specify absolute rather than relative. If the operand starts with "\" then the absolute version of the instruction is always generated. Otherwise the relative version is generated, if that's possible.
"@" has nothing to do with absolute/relative; it's the sign that the HUB address of a label is desired. If the label is already after an ORGH then putting "@" does nothing, really. (And if you're mixing Spin and PASM then "@" in PASM may only give you an offset rather than the final hub address, depending on the compiler you use.)
"\" is the way you specify absolute rather than relative. If the operand starts with "\" then the absolute version of the instruction is always generated. Otherwise the relative version is generated, if that's possible.
"@" has nothing to do with absolute/relative; it's the sign that the HUB address of a label is desired. If the label is already after an ORGH then putting "@" does nothing, really. (And if you're mixing Spin and PASM then "@" in PASM may only give you an offset rather than the final hub address, depending on the compiler you use.)
Thanks Eric.
Why would you want a call/jmp to use an offset rather than either a relative or absolute address? It would never be a correct address. I cannot even fathom why we have this third mode???
We do need a table of some sorts, which includes the various compilers. Getting the wrong result without realising it doesn't help - it is a trap for everyone
I specifically put the @ in the call and jmp/djnz/etc in my ROM code because the early pnut gave wrong results without it. Now pnut gives wrong results with it if it's mixed with spin2. I don't know about pnut with pure pasm.
I have been having problems testing out my new SD pasm code (was pure pasm) and this could be at least one of the problems - I've been using both fastspin and to a lesser extent pnut.
Well, technically, even with pure pasm2, @ only works as hubRAM addresses because the binary is loaded at address zero. If it gets loaded anywhere else then you're in the same boat as spin2/pasm2 mixed.
@Cluso99: I think you got misled somehow by an early, buggy pnut, or something like that. But the meaning of "@" and "\" is fairly easy to remember. I'll cover the pure PASM situation first because all the compilers agree on it:
(1) "\" modifies the instruction. That is, "jmp #\anything" causes the jmp to be an absolute jump. "anything" really can be anything there, it doesn't have to be a label. "jmp #\$400" generates an absolute jump to $400, whereas "jmp #$400" generates a relative jump if that's at all possible. If the jmp instruction is in COG or LUT then a relative jump to a HUB address isn't possible. Rather than failing the assembler will turn it into an absolute jump.
"\" may only be used in instructions that have a relative and absolute form, i.e. jumps and LOC.
(2) "@" modifies a label, and may only be put in front of one. It asks for the hub value of the label, i.e. where the code after that label was initially loaded into HUB memory. For labels defined after an ORGH but before any ORG, "label" and "@label" are the same.
"@" may be used with any instruction, because again, it does not modify the instruction. It only affects the value used in the instruction. (OK, technically, changing the value could in some instances change the instruction, but that's a secondary effect and is not what "@" is for.) So "mov x, #@label" is legal, as long as the hub address of "label" fits into 9 bits.
To illustrate: suppose we have
orgh $400
org 0
cogval
nop
Then the label "cogval" has two values: its ordinary cog value 0, and its hub address $400 (where it initially is placed at load time). In all cases, the following equivalences hold (for pure PASM code, mixed PASM and Spin will be discussed below):
jmp #cogval ' is exactly equivalent to jmp #0
jmp #@cogval ' is exactly equivalent to jmp #$400
jmp #\cogval ' is exactly equivalent to jmp #\0
jmp #\@cogval ' is exactly equivalent to jmp #\$400
The jmp instructions with "\" will always be compiled as absolute jumps, so there's no ambiguity with any of them.
The jmp instructions without "\" will be compiled as relative jumps if that's possible, i.e. if the jump target is in the same memory as the instruction. Whether or not there's a "@" sometimes affects which address the jmp is to, so in that sense it might affect whether it's relative or not, but that's a side effect. The same branches would be generated if you used plain numbers like "$400".
If you're mixing PASM with Spin2 in Chip's compiler then I gather that there's a wrinkle, namely that the hub address is not known at compile time. Thus "@cogval" does not produce a sensible result. Basically you should never use it in PASM code that's mixed with Spin, unless you then go on to adjust it to the proper "final" address. This is not anything new, Spin1 worked the same way. That's why "@@@" had to be invented by some Spin1 compilers.
Ray: Another way to think of it is that "@" means basically the same thing in Spin2/Pasm2 as it did in Spin1/Pasm1, and comes with the same limitations. Presumably you came up with workarounds for these limitations in your Spin1 code. The same workarounds will probably work for Spin2.
results correctly in a negative offset of 5 longs = 20 bytes as _reset_booter is a label on an instruction at hub $fca78 which is 4+1 instructions prior.
v34R compiles DAT orgh code into a binary beginning at $00008 (from the binary listing in v34r). The loader loads this code into hub $01000 (at least in my example code above).
So the instruction gets encoded as shown below (determined from a dump of hub code)
results in a bogus negative offset. Chip says this is an address relative to the object. No idea what use this would be as it certainly will not result in a correct relative address!
So now we have this scenario...
"@" must be used when referring to a label of an address in hub, BUT must not be used if the label is the address (hub or otherwise) of the target in a CALL/JMP/DJNZ/etc, at least when used with spin2.
As I pointed out in the last paragraph of my post, things change when Spin enters the mix. In that case @ becomes useless in some compilers, just as it is useless in pasm in Spin1. It's frustrating, but in that case you have to pass the address as a parameter from Spin to pasm. Or, if everything is hubexec you may be able to use LOC as Andy suggested. But in this scenario the LOC instruction must execute from hub memory.
"@" must be used when referring to a label of an address in hub, BUT must not be used if the label is the address (hub or otherwise) of the target in a CALL/JMP/DJNZ/etc, at least when used with spin2.
BTW it's not true that "@ must be used when referring to a hub address". That's only the case for labels with two addresses, i.e. labels in an ORG section where the ordinary address is in cog memory. For labels after ORGH the @ is optional and does nothing. Not that that helps you. Chip's Spin2 compiler is like his Spin1 compiler, the pasm code has no way to access the hub addresses of labels at compile time. It has to be done at run time.
Fastspin, like bstc and homespun, does have a way to do this.
Hi Chip, could you please make PNut's -c mode show compiler errors on the console instead of just failing silently? I'm using an external editor on Linux and trying to use PNut through Wine, and command-line mode isn't really useful if it doesn't ever show error messages. I want to be able to use both PNut and Fastspin; I'm currently only using Fastspin.
Also, if it's easy, could you make PNut able to handle Unix line endings (i.e. just LF ($0a) without CR) in addition to Windows' CRLF line endings? Right now, PNut just ignores the LFs - it thinks the whole file is one long line. I don't mind if the display is wrong - I only need it to work in command-line mode. This isn't as important as having -c show error messages, since I can have my editor use the Windows line endings.
_HubTxStrVer mov lmm_p, ##_str_vers ' send version string, $00 terminated
_HubTxStrVer mov lmm_p, ##@_str_vers ' send version string, $00 terminated
How do we solve this in spin2 for the pasm code ???
I think you need to use LOC so the compiler can calculate the address relative:
_HubTxStrVer loc lmm_p, #_str_vers ' send version string, $00 terminated
But I have not tried it, just my guess.
Andy
LOC can only be used with PA/PB/PTRA/PTRB registers.
Okay, so he could do it with two instructions:
_HubTxStrVer loc pa , #_str_vers ' send version string, $00 terminated
mov lmm_p, pa
These are two longs, just like the version with mov ..,##
But better would be to modify the string output routine to use ptra or ptrb.
You have to remember that the concept for the routines in ROM (and now being replaced in the exact ROM position) was to not use any resources if possible so as to allow the calling program free rain over the resources. Hence PA/PB/PTRA/PTRB etc were specifically not used. Only 16 cog registers were used which were $1E0-$1EF which were the top free 16 registers. Then spin grabbed them, hence the ROM code needing to be replaced.
And I repeat again, this code compiles as pasm in both pnut (pasm only) and fastspin but it doesn't compile correctly in pnut if spin2 is used!
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 "\".
Your NOT crossing a domain so your call's will always be treated as relative.
Comments
AKPIN returns nothing, right? It sounds like you are using it as a term which is expected to return a value. AKPIN needs to be used in isolation as an instruction.
_XINFREQ = 5_000_000 + 0000
_CLKMODE = XTAL1 + PLL16X
once, where clkfreq was calculated, and all lower levels inherited this value. eg in FullDuplexSerial we could calculate the baud for the inherited clkfreq thus...
PUB start(rxpin, txpin, mode, baudrate) : okay
bit_ticks := clkfreq / baudrate
Do we have similar capability in spin2?
You can always access the runtime variables at any level, like you are talking about. However, you can't access the hard-coded values from the top level file that were compiled.
My serial/monitor/debugger (and SD) p2asm code originally compiled for the P2 ROM (pnut v32i) used this format...
Now when this compiles with spin2 and pnut v34R we get this (derived from the monitor hex dump) Note: There is no realistic/useful listing in pnut. In fact, the code doesn't even reside where the listing (dump) says it is
Now we can finally examine the code to see what is wrong. So here is the snippet just to examine the problem...
So the ROM code at does a call to a preceeding Here we can see that both pieces of code
_Start_Monitor call #@_reset_booter
The _reset_booter label is located 5 longs backwards. The original pnut calculated this correctly as -20 bytes $FFFEC but pnut v34R calculates this to be $FFBF4. So Pnut is incorrectly calculating the relative branch offset.
BTW I've wasted many days on this since I was flying blind and wondering why things didn't work!
I accept that there can always be bugs. What gets me so upset is the fact that all of the test basics that we have in the ROM is useless, it's a nightmare toconvert P1PASM, and Spin2 is so different it shouldn't even be called spin2. Everything has been thrown out the window with total disregard to what came before.
Cluso, in your second CALL, try getting rid of the @, since it is returning the offset within the object, not the ORGH address.
Having said this, the documents are going to need to spell out where and how to use the “@“, “/“ and nothing. There was discussion a long time ago. We need to be able to specifically dictate in pasm precisely whether relative or absolute addressing is used. Getting something that has some weird base is not acceptable IMHO.
I feel like anything I say might set you off, but you're being very pushy towards a particular programming style.
When Chip has offered to work thru some examples regarding how to convert code, your tone has gotten angrier. Please be willing to accept that what may have taken one instruction on P1 might take 2 or 3 on P2 in certain instances.
"@" has nothing to do with absolute/relative; it's the sign that the HUB address of a label is desired. If the label is already after an ORGH then putting "@" does nothing, really. (And if you're mixing Spin and PASM then "@" in PASM may only give you an offset rather than the final hub address, depending on the compiler you use.)
Thanks Eric.
Why would you want a call/jmp to use an offset rather than either a relative or absolute address? It would never be a correct address. I cannot even fathom why we have this third mode???
We do need a table of some sorts, which includes the various compilers. Getting the wrong result without realising it doesn't help - it is a trap for everyone
I specifically put the @ in the call and jmp/djnz/etc in my ROM code because the early pnut gave wrong results without it. Now pnut gives wrong results with it if it's mixed with spin2. I don't know about pnut with pure pasm.
I have been having problems testing out my new SD pasm code (was pure pasm) and this could be at least one of the problems - I've been using both fastspin and to a lesser extent pnut.
(1) "\" modifies the instruction. That is, "jmp #\anything" causes the jmp to be an absolute jump. "anything" really can be anything there, it doesn't have to be a label. "jmp #\$400" generates an absolute jump to $400, whereas "jmp #$400" generates a relative jump if that's at all possible. If the jmp instruction is in COG or LUT then a relative jump to a HUB address isn't possible. Rather than failing the assembler will turn it into an absolute jump.
"\" may only be used in instructions that have a relative and absolute form, i.e. jumps and LOC.
(2) "@" modifies a label, and may only be put in front of one. It asks for the hub value of the label, i.e. where the code after that label was initially loaded into HUB memory. For labels defined after an ORGH but before any ORG, "label" and "@label" are the same.
"@" may be used with any instruction, because again, it does not modify the instruction. It only affects the value used in the instruction. (OK, technically, changing the value could in some instances change the instruction, but that's a secondary effect and is not what "@" is for.) So "mov x, #@label" is legal, as long as the hub address of "label" fits into 9 bits.
To illustrate: suppose we have
Then the label "cogval" has two values: its ordinary cog value 0, and its hub address $400 (where it initially is placed at load time). In all cases, the following equivalences hold (for pure PASM code, mixed PASM and Spin will be discussed below):
The jmp instructions with "\" will always be compiled as absolute jumps, so there's no ambiguity with any of them.
The jmp instructions without "\" will be compiled as relative jumps if that's possible, i.e. if the jump target is in the same memory as the instruction. Whether or not there's a "@" sometimes affects which address the jmp is to, so in that sense it might affect whether it's relative or not, but that's a side effect. The same branches would be generated if you used plain numbers like "$400".
If you're mixing PASM with Spin2 in Chip's compiler then I gather that there's a wrinkle, namely that the hub address is not known at compile time. Thus "@cogval" does not produce a sensible result. Basically you should never use it in PASM code that's mixed with Spin, unless you then go on to adjust it to the proper "final" address. This is not anything new, Spin1 worked the same way. That's why "@@@" had to be invented by some Spin1 compilers.
I'll digest it again a little later and maybe make a table.
Meanwhile I've found another problem with my code which I think is the "@@@" issue. I'll post for Chip to solve next.
Neither of the lines below compile/resolve to a correct hub address so that the correct string can be printed.
How do we solve this in spin2 for the pasm code ???
code attached
Your cogval example is not what happens with Chips' v34R with spin2. Let me try to explain. (refer to my post about 12 posts back)
In the original pnut v32i the ROM code was compiled as follows results correctly in a negative offset of 5 longs = 20 bytes as _reset_booter is a label on an instruction at hub $fca78 which is 4+1 instructions prior.
v34R compiles DAT orgh code into a binary beginning at $00008 (from the binary listing in v34r). The loader loads this code into hub $01000 (at least in my example code above).
So the instruction gets encoded as shown below (determined from a dump of hub code) results in a bogus negative offset. Chip says this is an address relative to the object. No idea what use this would be as it certainly will not result in a correct relative address!
So now we have this scenario...
"@" must be used when referring to a label of an address in hub, BUT must not be used if the label is the address (hub or otherwise) of the target in a CALL/JMP/DJNZ/etc, at least when used with spin2.
Do you see the confusion?
I think you need to use LOC so the compiler can calculate the address relative: But I have not tried it, just my guess.
Andy
LOC can only be used with PA/PB/PTRA/PTRB registers.
BTW it's not true that "@ must be used when referring to a hub address". That's only the case for labels with two addresses, i.e. labels in an ORG section where the ordinary address is in cog memory. For labels after ORGH the @ is optional and does nothing. Not that that helps you. Chip's Spin2 compiler is like his Spin1 compiler, the pasm code has no way to access the hub addresses of labels at compile time. It has to be done at run time.
Fastspin, like bstc and homespun, does have a way to do this.
Okay, so he could do it with two instructions: These are two longs, just like the version with mov ..,##
But better would be to modify the string output routine to use ptra or ptrb.
Also, if it's easy, could you make PNut able to handle Unix line endings (i.e. just LF ($0a) without CR) in addition to Windows' CRLF line endings? Right now, PNut just ignores the LFs - it thinks the whole file is one long line. I don't mind if the display is wrong - I only need it to work in command-line mode. This isn't as important as having -c show error messages, since I can have my editor use the Windows line endings.
Thanks!
You have to remember that the concept for the routines in ROM (and now being replaced in the exact ROM position) was to not use any resources if possible so as to allow the calling program free rain over the resources. Hence PA/PB/PTRA/PTRB etc were specifically not used. Only 16 cog registers were used which were $1E0-$1EF which were the top free 16 registers. Then spin grabbed them, hence the ROM code needing to be replaced.
And I repeat again, this code compiles as pasm in both pnut (pasm only) and fastspin but it doesn't compile correctly in pnut if spin2 is used!
PR0 := "ABCD"
instead of
PR0 := ("A"<<24) + ("B"<<16) + ("C"<<8)+"D"
or
PR0 := $41424344
This would load register PR0 (ie $1D8) with the long $41_42_43_44 or $44_43_42_41 (not sure which way around)
The following instructions are being compiled as a relative addresses but the address at runtime is incorrect. Surely, when a specific address is specified, shouldn't it compile to an absolute address?
BTW forcing absolute addressing does work
See also here
Your NOT crossing a domain so your call's will always be treated as relative.