Dan Sander
Dan Sander

Reputation: 21

Multiplication algorithm in SPARC

been working for a few (straight) days on this multiplication algorithm in SPARC... Really can't figure out what's wrong. I've stepped through a few iterations of the code. It's doing what the proposed C algorithm wants it to. Here it is in C

negative = multiplier >= 0 ? 0 : 1;
product = 0;
for (i = 0; i < 32; i++) {
    if (multiplier & 1)
        product += multiplicand;
(product and multiplier registers combined as a unit) >> 1;
}
if (negative)
    product -= multiplicand;

And here it is in SPARC Assembly, note I haven't implemented functionality for negative numbers yet. The program runs the proposed number of times. So the loop is not the issue. I think my problem may be how I am accounting for the right shift across two 32 bit registers, which currently is just (in Psuedo-code)

sra small register 1 if (rightmost bit of large register = 1) change leftmost bit of small register to a 1 sra larger register

But it doesn't seem to be working out as planned, as I am getting really wonky numbers

Here's the whole program in SPARC... any help you guys could offer would be appreciated.

 fmt:   .asciz "Multiplicand: %d, Product: %8.8X%8.8X Counter: %d\n"            !output statement
.align 4                !align formatting

.global main
main:   save     %sp, -96, %sp
set     82732983, %l0       !move multiplicand into register %l0
set     120490892, %l1      !move multiplier into register %l1
set     0, %l2          !initialize product variable at 0
set     1, %l3          !initialize counter variable to 1
ba  test
mov     32, %l5         !put max loop value in a register

loop:
set     fmt, %o0        !setup the format string for the print statement
mov     %l0, %o1        !moving variables for printing
mov     %l1, %o2
mov     %l2, %o3
mov %l3, %o4
call    printf
nop
postprint:
    and     %l1, 1, %l6     !bitwise and between multiplier and 1, store result in %l6
cmp     %l6, 0          !comparison statement comparing the above to 1
be  else            !skip the addition if rightmost bit of multiplier is 0
nop

add     %l0, %l2, %l2       !adding multiplicand and product
sra     %l1, 1, %l1     !shifting multiplier right
and     1, %l2, %l6     !checking if rightmost bit of product is a 1
cmp     %l6, 1          !conditional statement to check this
bl  endif           !if it's not a one, branch to zero
nop             !non op

clr     %o4
set 0x40000000, %o4     !put 0x40000000 in a register
or      %l1,    %o4,    %l1 !if it is a one, bitwise do or with 0x40000000 to make a one in the leftmost bit of the multiplier
    sra     %l2,    1,  %l2     !shift product to the right by 1
    inc     %l3         !increment counter variable
    ba      test            !and branch to the testing statement
    nop

endif:
clr     %o5
sra     %l2, 1, %l2     !arithmetic shift product right by one (first line of endif)
inc     %l3         !increment counter variable
ba  test            
nop
else:
    sra     %l1, 1, %l1     !shift multiplier to the right
    and     %l2, 1, %l6     !check if rightmost bit of product is 1
    cmp     %l6, 1          !conditional statement to check this
    bl      endif           !branch to endif if it's not
    nop             !nop
clr     %o4
set 0x40000000, %o4     !put 0x40000000 in a register
    or      %l1, %o4, %l1       !if the rightmost bit is one, we use a bitwise or to place a 1 in the leftmost bit of the multiplier
    sra     %l2, 1, %l2     !then right arithmetic shift the product
    inc     %l3         !and increment the counter
    ba      test
    nop

test:   cmp     %l3, %l5
    bl      loop


done:   mov 1,  %g1             !Exit the program
    ta  0

Upvotes: 2

Views: 2018

Answers (1)

Gaurav Agarwal Garg
Gaurav Agarwal Garg

Reputation: 113

Split the functionality as: Add()and Multiply()

SPARC Assembly manual

Addition Algorithm

unsigned int Add(unsigned int num1, unsigned int num2)
{
    /* Iterate till there is no carry  */
    while (num2 != 0)
    {
        /* carry now contains common set bits of num1 and num2  */
        unsigned int carry = num1 & num2;  

        /* Sum of bits of numbers where at least one of the bits is not set */
        num1 = num1 ^ num2; 

        /* Carry is shifted by one so that adding it to x gives the required sum */
        num2 = carry << 1;
    }
    return num1;
}

Multiplication Algorithm

unsigned int Multiply(unsigned int multiplicand, unsigned int multiplier)
{
    unsigned int result = 0;

    while(multiplier != 0) /* Use while instead of for */
    {
        if (multiplier & 0x01) 
        {
            result = Add(result, multiplicand);
        }

        multiplicand <<= 1; /* Left shifting the value contained in 'multiplicand' by 1 */
        multiplier >>=1;    /* Right shifting the value contained in 'multiplier' by 1. */
   }

   return result;
}

Please Note: int is assumed to be 32bit integer here. (You can replace the function signature according to the typedefs present). Also, you can add checks for overflow and handle error accordingly.

Upvotes: 0

Related Questions