How to do an ASM signed multiply.
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:
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,
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
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
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 0Depending 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
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
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,
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
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
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,