Shop OBEX P1 Docs P2 Docs Learn Events
Confusion about @, @@, @@@, ... — Parallax Forums

Confusion about @, @@, @@@, ...

David BetzDavid Betz Posts: 14,516
edited 2013-09-05 15:09 in Propeller 1
I'm trying to debug some code that I wrote that requires a 16 byte aligned address. This is the code I wrote to accomplish that but I'm not sure it's working correctly. In particular, I'm not sure I'm using the @ operator correctly. The manual says something about runtime vs. compile time but I'm not sure I understand the difference. Should this work?
PUB init
  mm_data_ptr := (@mm_data_padded + 15) & !15

DAT

mm_data_padded      long    0[2048+15]
mm_data_ptr         long    0

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-09-04 15:08
    'Looks good to me, David, except that you're reserving more extra space than you need (15 longs, instead of 15 bytes).

    -Phil
  • David BetzDavid Betz Posts: 14,516
    edited 2013-09-04 15:11
    'Looks good to me, David, except that you're reserving more extra space than you need (15 longs, instead of 15 bytes).

    -Phil
    Ah, good point. Thanks for noticing that!
  • ElectrodudeElectrodude Posts: 1,658
    edited 2013-09-04 15:50
    I've had many headaches when trying to convince the compiler to 64 byte align graphics tiles to be fed to VGA.spin or the like. Try adding big dummy arrays to space things apart so memory overruns don't do anything bad as shown below. Note that my dummy arrays are huge, possibly too big to fit; if so, make one smaller and then the other until you find which side is being overrun - the top or bottom. Read these dummy arrays to make sure the longs bordering mm_data_padded are 0 i.e. not overrun. If they aren't zeros, then you have a memory management problem, otherwise the bug is probably not in the code you posted (but I might be missing something, I didn't test your code, just telling you what I did when it happened to me)
    PUB init
      mm_data_ptr := (@mm_data_padded + 15) & !15
    
    DAT
    
    dummy1              long    0[2048]
    mm_data_padded      long    0[2048+15]
    dummy2              long    0[2048]
    mm_data_ptr         long    0
    
  • David BetzDavid Betz Posts: 14,516
    edited 2013-09-04 15:53
    I've had many headaches when trying to convince the compiler to 64 byte align graphics tiles to be fed to VGA.spin or the like. Try adding big dummy arrays to space things apart so memory overruns don't do anything bad as shown below. Note that my dummy arrays are huge, possibly too big to fit; if so, make one smaller and then the other until you find which side is being overrun - the top or bottom. Read these dummy arrays to make sure the longs bordering mm_data_padded are 0 i.e. not overrun. If they aren't zeros, then you have a memory management problem, otherwise the bug is probably not in the code you posted (but I might be missing something, I didn't test your code, just telling you what I did when it happened to me)
    PUB init
      mm_data_ptr := (@mm_data_padded + 15) & !15
    
    DAT
    
    dummy1              long    0[2048]
    mm_data_padded      long    0[2048+15]
    dummy2              long    0[2048]
    mm_data_ptr         long    0
    
    I'm not sure I understand why I need these extra arrays. My approach is to allocate a buffer that is not necessarily aligned in any particular way but that is bigger than the one I actually need. I then skip over the first few bytes in that bigger buffer until I get to an address that is aligned the way I want. I then use the computed value mm_data_ptr as the base address of the aligned buffer. Do I still need your additional arrays with this approach?
  • AribaAriba Posts: 2,690
    edited 2013-09-05 02:51
    A variation that is a little bit more efficient:
    PUB init
      mm_data_ptr := @mm_data_padded & !15
    
    DAT
    
                        byte    0[15]			
    mm_data_padded      long    0[2048]
    mm_data_ptr         long    0
    

    Andy
  • David BetzDavid Betz Posts: 14,516
    edited 2013-09-05 04:26
    Ariba wrote: »
    A variation that is a little bit more efficient:
    PUB init
      mm_data_ptr := @mm_data_padded & !15
    
    DAT
    
                        byte    0[15]			
    mm_data_padded      long    0[2048]
    mm_data_ptr         long    0
    

    Andy
    Thanks Andy!
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-09-05 06:06
    Ariba's code would require the mm_data_padded label to be on the "byte 0[15]" to work correctly. Alternatively, you could just do
    PUB init
      mm_data_ptr := @mm_data_padded & !15
    
    DAT
    			
    mm_data_padded      long    0[2048+3]
    mm_data_ptr         long    0
    
    This will work since mm_data_padded is already long-aligned, so you just need to allocate 3 extra longs to allow for 16-byte, or 4-long alignment.

    EDIT: Ariba's code looks good to me. I need more coffee. :)

    EDIT2: Ariba's code would use slightly less memory if you replace "byte 0[15]" with "long 0[3]".
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-09-05 07:32
    Dave Hein wrote:
    Ariba's code would use slightly less memory if you replace "byte 0[15]" with "long 0[3]".
    Most fo the time, but not always; and it's never more. It depends on how much padding the compiler adds to hit the long boundary.

    -Phil
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2013-09-05 10:09
    byte 0[15] is the same as byte 0[16], because the compiler inserts a pad byte to make the long start on a 4 byte alignment.

    long 0[3] might have padding before it, but it wouldn't have any padding after it.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-09-05 10:32
    The byte alignment before the "byte 0[15]" is unknown, so "byte 0[15]" is not necessarily the same as "byte 0[16]". The compiler will insert 0 to 3 padding bytes before the long depending on the initial alignment.

    EDIT: "byte 0[12]" or "long 0[3]" is sufficient.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-09-05 11:07
    Roy Eltham wrote:
    byte 0[15] is the same as byte 0[16] ...
    Actually, it's not in the case where it starts, for example, on a long + 1-byte boundary. In that case, the 0[16] requires more padding bytes ahead of the following long.

    -Phil
  • David BetzDavid Betz Posts: 14,516
    edited 2013-09-05 11:54
    Actually, it's not in the case where it starts, for example, on a long + 1-byte boundary. In that case, the 0[16] requires more padding bytes ahead of the following long.

    -Phil
    Given all of these auto-alignment issues done by the compiler, it seems like this is likely to work best. The compiler won't insert any extra bytes since I'm only asking for byte alignment.
                        byte    0[15]
    mm_data_padded      byte    0[2048]
    mm_data_ptr         long    0
    
    Edit: Of course, it still might put some padding bytes just before mm_data_ptr to align it on a long boundary.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-09-05 12:00
    Or you could just do:
    mm_data_padded      byte    0[2063] 'Requires +15 in address computation.
    mm_data_ptr         long    0
    

    But there's nothing at all wrong with:
    mm_data_padded      long    0[3] 'Requires +15 in address computation.
                        byte    0[2048]
    mm_data_ptr         long    0
    

    Note that I moved the label. It's because of the +15 in your (original) address computation. Without the +15, the label belongs on the following line.

    -Phil
  • AribaAriba Posts: 2,690
    edited 2013-09-05 12:31
    To meet the title of this thread you can also make it like that (with BST, Homespun and maybe OpenSpin):
    ' no Spin methode required
    DAT
                        byte    0[15]               'or long 0[3]	
    mm_data_padded      long    0[2048]
    mm_data_ptr         long    @@@mm_data_padded & !15
    

    or like that:
    PUB init
      mm_data_ptr := @@mm_data_ptr & !15
    
    DAT
                        byte    0[15]			
    mm_data_padded      long    0[2048]
    mm_data_ptr         long    @mm_data_padded
    

    Andy
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2013-09-05 15:09
    In the code snippet given the byte 0[15] was at the start of the DAT section which would be 4 byte aligned already.

    The DAT section ends up first in the binary output of an object, and the compiler pads objects as well so the other objects DATs in the same binary will be aligned also. Even if it wasn't the only DAT in the file it's extremely like that it would be 4 byte aligned.

    I agree that in the general case a byte 0[15] might not be the same a byte 0[16], but in the example given it is. That's all I was saying. Plus, the obvious choice is to use long 0[3] anyway.
Sign In or Register to comment.