Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion about ARM documentation on carry flag

In the ARM documentation here, it says that:

A carry occurs:

... if the result of a subtraction is positive or zero ...

I know from this answer on SO that the carry flag is set in subtraction when there is unsigned underflow (ie the number being subtracted (subtrahend) is greater than the number that is being subtracted from (minuend)).

So consider the example:

r1 = 5
r2 = 10
CMP r1, r2

Compare (CMP) does a subtraction as mentioned here and then sets the appropriate flags. In this case, r1-r2 = 5-10 = -5. Since we have unsigned underflow here (5 < 10), we expect the carry flag to be set. But according to the ARM documentation, the result (-5) is not positive or zero, so the carry flag should not be set. (Assuming we look at the result signed; otherwise a carry would never occur according to the documentation).

Is the ARM documentation wrong? What's my misunderstanding?

like image 284
takanuva15 Avatar asked Oct 30 '18 13:10

takanuva15


2 Answers

ARM uses an inverted carry flag for borrow (i.e. subtraction). That's why the carry is set whenever there is no borrow and clear whenever there is. This design decision makes building an ALU slightly simpler which is why some CPUs do it.

like image 158
fuz Avatar answered Oct 20 '22 02:10

fuz


we dont need all 32 bits to show what is going on with a subtraction

5 - 3

from gradeschool we know that 5 - 3 = 5 +(-3) which is how it is done in logic, a feature of twos complement is to get to -3 you invert and add one so

5 - 3

      1
   0101
 + 1100
=========

finish it

  11011
   0101
 + 1100
=========
   0010

so generically (not processor specific) 5 - 3 = 2. the carry in and carry out of the misbit are both one so the signed overflow would be not set the carry out is a 1. But some architectures as well as inverting the second operand and the carry in (to the lsbit) also invert the carry out calling it a borrow. Some dont.

Some document this when you look at things like greater than and less than as to what the definition of the carry bit is

5 - 4

  11111
   0101
 + 1011
=========
   0001

5 - 5

  11111
   0101
 + 1010
=========
   0000

5 - 6

  00011
   0101
 + 1001
=========
   1111

5 - 7

  00011
   0101
 + 1000
=========
   1110

What this is showing is that if you look at the raw carry out it switches when operand b equals operand a, when b is less than a it is set when b is equal to or greater than a it is clear. So then if the architecture leaves it unmodified you can use the carry bit for unsigned greater than or less than (but not equal) in one of the cases greater than or equal is defined by that flag and which direction depends on the architecture (if it inverts carry out into a borrow). the other direction you either flip the operands and use the one bit or you use N and C to determine something than or equal.

The arm docs unlike some others show you for each of the conditionals what the flags are and knowing the above or being able to repeat it in a simple test you can figure out if they invert or dont. the instruction sbb is subtract with borrow rather than sbc subtract with carry which sorta, but not by itself implies how that instruction set interprets the bit.

like image 34
old_timer Avatar answered Oct 20 '22 03:10

old_timer