_Sub16 COMF Acc2H ; Take two's complement
COMF Acc2L ; of Acc2. If zero, Acc2L
INCF Acc2L
BTFSC STATUS, Z ; overflowed, so carry
INCF Acc2H ; into Acc2H.
_Add16 BCF Flags, OverFlow ; clear overflow flag
MOVF Acc2L, w ; Add the LSBs. If carry,
ADDWF Acc1L
BTFSC STATUS, C ; increment MSB of sum.
INCF Acc1H
MOVF Acc2H, w ; Add the MSBs
ADDWF Acc1H
BTFSC STATUS, C ; check for sum overflow
BSF Flags, OverFlow ; set overflow flag
MOVF Acc1L, w ; return lobyte in W
RETURN
_Mult16
CLRF Acc3H ; Clear product to make
CLRF Acc3L ; way for new calculation.
MOVLW d'16' ; Number of bits to calc.
MOVWF TEMP1
Multiply_loop
BCF STATUS, C
RLF Acc3L ; Shift product left.
RLF Acc3H
BCF STATUS, C
RLF Acc1L ; Shift multiplicand left.
RLF Acc1H
BTFSS STATUS, C ; If carry, add multiplier
GOTO Multiply_skip
MOVF Acc2L,w ; to the product. Else skip.
ADDWF Acc3L
BTFSC STATUS, C ; 16-bit addition: prod+mulp
INCF Acc3H
MOVF Acc2H, w
ADDWF Acc3H
Multiply_skip
DECFSZ TEMP1
GOTO Multiply_loop
MOVF Acc3H, w
MOVWF Acc1H ; return answer in Acc1
MOVF Acc3L, w
MOVWF Acc1L ; with lobyte in W
RETURN
_DIV16 MOVF Acc2H, w ; Check for division by 0.
IORWF Acc2L, w
BTFSC STATUS, Z
RETLW d'255' ; Error code= 255: return.
MOVLW d'1' ; Otherwise, initialize variables
MOVWF TEMP1
CLRF TEMP2 ; index for the division.
CLRF Acc3H
CLRF Acc3L
Divide_sh_loop BTFSC Acc2H, d'7' ; Shift divisor left
GOTO Divide_d1
BCF STATUS, C ; until msb is in
RLF Acc2L ; Acc2H.7.
RLF Acc2H ; TEMP1 = no. of shifts+1.
INCF TEMP1
GOTO Divide_sh_loop
Divide_d1 BCF STATUS, C
RLF Acc3L ; Shift quotient left.
RLF Acc3H
MOVF Acc2L,w ; top = top - btm.
SUBWF Acc1L
BTFSC STATUS, C ; If top - btm < 0 then
GOTO Divide_d2
MOVLW d'1' ; top = top + btm
SUBWF Acc1H
BTFSC STATUS, C ; The idea is to do the
GOTO Divide_d2
INCF Acc1H ; the subtraction and comparison
MOVF Acc2L, w ; (top > btm?) in one step.
ADDWF Acc1L
goto Divide_reentr ; Then, if btm > top, undo <Microchip instruction>
Divide_d2 MOVF Acc2H, w ; the subtraction by adding
SUBWF Acc1H
BTFSS STATUS, C ; top and btm back together
goto Divide_less ; <Microchip instruction>
BSF Acc3L, d'0'
Divide_reentr
BCF STATUS, C
RRF Acc2H
RRF Acc2L
DECFSZ TEMP1
GOTO Divide_d1
MOVF Acc3H, w
MOVWF Acc1H ; return answer in Acc1
MOVF Acc3L, w
MOVWF Acc1L ; with lobyte in W
RETURN
Divide_less MOVF Acc2L, w ; btm > top, so
ADDWF Acc1L
BTFSC STATUS, C ; undo the subtraction by
INCF Acc1H ; adding them back together.
MOVF Acc2H, w
ADDWF Acc1H
goto Divide_reentr ; <Microchip instruction>
_SHIFTR MOVWF Acc2L
_LoopR BCF STATUS, C
RRF Acc1H, F
RRF Acc1L, F
DECFSZ Acc2L
GOTO _LoopR
MOVF Acc1L, W
RETURN
_SHIFTL MOVWF Acc2L
_LoopL BCF STATUS, C
RLF Acc1L, F
RLF Acc1H, F
DECFSZ Acc2L
GOTO _LoopL
MOVF Acc1L, W
RETURN