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)offsetBranches 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-Format | code | description | |||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
signed | unsigned | ||||||||||||||||||||||||||
brunconditional
| beq | a == b | a equals b
| bne | a != b | a not equal to b
| blt | bltu | a < b | a less than b
| bgt | bgtu | a > b | a greater than b
| ble | bleu | a <= b | a not greater than b
| bge | bgeu | a >= b | a not less than b
| |
pseudo-instruction |
blt rA, rB, label
if (signed) rA < (signed) rB | then PC = PC + 4 + se(IMMED16) |
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.
The unconditional branch instruction
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.
Download: branch.zip.
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: }
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