NOLIST
_PINZ ADDWF PCL
RETLW d'1'
RETLW d'2'
RETLW d'4'
RETLW d'8'
RETLW d'16'
RETLW d'32'
RETLW d'64'
RETLW d'128'
_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 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
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
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
_CONVERT: ; Takes number in Acc1H:Acc1L
; Returns decimal in
; TenK:Thou:Hund:Tens:Ones
swapf Acc1H, w
iorlw B'11110000'
movwf Thou
addwf Thou,f
addlw 0XE2
movwf Hund
addlw 0X32
movwf Ones
movf Acc1H,w
andlw 0X0F
addwf Hund,f
addwf Hund,f
addwf Ones,f
addlw 0XE9
movwf Tens
addwf Tens,f
addwf Tens,f
swapf Acc1L,w
andlw 0X0F
addwf Tens,f
addwf Ones,f
rlf Tens,f
rlf Ones,f
comf Ones,f
rlf Ones,f
movf Acc1L,w
andlw 0X0F
addwf Ones,f
rlf Thou,f
movlw 0X07
movwf TenK
movlw 0X0A
Lb1:
addwf Ones,f
decf Tens,f
btfss 3,0
goto Lb1
Lb2:
addwf Tens,f
decf Hund,f
btfss 3,0
goto Lb2
Lb3:
addwf Hund,f
decf Thou,f
btfss 3,0
goto Lb3
Lb4:
addwf Thou,f
decf TenK,f
btfss 3,0
goto Lb4
return
_COMP16:
movf Acc1H, w
subwf Acc2H, w
btfss STATUS, Z
goto $+3
movf Acc1L, w
subwf Acc2L,
return
_COMP16I:
movf Acc2H, w
subwf Acc1H, w
btfss STATUS, Z
goto $+3
movf Acc2L, w
subwf Acc1L, w
return
LIST