|
In the ARM instruction encoding, every arithmetic and logical instruction is "conditional". The destination register is either updated or not depending on the four bit condition field and the state of the condition flags in the processor. As a simple contrived example, consider the following C code: int a[100], b[100], count;
...
for (int i=0; i<100; i++) {
if (a[i] > b[i]) count++;
}
without conditional execution, one might compile this to code that uses a branch to either increment count or not; on ARM it would be more idiomatic to use conditional execution. Here's a very literal translation as an example (not tested, apologies for any inadvertent errors): // setup: a in R0, b in R1, count in R2, i in R3.
loop: LDR R4, [R0, R3, LSL #2] // load a[i]
LDR R5, [R1, R3, LSL #2] // load b[i]
CMP R4, R5 // if a[i] > b[i]
ADDGT R2, R2, #1 // count++
ADD R3, R3, #1 // i++
CMP R3, #100 // if (i < 100)
BLT loop // continue loop
The fourth instruction, ADDGT, is conditional. Count is only updated with the result of the addition if the "greater than" condition is satisfied (the flags were set by the preceding instruction). To be more precise, all of the instructions here are conditional, it's just that for most of them the condition field is 1110, meaning "always".Many instructions also have an "S" bit, which toggles whether or not they update the flags on which conditional execution depends. Taken together, these two features allow a clever assembly programmer to do some really clever things (but historically not too much effort has been directed at getting compilers to make really clever use of these features). For low-power parts, this is a cute trick, as it allows a programmer to avoid stressing a limited branch predictor with lots of small branches. It does add some complication to the implementation however, especially when you get into designs that retire multiple instructions per cycle or support out-of-order execution, as conditional execution basically adds additional dependencies to every instruction. |