takanuva15
takanuva15

Reputation: 1668

Contradiction in this ARM documentation on carry flag?

In the ARM documentation here, it says that:

C

Set to 1 when the operation resulted in a carry, cleared to 0 otherwise.

and

A carry occurs:

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

(Obviously the result has to be treated as a signed number; otherwise a carry would always occur with subtractions).

I know that the carry flag is "inverted" in ARM. Thus, if a subtraction requires a borrow, then the carry flag is not set even though a "carry" (ie unsigned underflow) did occur logically.

This makes sense for this scenario:

CMP 3,5

This will do 3-5. Since 3 < 5, unsigned underflow occurs and the carry flag would not be set in ARM. Using the logic in the ARM documentation, 3-5 results in -2, which is negative, so a carry doesn't occur and thus the carry flag is not set.

Now, according to the ARM documentation linked above, the LO (aka CC) condition code in ARM, which represents an "unsigned, lower" comparison, is true when the carry flag is not set in ARM (ie C == 0). Thus, for the example above, the LO condition code would be true. This makes sense too since 3 is lower than 5 when treating them both as unsigned numbers.

========

Now consider this scenario:

CMP -1,0

This will do -1-0, ie 0xffffffff - 0x00000000. Logically, since 0xffffffff > 0x00000000, no unsigned underflow occurs and the carry flag would be set.

But look at what the ARM documentation says:

A carry occurs:

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

According to the documentation above, since -1-0 results in -1, which is negative, a carry doesn't occur and thus the carry flag is not set. But this means that the LO condition code is true, which means that -1 is lower than 0 when treating them both as unsigned numbers (just like how 3 was lower then 5 when we treated them both as unsigned numbers in the previous scenario). Obviously that's not true since 0xffffffff > 0x00000000.

How do I explain this contradiction when I'm trying to calculate the carry-flag logic based off of what the documentation is saying?

Upvotes: 0

Views: 518

Answers (2)

old_timer
old_timer

Reputation: 71506

CC/LO is UNSIGNED lower not SIGNED lower. There is no -1 unsigned number it is 2^32-1, 2^32-1 - 0 = 2^32-1 and 0 is most definitely less than 2^32-1.

Now if you want to compare -1 to 0 then that is a signed comparison and go back to that table and look at flags related to signed results.

two numbers one is one bigger than the other, as written clearly want to interpret them as signed math.

-3 - -4 = -3 + 4

 11000
  1101
+ 0100
=======
  0001

N = 0 V = 0

If N == V then singed greater or same and that is true -3 is greater than -4

1100 GT Signed greater than N == V

-1 - 0 = -1 + (-0) = -1 + 0

 0000 
  111
 +000
=====
  111

N = 1 V = 0

Or what if -1 + (-0)

  1111
   111
 + 111
=======
   111

N = 1, V = 0

1011 LT Signed less than N!=V

and that is is true -1 is less than zero.

And BTW

3 - 5

 00111
  0011
 +1010
=======
  1110

Unsigned 3 - unsigned 5 is a very large number 0xFFFFFFFE two shy of 2^32

C = 1, N = 1, V = 0, Z = 0

Being unsigned C = 1 means

0010 CS/HS Carry set/unsigned higher or same

And that is true 5 is greater than 3

If you want to have unsigned higher but not same then you look at the Z flag as well

1000 HI Unsigned higher C set and Z clear

Now you were trying to argue that 3 - 5 = -2, that is clearly SIGNED math NOT UNSIGNED math. so V == Z

1100 GT Signed greater than

a signed 5 is greater than a signed 3 just like

0010 CS/HS Carry set/unsigned higher or same C set

an unsigned 5 is greater than an unsigned 3

3 - 5 = 0xFFFFFFFE

(carry set is an unsigned overflow BTW and at least in this case it works)

Upvotes: 0

Timothy Baldwin
Timothy Baldwin

Reputation: 3675

Your quote only makes sense if the input values are considered as unsigned, along with the full (33-bit) output. Note the the accompanying description refers to outputs larger than 2^32.

Upvotes: 2

Related Questions