You are here: Math Resources > Math Examples

Math Examples

Multiplication, division, and square root can be computed by using add, subtract, and shift instructions. For other math-related examples, see the Log Table, Anti-Log Table, and Sine Table.

Multiplication

Here is an unsigned multiplier routine that multiplies two 16-bit values to yield a 32-bit product:

DAT

'' Multiply x[15..0] by y[15..0] (y[31..16] must be 0)
' on exit, product in y[31..0]
'
multiply        shl     x,#16            'get multiplicand into x[31..16]
                mov     t,#16            'ready for 16 multiplier bits
                shr     y,#1      wc     'get initial multiplier bit into c
:loop  if_c     add     y,x       wc     'if c set, add multiplicand to product
                rcr     y,#1      wc     'put next multiplier in c, shift prod.
                djnz    t,#:loop         'loop until done
multiply_ret    ret                      'return with product in y[31..0]

 

The above routine's execution time could be cut by ~1/3 if the loop was unrolled, repeating the ADD / RCR sequence and getting rid of the DJNZ instruction.

Division

Division is like multiplication, but backwards. It is potentially more complex, though, because a comparison test must be performed before a subtraction can take place. To remedy this, there don’t is a special CMPSUB D, S instructions which tests to see if a subtraction can be performed without causing an underflow. If no underflow would occur, the subtraction takes place and the C output is 1. If an underflow would occur, D is left alone and the C output is 0.

Here is an unsigned divider routine that divides a 32-bit value by a 16-bit value to yield a 16-bit quotient and a 16-bit remainder:

DAT

' Divide x[31..0] by y[15..0] (y[16] must be 0)
' on exit, quotient is in x[15..0] and remainder is in x[31..16]
'
divide          shl     y,#15            'get divisor into y[30..15]
                mov     t,#16            'ready for 16 quotient bits
:loop           cmpsub  x,y       wc     'y =< x? Subtract it, quotient bit in c
                rcl     x,#1             'rotate c into quotient, shift dividend
                djnz    t,#:loop         'loop until done
divide_ret      ret                      'quotient in x[15..0],
                                         'remainder in x[31..16]

 

Like the multiplier routine, this divider routine could be recoded with a sequence of 16 CMPSUB + RCL instruction pairs to get rid of the DJNZ and cut execution time by ~1/3. By making such changes, speed can often be gained at the expense of code size.

Square Root

Here is a square-root routine that uses the CMPSUB instruction:

DAT
'
' Compute square-root of y[31..0] into x[15..0]
'
root            mov     a,#0             'reset accumulator
                mov     x,#0             'reset root
                mov     t,#16            'ready for 16 root bits
:loop           shl     y,#1    wc       'rotate top two bits of y to accumulator
                rcl     a,#1
                shl     y,#1    wc
                rcl     a,#1
                shl     x,#2             'determine next bit of root
                or      x,#1
                cmpsub  a,x     wc
                shr     x,#2
                rcl     x,#1
                djnz    t,#:loop         'loop until done
root_ret        ret                      'square root in x[15..0]

 

Many complex math functions can be realized by additions, subtractions, and shifts. Though specific examples were given here, these types of algorithms may be coded in many different ways to best suit the application.

Propeller Help Version 1.1

Copyright © Parallax Inc.

5/13/2009