1 /////////////////////////////////////////////////////////////////////////
2 // $Id: fpu_const.cc 13466 2018-02-16 07:57:32Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //   Copyright (c) 2003-2018 Stanislav Shwartsman
6 //          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Lesser General Public
19 //  License along with this library; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
21 //
22 /////////////////////////////////////////////////////////////////////////
23 
24 #define NEED_CPU_REG_SHORTCUTS 1
25 #include "bochs.h"
26 #include "cpu/cpu.h"
27 #define LOG_THIS BX_CPU_THIS_PTR
28 
29 #if BX_SUPPORT_FPU
30 
31 #include "softfloatx80.h"
32 
33 const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
34 const floatx80 Const_Z    = packFloatx80(0, 0x0000, 0);
35 const floatx80 Const_1    = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
36 const floatx80 Const_L2T  = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe));
37 const floatx80 Const_L2E  = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc));
38 const floatx80 Const_PI   = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235));
39 const floatx80 Const_LG2  = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799));
40 const floatx80 Const_LN2  = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac));
41 const floatx80 Const_INF  = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000));
42 
43 /* A fast way to find out whether x is one of RC_DOWN or RC_CHOP
44    (and not one of RC_RND or RC_UP).
45    */
46 #define DOWN_OR_CHOP()  (FPU_CONTROL_WORD & FPU_CW_RC & FPU_RC_DOWN)
47 
FPU_round_const(const floatx80 & a,int adj)48 BX_CPP_INLINE floatx80 FPU_round_const(const floatx80 &a, int adj)
49 {
50   floatx80 result = a;
51   result.fraction += adj;
52   return result;
53 }
54 
FLDL2T(bxInstruction_c * i)55 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLDL2T(bxInstruction_c *i)
56 {
57   BX_CPU_THIS_PTR prepareFPU(i);
58   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
59 
60   clear_C1();
61 
62   if (! IS_TAG_EMPTY(-1))
63   {
64     FPU_stack_overflow(i);
65   }
66   else {
67     BX_CPU_THIS_PTR the_i387.FPU_push();
68     BX_WRITE_FPU_REG(FPU_round_const(Const_L2T, (FPU_CONTROL_WORD & FPU_CW_RC) == FPU_RC_UP), 0);
69   }
70 
71   BX_NEXT_INSTR(i);
72 }
73 
FLDL2E(bxInstruction_c * i)74 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLDL2E(bxInstruction_c *i)
75 {
76   BX_CPU_THIS_PTR prepareFPU(i);
77   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
78 
79   clear_C1();
80 
81   if (! IS_TAG_EMPTY(-1))
82   {
83     FPU_stack_overflow(i);
84   }
85   else {
86     BX_CPU_THIS_PTR the_i387.FPU_push();
87     BX_WRITE_FPU_REG(FPU_round_const(Const_L2E, DOWN_OR_CHOP() ? -1 : 0), 0);
88   }
89 
90   BX_NEXT_INSTR(i);
91 }
92 
FLDPI(bxInstruction_c * i)93 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLDPI(bxInstruction_c *i)
94 {
95   BX_CPU_THIS_PTR prepareFPU(i);
96   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
97 
98   clear_C1();
99 
100   if (! IS_TAG_EMPTY(-1))
101   {
102     FPU_stack_overflow(i);
103   }
104   else {
105     BX_CPU_THIS_PTR the_i387.FPU_push();
106     BX_WRITE_FPU_REG(FPU_round_const(Const_PI, DOWN_OR_CHOP() ? -1 : 0), 0);
107   }
108 
109   BX_NEXT_INSTR(i);
110 }
111 
FLDLG2(bxInstruction_c * i)112 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLDLG2(bxInstruction_c *i)
113 {
114   BX_CPU_THIS_PTR prepareFPU(i);
115   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
116 
117   clear_C1();
118 
119   if (! IS_TAG_EMPTY(-1))
120   {
121     FPU_stack_overflow(i);
122   }
123   else {
124     BX_CPU_THIS_PTR the_i387.FPU_push();
125     BX_WRITE_FPU_REG(FPU_round_const(Const_LG2, DOWN_OR_CHOP() ? -1 : 0), 0);
126   }
127 
128   BX_NEXT_INSTR(i);
129 }
130 
FLDLN2(bxInstruction_c * i)131 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLDLN2(bxInstruction_c *i)
132 {
133   BX_CPU_THIS_PTR prepareFPU(i);
134   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
135 
136   clear_C1();
137 
138   if (! IS_TAG_EMPTY(-1))
139   {
140     FPU_stack_overflow(i);
141   }
142   else {
143     BX_CPU_THIS_PTR the_i387.FPU_push();
144     BX_WRITE_FPU_REG(FPU_round_const(Const_LN2, DOWN_OR_CHOP() ? -1 : 0), 0);
145   }
146 
147   BX_NEXT_INSTR(i);
148 }
149 
FLD1(bxInstruction_c * i)150 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD1(bxInstruction_c *i)
151 {
152   BX_CPU_THIS_PTR prepareFPU(i);
153   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
154 
155   clear_C1();
156 
157   if (! IS_TAG_EMPTY(-1))
158   {
159     FPU_stack_overflow(i);
160   }
161   else {
162     BX_CPU_THIS_PTR the_i387.FPU_push();
163     BX_WRITE_FPU_REG(Const_1, 0);
164   }
165 
166   BX_NEXT_INSTR(i);
167 }
168 
FLDZ(bxInstruction_c * i)169 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLDZ(bxInstruction_c *i)
170 {
171   BX_CPU_THIS_PTR prepareFPU(i);
172   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
173 
174   clear_C1();
175 
176   if (! IS_TAG_EMPTY(-1))
177   {
178     FPU_stack_overflow(i);
179   }
180   else {
181     BX_CPU_THIS_PTR the_i387.FPU_push();
182     BX_WRITE_FPU_REG(Const_Z, 0);
183   }
184 
185   BX_NEXT_INSTR(i);
186 }
187 
188 #endif
189