Shop OBEX P1 Docs P2 Docs Learn Events
Continuing discussion on memory alignment — Parallax Forums

Continuing discussion on memory alignment

agsags Posts: 386
edited 2013-04-10 18:12 in Propeller 1
With clarity on the topic of memory alignment from a recent, similar thread, and implications on symbol definitions in VAR blocks, I now move my attention to DAT blocks. A few things now become apparent (long train of thought perhaps): 1) Because DAT blocks can contain PASM code, I presume they are not reordered like VAR blocks are, so a long/byte/long/byte/long/byte/long/byte sequence wastes space (total of 8 longs in the DAT block) whereas in a VAR block, symbols are reordered by size; in the case of a VAR block the memory would be allocated as four longs followed by four consecutive bytes, total of 5 longs. 1a) I also presume that all DAT blocks are effectively concatenated into one large block, in the same order in which they appear in the source. 2) Since the entry point provided as the first argument to coginit() is the location in the (concatenated) DAT block which will be loaded into cog RAM starting at 0x00, nothing before it exists in cog RAM. So, even though it will compile, if the PASM code after that entry point (with ORG or ORG 0 directive) refers to memory (a label in DAT block) that is before that entry point, that is not the symbol that will be used in the PASM code. IOW, if mySymbol is a label for the 5th long as it appears in the DAT block, and the PASM code that will be loaded into cog RAM occurs after that symbol and references it, the PASM code will actually be accessing the 5th long after the ORG directive, likely a collision with contents with a completely different purpose (an instruction or now aliased to a storage location with a different symbol/name. Do I have this right?

Comments

  • Heater.Heater. Posts: 21,230
    edited 2013-04-07 12:55
    Yep, sounds good to me.
  • Heater.Heater. Posts: 21,230
    edited 2013-04-07 12:59
    IOW, if mySymbol is a label for the 5th long as it appears in the DAT block, and the PASM code that will be loaded into cog RAM occurs after that symbol and references it, the PASM code will actually be accessing the 5th long after the ORG directive,

    You mean like:
    DAT
    a long 0
    b long 0
    c long 0
    d long 0
    e long 0
          org 0
    start    mov b,a
    .
    .
    
    I'm not really sure what that compiles to. I don't have a Spin tool at hand to find out. Cannot be good though.
  • agsags Posts: 386
    edited 2013-04-07 13:12
    Yes, that's what I mean. Since the ORG directive resets the assembly pointer, (and presuming that until there is an ORG directive found, the default is to begin with address 0 at the first location in the first DAT block present in the object) I presume it will result in the contents of the memory location immediately following the first (labeled "start") to be written to the location labeled "start". That's because "a"==0x00, "b"==0x01, "start"=0x00, and "<line after start>"==0x1.Not good.
  • Heater.Heater. Posts: 21,230
    edited 2013-04-07 13:24
    That's not how I see it. If you write
    DAT
    a long 0
    b long 0
    c long 0
    d long 0
    e long 0
          org 0
    start mov 0,0
    
    I'd expect that mov to move the contents of COG location (Not DAT location) zero into the contents of cog location zero. I.e move the mov instruction itself back over itself.
    So then "mov 0, e" would be moving the content of cog location -1 int o location zero.
    We don't have negative addresses so if that compiles at all it must refer to the top most long in cog.
    Probably not what you had in mind.
  • agsags Posts: 386
    edited 2013-04-07 13:28
    We agree it's almost certainly not behavior that is wanted except in very strange cases. However, if it's true that without an ORD directive, the assembly pointer starts at 0, then I'm thinking that a and start are both associated with cog memory location 0. In effect, an alias.
  • AribaAriba Posts: 2,690
    edited 2013-04-07 14:10
    ags wrote: »
    We agree it's almost certainly not behavior that is wanted except in very strange cases. However, if it's true that without an ORD directive, the assembly pointer starts at 0, then I'm thinking that a and start are both associated with cog memory location 0. In effect, an alias.

    Yes I expect also this behavior. The Assembler will not go back and give a..e negative addresses.
    But why do you find that "not good"?.
    What would be good? If you refer to an address outside the range that lands in the cog, then it's your fault, and you don't know what you do. That's never good if you propgram in Assembly.
    You can say it must give an error or warning, but I like Spin (and PASM) exactly because it does what I write. Other compilers try to be more intelligent than me, and I hate that. This loose checking allows a lot of PASM tricks.

    Andy
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-07 17:11
    If it helps, once you compiled your code in the PropTool (or BST IIRC) you can place the cursor on a label and it tells you DAT offset and cog register index. That should clear up all offset questions. The first DAT block has an implicit org 0 attached.
  • Cluso99Cluso99 Posts: 18,069
    edited 2013-04-07 17:58
    bst and homespun both have listing outputs. They will provide you with a lot of answers.

    The use of a DAT section with numerous ORG 0's will permit redefinition (aliases if you like) of things. Take a look at my overlay loader in OBEX. There you will find a few tricks about this and also the offsets in rdlong used to advantage. They are not all my own ideas/concepts, but a conglomeration of those into something useful.
  • agsags Posts: 386
    edited 2013-04-07 20:53
    Ariba wrote: »
    ...But why do you find that "not good"?.
    What would be good? If you refer to an address outside the range that lands in the cog, then it's your fault, and you don't know what you do. That's never good if you propgram in Assembly...
    Andy
    That is certainly an intriguing position. Experiments with software development teams has shown a correlation between rigorous code inspection (not peer inspection, but review by the author) and # of escaped defects. On the other hand, having a compiler flag the problems that it can is also very useful. For this discussion, let me state that my goal was to understand precisely the behavior of the compiler/assembler, so that I can fully appreciate the nuances of the instructions I am giving those tools. I accept responsibility for the outcome. My experience is that the documentation provided by Parallax is insufficient for new and developing users to gain a thorough and effective understanding of how the tools (and hardware) operate.
  • agsags Posts: 386
    edited 2013-04-07 21:00
    kuroneko wrote: »
    If it helps, once you compiled your code in the PropTool (or BST IIRC) you can place the cursor on a label and it tells you DAT offset and cog register index. That should clear up all offset questions. The first DAT block has an implicit org 0 attached.
    I never noticed that feature, thank you for pointing it out. I observe that using the mechanism you highlight, if I click on a label in a DAT block above the ORG directive for the PASM code that is launched in a separate cog, it provides an OBJ location but no COG location. The same steps taken on a label below the ORG directive provide both an OBJ location and a COG location. Very surprising. Still, no warning from the compiler (or is it an assembler?)
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-07 21:06
    ags wrote: »
    I observe that using the mechanism you highlight, if I click on a label in a DAT block above the ORG directive for the PASM code that is launched in a separate cog, it provides an OBJ location but no COG location.
    That sounds like something which isn't a long. In a quick test all longs do have a cog location (controlled by a preceding org). byte and word entries (aligned or not) don't.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-04-07 21:10
    heater wrote:
    So then "mov 0, e" would be moving the content of cog location -1 int o location zero.

    re:
    DAT
    a long 0
    b long 0
    c long 0
    d long 0
    e long 0
          org 0
    start mov 0,e
    

    No. If you cognew(@start, 0), mov 0,e would load the contents of cog location 4 (relative to start) to location 0 (i.e. start), since e has a cog address of 4, relative to its own implied org of 0 -- even though its contents do not even exist in the started cog.

    -Phil
  • agsags Posts: 386
    edited 2013-04-07 21:27
    kuroneko wrote: »
    That sounds like something which isn't a long. In a quick test all longs do have a cog location (controlled by a preceding org). byte and word entries (aligned or not) don't.
    Once again, you are correct, sir. My simple test case was creating a DAT block above the one containing my PASM code, and in it I added a single symbol for a byte sized location. Out of curiosity, why isn't the (long-aligned) location containing the selected byte presented to the user? (not a well-formed question, as I don't know if anyone other than the authors of the Propeller Tool could really answer with 1st hand knowledge).
  • Heater.Heater. Posts: 21,230
    edited 2013-04-08 00:11
    Phi,

    Ah yes of course, it must be like that. The assembler assigns cog addresses 0, 1, 2, 3, 4 to a, b, c, d, e respectively before it hits the ORG.
    On hitting the ORG it resets it's COG counter to zero and continues. So the COG address of e is already defined as 4.
    No negative addresses involved.
    Still. it's unlikely to be what you want to do.
  • AribaAriba Posts: 2,690
    edited 2013-04-08 08:22
    Heater. wrote: »
    Phi,

    Ah yes of course, it must be like that. The assembler assigns cog addresses 0, 1, 2, 3, 4 to a, b, c, d, e respectively before it hits the ORG.
    On hitting the ORG it resets it's COG counter to zero and continues. So the COG address of e is already defined as 4.
    No negative addresses involved.
    Still. it's unlikely to be what you want to do.

    If you do it with long 0 then it's a waste of hub memory, but with res 1 then it makes sense. I've seen this several times in Chip's code. It's a way to make aliases for the first few instructions if you later use them as registers:
    DAT
          org 0
    a     res 1       'reuse init code for registers a..e
    b     res 1
    c     res 1
    d     res 1
    e     res 1
    
          org 0
    start mov p,par   'this will be later reg a
          ...         'do init code
          ...
    loop  mov a,#0
          ...
    
    normally you define the aliases after the code, and you should use an ORG before the regs. You can't be sure that it is the first DAT.

    Andy
  • Heater.Heater. Posts: 21,230
    edited 2013-04-08 10:26
    let me revise that then:

    "It's something you are quite likely to want to do".

    Fiendishly clever.
  • agsags Posts: 386
    edited 2013-04-10 15:09
    This topic just won't resolve...

    What happens with this?:
    DAT
      org  0
    sym0    mov sym2, #1
    sym1    mov sym3, #2
    ...
    sym2    long      0
    sym3    byte      0
    sym4    byte      0
    sym5    long      0
    

    Here's my thinking -

    Since DAT blocks define initialized data, it exists in hub RAM (other than when using the RES directive). Each symbol has to resolve to a hub address as it can be accessed using @<symbol> syntax in SPIN. The long/word/byte keywords designate alignment (and/or size).

    IF this DAT block is loaded into cog RAM and launched, it is directly copied as laid out in hub RAM, beginning with the entry point (in this case, at @sym0). In hub RAM sym3 and sym4 are byte aligned - so they occupy consecutive bytes in hub RAM. But in cog RAM, sym3 and sym4 contents are contained in a single (long) register - immediately following sym2. Yet the assembly pointer for sym4 is sym3+1 (or is it? If not, then both will resolve to the same cog location, and neither will result in the byte value that was most likely intended but a long with the two byte values in the low word). Moreover, every label following sym3 will be off-by-one. So even if the miscreant byte-aligned locations are not used, they will cause all following locations to be incorrect. (DAT block contents are not reordered as VAR blocks are).

    I can't test this as I am on a Mac and can't run Propeller tool. What the heck happens in this case? Am I missing something?

    If this accurately describe what will happen, in addition to "make sure RES directives are after all instructions and long aligned locations", there should be a "avoid byte/word aligned locations in any DAT blocks that will be launched in a cog" in the tips & tricks document. (or was it tricks & traps?)
  • Heater.Heater. Posts: 21,230
    edited 2013-04-10 15:18
    ags,

    .
    ..This topic just won't resolve...

    No it won't. You mentioned "@". That thing means different thing depending on where you use it. For this reason there is "@@" which does not help and if I remember corectly BST has an "@@@". Give me strength.
  • agsags Posts: 386
    edited 2013-04-10 16:01
    Heater. wrote: »
    No it won't. You mentioned "@". That thing means different thing depending on where you use it. For this reason there is "@@" which does not help and if I remember corectly BST has an "@@@". Give me strength.

    Yes, I now understand when/why/how to use "@@". Didn't want to, but do now.

    I shouldn't have spoken so loosely: "This won't resolve" really means "I keep coming up with things that could be landmines that I didn't know about". While I do enjoy mastering technical content, the driver behind all this thinking/fretting/posting is that I am battling an insidious hang in my current project and I've looked at every line of code over and over. It has symptoms of memory overrun, but is hard to reproduce and so far impossible to debug.
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-10 16:57
    sym3/sym4 will occupy the same cog register. sym5 (being a long) goes into the next one (even in hub because it gets aligned according to type), i.e.
    '                         hub     cog
    sym2    long      0    'DAT+$10  $002
    sym3    byte      0    'DAT+$14  $003
    sym4    byte      0    'DAT+$15  $003
    sym5    long      0    'DAT+$18  $004
    
  • agsags Posts: 386
    edited 2013-04-10 17:21
    Wow. So the assembler is smart enough to determine the actual layout in cog RAM and determine the proper location (for each symbol)? Does that extend to other more complex syntax, like:
    DAT
    symComposite  byte $F0[13], long $FF00FF00, $55, word $AABB, $CCCCCCCC
    
    That would be one less land mine to worry about (although it does require a bit of thought to keep the aliased labels and what they will really contain straight).

    Sure wish I could solve my memory problem...
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-10 17:27
    ags wrote: »
    DAT
    symComposite  [COLOR="#FF8C00"]byte[/COLOR] $F0[13], [COLOR="blue"]long[/COLOR] $FF00FF00, $55, [COLOR="blue"]word[/COLOR] $AABB, $CCCCCCCC
    
    Careful here! long and word are only alignment modifiers for byte (same line). IOW you end up with 13x $F0, an unaligned long $FF00FF00, a $55, an (un)aligned word $AABB and finally a single byte $CC (silently masked, primary type is still byte).

    To clarify, if you want greater-than-byte-and-aligned elements in your table they have to be in a separate line (e.g. [post=1176542]#18[/post]).
  • agsags Posts: 386
    edited 2013-04-10 18:12
    You described it very clearly, (thanks for verifying my work :smile:) - and that is exactly what I was trying to specify in my example. In other words, I tried to include all the esoteric data-table-creation tricks I've learned about. Bottom line is that there is one assembly pointer for symComposite, and the following line would have a pointer value of symComposite+ceil((13+4+1+2+1)/4.0) = symComposite+6 - if it was to accurately reflect the way the data is laid out in hub and cog RAM. The way I think of it is "byte" is the alignment specification, and the "long" and "word" on the same line are size specifications.
Sign In or Register to comment.