Mercurial > public > hwos_code
comparison src/math.asm @ 646:5b7fe7777425
3.16 release
author | heinrichs weikamp |
---|---|
date | Thu, 14 Oct 2021 12:03:24 +0200 |
parents | 4050675965ea |
children | 75e90cd0c2c3 |
comparison
equal
deleted
inserted
replaced
642:a9a0188091e4 | 646:5b7fe7777425 |
---|---|
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 |