Reputation: 1668
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?
Upvotes: 9
Views: 10583
Reputation: 71506
We don't need all 32 bits to show what is going on with a subtraction:
5 - 3
From grade school 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 msbit 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 don't.
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 don't. the instruction sbb is subtract with borrow rather than sbc subtract with carry which sort of, but not by itself, implies how that instruction set interprets the bit.
Upvotes: 2
Reputation: 14318
I have same confusion about:
A carry occurs if the result of an addition is greater than or equal to 232, if the result of a subtraction is positive, or as the result of an inline barrel shifter operation in a move or logical instruction
thought: 5 - 3 = 2
-> positive result
-> should C=1
?
finally found ARM official useful doc: Carry flag
In A32/T32 code, C is set in one of the following ways:
- For an addition, including the comparison instruction CMN, C is set to 1 if the addition produced a carry (that is, an unsigned overflow), and to 0 otherwise.
- For a subtraction, including the comparison instruction CMP, C is set to 0 if the subtraction produced a borrow (that is, an unsigned underflow), and to 1 otherwise.
to know:
5 - 10 = -5
-> produced a borrow
= unsigned underflow
= negative result
-> should C=0
C=1
so, conform to:
5 - 3 = 2
-> positive result
-> should C=1
Upvotes: 1
Reputation: 92966
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.
Upvotes: 10