Hardware bug: AUGS + ALTS doesn't clear internal AUGS flag
Wuerfel_21
Posts: 5,059
in Propeller 2
Just something to be aware of. And perhaps fix in whatever the next rev is @cgracey
CON _CLKFREQ = 10_000_000 DAT org mov pb,#someval alts pb,##1024 mov sometmp,0-0 nop nop mov pa,#0 sub pb,#someval debug(uhex_long(pa),uhex_long(pb)) jmp #$ someval long $DEADBEEF sometmp res 1
Results in pa = $0000_0400
and pb = $0000_0002
. The value for PB is as expected (ALTx autoincrement), but PA should obviously be zero, but isn't because it gets the high bits from the AUGS that is supposed to apply to ALTS only.
Comments
AUGS + ALTS seems to make no sense.
What is final value of someval sometmp?
It makes total sense: for AUGS, S is the base pointer and autoincrement amount. With an unaugmented immediate, the autoincrement field is always zero.
sometmp is set to someval (so $DEADBEEF), but that's not interesting.
You are using the address of someval not the value DEADBEEF when you move into pb, and subtract later. This might be $A if the debug instruction takes one long. Doesn't affect the result for PB, but is a little confusing.
Still it doesn't really explain the PA result unless ALTS leaves the AUGS flag alone or something weird like that.
That that exact weird thing happens is the point of the post. AUGS is applying to both the ALTS and whatever immediate op comes after (the move into pa, in this case)
Cool! I hadn't tested that one before.
The ALTS behaviour is known correct. ALTx instructions are excluded from AUGmenting. What I didn't know is that an unused AUGx state can stay primed until there is a use for it. In this case the first instruction that can consume the AUGS value is the
mov pa,#0
. It's surprising that themov sometmp,0-0
doesn't consume the AUGS state/value but I guess it must require immediate addressing to be consumed.If that's all true (I don't have a Prop2 with me to test with.) then this can be used in some neat ways me thinks.
What is interesting here is how long AUGS "stays alive", until there is an instruction with immediate S that can be AUGmented.
It needs to be documented at least.
Hehe, it does have a one-liner in the spreadsheet where it does explicitly say next 9-bit #S ...
Oh, that's another IRQ staller too. Like using REP as a code protect, an AUGx prevents branching to ISR until consumed.
The funny is that the ALTS is being augmented (otherwise pb would end up as zero), but it doesn't actually consume the AUGS.
Also, I assumed that AUGx stick around until used was common knowledge.
Hmm, I see. So the following will be PA = $0000_0400 and PB = 0, I presume?
I had thought only ALTx instructions postponed AUGx instructions. But clearly they're more flexible.
You have the right idea, but the assembler syntax is a bit weird in that you have to do
AUGS #2<<9
Then it will indeed have your predicted result.
More accurate to say that ALTS D is incremented (or decremented), rather than ALTS is augmented.
How so? The higher bits of S being added to D is a normal thing, you just can't do it with a short immediate. I've always used that feature in tight loops where I hoisted the S value into a register, so that's why I never noticed the issue with AUGS before.
Funnily, I can't find documentation saying that AUGx instructions are ignored by ALTx instructions.
Because they don't. It's more like "AUGx ignores ALTx, but not the other way round", I guess
Chip did talk about it long time ago. I wasn't following too closely though so may have miss-understood intent.
I understand the point you are making, namely that you don't want AUGS to take effect in some later instruction, but ALTS D,S is the same code size and two cycles faster than ALTS D,##S and avoids the AUGS + ALTS issue.
The question is less what Ada expected in the example, but more around what did Chip intend originally, and is it doing so. Then secondly, what can be done with the new knowledge of how it actually works - which appears to be different to everyone's expectations.
@cgracey Could this perhaps be added to the "Known Bugs" bit of the silicon doc?
Just scrolled by that again and thought this should probably be there.
Yes, I'm glad you discovered this. I will look at the Verilog source code tomorrow to figure out why this is happening.
By the way, this...
debug(uhex_long(pa),uhex_long(pb))
...could be shortened to this...
debug(uhex_long(pa,pb))
I realized this, too. Didn't work in flexspin's debug implementation until then (though it was actually Eric who fixed it)
Indeed, AUGS is intentionally not consumed by ALTx instructions, but I forgot to inhibit the AUGS value from augmenting an ALTx #S.
I'll make a note of this in the Google P2 Silicon doc.
I also made a note in the Verilog code to fix this in any future silicon version, so that ALTx #S does not use the AUGS value. The fact that it does use the AUGS value undermines ALTx #S operation.