;16 bit Maths subroutines
Sub16:
COMF Acc2H, f ; Take two's complement
COMF Acc2L, f ; of Acc2. If zero, Acc2L
INCF Acc2L, f
BTFSC STATUS, Z ; overflowed, so carry
INCF Acc2H, f ; into Acc2H.
Add16:
BCF Flags, OverFlow ; clear overflow flag
MOVF Acc2L, w ; Add the LSBs. If carry,
ADDWF Acc1L, f
BTFSC STATUS, C ; increment MSB of sum.
INCF Acc1H, f
MOVF Acc2H, w ; Add the MSBs
ADDWF Acc1H, f
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 tmp1
Multiply_loop
BCF STATUS, C
RLF Acc3L, f ; Shift product left.
RLF Acc3H, f
BCF STATUS, C
RLF Acc1L, f ; Shift multiplicand left.
RLF Acc1H, f
BTFSS STATUS, C ; If carry, add multiplier
GOTO Multiply_skip
MOVF Acc2L, w ; to the product. Else skip.
ADDWF Acc3L, f
BTFSC STATUS, C ; 16-bit addition: prod+mulp
INCF Acc3H, f
MOVF Acc2H, w
ADDWF Acc3H, f
Multiply_skip
DECFSZ tmp1
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 tmp1
CLRF tmp2 ; 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, f ; Acc2H.7.
RLF Acc2H, f ; tmp1 = no. of shifts+1.
INCF tmp1
GOTO Divide_sh_loop
Divide_d1 BCF STATUS, C
RLF Acc3L, f ; Shift quotient left.
RLF Acc3H, f
MOVF Acc2L,w ; top = top - btm.
SUBWF Acc1L, f
BTFSC STATUS, C ; If top - btm < 0 then
GOTO Divide_d2
MOVLW d'1' ; top = top + btm
SUBWF Acc1H, f
BTFSC STATUS, C ; The idea is to do the
GOTO Divide_d2
INCF Acc1H, f ; the subtraction and comparison
MOVF Acc2L, w ; (top > btm?) in one step.
ADDWF Acc1L, f
goto Divide_reentr ; Then, if btm > top, undo <Microchip instruction>
Divide_d2 MOVF Acc2H, w ; the subtraction by adding
SUBWF Acc1H, f
BTFSS STATUS, C ; top and btm back together
goto Divide_less ; <Microchip instruction>
BSF Acc3L, d'0'
Divide_reentr
BCF STATUS, C
RRF Acc2H, f
RRF Acc2L, f
DECFSZ tmp1
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, f
BTFSC STATUS, C ; undo the subtraction by
INCF Acc1H, f ; adding them back together.
MOVF Acc2H, w
ADDWF Acc1H, f
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