Statistics
| Branch: | Revision:

root / target-i386 / fpu_helper.c @ 93ab25d7

History | View | Annotate | Download (29.8 kB)

1 f299f437 Blue Swirl
/*
2 f299f437 Blue Swirl
 *  x86 FPU, MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI helpers
3 f299f437 Blue Swirl
 *
4 f299f437 Blue Swirl
 *  Copyright (c) 2003 Fabrice Bellard
5 f299f437 Blue Swirl
 *
6 f299f437 Blue Swirl
 * This library is free software; you can redistribute it and/or
7 f299f437 Blue Swirl
 * modify it under the terms of the GNU Lesser General Public
8 f299f437 Blue Swirl
 * License as published by the Free Software Foundation; either
9 f299f437 Blue Swirl
 * version 2 of the License, or (at your option) any later version.
10 f299f437 Blue Swirl
 *
11 f299f437 Blue Swirl
 * This library is distributed in the hope that it will be useful,
12 f299f437 Blue Swirl
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 f299f437 Blue Swirl
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 f299f437 Blue Swirl
 * Lesser General Public License for more details.
15 f299f437 Blue Swirl
 *
16 f299f437 Blue Swirl
 * You should have received a copy of the GNU Lesser General Public
17 f299f437 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 f299f437 Blue Swirl
 */
19 f299f437 Blue Swirl
20 f299f437 Blue Swirl
#include <math.h>
21 f299f437 Blue Swirl
#include "cpu.h"
22 f299f437 Blue Swirl
#include "helper.h"
23 f299f437 Blue Swirl
24 92fc4b58 Blue Swirl
#if !defined(CONFIG_USER_ONLY)
25 022c62cb Paolo Bonzini
#include "exec/softmmu_exec.h"
26 92fc4b58 Blue Swirl
#endif /* !defined(CONFIG_USER_ONLY) */
27 92fc4b58 Blue Swirl
28 f299f437 Blue Swirl
#define FPU_RC_MASK         0xc00
29 f299f437 Blue Swirl
#define FPU_RC_NEAR         0x000
30 f299f437 Blue Swirl
#define FPU_RC_DOWN         0x400
31 f299f437 Blue Swirl
#define FPU_RC_UP           0x800
32 f299f437 Blue Swirl
#define FPU_RC_CHOP         0xc00
33 f299f437 Blue Swirl
34 f299f437 Blue Swirl
#define MAXTAN 9223372036854775808.0
35 f299f437 Blue Swirl
36 f299f437 Blue Swirl
/* the following deal with x86 long double-precision numbers */
37 f299f437 Blue Swirl
#define MAXEXPD 0x7fff
38 f299f437 Blue Swirl
#define EXPBIAS 16383
39 f299f437 Blue Swirl
#define EXPD(fp)        (fp.l.upper & 0x7fff)
40 f299f437 Blue Swirl
#define SIGND(fp)       ((fp.l.upper) & 0x8000)
41 f299f437 Blue Swirl
#define MANTD(fp)       (fp.l.lower)
42 f299f437 Blue Swirl
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
43 f299f437 Blue Swirl
44 f299f437 Blue Swirl
#define FPUS_IE (1 << 0)
45 f299f437 Blue Swirl
#define FPUS_DE (1 << 1)
46 f299f437 Blue Swirl
#define FPUS_ZE (1 << 2)
47 f299f437 Blue Swirl
#define FPUS_OE (1 << 3)
48 f299f437 Blue Swirl
#define FPUS_UE (1 << 4)
49 f299f437 Blue Swirl
#define FPUS_PE (1 << 5)
50 f299f437 Blue Swirl
#define FPUS_SF (1 << 6)
51 f299f437 Blue Swirl
#define FPUS_SE (1 << 7)
52 f299f437 Blue Swirl
#define FPUS_B  (1 << 15)
53 f299f437 Blue Swirl
54 f299f437 Blue Swirl
#define FPUC_EM 0x3f
55 f299f437 Blue Swirl
56 f299f437 Blue Swirl
#define floatx80_lg2 make_floatx80(0x3ffd, 0x9a209a84fbcff799LL)
57 f299f437 Blue Swirl
#define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL)
58 f299f437 Blue Swirl
#define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL)
59 f299f437 Blue Swirl
60 d3eb5eae Blue Swirl
static inline void fpush(CPUX86State *env)
61 f299f437 Blue Swirl
{
62 f299f437 Blue Swirl
    env->fpstt = (env->fpstt - 1) & 7;
63 f299f437 Blue Swirl
    env->fptags[env->fpstt] = 0; /* validate stack entry */
64 f299f437 Blue Swirl
}
65 f299f437 Blue Swirl
66 d3eb5eae Blue Swirl
static inline void fpop(CPUX86State *env)
67 f299f437 Blue Swirl
{
68 f299f437 Blue Swirl
    env->fptags[env->fpstt] = 1; /* invalidate stack entry */
69 f299f437 Blue Swirl
    env->fpstt = (env->fpstt + 1) & 7;
70 f299f437 Blue Swirl
}
71 f299f437 Blue Swirl
72 d3eb5eae Blue Swirl
static inline floatx80 helper_fldt(CPUX86State *env, target_ulong ptr)
73 f299f437 Blue Swirl
{
74 f299f437 Blue Swirl
    CPU_LDoubleU temp;
75 f299f437 Blue Swirl
76 d3eb5eae Blue Swirl
    temp.l.lower = cpu_ldq_data(env, ptr);
77 d3eb5eae Blue Swirl
    temp.l.upper = cpu_lduw_data(env, ptr + 8);
78 f299f437 Blue Swirl
    return temp.d;
79 f299f437 Blue Swirl
}
80 f299f437 Blue Swirl
81 d3eb5eae Blue Swirl
static inline void helper_fstt(CPUX86State *env, floatx80 f, target_ulong ptr)
82 f299f437 Blue Swirl
{
83 f299f437 Blue Swirl
    CPU_LDoubleU temp;
84 f299f437 Blue Swirl
85 f299f437 Blue Swirl
    temp.d = f;
86 d3eb5eae Blue Swirl
    cpu_stq_data(env, ptr, temp.l.lower);
87 d3eb5eae Blue Swirl
    cpu_stw_data(env, ptr + 8, temp.l.upper);
88 f299f437 Blue Swirl
}
89 f299f437 Blue Swirl
90 f299f437 Blue Swirl
/* x87 FPU helpers */
91 f299f437 Blue Swirl
92 d3eb5eae Blue Swirl
static inline double floatx80_to_double(CPUX86State *env, floatx80 a)
93 f299f437 Blue Swirl
{
94 f299f437 Blue Swirl
    union {
95 f299f437 Blue Swirl
        float64 f64;
96 f299f437 Blue Swirl
        double d;
97 f299f437 Blue Swirl
    } u;
98 f299f437 Blue Swirl
99 f299f437 Blue Swirl
    u.f64 = floatx80_to_float64(a, &env->fp_status);
100 f299f437 Blue Swirl
    return u.d;
101 f299f437 Blue Swirl
}
102 f299f437 Blue Swirl
103 d3eb5eae Blue Swirl
static inline floatx80 double_to_floatx80(CPUX86State *env, double a)
104 f299f437 Blue Swirl
{
105 f299f437 Blue Swirl
    union {
106 f299f437 Blue Swirl
        float64 f64;
107 f299f437 Blue Swirl
        double d;
108 f299f437 Blue Swirl
    } u;
109 f299f437 Blue Swirl
110 f299f437 Blue Swirl
    u.d = a;
111 f299f437 Blue Swirl
    return float64_to_floatx80(u.f64, &env->fp_status);
112 f299f437 Blue Swirl
}
113 f299f437 Blue Swirl
114 d3eb5eae Blue Swirl
static void fpu_set_exception(CPUX86State *env, int mask)
115 f299f437 Blue Swirl
{
116 f299f437 Blue Swirl
    env->fpus |= mask;
117 f299f437 Blue Swirl
    if (env->fpus & (~env->fpuc & FPUC_EM)) {
118 f299f437 Blue Swirl
        env->fpus |= FPUS_SE | FPUS_B;
119 f299f437 Blue Swirl
    }
120 f299f437 Blue Swirl
}
121 f299f437 Blue Swirl
122 d3eb5eae Blue Swirl
static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b)
123 f299f437 Blue Swirl
{
124 f299f437 Blue Swirl
    if (floatx80_is_zero(b)) {
125 d3eb5eae Blue Swirl
        fpu_set_exception(env, FPUS_ZE);
126 f299f437 Blue Swirl
    }
127 f299f437 Blue Swirl
    return floatx80_div(a, b, &env->fp_status);
128 f299f437 Blue Swirl
}
129 f299f437 Blue Swirl
130 d3eb5eae Blue Swirl
static void fpu_raise_exception(CPUX86State *env)
131 f299f437 Blue Swirl
{
132 f299f437 Blue Swirl
    if (env->cr[0] & CR0_NE_MASK) {
133 f299f437 Blue Swirl
        raise_exception(env, EXCP10_COPR);
134 f299f437 Blue Swirl
    }
135 f299f437 Blue Swirl
#if !defined(CONFIG_USER_ONLY)
136 f299f437 Blue Swirl
    else {
137 f299f437 Blue Swirl
        cpu_set_ferr(env);
138 f299f437 Blue Swirl
    }
139 f299f437 Blue Swirl
#endif
140 f299f437 Blue Swirl
}
141 f299f437 Blue Swirl
142 d3eb5eae Blue Swirl
void helper_flds_FT0(CPUX86State *env, uint32_t val)
143 f299f437 Blue Swirl
{
144 f299f437 Blue Swirl
    union {
145 f299f437 Blue Swirl
        float32 f;
146 f299f437 Blue Swirl
        uint32_t i;
147 f299f437 Blue Swirl
    } u;
148 f299f437 Blue Swirl
149 f299f437 Blue Swirl
    u.i = val;
150 f299f437 Blue Swirl
    FT0 = float32_to_floatx80(u.f, &env->fp_status);
151 f299f437 Blue Swirl
}
152 f299f437 Blue Swirl
153 d3eb5eae Blue Swirl
void helper_fldl_FT0(CPUX86State *env, uint64_t val)
154 f299f437 Blue Swirl
{
155 f299f437 Blue Swirl
    union {
156 f299f437 Blue Swirl
        float64 f;
157 f299f437 Blue Swirl
        uint64_t i;
158 f299f437 Blue Swirl
    } u;
159 f299f437 Blue Swirl
160 f299f437 Blue Swirl
    u.i = val;
161 f299f437 Blue Swirl
    FT0 = float64_to_floatx80(u.f, &env->fp_status);
162 f299f437 Blue Swirl
}
163 f299f437 Blue Swirl
164 d3eb5eae Blue Swirl
void helper_fildl_FT0(CPUX86State *env, int32_t val)
165 f299f437 Blue Swirl
{
166 f299f437 Blue Swirl
    FT0 = int32_to_floatx80(val, &env->fp_status);
167 f299f437 Blue Swirl
}
168 f299f437 Blue Swirl
169 d3eb5eae Blue Swirl
void helper_flds_ST0(CPUX86State *env, uint32_t val)
170 f299f437 Blue Swirl
{
171 f299f437 Blue Swirl
    int new_fpstt;
172 f299f437 Blue Swirl
    union {
173 f299f437 Blue Swirl
        float32 f;
174 f299f437 Blue Swirl
        uint32_t i;
175 f299f437 Blue Swirl
    } u;
176 f299f437 Blue Swirl
177 f299f437 Blue Swirl
    new_fpstt = (env->fpstt - 1) & 7;
178 f299f437 Blue Swirl
    u.i = val;
179 f299f437 Blue Swirl
    env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status);
180 f299f437 Blue Swirl
    env->fpstt = new_fpstt;
181 f299f437 Blue Swirl
    env->fptags[new_fpstt] = 0; /* validate stack entry */
182 f299f437 Blue Swirl
}
183 f299f437 Blue Swirl
184 d3eb5eae Blue Swirl
void helper_fldl_ST0(CPUX86State *env, uint64_t val)
185 f299f437 Blue Swirl
{
186 f299f437 Blue Swirl
    int new_fpstt;
187 f299f437 Blue Swirl
    union {
188 f299f437 Blue Swirl
        float64 f;
189 f299f437 Blue Swirl
        uint64_t i;
190 f299f437 Blue Swirl
    } u;
191 f299f437 Blue Swirl
192 f299f437 Blue Swirl
    new_fpstt = (env->fpstt - 1) & 7;
193 f299f437 Blue Swirl
    u.i = val;
194 f299f437 Blue Swirl
    env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status);
195 f299f437 Blue Swirl
    env->fpstt = new_fpstt;
196 f299f437 Blue Swirl
    env->fptags[new_fpstt] = 0; /* validate stack entry */
197 f299f437 Blue Swirl
}
198 f299f437 Blue Swirl
199 d3eb5eae Blue Swirl
void helper_fildl_ST0(CPUX86State *env, int32_t val)
200 f299f437 Blue Swirl
{
201 f299f437 Blue Swirl
    int new_fpstt;
202 f299f437 Blue Swirl
203 f299f437 Blue Swirl
    new_fpstt = (env->fpstt - 1) & 7;
204 f299f437 Blue Swirl
    env->fpregs[new_fpstt].d = int32_to_floatx80(val, &env->fp_status);
205 f299f437 Blue Swirl
    env->fpstt = new_fpstt;
206 f299f437 Blue Swirl
    env->fptags[new_fpstt] = 0; /* validate stack entry */
207 f299f437 Blue Swirl
}
208 f299f437 Blue Swirl
209 d3eb5eae Blue Swirl
void helper_fildll_ST0(CPUX86State *env, int64_t val)
210 f299f437 Blue Swirl
{
211 f299f437 Blue Swirl
    int new_fpstt;
212 f299f437 Blue Swirl
213 f299f437 Blue Swirl
    new_fpstt = (env->fpstt - 1) & 7;
214 f299f437 Blue Swirl
    env->fpregs[new_fpstt].d = int64_to_floatx80(val, &env->fp_status);
215 f299f437 Blue Swirl
    env->fpstt = new_fpstt;
216 f299f437 Blue Swirl
    env->fptags[new_fpstt] = 0; /* validate stack entry */
217 f299f437 Blue Swirl
}
218 f299f437 Blue Swirl
219 d3eb5eae Blue Swirl
uint32_t helper_fsts_ST0(CPUX86State *env)
220 f299f437 Blue Swirl
{
221 f299f437 Blue Swirl
    union {
222 f299f437 Blue Swirl
        float32 f;
223 f299f437 Blue Swirl
        uint32_t i;
224 f299f437 Blue Swirl
    } u;
225 f299f437 Blue Swirl
226 f299f437 Blue Swirl
    u.f = floatx80_to_float32(ST0, &env->fp_status);
227 f299f437 Blue Swirl
    return u.i;
228 f299f437 Blue Swirl
}
229 f299f437 Blue Swirl
230 d3eb5eae Blue Swirl
uint64_t helper_fstl_ST0(CPUX86State *env)
231 f299f437 Blue Swirl
{
232 f299f437 Blue Swirl
    union {
233 f299f437 Blue Swirl
        float64 f;
234 f299f437 Blue Swirl
        uint64_t i;
235 f299f437 Blue Swirl
    } u;
236 f299f437 Blue Swirl
237 f299f437 Blue Swirl
    u.f = floatx80_to_float64(ST0, &env->fp_status);
238 f299f437 Blue Swirl
    return u.i;
239 f299f437 Blue Swirl
}
240 f299f437 Blue Swirl
241 d3eb5eae Blue Swirl
int32_t helper_fist_ST0(CPUX86State *env)
242 f299f437 Blue Swirl
{
243 f299f437 Blue Swirl
    int32_t val;
244 f299f437 Blue Swirl
245 f299f437 Blue Swirl
    val = floatx80_to_int32(ST0, &env->fp_status);
246 f299f437 Blue Swirl
    if (val != (int16_t)val) {
247 f299f437 Blue Swirl
        val = -32768;
248 f299f437 Blue Swirl
    }
249 f299f437 Blue Swirl
    return val;
250 f299f437 Blue Swirl
}
251 f299f437 Blue Swirl
252 d3eb5eae Blue Swirl
int32_t helper_fistl_ST0(CPUX86State *env)
253 f299f437 Blue Swirl
{
254 f299f437 Blue Swirl
    int32_t val;
255 f299f437 Blue Swirl
256 f299f437 Blue Swirl
    val = floatx80_to_int32(ST0, &env->fp_status);
257 f299f437 Blue Swirl
    return val;
258 f299f437 Blue Swirl
}
259 f299f437 Blue Swirl
260 d3eb5eae Blue Swirl
int64_t helper_fistll_ST0(CPUX86State *env)
261 f299f437 Blue Swirl
{
262 f299f437 Blue Swirl
    int64_t val;
263 f299f437 Blue Swirl
264 f299f437 Blue Swirl
    val = floatx80_to_int64(ST0, &env->fp_status);
265 f299f437 Blue Swirl
    return val;
266 f299f437 Blue Swirl
}
267 f299f437 Blue Swirl
268 d3eb5eae Blue Swirl
int32_t helper_fistt_ST0(CPUX86State *env)
269 f299f437 Blue Swirl
{
270 f299f437 Blue Swirl
    int32_t val;
271 f299f437 Blue Swirl
272 f299f437 Blue Swirl
    val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
273 f299f437 Blue Swirl
    if (val != (int16_t)val) {
274 f299f437 Blue Swirl
        val = -32768;
275 f299f437 Blue Swirl
    }
276 f299f437 Blue Swirl
    return val;
277 f299f437 Blue Swirl
}
278 f299f437 Blue Swirl
279 d3eb5eae Blue Swirl
int32_t helper_fisttl_ST0(CPUX86State *env)
280 f299f437 Blue Swirl
{
281 f299f437 Blue Swirl
    int32_t val;
282 f299f437 Blue Swirl
283 f299f437 Blue Swirl
    val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
284 f299f437 Blue Swirl
    return val;
285 f299f437 Blue Swirl
}
286 f299f437 Blue Swirl
287 d3eb5eae Blue Swirl
int64_t helper_fisttll_ST0(CPUX86State *env)
288 f299f437 Blue Swirl
{
289 f299f437 Blue Swirl
    int64_t val;
290 f299f437 Blue Swirl
291 f299f437 Blue Swirl
    val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status);
292 f299f437 Blue Swirl
    return val;
293 f299f437 Blue Swirl
}
294 f299f437 Blue Swirl
295 d3eb5eae Blue Swirl
void helper_fldt_ST0(CPUX86State *env, target_ulong ptr)
296 f299f437 Blue Swirl
{
297 f299f437 Blue Swirl
    int new_fpstt;
298 f299f437 Blue Swirl
299 f299f437 Blue Swirl
    new_fpstt = (env->fpstt - 1) & 7;
300 d3eb5eae Blue Swirl
    env->fpregs[new_fpstt].d = helper_fldt(env, ptr);
301 f299f437 Blue Swirl
    env->fpstt = new_fpstt;
302 f299f437 Blue Swirl
    env->fptags[new_fpstt] = 0; /* validate stack entry */
303 f299f437 Blue Swirl
}
304 f299f437 Blue Swirl
305 d3eb5eae Blue Swirl
void helper_fstt_ST0(CPUX86State *env, target_ulong ptr)
306 f299f437 Blue Swirl
{
307 d3eb5eae Blue Swirl
    helper_fstt(env, ST0, ptr);
308 f299f437 Blue Swirl
}
309 f299f437 Blue Swirl
310 d3eb5eae Blue Swirl
void helper_fpush(CPUX86State *env)
311 f299f437 Blue Swirl
{
312 d3eb5eae Blue Swirl
    fpush(env);
313 f299f437 Blue Swirl
}
314 f299f437 Blue Swirl
315 d3eb5eae Blue Swirl
void helper_fpop(CPUX86State *env)
316 f299f437 Blue Swirl
{
317 d3eb5eae Blue Swirl
    fpop(env);
318 f299f437 Blue Swirl
}
319 f299f437 Blue Swirl
320 d3eb5eae Blue Swirl
void helper_fdecstp(CPUX86State *env)
321 f299f437 Blue Swirl
{
322 f299f437 Blue Swirl
    env->fpstt = (env->fpstt - 1) & 7;
323 f299f437 Blue Swirl
    env->fpus &= ~0x4700;
324 f299f437 Blue Swirl
}
325 f299f437 Blue Swirl
326 d3eb5eae Blue Swirl
void helper_fincstp(CPUX86State *env)
327 f299f437 Blue Swirl
{
328 f299f437 Blue Swirl
    env->fpstt = (env->fpstt + 1) & 7;
329 f299f437 Blue Swirl
    env->fpus &= ~0x4700;
330 f299f437 Blue Swirl
}
331 f299f437 Blue Swirl
332 f299f437 Blue Swirl
/* FPU move */
333 f299f437 Blue Swirl
334 d3eb5eae Blue Swirl
void helper_ffree_STN(CPUX86State *env, int st_index)
335 f299f437 Blue Swirl
{
336 f299f437 Blue Swirl
    env->fptags[(env->fpstt + st_index) & 7] = 1;
337 f299f437 Blue Swirl
}
338 f299f437 Blue Swirl
339 d3eb5eae Blue Swirl
void helper_fmov_ST0_FT0(CPUX86State *env)
340 f299f437 Blue Swirl
{
341 f299f437 Blue Swirl
    ST0 = FT0;
342 f299f437 Blue Swirl
}
343 f299f437 Blue Swirl
344 d3eb5eae Blue Swirl
void helper_fmov_FT0_STN(CPUX86State *env, int st_index)
345 f299f437 Blue Swirl
{
346 f299f437 Blue Swirl
    FT0 = ST(st_index);
347 f299f437 Blue Swirl
}
348 f299f437 Blue Swirl
349 d3eb5eae Blue Swirl
void helper_fmov_ST0_STN(CPUX86State *env, int st_index)
350 f299f437 Blue Swirl
{
351 f299f437 Blue Swirl
    ST0 = ST(st_index);
352 f299f437 Blue Swirl
}
353 f299f437 Blue Swirl
354 d3eb5eae Blue Swirl
void helper_fmov_STN_ST0(CPUX86State *env, int st_index)
355 f299f437 Blue Swirl
{
356 f299f437 Blue Swirl
    ST(st_index) = ST0;
357 f299f437 Blue Swirl
}
358 f299f437 Blue Swirl
359 d3eb5eae Blue Swirl
void helper_fxchg_ST0_STN(CPUX86State *env, int st_index)
360 f299f437 Blue Swirl
{
361 f299f437 Blue Swirl
    floatx80 tmp;
362 f299f437 Blue Swirl
363 f299f437 Blue Swirl
    tmp = ST(st_index);
364 f299f437 Blue Swirl
    ST(st_index) = ST0;
365 f299f437 Blue Swirl
    ST0 = tmp;
366 f299f437 Blue Swirl
}
367 f299f437 Blue Swirl
368 f299f437 Blue Swirl
/* FPU operations */
369 f299f437 Blue Swirl
370 f299f437 Blue Swirl
static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
371 f299f437 Blue Swirl
372 d3eb5eae Blue Swirl
void helper_fcom_ST0_FT0(CPUX86State *env)
373 f299f437 Blue Swirl
{
374 f299f437 Blue Swirl
    int ret;
375 f299f437 Blue Swirl
376 f299f437 Blue Swirl
    ret = floatx80_compare(ST0, FT0, &env->fp_status);
377 f299f437 Blue Swirl
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
378 f299f437 Blue Swirl
}
379 f299f437 Blue Swirl
380 d3eb5eae Blue Swirl
void helper_fucom_ST0_FT0(CPUX86State *env)
381 f299f437 Blue Swirl
{
382 f299f437 Blue Swirl
    int ret;
383 f299f437 Blue Swirl
384 f299f437 Blue Swirl
    ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
385 f299f437 Blue Swirl
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
386 f299f437 Blue Swirl
}
387 f299f437 Blue Swirl
388 f299f437 Blue Swirl
static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
389 f299f437 Blue Swirl
390 d3eb5eae Blue Swirl
void helper_fcomi_ST0_FT0(CPUX86State *env)
391 f299f437 Blue Swirl
{
392 f299f437 Blue Swirl
    int eflags;
393 f299f437 Blue Swirl
    int ret;
394 f299f437 Blue Swirl
395 f299f437 Blue Swirl
    ret = floatx80_compare(ST0, FT0, &env->fp_status);
396 d3eb5eae Blue Swirl
    eflags = cpu_cc_compute_all(env, CC_OP);
397 f299f437 Blue Swirl
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
398 f299f437 Blue Swirl
    CC_SRC = eflags;
399 f299f437 Blue Swirl
}
400 f299f437 Blue Swirl
401 d3eb5eae Blue Swirl
void helper_fucomi_ST0_FT0(CPUX86State *env)
402 f299f437 Blue Swirl
{
403 f299f437 Blue Swirl
    int eflags;
404 f299f437 Blue Swirl
    int ret;
405 f299f437 Blue Swirl
406 f299f437 Blue Swirl
    ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
407 d3eb5eae Blue Swirl
    eflags = cpu_cc_compute_all(env, CC_OP);
408 f299f437 Blue Swirl
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
409 f299f437 Blue Swirl
    CC_SRC = eflags;
410 f299f437 Blue Swirl
}
411 f299f437 Blue Swirl
412 d3eb5eae Blue Swirl
void helper_fadd_ST0_FT0(CPUX86State *env)
413 f299f437 Blue Swirl
{
414 f299f437 Blue Swirl
    ST0 = floatx80_add(ST0, FT0, &env->fp_status);
415 f299f437 Blue Swirl
}
416 f299f437 Blue Swirl
417 d3eb5eae Blue Swirl
void helper_fmul_ST0_FT0(CPUX86State *env)
418 f299f437 Blue Swirl
{
419 f299f437 Blue Swirl
    ST0 = floatx80_mul(ST0, FT0, &env->fp_status);
420 f299f437 Blue Swirl
}
421 f299f437 Blue Swirl
422 d3eb5eae Blue Swirl
void helper_fsub_ST0_FT0(CPUX86State *env)
423 f299f437 Blue Swirl
{
424 f299f437 Blue Swirl
    ST0 = floatx80_sub(ST0, FT0, &env->fp_status);
425 f299f437 Blue Swirl
}
426 f299f437 Blue Swirl
427 d3eb5eae Blue Swirl
void helper_fsubr_ST0_FT0(CPUX86State *env)
428 f299f437 Blue Swirl
{
429 f299f437 Blue Swirl
    ST0 = floatx80_sub(FT0, ST0, &env->fp_status);
430 f299f437 Blue Swirl
}
431 f299f437 Blue Swirl
432 d3eb5eae Blue Swirl
void helper_fdiv_ST0_FT0(CPUX86State *env)
433 f299f437 Blue Swirl
{
434 d3eb5eae Blue Swirl
    ST0 = helper_fdiv(env, ST0, FT0);
435 f299f437 Blue Swirl
}
436 f299f437 Blue Swirl
437 d3eb5eae Blue Swirl
void helper_fdivr_ST0_FT0(CPUX86State *env)
438 f299f437 Blue Swirl
{
439 d3eb5eae Blue Swirl
    ST0 = helper_fdiv(env, FT0, ST0);
440 f299f437 Blue Swirl
}
441 f299f437 Blue Swirl
442 f299f437 Blue Swirl
/* fp operations between STN and ST0 */
443 f299f437 Blue Swirl
444 d3eb5eae Blue Swirl
void helper_fadd_STN_ST0(CPUX86State *env, int st_index)
445 f299f437 Blue Swirl
{
446 f299f437 Blue Swirl
    ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status);
447 f299f437 Blue Swirl
}
448 f299f437 Blue Swirl
449 d3eb5eae Blue Swirl
void helper_fmul_STN_ST0(CPUX86State *env, int st_index)
450 f299f437 Blue Swirl
{
451 f299f437 Blue Swirl
    ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status);
452 f299f437 Blue Swirl
}
453 f299f437 Blue Swirl
454 d3eb5eae Blue Swirl
void helper_fsub_STN_ST0(CPUX86State *env, int st_index)
455 f299f437 Blue Swirl
{
456 f299f437 Blue Swirl
    ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status);
457 f299f437 Blue Swirl
}
458 f299f437 Blue Swirl
459 d3eb5eae Blue Swirl
void helper_fsubr_STN_ST0(CPUX86State *env, int st_index)
460 f299f437 Blue Swirl
{
461 f299f437 Blue Swirl
    ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status);
462 f299f437 Blue Swirl
}
463 f299f437 Blue Swirl
464 d3eb5eae Blue Swirl
void helper_fdiv_STN_ST0(CPUX86State *env, int st_index)
465 f299f437 Blue Swirl
{
466 f299f437 Blue Swirl
    floatx80 *p;
467 f299f437 Blue Swirl
468 f299f437 Blue Swirl
    p = &ST(st_index);
469 d3eb5eae Blue Swirl
    *p = helper_fdiv(env, *p, ST0);
470 f299f437 Blue Swirl
}
471 f299f437 Blue Swirl
472 d3eb5eae Blue Swirl
void helper_fdivr_STN_ST0(CPUX86State *env, int st_index)
473 f299f437 Blue Swirl
{
474 f299f437 Blue Swirl
    floatx80 *p;
475 f299f437 Blue Swirl
476 f299f437 Blue Swirl
    p = &ST(st_index);
477 d3eb5eae Blue Swirl
    *p = helper_fdiv(env, ST0, *p);
478 f299f437 Blue Swirl
}
479 f299f437 Blue Swirl
480 f299f437 Blue Swirl
/* misc FPU operations */
481 d3eb5eae Blue Swirl
void helper_fchs_ST0(CPUX86State *env)
482 f299f437 Blue Swirl
{
483 f299f437 Blue Swirl
    ST0 = floatx80_chs(ST0);
484 f299f437 Blue Swirl
}
485 f299f437 Blue Swirl
486 d3eb5eae Blue Swirl
void helper_fabs_ST0(CPUX86State *env)
487 f299f437 Blue Swirl
{
488 f299f437 Blue Swirl
    ST0 = floatx80_abs(ST0);
489 f299f437 Blue Swirl
}
490 f299f437 Blue Swirl
491 d3eb5eae Blue Swirl
void helper_fld1_ST0(CPUX86State *env)
492 f299f437 Blue Swirl
{
493 f299f437 Blue Swirl
    ST0 = floatx80_one;
494 f299f437 Blue Swirl
}
495 f299f437 Blue Swirl
496 d3eb5eae Blue Swirl
void helper_fldl2t_ST0(CPUX86State *env)
497 f299f437 Blue Swirl
{
498 f299f437 Blue Swirl
    ST0 = floatx80_l2t;
499 f299f437 Blue Swirl
}
500 f299f437 Blue Swirl
501 d3eb5eae Blue Swirl
void helper_fldl2e_ST0(CPUX86State *env)
502 f299f437 Blue Swirl
{
503 f299f437 Blue Swirl
    ST0 = floatx80_l2e;
504 f299f437 Blue Swirl
}
505 f299f437 Blue Swirl
506 d3eb5eae Blue Swirl
void helper_fldpi_ST0(CPUX86State *env)
507 f299f437 Blue Swirl
{
508 f299f437 Blue Swirl
    ST0 = floatx80_pi;
509 f299f437 Blue Swirl
}
510 f299f437 Blue Swirl
511 d3eb5eae Blue Swirl
void helper_fldlg2_ST0(CPUX86State *env)
512 f299f437 Blue Swirl
{
513 f299f437 Blue Swirl
    ST0 = floatx80_lg2;
514 f299f437 Blue Swirl
}
515 f299f437 Blue Swirl
516 d3eb5eae Blue Swirl
void helper_fldln2_ST0(CPUX86State *env)
517 f299f437 Blue Swirl
{
518 f299f437 Blue Swirl
    ST0 = floatx80_ln2;
519 f299f437 Blue Swirl
}
520 f299f437 Blue Swirl
521 d3eb5eae Blue Swirl
void helper_fldz_ST0(CPUX86State *env)
522 f299f437 Blue Swirl
{
523 f299f437 Blue Swirl
    ST0 = floatx80_zero;
524 f299f437 Blue Swirl
}
525 f299f437 Blue Swirl
526 d3eb5eae Blue Swirl
void helper_fldz_FT0(CPUX86State *env)
527 f299f437 Blue Swirl
{
528 f299f437 Blue Swirl
    FT0 = floatx80_zero;
529 f299f437 Blue Swirl
}
530 f299f437 Blue Swirl
531 d3eb5eae Blue Swirl
uint32_t helper_fnstsw(CPUX86State *env)
532 f299f437 Blue Swirl
{
533 f299f437 Blue Swirl
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
534 f299f437 Blue Swirl
}
535 f299f437 Blue Swirl
536 d3eb5eae Blue Swirl
uint32_t helper_fnstcw(CPUX86State *env)
537 f299f437 Blue Swirl
{
538 f299f437 Blue Swirl
    return env->fpuc;
539 f299f437 Blue Swirl
}
540 f299f437 Blue Swirl
541 d3eb5eae Blue Swirl
static void update_fp_status(CPUX86State *env)
542 f299f437 Blue Swirl
{
543 f299f437 Blue Swirl
    int rnd_type;
544 f299f437 Blue Swirl
545 f299f437 Blue Swirl
    /* set rounding mode */
546 f299f437 Blue Swirl
    switch (env->fpuc & FPU_RC_MASK) {
547 f299f437 Blue Swirl
    default:
548 f299f437 Blue Swirl
    case FPU_RC_NEAR:
549 f299f437 Blue Swirl
        rnd_type = float_round_nearest_even;
550 f299f437 Blue Swirl
        break;
551 f299f437 Blue Swirl
    case FPU_RC_DOWN:
552 f299f437 Blue Swirl
        rnd_type = float_round_down;
553 f299f437 Blue Swirl
        break;
554 f299f437 Blue Swirl
    case FPU_RC_UP:
555 f299f437 Blue Swirl
        rnd_type = float_round_up;
556 f299f437 Blue Swirl
        break;
557 f299f437 Blue Swirl
    case FPU_RC_CHOP:
558 f299f437 Blue Swirl
        rnd_type = float_round_to_zero;
559 f299f437 Blue Swirl
        break;
560 f299f437 Blue Swirl
    }
561 f299f437 Blue Swirl
    set_float_rounding_mode(rnd_type, &env->fp_status);
562 f299f437 Blue Swirl
    switch ((env->fpuc >> 8) & 3) {
563 f299f437 Blue Swirl
    case 0:
564 f299f437 Blue Swirl
        rnd_type = 32;
565 f299f437 Blue Swirl
        break;
566 f299f437 Blue Swirl
    case 2:
567 f299f437 Blue Swirl
        rnd_type = 64;
568 f299f437 Blue Swirl
        break;
569 f299f437 Blue Swirl
    case 3:
570 f299f437 Blue Swirl
    default:
571 f299f437 Blue Swirl
        rnd_type = 80;
572 f299f437 Blue Swirl
        break;
573 f299f437 Blue Swirl
    }
574 f299f437 Blue Swirl
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
575 f299f437 Blue Swirl
}
576 f299f437 Blue Swirl
577 d3eb5eae Blue Swirl
void helper_fldcw(CPUX86State *env, uint32_t val)
578 f299f437 Blue Swirl
{
579 f299f437 Blue Swirl
    env->fpuc = val;
580 d3eb5eae Blue Swirl
    update_fp_status(env);
581 f299f437 Blue Swirl
}
582 f299f437 Blue Swirl
583 d3eb5eae Blue Swirl
void helper_fclex(CPUX86State *env)
584 f299f437 Blue Swirl
{
585 f299f437 Blue Swirl
    env->fpus &= 0x7f00;
586 f299f437 Blue Swirl
}
587 f299f437 Blue Swirl
588 d3eb5eae Blue Swirl
void helper_fwait(CPUX86State *env)
589 f299f437 Blue Swirl
{
590 f299f437 Blue Swirl
    if (env->fpus & FPUS_SE) {
591 d3eb5eae Blue Swirl
        fpu_raise_exception(env);
592 f299f437 Blue Swirl
    }
593 f299f437 Blue Swirl
}
594 f299f437 Blue Swirl
595 d3eb5eae Blue Swirl
void helper_fninit(CPUX86State *env)
596 f299f437 Blue Swirl
{
597 f299f437 Blue Swirl
    env->fpus = 0;
598 f299f437 Blue Swirl
    env->fpstt = 0;
599 f299f437 Blue Swirl
    env->fpuc = 0x37f;
600 f299f437 Blue Swirl
    env->fptags[0] = 1;
601 f299f437 Blue Swirl
    env->fptags[1] = 1;
602 f299f437 Blue Swirl
    env->fptags[2] = 1;
603 f299f437 Blue Swirl
    env->fptags[3] = 1;
604 f299f437 Blue Swirl
    env->fptags[4] = 1;
605 f299f437 Blue Swirl
    env->fptags[5] = 1;
606 f299f437 Blue Swirl
    env->fptags[6] = 1;
607 f299f437 Blue Swirl
    env->fptags[7] = 1;
608 f299f437 Blue Swirl
}
609 f299f437 Blue Swirl
610 f299f437 Blue Swirl
/* BCD ops */
611 f299f437 Blue Swirl
612 d3eb5eae Blue Swirl
void helper_fbld_ST0(CPUX86State *env, target_ulong ptr)
613 f299f437 Blue Swirl
{
614 f299f437 Blue Swirl
    floatx80 tmp;
615 f299f437 Blue Swirl
    uint64_t val;
616 f299f437 Blue Swirl
    unsigned int v;
617 f299f437 Blue Swirl
    int i;
618 f299f437 Blue Swirl
619 f299f437 Blue Swirl
    val = 0;
620 f299f437 Blue Swirl
    for (i = 8; i >= 0; i--) {
621 d3eb5eae Blue Swirl
        v = cpu_ldub_data(env, ptr + i);
622 f299f437 Blue Swirl
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
623 f299f437 Blue Swirl
    }
624 f299f437 Blue Swirl
    tmp = int64_to_floatx80(val, &env->fp_status);
625 d3eb5eae Blue Swirl
    if (cpu_ldub_data(env, ptr + 9) & 0x80) {
626 f299f437 Blue Swirl
        floatx80_chs(tmp);
627 f299f437 Blue Swirl
    }
628 d3eb5eae Blue Swirl
    fpush(env);
629 f299f437 Blue Swirl
    ST0 = tmp;
630 f299f437 Blue Swirl
}
631 f299f437 Blue Swirl
632 d3eb5eae Blue Swirl
void helper_fbst_ST0(CPUX86State *env, target_ulong ptr)
633 f299f437 Blue Swirl
{
634 f299f437 Blue Swirl
    int v;
635 f299f437 Blue Swirl
    target_ulong mem_ref, mem_end;
636 f299f437 Blue Swirl
    int64_t val;
637 f299f437 Blue Swirl
638 f299f437 Blue Swirl
    val = floatx80_to_int64(ST0, &env->fp_status);
639 f299f437 Blue Swirl
    mem_ref = ptr;
640 f299f437 Blue Swirl
    mem_end = mem_ref + 9;
641 f299f437 Blue Swirl
    if (val < 0) {
642 d3eb5eae Blue Swirl
        cpu_stb_data(env, mem_end, 0x80);
643 f299f437 Blue Swirl
        val = -val;
644 f299f437 Blue Swirl
    } else {
645 d3eb5eae Blue Swirl
        cpu_stb_data(env, mem_end, 0x00);
646 f299f437 Blue Swirl
    }
647 f299f437 Blue Swirl
    while (mem_ref < mem_end) {
648 f299f437 Blue Swirl
        if (val == 0) {
649 f299f437 Blue Swirl
            break;
650 f299f437 Blue Swirl
        }
651 f299f437 Blue Swirl
        v = val % 100;
652 f299f437 Blue Swirl
        val = val / 100;
653 f299f437 Blue Swirl
        v = ((v / 10) << 4) | (v % 10);
654 d3eb5eae Blue Swirl
        cpu_stb_data(env, mem_ref++, v);
655 f299f437 Blue Swirl
    }
656 f299f437 Blue Swirl
    while (mem_ref < mem_end) {
657 d3eb5eae Blue Swirl
        cpu_stb_data(env, mem_ref++, 0);
658 f299f437 Blue Swirl
    }
659 f299f437 Blue Swirl
}
660 f299f437 Blue Swirl
661 d3eb5eae Blue Swirl
void helper_f2xm1(CPUX86State *env)
662 f299f437 Blue Swirl
{
663 d3eb5eae Blue Swirl
    double val = floatx80_to_double(env, ST0);
664 f299f437 Blue Swirl
665 f299f437 Blue Swirl
    val = pow(2.0, val) - 1.0;
666 d3eb5eae Blue Swirl
    ST0 = double_to_floatx80(env, val);
667 f299f437 Blue Swirl
}
668 f299f437 Blue Swirl
669 d3eb5eae Blue Swirl
void helper_fyl2x(CPUX86State *env)
670 f299f437 Blue Swirl
{
671 d3eb5eae Blue Swirl
    double fptemp = floatx80_to_double(env, ST0);
672 f299f437 Blue Swirl
673 f299f437 Blue Swirl
    if (fptemp > 0.0) {
674 f299f437 Blue Swirl
        fptemp = log(fptemp) / log(2.0); /* log2(ST) */
675 d3eb5eae Blue Swirl
        fptemp *= floatx80_to_double(env, ST1);
676 d3eb5eae Blue Swirl
        ST1 = double_to_floatx80(env, fptemp);
677 d3eb5eae Blue Swirl
        fpop(env);
678 f299f437 Blue Swirl
    } else {
679 f299f437 Blue Swirl
        env->fpus &= ~0x4700;
680 f299f437 Blue Swirl
        env->fpus |= 0x400;
681 f299f437 Blue Swirl
    }
682 f299f437 Blue Swirl
}
683 f299f437 Blue Swirl
684 d3eb5eae Blue Swirl
void helper_fptan(CPUX86State *env)
685 f299f437 Blue Swirl
{
686 d3eb5eae Blue Swirl
    double fptemp = floatx80_to_double(env, ST0);
687 f299f437 Blue Swirl
688 f299f437 Blue Swirl
    if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
689 f299f437 Blue Swirl
        env->fpus |= 0x400;
690 f299f437 Blue Swirl
    } else {
691 f299f437 Blue Swirl
        fptemp = tan(fptemp);
692 d3eb5eae Blue Swirl
        ST0 = double_to_floatx80(env, fptemp);
693 d3eb5eae Blue Swirl
        fpush(env);
694 f299f437 Blue Swirl
        ST0 = floatx80_one;
695 f299f437 Blue Swirl
        env->fpus &= ~0x400; /* C2 <-- 0 */
696 f299f437 Blue Swirl
        /* the above code is for |arg| < 2**52 only */
697 f299f437 Blue Swirl
    }
698 f299f437 Blue Swirl
}
699 f299f437 Blue Swirl
700 d3eb5eae Blue Swirl
void helper_fpatan(CPUX86State *env)
701 f299f437 Blue Swirl
{
702 f299f437 Blue Swirl
    double fptemp, fpsrcop;
703 f299f437 Blue Swirl
704 d3eb5eae Blue Swirl
    fpsrcop = floatx80_to_double(env, ST1);
705 d3eb5eae Blue Swirl
    fptemp = floatx80_to_double(env, ST0);
706 d3eb5eae Blue Swirl
    ST1 = double_to_floatx80(env, atan2(fpsrcop, fptemp));
707 d3eb5eae Blue Swirl
    fpop(env);
708 f299f437 Blue Swirl
}
709 f299f437 Blue Swirl
710 d3eb5eae Blue Swirl
void helper_fxtract(CPUX86State *env)
711 f299f437 Blue Swirl
{
712 f299f437 Blue Swirl
    CPU_LDoubleU temp;
713 f299f437 Blue Swirl
714 f299f437 Blue Swirl
    temp.d = ST0;
715 f299f437 Blue Swirl
716 f299f437 Blue Swirl
    if (floatx80_is_zero(ST0)) {
717 f299f437 Blue Swirl
        /* Easy way to generate -inf and raising division by 0 exception */
718 f299f437 Blue Swirl
        ST0 = floatx80_div(floatx80_chs(floatx80_one), floatx80_zero,
719 f299f437 Blue Swirl
                           &env->fp_status);
720 d3eb5eae Blue Swirl
        fpush(env);
721 f299f437 Blue Swirl
        ST0 = temp.d;
722 f299f437 Blue Swirl
    } else {
723 f299f437 Blue Swirl
        int expdif;
724 f299f437 Blue Swirl
725 f299f437 Blue Swirl
        expdif = EXPD(temp) - EXPBIAS;
726 f299f437 Blue Swirl
        /* DP exponent bias */
727 f299f437 Blue Swirl
        ST0 = int32_to_floatx80(expdif, &env->fp_status);
728 d3eb5eae Blue Swirl
        fpush(env);
729 f299f437 Blue Swirl
        BIASEXPONENT(temp);
730 f299f437 Blue Swirl
        ST0 = temp.d;
731 f299f437 Blue Swirl
    }
732 f299f437 Blue Swirl
}
733 f299f437 Blue Swirl
734 d3eb5eae Blue Swirl
void helper_fprem1(CPUX86State *env)
735 f299f437 Blue Swirl
{
736 f299f437 Blue Swirl
    double st0, st1, dblq, fpsrcop, fptemp;
737 f299f437 Blue Swirl
    CPU_LDoubleU fpsrcop1, fptemp1;
738 f299f437 Blue Swirl
    int expdif;
739 f299f437 Blue Swirl
    signed long long int q;
740 f299f437 Blue Swirl
741 d3eb5eae Blue Swirl
    st0 = floatx80_to_double(env, ST0);
742 d3eb5eae Blue Swirl
    st1 = floatx80_to_double(env, ST1);
743 f299f437 Blue Swirl
744 f299f437 Blue Swirl
    if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
745 d3eb5eae Blue Swirl
        ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */
746 f299f437 Blue Swirl
        env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
747 f299f437 Blue Swirl
        return;
748 f299f437 Blue Swirl
    }
749 f299f437 Blue Swirl
750 f299f437 Blue Swirl
    fpsrcop = st0;
751 f299f437 Blue Swirl
    fptemp = st1;
752 f299f437 Blue Swirl
    fpsrcop1.d = ST0;
753 f299f437 Blue Swirl
    fptemp1.d = ST1;
754 f299f437 Blue Swirl
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
755 f299f437 Blue Swirl
756 f299f437 Blue Swirl
    if (expdif < 0) {
757 f299f437 Blue Swirl
        /* optimisation? taken from the AMD docs */
758 f299f437 Blue Swirl
        env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
759 f299f437 Blue Swirl
        /* ST0 is unchanged */
760 f299f437 Blue Swirl
        return;
761 f299f437 Blue Swirl
    }
762 f299f437 Blue Swirl
763 f299f437 Blue Swirl
    if (expdif < 53) {
764 f299f437 Blue Swirl
        dblq = fpsrcop / fptemp;
765 f299f437 Blue Swirl
        /* round dblq towards nearest integer */
766 f299f437 Blue Swirl
        dblq = rint(dblq);
767 f299f437 Blue Swirl
        st0 = fpsrcop - fptemp * dblq;
768 f299f437 Blue Swirl
769 f299f437 Blue Swirl
        /* convert dblq to q by truncating towards zero */
770 f299f437 Blue Swirl
        if (dblq < 0.0) {
771 f299f437 Blue Swirl
            q = (signed long long int)(-dblq);
772 f299f437 Blue Swirl
        } else {
773 f299f437 Blue Swirl
            q = (signed long long int)dblq;
774 f299f437 Blue Swirl
        }
775 f299f437 Blue Swirl
776 f299f437 Blue Swirl
        env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
777 f299f437 Blue Swirl
        /* (C0,C3,C1) <-- (q2,q1,q0) */
778 f299f437 Blue Swirl
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
779 f299f437 Blue Swirl
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
780 f299f437 Blue Swirl
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
781 f299f437 Blue Swirl
    } else {
782 f299f437 Blue Swirl
        env->fpus |= 0x400;  /* C2 <-- 1 */
783 f299f437 Blue Swirl
        fptemp = pow(2.0, expdif - 50);
784 f299f437 Blue Swirl
        fpsrcop = (st0 / st1) / fptemp;
785 f299f437 Blue Swirl
        /* fpsrcop = integer obtained by chopping */
786 f299f437 Blue Swirl
        fpsrcop = (fpsrcop < 0.0) ?
787 f299f437 Blue Swirl
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
788 f299f437 Blue Swirl
        st0 -= (st1 * fpsrcop * fptemp);
789 f299f437 Blue Swirl
    }
790 d3eb5eae Blue Swirl
    ST0 = double_to_floatx80(env, st0);
791 f299f437 Blue Swirl
}
792 f299f437 Blue Swirl
793 d3eb5eae Blue Swirl
void helper_fprem(CPUX86State *env)
794 f299f437 Blue Swirl
{
795 f299f437 Blue Swirl
    double st0, st1, dblq, fpsrcop, fptemp;
796 f299f437 Blue Swirl
    CPU_LDoubleU fpsrcop1, fptemp1;
797 f299f437 Blue Swirl
    int expdif;
798 f299f437 Blue Swirl
    signed long long int q;
799 f299f437 Blue Swirl
800 d3eb5eae Blue Swirl
    st0 = floatx80_to_double(env, ST0);
801 d3eb5eae Blue Swirl
    st1 = floatx80_to_double(env, ST1);
802 f299f437 Blue Swirl
803 f299f437 Blue Swirl
    if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
804 d3eb5eae Blue Swirl
        ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */
805 f299f437 Blue Swirl
        env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
806 f299f437 Blue Swirl
        return;
807 f299f437 Blue Swirl
    }
808 f299f437 Blue Swirl
809 f299f437 Blue Swirl
    fpsrcop = st0;
810 f299f437 Blue Swirl
    fptemp = st1;
811 f299f437 Blue Swirl
    fpsrcop1.d = ST0;
812 f299f437 Blue Swirl
    fptemp1.d = ST1;
813 f299f437 Blue Swirl
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
814 f299f437 Blue Swirl
815 f299f437 Blue Swirl
    if (expdif < 0) {
816 f299f437 Blue Swirl
        /* optimisation? taken from the AMD docs */
817 f299f437 Blue Swirl
        env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
818 f299f437 Blue Swirl
        /* ST0 is unchanged */
819 f299f437 Blue Swirl
        return;
820 f299f437 Blue Swirl
    }
821 f299f437 Blue Swirl
822 f299f437 Blue Swirl
    if (expdif < 53) {
823 f299f437 Blue Swirl
        dblq = fpsrcop / fptemp; /* ST0 / ST1 */
824 f299f437 Blue Swirl
        /* round dblq towards zero */
825 f299f437 Blue Swirl
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
826 f299f437 Blue Swirl
        st0 = fpsrcop - fptemp * dblq; /* fpsrcop is ST0 */
827 f299f437 Blue Swirl
828 f299f437 Blue Swirl
        /* convert dblq to q by truncating towards zero */
829 f299f437 Blue Swirl
        if (dblq < 0.0) {
830 f299f437 Blue Swirl
            q = (signed long long int)(-dblq);
831 f299f437 Blue Swirl
        } else {
832 f299f437 Blue Swirl
            q = (signed long long int)dblq;
833 f299f437 Blue Swirl
        }
834 f299f437 Blue Swirl
835 f299f437 Blue Swirl
        env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
836 f299f437 Blue Swirl
        /* (C0,C3,C1) <-- (q2,q1,q0) */
837 f299f437 Blue Swirl
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
838 f299f437 Blue Swirl
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
839 f299f437 Blue Swirl
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
840 f299f437 Blue Swirl
    } else {
841 f299f437 Blue Swirl
        int N = 32 + (expdif % 32); /* as per AMD docs */
842 f299f437 Blue Swirl
843 f299f437 Blue Swirl
        env->fpus |= 0x400;  /* C2 <-- 1 */
844 f299f437 Blue Swirl
        fptemp = pow(2.0, (double)(expdif - N));
845 f299f437 Blue Swirl
        fpsrcop = (st0 / st1) / fptemp;
846 f299f437 Blue Swirl
        /* fpsrcop = integer obtained by chopping */
847 f299f437 Blue Swirl
        fpsrcop = (fpsrcop < 0.0) ?
848 f299f437 Blue Swirl
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
849 f299f437 Blue Swirl
        st0 -= (st1 * fpsrcop * fptemp);
850 f299f437 Blue Swirl
    }
851 d3eb5eae Blue Swirl
    ST0 = double_to_floatx80(env, st0);
852 f299f437 Blue Swirl
}
853 f299f437 Blue Swirl
854 d3eb5eae Blue Swirl
void helper_fyl2xp1(CPUX86State *env)
855 f299f437 Blue Swirl
{
856 d3eb5eae Blue Swirl
    double fptemp = floatx80_to_double(env, ST0);
857 f299f437 Blue Swirl
858 f299f437 Blue Swirl
    if ((fptemp + 1.0) > 0.0) {
859 f299f437 Blue Swirl
        fptemp = log(fptemp + 1.0) / log(2.0); /* log2(ST + 1.0) */
860 d3eb5eae Blue Swirl
        fptemp *= floatx80_to_double(env, ST1);
861 d3eb5eae Blue Swirl
        ST1 = double_to_floatx80(env, fptemp);
862 d3eb5eae Blue Swirl
        fpop(env);
863 f299f437 Blue Swirl
    } else {
864 f299f437 Blue Swirl
        env->fpus &= ~0x4700;
865 f299f437 Blue Swirl
        env->fpus |= 0x400;
866 f299f437 Blue Swirl
    }
867 f299f437 Blue Swirl
}
868 f299f437 Blue Swirl
869 d3eb5eae Blue Swirl
void helper_fsqrt(CPUX86State *env)
870 f299f437 Blue Swirl
{
871 f299f437 Blue Swirl
    if (floatx80_is_neg(ST0)) {
872 f299f437 Blue Swirl
        env->fpus &= ~0x4700;  /* (C3,C2,C1,C0) <-- 0000 */
873 f299f437 Blue Swirl
        env->fpus |= 0x400;
874 f299f437 Blue Swirl
    }
875 f299f437 Blue Swirl
    ST0 = floatx80_sqrt(ST0, &env->fp_status);
876 f299f437 Blue Swirl
}
877 f299f437 Blue Swirl
878 d3eb5eae Blue Swirl
void helper_fsincos(CPUX86State *env)
879 f299f437 Blue Swirl
{
880 d3eb5eae Blue Swirl
    double fptemp = floatx80_to_double(env, ST0);
881 f299f437 Blue Swirl
882 f299f437 Blue Swirl
    if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
883 f299f437 Blue Swirl
        env->fpus |= 0x400;
884 f299f437 Blue Swirl
    } else {
885 d3eb5eae Blue Swirl
        ST0 = double_to_floatx80(env, sin(fptemp));
886 d3eb5eae Blue Swirl
        fpush(env);
887 d3eb5eae Blue Swirl
        ST0 = double_to_floatx80(env, cos(fptemp));
888 f299f437 Blue Swirl
        env->fpus &= ~0x400;  /* C2 <-- 0 */
889 f299f437 Blue Swirl
        /* the above code is for |arg| < 2**63 only */
890 f299f437 Blue Swirl
    }
891 f299f437 Blue Swirl
}
892 f299f437 Blue Swirl
893 d3eb5eae Blue Swirl
void helper_frndint(CPUX86State *env)
894 f299f437 Blue Swirl
{
895 f299f437 Blue Swirl
    ST0 = floatx80_round_to_int(ST0, &env->fp_status);
896 f299f437 Blue Swirl
}
897 f299f437 Blue Swirl
898 d3eb5eae Blue Swirl
void helper_fscale(CPUX86State *env)
899 f299f437 Blue Swirl
{
900 f299f437 Blue Swirl
    if (floatx80_is_any_nan(ST1)) {
901 f299f437 Blue Swirl
        ST0 = ST1;
902 f299f437 Blue Swirl
    } else {
903 f299f437 Blue Swirl
        int n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status);
904 f299f437 Blue Swirl
        ST0 = floatx80_scalbn(ST0, n, &env->fp_status);
905 f299f437 Blue Swirl
    }
906 f299f437 Blue Swirl
}
907 f299f437 Blue Swirl
908 d3eb5eae Blue Swirl
void helper_fsin(CPUX86State *env)
909 f299f437 Blue Swirl
{
910 d3eb5eae Blue Swirl
    double fptemp = floatx80_to_double(env, ST0);
911 f299f437 Blue Swirl
912 f299f437 Blue Swirl
    if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
913 f299f437 Blue Swirl
        env->fpus |= 0x400;
914 f299f437 Blue Swirl
    } else {
915 d3eb5eae Blue Swirl
        ST0 = double_to_floatx80(env, sin(fptemp));
916 f299f437 Blue Swirl
        env->fpus &= ~0x400;  /* C2 <-- 0 */
917 f299f437 Blue Swirl
        /* the above code is for |arg| < 2**53 only */
918 f299f437 Blue Swirl
    }
919 f299f437 Blue Swirl
}
920 f299f437 Blue Swirl
921 d3eb5eae Blue Swirl
void helper_fcos(CPUX86State *env)
922 f299f437 Blue Swirl
{
923 d3eb5eae Blue Swirl
    double fptemp = floatx80_to_double(env, ST0);
924 f299f437 Blue Swirl
925 f299f437 Blue Swirl
    if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) {
926 f299f437 Blue Swirl
        env->fpus |= 0x400;
927 f299f437 Blue Swirl
    } else {
928 d3eb5eae Blue Swirl
        ST0 = double_to_floatx80(env, cos(fptemp));
929 f299f437 Blue Swirl
        env->fpus &= ~0x400;  /* C2 <-- 0 */
930 f299f437 Blue Swirl
        /* the above code is for |arg| < 2**63 only */
931 f299f437 Blue Swirl
    }
932 f299f437 Blue Swirl
}
933 f299f437 Blue Swirl
934 d3eb5eae Blue Swirl
void helper_fxam_ST0(CPUX86State *env)
935 f299f437 Blue Swirl
{
936 f299f437 Blue Swirl
    CPU_LDoubleU temp;
937 f299f437 Blue Swirl
    int expdif;
938 f299f437 Blue Swirl
939 f299f437 Blue Swirl
    temp.d = ST0;
940 f299f437 Blue Swirl
941 f299f437 Blue Swirl
    env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
942 f299f437 Blue Swirl
    if (SIGND(temp)) {
943 f299f437 Blue Swirl
        env->fpus |= 0x200; /* C1 <-- 1 */
944 f299f437 Blue Swirl
    }
945 f299f437 Blue Swirl
946 f299f437 Blue Swirl
    /* XXX: test fptags too */
947 f299f437 Blue Swirl
    expdif = EXPD(temp);
948 f299f437 Blue Swirl
    if (expdif == MAXEXPD) {
949 f299f437 Blue Swirl
        if (MANTD(temp) == 0x8000000000000000ULL) {
950 f299f437 Blue Swirl
            env->fpus |= 0x500; /* Infinity */
951 f299f437 Blue Swirl
        } else {
952 f299f437 Blue Swirl
            env->fpus |= 0x100; /* NaN */
953 f299f437 Blue Swirl
        }
954 f299f437 Blue Swirl
    } else if (expdif == 0) {
955 f299f437 Blue Swirl
        if (MANTD(temp) == 0) {
956 f299f437 Blue Swirl
            env->fpus |=  0x4000; /* Zero */
957 f299f437 Blue Swirl
        } else {
958 f299f437 Blue Swirl
            env->fpus |= 0x4400; /* Denormal */
959 f299f437 Blue Swirl
        }
960 f299f437 Blue Swirl
    } else {
961 f299f437 Blue Swirl
        env->fpus |= 0x400;
962 f299f437 Blue Swirl
    }
963 f299f437 Blue Swirl
}
964 f299f437 Blue Swirl
965 d3eb5eae Blue Swirl
void helper_fstenv(CPUX86State *env, target_ulong ptr, int data32)
966 f299f437 Blue Swirl
{
967 f299f437 Blue Swirl
    int fpus, fptag, exp, i;
968 f299f437 Blue Swirl
    uint64_t mant;
969 f299f437 Blue Swirl
    CPU_LDoubleU tmp;
970 f299f437 Blue Swirl
971 f299f437 Blue Swirl
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
972 f299f437 Blue Swirl
    fptag = 0;
973 f299f437 Blue Swirl
    for (i = 7; i >= 0; i--) {
974 f299f437 Blue Swirl
        fptag <<= 2;
975 f299f437 Blue Swirl
        if (env->fptags[i]) {
976 f299f437 Blue Swirl
            fptag |= 3;
977 f299f437 Blue Swirl
        } else {
978 f299f437 Blue Swirl
            tmp.d = env->fpregs[i].d;
979 f299f437 Blue Swirl
            exp = EXPD(tmp);
980 f299f437 Blue Swirl
            mant = MANTD(tmp);
981 f299f437 Blue Swirl
            if (exp == 0 && mant == 0) {
982 f299f437 Blue Swirl
                /* zero */
983 f299f437 Blue Swirl
                fptag |= 1;
984 f299f437 Blue Swirl
            } else if (exp == 0 || exp == MAXEXPD
985 f299f437 Blue Swirl
                       || (mant & (1LL << 63)) == 0) {
986 f299f437 Blue Swirl
                /* NaNs, infinity, denormal */
987 f299f437 Blue Swirl
                fptag |= 2;
988 f299f437 Blue Swirl
            }
989 f299f437 Blue Swirl
        }
990 f299f437 Blue Swirl
    }
991 f299f437 Blue Swirl
    if (data32) {
992 f299f437 Blue Swirl
        /* 32 bit */
993 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr, env->fpuc);
994 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 4, fpus);
995 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 8, fptag);
996 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 12, 0); /* fpip */
997 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 16, 0); /* fpcs */
998 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 20, 0); /* fpoo */
999 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 24, 0); /* fpos */
1000 f299f437 Blue Swirl
    } else {
1001 f299f437 Blue Swirl
        /* 16 bit */
1002 d3eb5eae Blue Swirl
        cpu_stw_data(env, ptr, env->fpuc);
1003 d3eb5eae Blue Swirl
        cpu_stw_data(env, ptr + 2, fpus);
1004 d3eb5eae Blue Swirl
        cpu_stw_data(env, ptr + 4, fptag);
1005 d3eb5eae Blue Swirl
        cpu_stw_data(env, ptr + 6, 0);
1006 d3eb5eae Blue Swirl
        cpu_stw_data(env, ptr + 8, 0);
1007 d3eb5eae Blue Swirl
        cpu_stw_data(env, ptr + 10, 0);
1008 d3eb5eae Blue Swirl
        cpu_stw_data(env, ptr + 12, 0);
1009 f299f437 Blue Swirl
    }
1010 f299f437 Blue Swirl
}
1011 f299f437 Blue Swirl
1012 d3eb5eae Blue Swirl
void helper_fldenv(CPUX86State *env, target_ulong ptr, int data32)
1013 f299f437 Blue Swirl
{
1014 f299f437 Blue Swirl
    int i, fpus, fptag;
1015 f299f437 Blue Swirl
1016 f299f437 Blue Swirl
    if (data32) {
1017 d3eb5eae Blue Swirl
        env->fpuc = cpu_lduw_data(env, ptr);
1018 d3eb5eae Blue Swirl
        fpus = cpu_lduw_data(env, ptr + 4);
1019 d3eb5eae Blue Swirl
        fptag = cpu_lduw_data(env, ptr + 8);
1020 f299f437 Blue Swirl
    } else {
1021 d3eb5eae Blue Swirl
        env->fpuc = cpu_lduw_data(env, ptr);
1022 d3eb5eae Blue Swirl
        fpus = cpu_lduw_data(env, ptr + 2);
1023 d3eb5eae Blue Swirl
        fptag = cpu_lduw_data(env, ptr + 4);
1024 f299f437 Blue Swirl
    }
1025 f299f437 Blue Swirl
    env->fpstt = (fpus >> 11) & 7;
1026 f299f437 Blue Swirl
    env->fpus = fpus & ~0x3800;
1027 f299f437 Blue Swirl
    for (i = 0; i < 8; i++) {
1028 f299f437 Blue Swirl
        env->fptags[i] = ((fptag & 3) == 3);
1029 f299f437 Blue Swirl
        fptag >>= 2;
1030 f299f437 Blue Swirl
    }
1031 f299f437 Blue Swirl
}
1032 f299f437 Blue Swirl
1033 d3eb5eae Blue Swirl
void helper_fsave(CPUX86State *env, target_ulong ptr, int data32)
1034 f299f437 Blue Swirl
{
1035 f299f437 Blue Swirl
    floatx80 tmp;
1036 f299f437 Blue Swirl
    int i;
1037 f299f437 Blue Swirl
1038 d3eb5eae Blue Swirl
    helper_fstenv(env, ptr, data32);
1039 f299f437 Blue Swirl
1040 f299f437 Blue Swirl
    ptr += (14 << data32);
1041 f299f437 Blue Swirl
    for (i = 0; i < 8; i++) {
1042 f299f437 Blue Swirl
        tmp = ST(i);
1043 d3eb5eae Blue Swirl
        helper_fstt(env, tmp, ptr);
1044 f299f437 Blue Swirl
        ptr += 10;
1045 f299f437 Blue Swirl
    }
1046 f299f437 Blue Swirl
1047 f299f437 Blue Swirl
    /* fninit */
1048 f299f437 Blue Swirl
    env->fpus = 0;
1049 f299f437 Blue Swirl
    env->fpstt = 0;
1050 f299f437 Blue Swirl
    env->fpuc = 0x37f;
1051 f299f437 Blue Swirl
    env->fptags[0] = 1;
1052 f299f437 Blue Swirl
    env->fptags[1] = 1;
1053 f299f437 Blue Swirl
    env->fptags[2] = 1;
1054 f299f437 Blue Swirl
    env->fptags[3] = 1;
1055 f299f437 Blue Swirl
    env->fptags[4] = 1;
1056 f299f437 Blue Swirl
    env->fptags[5] = 1;
1057 f299f437 Blue Swirl
    env->fptags[6] = 1;
1058 f299f437 Blue Swirl
    env->fptags[7] = 1;
1059 f299f437 Blue Swirl
}
1060 f299f437 Blue Swirl
1061 d3eb5eae Blue Swirl
void helper_frstor(CPUX86State *env, target_ulong ptr, int data32)
1062 f299f437 Blue Swirl
{
1063 f299f437 Blue Swirl
    floatx80 tmp;
1064 f299f437 Blue Swirl
    int i;
1065 f299f437 Blue Swirl
1066 d3eb5eae Blue Swirl
    helper_fldenv(env, ptr, data32);
1067 f299f437 Blue Swirl
    ptr += (14 << data32);
1068 f299f437 Blue Swirl
1069 f299f437 Blue Swirl
    for (i = 0; i < 8; i++) {
1070 d3eb5eae Blue Swirl
        tmp = helper_fldt(env, ptr);
1071 f299f437 Blue Swirl
        ST(i) = tmp;
1072 f299f437 Blue Swirl
        ptr += 10;
1073 f299f437 Blue Swirl
    }
1074 f299f437 Blue Swirl
}
1075 f299f437 Blue Swirl
1076 f299f437 Blue Swirl
#if defined(CONFIG_USER_ONLY)
1077 d3eb5eae Blue Swirl
void cpu_x86_fsave(CPUX86State *env, target_ulong ptr, int data32)
1078 f299f437 Blue Swirl
{
1079 d3eb5eae Blue Swirl
    helper_fsave(env, ptr, data32);
1080 f299f437 Blue Swirl
}
1081 f299f437 Blue Swirl
1082 d3eb5eae Blue Swirl
void cpu_x86_frstor(CPUX86State *env, target_ulong ptr, int data32)
1083 f299f437 Blue Swirl
{
1084 d3eb5eae Blue Swirl
    helper_frstor(env, ptr, data32);
1085 f299f437 Blue Swirl
}
1086 f299f437 Blue Swirl
#endif
1087 f299f437 Blue Swirl
1088 d3eb5eae Blue Swirl
void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64)
1089 f299f437 Blue Swirl
{
1090 f299f437 Blue Swirl
    int fpus, fptag, i, nb_xmm_regs;
1091 f299f437 Blue Swirl
    floatx80 tmp;
1092 f299f437 Blue Swirl
    target_ulong addr;
1093 f299f437 Blue Swirl
1094 f299f437 Blue Swirl
    /* The operand must be 16 byte aligned */
1095 f299f437 Blue Swirl
    if (ptr & 0xf) {
1096 f299f437 Blue Swirl
        raise_exception(env, EXCP0D_GPF);
1097 f299f437 Blue Swirl
    }
1098 f299f437 Blue Swirl
1099 f299f437 Blue Swirl
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1100 f299f437 Blue Swirl
    fptag = 0;
1101 f299f437 Blue Swirl
    for (i = 0; i < 8; i++) {
1102 f299f437 Blue Swirl
        fptag |= (env->fptags[i] << i);
1103 f299f437 Blue Swirl
    }
1104 d3eb5eae Blue Swirl
    cpu_stw_data(env, ptr, env->fpuc);
1105 d3eb5eae Blue Swirl
    cpu_stw_data(env, ptr + 2, fpus);
1106 d3eb5eae Blue Swirl
    cpu_stw_data(env, ptr + 4, fptag ^ 0xff);
1107 f299f437 Blue Swirl
#ifdef TARGET_X86_64
1108 f299f437 Blue Swirl
    if (data64) {
1109 d3eb5eae Blue Swirl
        cpu_stq_data(env, ptr + 0x08, 0); /* rip */
1110 d3eb5eae Blue Swirl
        cpu_stq_data(env, ptr + 0x10, 0); /* rdp */
1111 f299f437 Blue Swirl
    } else
1112 f299f437 Blue Swirl
#endif
1113 f299f437 Blue Swirl
    {
1114 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 0x08, 0); /* eip */
1115 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 0x0c, 0); /* sel  */
1116 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 0x10, 0); /* dp */
1117 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 0x14, 0); /* sel  */
1118 f299f437 Blue Swirl
    }
1119 f299f437 Blue Swirl
1120 f299f437 Blue Swirl
    addr = ptr + 0x20;
1121 f299f437 Blue Swirl
    for (i = 0; i < 8; i++) {
1122 f299f437 Blue Swirl
        tmp = ST(i);
1123 d3eb5eae Blue Swirl
        helper_fstt(env, tmp, addr);
1124 f299f437 Blue Swirl
        addr += 16;
1125 f299f437 Blue Swirl
    }
1126 f299f437 Blue Swirl
1127 f299f437 Blue Swirl
    if (env->cr[4] & CR4_OSFXSR_MASK) {
1128 f299f437 Blue Swirl
        /* XXX: finish it */
1129 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 0x18, env->mxcsr); /* mxcsr */
1130 d3eb5eae Blue Swirl
        cpu_stl_data(env, ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
1131 f299f437 Blue Swirl
        if (env->hflags & HF_CS64_MASK) {
1132 f299f437 Blue Swirl
            nb_xmm_regs = 16;
1133 f299f437 Blue Swirl
        } else {
1134 f299f437 Blue Swirl
            nb_xmm_regs = 8;
1135 f299f437 Blue Swirl
        }
1136 f299f437 Blue Swirl
        addr = ptr + 0xa0;
1137 f299f437 Blue Swirl
        /* Fast FXSAVE leaves out the XMM registers */
1138 f299f437 Blue Swirl
        if (!(env->efer & MSR_EFER_FFXSR)
1139 f299f437 Blue Swirl
            || (env->hflags & HF_CPL_MASK)
1140 f299f437 Blue Swirl
            || !(env->hflags & HF_LMA_MASK)) {
1141 f299f437 Blue Swirl
            for (i = 0; i < nb_xmm_regs; i++) {
1142 d3eb5eae Blue Swirl
                cpu_stq_data(env, addr, env->xmm_regs[i].XMM_Q(0));
1143 d3eb5eae Blue Swirl
                cpu_stq_data(env, addr + 8, env->xmm_regs[i].XMM_Q(1));
1144 f299f437 Blue Swirl
                addr += 16;
1145 f299f437 Blue Swirl
            }
1146 f299f437 Blue Swirl
        }
1147 f299f437 Blue Swirl
    }
1148 f299f437 Blue Swirl
}
1149 f299f437 Blue Swirl
1150 d3eb5eae Blue Swirl
void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64)
1151 f299f437 Blue Swirl
{
1152 f299f437 Blue Swirl
    int i, fpus, fptag, nb_xmm_regs;
1153 f299f437 Blue Swirl
    floatx80 tmp;
1154 f299f437 Blue Swirl
    target_ulong addr;
1155 f299f437 Blue Swirl
1156 f299f437 Blue Swirl
    /* The operand must be 16 byte aligned */
1157 f299f437 Blue Swirl
    if (ptr & 0xf) {
1158 f299f437 Blue Swirl
        raise_exception(env, EXCP0D_GPF);
1159 f299f437 Blue Swirl
    }
1160 f299f437 Blue Swirl
1161 d3eb5eae Blue Swirl
    env->fpuc = cpu_lduw_data(env, ptr);
1162 d3eb5eae Blue Swirl
    fpus = cpu_lduw_data(env, ptr + 2);
1163 d3eb5eae Blue Swirl
    fptag = cpu_lduw_data(env, ptr + 4);
1164 f299f437 Blue Swirl
    env->fpstt = (fpus >> 11) & 7;
1165 f299f437 Blue Swirl
    env->fpus = fpus & ~0x3800;
1166 f299f437 Blue Swirl
    fptag ^= 0xff;
1167 f299f437 Blue Swirl
    for (i = 0; i < 8; i++) {
1168 f299f437 Blue Swirl
        env->fptags[i] = ((fptag >> i) & 1);
1169 f299f437 Blue Swirl
    }
1170 f299f437 Blue Swirl
1171 f299f437 Blue Swirl
    addr = ptr + 0x20;
1172 f299f437 Blue Swirl
    for (i = 0; i < 8; i++) {
1173 d3eb5eae Blue Swirl
        tmp = helper_fldt(env, addr);
1174 f299f437 Blue Swirl
        ST(i) = tmp;
1175 f299f437 Blue Swirl
        addr += 16;
1176 f299f437 Blue Swirl
    }
1177 f299f437 Blue Swirl
1178 f299f437 Blue Swirl
    if (env->cr[4] & CR4_OSFXSR_MASK) {
1179 f299f437 Blue Swirl
        /* XXX: finish it */
1180 d3eb5eae Blue Swirl
        env->mxcsr = cpu_ldl_data(env, ptr + 0x18);
1181 d3eb5eae Blue Swirl
        /* cpu_ldl_data(env, ptr + 0x1c); */
1182 f299f437 Blue Swirl
        if (env->hflags & HF_CS64_MASK) {
1183 f299f437 Blue Swirl
            nb_xmm_regs = 16;
1184 f299f437 Blue Swirl
        } else {
1185 f299f437 Blue Swirl
            nb_xmm_regs = 8;
1186 f299f437 Blue Swirl
        }
1187 f299f437 Blue Swirl
        addr = ptr + 0xa0;
1188 f299f437 Blue Swirl
        /* Fast FXRESTORE leaves out the XMM registers */
1189 f299f437 Blue Swirl
        if (!(env->efer & MSR_EFER_FFXSR)
1190 f299f437 Blue Swirl
            || (env->hflags & HF_CPL_MASK)
1191 f299f437 Blue Swirl
            || !(env->hflags & HF_LMA_MASK)) {
1192 f299f437 Blue Swirl
            for (i = 0; i < nb_xmm_regs; i++) {
1193 d3eb5eae Blue Swirl
                env->xmm_regs[i].XMM_Q(0) = cpu_ldq_data(env, addr);
1194 d3eb5eae Blue Swirl
                env->xmm_regs[i].XMM_Q(1) = cpu_ldq_data(env, addr + 8);
1195 f299f437 Blue Swirl
                addr += 16;
1196 f299f437 Blue Swirl
            }
1197 f299f437 Blue Swirl
        }
1198 f299f437 Blue Swirl
    }
1199 f299f437 Blue Swirl
}
1200 f299f437 Blue Swirl
1201 f299f437 Blue Swirl
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
1202 f299f437 Blue Swirl
{
1203 f299f437 Blue Swirl
    CPU_LDoubleU temp;
1204 f299f437 Blue Swirl
1205 f299f437 Blue Swirl
    temp.d = f;
1206 f299f437 Blue Swirl
    *pmant = temp.l.lower;
1207 f299f437 Blue Swirl
    *pexp = temp.l.upper;
1208 f299f437 Blue Swirl
}
1209 f299f437 Blue Swirl
1210 f299f437 Blue Swirl
floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
1211 f299f437 Blue Swirl
{
1212 f299f437 Blue Swirl
    CPU_LDoubleU temp;
1213 f299f437 Blue Swirl
1214 f299f437 Blue Swirl
    temp.l.upper = upper;
1215 f299f437 Blue Swirl
    temp.l.lower = mant;
1216 f299f437 Blue Swirl
    return temp.d;
1217 f299f437 Blue Swirl
}
1218 f299f437 Blue Swirl
1219 f299f437 Blue Swirl
/* MMX/SSE */
1220 f299f437 Blue Swirl
/* XXX: optimize by storing fptt and fptags in the static cpu state */
1221 f299f437 Blue Swirl
1222 f299f437 Blue Swirl
#define SSE_DAZ             0x0040
1223 f299f437 Blue Swirl
#define SSE_RC_MASK         0x6000
1224 f299f437 Blue Swirl
#define SSE_RC_NEAR         0x0000
1225 f299f437 Blue Swirl
#define SSE_RC_DOWN         0x2000
1226 f299f437 Blue Swirl
#define SSE_RC_UP           0x4000
1227 f299f437 Blue Swirl
#define SSE_RC_CHOP         0x6000
1228 f299f437 Blue Swirl
#define SSE_FZ              0x8000
1229 f299f437 Blue Swirl
1230 d3eb5eae Blue Swirl
static void update_sse_status(CPUX86State *env)
1231 f299f437 Blue Swirl
{
1232 f299f437 Blue Swirl
    int rnd_type;
1233 f299f437 Blue Swirl
1234 f299f437 Blue Swirl
    /* set rounding mode */
1235 f299f437 Blue Swirl
    switch (env->mxcsr & SSE_RC_MASK) {
1236 f299f437 Blue Swirl
    default:
1237 f299f437 Blue Swirl
    case SSE_RC_NEAR:
1238 f299f437 Blue Swirl
        rnd_type = float_round_nearest_even;
1239 f299f437 Blue Swirl
        break;
1240 f299f437 Blue Swirl
    case SSE_RC_DOWN:
1241 f299f437 Blue Swirl
        rnd_type = float_round_down;
1242 f299f437 Blue Swirl
        break;
1243 f299f437 Blue Swirl
    case SSE_RC_UP:
1244 f299f437 Blue Swirl
        rnd_type = float_round_up;
1245 f299f437 Blue Swirl
        break;
1246 f299f437 Blue Swirl
    case SSE_RC_CHOP:
1247 f299f437 Blue Swirl
        rnd_type = float_round_to_zero;
1248 f299f437 Blue Swirl
        break;
1249 f299f437 Blue Swirl
    }
1250 f299f437 Blue Swirl
    set_float_rounding_mode(rnd_type, &env->sse_status);
1251 f299f437 Blue Swirl
1252 f299f437 Blue Swirl
    /* set denormals are zero */
1253 f299f437 Blue Swirl
    set_flush_inputs_to_zero((env->mxcsr & SSE_DAZ) ? 1 : 0, &env->sse_status);
1254 f299f437 Blue Swirl
1255 f299f437 Blue Swirl
    /* set flush to zero */
1256 f299f437 Blue Swirl
    set_flush_to_zero((env->mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status);
1257 f299f437 Blue Swirl
}
1258 f299f437 Blue Swirl
1259 d3eb5eae Blue Swirl
void helper_ldmxcsr(CPUX86State *env, uint32_t val)
1260 f299f437 Blue Swirl
{
1261 f299f437 Blue Swirl
    env->mxcsr = val;
1262 d3eb5eae Blue Swirl
    update_sse_status(env);
1263 f299f437 Blue Swirl
}
1264 f299f437 Blue Swirl
1265 d3eb5eae Blue Swirl
void helper_enter_mmx(CPUX86State *env)
1266 f299f437 Blue Swirl
{
1267 f299f437 Blue Swirl
    env->fpstt = 0;
1268 f299f437 Blue Swirl
    *(uint32_t *)(env->fptags) = 0;
1269 f299f437 Blue Swirl
    *(uint32_t *)(env->fptags + 4) = 0;
1270 f299f437 Blue Swirl
}
1271 f299f437 Blue Swirl
1272 d3eb5eae Blue Swirl
void helper_emms(CPUX86State *env)
1273 f299f437 Blue Swirl
{
1274 f299f437 Blue Swirl
    /* set to empty state */
1275 f299f437 Blue Swirl
    *(uint32_t *)(env->fptags) = 0x01010101;
1276 f299f437 Blue Swirl
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
1277 f299f437 Blue Swirl
}
1278 f299f437 Blue Swirl
1279 f299f437 Blue Swirl
/* XXX: suppress */
1280 d3eb5eae Blue Swirl
void helper_movq(CPUX86State *env, void *d, void *s)
1281 f299f437 Blue Swirl
{
1282 f299f437 Blue Swirl
    *(uint64_t *)d = *(uint64_t *)s;
1283 f299f437 Blue Swirl
}
1284 f299f437 Blue Swirl
1285 f299f437 Blue Swirl
#define SHIFT 0
1286 f299f437 Blue Swirl
#include "ops_sse.h"
1287 f299f437 Blue Swirl
1288 f299f437 Blue Swirl
#define SHIFT 1
1289 f299f437 Blue Swirl
#include "ops_sse.h"