Branch Instructions

Branch instructions perform a test by evaluating a logical condition and depending on the outcome of the condition modify the program counter to take the branch or continue to the next instruction.

Branch instructions are always relative to the current program counter. That is, the next instruction is obtained by adding a signed offset to current program counter:

   PC += (int)offset
Branches are inherently relocatable. That is, the program can be moved to any other block of memory and still execute correctly. Jump instructions, by contrast, specify an absolute memory reference. If the underlying program is moved in memory, those jump memory references pointing to the interior of the moved block must be changed.

The table below lists the branch instructions of the Nios II computer.

I-Formatcodedescription
signedunsigned
br

unconditional
beq
a == ba equals b
bne
a != ba not equal to b
bltbltua < ba less than b
bgtbgtua > ba greater than b
blebleua <= ba not greater than b
bgebgeua >= ba not less than b

pseudo-instruction

blt rA, rB, label if (signed) rA < (signed) rB
then PC = PC + 4 + se(IMMED16)

Branch Details

Let us examine a portion of the disassembly output for our example:

    if (a<b) {
    812c:    e0c00017     ldw    r3,0(fp)
    8130:    e0800117     ldw    r2,4(fp)
    8134:    1880030e     bge    r3,r2,8144 <branch+0x40>
        return 1;
    8138:    00800044     movi    r2,1
    813c:    e0800215     stw    r2,8(fp)
    8140:    00000e06     br    817c <branch+0x78>
    }
    if (a<=0) {
    8144:    e0800017     ldw    r2,0(fp)

The bge destination above is 0x8144, which is 0x40 from the start of the branch function entry (0x8104).

The machine instruction is 0x1880030E. The last 12 bits are 0011_0000_1110. The opcode is 0x0e (bge) and the immediate operand is 0xC. The PC at the branch is 0x8134, add four to get the next instruction (PC+4 = 0x8138). Finally add the immediate offset (0xC) to get the branch destination 0x8144, as advertised.

In the instruction encoding, the offset given by IMMED16 is treated as a signed number of bytes relative to the instruction immediately following the branch instruction. The two least significant bits of IMMED16 are always zero, because instruction addresses must be word-aligned.

Unconditional Branch

The unconditional branch instruction

br label has rA and rB set equal to zero. This means that the instruction can be implemented as beq zero,zero,label. The unconditional branch, then, could have been a pseudo-instrucion, but it does have a separate op-code (0x06) in the Nios II processor.

Comparision vs. Branch

All branch instructions are I-type instructions. The immediate field is used to compute the branch address.

Compare immediate instructions use the immediate field as the b operand (as in a < b ).

A branch, therefore, is an I-type “compare” instruction that uses the rB register as input rather than output.

C Source

Download: branch.zip. branch.c

branch.c


01: 
02: int branch(int a, int b);
03: 
04: int main()
05: {
06:         int i, sum;
07:         int n1,n2,n3,n4;
08:         n1 = branch(5,3);
09:         n2 = branch(-2,7);
10:         n3 = branch(3,3);
11:         n4 = branch(-3,-5);
12:         sum = 0;
13:         for (i=0; i<10; i++) {
14:                 sum += i;
15:         }
16:         
17:         //printf("%d %d %d %d\n",n1,n2,n3,n4);
18:         //printf("sum = %d\n",sum);
19:         return 0;
20: }
21: 
22: int branch(int a, int b)
23: {
24:         if (a==b) {
25:                 return 0;
26:         }
27:         if (a<b) {
28:                 return 1;
29:         }
30:         if (a<=0) {
31:                 return 2;
32:         }
33:         if (a>=0) {
34:                 return 3;
35:         }
36:         return -1;
37: }


Disassembly

0000806c <main>:

int branch(int a, int b);

int main()
{
    806c:    defff804     addi    sp,sp,-32
    8070:    dfc00715     stw    ra,28(sp)
    8074:    df000615     stw    fp,24(sp)
    8078:    d839883a     mov    fp,sp
    int i, sum;
    int n1,n2,n3,n4;
    n1 = branch(5,3);
    807c:    01000144     movi    r4,5
    8080:    014000c4     movi    r5,3
    8084:    00081040     call    8104 <branch>
    8088:    e0800215     stw    r2,8(fp)
    n2 = branch(-2,7);
    808c:    013fff84     movi    r4,-2
    8090:    014001c4     movi    r5,7
    8094:    00081040     call    8104 <branch>
    8098:    e0800315     stw    r2,12(fp)
    n3 = branch(3,3);
    809c:    010000c4     movi    r4,3
    80a0:    014000c4     movi    r5,3
    80a4:    00081040     call    8104 <branch>
    80a8:    e0800415     stw    r2,16(fp)
    n4 = branch(-3,-5);
    80ac:    013fff44     movi    r4,-3
    80b0:    017ffec4     movi    r5,-5
    80b4:    00081040     call    8104 <branch>
    80b8:    e0800515     stw    r2,20(fp)
    sum = 0;
    80bc:    e0000115     stw    zero,4(fp)
    for (i=0; i<10; i++) {
    80c0:    e0000015     stw    zero,0(fp)
    80c4:    e0800017     ldw    r2,0(fp)
    80c8:    10800288     cmpgei    r2,r2,10
    80cc:    1000081e     bne    r2,zero,80f0 <main+0x84>
        sum += i;
    80d0:    e0c00117     ldw    r3,4(fp)
    80d4:    e0800017     ldw    r2,0(fp)
    80d8:    1885883a     add    r2,r3,r2
    80dc:    e0800115     stw    r2,4(fp)
    80e0:    e0800017     ldw    r2,0(fp)
    80e4:    10800044     addi    r2,r2,1
    80e8:    e0800015     stw    r2,0(fp)
    80ec:    003ff506     br    80c4 <main+0x58>
    }
    
    //printf("%d %d %d %d\n",n1,n2,n3,n4);
    //printf("sum = %d\n",sum);    DBPUTS("Program terminated. Click HALT and then RESET to stop the microcontroller. \n");
    return 0;
    80f0:    0005883a     mov    r2,zero
}
    80f4:    dfc00717     ldw    ra,28(sp)
    80f8:    df000617     ldw    fp,24(sp)
    80fc:    dec00804     addi    sp,sp,32
    8100:    f800283a     ret

00008104 <branch>:

int branch(int a, int b)
{
    8104:    defffc04     addi    sp,sp,-16
    8108:    df000315     stw    fp,12(sp)
    810c:    d839883a     mov    fp,sp
    8110:    e1000015     stw    r4,0(fp)
    8114:    e1400115     stw    r5,4(fp)
    if (a==b) {
    8118:    e0c00017     ldw    r3,0(fp)
    811c:    e0800117     ldw    r2,4(fp)
    8120:    1880021e     bne    r3,r2,812c <branch+0x28>
        return 0;
    8124:    e0000215     stw    zero,8(fp)
    8128:    00001406     br    817c <branch+0x78>
    }
    if (a<b) {
    812c:    e0c00017     ldw    r3,0(fp)
    8130:    e0800117     ldw    r2,4(fp)
    8134:    1880030e     bge    r3,r2,8144 <branch+0x40>
        return 1;
    8138:    00800044     movi    r2,1
    813c:    e0800215     stw    r2,8(fp)
    8140:    00000e06     br    817c <branch+0x78>
    }
    if (a<=0) {
    8144:    e0800017     ldw    r2,0(fp)
    8148:    10800048     cmpgei    r2,r2,1
    814c:    1000031e     bne    r2,zero,815c <branch+0x58>
        return 2;
    8150:    00800084     movi    r2,2
    8154:    e0800215     stw    r2,8(fp)
    8158:    00000806     br    817c <branch+0x78>
    }
    if (a>=0) {
    815c:    e0800017     ldw    r2,0(fp)
    8160:    1004803a     cmplt    r2,r2,zero
    8164:    1000031e     bne    r2,zero,8174 <branch+0x70>
        return 3;
    8168:    008000c4     movi    r2,3
    816c:    e0800215     stw    r2,8(fp)
    8170:    00000206     br    817c <branch+0x78>
    }
    return -1;
    8174:    00bfffc4     movi    r2,-1
    8178:    e0800215     stw    r2,8(fp)
}
    817c:    e0800217     ldw    r2,8(fp)
    8180:    df000317     ldw    fp,12(sp)
    8184:    dec00404     addi    sp,sp,16
    8188:    f800283a     ret


Maintained by John Loomis, updated Tue Sep 23 20:46:14 2008