Still struggling with hub locations in spin2 and pnut
Cluso99
Posts: 18,069
I have this great piece of code that compiles and runs fine with pnut v34s while the code is totally pasm.
But the moment I introduce spin2 into the mix it fails
I know it's because the compiler places the string in a different location in hub to where the compiler thinks it placed it
Here is an extract of the few lines
If I comment out the PUB and its' two lines (which then becomes a pure pasm program) the program runs fine.
1. How am I supposed to get the address of the string when my pasm program is run with spin
2. Why on earth cannot the same code run in spin when it runs just fine in pasm only?
3. Isn't it time for this pedantic madness to be fixed!
Why? Well because otherwise spin would not know how to load the pasm code from hub into the cog when it executes the coginit(16, @entry, 0) instruction. Here, it does indeed know the address @entry or otherwise that instruction would fail.
But the moment I introduce spin2 into the mix it fails
I know it's because the compiler places the string in a different location in hub to where the compiler thinks it placed it
Here is an extract of the few lines
If I comment out the PUB and its' two lines (which then becomes a pure pasm program) the program runs fine.
1. How am I supposed to get the address of the string when my pasm program is run with spin
2. Why on earth cannot the same code run in spin when it runs just fine in pasm only?
3. Isn't it time for this pedantic madness to be fixed!
PUB startcog() coginit(16, @entry, 0) repeat DAT org 0 entry ... mov lmm_p, ##@str_p2eval ' must be in hub! call #_HubTxString ... DAT orgh _sd_vers byte "P2-test-program v.???",$0D,$0A,0The excuse that pnut (in spin) doesn't know the address of where the code is placed in hub is actually utter nonsense because in fact it does indeed know.
Why? Well because otherwise spin would not know how to load the pasm code from hub into the cog when it executes the coginit(16, @entry, 0) instruction. Here, it does indeed know the address @entry or otherwise that instruction would fail.
Comments
But I try to explain how I'm seeing it:
* As long as you have a pure pasm program there are no objects that are to be re-located. So hub adresses are fixed and all known at compile time.
* As soon as Spin is involved only Spin knows the absolute adresses. There is no "linker" that patches pasm code to fix any address offsets. I had the same problem long ago with P1 asm. I found out how to fix that: So I simply accept that ##@ does not work in pasm and let the spin part insert the correct address at runtime. It doesn't make the asm code longer and it's only a few letters more to type.
Where does that +$ff8 come from?
Can we guarantee that will always be the case?
And, since we don't have conditional assembly, we cannot effectively make an object that can be used in both cases. That was my objective. I cannot see why we cannot have a pasm blob that will work whether it is compiled for pasm only or a mix of spin and pam. Add to this, spin does indeed know where the code is placed in hub, it just doesn't tell the pasm part of the compiler.
I'll try your trick of +$ff8 probably tonight and see how it goes. Thanks.
BTW To make your example work for pasm you would need to do this, which would need to be overwritten by spin
strPtr long @_sd_vers
So you need two distinct instrcutions for the same pasm code depending on whether your program is all pasm or a mix of pasm and spin
MOV x, ##str
MOV x, ##@str
MOV x, ##@str+$ff8
IIRC the first two gave me $109 And the last $1101.
Posteditted
With pure pasm these all gave the correct result when displaying the string so I investigated further.
There are two copies of this string in hub! One at $109 and again at $10f9.
Why are there two copies ???
I need to check the binary. Binary only has one. Problem was the old one was left over from the previous download of the spin binary.
With spin, the addresses were slightly different. I haven’t looked in hub yet.
The 3 addresses from the above instructions were $509, $111 and $1109 respectively. Only the last one worked.
If the +$ff8 always works, then why can’t the compiler adjust for this offset ???
If +$ff8 works in spin. then why can't the compiler adjust for this offset ???
Spin knows the object offset at runtime, but not at compile time. I find this also strange, but it's based on the way the compiler works.
You get the object offset in PTRB when you start a PASM cog, so you can add PTRB to the address if you call a hubexec subroutine.
Or you calculate the right addresses in Spin, before you start the cog. There are some ideas in this thread.
Adding the offset as a constant will only work for the first object, and the offset may change if the interpreter code gets bigger (or smaller).
Andy
I think the idea is to eventually(TM) support loading objects into arbitrary memory locations at runtime. To my knowledge, that never manifested for Spin1 in any capacity. May come into play with the self-hosted Spin2 compiler?
(a) this will fail in sub-objects
(b) this will fail in PASM only builds
(c) this will fail in fastspin
I wish Chip would change PNut to allow the possibility of absolute addresses in Spin2 objects, but I have some sympathy for him. It was quite a pain to get this working in fastspin, and I only did it because I erroneously thought that was the way Spin2 was going to work (based on how it worked in PASM only Spin2).
However, it is possible to write position independent code that calls from COG to HUB and works in any object and with both compilers. The easiest way is probably to use a jump table which you fix up at run time. You can do this either in PASM (using ptrb, which contains the PASM entry point at startup) or in Spin using @ arithmetic.
The jump table should look like: The "-@entry" adjusts the pointers to whatever ptrb will have when the COG starts up.
You can put this table into COG or LUT memory (in which case it's usable directly). or you can leave it in HUB and adjust ptrb to point to it. Probably there's some nice way to use "jmprel" in this scheme, but it's too early here for me to risk trying to write that down .
Here is the direct link: http://forums.parallax.com/discussion/comment/1493032/#Comment_1493032
A few post before there are 2 other solutions with jump tables.
Having to "patch" your code is just asking for trouble.
Currently I have to "move" my hubexec pasm code to where I want to place it in hub because there is no way to put it there in the first place.
There is no way to perform a jump or call to it without constructing a set of equates (after you compile an work out the hub addresses. This way means if you change the hubexec pasm you MUST remember to change the equates - a bad trap.
Alternately, you put a jump table at the beginning. Just a PITA.
Or you let pnut/spin put it anywhere in hub, and use a jump table at the beginning. Now you need to "patch" your code that uses it. Another PITA and trap.
The advantage of this so-called "relocatable" way defeats any possible use of relocatable code, and at the same time causes grief to anyone using it in a normal way.
This problem won't go away by ignoring it. IMHO SPIN2 with pnut is unusable for prime-time!!!
PASM does not work with the offset, and spin requires the offset. No simple solution here either
PASM alone...
instr regx,##str
or
instr regx,##@str
SPIN with PASM...
offset = $ff8 ' or whatever?
instr regx, ##@str+offset
where
DAT
str long "a string",0
But you should not have to jump thru these hoops just to get a pasm program that works fine in pure pasm compiles, but does not work when another spin cog is used. The spin that has been added may have nothing to do with the pasm running in another cog. Introducing spin into the mix breaks perfectly fine running pasm code.
But in P1 we could not run pasm only.
Here we have the same perfectly running pasm code that runs in its' own cog, and references code in hub. Works perfectly. But when we add spin into the mix, the pasm breaks. Now we have to "patch" the perfect pasm code so that it works. And it's definitley not intuitive.
I myself prefer not to use the spin interpreter at all because of numerous reasons
Pnut/spin is a nice to have thing but loosing the cog ram and the complicated ##@@#@ addressing
Makes me tend to use fastspin or pure PASM code or go to C
One of the great features of p2 is the extreme cool streamer and smartpin modes
But most cool things need to be in cog or lut ram to free the fifo.
I wish we had a p2 programmer documentation where all coding options are listed and the pros and
Cons of this options are mentioned. And also what constraints are to follow for using the full
Potential of the p2 smartpins
Yesterday I abandoned using spin2 for this project and started replacing the spin with pasm. In one day I’ve advanced further than all my wasted time trying to get spin3 to works with pasm code.
Sad day
You know where fastspin is if you ever want to use a high level language...
Only left fastspin because I wanted read spin2 bytecode, not compiled pasm.
I just posted a problem compiling my new pasm only stuff.
Some time shortly I'll get my spin1 intrpreter finally debugged for P2. It pretty much works when I stopped working on it because spin2 was so close.
Then I can compile spin1 code with bst and just include the binary blob in my P2 pasm programs. I'll get over those spin2 shortcomings one way or another.