?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

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
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3