CMP and SUB instructions of ARM CPU.

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View

Somewhere in the specifications of ARM CPUs
it states that CMP is like a SUB instruction
without register overwrite...

  mov  r0,0
  mov  r1,1
  cmp  r0,r1

As "cmp r0,r1" is equivalent to
"sub r0,r0,r1" (without writing r0)
and equivalent to "r0-r1"
then the Carry flag (C) should be set in this example,
but IT IS NOT, at least for the CMP instruction.

This means that the CS (Carry Set) and CC (Carry Clear)
condition codes must be interpreted inverted:
CC == "r0 unsigned lower than r1", (normally r0 > r1)
CS == "r0 unsigned higher or same than r1", (normally r0 <= r1)

This leads to weird condition codes for
comparing and branching, for people that
have been programming i86 and 68000.

Is this a specification fault of ARM?

H.Samso (

Re: CMP and SUB instructions of ARM CPU.

Quoted text here. Click to load it
Quoted text here. Click to load it

It's not wrong, it's just different. ARM uses C as a NOT-borrow flag for
subtraction operations. Yes, it's different from some architectures, but
it's the same as others, notably the 6502 (which was the previous
architecture used by ARM's original designer, Acorn Computers).

This behaviour is also entirely consistent with ARM's RISC philosophy: when
the C flag is defined in this way, the only difference between ADC and SBC
is that the second source register is NOTted for SBC.


Re: CMP and SUB instructions of ARM CPU.

Quoted text here. Click to load it

Then the specification would better state (in the next revision)
that it offers a Borrow (B) flag when using SUB, and that it is
a Carry (C) flag when using ADD. For unsigned, at least.

Because, when using ADD with the 2complement of the substractor,
and substractor is higher, the Carry is not set (Borrow). But if the
substractor is lower, and adding its 2complement, the carry is set

Borrow is the inverted Carry:
r0 < r1: r0 + complement2(r1)  -> Carry Clear
r0 > r1: r0 + complement2(r1)  -> Carry Set

You mean that when using SUB it negates the Carry,
very advanced. :)
Maybe it uses a complement2() and Add() the ARM processor, when
instructing a SUB.

H.Samso (

Re: CMP and SUB instructions of ARM CPU.

Quoted text here. Click to load it

Basically the Carry flag is just the carry-out of the 32-bit adder (ie. bit 32).
There is no borrow flag or anything similar. The ARM-ARM explicitly states
that subtract is done by inverting the input and forcing the carry input flag to
You're right that the meaning of that carry flag depends on the operation you've
done, after an add it gives you unsigned overflow, after subtract it tells you
which operand is larger. If you use CC/CS for add, and LO/HI/LS/HS for sub
then you can avoid having to think about the details...

Quoted text here. Click to load it

All ALUs use ones-complement and set the carry-in to implement subtract.
This is almost the same as your complement2() except when both operands
are zero (0 + 0 gives carry clear, 0 - 0 gives carry set).


Site Timeline