| 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