Something else the HC11 does, which is very common, is to use the C bit to mean ``Borrow'' for a subtract or a compare.
Put them together, and it means you do branches by somehow getting the relevant information into the condition codes (ideally as a side-effect of some other computation that was necessary anyway), and then use an appropriate branch instruction.
Here's an example: let's assume we have a pair of signed integers in
the a
and b
accumulators, and we want to end
up with the smaller of the two in the a
accumulator. We
don't care what ends up in the b
accumulator; this isn't
a swap. We can do it like this:
cba * a - b
ble noswap * branch based on results of compare
tba * copy b into a
noswap
Here's another example: we want to compute the sum of the integers
from one to b
, where b
is the integer in the
b
accumulator. We'll assume b
is non-zero.
We can do this with a loop:
clra * a = 0
loop * do {
aba * a = a + b
decb * b = b - 1
bne * } while (b != 0)
Notice that this time, we didn't explicitly do a compare. We relied
on the fact that the decb
instruction would set the
condition codes for us.
Here's a table showing the full set of branch instructions on the HC11:
Positive Form | Negative Form | ||||
---|---|---|---|---|---|
Mnemonic | Description | Boolean Expression | Mnemonic | Description | Boolean Expression |
Unconditional | |||||
bra |
Branch Always | 1 | brn |
Branch Never | 0 |
Single Condition Code | |||||
bcs |
Branch Carry Set | C = 1 | bcc |
Branch Carry Clear | C = 0 |
bmi |
Branch Minus | N = 1 | bpl |
Branch Plus | N = 0 |
bvs |
Branch oVerflow Set | V = 1 | bvc |
Branch oVerflow Clear | V = 0 |
beq |
Branch Equal (to 0) | Z = 1 | bne |
Branch Not Equal (to 0) | Z = 0 |
Signed Branches | |||||
blt |
Branch Less Than | N ^ V = 1 | bge |
Branch Greater Than or Equal | N ^ V = 0 |
ble |
Branch Less Than or Equal | (N ^ V) | Z = 1 | bgt |
Branch Greater Than | (N ^ V) | Z = 0 | Unsigned Branches |
blo |
Branch Lower | C = 1 | bhs |
Branch Greater Than or Equal | C = 0 |
bls |
Branch Less Than or Equal | C | Z = 1 | bhi |
Branch Higher | C | Z = 0 |
Notice a few things: bpl
is misnamed - it really
branches on non-negative. There are two instructions in the table
that appear twice each! I don't really know why the brn
instruction exists. My suspicion is that, since all the other
branches have both a positive and a negative form, it was just easier
to build it into the instruction set than to leave it out. It can
also be useful in timing loops; since a nop
takes two
cycles and a brn
takes three, you can delay for any
number of cycles you want (greater than one).