I'm writing a compiler and I have to output code for branching conditions on float values. For example, to compile this kind of code:
if(a <= b){
//1. DO something
} else {
//2. Do something else
}
When a and b are float variables. I just need to jump to 2 if the condition is not true, else fall to 1. I'm considering here optimization at the compiler level considering what's in 1 and 2.
I need something that works with all the comparison operators >, >=, <, <=, == and !=
A way I found to make the comparison is to use CMPLTSD (and other equivalent instructions for other relational operators). But with that, I have to use a SSE register especially for the result and then I have to move its value on a general purpose register (eax for example) and finally compare the value with 0.
I also saw that the UCOMISD instruction should set the flags correctly, but apparently it doesn't work the way I thought.
So, what's the best way to handle code like that? Is there better instructions than the first solution I have?
By best, I mean, the general solution to this problem. If possible, I would like to have code behave the same way as when doing comparisons on integers (cmp a, b; jge label). Of course, I would prefer the fastest instructions to achieve that.
The condition codes for ucomisd
do not correspond to signed integer comparison codes, but to unsigned ones (with "unordered" in the parity flag). It's a bit strange, I admit, but all clearly documented.
The code if you actually want to branch could be something like this for <=
:
ucomisd a,b
ja else ; greater
jp else ; unordered
; code for //1 goes here
jmp end
else:
; code for //2 goes here
end:
For <
:
jae else ; greater or equal
jp else ; unordered
I could list them all if you really want but you can just look at the condition codes for ucomisd
and match them to what jump you need.