Line No. | Rev | Author | Line |
---|---|---|---|
1 | 32 | kaklik | ; ********************************************************************* |
2 | ; * |
||
3 | ; * Big Integer Assembly Helpers |
||
4 | ; * Library for Microchip TCP/IP Stack |
||
5 | ; * - Accelerates processing for BigInt functions |
||
6 | ; * |
||
7 | ; ********************************************************************* |
||
8 | ; * FileName: BigInt_helper.asm |
||
9 | ; * Dependencies: None |
||
10 | ; * Processor: PIC18 |
||
11 | ; * Compiler: Microchip C18 v3.30 or higher |
||
12 | ; * Company: Microchip Technology, Inc. |
||
13 | ; * |
||
14 | ; * Software License Agreement |
||
15 | ; * |
||
16 | ; * Copyright (C) 2002-2009 Microchip Technology Inc. All rights |
||
17 | ; * reserved. |
||
18 | ; * |
||
19 | ; * Microchip licenses to you the right to use, modify, copy, and |
||
20 | ; * distribute: |
||
21 | ; * (i) the Software when embedded on a Microchip microcontroller or |
||
22 | ; * digital signal controller product ("Device") which is |
||
23 | ; * integrated into Licensee's product; or |
||
24 | ; * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h, |
||
25 | ; * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device |
||
26 | ; * used in conjunction with a Microchip ethernet controller for |
||
27 | ; * the sole purpose of interfacing with the ethernet controller. |
||
28 | ; * |
||
29 | ; * You should refer to the license agreement accompanying this |
||
30 | ; * Software for additional information regarding your rights and |
||
31 | ; * obligations. |
||
32 | ; * |
||
33 | ; * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT |
||
34 | ; * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT |
||
35 | ; * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A |
||
36 | ; * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
37 | ; * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR |
||
38 | ; * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF |
||
39 | ; * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS |
||
40 | ; * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE |
||
41 | ; * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER |
||
42 | ; * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT |
||
43 | ; * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE. |
||
44 | ; * |
||
45 | ; * |
||
46 | ; * Author Date Comment |
||
47 | ; *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
48 | ; * Elliott Wood 06/20/07 Original |
||
49 | ; * Howard Schlunder 11/15/07 Converted to little endian |
||
50 | ; ********************************************************************/ |
||
51 | |||
52 | BIGINT_VARS udata |
||
53 | global _iA |
||
54 | global _iB |
||
55 | global _iBr ; when B is a ROM pointer |
||
56 | global _iR |
||
57 | global _xA |
||
58 | global _xB |
||
59 | global _xBr ; when B is a ROM pointer |
||
60 | global _wC |
||
61 | _iA res 2 ;*_iA, starting pointer for A (low address) |
||
62 | _xA res 2 ;*_xA, end pointer for A (high address) |
||
63 | _iB res 2 ;*_iB, starting pointer for B (low address) |
||
64 | _xB res 2 ;*_xB, end pointer for B (high address) |
||
65 | _iBr res 3 ;*_iBr, starting pointer for B in ROM (low address) |
||
66 | _xBr res 3 ;*_xBr, end pointer for B in ROM (high address) |
||
67 | _iR res 2 ;*_iR, starting pointer for multiplication Result (low address) |
||
68 | _wC res 1 ;Value of C for _masBI (scalar) and _mul (temp storage) |
||
69 | |||
70 | CarryByte res 1 ;Value of carry for _mul and _sqr (scalar) |
||
71 | CarryH res 1 ;High value of carry for _sqr (scalar) |
||
72 | |||
73 | BIGINT_CODE code |
||
74 | |||
75 | #include p18cxxx.inc |
||
76 | #include P18MACRO.INC |
||
77 | |||
78 | |||
79 | ;*************************************************************************** |
||
80 | ; Function: void _addBI() |
||
81 | ; |
||
82 | ; PreCondition: _iA and _iB are loaded with the LSB of each BigInt |
||
83 | ; _xA and _xB are loaded with the MSB of each BigInt |
||
84 | ; A.size >= B.magnitude |
||
85 | ; A and B must both be 2048 bits or less (256 bytes) |
||
86 | ; |
||
87 | ; Input: A and B, the BigInts to add |
||
88 | ; |
||
89 | ; Output: A = A + B |
||
90 | ; |
||
91 | ; Side Effects: None |
||
92 | ; |
||
93 | ; Stack Req: 2 bytes |
||
94 | ; |
||
95 | ; Overview: Quickly performs the bulk addition of two BigInts |
||
96 | ;*************************************************************************** |
||
97 | GLOBAL _addBI |
||
98 | _addBI: |
||
99 | Stk2PushFromReg FSR2L ;Save FSR2 on the stack |
||
100 | banksel _xA ;select the assembly pointer bank |
||
101 | movff _iA+0x0,FSR0L ;Put iA in FSR0 |
||
102 | movff _iA+0x1,FSR0H |
||
103 | movff _iB+0x0,FSR2L ;Put iB in FSR2 |
||
104 | movff _iB+0x1,FSR2H |
||
105 | |||
106 | ; Predecrement A and B pointers |
||
107 | movf POSTDEC0, W |
||
108 | movf POSTDEC2, W |
||
109 | |||
110 | ; Calculate how many adds are needed divided by 8, store count in |
||
111 | ; PRODH |
||
112 | ; Note: This assumes there are no more than 256 adds to do |
||
113 | decf _iB+0x0, W |
||
114 | subwf _xB+0x0, W |
||
115 | andlw 0xF8 |
||
116 | movwf PRODH |
||
117 | swapf PRODH, F |
||
118 | rlncf PRODH, F |
||
119 | |||
120 | incf PRODH, F ; Preincrement so we can start the loop with a decrement |
||
121 | clrf PRODL ; Start out with no carry |
||
122 | bra aTest8Add |
||
123 | |||
124 | ; Add 8 bytes of B into A at a time. Doing it in such large |
||
125 | ; chunks saves loop and branch overhead |
||
126 | aDo8Add: |
||
127 | rrcf PRODL, F ; Load carry in value |
||
128 | movf PREINC2, W |
||
129 | addwfc PREINC0, F |
||
130 | movf PREINC2, W |
||
131 | addwfc PREINC0, F |
||
132 | movf PREINC2, W |
||
133 | addwfc PREINC0, F |
||
134 | movf PREINC2, W |
||
135 | addwfc PREINC0, F |
||
136 | movf PREINC2, W |
||
137 | addwfc PREINC0, F |
||
138 | movf PREINC2, W |
||
139 | addwfc PREINC0, F |
||
140 | movf PREINC2, W |
||
141 | addwfc PREINC0, F |
||
142 | movf PREINC2, W |
||
143 | addwfc PREINC0, F |
||
144 | rlcf PRODL, F ; Save carry out value |
||
145 | aTest8Add: |
||
146 | decf PRODH, F |
||
147 | bnz aDo8Add |
||
148 | |||
149 | |||
150 | rrcf PRODL, F ; Load carry in value |
||
151 | bra aTestResidualAdd |
||
152 | |||
153 | |||
154 | ; Add up to 7 bytes of B into A, one byte at a time. |
||
155 | aDoResidualAdd: |
||
156 | movf PREINC2, W |
||
157 | addwfc PREINC0, F |
||
158 | |||
159 | aTestResidualAdd: |
||
160 | movf FSR2L, W |
||
161 | xorwf _xB+0x0, W |
||
162 | bnz aDoResidualAdd |
||
163 | |||
164 | ; Carry forward the carry out (in A) if needed |
||
165 | bnc aDone |
||
166 | |||
167 | aDoFinalCarry: |
||
168 | movf FSR0L, W |
||
169 | xorwf _xA+0x0, W |
||
170 | bz aDone |
||
171 | incf PREINC0, F |
||
172 | bc aDoFinalCarry |
||
173 | |||
174 | aDone: |
||
175 | Stk2PopToReg FSR2L ;restore FSR2 from stack |
||
176 | return |
||
177 | |||
178 | |||
179 | ;*************************************************************************** |
||
180 | ; Function: void _addBIROM() |
||
181 | ; |
||
182 | ; PreCondition: _iA and _iBr are loaded with the LSB of each BigInt |
||
183 | ; _xA and _xBr are loaded with the MSB of each BigInt |
||
184 | ; A.size >= B.magnitude |
||
185 | ; A and B must both be 2048 bits or less (256 bytes) |
||
186 | ; |
||
187 | ; Input: A: a BigInt in RAM |
||
188 | ; B: a BigInt in ROM |
||
189 | ; |
||
190 | ; Output: A = A + B |
||
191 | ; |
||
192 | ; Side Effects: Overwrites TBLPTRU:TBLPTRH:TBLPTRL registers |
||
193 | ; |
||
194 | ; Stack Req: 0 bytes |
||
195 | ; |
||
196 | ; Overview: Quickly performs the bulk addition of two BigInts |
||
197 | ;*************************************************************************** |
||
198 | GLOBAL _addBIROM |
||
199 | _addBIROM: |
||
200 | banksel _xA ;Select the assembly pointer bank |
||
201 | movff _iA+0x0,FSR0L ;Put iA in FSR0 |
||
202 | movff _iA+0x1,FSR0H |
||
203 | movff _iBr+0x0,TBLPTRL ;Put iB in TBLPTR |
||
204 | movff _iBr+0x1,TBLPTRH |
||
205 | movff _iBr+0x2,TBLPTRU |
||
206 | |||
207 | ; Predecrement A and B pointers |
||
208 | movf POSTDEC0, W |
||
209 | tblrd*- |
||
210 | |||
211 | ; Calculate how many adds are needed divided by 8, store count in |
||
212 | ; PRODH |
||
213 | ; Note: This assumes there are no more than 256 adds to do |
||
214 | decf _iBr+0x0, W |
||
215 | subwf _xBr+0x0, W |
||
216 | andlw 0xF8 |
||
217 | movwf PRODH |
||
218 | swapf PRODH, F |
||
219 | rlncf PRODH, F |
||
220 | |||
221 | incf PRODH, F ; Preincrement so we can start the loop with a decrement |
||
222 | clrf PRODL ; Start out with no carry |
||
223 | bra aRTest8Add |
||
224 | |||
225 | ; Add 8 bytes of B into A at a time. Doing it in such large |
||
226 | ; chunks saves loop and branch overhead |
||
227 | aRDo8Add: |
||
228 | rrcf PRODL, F ; Load carry in value |
||
229 | tblrd+* |
||
230 | movf TABLAT, W |
||
231 | addwfc PREINC0, F |
||
232 | tblrd+* |
||
233 | movf TABLAT, W |
||
234 | addwfc PREINC0, F |
||
235 | tblrd+* |
||
236 | movf TABLAT, W |
||
237 | addwfc PREINC0, F |
||
238 | tblrd+* |
||
239 | movf TABLAT, W |
||
240 | addwfc PREINC0, F |
||
241 | tblrd+* |
||
242 | movf TABLAT, W |
||
243 | addwfc PREINC0, F |
||
244 | tblrd+* |
||
245 | movf TABLAT, W |
||
246 | addwfc PREINC0, F |
||
247 | tblrd+* |
||
248 | movf TABLAT, W |
||
249 | addwfc PREINC0, F |
||
250 | tblrd+* |
||
251 | movf TABLAT, W |
||
252 | addwfc PREINC0, F |
||
253 | rlcf PRODL, F ; Save carry out value |
||
254 | aRTest8Add: |
||
255 | decf PRODH, F |
||
256 | bnz aRDo8Add |
||
257 | |||
258 | |||
259 | rrcf PRODL, F ; Load carry in value |
||
260 | bra aRTestResidualAdd |
||
261 | |||
262 | |||
263 | ; Add up to 7 bytes of B into A, one byte at a time. |
||
264 | aRDoResidualAdd: |
||
265 | tblrd+* |
||
266 | movf TABLAT, W |
||
267 | addwfc PREINC0, F |
||
268 | |||
269 | aRTestResidualAdd: |
||
270 | movf TBLPTRL, W |
||
271 | xorwf _xBr+0x0, W |
||
272 | bnz aRDoResidualAdd |
||
273 | |||
274 | ; Carry forward the carry out (in A) if needed |
||
275 | bnc aRDone |
||
276 | |||
277 | aRDoFinalCarry: |
||
278 | movf FSR0L, W |
||
279 | xorwf _xA+0x0, W |
||
280 | bz aRDone |
||
281 | incf PREINC0, F |
||
282 | bc aRDoFinalCarry |
||
283 | |||
284 | aRDone: |
||
285 | return |
||
286 | |||
287 | |||
288 | ;*************************************************************************** |
||
289 | ; Function: void _subBI() |
||
290 | ; |
||
291 | ; PreCondition: _iA and _iB are loaded with the LSB of each BigInt |
||
292 | ; _xA and _xB are loaded with the MSB of each BigInt |
||
293 | ; A.size >= B.magnitude |
||
294 | ; A and B must both be 2048 bits or less (256 bytes) |
||
295 | ; |
||
296 | ; Input: A and B, the BigInts to subtract |
||
297 | ; |
||
298 | ; Output: A = A - B |
||
299 | ; |
||
300 | ; Side Effects: None |
||
301 | ; |
||
302 | ; Stack Req: 2 bytes |
||
303 | ; |
||
304 | ; Overview: Quickly performs the bulk subtraction of two BigInts |
||
305 | ;*************************************************************************** |
||
306 | GLOBAL _subBI |
||
307 | _subBI: |
||
308 | Stk2PushFromReg FSR2L ;Save FSR2 on the stack |
||
309 | banksel _xA ;select the assembly pointer bank |
||
310 | movff _iA+0x0,FSR0L ;Put iA in FSR0 |
||
311 | movff _iA+0x1,FSR0H |
||
312 | movff _iB+0x0,FSR2L ;Put iB in FSR2 |
||
313 | movff _iB+0x1,FSR2H |
||
314 | |||
315 | ; Predecrement A and B pointers |
||
316 | movf POSTDEC0, W |
||
317 | movf POSTDEC2, W |
||
318 | |||
319 | ; Calculate how many subtracts are needed divided by 8, store |
||
320 | ; count in PRODH |
||
321 | ; Note: This assumes there are no more than 256 subtracts to do |
||
322 | decf _iB+0x0, W |
||
323 | subwf _xB+0x0, W |
||
324 | andlw 0xF8 |
||
325 | movwf PRODH |
||
326 | swapf PRODH, F |
||
327 | rlncf PRODH, F |
||
328 | |||
329 | incf PRODH, F ; Preincrement so we can start the loop with a decrement |
||
330 | setf PRODL ; Start out with no borrow |
||
331 | bra sTest8Subtract |
||
332 | |||
333 | ; Add 8 bytes of B into A at a time. Doing it in such large |
||
334 | ; chunks saves loop and branch overhead |
||
335 | sDo8Subtract: |
||
336 | rrcf PRODL, F ; Load borrow in value |
||
337 | movf PREINC2, W |
||
338 | subwfb PREINC0, F |
||
339 | movf PREINC2, W |
||
340 | subwfb PREINC0, F |
||
341 | movf PREINC2, W |
||
342 | subwfb PREINC0, F |
||
343 | movf PREINC2, W |
||
344 | subwfb PREINC0, F |
||
345 | movf PREINC2, W |
||
346 | subwfb PREINC0, F |
||
347 | movf PREINC2, W |
||
348 | subwfb PREINC0, F |
||
349 | movf PREINC2, W |
||
350 | subwfb PREINC0, F |
||
351 | movf PREINC2, W |
||
352 | subwfb PREINC0, F |
||
353 | rlcf PRODL, F ; Save borrow out value |
||
354 | sTest8Subtract: |
||
355 | decf PRODH, F |
||
356 | bnz sDo8Subtract |
||
357 | |||
358 | |||
359 | rrcf PRODL, F ; Load borrow in value |
||
360 | bra sTestResidualSubtract |
||
361 | |||
362 | |||
363 | ; Subtract up to 7 bytes of B from A, one byte at a time. |
||
364 | sDoResidualSubtract: |
||
365 | movf PREINC2, W |
||
366 | subwfb PREINC0, F |
||
367 | |||
368 | sTestResidualSubtract: |
||
369 | movf FSR2L, W |
||
370 | xorwf _xB+0x0, W |
||
371 | bnz sDoResidualSubtract |
||
372 | |||
373 | ; Carry forward the borrow out (in A) if needed |
||
374 | bc sDone |
||
375 | |||
376 | sDoFinalCarry: |
||
377 | movf FSR0L, W |
||
378 | xorwf _xA+0x0, W |
||
379 | bz sDone |
||
380 | decf PREINC0, F |
||
381 | bnc sDoFinalCarry |
||
382 | |||
383 | sDone: |
||
384 | Stk2PopToReg FSR2L ;restore FSR2 from stack |
||
385 | return |
||
386 | |||
387 | |||
388 | ;*************************************************************************** |
||
389 | ; Function: void _subBIROM() |
||
390 | ; |
||
391 | ; PreCondition: _iA and _iBr are loaded with the LSB of each BigInt |
||
392 | ; _xA and _xBr are loaded with the MSB of each BigInt |
||
393 | ; A.size >= B.magnitude |
||
394 | ; A and B must both be 2048 bits or less (256 bytes) |
||
395 | ; |
||
396 | ; Input: A: a BigInt in RAM |
||
397 | ; B: a BigInt in ROM |
||
398 | ; |
||
399 | ; Output: A = A - B |
||
400 | ; |
||
401 | ; Side Effects: Overwrites TBLPTRU:TBLPTRH:TBLPTRL registers |
||
402 | ; |
||
403 | ; Stack Req: None |
||
404 | ; |
||
405 | ; Overview: Quickly performs the bulk subtraction of two BigInts |
||
406 | ;*************************************************************************** |
||
407 | GLOBAL _subBIROM |
||
408 | _subBIROM: |
||
409 | banksel _xA ;Select the assembly pointer bank |
||
410 | movff _iA+0x0,FSR0L ;Put iA in FSR0 |
||
411 | movff _iA+0x1,FSR0H |
||
412 | movff _iBr+0x0,TBLPTRL ;Put iB in TBLPTR |
||
413 | movff _iBr+0x1,TBLPTRH |
||
414 | movff _iBr+0x2,TBLPTRU |
||
415 | |||
416 | ; Predecrement A and B pointers |
||
417 | movf POSTDEC0, W |
||
418 | tblrd*- |
||
419 | |||
420 | ; Calculate how many adds are needed divided by 8, store count in |
||
421 | ; PRODH |
||
422 | ; Note: This assumes there are no more than 256 adds to do |
||
423 | decf _iBr+0x0, W |
||
424 | subwf _xBr+0x0, W |
||
425 | andlw 0xF8 |
||
426 | movwf PRODH |
||
427 | swapf PRODH, F |
||
428 | rlncf PRODH, F |
||
429 | |||
430 | incf PRODH, F ; Preincrement so we can start the loop with a decrement |
||
431 | setf PRODL ; Start out with no borrow |
||
432 | bra sRTest8Subtract |
||
433 | |||
434 | ; Subtract 8 bytes of B from A at a time. Doing it in such large |
||
435 | ; chunks saves loop and branch overhead |
||
436 | sRDo8Subtract: |
||
437 | rrcf PRODL, F ; Load borrow in value |
||
438 | tblrd+* |
||
439 | movf TABLAT, W |
||
440 | subwfb PREINC0, F |
||
441 | tblrd+* |
||
442 | movf TABLAT, W |
||
443 | subwfb PREINC0, F |
||
444 | tblrd+* |
||
445 | movf TABLAT, W |
||
446 | subwfb PREINC0, F |
||
447 | tblrd+* |
||
448 | movf TABLAT, W |
||
449 | subwfb PREINC0, F |
||
450 | tblrd+* |
||
451 | movf TABLAT, W |
||
452 | subwfb PREINC0, F |
||
453 | tblrd+* |
||
454 | movf TABLAT, W |
||
455 | subwfb PREINC0, F |
||
456 | tblrd+* |
||
457 | movf TABLAT, W |
||
458 | subwfb PREINC0, F |
||
459 | tblrd+* |
||
460 | movf TABLAT, W |
||
461 | subwfb PREINC0, F |
||
462 | rlcf PRODL, F ; Save borrow out value |
||
463 | sRTest8Subtract: |
||
464 | decf PRODH, F |
||
465 | bnz sRDo8Subtract |
||
466 | |||
467 | |||
468 | rrcf PRODL, F ; Load borrow in value |
||
469 | bra sRTestResidualSubtract |
||
470 | |||
471 | |||
472 | ; Subtract up to 7 bytes of B from A, one byte at a time. |
||
473 | sRDoResidualSubtract: |
||
474 | tblrd+* |
||
475 | movf TABLAT, W |
||
476 | subwfb PREINC0, F |
||
477 | |||
478 | sRTestResidualSubtract: |
||
479 | movf TBLPTRL, W |
||
480 | xorwf _xBr+0x0, W |
||
481 | bnz sRDoResidualSubtract |
||
482 | |||
483 | ; Carry forward the borrow out (in A) if needed |
||
484 | bc sRDone |
||
485 | |||
486 | sRDoFinalCarry: |
||
487 | movf FSR0L, W |
||
488 | xorwf _xA+0x0, W |
||
489 | bz sRDone |
||
490 | incf PREINC0, F |
||
491 | bnc sRDoFinalCarry |
||
492 | |||
493 | sRDone: |
||
494 | return |
||
495 | |||
496 | |||
497 | ;*************************************************************************** |
||
498 | ; Function: void _zeroBI() |
||
499 | ; |
||
500 | ; PreCondition: _iA is loaded with the LSB of the BigInt |
||
501 | ; _xA is loaded with the MSB the BigInt |
||
502 | ; |
||
503 | ; Input: A: a BigInt |
||
504 | ; |
||
505 | ; Output: A = 0 |
||
506 | ; |
||
507 | ; Side Effects: None |
||
508 | ; |
||
509 | ; Stack Req: None |
||
510 | ; |
||
511 | ; Overview: Sets all bytes from _iA to _xA to zero |
||
512 | ;*************************************************************************** |
||
513 | GLOBAL _zeroBI |
||
514 | _zeroBI: |
||
515 | banksel _xA ;select the assembly pointer bank |
||
516 | movff _iA+0x0,FSR0L ;Put iA-1 in FSR0 |
||
517 | movff _iA+0x1,FSR0H |
||
518 | movf POSTDEC0, W |
||
519 | |||
520 | zLoop: |
||
521 | clrf PREINC0 ;set byte to zero |
||
522 | movf FSR0L,W ;check if A is at MSB |
||
523 | xorwf _xA+0x0,W ;test low byte first |
||
524 | bnz zLoop ;add to A, and continue |
||
525 | movf FSR0H,W ;check high byte |
||
526 | xorwf _xA+0x1,W ; |
||
527 | bnz zLoop ;if A is not at MSB, we're not done |
||
528 | |||
529 | return |
||
530 | |||
531 | |||
532 | ;*************************************************************************** |
||
533 | ; Function: void _msbBI() |
||
534 | ; |
||
535 | ; PreCondition: _iA is loaded with the address of the LSB of the BigInt buffer |
||
536 | ; _xA is loaded with the address of the right most byte of the BigInt buffer |
||
537 | ; |
||
538 | ; Input: None |
||
539 | ; |
||
540 | ; Output: _xA is now pointing to the MSB of the BigInt |
||
541 | ; |
||
542 | ; Side Effects: None |
||
543 | ; |
||
544 | ; Overview: Finds the MSB (first non-zero word) of the BigInt, starting |
||
545 | ; from the right-most word and testing to the left. This |
||
546 | ; function will stop if _iA is reached. |
||
547 | ;*************************************************************************** |
||
548 | GLOBAL _msbBI |
||
549 | _msbBI: |
||
550 | banksel _xA ; Select the correct bank |
||
551 | movff _xA+0x0,FSR0L ; Put xA in FSR0 |
||
552 | movff _xA+0x1,FSR0H |
||
553 | |||
554 | msbLoop: |
||
555 | movf FSR0L, W |
||
556 | subwf _iA+0x0, W |
||
557 | bz msbFound |
||
558 | movf POSTDEC0, W ; load the next value |
||
559 | bz msbLoop ; if value isn't zero, this is the MSB |
||
560 | |||
561 | movf PREINC0, W ; Correct the pointer's last decrement |
||
562 | |||
563 | ; Copy FSR0 back to _xA and return |
||
564 | msbFound: |
||
565 | movff FSR0L,_xA+0x0 ; Move FSR0 back to iA |
||
566 | movff FSR0H,_xA+0x1 |
||
567 | return |
||
568 | |||
569 | |||
570 | ;*************************************************************************** |
||
571 | ; Function: void _mulBI() |
||
572 | ; |
||
573 | ; PreCondition: _iA and _iB are loaded with the LSB of each BigInt |
||
574 | ; _xA and _xB are loaded with the MSB of each BigInt |
||
575 | ; _iR is the LSB of the accumulator BigInt |
||
576 | ; _iR is zeroed, and has enough space |
||
577 | ; A and B must both by 2048 bits or less (256 bytes max) |
||
578 | ; |
||
579 | ; Input: A and B, the BigInts to multiply |
||
580 | ; |
||
581 | ; Output: R = A * B |
||
582 | ; |
||
583 | ; Side Effects: None |
||
584 | ; |
||
585 | ; Stack Req: 2 bytes |
||
586 | ; |
||
587 | ; Overview: Performs the bulk multiplication of two BigInts |
||
588 | ;*************************************************************************** |
||
589 | GLOBAL _mulBI |
||
590 | _mulBI: |
||
591 | Stk2PushFromReg FSR2L ;Save FSR2 on the stack |
||
592 | banksel _xA ;select the assembly pointer bank |
||
593 | |||
594 | ; Predecrement B and R pointers |
||
595 | clrf WREG |
||
596 | decf _iB+0x0, F |
||
597 | subwfb _iB+0x1, F |
||
598 | decf _iR+0x0, F |
||
599 | subwfb _iR+0x1, F |
||
600 | |||
601 | mLoadB: |
||
602 | ; Load B pointer to FSR2 and increment B pointer |
||
603 | ; Increment iR to match the new starting position |
||
604 | ; Fetch new B value |
||
605 | movff _iB+0x0, FSR2L |
||
606 | movff _iB+0x1, FSR2H |
||
607 | clrf WREG |
||
608 | mLoadBAgain: |
||
609 | incf _iB+0x0, F |
||
610 | addwfc _iB+0x1, F |
||
611 | incf _iR+0x0, F |
||
612 | addwfc _iR+0x1, F |
||
613 | movf PREINC2, W |
||
614 | bz mLoadBAgain ; No need to multiply this byte if it is zero |
||
615 | movwf _wC |
||
616 | |||
617 | ; Restore iA start pointer in FSR0 |
||
618 | movff _iA+0x0, FSR0L |
||
619 | movff _iA+0x1, FSR0H |
||
620 | |||
621 | ; Store new iR start pointer in FSR2 |
||
622 | movff _iR+0x0, FSR2L |
||
623 | movff _iR+0x1, FSR2H |
||
624 | |||
625 | ; Clear carry byte |
||
626 | clrf CarryByte |
||
627 | |||
628 | mLoopA: |
||
629 | movf CarryByte, W ;load carry byte |
||
630 | addwf INDF2, F ;add to accumulator |
||
631 | clrf CarryByte ;clear carry byte |
||
632 | rlcf CarryByte, F ;if a carry occurred, save to CarryByte |
||
633 | movf _wC, W ;load wC |
||
634 | mulwf POSTINC0 ;calculate wC * A[iA++] |
||
635 | movf PRODL,W ;load low result byte |
||
636 | addwf POSTINC2, F ;add to accumulator, and move ptr |
||
637 | movf PRODH,W ;load high result byte |
||
638 | addwfc CarryByte, F ;add to carry byte, along with |
||
639 | ; any carry from previous addition |
||
640 | |||
641 | ; See if A loop is done |
||
642 | decf FSR0L, W |
||
643 | xorwf _xA+0x0, W |
||
644 | bnz mLoopA |
||
645 | |||
646 | ; If A loop is done, finish out the carrying |
||
647 | movff CarryByte, INDF2 ;save carry byte (always adding to zero) |
||
648 | |||
649 | ; See if B loop is done |
||
650 | movf _xB+0x0, W |
||
651 | xorwf _iB+0x0, W |
||
652 | bnz mLoadB |
||
653 | |||
654 | mDone: |
||
655 | Stk2PopToReg FSR2L ;restore old FSR2 |
||
656 | return |
||
657 | |||
658 | |||
659 | ;*************************************************************************** |
||
660 | ; Function: void _mulBIROM() |
||
661 | ; |
||
662 | ; PreCondition: _iA and _iBr are loaded with the LSB of each BigInt |
||
663 | ; _xA and _xBr are loaded with the MSB of each BigInt |
||
664 | ; _iR is the LSB of the accumulator BigInt |
||
665 | ; _iR is zeroed, and has enough space |
||
666 | ; |
||
667 | ; Input: A: BigInt in RAM |
||
668 | ; B: BigInt in ROM |
||
669 | ; |
||
670 | ; Output: R = A * B |
||
671 | ; |
||
672 | ; Side Effects: Overwrites TBLPTRU:TBLPTRH:TBLPTRL |
||
673 | ; |
||
674 | ; Stack Req: 2 bytes |
||
675 | ; |
||
676 | ; Overview: Performs the bulk multiplication of two BigInts |
||
677 | ;*************************************************************************** |
||
678 | GLOBAL _mulBIROM |
||
679 | _mulBIROM: |
||
680 | Stk2PushFromReg FSR2L ;Save FSR2 on the stack |
||
681 | banksel _xA ;select the assembly pointer bank |
||
682 | |||
683 | ; Predecrement B and R pointers |
||
684 | movff _iBr+0x0, TBLPTRL |
||
685 | movff _iBr+0x1, TBLPTRH |
||
686 | movff _iBr+0x2, TBLPTRU |
||
687 | tblrd*- |
||
688 | clrf WREG |
||
689 | decf _iR+0x0, F |
||
690 | subwfb _iR+0x1, F |
||
691 | |||
692 | mRLoadB: |
||
693 | ; Increment iR to match the new starting position |
||
694 | ; Fetch new B value |
||
695 | clrf WREG |
||
696 | mRLoadBAgain: |
||
697 | incf _iR+0x0, F |
||
698 | addwfc _iR+0x1, F |
||
699 | tblrd+* |
||
700 | movf TABLAT, W |
||
701 | bz mRLoadBAgain ; No need to multiply this byte if it is zero |
||
702 | movwf _wC |
||
703 | |||
704 | ; Restore iA start pointer in FSR0 |
||
705 | movff _iA+0x0, FSR0L |
||
706 | movff _iA+0x1, FSR0H |
||
707 | |||
708 | ; Store new iR start pointer in FSR2 |
||
709 | movff _iR+0x0, FSR2L |
||
710 | movff _iR+0x1, FSR2H |
||
711 | |||
712 | ; Clear carry byte |
||
713 | clrf CarryByte |
||
714 | |||
715 | mRLoopA: |
||
716 | movf CarryByte, W ;load carry byte |
||
717 | addwf INDF2, F ;add to accumulator |
||
718 | clrf CarryByte ;clear carry byte |
||
719 | rlcf CarryByte, F ;if a carry occurred, save to CarryByte |
||
720 | movf _wC, W ;load wC |
||
721 | mulwf POSTINC0 ;calculate wC * A[iA++] |
||
722 | movf PRODL,W ;load low result byte |
||
723 | addwf POSTINC2, F ;add to accumulator, and move ptr |
||
724 | movf PRODH,W ;load high result byte |
||
725 | addwfc CarryByte, F ;add to carry byte, along with |
||
726 | ; any carry from previous addition |
||
727 | |||
728 | ; See if A loop is done |
||
729 | decf FSR0L, W |
||
730 | xorwf _xA+0x0, W |
||
731 | bnz mRLoopA |
||
732 | |||
733 | ; If A loop is done, finish out the carrying |
||
734 | movff CarryByte, INDF2 ;save carry byte (always adding to zero) |
||
735 | |||
736 | ; See if B loop is done |
||
737 | movf _xBr+0x0, W |
||
738 | xorwf TBLPTRL, W |
||
739 | bnz mRLoadB |
||
740 | |||
741 | mRDone: |
||
742 | Stk2PopToReg FSR2L ;restore old FSR2 |
||
743 | return |
||
744 | |||
745 | |||
746 | ;*************************************************************************** |
||
747 | ; Function: void _sqrBI() |
||
748 | ; |
||
749 | ; PreCondition: _iA is loaded with the LSB of the BigInt |
||
750 | ; _xA is loaded with the MSB of the BigInt |
||
751 | ; _iR is the LSB of the accumulator BigInt |
||
752 | ; _iR is zeroed, and has enough space |
||
753 | ; |
||
754 | ; Input: A: Source BigInt to square |
||
755 | ; R: Output location |
||
756 | ; |
||
757 | ; Output: R = A * A |
||
758 | ; |
||
759 | ; Side Effects: None |
||
760 | ; |
||
761 | ; Stack Req: 6 bytes |
||
762 | ; |
||
763 | ; Overview: Performs the bulk multiplication of two BigInts |
||
764 | ;*************************************************************************** |
||
765 | GLOBAL _sqrBI |
||
766 | _sqrBI: |
||
767 | Stk2PushFromReg FSR2L ;Save FSR2 on the stack |
||
768 | banksel _iA ;select the assembly pointer bank |
||
769 | |||
770 | ;decement iA (to set up for termination case) |
||
771 | clrf WREG ;load zero to W |
||
772 | decf _iA,F ;decrement iA |
||
773 | subwfb _iA+0x1,F ;borrow if needed |
||
774 | |||
775 | ;set up for outer loop over all values of A |
||
776 | Stk2PushFromReg _iR ;save initial iR to stack |
||
777 | Stk2PushFromReg _iA ;save initial iA to stack |
||
778 | |||
779 | qOuterLoop: |
||
780 | Stk2PopToReg FSR0L ;pop next iA from stack |
||
781 | Stk2PopToReg FSR2L ;pop next iR from stack |
||
782 | |||
783 | ;check if outer loop is done |
||
784 | movf FSR0L,W ;check if low byte of A ptr |
||
785 | xorwf _xA+0x0,W ; equals low byte of stop ptr |
||
786 | bnz qNextOut ;if not, work on next byte of A |
||
787 | movf FSR0H,W ;check if high byte of A ptr |
||
788 | xorwf _xA+0x1,W ; equals high byte of stop ptr |
||
789 | bz qDone ;if so, terminate |
||
790 | |||
791 | qNextOut: |
||
792 | ;save next value of iR |
||
793 | movf PREINC2,W ;decrement iR twice for next value |
||
794 | movf PREINC2,W |
||
795 | Stk2PushFromReg FSR2L ;save next value of iR to stack |
||
796 | movf POSTDEC2,W ;restore iR value |
||
797 | movf POSTDEC2,W |
||
798 | |||
799 | ;save next value of iA |
||
800 | movf PREINC0,W ;decrement iA for next value |
||
801 | Stk2PushFromReg FSR0L ;save next value of iA to stack |
||
802 | |||
803 | ;load wC with value of A[iA--] |
||
804 | ;check wC==0, if so then we can skip this byte |
||
805 | movf POSTDEC0,W ;restore iA and copy value |
||
806 | bz qOuterLoop ;if B==0, continue to next byte |
||
807 | movwf _wC ; into temporary byte |
||
808 | |||
809 | ;set up for inner loop over all remaining values in A |
||
810 | clrf CarryByte ;clear carry bytes |
||
811 | clrf CarryH |
||
812 | |||
813 | ;first result only gets accumulated once |
||
814 | mulwf PREINC0 ;square first byte (W = B above) |
||
815 | movf PRODL,W ;load PRODL |
||
816 | addwf POSTINC2,F ;accumulate |
||
817 | movf PRODH,W ;load PRODH |
||
818 | addwfc CarryByte,F ;save carry byte (with prev carry) |
||
819 | |||
820 | qInnerLoop: |
||
821 | ;if A isn't complete, keep looping |
||
822 | movf FSR0L,W ;check if low byte of A ptr |
||
823 | xorwf _xA+0x0,W ; equals low byte of stop ptr |
||
824 | bnz qInnerByte ;if not, continue looping |
||
825 | movf FSR0H,W ;check if high byte of A ptr |
||
826 | xorwf _xA+0x1,W ; equals high byte of stop ptr |
||
827 | bz qInnerDone ;if not, continue looping |
||
828 | |||
829 | qInnerByte: |
||
830 | ;all future bytes get accumulated twice |
||
831 | movf CarryByte,W ;load carry byte |
||
832 | addwf INDF2,F ;add to accumulator |
||
833 | movff CarryH,CarryByte ;move high carry byte down |
||
834 | clrf CarryH |
||
835 | btfsc STATUS,C ;if a carry occurred |
||
836 | incf CarryByte,F ; add 1 to the carry byte |
||
837 | movf _wC,W ;load B |
||
838 | mulwf PREINC0 ;calculate B * A[iA--] |
||
839 | bcf STATUS,C ;multiply product by 2 |
||
840 | rlcf PRODL,F |
||
841 | rlcf PRODH,F |
||
842 | btfsc STATUS,C ;if a carry occurrs |
||
843 | incf CarryH,F ; save 1 to the CarryH byte |
||
844 | movf PRODL,W ;load low result byte |
||
845 | addwf POSTINC2,F ;add to accumulator, and move ptr |
||
846 | movf PRODH,W ;load high result byte |
||
847 | addwfc CarryByte,F ;add to carry byte, along with |
||
848 | ; any carry from previous addition |
||
849 | btfsc STATUS,C ;if a carry occurrs |
||
850 | incf CarryH,F ; save 1 to the CarryH byte |
||
851 | bra qInnerLoop |
||
852 | |||
853 | |||
854 | qInnerDone |
||
855 | ;A is complete, finish out the carrying |
||
856 | movf CarryByte,W ;accumulate the carry bytes |
||
857 | addwf POSTINC2,F |
||
858 | movf CarryH,W |
||
859 | addwfc INDF2 |
||
860 | bra qOuterLoop |
||
861 | |||
862 | qDone: |
||
863 | ;movff FSR2L,_iR+0x0 |
||
864 | ;movff FSR2H,_iR+0x1 |
||
865 | Stk2PopToReg FSR2L ;restore old FSR2 |
||
866 | return |
||
867 | |||
868 | |||
869 | ;*************************************************************************** |
||
870 | ; Function: void _masBI() |
||
871 | ; |
||
872 | ; PreCondition: _iB is loaded with the LSB of the modulus BigInt |
||
873 | ; _xB is loaded with the MSB of the modulus BigInt |
||
874 | ; _wC is loaded with the 8 bit integer by which to multiply |
||
875 | ; _iR is the starting LSB of the decumulator BigInt |
||
876 | ; B must be 256 bytes or less |
||
877 | ; |
||
878 | ; Input: B: a BigInt to multiply with wC |
||
879 | ; wC: a simple scalar |
||
880 | ; R: a BigInt decumulator to subtract the result from |
||
881 | ; |
||
882 | ; Output: R = R - (B * wC) |
||
883 | ; |
||
884 | ; Side Effects: None |
||
885 | ; |
||
886 | ; Stack Req: 2 bytes |
||
887 | ; |
||
888 | ; Overview: Performs a Multiply And Subtract function. This is used in |
||
889 | ; the modulus calculation. |
||
890 | ; |
||
891 | ; Note: As an optimization, the final borrow forward propagation |
||
892 | ; is commented out below. This results in an a potentially |
||
893 | ; incorrect result in R, but for the BigIntMod() algorithm, |
||
894 | ; the final borrow forward propagation would be both unneeded |
||
895 | ; and unwanted. For BigIntMod(), this underflow is repaired |
||
896 | ; by adding B back into R one or two times. |
||
897 | ;*************************************************************************** |
||
898 | GLOBAL _masBI |
||
899 | _masBI: |
||
900 | Stk2PushFromReg FSR2L ;Save FSR2 on the stack |
||
901 | banksel _xB ;select the assembly pointer bank |
||
902 | |||
903 | ; Load B pointer into FSR2 and R pointer into FSR0 |
||
904 | movff _iR+0x0, FSR0L ;load iR into FSR0 |
||
905 | movff _iR+0x1, FSR0H |
||
906 | movff _iB+0x0, FSR2L ;load iB into FSR2 |
||
907 | movff _iB+0x1, FSR2H |
||
908 | |||
909 | ; Predecrement B pointer |
||
910 | movf POSTDEC2, W |
||
911 | |||
912 | ; Calculate loop counters for /4 and /1 |
||
913 | masLoop4Init: |
||
914 | clrf CarryByte |
||
915 | movf FSR2L, W |
||
916 | subwf _xB+0x0, W |
||
917 | bcf STATUS, C |
||
918 | rrcf WREG, W |
||
919 | rlcf CarryByte |
||
920 | rrcf WREG, W |
||
921 | btfsc STATUS, C |
||
922 | bsf CarryByte, 1 |
||
923 | movwf CarryH |
||
924 | |||
925 | movf CarryH, F |
||
926 | bz masLoopInit |
||
927 | |||
928 | clrf WREG |
||
929 | |||
930 | masLoop4: |
||
931 | subwf INDF0, F ;subtract from decumulator |
||
932 | movf _wC, W ;load B |
||
933 | mulwf PREINC2 ;calculate wC * B[iB--] |
||
934 | btfss STATUS, C ;if a borrow occurred |
||
935 | incf PRODH, F ; save 1 to the carry byte |
||
936 | movf PRODL, W ;load low result byte |
||
937 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
938 | movf PRODH, W |
||
939 | btfss STATUS, C |
||
940 | incf PRODH, W |
||
941 | |||
942 | subwf INDF0, F ;subtract from decumulator |
||
943 | movf _wC, W ;load B |
||
944 | mulwf PREINC2 ;calculate wC * B[iB--] |
||
945 | btfss STATUS, C ;if a borrow occurred |
||
946 | incf PRODH, F ; save 1 to the carry byte |
||
947 | movf PRODL, W ;load low result byte |
||
948 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
949 | movf PRODH, W |
||
950 | btfss STATUS, C |
||
951 | incf PRODH, W |
||
952 | |||
953 | subwf INDF0, F ;subtract from decumulator |
||
954 | movf _wC, W ;load B |
||
955 | mulwf PREINC2 ;calculate wC * B[iB--] |
||
956 | btfss STATUS, C ;if a borrow occurred |
||
957 | incf PRODH, F ; save 1 to the carry byte |
||
958 | movf PRODL, W ;load low result byte |
||
959 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
960 | movf PRODH, W |
||
961 | btfss STATUS, C |
||
962 | incf PRODH, W |
||
963 | |||
964 | subwf INDF0, F ;subtract from decumulator |
||
965 | movf _wC, W ;load B |
||
966 | mulwf PREINC2 ;calculate wC * B[iB--] |
||
967 | btfss STATUS, C ;if a borrow occurred |
||
968 | incf PRODH, F ; save 1 to the carry byte |
||
969 | movf PRODL, W ;load low result byte |
||
970 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
971 | movf PRODH, W |
||
972 | btfss STATUS, C |
||
973 | incf PRODH, W |
||
974 | |||
975 | ; See if we've looped through all (B bytes)/4 |
||
976 | decfsz CarryH, F |
||
977 | bra masLoop4 |
||
978 | |||
979 | |||
980 | masLoopInit: |
||
981 | movf CarryByte, F |
||
982 | bz masFinalBorrow |
||
983 | |||
984 | masLoop: |
||
985 | subwf INDF0, F ;subtract from decumulator |
||
986 | movf _wC, W ;load B |
||
987 | mulwf PREINC2 ;calculate wC * B[iB--] |
||
988 | btfss STATUS, C ;if a borrow occurred |
||
989 | incf PRODH, F ; save 1 to the carry byte |
||
990 | movf PRODL, W ;load low result byte |
||
991 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
992 | movf PRODH, W |
||
993 | btfss STATUS, C |
||
994 | incf PRODH, W |
||
995 | |||
996 | ; See if we've looped through all B bytes in the residual |
||
997 | decfsz CarryByte, F |
||
998 | bra masLoop |
||
999 | |||
1000 | ; If B is complete, finish out the borrow and return |
||
1001 | masFinalBorrow: |
||
1002 | subwf POSTINC0, F |
||
1003 | |||
1004 | Stk2PopToReg FSR2L ;restore old FSR2 |
||
1005 | return |
||
1006 | |||
1007 | |||
1008 | ;*************************************************************************** |
||
1009 | ; Function: void _masBIROM() |
||
1010 | ; |
||
1011 | ; PreCondition: _iBr is loaded with the LSB of the modulus BigInt |
||
1012 | ; _xBr is loaded with the MSB of the modulus BigInt |
||
1013 | ; _wC is loaded with the 8 bit integer by which to multiply |
||
1014 | ; _iR is the starting LSB of the decumulator BigInt |
||
1015 | ; Br must be 256 bytes or less |
||
1016 | ; |
||
1017 | ; Input: Br: a BigInt in ROM to multiply with wC |
||
1018 | ; wC: a simple scalar |
||
1019 | ; R: a BigInt decumulator in RAM to subtract the result from |
||
1020 | ; |
||
1021 | ; Output: R = R - (Br * wC) |
||
1022 | ; |
||
1023 | ; Side Effects: Overwrites TBLPTRU:TBLPTRH:TBLPTRL |
||
1024 | ; |
||
1025 | ; Stack Req: None |
||
1026 | ; |
||
1027 | ; Overview: Performs a Multiply And Subtract function. This is used in |
||
1028 | ; the modulus calculation. |
||
1029 | ; |
||
1030 | ; Note: As an optimization, the final borrow forward propagation |
||
1031 | ; is commented out below. This results in an a potentially |
||
1032 | ; incorrect result in R, but for the BigIntMod() algorithm, |
||
1033 | ; the final borrow forward propagation would be both unneeded |
||
1034 | ; and unwanted. For BigIntMod(), this underflow is repaired |
||
1035 | ; by adding B back into R one or two times. |
||
1036 | ;*************************************************************************** |
||
1037 | GLOBAL _masBIROM |
||
1038 | _masBIROM: |
||
1039 | banksel _xB ;select the assembly pointer bank |
||
1040 | |||
1041 | ; Load B pointer into TBLPTR and R pointer into FSR0 |
||
1042 | movff _iR+0x0, FSR0L ;load iR into FSR0 |
||
1043 | movff _iR+0x1, FSR0H |
||
1044 | movff _iBr+0x0, TBLPTRL ;load iBr into TBLPTR |
||
1045 | movff _iBr+0x1, TBLPTRH |
||
1046 | movff _iBr+0x2, TBLPTRU |
||
1047 | |||
1048 | ; Predecrement Br pointer and set up carry byte |
||
1049 | tblrd*- |
||
1050 | |||
1051 | ; Calculate loop counters for /4 and /1 |
||
1052 | masRLoop4Init: |
||
1053 | clrf CarryByte |
||
1054 | movf TBLPTRL, W |
||
1055 | subwf _xBr+0x0, W |
||
1056 | bcf STATUS, C |
||
1057 | rrcf WREG, W |
||
1058 | rlcf CarryByte |
||
1059 | rrcf WREG, W |
||
1060 | btfsc STATUS, C |
||
1061 | bsf CarryByte, 1 |
||
1062 | movwf CarryH |
||
1063 | |||
1064 | movf CarryH, F |
||
1065 | bz masRLoopInit |
||
1066 | |||
1067 | clrf WREG |
||
1068 | |||
1069 | masRLoop4: |
||
1070 | subwf INDF0, F ;subtract from decumulator |
||
1071 | movf _wC, W ;load B |
||
1072 | tblrd+* |
||
1073 | mulwf TABLAT ;calculate wC * B[iB--] |
||
1074 | btfss STATUS, C ;if a borrow occurred |
||
1075 | incf PRODH, F ; save 1 to the carry byte |
||
1076 | movf PRODL, W ;load low result byte |
||
1077 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
1078 | movf PRODH, W |
||
1079 | btfss STATUS, C |
||
1080 | incf PRODH, W |
||
1081 | |||
1082 | subwf INDF0, F ;subtract from decumulator |
||
1083 | movf _wC, W ;load B |
||
1084 | tblrd+* |
||
1085 | mulwf TABLAT ;calculate wC * B[iB--] |
||
1086 | btfss STATUS, C ;if a borrow occurred |
||
1087 | incf PRODH, F ; save 1 to the carry byte |
||
1088 | movf PRODL, W ;load low result byte |
||
1089 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
1090 | movf PRODH, W |
||
1091 | btfss STATUS, C |
||
1092 | incf PRODH, W |
||
1093 | |||
1094 | subwf INDF0, F ;subtract from decumulator |
||
1095 | movf _wC, W ;load B |
||
1096 | tblrd+* |
||
1097 | mulwf TABLAT ;calculate wC * B[iB--] |
||
1098 | btfss STATUS, C ;if a borrow occurred |
||
1099 | incf PRODH, F ; save 1 to the carry byte |
||
1100 | movf PRODL, W ;load low result byte |
||
1101 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
1102 | movf PRODH, W |
||
1103 | btfss STATUS, C |
||
1104 | incf PRODH, W |
||
1105 | |||
1106 | subwf INDF0, F ;subtract from decumulator |
||
1107 | movf _wC, W ;load B |
||
1108 | tblrd+* |
||
1109 | mulwf TABLAT ;calculate wC * B[iB--] |
||
1110 | btfss STATUS, C ;if a borrow occurred |
||
1111 | incf PRODH, F ; save 1 to the carry byte |
||
1112 | movf PRODL, W ;load low result byte |
||
1113 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
1114 | movf PRODH, W |
||
1115 | btfss STATUS, C |
||
1116 | incf PRODH, W |
||
1117 | |||
1118 | ; See if we've looped through all B bytes |
||
1119 | decfsz CarryH, F |
||
1120 | bra masRLoop4 |
||
1121 | |||
1122 | |||
1123 | masRLoopInit: |
||
1124 | movf CarryByte, F |
||
1125 | bz masRFinalBorrow |
||
1126 | |||
1127 | masRLoop: |
||
1128 | subwf INDF0, F ;subtract from decumulator |
||
1129 | movf _wC, W ;load B |
||
1130 | tblrd+* |
||
1131 | mulwf TABLAT ;calculate wC * B[iB--] |
||
1132 | btfss STATUS, C ;if a borrow occurred |
||
1133 | incf PRODH, F ; save 1 to the carry byte |
||
1134 | movf PRODL, W ;load low result byte |
||
1135 | subwf POSTINC0, F ;subtract from decumulator, and move ptr |
||
1136 | movf PRODH, W |
||
1137 | btfss STATUS, C |
||
1138 | incf PRODH, W |
||
1139 | |||
1140 | ; See if we've looped through all B bytes in the residual |
||
1141 | decfsz CarryByte, F |
||
1142 | bra masRLoop |
||
1143 | |||
1144 | ; If B is complete, finish out the borrow and return |
||
1145 | masRFinalBorrow: |
||
1146 | subwf POSTINC0, F |
||
1147 | |||
1148 | return |
||
1149 | |||
1150 | |||
1151 | ;*************************************************************************** |
||
1152 | ; Function: void _copyBI() |
||
1153 | ; |
||
1154 | ; PreCondition: _iA and _iB are loaded with the LSB of each BigInt |
||
1155 | ; _xA and _xB are loaded with the MSB of each BigInt |
||
1156 | ; B must be 256 bytes or less |
||
1157 | ; |
||
1158 | ; Input: A: the destination |
||
1159 | ; B: the source |
||
1160 | ; |
||
1161 | ; Output: A = B |
||
1162 | ; |
||
1163 | ; Side Effects: None |
||
1164 | ; |
||
1165 | ; Stack Req: 2 bytes |
||
1166 | ; |
||
1167 | ; Overview: Copies a value from BigInt B into BigInt A. If A has more |
||
1168 | ; bytes allocated than B, then the most significant bytes in |
||
1169 | ; A are zero padded. If A has less bytes allocated than B, |
||
1170 | ; then the most significant bytes are truncated off in A. |
||
1171 | ;*************************************************************************** |
||
1172 | GLOBAL _copyBI |
||
1173 | _copyBI: |
||
1174 | Stk2PushFromReg FSR2L ;Save FSR2 on the stack |
||
1175 | banksel _xA ;select the assembly pointer bank |
||
1176 | |||
1177 | ;Load and predecrement iA, iB (to set up termination case) |
||
1178 | movff _iA+0x0, FSR0L ;load iA into FSR0 |
||
1179 | movff _iA+0x1, FSR0H |
||
1180 | movff _iB+0x0, FSR2L ;load iB into FSR2 |
||
1181 | movff _iB+0x1, FSR2H |
||
1182 | movf POSTDEC0, W |
||
1183 | movf POSTDEC2, W |
||
1184 | |||
1185 | cLoop: |
||
1186 | movff PREINC2, PREINC0 ;copy B to A |
||
1187 | movf FSR2L, W ;check if low byte of B ptr |
||
1188 | xorwf _xB+0x0, W ; equals low byte of stop ptr |
||
1189 | bz cZeroTest ;if so, B is done, so clear rest of A |
||
1190 | |||
1191 | movf FSR0L, W ;check if low byte of A ptr |
||
1192 | xorwf _xA+0x0, W ; equals low byte of stop ptr |
||
1193 | bnz cLoop ;if not, continue |
||
1194 | movf FSR0H, W ;check if high byte of A ptr |
||
1195 | xorwf _xA+0x1, W ; equals high byte of stop ptr |
||
1196 | bnz cLoop ;if so, terminate |
||
1197 | |||
1198 | bra cZeroTest |
||
1199 | |||
1200 | cZero: |
||
1201 | clrf PREINC0 ;set A byte to zero |
||
1202 | |||
1203 | cZeroTest: |
||
1204 | movf FSR0L, W ;check if low byte of A ptr |
||
1205 | xorwf _xA+0x0, W ; equals low byte of stop ptr |
||
1206 | bnz cZero ;if not, continue |
||
1207 | movf FSR0H, W ;check if high byte of A ptr |
||
1208 | xorwf _xA+0x1, W ; equals high byte of stop ptr |
||
1209 | bnz cZero ;if so, terminate |
||
1210 | |||
1211 | Stk2PopToReg FSR2L ;restore old FSR2 |
||
1212 | return |
||
1213 | |||
1214 | |||
1215 | end |
Powered by WebSVN v2.8.3