63. Decrement and Branch Conditionally

63.1. Name

DBcc -- Decrement and branch conditionally

63.2. Synopsis

        DBcc        Dn,<label>

        Size of offset = (Word)

63.3. Function

Controls a loop of instructions. The parameters are: a condition code, a data register (counter), and an offset value. The instruction first tests the condition (for termination); if it is true, no operation is performed. If the termination condition is not true, the low-order 16 bits of the counter are decremented by one. If the result is -1, execution continues at the next instruction, otherwise, execution continues at the specified address.

Condition code 'cc' specifies one of the following:

BitmapCCNameFlagsBitmapCCNameFlags
0000FFalseZ = 11000VCoVerflow ClearV = 0
0001TTrueZ = 01001VSoVerflow SetV = 1
0010HIHIghC + Z = 01010PLPLusN = 0
0011LSLow or SameC + Z = 11011MIMInusN = 1
0100CCCarry ClearC = 01100GEGreater or EqualN (+) V = 0
0101CSCarry SetC = 11101LTLess ThanN (+) V = 1
0110NENot EqualZ = 01110GTGreater ThanZ + (N (+) V) = 0
0111EQEQualZ = 11111LELess or EqualZ + (N (+) V) = 1

Keep the following in mind when using DBcc instructions:

  • A DBcc acts as the UNTIL loop contruct in high level languages. E.g., DBMI would be "decrement and branch until minus".

  • Most assemblers accept DBRA or DBF for use when no condition is required for termination of a loop.

The DBcc will, unlike the Bcc instruction, take the branch only if the set of conditions are NOT satified. The loop will be terminated if the condition is true, or the counter is zero BEFORE a decrement, and wrap to -1. This mean that if you execute code like:

        move.w     #30,d0

.Loop
        move.l     (a0)+,(a1)+
        dbf        d0,.Loop

then the copy will be executed *31* times, and 124 bytes of memory will be copied, not 120.

A good practice is therefore to write:

        move.w        #30-1,d0

.Loop
        move.l     (a0)+,(a1)+
        dbf        d0,.Loop

To compare two strings that may be in excess of 64k length for being equal, you could execute the following code:

        ...

        move.l      #$53452-1,d0
        beq.s       .NoLength        ; Zero length!
        bra.s       .StartOuterLoop  ; The upper word contain count of 65536's..

.OuterLoop
        swap        d0

.InnerLoop
        cmp.b       (a0)+,(a1)+
        dbne        d0,.InnerLoop    ; Remember, drop through on condition TRUE.

.StartOuterLoop                      ; d0 will be $FFFF on 2.+ run-through
        bne.s       .NotEqual        ; Dropped through due to Not Equal?
        swap        d0               ; Get upper part of word...
        dbf         d0,.OuterLoop
        ...

It would not be possible to use two sets of DBNEs, as SWAP changes the condition codes - and we don't want the drop- though to be on account of D0, instead of the compares...

Another neat trick is to use instruction as a conditional decrementer; this code will decrement d0.w if the last instruction returned NOT EQUAL:

        ...
        dbeq        d0,.Next

.Next
        ...

63.4. Format

        -----------------------------------------------------------------
        |15 |14 |13 |12 |11 |10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
        |---|---|---|---|---------------|---|---|---|---|---|-----------|
        | 0 | 1 | 0 | 1 |   CONDITION   | 1 | 1 | 0 | 0 | 1 | REGISTER  |
        |---------------------------------------------------------------|
        |                      16 BITS OFFSET (d16)                     |
        -----------------------------------------------------------------

        "CONDITION" is one of the condition code given some lines before.
        "REGISTER" is the number of data register.
        Offset is the relative gap in byte to do branching.

63.5. Result

        Not affected.

63.6. See also

Bcc Scc