;******************************************************************* ; Double Precision Multiplication ; ; ( Optimized for Speed : straight Line Code ) ; ;*******************************************************************; ; Multiplication : ACCb(16 bits) * ACCa(16 bits) -> ACCb,ACCc ( 32 bits ) ; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits ) ; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits ) ; (c) CALL D_mpy ; (d) The 32 bit result is in location ( ACCbHI,ACCbLO,ACCcHI,ACCcLO ) ;*******************************************************************; ; ; multiplication macro ; mulMac MACRO LOCAL NO_ADD ; rrf ACCdHI, F ;rotate d right rrf ACCdLO, F btfss STATUS,C ;need to add? goto NO_ADD ; no addition necessary movf ACCaLO,w ; Addition ( ACCb + ACCa -> ACCb ) addwf ACCbLO, F ;add lsb btfsc STATUS,C ;add in carry incf ACCbHI, F movf ACCaHI,w addwf ACCbHI, F ;add msb NO_ADD rrf ACCbHI, F rrf ACCbLO, F rrf ACCcHI, F rrf ACCcLO, F ; ENDM ; ;*******************************************************************; ; Double Precision Multiply ( 16x16 -> 32 ) ; ( ACCb*ACCa -> ACCb,ACCc ) : 32 bit output with high word ; in ACCb ( ACCbHI,ACCbLO ) and low word in ACCc ( ACCcHI,ACCcLO ). ; D_mpyF ;results in ACCb(16 msb's) and ACCc(16 lsb's) ; IF SIGNED CALL S_SIGN ENDIF ; call setup ; ; use the mulMac macro 16 times ; mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac mulMac ; IF SIGNED btfss sign,MSB retlw 0 comf ACCcLO ; negate ACCa ( -ACCa -> ACCa ) incf ACCcLO btfsc STATUS,Z decf ACCcHI comf ACCcHI btfsc STATUS,Z neg_B comf ACCbLO ; negate ACCb incf ACCbLO btfsc STATUS,Z decf ACCbHI comf ACCbHI retlw 0 ELSE retlw 0 ENDIF ;******************************************************************* setup movlw .16 ; for 16 shifts movwf temp movf ACCbHI,w ;move ACCb to ACCd movwf ACCdHI movf ACCbLO,w movwf ACCdLO clrf ACCbHI clrf ACCbLO retlw 0 ;******************************************************************* ; Assemble this section only if Signed Arithmetic Needed ; IF SIGNED ; S_SIGN movf ACCaHI,W xorwf ACCbHI,W movwf sign btfss ACCbHI,MSB ; if MSB set go & negate ACCb goto chek_A ; comf ACCbLO ; negate ACCb incf ACCbLO btfsc STATUS,Z decf ACCbHI comf ACCbHI ; chek_A btfss ACCaHI,MSB ; if MSB set go & negate ACCa retlw 0 goto neg_A ; ENDIF ; ;******************************************************************* ; Double Precision Division ; ; ( Optimized for Speed : straight Line Code ) ; ;*******************************************************************; ; Division : ACCb(16 bits) / ACCa(16 bits) -> ACCb(16 bits) with ; Remainder in ACCc (16 bits) ; (a) Load the Denominator in location ACCaHI & ACCaLO ( 16 bits ) ; (b) Load the Numerator in location ACCbHI & ACCbLO ( 16 bits ) ; (c) CALL D_div ; (d) The 16 bit result is in location ACCbHI & ACCbLO ; (e) The 16 bit Remainder is in locations ACCcHI & ACCcLO ;*******************************************************************; ; divMac MACRO LOCAL NOCHK LOCAL NOGO bcf STATUS,C rlf ACCdLO, F rlf ACCdHI, F rlf ACCcLO, F rlf ACCcHI, F movf ACCaHI,w subwf ACCcHI,w ;check if a>c btfss STATUS,Z goto NOCHK movf ACCaLO,w subwf ACCcLO,w ;if msb equal then check lsb NOCHK btfss STATUS,C ;carry set if c>a goto NOGO movf ACCaLO,w ;c-a into c subwf ACCcLO, F btfss STATUS,C decf ACCcHI, F movf ACCaHI,w subwf ACCcHI, F bsf STATUS,C ;shift a 1 into b (result) NOGO rlf ACCbLO, F rlf ACCbHI, F ENDM ;******************************************************************* ; Double Precision Divide ( 16/16 -> 16 ) ; ; ( ACCb/ACCa -> ACCb with remainder in ACCc ) : 16 bit output ; with Quotiont in ACCb (ACCbHI,ACCbLO) and Remainder in ACCc (ACCcHI,ACCcLO). ; ; NOTE : Before calling this routine, the user should make sure that ; the Numerator(ACCb) is greater than Denominator(ACCa). If ; the case is not true, the user should scale either Numerator ; or Denominator or both such that Numerator is greater than ; the Denominator. ;******************************************************************* neg_A comf ACCaLO, F ; negate ACCa ( -ACCa -> ACCa ) incf ACCaLO, F btfsc STATUS,Z decf ACCaHI, F comf ACCaHI, F retlw 0 ;******************************************************************* D_divF IF SIGNED CALL S_SIGN ENDIF call setup clrf ACCcHI clrf ACCcLO ; use the mulMac macro 16 times divMac divMac divMac divMac divMac divMac divMac divMac divMac divMac divMac divMac divMac divMac divMac divMac ; IF SIGNED btfss sign,MSB ; check sign if negative retlw 0 goto neg_B ; negate ACCa ( -ACCa -> ACCa ) ELSE retlw 0 ENDIF ; ;******************************************************************* ; Assemble this section only if Signed Arithmetic Needed ; IF SIGNED ; S_SIGN movf ACCaHI,W xorwf ACCbHI,W movwf sign btfss ACCbHI,MSB ; if MSB set go & negate ACCb goto chek_A ; comf ACCbLO ; negate ACCb incf ACCbLO btfsc STATUS,Z decf ACCbHI comf ACCbHI ; chek_A btfss ACCaHI,MSB ; if MSB set go & negate ACCa retlw 0 goto neg_A ; ENDIF ; ;******************************************************************* ; Double Precision Addition & Subtraction ;*******************************************************************; ; Addition : ACCb(16 bits) + ACCa(16 bits) -> ACCb(16 bits) ; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits ) ; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits ) ; (c) CALL D_add ; (d) The result is in location ACCbLO & ACCbHI ( 16 bits ) ;*******************************************************************; ; Subtraction : ACCb(16 bits) - ACCa(16 bits) -> ACCb(16 bits) ; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits ) ; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits ) ; (c) CALL D_sub ; (d) The result is in location ACCbLO & ACCbHI ( 16 bits ) ;*******************************************************************; D_sub call neg_A ; At first negate ACCa; Then add ;******************************************************************* D_add movf ACCaLO,w addwf ACCbLO, F ;add lsb btfsc STATUS,C ;add in carry incf ACCbHI, F movf ACCaHI,w addwf ACCbHI, F ;add msb retlw 0