I think the main subtlety is that the correct method of performing compares changes between signed and unsigned values, and between single-byte and multi-byte values. The ARM generates status flags according to the same rules (modified for the much wider ALU), but has a much richer array of branch instructions (actually, condition field values that can be applied to most instructions, not just branches) which make dealing with signed values far more convenient:
Code:
Code | Meaning | Test | 6502 equivalent
====================================================
EQ | equal | Z | BEQ t
NE | not equal | !Z | BNE t
CS | unsigned >= | C | BCS t
CC | unsigned < | !C | BCC t
MI | negative | N | BMI t
PL | not negative | !N | BPL t
VS | overflow | V | BVS t
VC | not overflow | !V | BVC t
HI | unsigned > | C & !Z | BEQ *+4 : BCS t (or reverse operands and use BCC)
LS | unsigned <= | !C || Z | BCC t : BEQ t (or reverse operands and use BCS)
GE | signed >= | N == V | BMI *+6 : BVC t : BRA *+4 : BVS t
LT | signed < | N != V | BPL *+6 : BVC t : BRA *+4 : BVS t
GT | signed > | !Z && N == V | BEQ *+10 : BMI *+6 : BVC t : BRA *+4 : BVS t
LE | signed <= | Z || N != V | BEQ t : BPL *+6 : BVC t : BRA *+4 : BVS t
The above table works only for comparing single-byte operands (though on the '816 you can also use it for 16-bit compares). For multi-precision compares, the correct method is to refer to the above table for the most-significant byte, but if they are equal you must defer the result of the comparison to an
unsigned compare of the next significant byte, and so on if there's more than two.
The PowerPC takes a rather different approach to this: the three status flags are equivalent to Positive (or Greater), Zero (or Equal), and Negative (or Less). There are distinct signed and unsigned compare instructions to generate these flags correctly. For floating-point comparisons there is a fourth flag meaning Unordered.