asymmetry between rd[long,word] and wr[long,word]
ags
Posts: 386
Every time I find something that seems odd, there's been a good reason behind it. I suspect this is no different.
Can anyone explain the thinking behind the PASM hub RAM read/write instructions? Specifically, the rdlong and rdword instructions clear the 2- and 1-LSbit of the address to be read, ensuring a long- and word-aligned destination (respectively). However, (per the documentation) the wrlong and wrword instructions do not do this (or it isn't stated that they do - I can't test at the moment as I don't have a Prop with me). That (apparently) means that I can write a long value to address xxx01, not long-aligned.
Thanks for any insight into this.
Can anyone explain the thinking behind the PASM hub RAM read/write instructions? Specifically, the rdlong and rdword instructions clear the 2- and 1-LSbit of the address to be read, ensuring a long- and word-aligned destination (respectively). However, (per the documentation) the wrlong and wrword instructions do not do this (or it isn't stated that they do - I can't test at the moment as I don't have a Prop with me). That (apparently) means that I can write a long value to address xxx01, not long-aligned.
Thanks for any insight into this.
Comments
-Phil
Phil:
This is the first time I've seen (or understood) this. I suspected it (don't know how the hardware would implement arbitrary read/write alignment/size, implying no inherent boundaries in memory at all) but now it's clear. This is a good example of how (for me) understanding the details of the underlying hardware is very helpful in avoiding problems. I can now just keep in mind that memory (even hub RAM) is really long-aligned. In other words, accessing a byte really accesses a long (masking the 2 LSbits to determine the "container long" to access, and then the 2 LSbits are used to mask and shift bits appropriately). Is this the way the SPIN interpreter is implemented?
One other way of saying this, more simply and clearly: hub RAM is just as long-aligned as cog RAM. SPIN provides an illusion of byte- or word-level access by handling the masking/shifting that is done manually in PASM code.
This has resurfaced as a topic of interest for me as I am doing more advanced (or maybe just risky, poor design) work. For instance, I define a VAR byte array. So that is (only guaranteed to be) byte aligned. But I pass the address in to a PASM driver (using a "mailbox", not par, so all 16 address bits are intact). To speed up hub RAM r/w, I aways r/w using RD/WRLONG, rather than RD/WRBYTE four times. You can see the problem - made worse because there is a one-in-four chance that it will actually work, depending on ordering of the VAR block symbols. Ouch.
2) The SPIN interpreter doesn't do anything special with this. Byte variables are accessed using xxBYTE instructions and word variables are accessed using xxWORD instructions and the hardware takes care of the rest.
3) Yes, you will run into trouble if you use xxLONG to access values that are not aligned on 32-bit boundaries. You will also run into trouble if you use xxWORD to access values not aligned on 16-bit boundaries.
4) This is often solved by allocating your "fast" buffers as LONG arrays and accessing them using xxBYTE instructions and .BYTE[n] suffixes (like myLongArray.BYTE[n]). This will force SPIN to use its byte interpretive codes to access the individual bytes in the array and "n" is considered a byte index.
The reason I declared the array a byte array is because I do access it in SPIN, and I wanted to avoid the tedious (IMO) need to use the byte[base][offset] syntax everywhere. (I realize I can also just use base+offset to calculate the address directly). I posted in a separate thread in hopes there was some way around this (like a C typedef) but no one had a solution to offer.
I suppose one way around this would be to ensure that the array is the first byte aligned symbol in the VAR section. That strikes me as pretty fragile and error prone, though. At least I understand it now though.