Shop OBEX P1 Docs P2 Docs Learn Events
PASM help with "arrays" — Parallax Forums

PASM help with "arrays"

jmspaggijmspaggi Posts: 629
edited 2010-04-12 21:31 in Propeller 1
Hi,

Can someone help me with PASM?

I have 3 res variables. A, B and C.

C is res 64.
B is in index
A need to point the the right place in C.

All my values should be bytes.

So I do:

        mov A, #C
        add A, B




Now, I'm missing one more instruction to have A pointing to the address stored in A. I tried to play with @ an # with no success and read also fiew PDFs, but I'm not not able.

So what should I put to have A pointing to the right place?

On a post from Mike (http://forums.parallax.com/showthread.php?p=601870) I found:
'' Here's a simple example of table lookup in assembly.
'' This particular example takes a table index in "ptr"
'' and sets the "data" to the word value from the table.
'' There's no range checking.  If you want long values,
'' just eliminate the shifts and masks (*).  You can use
'' the same kind of logic for byte values.

DAT
            org   0
test      mov   ptr,#2        ' for an example, get third value
            call  #look            ' note table indices are 0 to n-1
:stop     jmp   #:stop        ' no checking for out of range

look         mov    data,ptr      ' ptr is a table index (0 to n-1)
              shr   data,#1       ' divide input value by 2 to get (*)
              add    data,#table    '   long word index, add table address
              movs   :inline,data   ' have to use instruction modification
              nop                        ' need pause here for pipelining
:inline    mov    data,0-0         ' get long value from table
              test   ptr,#1   wz     ' do we want odd or even half  (*)
    if_z     and    data,mask       ' if even, take lower 16 bits (*)
    if_nz   shr    data,#16         ' if odd, take upper 16 bits  (*)
look_ret   ret
table       word    $0000
              word    $C0C1
              word    $C181
              word    $0140
              word    $C301
              word    $03C0
              word    $0280
mask        long   $FFFF
data        res     




So should I "simply" do that?

        mov A, #C
        add A, B
     movs :inline,A
        nop           
:inline mov    A,0-0  





Thanks,

JM

Comments

  • AleAle Posts: 2,363
    edited 2010-04-12 20:03
    Yes, using self-modifying code is the only way. Be aware that memory in the COG is accessed in longs, i.e. 32 bits at a time so you will fetch 2 words with the mov. Every memory position (0, 1, 2 to 511) is a long, memory is not accessible as bytes!.
    Either change it to long and take care that the pointer accesses the right position or read two words at the time and use a mask/shift accordingly, I'd use longs unless memory is a constraint.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Visit some of my articles at Propeller Wiki:
    MATH on the propeller propeller.wikispaces.com/MATH
    pPropQL: propeller.wikispaces.com/pPropQL
    pPropQL020: propeller.wikispaces.com/pPropQL020
    OMU for the pPropQL/020 propeller.wikispaces.com/OMU
    pPropellerSim - A propeller simulator for ASM development sourceforge.net/projects/ppropellersim
  • jazzedjazzed Posts: 11,803
    edited 2010-04-12 20:28
    jmspaggi said...
    Hi,

    Can someone help me with PASM?

    I have 3 res variables. A, B and C.

    C is res 64.
    B is in index
    A need to point the the right place in C.

    All my values should be bytes.


    @JM,

    It will be easier and faster to hold your table in HUB RAM and access it using rdbyte and wrbyte.
    You will have to pass a reference to your array from Spin to PASM at cog startup using cognew(@pasm, @parms).
    While rdbyte can take up to 22 clocks to get started, you can reduce that time to 8 clocks by keeping the access in "the window."

    ' Untested quick example ... try same with movs,movd for exercise
    var
      long length ' dynamic length of table. also can be some parameter for mailbox, etc...
      long table[noparse][[/noparse]64>>2] ' 64 bytes ... keep var data all the same type so addresses are contiguous
    
    pub main
      cognew(@pasm, @length)
    
    dat
    pasm  org 0
    jmp #init ' jump immediate to address of init
    ' can use space before variables as a jump table similar to ISR code
    index long 0
    value long 0
    len long 0
    lenadr long 0 ' storage for length address
    tabadr long 0 ' storage for table address
    tptr long 0 ' use RES only at end of cog pasm code
    init
      mov tptr, par
      mov lenaddr, tptr ' save length pointer
      add tptr, #4 ' point to table
      mov tabadr, tptr ' tabadr contains table pointer
    
    mainloop
      rdlong len, lenadr wz
      if_z jmp #mainloop ' jump back to length read ... faster than tjz ...  
      mov tptr, tabaddr
      'add tptr, len ' oops ... this would be for decrementing pointer
    :readtable
      rdbyte value, tptr ' rdbyte hub operation is always in window
      add tptr, #1 ' next address
    ' if you need more instructions, add up to 4 before djnz to stay in next hub window
      djnz len, #:readtable 
      jmp #mainloop
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    May the road rise to meet you; may the sun shine on your back.
    May you create something useful, even if it's just a hack.

    Post Edited (jazzed) : 4/12/2010 9:08:04 PM GMT
  • jmspaggijmspaggi Posts: 629
    edited 2010-04-12 21:05
    Thanks for your replies. I did not figured it was words only. I can deal with that since I should have enought memory.

    @jazzed, what is he hub faster that the cog memory? I will have all the cogs running the same code, so all accessing the hub. Will it not be faster to access the COG memory instead? I'm trying to do a kind of stack. I'm working on that 8h a day for the 3 last days and starting to find PASM difficult [noparse];)[/noparse]

    I don't want to post my code yet because you will clean it in 10 seconds and propose a better solution and I don't want to be frustrated [noparse];)[/noparse]

    To put on the stack, I need this code:
            mov Addr, #Stack
            add Addr, Index
            movd :i2, Addr
            nop
    :i2     mov 0-0, Temp
    
    


    Duration: 5x4 cloks = 20 clocks.

    Your solution (Not sure, correct if I'm wrong):
            mov Addr, #Stack
            add Addr, Index
            wrbyte Addr, Temp
    
    


    Duration=4+4+7..22 so min=15 max=30.

    Is it really better?

    Also, what can I use to trace the PASM? I tried pPropelleSim, but it's petty buggy. GEAR does not display instruction and memory and is only working on windows. Pretty difficult to find a good tool. Is Parallax tool coming with a debuger like for the Javelin?

    JM
  • jazzedjazzed Posts: 11,803
    edited 2010-04-12 21:31
    jmspaggi said...

    @jazzed, what is he hub faster that the cog memory? I will have all the cogs running the same code, so all accessing the hub. Will it not be faster to access the COG memory instead? I'm trying to do a kind of stack. I'm working on that 8h a day for the 3 last days and starting to find PASM difficult [noparse];)[/noparse]
    If you are willing to sacrifice 64 longs instead of 64 bytes, the speed is about the same.
    Your two examples illustrate it fairly well:

            mov Addr, #Stack  ' 0
            add Addr, Index   ' 4
            movd :i2, Addr  ' 8
            nop                  ' 12
    :i2     mov 0-0, Temp ' 16
    ' 20 for next instruction
    
    


    Duration: 5x4 clocks = 20 clocks.

            ' assuming a hub operation is here before the mov Addr, Stack pointer ....
            mov Addr, StackPointer ' 0 must be a reference to hub ram
            add Addr, Index    ' 4
            wrbyte Addr, Temp  ' 8
    ' 16 for next instruction
    
    


    Duration: 2x4 + 1*8 clocks = 16 clocks minimum

            ' assuming no hub operation is here before the mov ....
            mov Addr, StackPointer ' 0 must be a reference to hub ram
            add Addr, Index    ' 4
            wrbyte Addr, Temp  ' 8 .. 22
    ' 16 .. 30 for next instruction
    
    


    Duration: 2x4 + 22 max clocks = 30 clocks maximum.

    Clearly, if you can't keep hub accesses in the window, the intracog solution is faster.
    Problem is you need 4x the memory in the COG and if the data is only byte wide, that's a big waste.
    To do the same byte size operations intra-cog requires more instructions.

    I use a tool I developed for on-chip debugging, but it's not for everyone [noparse]:)[/noparse]
    There is a GUI add-on for that, but it is not ready for prime-time as they say.

    Perhaps you should try GEAR since you don't have a Propeller yet.
    I bet Ale would help you with whatever issues you have with ppropellersim though.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    May the road rise to meet you; may the sun shine on your back.
    May you create something useful, even if it's just a hack.
Sign In or Register to comment.