Shop OBEX P1 Docs P2 Docs Learn Events
Could we have right moving versions of byte/word/longmove? Solved! it already does! — Parallax Forums

Could we have right moving versions of byte/word/longmove? Solved! it already does!

R BaggettR Baggett Posts: 264
edited 2026-03-11 15:12 in Propeller 2

I have a memory constrained application and must modify large strings. The usual ways to do this would require additional buffers to do something like add 'very ' to 'a long string' at index 7.
I wrote the following for creating space in the buffer for 'very ' without requiring another buffer:

Would it break the world (Or even your little corner of it) if we had byte/word/longmove move right, maybe when count is negative?

Comments

  • RaymanRayman Posts: 16,138

    Guess bytemove would clobber the string right?

    Guess something like bytemoveR would be useful for that.

    If stack is big enough, could define a local array of longs to copy to, modify, then write back?

  • @Rayman said:
    Guess bytemove would clobber the string right?

    Guess something like bytemoveR would be useful for that.

    If stack is big enough, could define a local array of longs to copy to, modify, then write back?

    Right in all cases. Problem is, my string is JSON and contains the entire dump of information between boards, and the master computer, it's of a manageable size, but eventually not so much if I need a second buffer large enough to add something at the beginning of the string.
    I would like something like this, but I really don't want see substantial changes. Appending 'R' would seem clean. So would a negative number for count (I even tried it... I had no idea something like that could make a cog reset 6 times in a row...)

  • Or maybe bytemove should just do the right thing for overlapping memory regions (moving right if it has to)? I don't think it's officially documented anywhere that it moves in some particular order, is it?

  • @ersmith said:
    Or maybe bytemove should just do the right thing for overlapping memory regions (moving right if it has to)? I don't think it's officially documented anywhere that it moves in some particular order, is it?

    I read carefully before trying it. (Even p1 docs) It seems that this case where the move overlaps is not anticipated.

  • R BaggettR Baggett Posts: 264
    edited 2026-03-11 14:29

    From P1 docs:
    BYTEMOVE is one of three commands (BYTEMOVE, WORDMOVE, and LONGMOVE) used to copy blocks of main memory from one area to another.

    By this description, my use case seem to be an abuse of BYTEMOVE but that is probably for simplicity in the docs. (I do use bytemove when I am making the string shorter)

  • maccamacca Posts: 1,011

    @"R Baggett" said:

    @ersmith said:
    Or maybe bytemove should just do the right thing for overlapping memory regions (moving right if it has to)? I don't think it's officially documented anywhere that it moves in some particular order, is it?

    I read carefully before trying it. (Even p1 docs) It seems that this case where the move overlaps is not anticipated.

    Don't know if I miss something, but looking at the Spin Interpreter code at lines 2099-2224, all the byte/word/long-move methods, at least in P2, do the reverse move, if source is greater than destination.
    Seems there is a similar check in the P1 interpreter code but can't test right now.

    {Spin2_v52}
    CON
    
        _CLKFREQ = 160_000_000
    
    VAR
    
        byte mem[16]
    
    PUB start() | i
    
        repeat i from 0 to 16
            mem[i] := i
        debug(udec_byte_array(@mem, 16))
        bytemove(@mem[0], @mem[1], 15)
        debug(udec_byte_array(@mem, 16))
    
        repeat i from 0 to 16
            mem[i] := i
        debug(udec_byte_array(@mem, 16))
        bytemove(@mem[1], @mem[0], 15)
        debug(udec_byte_array(@mem, 16))
    
        repeat
    

    Result:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  INIT $0000_0F64 $0000_18B4 jump
    Cog0  @mem = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    Cog0  @mem = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 15
    Cog0  @mem = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    Cog0  @mem = 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
    
  • JonnyMacJonnyMac Posts: 9,737
    edited 2026-03-11 14:58

    I could be mistaken, but I though Ada once commented (some time ago) by the xxxxmove instructions adjust based on the source and destination locations. In the interpreter source code, there are separate move loops for forward and reverse.

    ...do something like add 'very ' to 'a long string' at index 7.

  • R BaggettR Baggett Posts: 264
    edited 2026-03-11 15:14

    @JonnyMac said:
    I could be mistaken, but I though Ada once commented (some time ago) by the xxxxmove instructions adjust based on the source and destination locations. In the interpreter source code, there are separate move loops for forward and reverse.

    @macca said:

    @"R Baggett" said:

    @ersmith said:
    Or maybe bytemove should just do the right thing for overlapping memory regions (moving right if it has to)? I don't think it's officially documented anywhere that it moves in some particular order, is it?

    I read carefully before trying it. (Even p1 docs) It seems that this case where the move overlaps is not anticipated.

    Don't know if I miss something, but looking at the Spin Interpreter code at lines 2099-2224, all the byte/word/long-move methods, at least in P2, do the reverse move, if source is greater than destination.
    Seems there is a similar check in the P1 interpreter code but can't test right now.

    Indeed it does just 'do the right thing' !!!!
    Thinking back, I ASSumed it wouldn't work that way, I tried fooling it with a negative count, and in my little mind that was that when it failed and I wrote shiftright()

    Thanks so much!

  • JonnyMacJonnyMac Posts: 9,737
    edited 2026-03-11 15:29

    It took a couple tries but I got a string insert method working:

    Here's the method code for copy-and-paste if you want to try

    pub insert_str(p_src, p_dst, ofs) | slen, dlen
    
    '' Insert string at p_src into string p_dst at ofs
    
      slen := strsize(p_src)
      dlen := strsize(p_dst)
    
      bytemove(p_dst+ofs+slen, p_dst+ofs, dlen-ofs) 
      bytemove(p_dst+ofs, p_src, slen)
    
  • @JonnyMac said:
    It took a couple tries but I got a string insert method working:

    I haven't untangled my in-place string insert routine to properly use bytemove yet, I guess it's done now! Thanks, Jon!

  • Please wring it out as hard as you can -- my testing was very simple, just to demonstrate that bytemove does adjust direction.

  • RaymanRayman Posts: 16,138

    Is this true for pnut flexprop and spin tools?

  • I should have uploaded the whole test program. The answer is yes.

    Propeller Tool + PST

    Spin Tools + Internal Terminal

    FlexProp + Internal Terminal (byte code)

    FlexProp + Internal Terminal (pasm)

  • @JonnyMac said:
    I could be mistaken, but I though Ada once commented (some time ago) by the xxxxmove instructions adjust based on the source and destination locations. In the interpreter source code, there are separate move loops for forward and reverse.

    IIRC Eric actually said that after you complained about the lengthy flexspin ASM output for bytemove. (which is due to needing to handle that backwards condition, in addition to rather worthwhile optimization to copy longs at a time instead of bytes)

    But this behaviour has always been documented in the P1 manual. The "move" also hints towards it (Spin's bytemove is analogous to C's memmove, with no equivalent to memcpy (C's "dumb" copy)).

Sign In or Register to comment.