0

Still looking at ARM assembler semantics (and, I try hard to read the specification, I ensure you!!!). I have some doubts about the ARM bit-shift instructions in general and RRX in particular.

Lets start with RRX.

From Davespace, Introduction to ARM, section Barrel Shifter, we see that RRX correspond to:

RRX: Barrel RollRotate Right Extended

I suppose the C to be the carry flag found in the CPSR, is it correct ?

Second question, in the case of the following instruction:

ands   r9, r0, r0, ror #3

I read that the carry flag (C) is set to the value of the last bit shifted out by the shifter operand (here ROR).

My problem is that the ands is also supposed to update the CPSR because of its flag s. So, who is winning at the end ? And, what is left in the final carry flag ? The value resulting of AND or the value resulting of ROR ?

1
  • I know that I should try, but I have no easy ARM platform with a debugger at hand reach by now... (though an ARM QEmu could do it as well...).
    – perror
    Aug 13, 2014 at 13:50

1 Answer 1

3
  1. Yes, C is the carry flag.

  2. C is set from the result of the ROR operation.

Pseudocode of the AND (register) instruction from the ARM ARM:

if ConditionPassed() then
    EncodingSpecificOperations();
    (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
    result = R[n] AND shifted;
    if d == 15 then // Can only occur for ARM encoding
        ALUWritePC(result); // setflags is always FALSE here
    else
        R[d] = result;
        if setflags then
            APSR.N = result<31>;
            APSR.Z = IsZeroBit(result);
            APSR.C = carry;
            // APSR.V unchanged

As you can see, APSR.C is set to the result of the shift operation, not the AND operation.

Now, AND is pretty straightforward but in case of e.g. ADD you may have carry affected by both the shift and the add. So what happens? Again, ARM ARM to the rescue:

if ConditionPassed() then
    EncodingSpecificOperations();
    shift_n = UInt(R[s]<7:0>);
    shifted = Shift(R[m], shift_t, shift_n, APSR.C);
    (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
    R[d] = result;
    if setflags then
        APSR.N = result<31>;
        APSR.Z = IsZeroBit(result);
        APSR.C = carry;
        APSR.V = overflow;

The answer: the add "wins" and the carry of the shift operation is discarded.

BTW, a good page to check what happens for each concrete instruction is here. For example:

ands r9, r0, r0, ror #3
machine code: E01091E0
...
cpsr.N  ←   (r0 AND r0 ROR 3)<31>
cpsr.Z  ←   r0 AND r0 ROR 3 = 0
cpsr.C  ←   #CARRY (ROR_C (r0,3))
r9  ←   r0 AND r0 ROR 3
r15 ←   r15 + 4


adds r9, r0, r0, ror #3
machine code: E09091E0
...
cpsr.N  ←   (r0 + r0 ROR 3)<31>
cpsr.Z  ←   r0 + r0 ROR 3 = 0
cpsr.C  ←   #CARRY (AddWithCarry (r0,r0 ROR 3,False))
cpsr.V  ←   #OVERFLOW (AddWithCarry (r0,r0 ROR 3,False))
r9  ←   r0 + r0 ROR 3
r15 ←   r15 + 4
1
  • Igor, if I meet you in real life at some point, remember me to offer you a drink (what ever you want!). :-)
    – perror
    Aug 13, 2014 at 14:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.