Hello!

It looks that i387 control word register definition is missing from register
definitions for i386 processor. Inside i386.h, we have:

#define FIXED_REGISTERS                                         \
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/      \
{  0, 0, 0, 0, 0, 0, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,       \
/*arg,flags,fpsr,dir,frame*/                                    \
    1,    1,   1,  1,    1,                                     \
/*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/                     \
     0,   0,   0,   0,   0,   0,   0,   0,                      \
/*mmx0,mmx1,mmx2,mmx3,mmx4,mmx5,mmx6,mmx7*/                     \
     0,   0,   0,   0,   0,   0,   0,   0,                      \
/*  r8,  r9, r10, r11, r12, r13, r14, r15*/                     \
     2,   2,   2,   2,   2,   2,   2,   2,                      \
/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/               \
     2,   2,    2,    2,    2,    2,    2,    2}

However, there should be another register defined, i387 control word register,
'fpcr' (Please look at chapter 11.2.1.2 and 11.2.1.3 in
http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetic.html). There are two
instructions in i386.md that actually use fpcr:

(define_insn "x86_fnstcw_1"
  [(set (match_operand:HI 0 "memory_operand" "=m")
        (unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))]
  "TARGET_80387"
  "fnstcw\t%0"
  [(set_attr "length" "2")
   (set_attr "mode" "HI")
   (set_attr "unit" "i387")])

(define_insn "x86_fldcw_1"
  [(set (reg:HI FPSR_REG)
        (unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
  "TARGET_80387"
  "fldcw\t%0"
  [(set_attr "length" "2")
   (set_attr "mode" "HI")
   (set_attr "unit" "i387")
   (set_attr "athlon_decode" "vector")])

However, RTL template for these two instructions state that they use i387 STATUS
register, but they should use i387 CONTROL register. To be correct, a new fixed
register should be introduced:

#define FIXED_REGISTERS                                         \
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/      \
{  0, 0, 0, 0, 0, 0, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,       \
/*arg,flags,fpsr,fpcr,dir,frame*/                               \
    1,    1,   1,   1,  1,    1,                                \
...

and above two insn definitions should be changed to use FPCR_REG. Unfortunately,
some changes would be needed through the code (mainly to various register masks
and definitions) to fix this issue, so I would like to ask for opinions on this
matter before proceeding.

This change is needed to get i387 status word switching instructions in
(int)->(float) conversions out of the loops, i.e.:

int i;
double d;

for (x = 0... {
   i[x] = d[x];
}


Thanks,
Uros.

Reply via email to