Please note: We are aware of an issue affecting replies on the Arm Community forums, which may not be loading as expected.
We apologize for any inconvenience and appreciate your patience while we investigate and work to resolve the issue.
Thank you for your understanding.
In the SSAT instruction description it says:
ASR #32 Arithmetic right shift by 32 bits, permitted only for encoding A1. Encoded as sh = 1, immsh = 0b00000.
ASR #32 Arithmetic right shift by 32 bits, permitted only for encoding A1.
Encoded as sh = 1, immsh = 0b00000.
What does that mean?
Isn't ASR #32 the same as ASR #31?
I understand that it shifts (with "sign extension") the whole 32-bit value out and leaves only the sign extension bits
that are "copies" of the highest bit of the original value.
What am I missing here?
I'd like to add a hint: Use the ASR as operand2; perhaps with AND, ORR, BIC, EOR, ADD, SUB or another instruction. It's sometimes useful to get bit31 into the carry flag when doing math and needing to test the sign. -But beware; the rest of the instruction might also update the flags, including the carry flag.
It just tends to multiply the result by two in the process.
I was first thinking of long shift together with RRX, then I thought about how, and realized, it wouldn't work.
Now that I've been going through the instructions in case PC is used as the destination I realize that about half of the instructions look like once-in-a-lifetime instructions.
I think only compiler writers can find some use for them.
Maybe the instruction set architects took this too seriously:
http://web.mit.edu/humor/Computers/extended.opcodes
Long shift is easy; I've prepared a document about it (which is in the queue to being published; I just need to finish the ones before that one first).
-Starting from the msb end, it goes something like ... [A/L]SRS : RRX : RRX : RRX : RRX : ... : RRX
Notice: The condition codes do not need to be updated by RRX!
If you need to shift by larger amounts than just 1, then it's a good idea to use LSR and BFI only; this means you'll need to start from the lsb end.
I've found good use for them on a Cortex-M, for instance the ADD, where PC is the destination.
This can be used to synchronize an interrupt to a Timer Counter on the exact clock cycle (and daith mentions a couple of other use cases too).
-If you're in a situation, where every clock cycle is important (this usually happens when you need your device to run on very low frequencies in order to save power - or when you need to do high-speed I/O on a device), then it's important to have the "strange options", where you can find a solution to an otherwise unsolvable problem.
Starting from the msb end, it goes something like ... [A/L]SRS : RRX : RRX : RRX : RRX : ... : RRX
That's what I thought - longer shifts won't work.
BTW, nice post (the Cortex-M0 tricks).
I was rather thinking about uqadd16, uxtab, qdadd, and the like.
Not used in every program.
Well I was thinking of something simple like testing the top two bits of a register. (I haven't tested this)
MOVS r0, r1, ASR #31
BHI starts_11 ; Z clear C set
BMI starts_10
BCS starts_01
... starts_00
using MVNS you can test for 01 first.
p.s. I don't think this sort of thing makes for happy colleagues though it might ensure a living for years to come.
That definitely qualifies for a cool trick. If you want to avoid branching, you could combine it with the sbcs instruction like SBCS r3,r3,r3 after a BMI.
(or of course use conditional execution). Using it as a mask for a conditional AND would probably also be useful.
... MVNS r0,r1,asr#31 might also prove useful, if you need to invert the sign.