?? arith.asm
字號:
; : 183 (SIGNED :excluding CALL & RETURN)
;
; Note : The above timing is the worst case timing, when the
; register ACCb = FFFF. The speed may be improved if
; the register ACCb contains a number ( out of the two
; numbers ) with less number of 1s.
;
; The performance specs are for Unsigned arithmetic ( i.e,
; with "SIGNED equ FALSE ").
;
; Upon return from subroutine, the input registers
;
;
;**********************************************************
; Multiplication Macro
;**********************************************************
;
mulMac MACRO
variable i
i = 0
#if SIGNED
.while i < 15
#else
.while i < 16
#endif
.if i < 8
btfss ACCbLO,i ; test low byte
.else
btfss ACCbHI,i-8 ; test high byte
.fi
goto NoAdd#v(i) ; LSB is 0, so no need to addwf
movfp ACCaLO,wreg
addwf ACCdLO ;addwf lsb
movfp ACCaHI,wreg
addwfc ACCdHI ;addwf msb
NoAdd#v(i)
rrcf ACCdHI
rrcf ACCdLO
rrcf ACCcHI
rrcf ACCcLO
bcf _carry
i = i+1
.endw
#if SIGNED
rrcf ACCdHI
rrcf ACCdLO
rrcf ACCcHI
rrcf ACCcLO
bcf _carry
#endif
;
ENDM
;
PAGE
;***************************************************************
; Double Precision Negate Macros
;***************************************************************
AltNegMac MACRO fileRegLo,fileRegHi
movfp fileRegLo,wreg
negw fileRegLo
movfp fileRegHi,wreg
clrf fileRegHi
subwfb fileRegHi
ENDM
;
negMac MACRO fileRegLo, fileRegHi
comf fileRegLo ; negate FileReg ( -FileReg -> FileReg )
incf fileRegLo
btfsc _z
decf fileRegHi
comf fileRegHi
ENDM
;
NegMac32 MACRO x3,x2,x1,x0
movfp x3,wreg
negw x3
movfp x2,wreg
clrf x2
subwfb x2
movfp x1,wreg
clrf x1
subwfb x1
movfp x0,wreg
clrf x0
subwfb x0
ENDM
;
PAGE
;*******************************************************************;
; Double Precision Multiply ( 16x16 -> 32 )
; ( ACCb*ACCa -> ACCb,ACCc ) : 32 bit output with high word
; in ACCd ( ACCdHI,ACCdLO ) and low word in ACCc ( ACCcHI,ACCcLO ).
;
D_mpyF ;results in ACCd(16 msb's) and ACCc(16 lsb's)
;
#if SIGNED
;
movfp ACCaHI,wreg
xorwf ACCbHI,w
movwf sign
btfss ACCbHI,MSB ; if MSB set go & negate ACCb
goto chek_A_MSB_MPY
;
negMac ACCbLO,ACCbHI
;
chek_A_MSB_MPY
btfss ACCaHI,MSB ; if MSB set go & negate ACCa
goto continue_MPY
negMac ACCaLO,ACCaHI
;
#endif
;
continue_MPY
clrf ACCdHI
clrf ACCdLO
bcf _carry
;
; use the mulMac macro 16 times
;
mulMac
;
#if SIGNED
btfss sign,MSB ; negate (ACCc,ACCd)
return
NegMac32 ACCcHI,ACCcLO,ACCdHI, ACCdLO
return
#else
return
#endif
;
PAGE
;*******************************************************************
; Double Precision Division
;
; ( Optimized for Code : Looped 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
;
; Performance :
; Program Memory : 31 (UNSIGNED)
; 39 (SIGNED)
; Clock Cycles : 300 (UNSIGNED : excluding CALL & RETURN)
; : 312 (SIGNED : excluding CALL & RETURN)
;
; NOTE :
; The performance specs are for Unsigned arithmetic ( i.e,
; with "SIGNED equ FALSE ").
;
;*******************************************************************
; 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).
;
; B/A = (Q) + (R)/A
; or B = A*Q + R
;
; where B : Numerator
; A : Denominator
; Q : Quotiont (Integer Result)
; R : Remainder
;
; Note : Check for ZERO Denominator or Numerator is not performed
; A ZERO Denominator will produce incorrect results
;
; SIGNED Arithmetic :
; In case of signed arithmetic, if either
; numerator or denominator is negative, then both Q & R are
; represented as negative numbers
; -(B/A) = -(Q) + (-R)/A
; or -B = (-Q)*A + (-R)
;
;*******************************************************************
;
D_divS
;
bsf _fs0
bsf _fs1 ; set no auto-incrment for fsr0
#if SIGNED
CALL S_SIGN
#endif
;
clrf count
bsf count,4 ; set count = 16
clrf ACCcHI
clrf ACCcLO
clrf ACCdLO
clrf ACCdHI
;
; Looped code
;
divLoop
bcf _carry
rlcf ACCbLO
rlcf ACCbHI
rlcf ACCcLO
rlcf ACCcHI
movfp ACCaHI,wreg
subwf ACCcHI,w ;check if a>c
btfss _z
goto notz
movfp ACCaLO,wreg
subwf ACCcLO,w ; if msb equal then check lsb
notz
btfss _carry ; carry set if c>a
goto nosub ; if c < a
subca
movfp ACCaLO,wreg ; c-a into c
subwf ACCcLO
movfp ACCaHI,wreg
subwfb ACCcHI
bsf _carry ;shift a 1 into d (result)
nosub
rlcf ACCdLO
rlcf ACCdHI
decfsz count
goto divLoop
;
#if SIGNED
btfss sign,MSB
return
movlw ACCcLO
movwf fsr0
call negate
movlw ACCdLO
movwf fsr0
call negate
return
#else
return
#endif
;
PAGE
;*******************************************************************
; 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
;
; B/A = (Q) + (R)/A
; or B = A*Q + R
;
; where B : Numerator
; A : Denominator
; Q : Quotiont (Integer Result)
; R : Remainder
;
; Note : Check for ZERO Denominator or Numerator is not performed
; A ZERO Denominator will produce incorrect results
;
; SIGNED Arithmetic :
; In case of signed arithmetic, if either
; numerator or denominator is negative, then both Q & R are
; represented as negative numbers
; -(B/A) = -(Q) + (-R)/A
; or -B = (-Q)*A + (-R)
;
; Performance :
; Program Memory : 325 (UNSIGNED)
; 354 (SIGNED)
; Clock Cycles : 250 (UNSIGNED : excluding CALL & RETURN)
; : 260 (SIGNED : excluding CALL & RETURN)
;
;*******************************************************************;
; division macro
;
divMac MACRO
variable i
i = 0
.while i < 16
;
bcf _carry
rlcf ACCbLO
rlcf ACCbHI
rlcf ACCcLO
rlcf ACCcHI
movfp ACCaHI,wreg
subwf ACCcHI,w ;check if a>c
btfss _z
goto notz#v(i)
movfp ACCaLO,wreg
subwf ACCcLO,w ;if msb equal then check lsb
notz#v(i) btfss _carry ;carry set if c>a
goto nosub#v(i) ; if c < a
subca#v(i) movfp ACCaLO,wreg ;c-a into c
subwf ACCcLO
movfp ACCaHI,wreg
subwfb ACCcHI
bsf _carry ;shift a 1 into d (result)
nosub#v(i) rlcf ACCdLO
rlcf ACCdHI
i=i+1
.endw
;
ENDM
;
PAGE
;*******************************************************************
; 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.
;
;
;*******************************************************************
;
D_divF
;
#if SIGNED
movfp ACCaHI,wreg
xorwf ACCbHI,w
movwf sign
btfss ACCbHI,MSB ; if MSB set go & negate ACCb
goto chek_A_MSB_DIV
;
negMac ACCbLO,ACCbHI
;
chek_A_MSB_DIV
btfss ACCaHI,MSB ; if MSB set go & negate ACCa
goto continue_DIV
negMac ACCaLO,ACCaHI
#endif
;
continue_DIV
clrf ACCcHI
clrf ACCcLO
clrf ACCdLO
clrf ACCdHI
;
; straight line code : using the macro divMac
;
divMac
;
#if SIGNED
btfss sign,MSB ; negate (ACCc,ACCd)
return
negMac ACCcLO,ACCcHI
negMac ACCdLO,ACCdHI
return
#else
return
#endif
;
PAGE
;*******************************************************************
;
; Square Root By Newton Raphson Method
;
; This routine computes the square root of a 16 bit number(with
; low byte in NumLo & high byte in NumHi ). After loading NumLo &
; NumHi with the desired number whose square root is to be computed,
; branch to location Sqrt ( by "GOTO Sqrt" ). " CALL Sqrt" cannot
; be issued because the Sqrt function makes calls to Math routines
; and the stack is completely used up.
; The result = sqrt(NumHi,NumLo) is returned in location SqrtLo.
; The total number of iterations is set to ten. If more iterations
; are desired, change "LupCnt equ .10" to the desired value. Also,
; the initial guess value of the square root is given set as
; input/2 ( in subroutine "init" ). The user may modify this scheme
; if a better initial approximation value is known. A good initial
; guess will help the algorithm converge at a faster rate and thus
; less number of iterations required.
; Two utility math routines are used by this program : D_divS
; and D_add. These two routines are listed as seperate routines
; under double precision Division and double precision addition
; respectively.
;
; Note : If square root of an 8 bit number is desired, it is probably
; better to have a table look scheme rather than using numerical
; methods.
; This method is computationally quite intensive and
; slow, but very accurate and the convergence rate is high
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -