As part of my review of inline asm in gcc, I came across this code (from
libatomic/config/x86/fenv.c, among other places):
asm volatile ("fnstenv\t%0" : "=m" (temp));
temp.__status_word |= FE_DENORM;
asm volatile ("fldenv\t%0" : : "m" (temp));
asm("fwait");
I was wondering if this could be replaced by using builtins rather than
inline asm. Poking around, I found both __builtin_ia32_fnstenv and
__builtin_ia32_fldenv. But I found no __builtin_ia32_fwait (nor
anything similar).
I briefly considered whether __builtin_ia32_fldenv implies (or should
imply) an fwait, but it doesn't look like it does one. And it seems
plausible (to a floating point neophyte like me) that you could want to
use fldenv, but know that you won't cause an exception, so don't want to
waste cycles on the fwait.
So without __builtin_ia32_fwait, this is as close as I can get. Can
someone get me closer?
#define FE_DENORM 0x02
struct fenv
{
unsigned short int __control_word;
unsigned short int __unused1;
unsigned short int __status_word;
unsigned short int __unused2;
unsigned short int __tags;
unsigned short int __unused3;
unsigned int __eip;
unsigned short int __cs_selector;
unsigned int __opcode:11;
unsigned int __unused4:5;
unsigned int __data_offset;
unsigned short int __data_selector;
unsigned short int __unused5;
};
int main()
{
struct fenv temp;
__builtin_ia32_fnstenv(&temp);
temp.__status_word |= FE_DENORM;
__builtin_ia32_fldenv(&temp);
asm("fwait" :::);
}
dw
PS Should the fwait include "cc"? fwait changes flags, just not the eflags.