This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

ASR #32

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.

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?

  • There's a difference in the flags set. The carry bit depends on the last bit shifted out so 0x80000000 ASR #31 will be 0xFFFFFFFF with carry clear whereas 0x80000000 ASR #32 will have the carry bit set.

  • No problem you're welcome - and you can award the points to yourself instead if you can think of a single vaguely useful use for the difference or either of the variants!

  • 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.

    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'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.