ON 20090814@9:14:40 AM at page: On a web page you were interested in at: http://www.piclist.com/techref/member/BB-LTL-/index.htm# Brian Beard[BB-LTL-] edited the page. Difference: http://www.piclist.com/techref/diff.asp?url=H:\techref\member\BB-LTL-\index.htm&version=1 ON 20090814@9:15:11 AM at page: On a web page you were interested in at: http://www.piclist.com/techref/member/BB-LTL-/index.htm#40039.3855439815 Brian Beard[BB-LTL-] Code:
;******************************************************************************
;
; Filename:   QUAD_MATH_TESTS.ASM
; Function:   Math routines using PIC16F87
; Created:    29-Jul-2009
; Author:     Brian Beard
; Company:    Lucid Technologies
;
;******************************************************************************
;
	list      p=16F87           ;list directive to define processor
	#include <p16F87.inc>       ;processor specific variable definitions
	errorlevel  -302            ;suppress message 302 from list file
;
;Program Configuration Register 1
	__CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_CLKOUT
;
;Program Configuration Register 2
	__CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF
;
;******************************************************************************
;VARIABLE DEFINITIONS 
	ORG	0x020           ; Bank 0 = 000:07F
ACa3		RES	1       ; 32-bit Accumulator a, lsb+3, ms-byte
ACa2		RES	1       ; 32-bit Accumulator a, lsb+2
ACa1		RES	1       ; 32-bit Accumulator a, lsb+1
ACa0		RES	1       ; 32-bit Accumulator a, ls-byte
;
ACb3		RES	1       ; 32-bit Accumulator b, lsb+3, ms-byte
ACb2		RES	1       ; 32-bit Accumulator b, lsb+2
ACb1		RES	1       ; 32-bit Accumulator b, lsb+1
ACb0		RES	1       ; 32-bit Accumulator b, ls-byte
;
BCD9		RES	1       ; 10^9, billions
BCD8		RES	1       ; 10^8
BCD7		RES	1       ; 10^7
BCD6		RES	1       ; 10^6, millions
BCD5		RES	1       ; 10^5
BCD4		RES	1       ; 10^4
BCD3		RES	1       ; 10^3, thousands
BCD2		RES	1       ; 10^2
BCD1		RES	1       ; 10^1
BCD0		RES	1       ; 10^0
;
bitcnt		RES	1	; bit count
digcnt		RES	1	; digit count
c_hold		RES	1	; Carry bit hold
;
	ORG	0x070	        ; 0x70h to 0x7Fh is available in all banks
w_temp		res	1       ; variable used for context saving 
status_temp	res	1       ; variable used for context saving
pclath_temp	res	1       ; variable used for context saving
;
;******************************************************************************
;*****      Start of program memory, RESET and INTerrupt vectors.
;******************************************************************************
;
	ORG     0x000             ; processor reset vector
	nop                       ; required for ICD				
	clrf    PCLATH            ; ensure page bits are cleared
	goto    MAIN              ; go to beginning of program

	ORG     0x004             ; interrupt vector location
	movwf   w_temp            ; save off current W register contents
	movf	STATUS,w          ; move status register into W register
	movwf	status_temp       ; save off contents of STATUS register
	movf	PCLATH,W          ; move pclath register into W register
	movwf	pclath_temp       ; save off contents of PCLATH register
;
; isr code can go here or be located as a call subroutine elsewhere
;
	movf	pclath_temp,W	  ; retrieve copy of PCLATH register
	movwf	PCLATH		  ; restore pre-isr PCLATH register contents
	movf    status_temp,w     ; retrieve copy of STATUS register
	movwf	STATUS            ; restore pre-isr STATUS register contents
	swapf   w_temp,f	  ;
	swapf   w_temp,w          ; restore pre-isr W register contents
	retfie                    ; return from interrupt
;
;******************************************************************************
;*****       Subroutines.
;******************************************************************************
;
; Quadruple Precision (32-bit) Addition & Subtraction, adapted from AN526.
; ACa? and ACb? are each four-byte (32-bit) binary accumulators. 
; ACa3 and ACb3 are the MS-Bytes, ACa0 and ACb0 are the LS-Bytes.
; Addition (Q_add):    (ACb)+(ACa) --> (ACb), (ACa) is unchanged
; Subtraction (Q_sub): (ACb)-(ACa) --> (ACb), (ACa) is negated
;
Q_sub   call    neg_ACa       ;First negate ACa, then add
Q_add	movf    ACa0,w
	addwf   ACb0,f        ;Add lsb
	btfss   STATUS,C      ;Test for carry
	goto	q_2           ; go if no carry
	incf    ACb1,f        ;Add carry to lsb+1
	btfss	STATUS,Z      ;Test for carry ripple (FF --> 00)
	goto	q_2           ; and go if no carry
	incf	ACb2,f        ;Add carry to lsb+2
	btfsc	STATUS,Z      ;Test for carry ripple
	incf	ACb3,f        ; add carry to lsb+3, msb
q_2	movf    ACa1,w
	addwf   ACb1,f        ;Add lsb+1
	btfss   STATUS,C      ;Test for carry
	goto	q_4           ; go if no carry
	incf	ACb2,f        ;Add carry to lsb+2
	btfsc	STATUS,Z      ;Test for carry ripple
	incf	ACb3,f        ; add carry to lsb+3, msb
q_4	movf    ACa2,w
	addwf   ACb2,f        ;Add lsb+2
	btfsc   STATUS,C      ;Test for carry
	incf    ACb3,f        ; add carry to lsb+3, msb
	movf    ACa3,w
	addwf   ACb3,f        ;Add msb
	retlw   0
;
neg_ACa	comf    ACa0,f       ; complement (ACa)
	comf    ACa1,f
	comf    ACa2,f
	comf    ACa3,f
	incf    ACa0,f       ; add one
	btfss   STATUS,Z
	retlw	0
	incf    ACa1,f
	btfss   STATUS,Z
	retlw	0
	incf	ACa2,f
	btfss   STATUS,Z
	retlw	0
	incf    ACa3,f
	retlw   0
;
;============================================================================
; Quadruple Precision (32-bit) unsigned Binary to BCD conversion
; BCD9 to BCD0 comprise one ten digit unpacked Binary-Coded-Decimal number.
;  The upper nibble of each digit is zero (00008421). BCD9 is the MS-Digit.
; ACb3 to ACb0 comprise a four-byte (32-bit) binary accumulator.
;  ACb3 is the MS-Byte. 
; The 32-bit binary number in ACb in converted to a ten digit BCD number.
;
Q_b2bcd
	clrf	BCD9         ;Clear all bcd digits
	clrf	BCD8
	clrf	BCD7
	clrf	BCD6
	clrf	BCD5
	clrf	BCD4
	clrf	BCD3
	clrf	BCD2
	clrf	BCD1
	clrf	BCD0
	movlw	D'32'        ;Outer loop
	movwf	bitcnt       ; bit counter
b2bcd1
	rlf	ACb0,f       ;Shift 32-bit accumulator
	rlf	ACb1,f       ; left to 
	rlf	ACb2,f       ;  put ms-bit 
	rlf	ACb3,f       ;   into Carry
	movlw	BCD0         ;Point to address of least 
	movwf	FSR          ; significant bcd digit
	movlw	D'10'        ;Inner loop
	movwf	digcnt       ; digit counter
b2bcd2
	rlf	INDF,f       ;Shift Carry into bcd digit
	movlw	D'10'        ;Subtract ten from digit then
	subwf	INDF,w       ; check and adjust for decimal overflow
	btfsc   STATUS,C     ;If Carry = 1 (result >= 0)
	movwf	INDF         ; adjust for decimal overflow
	decf	FSR,f        ;Point to next bcd digit
	decfsz	digcnt,f     ;Decrement digit counter
	goto	b2bcd2       ; - go if digcnt > 0
	decfsz	bitcnt,f     ;Decrement bit counter
	goto	b2bcd1       ; - go if bitcnt > 0
	retlw   0
;
;============================================================================
; Quadruple Precision (32-bit) unsigned BCD to Binary conversion.
; BCD9 to BCD0 comprise one ten digit unpacked Binary-Coded-Decimal number.
;  The upper nibble of each digit is zero (00008421). BCD9 is the MS-Digit.
; ACb3 to ACb0 comprise a four-byte (32-bit) binary accumulator.
;  ACb3 is the MS-Byte. 
; The 10-digit BCD number is converted to a 32-bit binary number in ACb.
;
Q_bcd2b
	movlw	D'32'         ;Outer loop
	movwf	bitcnt        ; bit counter
bcd2b1
	movlw	BCD9          ;Set pointer for
	movwf	FSR           ; most significant digit
	movlw	D'10'         ;Inner loop
	movwf	digcnt        ; digit counter
	movlw	0x05          ;Weight of next MS-Digit's carry bit
	clrf	c_hold        ;0 --> carry_hold
bcd2b2
	bcf	STATUS,0      ;Clear Carry bit
	rrf	INDF,f        ;Right shift 0 into bcd digit
	rlf	c_hold,f      ;Carry --> c_hold,0
	btfsc	c_hold,1      ;Add five if carry from previous rotate is
	addwf	INDF,f        ; set, else no change
	incf	FSR,f         ;Advance digit pointer
	decfsz	digcnt,f      ;Decrement digit counter,
	goto	bcd2b2        ; repeat if > 0
	rrf	c_hold,f      ;Last carry from digit rotate --> C 
	rrf	ACb3,f        ;Ripple Carry bits
	rrf	ACb2,f        ; from MSB to
	rrf	ACb1,f        ;  LSB of 
	rrf	ACb0,f        ;   32-bit binary accumulator
	decfsz	bitcnt,f      ;Decrement bit counter,
	goto	bcd2b1        ; repeat if > 0
	retlw   0
;
;*******************************************************************
;                       Test Program
;*******************************************************************
;    Load constant values for testing
;
load1	movlw   0x10
	movwf   ACa3
	movlw   0x00             ; loads ACa = 10 00 00 00
	movwf   ACa2
	movlw   0x00
	movwf   ACa1
	movlw   0x00 
	movwf   ACa0

	movlw   0x32
	movwf   ACb3
	movlw   0xFF             ; loads ACb = 32 FF 7F DE
	movwf   ACb2
	movlw   0x7F
	movwf   ACb1
	movlw   0xDE 
	movwf   ACb0
	retlw   0

load2	movlw   0x00
	movwf   ACa3
	movlw   0x01             ; loads ACa = 00 01 FF AF
	movwf   ACa2
	movlw   0xFF
	movwf   ACa1
	movlw   0xAF 
	movwf   ACa0

	movlw   0x00
	movwf   ACb3
	movlw   0x00             ; loads ACb = 00 00 CF E7
	movwf   ACb2
	movlw   0xCF
	movwf   ACb1
	movlw   0xE7 
	movwf   ACb0
	retlw   0

load3	movlw   0x00
	movwf   ACa3
	movlw   0x00             ; loads ACa = 00 00 00 01
	movwf   ACa2
	movlw   0x00
	movwf   ACa1
	movlw   0x01 
	movwf   ACa0

	movlw   0x0F
	movwf   ACb3
	movlw   0xFF             ; loads ACb = 0F FF FF FF
	movwf   ACb2
	movlw   0xFF
	movwf   ACb1
	movlw   0xFF 
	movwf   ACb0
	retlw   0
;
MAIN	nop
	clrf      STATUS         ; Do initialization, select bank 0 registers
	page0	                 ; select program memory page 0
;
	call    load1       ; a=10 00 00 00, b=32 FF 7F DE
	call    Q_add       ; Answer = 42 FF 7F DE
	call	Q_b2bcd     ; Answer = 1,124,040,670
	call	Q_bcd2b     ; Answer = 42 FF 7F DE
;
self1	call    load1       ; a=10 00 00 00, b=32 FF 7F DE
	call    Q_sub       ; Neg = F0 00 00 00, Answer = 22 FF 7F DE
	call	Q_b2bcd     ; Answer = 0,587,169,758
	call	Q_bcd2b     ; Answer = 22 FF 7F DE
;
self2   call    load2       ; a=00 01 FF AF, b=00 00 CF E7
	call    Q_add       ; Answer = 00 02 CF 96
	call	Q_b2bcd     ; Answer = 0,000,184,214
	call	Q_bcd2b     ; Answer = 00 02 CF 96
;
self3	call    load2       ; a=00 01 FF AF, b=00 00 CF E7
	call    Q_sub       ; Neg = FF FE 00 51, Answer = FF FE D0 38
	call	Q_b2bcd     ; Answer = 4,294,889,528
	call	Q_bcd2b     ; Answer = FF FE D0 38
;
self4   call    load3       ;a=00 00 00 01, b=0F FF FF FF
	call    Q_add       ; Answer = 10 00 00 00
	call	Q_b2bcd     ; Answer = 0,268,435,456
	call	Q_bcd2b     ; Answer = 10 00 00 00
;
self5	call    load3       ;a=00 00 00 01, b=0F FF FF FF
	call    Q_sub       ; Neg = FF FF FF FF, Answer = 0F FF FF FE
	call	Q_b2bcd     ; Answer = 0,268,435,454
	call	Q_bcd2b     ; Answer = 0F FF FF FE
;
self99	NOP 

;============================================================================

	end