Text preview for : calcul2.pdf part of MAAS KNT-5000 Stabilized DC Power Supply
MAAS KNT-5000
Back to : Maas KNT-5000.pdf | Home
AN544
Math Utility Routines
Author: Amar Palacherla Microchip Technology Inc.
As more routines are available, they will be added to the library. The latest routines may be obtained either through Microchip's bulletin board or by contacting your nearest Microchip sales office for a copy on a MS-DOS® floppy. These routines have been optimized wherever possible with a compromise between speed, RAM utilization, and code size. Some routines (multiplication and division) are provided in two forms, one optimized for speed and the other optimized for code size. All the routines have been implemented as callable subroutines and the usage of each routine is explained below. At the end of the application note, the listing files of the above programs are given.
INTRODUCTION
PLEASE NOTE: This application note uses the old Microchip Math Routine format. It is intended for reference purposes only and is being provided for those of you still implementing Binary Coded Decimal(BCD) routines. For any new designs, please refer to application notes contained in Microchip's Embedded Control Handbook Volume II - Math Library This application note provides some utility math routines for Microchip's second generation of high performance 8-bit microcontroller, the PIC17C42. Three assembly language modules are provided, namely ARITH.ASM, BCD.ASM and FXPDIV.ASM. Currently in each file the following subroutines are implemented:
SINGLE PRECISION UNSIGNED MULTIPLICATION (8 x 8)
This routine computes the product of two unsigned 8-bit numbers and produces a 16-bit result. Two routines are provided: one routine is optimized for speed (a straight line code) and the other one has been optimized for code size (a looped code version). These subroutines are located in ARITH.ASM and printed in the listing file ARITH.LST. The performance specs are shown in Table 1.
ARITH.ASM
· Single precision 8 x 8 unsigned multiply · 16 x 16 double precision multiply (signed or unsigned) · 16 / 16 double precision divide (signed or unsigned) · 16 x 16 double precision addition · 16 x 16 double precision subtraction · double precision square root · double precision numerical differentiation · double precision numerical integration · Pseudo Random number generation · Gaussian distributed random number generation
DOUBLE PRECISION MULTIPLICATION
This routine computes the product of 16- bit numbers and produces a 32-bit result. Both signed and unsigned arithmetic is provided (2's complement arithmetic). Whether to use signed or unsigned is decided at assembly time depending on whether "SIGNED" is set to true or false (refer to the source code). These routines are extremely useful for high precision computation and are used extensively in the other programs provided in this application note (for example, the square root, integrator, differentiator call these routines). Two routines are provided. One routine is optimized for speed (a straight line code) and the other one has been optimized for code size (a looped code version). These subroutines are located in ARITH.ASM and printed in the listing file ARITH.LST. The performance specs are shown in Table 2.
BCD.ASM
· · · · 8-bit binary to 2 digit BCD conversion 16-bit binary to 5 digit BCD conversion 5-bit BCD to 16-bit binary conversion 2 digit BCD addition
FXPDIV.ASM.
The routines that are implementing in this source file are shown in Table 3.
TABLE 1:
Name mpy8x8_F MPY8X8_s
SINGLE PRECISION MULTIPLICATION
Comments speed efficient code efficient Program Memory Instruction Cycles 36 13 36 69 Scratch RAM 0 1 W Register used used
MS-DOS is a registered trademark of Microsoft Corporation.
© 1997 Microchip Technology Inc.
DS00544D-page 4-1
AN544
The listing file shown is assembled with "SIGNED equ TRUE". If unsigned arithmetic is needed, the source code should be changed to "SIGNED equ FALSE". Conditional assembly and the advanced macro features of the assembler are used. The data memory organization is explained in the comment section of the code. Faster execution and code space saving can be achieved by setting "MODE_FAST equ TRUE". However, setting MODE_FAST variable to TRUE restricts that operands and the 32-bit result be in data RAM locations 0x18 and 0x1F (in this mode, MOVFP and MOVPF instructions may be used to transfer data to/from any RAM location to addresses less than 0x1F). If MODE_FAST is set to FALSE, there will be no restriction on the location of the data RAM values used in this subroutine. However, the code will be slightly slower and occupies more program memory. The listing file shown is assembled with "SIGNED equ TRUE". If unsigned arithmetic is needed, the source code should be changed to "SIGNED equ FALSE". Conditional assembly and the advanced macro features of the assembler are used.
DOUBLE PRECISION DIVISION
This routine performs a 2's complement division of two 16-bit numbers and produces a 16-bit quotient with a 16-bit remainder. Both signed and unsigned arithmetic is provided (2's complement arithmetic). Whether to use signed or unsigned is decided at assembly time depending on whether "SIGNED" is set to true or false (refer to the source code). These routines are extremely useful for high precision computation and are used extensively in the other programs provided in this application note (for example, the square root, integrator, differentiator call these routines). Two routines are provided. One routine is optimized for speed (a straight line code) and the other one has been optimized for code size (a looped code version). These subroutines are located in Appendix C. The performance specs are shown in Table 3.
TABLE 2:
Name D_myfF D_mpyF D_mpyS D_mpyS
DOUBLE PRECISION MULTIPLICATION
Comments Speed Efficient, Signed Arithmetic Speed Efficient, Unsigned Arithmetic Code Efficient, Signed Arithmetic Code Efficient, Unsigned Arithmetic Program Memory 204 179 52 21 Instruction Cycles 183 176 254 242 Scratch RAM 1 0 4 3 W Register used used used used
TABLE 3:
Routine 16 / 8 Signed 16 / 8 Unsigned 16 / 7 Unsigned 15 / 7 Unsigned 16 / 16 Unsigned 16 / 16 Unsigned 16 / 15 Unsigned 16 / 15 Unsigned 32 / 16 Unsigned 32 / 16 Unsigned 32 / 15 Unsigned 31 / 15 Unsigned
FIXED POINT DIVIDE PERFORMANCE DATA
Max. Cycles 146 196 130 125 214 244 197 191 414 485 390 383 Min. Cycles 135 156 130 125 187 180 182 177 363 459 359 353 Program Memory 146 195 129 124 241 243 216 218 476 608 451 442 Data Memory 5 4 4 4 7 6 6 6 9 9 8 8
DS00544D-page 4-2
© 1997 Microchip Technology Inc.
AN544
DOUBLE PRECISION ADDITION AND SUBTRACTION
Two routines are provided. One performs a 2's complement addition and the other one performs a 2's complement subtraction of two 16-bit binary numbers. These subroutines are located in ARITH.ASM and printed in the listing file ARITH.LST. The performance specs are shown in Table 4.
EQUATION 1:
( Y Y 0 )2ff ( Y 0 ) f ( Y ) = f ( Y 0 ) + ( Y Y 0 )f ( Y 0 ) + --------------------------------------------- + ... 2!
If X is a root of f(Y), then f(X) = 0: Therefore,
NEGATE A DOUBLE PRECISION NUMBER
These routines negate a double precision number (16-bit and 32-bit). Two routines and two macros are provided to negate a 16-bit number. The subroutines use indirect addressing mode and the macros use a direct addressing scheme. A macro is provided to negate a 32- bit number.
If Y0 is an approximate root of f(Y), then the higher order terms in the above equation are negligible. Therefore, i.e.,
f ( Y 0 ) + ( X Y 0 )f ( Y 0 ) = 0
f ( Y0 ) X = Y 0 + --------------f ( Y )
0
Thus X is a better approximation for Y0. From the previous equation, the sequence {Xn} can be generated:
DOUBLE PRECISION SQUARE ROOT
Often in many applications, one needs to find the square root of a number. Of the many numerical methods available to compute the square root of a number, the Newton-Raphson method is one of the most attractive because of its fast convergence rate. In this method, the square root of number, N, is obtained as an approximate solution of f( Y ) = Y2 N = 0 The function f(Y) can be expanded about Y0 using the first order Taylor polynomial expansion as:
EQUATION 2:
f ( Xn 1 ) X n = X n 1 ----------------------- ,n 1 f' ( X n 1 )
For our case, equation 2, reduces to: N X n 1 + ------------Xn 1 ---------------------------------2
EQUATION 3:
The routine "Sqrt" in ARITH.ASM implements the above equation. Equation 3 requires that at first an initial approximation for the root is known. The better the initial approximation, the faster the convergence rate would be. In the "Sqrt" routine, the initial approximation root is set as N/2. This routine calls the double precision division routine (D_divS). In the code size, the Division routine (Ddiv_S) size is not included.
TABLE 4:
Name Dadd Dsub
DOUBLE PRECISION ADDITION AND SUBTRACTION
Program Memory 4 4 Instruction Cycles 4 4 Scratch RAM 0 0 W Register used used
TABLE 5:
Name Negate NegateAlt NegMac AltNegMac
NEGATE A DOUBLE ADDITION AND SUBTRACTION
Program Memory 7 7 5 5 11 Instruction Cycles 7 7 5 5 11 Scratch RAM 0 0 0 0 0 W Register unused used used unused used
NegMac32 (32 bit)
© 1997 Microchip Technology Inc.
DS00544D-page 4-3
AN544
BCD ROUTINES
Three routines are provided for general purpose BCD arithmetic: a) b) c) BCD to binary conversion Binary to BCD conversion BCD addition where t0 is the point at which the numerical derivative is desired and "h" is the step size. The smaller the value of the step size (h), the better the approximation. In case of say, PID motor control, the step size is proportional to the time intervals at which the new sample value of the position (or speed) is obtained. Using the above equation to compute the differential, three samples are necessary (present value and the last two past values). The subroutine "Diff" is implemented so that 1/2h factor is stored already in a RAM location (location DiffK) as 1/2h and not as "h" because it is more efficient to multiply than divide. After computation, the routine does not move the present value to the past value. So the user must update the past values before calling this routine again. This way, if necessary, differentiation may be performed without disturbing the present and past values. Also, when this routine is called for the first time, it is user's responsibility to set the initial values of the past data points (may be set to zero). This routine called "Diff" is located in "ARITH.ASM". In the code size, the double precision multiplication routine (Dmpy_S) used is not included.
EQUATION 4:
3-POINT FORMULA:
The BCD to binary conversion routine converts a 5-digit BCD code to a 16-bit binary number. The BCD addition routine adds two BCD digits directly without converting them at first to binary. Note the usage of the "DAW" instruction. The other two routines convert a binary number to a BCD code. The performance specs for the BCD routines is given in the Table 7 below.
NUMERICAL DIFFERENTIATION
This routine performs numerical differentiation of a sequence of data if the input sequence is assumed to be piecewise linear with no discontinuances (this is the case in most real world signals). Although this routine is provided as a tool to implement a PID algorithm for motor control, it can be used as a general purpose subroutine. This routine uses the so called 3-Point formula to compute the differential of a sequence of numbers. Given an equation f(t), its derivative is given by df ( t ) f' ( t ) = ----------dt The above equation can be approximated using the 3-Point formula as given below:
TABLE 6:
Name Sqrt
DOUBLE PRECISION SQUARE ROOT
Program Memory 22 Instruction Cycles 3300 (Approx.) Scratch RAM 6 W Register used
TABLE 7:
Name BCDtoB B2_BCD_Loope d
BCD ROUTINES
Comments BCD to Binary Binary to BCD (16 bit) looped code Program Memory 30 32 44 10 5 Instruction Cycles 112 750 572 62 5 Scratch RAM 0 1 1 1 0 W Register used used used unused used
B2_BCD_Straig Binary to BCD (16 ht bit) straight line code BinBCD BCDAdd Binary to BCD (8 bit) BCD addition
DS00544D-page 4-4
© 1997 Microchip Technology Inc.
AN544
NUMERICAL INTEGRATION
This routine performs numerical integration using Simpson's Three-Eighths Rule. This is a third order approximation for the function, whose integral is to be computed at a given point. Although this routine is provided as a tool to implement a PID algorithm for motor control, it can be used as a general purpose subroutine. Given a function f(t), its integral over a range t0 to t3 is represented as: t3 f(t)dt. This function is approximated as follows: t0 Simpson's Three-Eighths Rule: t3 3h = ------ [ f ( t0 ) + 3f ( t1 ) + 3f ( t2 ) + f ( t3 ) ] 8
PSEUDO RANDOM NUMBER GENERATOR
This routine (subroutine "Random 16" provided in ARITH.ASM) generates a pseudo random number sequence. The random points are generated using a 16-bit register and left shifting the contents with the LSB set as shown by the following schematic. As a test, the random points are generated by calling the subroutine from an infinite loop, and the data points are continuously captured into the real time trace buffer using the PICMASTER (the Universal In-Circuit Emulator for the PICmicroTM series). The autocorrelation of the captured data is computed using a stand alone program and is shown in Figure 2. From this figure, it can be seen that the data has a strong autocorrelation only at the origin and sharply approaches to zero within a few points. This demonstrates the randomness of the data captured.
f ( t ) dt
(t0)
FIGURE 1: 15 14 13 12 ..... 3 2 1 0
The constant 3h/8 can be computed before hand and stored in a RAM location (in location IntgKLo and IntgKHi as a 16-bit number). After computation, the routine does not move the present value to the past value. So the user must update the past values before calling this routine again. This way, if necessary, integration may be performed without disturbing the present and past values. Also, when this routine is called for the first time, it is user's responsibility to set the initial values of the past data points (may be set to zero). This routine called "Integrate" is located in "ARITH.ASM". In the code size, the double precision multiplication routine (Dmpy_S) used is not included.
TABLE 8:
Name Diff
DIFFERENTIATION
Comments Numerical Differentiation Program Memory 34 Instruction Cycles 365 Scratch RAM 10 W Register used
TABLE 9:
Name Integrate
INTEGRATION
Comments Numerical Integration Program Memory 39 Instruction Cycles 370 Scratch RAM 12 W Register used
© 1997 Microchip Technology Inc.
DS00544D-page 4-5
AN544
FIGURE 2: AUTOCORRELATION OF THE DATA POINTS GENERATED BY THE RANDOM NUMBER GENERATOR
Autocorrelation of Data from Random Number Generator 1.20 -1.00 -0.80 -Magnitude 0.60 -0.40 -0.20 -0.00 -| | | | | | | | | | | |
1 11 21 31 41 51 61 71 81 91 101 111 121 Sample Number
TABLE 10:
Name Random16 Gauss
RANDOM DOUBLE GENERATOR
Comments Pseudo Random Number Generator Gaussian Random Number Generator Program Memory Instruction Cycles 12 21 12 452 Scratch RAM 0 4 W Register used used
PN (pseudo noise) sequences are widely used in digital communication systems for synchronization. These code words can also be used for data scrambling because of their good correlation properties. An interesting application of these sequences is system integrity. For example, these sequences can be regularly transmitted to a processor whose watchdog timer will time out if, say, two consecutive PN sequences do not match.
GAUSSIAN DISTRIBUTED RANDOM NUMBER GENERATOR
This routine (subroutine "Gauss" provided in ARITH.ASM) generates a sequence of random numbers with a characteristic of a normal distribution (Gaussian distributed points). This routine calls the pseudo random number generator ("random16") to obtain a near uniformly distributed random points and from these points, the Gaussian distributed points are generated. The method of generating Gaussian points is based on the "Central Limit Theorem", which states that an ensemble of average weighted sum of a sequence of uncorrelated samples tends to have a Gaussian distribution. As a test, the Gaussian points are generated by calling the subroutine from an infinite loop, and the data points are continuously captured into the real time trace buffer using the PICMASTER (the Universal In-Circuit Emulator for the PICmicro series). A plot of the points captured is shown in Figure 3, which shows that the random points generated have the characteristics of a Gaussian distribution.
FIGURE 3:
HISTOGRAM OF THE DATA GENERATED BY THE GAUSSIAN GENERATOR
Gaussian Distributed Samples Generated by PIC17C42
100 -Relative 80 -Amplitude 60 --
40 -17 -33 -49 -65 -81 -97 -1 -20 -113 --
Samples
DS00544D-page 4-6
© 1997 Microchip Technology Inc.
AN544
Please check the Microchip BBS for the latest version of the source code. Microchip's Worldwide Web Address: www.microchip.com; Bulletin Board Support: MCHIPBBS using CompuServe® (CompuServe membership not required).
APPENDIX A:
GENERAL PURPOSE MATH ROUTINES LISTING FILE OF ARITH.LST
ARITH.ASM 1-16-1997 15:10:04 PAGE 1
MPASM 01.40 Released
LOC OBJECT CODE VALUE 00001 00002 00003 00004 00005 00006 00001 00002 00264 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 00025 00026 00027 00028 00029 00030 00031 00032 00033 00034 00035 00036 00037 00038 00039 00040 00041 00042 00043 00044 00045 00046 00047 00048 00049 00050
LINE SOURCE TEXT
TITLE LIST ;
"General Purpose Math Routines For PIC17C42 : Ver 1.0" P = 17C42, columns=120, WRAP, L=0, R = DEC
include LIST ; P17C42.INC Standard Header File, Version 1.03 Microchip Technology, Inc. LIST #define TRUE #define FALSE _INC _NO_INC _LOW _HIGH equ equ equ equ 1 0 0 1 1 0
00000001 00000000 00000000 00000001
00000001 00000000
; ;******************************************************************* ; Define RAM Locations necessary For the "ARITH.ASM" ; RAM locations should be defined before calling the library math ; routines ; ; Program: ARITH.ASM ; Revision Date: ; 1-13-97 Compatibility with MPASMWIN 1.40 ; ;******************************************************************* ; MODE_FAST equ TRUE SIGNED equ FALSE ; ;******************************************************************* ; #if MODE_FAST CBLOCK 0x18 ACCaLO, ACCaHI, ACCbLO, ACCbHI ACCcLO, ACCcHI, ACCdLO, ACCdHI ENDC #else CBLOCK 0x20 ACCaLO, ACCaHI, ACCbLO, ACCbHI ACCcLO, ACCcHI, ACCdLO, ACCdHI ENDC #endif ; CBLOCK
00000018 0000001C
; Ram Locations for Arithmetic ; Routines
© 1997 Microchip Technology Inc.
DS00544D-page 4-7
AN544
00000020 00051 00052 00053 00054 00055 00056 00057 00058 00059 00060 00061 00062 00063 00064 00065 00066 00067 00068 00069 00070 00071 00072 00073 00074 00075 00076 00077 00078 00079 00080 00081 00082 00083 00084 00085 00086 00087 00088 00089 00090 00091 00092 00093 00094 00095 00096 00097 00098 00099 00100 00101 00102 00103 00104 00105 00106 00107 00108 00109 00110 00111 00112 00113 00114 00115 00116 tempLo, tempHi, count, sign ENDC CBLOCK NumLo, NumHi iterCnt ENDC ; CBLOCK ; RAM locations for "Diff" routine XnLo, XnHi, Xn_1_Lo Xn_1_Hi, Xn_2_Lo, Xn_2_Hi DiffKLo, DiffKHi ; DiffK = h = Step Size DiffLo, DiffHi
00000024 00000026
00000027 0000002A 0000002D 0000002F
ENDC ; CBLOCK X0Lo, X0Hi, X1Lo, X1Hi X2Lo, X2Hi, X3Lo, X3Hi IntgKLo, IntgKHi IntgLo, IntgHi ; RAM Locations for "Integrate" ; Routine ; INTEGRATE CONST = 3*h/8
00000031 00000035 00000039 0000003B
00000018 00000019 0000001A 0000001B 0000000A 0000001E 0000001F
00000018 00000019 0000001B 0000001A 00000020
ENDC ; ;******************************************************************* ; mulcnd equ ACCaLO mulplr equ ACCaHI L_byte equ ACCbLO H_byte equ ACCbHI ; _LUPCNT equ 10 ; Set Desired Number of iterations SqrtLo equ ACCdLO ; for Square Root Routine(NEWTON Iterations) SqrtHi equ ACCdHI ; ; Define RAM locations for the Random Number Generators ; RandLo equ ACCaLO RandHi equ ACCaHI ; 16 bit Pseudo Random Number GaussHi equ ACCbHI GaussLo equ ACCbLO ; 16 bit Gaussian distributed number GaussTmp equ tempLo ; PAGE ORG 0x0000 ;******************************************************************* ; Math Routines Test Program ;******************************************************************* ; ; Load constant values to ACCa & ACCb for testing ; main call loadAB ; result of adding ACCb+ACCa->ACCb call D_add ; Here Accb = 81FE ; call loadAB ; result of subtracting ACCb - ACCa->ACCb call D_sub ; Here Accb = 7E00 ; call loadAB ; result of multiplying ACCb*ACCa->(ACCd,ACCc) call D_mpyS ; Here (ACCd,ACCc) = 00FF 7E01 ; call loadAB ; result of multiplying ACCb*ACCa->(ACCd,ACCc) call D_mpyF ; Here (ACCd,ACCc) = 00FF 7E01 ; call loadAB ; result of multiplying ACCb/ACCa->(ACCd,ACCc) call D_divS ; Here (ACCd,ACCc) = 0040 003f ;
0000
0000 0000 E02D 0001 E036 0002 E02D 0003 E03B 0004 E02D 0005 E050 0006 E02D 0007 E065 0008 E02D 0009 E119
DS00544D-page 4-8
© 1997 Microchip Technology Inc.
AN544
000A E02D 000B E138 000C 000D 000E 000F 0010 B0F3 0125 B0F6 0124 E27D 00117 00118 00119 00120 00121 00122 00123 00124 00125 00126 00127 00128 00129 00130 00131 00132 00133 00134 00135 00136 00137 00138 00139 00140 00141 00142 00143 00144 00145 00146 00147 00148 00149 00150 00151 00152 00153 00154 00155 00156 00157 00158 00159 00160 00161 00162 00163 00164 00165 00166 00167 00168 00169 00170 00171 00172 00173 00174 00175 00176 00177 00178 00179 00180 00181 00182 call call ; movlw movwf movlw movwf call ; ; movlw movwf movlw movwf call ; movlw movwf movlw movwf call 0xff mulplr 0xff mulcnd mpy8x8_S 0xff mulplr 0xff mulcnd mpy8x8_F xf3 NumHi xf6 NumLo Sqrt loadAB D_divF ; result of multiplying ACCb/ACCa->(ACCd,ACCc) ; Here (ACCd,ACCc) = 0040 003f
; Set input test number = 62454 ; = F3F6h ; result = 00F9h = 249 (in SqrtLo) ; exact sqrt(62454) = 249.9
0011 0012 0013 0014 0015 0016 0017 0018 0019 001A
B0FF 0119 B0FF 0118 E293 B0FF 0119 B0FF 0118 E2B8
; multiplier (in mulplr) = 0FF ; multiplicand(W Reg ) = 0FF ; The result 0FF*0FF = FE01 is in locations ; H_byte & L_byte ; multiplier (in mulplr) = 0FF ; multiplicand(W Reg ) = 0FF
001B 001C 001D 001E 001F 0020 0021 0022
B0FF 010D B05F 010E B030 0119 B045 0118
0023 C028 0024 0024 0025 0026 0027 0028 0028 0029 002A 002B
E311 A418 AE19 C024
E31E A41A AE1B C028
002C C02C 002D 002D 002E 002F 0030 0031 0032 0033 0034 0035
B001 0119 B0FF 0118 B07F 011B B0FF 011A 0002
; The result 0FF*0FF = FE01 is in locations ; ; H_byte & L_byte ; Test The Random Number Generators ; Capture data into trace buffer by TABLE WRITES to a ; dummy Program Memory location ; movlw 0xff movwf TBLPTRL movlw 0x5f movwf TBLPTRH ; movlw 0x30 movwf RandHi movlw 0x45 movwf RandLo ; goto GaussPoint ; RandPoint call Random16 tlwt _LOW,RandLo ; only for data capture tablwt _HIGH,0,RandHi ; using PICMASTER goto RandPoint ; GaussPoint call Gauss tlwt _LOW,GaussLo ; only for data capture tablwt _HIGH,0,GaussHi ; using PICMASTER goto GaussPoint ; self goto self ; End Of Test Routines ; loadAB movlw 0x01 movwf ACCaHI movlw 0xff ; loads ACCa = 01FF movwf ACCaLO ; movlw 0x7f movwf ACCbHI movlw 0xFF ; loads ACCb = 7FFF movwf ACCbLO return ; PAGE ;*******************************************************************
© 1997 Microchip Technology Inc.
DS00544D-page 4-9
AN544
00183 00184 00185 00186 00187 00188 00189 00190 00191 00192 00193 00194 00195 00196 00197 00198 00199 00200 00201 00202 00203 00204 00205 00206 00207 00208 00209 00210 00211 00212 00213 00214 00215 00216 00217 00218 00219 00220 00221 00222 00223 00224 00225 00226 00227 00228 00229 00230 00231 00232 00233 00234 00235 00236 00237 00238 00239 00240 00241 00242 00243 00244 00245 00246 00247 00248 ; Double Precision Arithmetic Routines ; ; Routines : Addition, Subtraction, Multiplication ,Division ; Square Root ; ; NOTE : MODE_FAST must first be set to either ; TRUE or FALSE ; ; MODE_FAST determines the RAM address locations of ACCa thru ACCd ; ; If MODE_FAST is set TRUE, data transfers can be done efficiently ; using "MOVFP" & "MOVPF" instructions instead of indirectly moving ; at first to W Reg and then to the desired RAM locations ; ; The speed increase using this way of locating ACCa to ; ACCd will result in a saving of about 20 Cycles/filter stage ; In this case ( a 2 stage filter), it is faster by 40 Cycles ; ; If due to other constraints, ACCa thru ACCd cannot be set at ; address 0x18 to 0x1f, then the user is required to set ; MODE_FAST to FALSE ; PAGE ;******************************************************************* ; Double Precision Addition ; ; 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 ) ; ; Performance : ; Program Memory : 4 (excluding call & return) ; Clock Cycles : 4 (excluding call & return) ; W Register : Used ; Scratch RAM : 0 ; ;*******************************************************************; ; D_add movfp ACCaLO,WREG addwf ACCbLO, F ;addwf lsb movfp ACCaHI,WREG addwfc ACCbHI, F ;addwf msb with carry return ; PAGE ;******************************************************************* ; Double Precision Subtraction ; ; 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 ) ; ; Performance : ; Program Memory : 4 (excluding call & return ) ; Clock Cycles : 4 (excluding call & return ) ; W Register : Used ; scratch RAM : 0 ;*******************************************************************; ; D_sub movfp ACCaLO,WREG
0036 0036 0037 0038 0039 003A
6A18 0F1A 6A19 111B 0002
003B 003B 6A18
DS00544D-page 4-10
© 1997 Microchip Technology Inc.
AN544
003C 003D 003E 003F 051A 6A19 031B 0002 00249 00250 00251 00252 00253 00254 00255 00256 00257 00258 00259 00260 00261 00262 00263 00264 00265 00266 00267 00268 00269 00270 00271 00272 00273 00274 00275 00276 00277 00278 00279 00280 00281 00282 00283 00284 00285 00286 00287 00288 00289 00290 00291 00292 00293 00294 00295 00296 00297 00298 00299 00300 00301 00302 00303 00304 00305 00306 00307 00308 00309 00310 00311 00312 00313 00314 subwf movfp subwfb return ; PAGE ;******************************************************************* ; Function to negate a 16 bit integer ; The two 8 bit integers are assumed to be in 2 consecutive ; locations. Before calling this routine, FSR0 should be loaded with ; the address of the lower byte. ; Assume that ALUSTA register is set for no autoincrement of ; FSR0. ;******************************************************************* ; negateAlt movfp INDF0,WREG bcf ALUSTA,FS1 negw INDF0, F bsf ALUSTA,FS1 movfp INDF0,WREG clrf INDF0, F subwfb INDF0, F return ; negate comf INDF0, F bcf ALUSTA,FS1 incf INDF0, F bsf ALUSTA,FS1 btfsc ALUSTA,Z decf INDF0, F comf INDF0, F return ; PAGE ;******************************************************************* ; Double Precision Multiplication ; ; ( Optimized for Code : Looped Code ) ; ; Multiplication : ACCb(16 bits) * ACCa(16 bits) -> ACCd,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_mpyS ; (d) The 32 bit result is in location ( ACCdHI,ACCdLO,ACCdHI,ACCdLO ) ; ; Performance : ; Program Memory : 21 (UNSIGNED) ; 52 (SIGNED) ; Clock Cycles : 242 (UNSIGNED :excluding CALL & RETURN) ; : 254 (SIGNED :excluding CALL & RETURN) ; Scratch RAM : 1 (used only if SIGNED arithmetic) ; ; 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. ; ; 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_mpyS ;results in ACCd(16 msb's) and ACCc(16 lsb's) ; ACCbLO, F ACCaHI,WREG ACCbHI, F
0040 0040 0041 0042 0043 0044 0045 0046 0047 0048 0048 0049 004A 004B 004C 004D 004E 004F
6A00 8D04 2D00 8504 6A00 2900 0300 0002
1300 8D04 1500 8504 9A04 0700 1300 0002
0050
© 1997 Microchip Technology Inc.
DS00544D-page 4-11
AN544
00315 00316 00317 00318 00319 00320 00321 00322 00323 00324 00325 00326 00327 00328 00329 00330 00331 00332 00333 00334 00335 00336 00337 00338 00339 00340 00341 00342 00343 00344 00345 00346 00347 00348 00349 00350 00351 00352 00353 00354 00355 00356 00357 00358 00359 00360 00361 00362 00363 00364 00365 00366 00367 00368 00369 00370 00371 00372 00373 00374 00375 00376 00377 00378 00379 00380 SIGNED CALL S_SIGN #endif ; clrf bsf ; #if MODE_FAST movpf movpf #else movfp movwf movfp movwf #endif clrf clrf ACCbLO,tempLo ACCbHI,tempHi ACCbLO,WREG tempLo ACCbHI,WREG empHi ACCdHI, F ACCdLO, F count, F count,4 ; set count = 16 #if
0050 2922 0051 8422
0052 5A20 0053 5B21
0054 291F 0055 291E
0056 0056 0057 0058 0059 005A 005B 005C 005D 005E 005E 005F 0060 0061 0062 0063
1921 1920 9004 C05E 6A18 0F1E 6A19 111F 191F 191E 191D 191C 1722 C056
0064 0002
; ; shift right and addwf 16 times ; mpyLoop rrcf tempHi, F rrcf tempLo, F btfss ALUSTA,C goto NoAdd ; LSB is 0, so no need to addwf movfp ACCaLO,WREG addwf ACCdLO, F ;addwf lsb movfp ACCaHI,WREG addwfc ACCdHI, F ;addwf msb NoAdd rrcf ACCdHI, F rrcf ACCdLO, F rrcf ACCcHI, F rrcf ACCcLO, F decfsz count, F goto mpyLoop ; #if SIGNED btfss sign,MSB return comf ACCcLO, F incf ACCcLO, F btfsc ALUSTA,Z decf ACCcHI, F comf ACCcHI, F btfsc ALUSTA,Z decf ACCdLO, F comf ACCdLO, F btfsc ALUSTA,Z decf ACCdHI, F comf ACCdHI, F return #else return #endif ; ; Assemble this section only if Signed Arithmetic Needed ; #if SIGNED ; S_SIGN movfp ACCaHI,WREG xorwf ACCbHI,W movwf sign ; MSB of sign determines whether signed
DS00544D-page 4-12
© 1997 Microchip Technology Inc.
AN544
00381 00382 00383 00384 00385 00386 00387 00388 00389 00390 00391 00392 00393 00394 00395 00396 00397 00398 00399 00400 00401 00402 00403 00404 00405 00406 00407 00408 00409 00410 00411 00412 00413 00414 00415 00416 00417 00418 00419 00420 00421 00422 00423 00424 00425 00426 00427 00428 00429 00430 00431 00432 00433 00434 00435 00436 00437 00438 00439 00440 00441 00442 00443 00444 00445 00446 btfss goto comf incf btfsc decf comf ; chek_A btfss return comf incf btfsc decf comf return ; #endif ; PAGE ;******************************************************************* ; Double Precision Multiplication ; ; ( Optimized for Speed : straight Line Code ) ; ; Multiplication : ACCb(16 bits) * ACCa(16 bits) -> ACCd,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 ( ACCdHI,ACCdLO,ACCdHI,ACCdLO ) ; ; Performance : ; Program Memory : 179 (UNSIGNED) ; 204 (SIGNED) ; Clock Cycles : 176 (UNSIGNED :excluding CALL & RETURN) ; : 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 variable i = 0 #if SIGNED variable MUL_LP_CNT = 15 #else variable MUL_LP_CNT = 16 #endif .while i < MUL_LP_CNT ; .if i < 8 ACCaHI,MSB ACCaLO, F ACCaLO, F ALUSTA,Z ACCaHI, F ACCaHI, F ; if MSB set go & negate ACCa ACCbHI,MSB chek_A ACCbLO, F ACCbLO, F ALUSTA,Z ACCbHI, F ACCbHI, F ; if MSB set go & negate ACCb
; negate ACCb
; negate ACCa
© 1997 Microchip Technology Inc.
DS00544D-page 4-13
AN544
00447 00448 00449 00450 00451 00452 00453 00454 00455 00456 00457 00458 00459 00460 00461 00462 00463 00464 00465 00466 00467 00468 00469 00470 00471 00472 00473 00474 00475 00476 00477 00478 00479 00480 00481 00482 00483 00484 00485 00486 00487 00488 00489 00490 00491 00492 00493 00494 00495 00496 00497 00498 00499 00500 00501 00502 00503 00504 00505 00506 00507 00508 00509 00510 00511 00512 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd#v(i) rrcf rrcf rrcf rrcf bcf variable .endw #if SIGNED rrcf rrcf rrcf rrcf bcf #endif ; ENDM ; PAGE ;*************************************************************** ; Double Precision Negate Macros ;*************************************************************** AltNegMac MACRO fileRegLo,fileRegHi movfp fileRegLo,WREG negw fileRegLo, F movfp fileRegHi,WREG clrf fileRegHi, F subwfb fileRegHi, F ENDM ; negMac ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd#v(i) ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ;addwf lsb ;addwf msb
ACCdHI, ACCdLO, ACCcHI, ACCcLO, ALUSTA,C
F F F F
MACRO comf incf btfsc decf comf ENDM
fileRegLo, fileRegLo, fileRegLo, ALUSTA,Z fileRegHi, fileRegHi,
fileRegHi F ; negate FileReg ( -FileReg -> FileReg ) F F F
; NegMac32 movfp negw movfp clrf subwfb movfp clrf subwfb movfp clrf subwfb ;
MACRO x3,x2,x1,x0 x3,WREG x3, F x2,WREG x2, F x2, F x1,WREG x1, F x1, F x0,WREG x0, F x0, F ENDM
PAGE ;*******************************************************************; ; Double Precision Multiply ( 16x16 -> 32 ) ; ( ACCb*ACCa -> ACCb,ACCc ) : 32 bit output with high word
DS00544D-page 4-14
© 1997 Microchip Technology Inc.
AN544
0065 00513 00514 00515 00516 00517 00518 00519 00520 00521 00522 00523 00524 00525 00526 00527 00528 00529 00530 00531 00532 00533 00534 00535 00536 00537 00538 00539 00540 00541 00542 M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M ; 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, F clrf ACCdLO, F bcf ALUSTA,C ; ; use the mulMac macro 16 times ; mulMac variable i variable i = 0 #if SIGNED variable MUL_LP_CNT = 15 #else variable MUL_LP_CNT = 16 #endif .while i < MUL_LP_CNT ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd0 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp ACCbLO,i ACCbHI,i-8 NoAdd1 ACCaLO,WREG ; test low byte ; test high byte ; LSB is 0, so no need to addwf ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd0 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb
0065 0065 291F 0066 291E 0067 8804
0000 0000
0010
0068 901A
0069 C06E 006A 6A18 006B 0F1E 006C 6A19 006D 111F 006E 006E 191F 006F 191E 0070 191D 0071 191C 0072 8804 0001
0073 911A
0074 C079 0075 6A18
© 1997 Microchip Technology Inc.
DS00544D-page 4-15
AN544
0076 0F1E 0077 6A19 0078 111F 0079 0079 191F 007A 191E 007B 191D 007C 191C 007D 8804 0002 M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M addwf movfp addwfc NoAdd1 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd2 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd3 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd4 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd4 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd3 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd2 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCdLO, F ACCaHI,WREG ACCdHI, F ;addwf lsb ;addwf msb
007E 921A
007F C084 0080 6A18 0081 0F1E 0082 6A19 0083 111F 0084 0084 191F 0085 191E 0086 191D 0087 191C 0088 8804 0003
0089 931A
008A C08F 008B 6A18 008C 0F1E 008D 6A19 008E 111F 008F 008F 191F 0090 191E 0091 191D 0092 191C 0093 8804 0004
0094 941A
0095 C09A 0096 6A18 0097 0F1E 0098 6A19 0099 111F 009A 009A 191F 009B 191E 009C 191D 009D 191C 009E 8804 0005
DS00544D-page 4-16
© 1997 Microchip Technology Inc.
AN544
009F 951A M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd5 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd6 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd7 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd8 rrcf rrcf ACCdHI, F ACCdLO, F ACCbLO,i ACCbHI,i-8 NoAdd8 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd7 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd6 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd5 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb
00A0 C0A5 00A1 6A18 00A2 0F1E 00A3 6A19 00A4 111F 00A5 00A5 191F 00A6 191E 00A7 191D 00A8 191C 00A9 8804 0006
00AA 961A
00AB C0B0 00AC 6A18 00AD 0F1E 00AE 6A19 00AF 111F 00B0 00B0 191F 00B1 191E 00B2 191D 00B3 191C 00B4 8804 0007
00B5 971A
00B6 C0BB 00B7 6A18 00B8 0F1E 00B9 6A19 00BA 111F 00BB 00BB 191F 00BC 191E 00BD 191D 00BE 191C 00BF 8804 0008
00C0 901B 00C1 00C2 00C3 00C4 00C5 00C6 00C6 00C7 C0C6 6A18 0F1E 6A19 111F 191F 191E
© 1997 Microchip Technology Inc.
DS00544D-page 4-17
AN544
00C8 191D 00C9 191C 00CA 8804 0009 M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd9 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd10 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd11 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp ACCbLO,i ACCbHI,i-8 NoAdd12 ACCaLO,WREG ; test low byte ; test high byte ; LSB is 0, so no need to addwf ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd11 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd10 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd9 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCcHI, F ACCcLO, F ALUSTA,C i = i+1
00CB 911B 00CC C0D1 00CD 6A18 00CE 0F1E 00CF 6A19 00D0 111F 00D1 00D1 191F 00D2 191E 00D3 191D 00D4 191C 00D5 8804 000A
00D6 921B 00D7 C0DC 00D8 6A18 00D9 0F1E 00DA 6A19 00DB 111F 00DC 00DC 191F 00DD 191E 00DE 191D 00DF 191C 00E0 8804 000B
00E1 931B 00E2 C0E7 00E3 6A18 00E4 0F1E 00E5 6A19 00E6 111F 00E7 00E7 191F 00E8 191E 00E9 191D 00EA 191C 00EB 8804 000C
00EC 941B 00ED C0F2 00EE 6A18
DS00544D-page 4-18
© 1997 Microchip Technology Inc.
AN544
00EF 0F1E 00F0 6A19 00F1 111F 00F2 00F2 191F 00F3 191E 00F4 191D 00F5 191C 00F6 8804 000D M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M addwf movfp addwfc NoAdd12 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd13 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd14 rrcf rrcf rrcf rrcf bcf variable ; .if i < 8 btfss .else btfss .fi goto movfp addwf movfp addwfc NoAdd15 rrcf rrcf rrcf rrcf bcf variable .endw #if SIGNED ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd15 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd14 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCbLO,i ACCbHI,i-8 NoAdd13 ACCaLO,WREG ACCdLO, F ACCaHI,WREG ACCdHI, F ; test low byte ; test high byte ; LSB is 0, so no need to addwf ; addwf lsb ; addwf msb ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C i = i+1 ACCdLO, F ACCaHI,WREG ACCdHI, F ;addwf lsb ;addwf msb
00F7 951B 00F8 C0FD 00F9 6A18 00FA 0F1E 00FB 6A19 00FC 111F 00FD 00FD 191F 00FE 191E 00FF 191D 0100 191C 0101 8804 000E
0102 961B 0103 C108 0104 6A18 0105 0F1E 0106 6A19 0107 111F 0108 0108 191F 0109 191E 010A 191D 010B 191C 010C 8804 000F
010D 971B 010E C113 010F 6A18 0110 0F1E 0111 6A19 0112 111F 0113 0113 191F 0114 191E 0115 191D 0116 191C 0117 8804 0010
© 1997 Microchip Technology Inc.
DS00544D-page 4-19
AN544
M M M M M M M 00543 00544 00545 00546 00547 00548 00549 00550 00551 00552 00553 00554 00555 00556 00557 00558 00559 00560 00561 00562 00563 00564 00565 00566 00567 00568 00569 00570 00571 00572 00573 00574 00575 00576 00577 00578 00579 00580 00581 00582 00583 00584 00585 00586 00587 00588 00589 00590 00591 00592 00593 00594 00595 00596 00597 00598 00599 00600 00601 rrcf rrcf rrcf rrcf bcf #endif ; ; #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) ; ACCdHI, F ACCdLO, F ACCcHI, F ACCcLO, F ALUSTA,C
0118 0002
DS00544D-page 4-20
© 1997 Microchip Technology Inc.
AN544
0119 0119 8404 011A 8504 00602 00603 00604 00605 00606 00607 00608 00609 00610 00611 00612 00613 00614 00615 00616 00617 00618 00619 00620 00621 00622 00623 00624 00625 00626 00627 00628 00629 00630 00631 00632 00633 00634 00635 00636 00637 00638 00639 00640 00641 00642 00643 00644 00645 00646 00647 00648 00649 00650 00651 00652 00653 00654 00655 00656 00657 00658 00659 00660 00661 00662 00663 00664 00665 00666 00667 ;******************************************************************* ; D_divS ; bsf ALUSTA,FS0 bsf ALUSTA,FS1 ; set no auto-incrment for fsr0 #if CALL #endif ; clrf bsf clrf clrf clrf clrf ; ; Looped code ; divLoop bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz btfss goto subca movfp subwf movfp subwfb bsf nosub rlcf rlcf decfsz goto ; #if SIGNED btfss return movlw movwf call movlw movwf call return #else return #endif ; PAGE ;******************************************************************* ; Double Precision Division ; sign,MSB ACCcLO fsr0 negate ACCdLO fsr0 negate count, F count,4 ACCcHI, F ACCcLO, F ACCdLO, F ACCdHI, F ; set count = 16 SIGNED S_SIGN
011B 011C 011D 011E 011F 0120
2922 8422 291D 291C 291E 291F
0121 0121 0122 0123 0124 0125 0126 0127 0128 0129 012A 012B 012C 012C 012D 012E 012E 012F 0130 0131 0132 0133 0133 0134 0135 0136
8804 1B1A 1B1B 1B1C 1B1D 6A19 041D 9204 C12C 6A18 041C 9004 C133 6A18 051C 6A19 031D 8004 1B1E 1B1F 1722 C121
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz ACCaLO,WREG ACCcLO,W ALUSTA,C nosub ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F count, F divLoop
; check if a>c
; if msb equal then check lsb ; carry set if c>a ; if c < a ; c-a into c
; shift a 1 into d (result)
0137 0002
© 1997 Microchip Technology Inc.
DS00544D-page 4-21
AN544
00668 00669 00670 00671 00672 00673 00674 00675 00676 00677 00678 00679 00680 00681 00682 00683 00684 00685 00686 00687 00688 00689 00690 00691 00692 00693 00694 00695 00696 00697 00698 00699 00700 00701 00702 00703 00704 00705 00706 00707 00708 00709 00710 00711 00712 00713 00714 00715 00716 00717 00718 00719 00720 00721 00722 00723 00724 00725 00726 00727 00728 00729 00730 00731 00732 00733 ; ( 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 variable i = 0 .while i < 16 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz#v(i) btfss goto subca#v(i) movfp subwf movfp subwfb bsf nosub#v(i) rlcf rlcf variable i=i+1 ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz#v(i) ACCaLO,WREG ACCcLO,W ALUSTA,C nosub#v(i) ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
DS00544D-page 4-22
© 1997 Microchip Technology Inc.
AN544
00734 00735 00736 00737 00738 00739 00740 00741 00742 00743 00744 00745 00746 00747 00748 00749 00750 00751 00752 00753 00754 00755 00756 00757 00758 00759 00760 00761 00762 00763 00764 00765 00766 00767 00768 00769 00770 00771 00772 00773 00774 00775 00776 00777 00778 00779 00780 00781 M M M M M M M M M M M M M M M M M M .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 clrf clrf clrf
0138
0138 0138 0139 013A 013B
291D 291C 291E 291F
ACCcHI, ACCcLO, ACCdLO, ACCdHI,
F F F F
0000 0000
; ; straight line code : using the macro divMac ; divMac variable i variable i = 0 .while i < 16 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf btfss goto ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz0 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub0
013C 013D 013E 013F 0140 0141 0142 0143 0144 0145 0146 0147 0148
8804 1B1A 1B1B 1B1C 1B1D 6A19 041D 9204 C147 6A18 041C 9004 C14E
; check if a>c
notz0
; if msb equal then check lsb ; carry set if c>a ; if c < a
© 1997 Microchip Technology Inc.
DS00544D-page 4-23
AN544
0149 6A18 014A 051C 014B 6A19 014C 031D 014D 8004 014E 1B1E 014F 1B1F 0001 0150 8804 0151 1B1A 0152 1B1B 0153 1B1C 0154 1B1D 0155 6A19 0156 041D 0157 9204 0158 C15B 0159 6A18 015A 041C 015B 9004 015C C162 015D 6A18 015E 051C 015F 6A19 0160 031D 0161 8004 0162 1B1E 0163 1B1F 0002 0164 8804 0165 1B1A 0166 1B1B 0167 1B1C 0168 1B1D 0169 6A19 016A 041D 016B 9204 016C C16F 016D 6A18 016E 041C 016F 9004 0170 C176 0171 6A18 0172 051C 0173 6A19 0174 031D 0175 8004 0176 1B1E 0177 1B1F 0003 0178 0179 017A 017B 017C 017D 017E 017F 0180 0181 0182 0183 0184 8804 1B1A 1B1B 1B1C 1B1D 6A19 041D 9204 C183 6A18 041C 9004 C18A M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M subca0 movfp subwf movfp subwfb bsf nosub0 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz1 btfss goto subca1 movfp subwf movfp subwfb bsf nosub1 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz2 btfss goto subca2 movfp subwf movfp subwfb bsf nosub2 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz3 btfss goto ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F ; c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz1 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub1 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz2 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub2 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz3 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub3
; check if a>c
; if msb equal then check lsb ; carry set if c>a ; if c < a
DS00544D-page 4-24
© 1997 Microchip Technology Inc.
AN544
0185 6A18 0186 051C 0187 6A19 0188 031D 0189 8004 018A 1B1E 018B 1B1F 0004 018C 8804 018D 1B1A 018E 1B1B 018F 1B1C 0190 1B1D 0191 6A19 0192 041D 0193 9204 0194 C197 0195 6A18 0196 041C 0197 9004 0198 C19E 0199 6A18 019A 051C 019B 6A19 019C 031D 019D 8004 019E 1B1E 019F 1B1F 0005 01A0 8804 01A1 1B1A 01A2 1B1B 01A3 1B1C 01A4 1B1D 01A5 6A19 01A6 041D 01A7 9204 01A8 C1AB 01A9 6A18 01AA 041C 01AB 9004 01AC C1B2 01AD 6A18 01AE 051C 01AF 6A19 01B0 031D 01B1 8004 01B2 1B1E 01B3 1B1F 0006 01B4 01B5 01B6 01B7 01B8 01B9 01BA 01BB 01BC 01BD 01BE 01BF 01C0 8804 1B1A 1B1B 1B1C 1B1D 6A19 041D 9204 C1BF 6A18 041C 9004 C1C6 M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M movfp subwf movfp subwfb bsf nosub3 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz4 btfss goto subca4 movfp subwf movfp subwfb bsf nosub4 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz5 btfss goto subca5 movfp subwf movfp subwfb bsf nosub5 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz6 btfss goto subca3 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F ; c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz4 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub4 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz5 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub5 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz6 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub6
; check if a>c
; if msb equal then check lsb ; carry set if c>a ; if c < a
© 1997 Microchip Technology Inc.
DS00544D-page 4-25
AN544
01C1 6A18 01C2 051C 01C3 6A19 01C4 031D 01C5 8004 01C6 1B1E 01C7 1B1F 0007 01C8 8804 01C9 1B1A 01CA 1B1B 01CB 1B1C 01CC 1B1D 01CD 6A19 01CE 041D 01CF 9204 01D0 C1D3 01D1 6A18 01D2 041C 01D3 9004 01D4 C1DA 01D5 6A18 01D6 051C 01D7 6A19 01D8 031D 01D9 8004 01DA 1B1E 01DB 1B1F 0008 01DC 8804 01DD 1B1A 01DE 1B1B 01DF 1B1C 01E0 1B1D 01E1 6A19 01E2 041D 01E3 9204 01E4 C1E7 01E5 6A18 01E6 041C 01E7 9004 01E8 C1EE 01E9 6A18 01EA 051C 01EB 6A19 01EC 031D 01ED 8004 01EE 1B1E 01EF 1B1F 0009 01F0 01F1 01F2 01F3 01F4 01F5 01F6 01F7 01F8 01F9 01FA 01FB 01FC 8804 1B1A 1B1B 1B1C 1B1D 6A19 041D 9204 C1FB 6A18 041C 9004 C202 M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M subca6 movfp subwf movfp subwfb bsf nosub6 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz7 btfss goto subca7 movfp subwf movfp subwfb bsf nosub7 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz8 btfss goto subca8 movfp subwf movfp subwfb bsf nosub8 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz9 btfss goto ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F ; c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz7 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub7 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz8 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub8 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz9 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub9
; check if a>c
; if msb equal then check lsb ; carry set if c>a ; if c < a
DS00544D-page 4-26
© 1997 Microchip Technology Inc.
AN544
01FD 6A18 01FE 051C 01FF 6A19 0200 031D 0201 8004 0202 1B1E 0203 1B1F 000A 0204 8804 0205 1B1A 0206 1B1B 0207 1B1C 0208 1B1D 0209 6A19 020A 041D 020B 9204 020C C20F 020D 6A18 020E 041C 020F 9004 0210 C216 0211 6A18 0212 051C 0213 6A19 0214 031D 0215 8004 0216 1B1E 0217 1B1F 000B 0218 8804 0219 1B1A 021A 1B1B 021B 1B1C 021C 1B1D 021D 6A19 021E 041D 021F 9204 0220 C223 0221 6A18 0222 041C 0223 9004 0224 C22A 0225 6A18 0226 051C 0227 6A19 0228 031D 0229 8004 022A 1B1E 022B 1B1F 000C 022C 022D 022E 022F 0230 0231 0232 0233 0234 0235 0236 0237 0238 8804 1B1A 1B1B 1B1C 1B1D 6A19 041D 9204 C237 6A18 041C 9004 C23E M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M movfp subwf movfp subwfb bsf nosub9 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz10 btfss goto subca10 movfp subwf movfp subwfb bsf nosub10 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz11 btfss goto subca11 movfp subwf movfp subwfb bsf nosub11 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz12 btfss goto subca9 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F ; c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz10 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub10 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz11 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub11 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz12 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub12
; check if a>c
; if msb equal then check lsb ; carry set if c>a ; if c < a
© 1997 Microchip Technology Inc.
DS00544D-page 4-27
AN544
0239 6A18 023A 051C 023B 6A19 023C 031D 023D 8004 023E 1B1E 023F 1B1F 000D 0240 8804 0241 1B1A 0242 1B1B 0243 1B1C 0244 1B1D 0245 6A19 0246 041D 0247 9204 0248 C24B 0249 6A18 024A 041C 024B 9004 024C C252 024D 6A18 024E 051C 024F 6A19 0250 031D 0251 8004 0252 1B1E 0253 1B1F 000E 0254 8804 0255 1B1A 0256 1B1B 0257 1B1C 0258 1B1D 0259 6A19 025A 041D 025B 9204 025C C25F 025D 6A18 025E 041C 025F 9004 0260 C266 0261 6A18 0262 051C 0263 6A19 0264 031D 0265 8004 0266 1B1E 0267 1B1F 000F 0268 0269 026A 026B 026C 026D 026E 026F 0270 0271 0272 0273 0274 8804 1B1A 1B1B 1B1C 1B1D 6A19 041D 9204 C273 6A18 041C 9004 C27A M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M subca12 movfp subwf movfp subwfb bsf nosub12 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz13 btfss goto subca13 movfp subwf movfp subwfb bsf nosub13 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz14 btfss goto subca14 movfp subwf movfp subwfb bsf nosub14 rlcf rlcf variable i=i+1 ; bcf rlcf rlcf rlcf rlcf movfp subwf btfss goto movfp subwf notz15 btfss goto ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F ; c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz13 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub13 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz14 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub14 ACCaLO,WREG ACCcLO, F ACCaHI,WREG ACCcHI, F ALUSTA,C ACCdLO, F ACCdHI, F
; check if a>c
; ; ; ;
if msb equal then check lsb carry set if c>a if c < a c-a into c
; shift a 1 into d (result)
ALUSTA,C ACCbLO, F ACCbHI, F ACCcLO, F ACCcHI, F ACCaHI,WREG ACCcHI,W ALUSTA,Z notz15 ACCaLO,WREG ACCcLO,W ALUSTA,C nosub15
; check if a>c
; if msb equal then check lsb ; carry set if c>a ; if c < a
DS00544D-page 4-28
© 1997 Microchip Technology Inc.
AN544
0275 6A18 0276 051C 0277 6A19 0278 031D 0279 8004 027A 1B1E 027B 1B1F 0010 M M M M M M M M M M 00782 00783 00784 00785 00786 00787 00788 00789 00790 00791 00792 00793 00794 00795 00796 00797 00798 00799 00800 00801 00802 00803 00804 00805 00806 00807 00808 00809 00810 00811 00812 00813 00814 00815 00816 00817 00818 00819 00820 00821 00822 00823 00824 00825 00826 00827 00828 00829 00830 00831 00832 00833 00834 00835 00836 00837 movfp ACCaLO,WREG ; c-a into c subwf ACCcLO, F movfp ACCaHI,WREG subwfb ACCcHI, F bsf ALUSTA,C ; shift a 1 into d (result) nosub15 rlcf ACCdLO, F rlcf ACCdHI, F variable i=i+1 .endw ; ; #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 ; ; Performance : ; Program Memory : 22 (excluding D_divS subroutine) ; Clock Cycles : 3000 (approximately,with 10 iterations) ; ; The #of cycles depends on Number of Iterations Selected. ; In a lot of cases 5 or less iterations may be sufficient ; ; ;******************************************************************* ; Newton-Raphson Method ;************************************************************* Sqrt call nextIter SqrtInit ; compute initial sqrt = Num/2 subca15
027C 0002
027D 027D E28B 027E
© 1997 Microchip Technology Inc.
DS00544D-page 4-29
AN544
027E 7A24 027F 7B25 00838 00839 00840 00841 00842 00843 00844 00845 00846 00847 00848 00849 00850 00851 00852 00853 00854 00855 00856 00857 00858 00859 00860 00861 00862 00863 00864 00865 00866 00867 00868 00869 00870 00871 00872 00873 00874 00875 00876 00877 00878 00879 00880 00881 00882 00883 00884 00885 00886 00887 00888 00889 00890 00891 00892 00893 00894 00895 00896 00897 00898 00899 00900 00901 00902 00903 #if MODE_FAST movfp movfp #else movfp movwf movfp movwf #endif ; call movfp addwf movfp addwfc bcf rrcf rrcf ; decfsz goto return ; SqrtInit movlw movwf #if MODE_FAST movfp movfp #else movfp movwf movfp movwf #endif bcf rrcf rrcf return ; PAGE ;******************************************************************* ; 8x8 Software Multi