Statistics
| Branch: | Revision:

root / target-i386 / fpu_helper.c @ 814589c4

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