tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Default value of x87 registers' reserved bits

Greetings everyone,

I've been working on floating-point exception support for x86_64 (as
part of this year's gsoc). It's basically done, just one subtlety
remaining. POSIX specs say that we must provide the constant
FE_DFL_ENV, which represents the default floating-point environment.

Here's the deal.

Control, status, etc x87 registers (which are part of the fp
environment) are 16 bit wide. In protected mode though, they are
accessed as 32 bit. The upper bits, 31-16, are marked as `reserved'
and are ought to be ignored. Their default value is _not_ mentioned in
the CPU specs. At the same time though, when we write to these
registers we must not tamper with the reserved bits.

So, I wrote this snippet to extract the default value of the reserved bits:

#include <inttypes.h>
#include <stdio.h>
#include <string.h>

/* Store x87 FPU state */
#define __fnstenv(__env)        __asm__ __volatile__ \
        ("fnstenv %0" : "=m" (*(__env)))

struct fenv {
        uint32_t fe_cw;         /* Control word register */
        uint32_t fe_sw;         /* Status word register */
        uint32_t fe_tw;         /* Tag word register */

        uint32_t fe_unused[5];

        struct fenv f;

        memset(&f, 0, sizeof f);

        printf("Control word: 0x%x\n", f.fe_cw);
        printf(" Status word: 0x%x\n", f.fe_sw);
        printf("    Tag word: 0x%x\n", f.fe_tw);

        printf("Instruct Ptr: 0x%x 0x%x\n",
        printf(" Operand Ptr: 0x%x 0x%x\n",

        return 0;

Here is the output I get in an Intel cpu:

stathis:~% gcc dumpfenv.c -o dumpfenv -Wall -W -ansi -pedantic
stathis:~% ./dumpfenv
Control word: 0xffff037f
 Status word: 0xffff0000
    Tag word: 0xffffffff
Instruct Ptr: 0x0 0x0
 Operand Ptr: 0x0 0xffff0000

So all of the reserved bits seem to be set to 1. Is it fine to assume
that this is true in all cases ? Could someone please confirm it with
an AMD processor ?
So that when I define FE_DFL_ENV, I do something like:

struct fenv fe_dfl_env = {
    0xffff0000 | 0x037f,         /* or just 0xffff037f */

#define FE_DFL_ENV (&fe_dfl_env)

I hope I made myself clear.
Thank you all for considering.


Home | Main Index | Thread Index | Old Index