comparison src/math.asm @ 643:7d8a4c60ec1a

3.15 release
author heinrichsweikamp
date Mon, 24 May 2021 18:40:53 +0200
parents 4050675965ea
children 75e90cd0c2c3
comparison
equal deleted inserted replaced
642:a9a0188091e4 643:7d8a4c60ec1a
344 addwfc isr_xC+2,F ; propagate carry 344 addwfc isr_xC+2,F ; propagate carry
345 clrf WREG ; ... 345 clrf WREG ; ...
346 addwfc isr_xC+3,F ; ... 346 addwfc isr_xC+3,F ; ...
347 return ; done 347 return ; done
348 348
349 ;=============================================================================
350 math12 CODE
351 ;=============================================================================
349 352
350 ;----------------------------------------------------------------------------- 353 ;-----------------------------------------------------------------------------
351 ; Multiply two SIGNED 16 Bit Integers: isr_xC = isr_xA * isr_xB 354 ; Multiply two SIGNED 16 Bit Integers: isr_xC = isr_xA * isr_xB
352 ; 355 ;
353 ; trashes PRODL, PRODH, WREG 356 ; trashes PRODL, PRODH, WREG
354 ; 357 ;
355 global isr_signed_mult16x16 358 global isr_signed_mult16x16
356 isr_signed_mult16x16: 359 isr_signed_mult16x16:
357 ; do an unsigned multiplication first 360 ; do an unsigned multiplication first
358 rcall isr_unsigned_mult16x16 361 call isr_unsigned_mult16x16
359 362
360 ; manage sign extension of operand B 363 ; manage sign extension of operand B
361 btfss isr_xB+1,7 ; is B negative ? 364 btfss isr_xB+1,7 ; is B negative ?
362 bra isr_signed_mult_checkA ; NO - continue checking operand A 365 bra isr_signed_mult_checkA ; NO - continue checking operand A
363 movf isr_xA+0,W ; YES - add -65536 * A 366 movf isr_xA+0,W ; YES - add -65536 * A
364 subwf isr_xC+2,F ; - ... 367 subwf isr_xC+2,F ; - ...
365 movf isr_xA+1,W ; - ... 368 movf isr_xA+1,W ; - ...
366 subwfb isr_xC+3,F ; - ... 369 subwfb isr_xC+3,F ; - ...
367 isr_signed_mult_checkA ; manage sign extension of operand B 370 isr_signed_mult_checkA: ; manage sign extension of operand B
368 btfss isr_xA+1,7 ; is A negative ? 371 btfss isr_xA+1,7 ; is A negative ?
369 return ; NO - done 372 return ; NO - done
370 movf isr_xB+0,W ; YES - add -65536 * B 373 movf isr_xB+0,W ; YES - add -65536 * B
371 subwf isr_xC+2,F ; - ... 374 subwf isr_xC+2,F ; - ...
372 movf isr_xB+1,W ; - ... 375 movf isr_xB+1,W ; - ...
373 subwfb isr_xC+3,F ; - ... 376 subwfb isr_xC+3,F ; - ...
374 return ; - done 377 return ; - done
375 378
379 ;=============================================================================
380 math13 CODE
381 ;=============================================================================
382
383 ;-----------------------------------------------------------------------------
384 ; Multiply two UNSIGNED 24 Bit Integers: isr_xC = isr_xA * isr_xB
385 ;
386 ; trashes PRODL, PRODH, WREG
387 ;
388 global isr_unsigned_mult24x24
389 isr_unsigned_mult24x24:
390 call isr_unsigned_mult16x16 ; Do the 16x16 first
391 clrf isr_xC+4
392 clrf isr_xC+5 ; clear upper 16 bit
393 ; do the remaining three multiplications
394 movf isr_xA+0,W ; multiply a[0] * b[2]
395 mulwf isr_xB+2 ; ...
396 movf PRODL,W ; add cross product to c[4]:c[3]:c[2]
397 addwf isr_xC+2,F ; ...
398 movf PRODH,W ; ...
399 addwfc isr_xC+3,F ; propagate carry
400 clrf WREG ; ...
401 addwfc isr_xC+4,F ; ...
402 addwfc isr_xC+5,F ; ...
403
404 movf isr_xA+2,W ; multiply a[2] * b[0]
405 mulwf isr_xB+0 ; ...
406 movf PRODL,W ; add cross product to c[4]:c[3]:c[2]
407 addwf isr_xC+2,F ; ...
408 movf PRODH,W ; ...
409 addwfc isr_xC+3,F ; propagate carry
410 clrf WREG ; ...
411 addwfc isr_xC+4,F ; ...
412 addwfc isr_xC+5,F ; ...
413 ; isr_xC[2] done.
414
415 movf isr_xA+2,W ; multiply a[2] * b[1]
416 mulwf isr_xB+1 ; ...
417 movf PRODL,W ; add cross product to c[5]:c[4]:c[3]
418 addwf isr_xC+3,F ; ...
419 movf PRODH,W ; ...
420 addwfc isr_xC+4,F ; propagate carry
421 clrf WREG ; ...
422 addwfc isr_xC+5,F ; ...
423
424 movf isr_xA+1,W ; multiply a[1] * b[2]
425 mulwf isr_xB+2 ; ...
426 movf PRODL,W ; add cross product to c[5]:c[4]:c[3]
427 addwf isr_xC+3,F ; ...
428 movf PRODH,W ; ...
429 addwfc isr_xC+4,F ; propagate carry
430 clrf WREG ; ...
431 addwfc isr_xC+5,F ; ...
432 ; isr_xC[3] done.
433
434 movf isr_xA+2,W ; multiply a[2] * b[2]
435 mulwf isr_xB+2 ; ...
436 movf PRODL,W ; add cross product to c[5]:c[4]
437 addwf isr_xC+4,F ; ...
438 movf PRODH,W ; ...
439 addwfc isr_xC+5,F ; propagate carry
440 ; isr_xC[4] done.
441 ; isr_xC[5] done.
442
443 return ; done
444
445 ;=============================================================================
446 math14 CODE
447 ;=============================================================================
448
449 ;-----------------------------------------------------------------------------
450 ; Multiply two UNSIGNED Integers (32 and 24 Bit): isr_xC = isr_xA * isr_xB
451 ;
452 ; trashes PRODL, PRODH, WREG
453 ;
454 global isr_unsigned_mult32x24
455 isr_unsigned_mult32x24:
456 call isr_unsigned_mult24x24 ; Do the 24x24 first
457 clrf isr_xC+6 ; clear upper 8 bit
458 ; do the remaining three multiplications
459 movf isr_xA+3,W ; multiply a[3] * b[0]
460 mulwf isr_xB+0 ; ...
461 movf PRODL,W ; add cross product to c[5]:c[4]:c[3]
462 addwf isr_xC+3,F ; ...
463 movf PRODH,W ; ...
464 addwfc isr_xC+4,F ; propagate carry
465 clrf WREG ; ...
466 addwfc isr_xC+5,F ; ...
467 addwfc isr_xC+6,F ; ...
468 ; isr_xC[3] done.
469
470 movf isr_xA+3,W ; multiply a[3] * b[1]
471 mulwf isr_xB+1 ; ...
472 movf PRODL,W ; add cross product to c[5]:c[4]
473 addwf isr_xC+4,F ; ...
474 movf PRODH,W ; ...
475 addwfc isr_xC+5,F ; propagate carry
476 clrf WREG ; ...
477 addwfc isr_xC+6,F ; ...
478 ; isr_xC[4] done.
479
480 movf isr_xA+3,W ; multiply a[3] * b[2]
481 mulwf isr_xB+2 ; ...
482 movf PRODL,W ; add cross product to c[5]:c[4]
483 addwf isr_xC+5,F ; ...
484 movf PRODH,W ; ...
485 addwfc isr_xC+6,F ; propagate carry
486 ; isr_xC[5] done.
487 ; isr_xC[6] done.
488 return ; done
489
490
491 ;=============================================================================
492 math15 CODE
493 ;=============================================================================
494
495 ;-----------------------------------------------------------------------------
496 ; Multiply two SIGNED 24 Bit Integers: isr_xC = isr_xA * isr_xB
497 ;
498 ; trashes PRODL, PRODH, WREG
499 ;
500 global isr_signed_mult24x24
501 isr_signed_mult24x24:
502 ; do an unsigned multiplication first
503 call isr_unsigned_mult24x24
504
505 ; manage sign extension of operand B
506 btfss isr_xB+2,7 ; is B negative ?
507 bra isr_signed24_mult_checkA ; NO - continue checking operand A
508 movf isr_xA+0,W ; YES - add -16777216 * A
509 subwf isr_xC+3,F ; - ...
510 movf isr_xA+1,W ; - ...
511 subwfb isr_xC+4,F ; - ...
512 movf isr_xA+2,W ; - ...
513 subwfb isr_xC+5,F ; - ...
514 isr_signed24_mult_checkA: ; manage sign extension of operand B
515 btfss isr_xA+2,7 ; is A negative ?
516 return ; NO - done
517 movf isr_xB+0,W ; YES - add -16777216 * B
518 subwf isr_xC+3,F ; - ...
519 movf isr_xB+1,W ; - ...
520 subwfb isr_xC+4,F ; - ...
521 movf isr_xB+2,W ; - ...
522 subwfb isr_xC+5,F ; - ...
523 return
524
525 ;=============================================================================
526 math16 CODE
527 ;=============================================================================
528
529 ;-----------------------------------------------------------------------------
530 ; Divide two UNSIGNED 16 Bit Integers: isr_xC:2 = isr_xA:2 / isr_xB:2 with xA as remainder
531 ;
532 ; trashes WREG
533 ;
534 global isr_div16x16
535 isr_div16x16:
536 movlw .16 ; process 16 bits ...
537 movwf isr_math_loop ; ... initialize loop counter
538 movff isr_xA+0,isr_xC+0 ; copy isr_xA to isr_xC
539 movff isr_xA+1,isr_xC+1 ; ...
540 clrf isr_xA+0 ; clear isr_xA, will now be used to hold the remainder
541 clrf isr_xA+1 ; ...
542 isr_div16x16_1:
543 bcf STATUS,C ; clear carry flag to shift in a zero bit
544 rlcf isr_xC+0,F ; shift left isr_xC
545 rlcf isr_xC+1,F ; ... shifting MSB out of isr_xC...
546 rlcf isr_xA+0,F ; ... and into LSB of isr_xA
547 rlcf isr_xA+1,F ; ...
548 btfsc STATUS,C ; did the remainder overflow (carry set)?
549 bra isr_div16x16_2 ; YES - directly generate a result bit = 1
550 movf isr_xB+0,W ; NO - compute remainder - divisor = isr_xA - isr_xB, trash result to WREG
551 subwf isr_xA+0,W ; - ...
552 movf isr_xB+1,W ; - ...
553 subwfb isr_xA+1,W ; - ...
554 btfss STATUS,C ; - remainder < divisor (-> borrow flag set, equals carry flag cleared) ?
555 bra isr_div16x16_3 ; YES - result bit = 0, keep LSB of isr_xC+0 being 0
556 isr_div16x16_2:
557 bsf isr_xC+0,0 ; NO - result bit = 1, set LSB of isr_xC+0 to 1
558 movf isr_xB+0,W ; - subtract divisor from remainder "for real": isr_xA = isr_xA - isr_xB
559 subwf isr_xA+0,F ; - ...
560 movf isr_xB+1,W ; - ...
561 subwfb isr_xA+1,F ; - ...
562 isr_div16x16_3:
563 decfsz isr_math_loop,F ; decrement loop counter, all bits done?
564 bra isr_div16x16_1 ; NO - loop
565 return ; YES - done
566
567 ;=============================================================================
568 math17 CODE
569 ;=============================================================================
570
571 ;-----------------------------------------------------------------------------
572 ; Divide a 32 Bit Integer by a 16 Bit Integer: isr_xC:4 = isr_xC:4 / isr_xB:2 with isr_xA as remainder
573 ;
574 ; trashes WREG
575 ;
576 global isr_div32x16
577 isr_div32x16:
578 movlw .32 ; process 32 bits ...
579 movwf isr_math_loop ; ... initialize loop counter
580 clrf isr_xA+0 ; clear isr_xA, will be used to hold the remainder
581 clrf isr_xA+1 ; ...
582 isr_div32x16_1:
583 bcf STATUS,C ; clear carry flag to shift in a zero bit
584 rlcf isr_xC+0,F ; shift left isr_xC
585 rlcf isr_xC+1,F ; ...
586 rlcf isr_xC+2,F ; ...
587 rlcf isr_xC+3,F ; ... shifting MSB out of isr_xC...
588 rlcf isr_xA+0,F ; ... and into LSB of isr_xA
589 rlcf isr_xA+1,F ; ...
590 btfsc STATUS,C ; did the remainder overflow (carry set)?
591 bra isr_div32x16_2 ; YES - directly generate a result bit = 1
592 movf isr_xB+0,W ; NO - compute remainder - divisor = isr_xA - isr_xB, trash result to WREG
593 subwf isr_xA+0,W ; - ...
594 movf isr_xB+1,W ; - ...
595 subwfb isr_xA+1,W ; - ...
596 btfss STATUS,C ; - remainder < divisor (-> borrow flag set, equals carry flag cleared) ?
597 bra isr_div32x16_3 ; YES - result bit = 0, keep LSB of isr_xC+0 being 0
598 isr_div32x16_2:
599 bsf isr_xC+0,0 ; NO - result bit = 1, set LSB of isr_xC+0 to 1
600 movf isr_xB+0,W ; - subtract divisor from remainder "for real": isr_xA = isr_xA - isr_xB
601 subwf isr_xA+0,F ; - ...
602 movf isr_xB+1,W ; - ...
603 subwfb isr_xA+1,F ; - ...
604 isr_div32x16_3:
605 decfsz isr_math_loop,F ; decrement loop counter, all bits done?
606 bra isr_div32x16_1 ; NO - loop
607 return ; YES - done
608
609
376 ;----------------------------------------------------------------------------- 610 ;-----------------------------------------------------------------------------
377 611
378 END 612 END