what's the easiest way to get an absolute value of an sse register?
I'm thinking I could use AND 07FFFFFFFFF..... or something, but is there a better way?
Signed integers use twos complement encoding.
For switching signs
not reg ; xor reg, -1
add 1
For example using a signed byte:
00000010 == 2
00000001 == 1
00000000 == 0
11111111 == -1
11111110 == -2
If you knew it was negative then the equivalent of this
xor reg, -1
add reg, 1
would give the positive version.
SSE code equivalent to this would do it no matter the sign of the integer.
mov reg, reg0
and reg,10000000 ; for byte sized signed integer
cmp reg, 0
je past
xor reg0, -1
add reg0, 1
past:
i don't know about SSE registers, but maybe something like this could be converted? (for eax)
CDQ
XOR EAX, EDX
SUB EAX, EDX
wow, yeah, guys, im asking about SSE =P
for regular registers i can just do
AND eax, 07FFF FFFFh
The problem is you can't use immediate values for sse instructions, so I was trying to avoid using a weird looking constant, it's not a big deal, I was just making sure there's not a faster way
AND eax, 07FFF FFFF wont give the correct absolute value.
The -1 will turn into 2147483647, surely not what you expected.
Redskull's code works correctly.
This code with tweaks may work, but it isn't tested .
.data
number dq somenum, somenum
minusone dq -1, -1
zero dq 0, 0
justhi dq 10..0b, 10..0b
.code
movaps xmm1, minusone
movaps xmm2, number
movaps xmm3, xmm2
andps xmm3, justhi
comisd xmm3, justhi
je past
movaps xmm1, zero
past:
xorps xmm2, xmm1
psubq xmm2, xmm1
dsouza123 is right, take a look at this: http://ossa.the-wot.co.uk/tutorial_asm1_tex.htm#1_6
It is something that I wrote a while back to explain 2's complement. Your code will only work for signed magnitude values, but Intel processors use 2's complement.
Ossa
Quote from: dsouza123 on June 14, 2006, 04:42:38 PM
Redskull's code works correctly.
Just for the record, i'm totally not claiming to have thought that code up; the original was a 16-bit version using CWD, taken from a book i can't remember long ago. Again, sorry I can't help with SSE registers :'(
alan
Quote from: Ossa on June 14, 2006, 04:47:23 PM
dsouza123 is right, take a look at this: http://ossa.the-wot.co.uk/tutorial_asm1_tex.htm#1_6
It is something that I wrote a while back to explain 2's complement. Your code will only work for signed magnitude values, but Intel processors use 2's complement.
Ossa
I feel stupid now, DUHHHHHHHHHHHHHHHHHHHHHH.
Sorry guys, my neurons aren't exactly working this week. :green2
What about
mov edx, eax
sub eax, edx
sub eax, edx
and
movaps xmm1, xmm0
subps xmm0, xmm1
subps xmm0, xmm1
Quote from: savage on June 15, 2006, 03:23:11 PM
mov edx, eax
sub eax, edx
sub eax, edx
Therefore:
mov edx, eax ; edx = eax = val
sub eax, edx ; eax = 0, edx = val
sub eax, edx ; eax = 0 - val = -val
I don't think that that's what you want to do.
Ossa
I never said that.
You liar! :cheekygreen:
I have a huge headache. I think my brain is falling out of my ear.
Why is it so hard to get the absolute value. Arrrg
This probably won't assemble (I haven't had time to check) but should work... there MUST be a better way though... I don't use MMX/SSE much, so I'm not the one to ask though:
mask1 dd 10000000h, 10000000h, 10000000h, 10000000h
movdqa xmm2, xmm1
pand xmm1, mask1
pcmpeqd xmm1, mask1 ; xmm1 has all 1s for any dword that is negative
pxor xmm3, xmm3
psubd xmm3, xmm2 ; xmm3 = -xmm2
pand xmm3, xmm1
pandn xmm1, xmm2
por xmm1, xmm3
[edit] Now that I finally looked at redskull's code, try this - I don't know of any sign extension instructions for SSE but I'll go have a look now:
mask1 dd 10000000h, 10000000h, 10000000h, 10000000h
movdqa xmm2, xmm1
pand xmm2, mask1
pcmpeqd xmm2, mask1 ; xmm1 has all 1s for any dword that is negative
pxor xmm1, xmm2
psubd xmm1, xmm2
(for non-dowrd things, you just change the mask and the psubd instruction)
[/edit]
Ossa
how does this look:
movaps xmm1, xmm0
cmpnltps xmm1, 0 ; obviously this shouldnt be immediate, but just an example
andps xmm1, xmm0
subps xmm0, xmm1
subps xmm0, xmm1
Wait - you're using FLOATS ??? well then, you first method WILL work and it is much the best.
[edit] The code that has been discussed so far is for integers, but you are using float SSE instructions there... which are you using? [/edit]
Ossa
Well I'd like to have the best method for both.
I think the Ossa's code should contain mask = 80000000h to work correct... on sign bit
For floats, definately just do the
and.
For integers, the code you just posted won't work as it is for floating point values (a quick glance says that the code will work for floats, but it will be much slower than the
and you posted about right at the start).
Quote from: asmfan on June 15, 2006, 04:22:41 PM
I think the Ossa's code should contain mask = 80000000h to work correct... on sign bit
Exactly right asmfan:
mask1 OWORD 80000000800000008000000080000000h
movaps xmm2, xmm1
pand xmm2, mask1
pcmpeqd xmm2, mask1 ; xmm1 has all 1s for any dword that is negative
pxor xmm1, xmm2
psubd xmm1, xmm2
Thanks for spotting that.
[edit] Just edited it to get it assemble under MASM... also used MOVAPS instead of MOVDQA (SSE instead of SSE2) [/edit]
Ossa
I just thought of this method for eax registers:
bt eax, 31
adc eax, 0
mov ecx, 45 ; << number to be absoluted
xor eax, eax
bt ecx, 31
adc eax, 0
adc ecx, 0
neg eax
sbb ecx,0
xor ecx, eax
Well at least that works, it's obviously not optimised
just a weird idea