Shop OBEX P1 Docs P2 Docs Learn Events
Still struggling with hub locations in spin2 and pnut — Parallax Forums

Still struggling with hub locations in spin2 and pnut

Cluso99Cluso99 Posts: 18,069
edited 2020-05-29 05:44 in Propeller 2
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!
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,0
The 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

  • What does that 3rd parameters 0 in coginit mean to you?
  • Disclaimer: I don't know anything of how PNut works internally. I'm also no expert when it comes to all that ## vs. ##\, @@, @@@ etc. stuff. I do that wrong frequently and just know from experience what works and what not.

    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:
    PUB startcog()
      strPtr:= @_sd_vers
      coginit(16, @entry, 0)
      repeat
    
    DAT
                  org       0
    entry         ...
                  mov       lmm_p,strPtr  ' must be in hub!
                  call      #_HubTxString
                  ...
    strPtr        long 0 ' is patched by spin
    
    DAT
                  orgh
    _sd_vers      byte      "P2-test-program v.???",$0D,$0A,0
    
    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.
  • All I do for pasm+spin2 in Pnut is add $ff8 to compensate for spin2. Works for me.
     mov       lmm_p,            ##@str_p2eval + $ff8
    
    :)
  • Cluso99Cluso99 Posts: 18,069
    ozpropdev wrote: »
    All I do for pasm+spin2 in Pnut is add $ff8 to compensate for spin2. Works for me.
     mov       lmm_p,            ##@str_p2eval + $ff8
    
    :)
    Brian,
    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.
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-29 08:08
    ManAtWork wrote: »
    Disclaimer: I don't know anything of how PNut works internally. I'm also no expert when it comes to all that ## vs. ##\, @@, @@@ etc. stuff. I do that wrong frequently and just know from experience what works and what not.

    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:
    PUB startcog()
      strPtr:= @_sd_vers
      coginit(16, @entry, 0)
      repeat
    
    DAT
                  org       0
    entry         ...
                  mov       lmm_p,strPtr  ' must be in hub!
                  call      #_HubTxString
                  ...
    strPtr        long 0 ' is patched by spin
    
    DAT
                  orgh
    _sd_vers      byte      "P2-test-program v.???",$0D,$0A,0
    
    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.
    This may work for this example, but where you have a large numbers of entry points in hubexec code it is not feasible to patch everything depending on whether you are running the very same code under pasm or spin. It just does not make any sense.

    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
  • Cluso99Cluso99 Posts: 18,069
    Thanks Brian. It worked.
    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       lmm_p,            ##str_p2eval        ' must be in hub! (for pasm)
                  mov       lmm_p,            ##@str_p2eval +$ff8 ' must be in hub! (offset for spin)
                  call      #_HubTxString
    
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-29 22:40
    It’s curious. I used pure pasm and displayed the results from
    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 ???

  • You could use a constant to make it easuer.
    con
        adj = $ff8  ' 0 for pasm only
    dat
    ...
    mov       lmm_p,            ##@str_p2eval + adj  ' must be in hub! (offset for spin)
                  call      #_HubTxString
    
  • AribaAriba Posts: 2,682
    edited 2020-05-29 10:26
    Cluso99 wrote: »
    ....
    The 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.

    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
  • Wuerfel_21Wuerfel_21 Posts: 4,464
    edited 2020-05-29 10:24
    Ariba wrote: »
    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.

    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?
  • Please don't use a fixed offset of $ff8:

    (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:
    func1  jmp #@func1_hub - @entry
    func2  jmp #@func2_hub - @entry
    func3  jmp #@func3_hub - @entry
    
    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 :).
  • AribaAriba Posts: 2,682
    Chip showed a solution with jumprel in the thread I linked to.
    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.
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-29 21:58
    My current problem is not with jumps and calls. It is with hub variables that also change position!

    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!!!
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-29 22:48
    Just edited my post about 7 posts back.

    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
  • RaymanRayman Posts: 13,861
    I either modify the assembly before launch or pass in address list with ptra
  • The way I've handled this in the P1 was to hard-code a "+16" to the object offsets stored in DAT space. Of course, this only works for the top object in the P1, and is not relocatable. For relocatable binaries, or for objects other than the top object I would run an initialization routine at startup that would add the object address to all the object offsets in DAT. It's an extra burden on the programmer to do this, but it's not that difficult to do.
  • Cluso99Cluso99 Posts: 18,069
    Rayman wrote: »
    I either modify the assembly before launch or pass in address list with ptra

    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.
  • How does it break spin? Can you show an example?
  • Cluso99Cluso99 Posts: 18,069
    Dave Hein wrote: »
    The way I've handled this in the P1 was to hard-code a "+16" to the object offsets stored in DAT space. Of course, this only works for the top object in the P1, and is not relocatable. For relocatable binaries, or for objects other than the top object I would run an initialization routine at startup that would add the object address to all the object offsets in DAT. It's an extra burden on the programmer to do this, but it's not that difficult to do.
    That's why we used homespun or bst. Solved the problem with @@@.

    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 was tempted to use @@@ in BST, but I wanted my code to compile under the PropTool as well. I was also interested in being able to run binaries at addresses other than zero so that I could run multiple binaries at the same time. For those reasons I decided to add initialization code that would convert the object offsets to absolute addresses at runtime.
  • All this hassle makes developing code extreme complicated
    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
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-30 20:04
    I put my Z80+CPM on hold hanging out for spin2.

    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 :(
  • Cluso99 wrote: »
    I put my Z80+CPM on hold hanging out for spin2.

    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...
  • Cluso99Cluso99 Posts: 18,069
    ersmith wrote: »
    Cluso99 wrote: »
    I put my Z80+CPM on hold hanging out for spin2.

    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...
    Yes, I'm on it :)
    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.
Sign In or Register to comment.