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