I am trying to figure out how to use the CMOV
instruction correctly. As far as I know CMOV
is used exactly like conditional jump instructions. It jumps/moves depending on the flags of the previous test
or cmp
instructions:
test %ecx, %ecx
cmovz %ebx, %eax
So I tried using this to create a small function that returns either the old_val
or the new_val
depending if the test variable is 0:
uint32_t cmov(uint8_t pred, uint32_t old_val, uint32_t new_val)
{
uint32_t result = 0;
__asm__ __volatile__(
"mov %2, %0;"
"test %1, %1;"
"cmovz %3, %0;"
: "=r"(result)
: "r"(pred), "r"(old_val), "r"(new_val)
: "cc");
return result;
}
But when I compile this it always returns the old_val. Where is my mistake?
Clearly, this can be done in C/C++ with a simple if but I want to do it with CMOV
.
Full example:
#include <cstdint>
#include <iostream>
uint32_t cmov(uint8_t pred, uint32_t old_val, uint32_t new_val)
{
uint32_t result = 0;
__asm__ __volatile__(
"mov %2, %0;"
"test %1, %1;"
"cmovz %3, %0;"
: "=r"(result)
: "r"(pred), "r"(old_val), "r"(new_val)
: "cc");
return result;
}
int main()
{
uint32_t old_val = 1;
uint32_t new_val = 5;
for (uint8_t pred = 0; pred < 2; pred++)
{
uint32_t result = cmov(pred, old_val, new_val);
std::cout << "\npred: " << pred
<< "\nold_val: " << old_val << "\nnew_val: " << new_val
<< "\nresult: " << result << std::endl;
}
return 0;
}