tags:

views:

380

answers:

4

Hi everyone:

I'm puzzled by this problem when writting an ARM assembly simulator in C. I've found some similar questions in the forum, but none of them explain how to set the carry flag just using the relationship between two operands and the result.

Any reply is appreciated. Thanks in advance.

Regard.

+4  A: 

The carry flag gets set in the normal way, e.g. as the result of an addition which generates a carry. You can then use an ADC (add with carry) instruction to propagate this carry into a high order word, e.g. when doing a 64 bit add:

ADDS    r4, r0, r2    ; add least significant words
ADC     r5, r1, r3    ; add most significant words with carry

In this example the 64 bit value in r4:r5 is equal to the sum of the 64-bit values in r0:r1 and r2:r3.

On early versions of ARM you could set the carry flag explicitly like this:

ORRS R15,R15,#&20000000

or like this:

TEQP R15,#&20000000

See this tutorial for more info: http://www.peter-cockerell.net/aalp/html/ch-3.html

Apparently newer versions of ARM have moved the carry flag to a different register (see comments below).

Paul R
And it's set when there's a borrow during subtraction too.
Skizz
@Skizz: actually I think C is *cleared* when there *is* a borrow, and *set* when there is *no* borrow. As with addition, this allows `SBB` (subtract with borrow) to be used when you need to propagate the borrow to a higher order word.
Paul R
The status flags haven't been in the top bits of R15 for a very long time. In architecture v4 and later (and possibly earlier ones too) they are in the CPSR register, accessed via the MSR and MRS instructions.
Mike Seymour
@Mike: thanks for the update - I don't know what ARM version the OP's simulator emulates but I'll add a comment to my answer to avoid confusion.
Paul R
+3  A: 

You have to check the reference manual for the processor to know which instructions set the carry flags and in which way. I don't know enough about ARM, but I've seen some variations in other processors:

  • some instructions which logically generates a carry may not set the carry flag

  • some instructions may use the carry flag with as some additional implicit operand or result without having a connection with addition/subtraction

  • after a subtraction, processors vary in which condition the carry flag is set (i.e some do it in the same way as after the addition of an inversed second operand, the other set it to the negation of that)

If what you want is a way to see if a carry should be generated for an addition in C, here are two ways (the first is straight from definition, the second comes from wrap around behavior of unsigned):

unsigned w1, w2, result;
int carry;

carry = w1 > UINT_MAX-w2;

result = w1 + w2;
carry = result < w1;
AProgrammer
+2  A: 
dwelch
@dewlch: Thanx!:-)
Summer_More_More_Tea
+2  A: 

Check out the ARM Architecture Reference Manual (affectionately referred to as the "ARM ARM"). You may need a login these days, but they're free (just behind a "promise not to sue us" agreement).

The ARM ARMs have detailed information about when the C bit is set and cleared for each instruction in pseudocode form. In the ARMv5 ARM, for ADCS, you have e.g.

C Flag = CarryFrom(Rn + shifter_operand + C Flag)

...and they cover both ARM and Thumb instruction set instructions.

(You'll note that almost all arithmetic Thumb-mode instructions set the condition code flags including the carry bit always; the ARM-mode ones mostly don't unless they have the S flag set.)

(Also, my info might not be current; I'm most familiar with the ARMv5TE architecture.)

leander
yes, most of the thumbs are tied to the S versions of the arm instruction, meaning most modify the flags. Arm instructions have an S bit allowing the programmer to choose to modify the flags or allow if-then-else type code without having to branch.
dwelch