Shop OBEX P1 Docs P2 Docs Learn Events
Integer Math Error — Parallax Forums

Integer Math Error

pjvpjv Posts: 1,903
edited 2005-04-22 21:32 in General Discussion
Hi All;

For those who work with integer math, I just ran accross what I think is an error in one of the integer multiply routines on the SX List.

Typically mutiplication is performed by successive shifting of the multiplier, then if the shifted-out bit is a one,·adding the multiplicand to an accumulator. This works for precisions using any number of bytes, I believe the errant code was for a 24 bit example.

As the multiplicand is added to the muli-byte accumulator, the carry represents overflows from the current accumulator byte being summed, and must cascade as a "plus one" into the next higher accumulator byte. (This can be handled directly·by the processor·if the carryx extension is enabled,·then the programmer need not bother).

In the errant example, this adding of "one" is handled by loading·an incremented value of the multiplicand if the carry was set (MOV w,++MultiplicandByte), or the regular value of the mutiplicand if carry was not set (MOV w,MultiplicandByte), and adding this carry-adjusted value to the accumulator. All good so far.

The problem comes in when the value in the loaded multiplicand byte is $FF, then loading the incremented multiplicand byte would be $00, and the ripple-through of the carry is lost, causing an error in the result.

To prevent this, the ripple-though carry must instead be handled·by·successively ADDING a·one to each of the higher accumulator bytes when a carry-out occurs, so that the carries can properly cascade through each byte of the accumulator.

Cheers,

Peter (pjv)




Post Edited (pjv) : 4/16/2005 10:57:28 PM GMT

Comments

  • dkemppaidkemppai Posts: 315
    edited 2005-04-19 18:13
    Hi,

    I have run into errors on the SX list in some of the mutliply divide routines.
    I will have to check my notes when I get home. I had to do a 'repair' of one
    of the samples of code to get my multiply/divide correct.

    I was going to check it out on the SX list page to see if any of the code
    would 'jog' my memory, but...··· ...apparently I was accessing pages too
    quickly...·· ...so no go.

    -Dan
    ·
  • James NewtonJames Newton Posts: 329
    edited 2005-04-22 19:59
    I've been getting pounded by page rippers lately... people who want to save a copy of the site locally or read it offline, etc... and they don't realise there is something like 3GB of content. I can't afford the bandwidth, so I try to detect that and stop it. I've put in a new "trap" and it is overly sensitive. It is being adjusted back, so it should be better soon. Sorry for the hassel.

    If ever you have any problem with the code you find on the site, do please use the little form at the bottom to post a comment, even if it is just "this didn't work for me" but hopefully people will post the corrections.

    If you guys remember what page you where looking at, please let me know.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ---
    James Newton, Host of SXList.com
    james@sxlist.com 1-619-652-0593 fax:1-208-279-8767
    SX FAQ / Code / Tutorials / Documentation:
    http://www.sxlist.com Pick faster!



  • LEINSTER MONSTERLEINSTER MONSTER Posts: 1
    edited 2005-04-22 21:32
    As a newbie to the sx, I've been having some problems with multi byte multiplication. The CARRYX directive causes problems with the SXB compiler macro's (such as serial comms), so heres a couple of modified routines from the sx_arith download from Parallax which will work without the CARRYX directive. They can easily be expanded to 24 byte sums.You can also use them for multiplication by a constant fraction ( /65536, stamp style) if you add one to the constant product and drop the two least significant bytes

    I hope someone who tags onto your thread can use them.

    Leinster
    IF mul1616_test=1
      ; 16 bit x 16 bit multiplication 
      ; entry: multiplicand in $09,08, multiplier at $0b,$0a
      ; exit : 32 bit product at $0d,$0c,$b,$a
          ; cycles
    ;mul1616 
      mov count,#17  ; 2 set number of times to shift
      clr upper_prdt  ; 1 clear upper product
      clr upper_prdt+1  ; 1 higher byte of the 16 bit upeper product
      clc    ; 1 clear carry
          ; the following are executed [noparse][[/noparse]count] times
    m1616loop rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
      
    no_add  decsz count   ; 1/2 loop [noparse][[/noparse]count] times to get proper product
      jmp m1616loop  ; 3 jmp to rotate the next half of product
      ret    ; 3 done...
     
     
     
    
     
      ; fast 16 bit x 16 bit multiplication 
      ; entry: multiplicand in $09,08, multiplier at $0b,$0a
      ; exit : 32 bit product at $0d,$0c,$b,$a
      
    IF mul1616_test=1      
         
    mul1616  
      clr upper_prdt  ; 1 clear upper product
      clr upper_prdt+1  ; 1 higher byte of the 16 bit upeper product
      clc    ; 1 clear carry
         
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add1   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add1  
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add2   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add2    
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add3   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add3
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add4   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add4
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add5   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add5
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add6   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add6
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add7   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add7
         
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add8   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add8
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add9   ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add9     
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add10  ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add10
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add11  ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add11
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add12  ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add12
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add13  ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add13
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add14  ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add14
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add15  ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add15   
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add16  ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add16
      rr upper_prdt+1  ; 1 rotate right the whole product
      rr upper_prdt  ; 1  lower byte of the 16 bit upper product
      rr mr16+1   ; 1 high byte of the multiplier
      rr mr16   ; 1 check lsb
      sc    ; 1 skip addition if no carry
      jmp no_add17  ; 3     no addition since lsb=0
      clc    ; 1 clear carry
      add upper_prdt,md16  ; 1 add multiplicand to upper product
      add upper_prdt+1,md16+1 ; 1 add the next 16 bit of multiplicand
      addb  upper_prdt+1, c  ; *********************CORRECTION FOR NO CARRYX
    no_add17
      ret    ; 3 done...
    
Sign In or Register to comment.