Shop OBEX P1 Docs P2 Docs Learn Events
How to do an ASM signed multiply. — Parallax Forums

How to do an ASM signed multiply.

KyeKye Posts: 2,200
edited 2010-01-12 16:08 in Propeller 1
I've been trying to do a signed multiply in ASM - 16x16. But I've come up with a piece of code that seems just a bit rather unoptimized:

                        abs     sampleBuffer,    sampleBuffer wc               ' Store sign.
                        muxc    multiplyTest,    #1                            '
                                                                                     
multiplicand            rdword  multiplyBuffer,  leftVolumeAddress             ' Setup inputs.
                        shl     sampleBuffer,    #16                           ' 
                        shr     multiplyBuffer,  #1 wc                         ' 
                        mov     multiplyCounter, #16                           ' Setup counter
                         
multiplyLoop if_c       add     multiplyBuffer,  sampleBuffer wc               ' Preform multiplication.
                        rcr     multiplyBuffer,  #1 wc                         '
                        
                        djnz    multiplyCounter, #multiplyLoop                 ' Repeat.
 
multiplyTest            test    multiplyTest,    #1 wc                         ' Negate/swap 
                        negc    sampleBuffer,    multiplyBuffer                '


So the input would be sampleBuffer and multiply buffer and the output is sampleBuffer. Sample buffer contains a signed value on entry while mulitply buffer does not. Multiply buffer basically holds a volume from 0 to 65535 which is used to scale the sample.

So, is there a better way to do this?

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,

Comments

  • AleAle Posts: 2,363
    edited 2010-01-12 06:14
    I used 15x15 plus signs in the FFT code below. Be awar that the signs are kept separated.

    Remember that you have to xor both signs and if you get a 1 then the result will be negative... in your code you are ignoring the sign of multiplyBuffer unless you know it will not be negative... You do not use the Z flag so you could use it to store the sign and then use negz, sorry it is 7:15 in the morning and I have to get ready to work and I cannot test your code right now... maybe later I can do it.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Visit some of my articles at Propeller Wiki:
    MATH on the propeller propeller.wikispaces.com/MATH
    pPropQL: propeller.wikispaces.com/pPropQL
    pPropQL020: propeller.wikispaces.com/pPropQL020
    OMU for the pPropQL/020 propeller.wikispaces.com/OMU
  • AleAle Posts: 2,363
    edited 2010-01-12 08:24
    This code works:

    In both cases the negative number has to be a 32 bit quantity for abs to work.

    DAT
                            abs     sampleBuffer,    sampleBuffer wc               ' Store sign.
                            muxc    multiplyTest,    #1                            '
                                                                                        
    multiplicand            'rdword  multiplyBuffer,  leftVolumeAddress             ' Setup inputs.
                            shl     sampleBuffer,    #16                           '
                            shr     multiplyBuffer,  #1 wc                         '
                            mov     multiplyCounter, #16                           ' Setup counter
                            
    multiplyLoop if_c       add     multiplyBuffer,  sampleBuffer wc               ' Preform multiplication.
                            rcr     multiplyBuffer,  #1 wc                         '
                           
                            djnz    multiplyCounter, #multiplyLoop                 ' Repeat.
     
    multiplySign            test    multiplyTest,    #1 wc                         ' Negate/swap 
                            negc    sampleBuffer,    multiplyBuffer            
    
    
    
    'local vars
    sampleBuffer     long $0000_0ffe
    multiplyTest     long 0
    multiplyBuffer     long $2
    multiplyCounter  long 0
    
    



    Depending on what you call optimizations... if you want speed or you prefer smaller code size... you cam either unroll the loop..

    Another piece of code could be this one. The loop is longer but if you do not have higher bits set in y it could be shorter... note the nice trick to use the Z flag to contain the sign of the number wink.gif



    
    smul
            mov   result,#0
            abs   x, x   wc
            rcr   result, #1   wz, nr   
    mloop
            shr    y, #1     wc
       if_c add    result, x  wc
            shl    x, #1    wc
            tjnz   y,#mloop
            negnz  result, result
    
    ende2   jmp    #ende2
    
    
    'local vars
    y       long $5
    result  long 0
    x       long $5
    
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Visit some of my articles at Propeller Wiki:
    MATH on the propeller propeller.wikispaces.com/MATH
    pPropQL: propeller.wikispaces.com/pPropQL
    pPropQL020: propeller.wikispaces.com/pPropQL020
    OMU for the pPropQL/020 propeller.wikispaces.com/OMU
  • KyeKye Posts: 2,200
    edited 2010-01-12 15:31
    Thanks Ale, I was just looking to see if I was missing something when doing the multiply and if there was just a way to do the multiply with signed numbers·no problem... However the shift operations would be a red flag indicating that you cannot do stuff like that.

    Okay, I'll use this code variant.
           
            rdword  y,  leftVolumeAddress
     
            mov    result,#0
            abs    x, x   wc
            rcr    result, #1   wz, nr
       
    mloop   shr    y, #1     wc
    if_c    add    result, x  wc
            shl    x, #1    wc
            tjnz   y,#mloop
    
            negnz  result, result
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • AleAle Posts: 2,363
    edited 2010-01-12 15:37
    Do not forget that it is shorter but not necessarily faster. It depends of the values of Volume you have... just simulate some examples with typical values and see. OTOH your version with my 3 instruction sign-is-kept-in-Z is 2 instructions longer (counting the variable)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Visit some of my articles at Propeller Wiki:
    MATH on the propeller propeller.wikispaces.com/MATH
    pPropQL: propeller.wikispaces.com/pPropQL
    pPropQL020: propeller.wikispaces.com/pPropQL020
    OMU for the pPropQL/020 propeller.wikispaces.com/OMU
  • KyeKye Posts: 2,200
    edited 2010-01-12 16:08
    I like your version becuase it has less instructions which was what I was going for.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
Sign In or Register to comment.