====== PIC18: branch instructions ====== {{:pic18_branch:tux-ascii.png |}}Skimming through the PIC 18F4550 istruction set we can see, among others, a bunch of //branch// instructions. What are they for and what's their relationship with the STATUS register? Let's see them in practice using some assembly code examples. This will also be a nice occasion to do a bit of simple HEX math. ===== Branch instructions ===== **BC** - Branch if Carry **BN** - Branch if Negative **BNC** - Branch if Not Carry **BNN** - Branch if Not Negative **BNOV** - Branch if Not Overflow **BNZ** - Branch if Not Zero **BOV** - Branch if Overflow **BRA** - Branch Unconditionally **BZ** - Branch if Zero Those instructions make the program counter (PC) jump to another part in the program code **on the evaluation of the STATUS register** (that's not true for the //BRA// instruction which branches //unconditionally//). So it's important to understand the various flags of this register and how they are affected by the execution of other instructions; for this purpose we are going to use a great piece of Windows software named //PIC18 Simulator IDE//, which runs fine under Linux thanks to Wine. ===== The STATUS register ===== {{:pic18_branch:pic18-status-register.png|}} Every flag in the STATUS register can be intercepted by the correspondent branch instruction; let's see this in practice. This is the first code we are going to assemble and load onto PIC18 Sim: processor 18F4550 INCLUDE testreg equ 0x00 org 0x00 goto Start org 0x08 nop org 0x18 nop Start movlw .1 movwf testreg ; Main loop Main movlw .4 addwf testreg bra Main END //testreg// is defined as a file register located at 0x00 and loaded with .1 Then what the Main loop does is adding the value .4 to it over and over again to see how that's reflected on the STATUS register. ==== Digit carry bit ==== The values that //testreg// goes through are: 1h, 5h, 9h, Dh. Let's stop here and do the next operations by ourselves. 0Dh + 04h = ___ 11h There is a //carry// for the lower //nibble//, which is added to the higher nibble; it is called a **digit carry** and that situation is reflected on **bit 1** of the STATUS register: {{:pic18_branch:pic18-sim01.png|}} ==== Overflow and negative bits ==== Let's go on and keep adding .4 to //testreg// until we come to the value 7Dh and do the math: 7Dh + 04h = ___ 81h Like before we have a //digit carry// (a carry resulting from the addition of the lower nibbles) ; as for the higher nibble, its most significant bit is on and that corresponds, in 2's complement notation, to a **negative number**: that turns on **bit 4** of the STATUS reg. > That alone doesn't make the number //negative//; it all //depends on the instruction// that uses the operand (the register) to //interpret it as a signed number or a positive one//. There is also an **overflow**, a condition which is met when there is a //change in the sign//, from positive to negative as in this case: **bit 3** is therefore also on. {{:pic18_branch:pic18-sim02.png|}} ==== Carry bit ==== In the next situation testreg is now FDh: FDh + 04h = ____ 101h The result i 101h, but since testreg, as all GPRs, is an 8 bit register the leading '1' is truncated and 01h is instead saved; both the higher and lower nibble had a carry, so **bit 0** (**carry**) is also on: {{:pic18_branch:pic18-sim03.png|}}> The Carry bit (but //not// the Digit Carry) is also affected by //register rotate instructions// like //RLCF (Rotate Left f through Carry)// and //RRCF (Rotate Right f through Carry)//: {{:pic18_branch:pic18-rlcf.png|}} Start movlw .1 movwf testreg ; Main loop Main rrcf testreg,F bra Main {{:pic18_branch:pic18-sim05.png|}} ==== Zero bit ==== This should be simple; for example: Start movlw .255 movwf testreg ; Main loop Main incf testreg,F bra Main {{:pic18_branch:pic18-sim04.png|}} We can see that **bit 2**, the STATUS bit that intercepts operations which lead to a result equal to Zero, is turned on, but also bit 0 (Carry) and bit 1 (Digit Carry). Let's try to explain that: FFh + 01h = ____ 100h When we sum the lower nibbles (Fh + 1h) we have a carry, so Digit Carry bit is on; the carry is then added to the higher nibbles (1h + Fh + 0), which makes the Carry bit on. ==== Borrow and Digit borrow bits ==== Carry and Digit Carry bits are affected by additions; but **when numbers are subtracted they become Borrow and Digit Borrow bits, which are //active low//**; this means that **when there is a borrow the bits are //off//**. Start movlw .1 movwf testreg ; Main loop Main decf testreg,F bra Main In the above example the subtraction is: 01h - 01h = ___ 00h First the lower nibbles are subtracted (1h - 1h); there's no borrow so Digit Borrow bit (**bit 1**) is //on//; then the higher nibbles are subtracted (0 - 0): no borrow so Borrow bit (**bit 0**) is //on//: {{:pic18_branch:pic18-borrow.png|}} (Zero bit - bit 2 - is also on) If we go further with the next subtraction: 00h - 01h = ___ FFh The lower nibbles are subtracted: there's a need for borrow (Digit Borrow bit //off//), which is also needed in turn by the higher nibbles (Borrow bit //off//): {{:pic18_branch:pic18-borrow02.png|}} (Negative bit - bit 4 - is also on) With the following subtraction only the Digit Borrow bit is affected and so it is turned //off//: F0h - 01h = ___ EFh {{:pic18_branch:pic18-borrow03.png|}}