Statistics
| Branch: | Revision:

root / op-i386.c @ 7d13299d

History | View | Annotate | Download (34.4 kB)

1 7d13299d bellard
/*
2 7d13299d bellard
 *  i386 micro operations
3 7d13299d bellard
 * 
4 7d13299d bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 7d13299d bellard
 *
6 7d13299d bellard
 *  This program is free software; you can redistribute it and/or modify
7 7d13299d bellard
 *  it under the terms of the GNU General Public License as published by
8 7d13299d bellard
 *  the Free Software Foundation; either version 2 of the License, or
9 7d13299d bellard
 *  (at your option) any later version.
10 7d13299d bellard
 *
11 7d13299d bellard
 *  This program is distributed in the hope that it will be useful,
12 7d13299d bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 7d13299d bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 7d13299d bellard
 *  GNU General Public License for more details.
15 7d13299d bellard
 *
16 7d13299d bellard
 *  You should have received a copy of the GNU General Public License
17 7d13299d bellard
 *  along with this program; if not, write to the Free Software
18 7d13299d bellard
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 7d13299d bellard
 */
20 7d13299d bellard
#include "exec-i386.h"
21 7bfdb6d1 bellard
22 0ecfa993 bellard
/* NOTE: data are not static to force relocation generation by GCC */
23 367e86e8 bellard
24 7bfdb6d1 bellard
uint8_t parity_table[256] = {
25 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
26 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
27 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
28 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
29 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
30 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
31 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
32 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
33 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
34 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
35 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
36 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
37 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
38 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
39 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
40 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
41 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
42 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
44 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
47 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
50 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
52 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
53 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
54 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
55 7bfdb6d1 bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
56 7bfdb6d1 bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
57 7bfdb6d1 bellard
};
58 7bfdb6d1 bellard
59 367e86e8 bellard
/* modulo 17 table */
60 367e86e8 bellard
const uint8_t rclw_table[32] = {
61 367e86e8 bellard
    0, 1, 2, 3, 4, 5, 6, 7, 
62 367e86e8 bellard
    8, 9,10,11,12,13,14,15,
63 367e86e8 bellard
   16, 0, 1, 2, 3, 4, 5, 6,
64 367e86e8 bellard
    7, 8, 9,10,11,12,13,14,
65 367e86e8 bellard
};
66 7bfdb6d1 bellard
67 367e86e8 bellard
/* modulo 9 table */
68 367e86e8 bellard
const uint8_t rclb_table[32] = {
69 367e86e8 bellard
    0, 1, 2, 3, 4, 5, 6, 7, 
70 367e86e8 bellard
    8, 0, 1, 2, 3, 4, 5, 6,
71 367e86e8 bellard
    7, 8, 0, 1, 2, 3, 4, 5, 
72 367e86e8 bellard
    6, 7, 8, 0, 1, 2, 3, 4,
73 367e86e8 bellard
};
74 7bfdb6d1 bellard
75 927f621e bellard
#ifdef USE_X86LDOUBLE
76 927f621e bellard
/* an array of Intel 80-bit FP constants, to be loaded via integer ops */
77 927f621e bellard
typedef unsigned short f15ld[5];
78 927f621e bellard
const f15ld f15rk[] =
79 927f621e bellard
{
80 927f621e bellard
/*0*/        {0x0000,0x0000,0x0000,0x0000,0x0000},
81 927f621e bellard
/*1*/        {0x0000,0x0000,0x0000,0x8000,0x3fff},
82 927f621e bellard
/*pi*/        {0xc235,0x2168,0xdaa2,0xc90f,0x4000},
83 927f621e bellard
/*lg2*/        {0xf799,0xfbcf,0x9a84,0x9a20,0x3ffd},
84 927f621e bellard
/*ln2*/        {0x79ac,0xd1cf,0x17f7,0xb172,0x3ffe},
85 927f621e bellard
/*l2e*/        {0xf0bc,0x5c17,0x3b29,0xb8aa,0x3fff},
86 927f621e bellard
/*l2t*/        {0x8afe,0xcd1b,0x784b,0xd49a,0x4000}
87 927f621e bellard
};
88 927f621e bellard
#else
89 927f621e bellard
/* the same, 64-bit version */
90 927f621e bellard
typedef unsigned short f15ld[4];
91 927f621e bellard
const f15ld f15rk[] =
92 927f621e bellard
{
93 927f621e bellard
#ifndef WORDS_BIGENDIAN
94 927f621e bellard
/*0*/        {0x0000,0x0000,0x0000,0x0000},
95 927f621e bellard
/*1*/        {0x0000,0x0000,0x0000,0x3ff0},
96 927f621e bellard
/*pi*/        {0x2d18,0x5444,0x21fb,0x4009},
97 927f621e bellard
/*lg2*/        {0x79ff,0x509f,0x4413,0x3fd3},
98 927f621e bellard
/*ln2*/        {0x39ef,0xfefa,0x2e42,0x3fe6},
99 927f621e bellard
/*l2e*/        {0x82fe,0x652b,0x1547,0x3ff7},
100 927f621e bellard
/*l2t*/        {0xa371,0x0979,0x934f,0x400a}
101 927f621e bellard
#else
102 927f621e bellard
/*0*/   {0x0000,0x0000,0x0000,0x0000},
103 927f621e bellard
/*1*/   {0x3ff0,0x0000,0x0000,0x0000},
104 927f621e bellard
/*pi*/  {0x4009,0x21fb,0x5444,0x2d18},
105 927f621e bellard
/*lg2*/        {0x3fd3,0x4413,0x509f,0x79ff},
106 927f621e bellard
/*ln2*/        {0x3fe6,0x2e42,0xfefa,0x39ef},
107 927f621e bellard
/*l2e*/        {0x3ff7,0x1547,0x652b,0x82fe},
108 927f621e bellard
/*l2t*/        {0x400a,0x934f,0x0979,0xa371}
109 927f621e bellard
#endif
110 927f621e bellard
};
111 927f621e bellard
#endif
112 927f621e bellard
    
113 367e86e8 bellard
/* n must be a constant to be efficient */
114 367e86e8 bellard
static inline int lshift(int x, int n)
115 7bfdb6d1 bellard
{
116 367e86e8 bellard
    if (n >= 0)
117 367e86e8 bellard
        return x << n;
118 367e86e8 bellard
    else
119 367e86e8 bellard
        return x >> (-n);
120 7bfdb6d1 bellard
}
121 7bfdb6d1 bellard
122 0ecfa993 bellard
/* exception support */
123 0ecfa993 bellard
/* NOTE: not static to force relocation generation by GCC */
124 0ecfa993 bellard
void raise_exception(int exception_index)
125 0ecfa993 bellard
{
126 0ecfa993 bellard
    env->exception_index = exception_index;
127 0ecfa993 bellard
    longjmp(env->jmp_env, 1);
128 0ecfa993 bellard
}
129 0ecfa993 bellard
130 7bfdb6d1 bellard
/* we define the various pieces of code used by the JIT */
131 7bfdb6d1 bellard
132 7bfdb6d1 bellard
#define REG EAX
133 7bfdb6d1 bellard
#define REGNAME _EAX
134 7bfdb6d1 bellard
#include "opreg_template.h"
135 7bfdb6d1 bellard
#undef REG
136 7bfdb6d1 bellard
#undef REGNAME
137 7bfdb6d1 bellard
138 7bfdb6d1 bellard
#define REG ECX
139 7bfdb6d1 bellard
#define REGNAME _ECX
140 7bfdb6d1 bellard
#include "opreg_template.h"
141 7bfdb6d1 bellard
#undef REG
142 7bfdb6d1 bellard
#undef REGNAME
143 7bfdb6d1 bellard
144 7bfdb6d1 bellard
#define REG EDX
145 7bfdb6d1 bellard
#define REGNAME _EDX
146 7bfdb6d1 bellard
#include "opreg_template.h"
147 7bfdb6d1 bellard
#undef REG
148 7bfdb6d1 bellard
#undef REGNAME
149 7bfdb6d1 bellard
150 7bfdb6d1 bellard
#define REG EBX
151 7bfdb6d1 bellard
#define REGNAME _EBX
152 7bfdb6d1 bellard
#include "opreg_template.h"
153 7bfdb6d1 bellard
#undef REG
154 7bfdb6d1 bellard
#undef REGNAME
155 7bfdb6d1 bellard
156 7bfdb6d1 bellard
#define REG ESP
157 7bfdb6d1 bellard
#define REGNAME _ESP
158 7bfdb6d1 bellard
#include "opreg_template.h"
159 7bfdb6d1 bellard
#undef REG
160 7bfdb6d1 bellard
#undef REGNAME
161 7bfdb6d1 bellard
162 7bfdb6d1 bellard
#define REG EBP
163 7bfdb6d1 bellard
#define REGNAME _EBP
164 7bfdb6d1 bellard
#include "opreg_template.h"
165 7bfdb6d1 bellard
#undef REG
166 7bfdb6d1 bellard
#undef REGNAME
167 7bfdb6d1 bellard
168 7bfdb6d1 bellard
#define REG ESI
169 7bfdb6d1 bellard
#define REGNAME _ESI
170 7bfdb6d1 bellard
#include "opreg_template.h"
171 7bfdb6d1 bellard
#undef REG
172 7bfdb6d1 bellard
#undef REGNAME
173 7bfdb6d1 bellard
174 7bfdb6d1 bellard
#define REG EDI
175 7bfdb6d1 bellard
#define REGNAME _EDI
176 7bfdb6d1 bellard
#include "opreg_template.h"
177 7bfdb6d1 bellard
#undef REG
178 7bfdb6d1 bellard
#undef REGNAME
179 7bfdb6d1 bellard
180 7bfdb6d1 bellard
/* operations */
181 7bfdb6d1 bellard
182 7bfdb6d1 bellard
void OPPROTO op_addl_T0_T1_cc(void)
183 7bfdb6d1 bellard
{
184 7bfdb6d1 bellard
    CC_SRC = T0;
185 7bfdb6d1 bellard
    T0 += T1;
186 7bfdb6d1 bellard
    CC_DST = T0;
187 7bfdb6d1 bellard
}
188 7bfdb6d1 bellard
189 7bfdb6d1 bellard
void OPPROTO op_orl_T0_T1_cc(void)
190 7bfdb6d1 bellard
{
191 7bfdb6d1 bellard
    T0 |= T1;
192 7bfdb6d1 bellard
    CC_DST = T0;
193 7bfdb6d1 bellard
}
194 7bfdb6d1 bellard
195 7bfdb6d1 bellard
void OPPROTO op_andl_T0_T1_cc(void)
196 7bfdb6d1 bellard
{
197 7bfdb6d1 bellard
    T0 &= T1;
198 7bfdb6d1 bellard
    CC_DST = T0;
199 7bfdb6d1 bellard
}
200 7bfdb6d1 bellard
201 7bfdb6d1 bellard
void OPPROTO op_subl_T0_T1_cc(void)
202 7bfdb6d1 bellard
{
203 7bfdb6d1 bellard
    CC_SRC = T0;
204 7bfdb6d1 bellard
    T0 -= T1;
205 7bfdb6d1 bellard
    CC_DST = T0;
206 7bfdb6d1 bellard
}
207 7bfdb6d1 bellard
208 7bfdb6d1 bellard
void OPPROTO op_xorl_T0_T1_cc(void)
209 7bfdb6d1 bellard
{
210 7bfdb6d1 bellard
    T0 ^= T1;
211 7bfdb6d1 bellard
    CC_DST = T0;
212 7bfdb6d1 bellard
}
213 7bfdb6d1 bellard
214 7bfdb6d1 bellard
void OPPROTO op_cmpl_T0_T1_cc(void)
215 7bfdb6d1 bellard
{
216 7bfdb6d1 bellard
    CC_SRC = T0;
217 7bfdb6d1 bellard
    CC_DST = T0 - T1;
218 7bfdb6d1 bellard
}
219 7bfdb6d1 bellard
220 7bfdb6d1 bellard
void OPPROTO op_notl_T0(void)
221 7bfdb6d1 bellard
{
222 7bfdb6d1 bellard
    T0 = ~T0;
223 7bfdb6d1 bellard
}
224 7bfdb6d1 bellard
225 7bfdb6d1 bellard
void OPPROTO op_negl_T0_cc(void)
226 7bfdb6d1 bellard
{
227 7bfdb6d1 bellard
    CC_SRC = 0;
228 7bfdb6d1 bellard
    T0 = -T0;
229 7bfdb6d1 bellard
    CC_DST = T0;
230 7bfdb6d1 bellard
}
231 7bfdb6d1 bellard
232 7bfdb6d1 bellard
void OPPROTO op_incl_T0_cc(void)
233 7bfdb6d1 bellard
{
234 4b74fe1f bellard
    CC_SRC = cc_table[CC_OP].compute_c();
235 7bfdb6d1 bellard
    T0++;
236 7bfdb6d1 bellard
    CC_DST = T0;
237 7bfdb6d1 bellard
}
238 7bfdb6d1 bellard
239 7bfdb6d1 bellard
void OPPROTO op_decl_T0_cc(void)
240 7bfdb6d1 bellard
{
241 4b74fe1f bellard
    CC_SRC = cc_table[CC_OP].compute_c();
242 7bfdb6d1 bellard
    T0--;
243 7bfdb6d1 bellard
    CC_DST = T0;
244 7bfdb6d1 bellard
}
245 7bfdb6d1 bellard
246 7bfdb6d1 bellard
void OPPROTO op_testl_T0_T1_cc(void)
247 7bfdb6d1 bellard
{
248 7bfdb6d1 bellard
    CC_DST = T0 & T1;
249 7bfdb6d1 bellard
}
250 7bfdb6d1 bellard
251 4b74fe1f bellard
void OPPROTO op_bswapl_T0(void)
252 4b74fe1f bellard
{
253 4b74fe1f bellard
    T0 = bswap32(T0);
254 4b74fe1f bellard
}
255 4b74fe1f bellard
256 7bfdb6d1 bellard
/* multiply/divide */
257 7bfdb6d1 bellard
void OPPROTO op_mulb_AL_T0(void)
258 7bfdb6d1 bellard
{
259 7bfdb6d1 bellard
    unsigned int res;
260 7bfdb6d1 bellard
    res = (uint8_t)EAX * (uint8_t)T0;
261 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | res;
262 7bfdb6d1 bellard
    CC_SRC = (res & 0xff00);
263 7bfdb6d1 bellard
}
264 7bfdb6d1 bellard
265 7bfdb6d1 bellard
void OPPROTO op_imulb_AL_T0(void)
266 7bfdb6d1 bellard
{
267 7bfdb6d1 bellard
    int res;
268 7bfdb6d1 bellard
    res = (int8_t)EAX * (int8_t)T0;
269 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
270 7bfdb6d1 bellard
    CC_SRC = (res != (int8_t)res);
271 7bfdb6d1 bellard
}
272 7bfdb6d1 bellard
273 7bfdb6d1 bellard
void OPPROTO op_mulw_AX_T0(void)
274 7bfdb6d1 bellard
{
275 7bfdb6d1 bellard
    unsigned int res;
276 7bfdb6d1 bellard
    res = (uint16_t)EAX * (uint16_t)T0;
277 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
278 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
279 7bfdb6d1 bellard
    CC_SRC = res >> 16;
280 7bfdb6d1 bellard
}
281 7bfdb6d1 bellard
282 7bfdb6d1 bellard
void OPPROTO op_imulw_AX_T0(void)
283 7bfdb6d1 bellard
{
284 7bfdb6d1 bellard
    int res;
285 7bfdb6d1 bellard
    res = (int16_t)EAX * (int16_t)T0;
286 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
287 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
288 7bfdb6d1 bellard
    CC_SRC = (res != (int16_t)res);
289 7bfdb6d1 bellard
}
290 7bfdb6d1 bellard
291 7bfdb6d1 bellard
void OPPROTO op_mull_EAX_T0(void)
292 7bfdb6d1 bellard
{
293 7bfdb6d1 bellard
    uint64_t res;
294 7bfdb6d1 bellard
    res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
295 7bfdb6d1 bellard
    EAX = res;
296 7bfdb6d1 bellard
    EDX = res >> 32;
297 7bfdb6d1 bellard
    CC_SRC = res >> 32;
298 7bfdb6d1 bellard
}
299 7bfdb6d1 bellard
300 7bfdb6d1 bellard
void OPPROTO op_imull_EAX_T0(void)
301 7bfdb6d1 bellard
{
302 7bfdb6d1 bellard
    int64_t res;
303 7bfdb6d1 bellard
    res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
304 7bfdb6d1 bellard
    EAX = res;
305 7bfdb6d1 bellard
    EDX = res >> 32;
306 7bfdb6d1 bellard
    CC_SRC = (res != (int32_t)res);
307 7bfdb6d1 bellard
}
308 7bfdb6d1 bellard
309 7bfdb6d1 bellard
void OPPROTO op_imulw_T0_T1(void)
310 7bfdb6d1 bellard
{
311 7bfdb6d1 bellard
    int res;
312 7bfdb6d1 bellard
    res = (int16_t)T0 * (int16_t)T1;
313 7bfdb6d1 bellard
    T0 = res;
314 7bfdb6d1 bellard
    CC_SRC = (res != (int16_t)res);
315 7bfdb6d1 bellard
}
316 7bfdb6d1 bellard
317 7bfdb6d1 bellard
void OPPROTO op_imull_T0_T1(void)
318 7bfdb6d1 bellard
{
319 7bfdb6d1 bellard
    int64_t res;
320 4b74fe1f bellard
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
321 7bfdb6d1 bellard
    T0 = res;
322 7bfdb6d1 bellard
    CC_SRC = (res != (int32_t)res);
323 7bfdb6d1 bellard
}
324 7bfdb6d1 bellard
325 7bfdb6d1 bellard
/* division, flags are undefined */
326 7bfdb6d1 bellard
/* XXX: add exceptions for overflow & div by zero */
327 7bfdb6d1 bellard
void OPPROTO op_divb_AL_T0(void)
328 7bfdb6d1 bellard
{
329 7bfdb6d1 bellard
    unsigned int num, den, q, r;
330 7bfdb6d1 bellard
331 7bfdb6d1 bellard
    num = (EAX & 0xffff);
332 7bfdb6d1 bellard
    den = (T0 & 0xff);
333 7bfdb6d1 bellard
    q = (num / den) & 0xff;
334 7bfdb6d1 bellard
    r = (num % den) & 0xff;
335 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
336 7bfdb6d1 bellard
}
337 7bfdb6d1 bellard
338 7bfdb6d1 bellard
void OPPROTO op_idivb_AL_T0(void)
339 7bfdb6d1 bellard
{
340 7bfdb6d1 bellard
    int num, den, q, r;
341 7bfdb6d1 bellard
342 7bfdb6d1 bellard
    num = (int16_t)EAX;
343 7bfdb6d1 bellard
    den = (int8_t)T0;
344 7bfdb6d1 bellard
    q = (num / den) & 0xff;
345 7bfdb6d1 bellard
    r = (num % den) & 0xff;
346 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
347 7bfdb6d1 bellard
}
348 7bfdb6d1 bellard
349 7bfdb6d1 bellard
void OPPROTO op_divw_AX_T0(void)
350 7bfdb6d1 bellard
{
351 7bfdb6d1 bellard
    unsigned int num, den, q, r;
352 7bfdb6d1 bellard
353 7bfdb6d1 bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
354 7bfdb6d1 bellard
    den = (T0 & 0xffff);
355 7bfdb6d1 bellard
    q = (num / den) & 0xffff;
356 7bfdb6d1 bellard
    r = (num % den) & 0xffff;
357 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | q;
358 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | r;
359 7bfdb6d1 bellard
}
360 7bfdb6d1 bellard
361 7bfdb6d1 bellard
void OPPROTO op_idivw_AX_T0(void)
362 7bfdb6d1 bellard
{
363 7bfdb6d1 bellard
    int num, den, q, r;
364 7bfdb6d1 bellard
365 7bfdb6d1 bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
366 7bfdb6d1 bellard
    den = (int16_t)T0;
367 7bfdb6d1 bellard
    q = (num / den) & 0xffff;
368 7bfdb6d1 bellard
    r = (num % den) & 0xffff;
369 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | q;
370 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | r;
371 7bfdb6d1 bellard
}
372 7bfdb6d1 bellard
373 7bfdb6d1 bellard
void OPPROTO op_divl_EAX_T0(void)
374 7bfdb6d1 bellard
{
375 7bfdb6d1 bellard
    unsigned int den, q, r;
376 7bfdb6d1 bellard
    uint64_t num;
377 7bfdb6d1 bellard
    
378 7bfdb6d1 bellard
    num = EAX | ((uint64_t)EDX << 32);
379 7bfdb6d1 bellard
    den = T0;
380 7bfdb6d1 bellard
    q = (num / den);
381 7bfdb6d1 bellard
    r = (num % den);
382 7bfdb6d1 bellard
    EAX = q;
383 7bfdb6d1 bellard
    EDX = r;
384 7bfdb6d1 bellard
}
385 7bfdb6d1 bellard
386 7bfdb6d1 bellard
void OPPROTO op_idivl_EAX_T0(void)
387 7bfdb6d1 bellard
{
388 7bfdb6d1 bellard
    int den, q, r;
389 4b74fe1f bellard
    int64_t num;
390 7bfdb6d1 bellard
    
391 7bfdb6d1 bellard
    num = EAX | ((uint64_t)EDX << 32);
392 4b74fe1f bellard
    den = T0;
393 7bfdb6d1 bellard
    q = (num / den);
394 7bfdb6d1 bellard
    r = (num % den);
395 7bfdb6d1 bellard
    EAX = q;
396 7bfdb6d1 bellard
    EDX = r;
397 7bfdb6d1 bellard
}
398 7bfdb6d1 bellard
399 7bfdb6d1 bellard
/* constant load */
400 7bfdb6d1 bellard
401 ba1c6e37 bellard
void OPPROTO op_movl_T0_im(void)
402 7bfdb6d1 bellard
{
403 7bfdb6d1 bellard
    T0 = PARAM1;
404 7bfdb6d1 bellard
}
405 7bfdb6d1 bellard
406 ba1c6e37 bellard
void OPPROTO op_movl_T1_im(void)
407 7bfdb6d1 bellard
{
408 7bfdb6d1 bellard
    T1 = PARAM1;
409 7bfdb6d1 bellard
}
410 7bfdb6d1 bellard
411 ba1c6e37 bellard
void OPPROTO op_movl_A0_im(void)
412 7bfdb6d1 bellard
{
413 7bfdb6d1 bellard
    A0 = PARAM1;
414 7bfdb6d1 bellard
}
415 7bfdb6d1 bellard
416 4b74fe1f bellard
void OPPROTO op_addl_A0_im(void)
417 4b74fe1f bellard
{
418 4b74fe1f bellard
    A0 += PARAM1;
419 4b74fe1f bellard
}
420 4b74fe1f bellard
421 4b74fe1f bellard
void OPPROTO op_andl_A0_ffff(void)
422 4b74fe1f bellard
{
423 4b74fe1f bellard
    A0 = A0 & 0xffff;
424 4b74fe1f bellard
}
425 4b74fe1f bellard
426 7bfdb6d1 bellard
/* memory access */
427 7bfdb6d1 bellard
428 7bfdb6d1 bellard
void OPPROTO op_ldub_T0_A0(void)
429 7bfdb6d1 bellard
{
430 7bfdb6d1 bellard
    T0 = ldub((uint8_t *)A0);
431 7bfdb6d1 bellard
}
432 7bfdb6d1 bellard
433 7bfdb6d1 bellard
void OPPROTO op_ldsb_T0_A0(void)
434 7bfdb6d1 bellard
{
435 7bfdb6d1 bellard
    T0 = ldsb((int8_t *)A0);
436 7bfdb6d1 bellard
}
437 7bfdb6d1 bellard
438 7bfdb6d1 bellard
void OPPROTO op_lduw_T0_A0(void)
439 7bfdb6d1 bellard
{
440 7bfdb6d1 bellard
    T0 = lduw((uint8_t *)A0);
441 7bfdb6d1 bellard
}
442 7bfdb6d1 bellard
443 7bfdb6d1 bellard
void OPPROTO op_ldsw_T0_A0(void)
444 7bfdb6d1 bellard
{
445 7bfdb6d1 bellard
    T0 = ldsw((int8_t *)A0);
446 7bfdb6d1 bellard
}
447 7bfdb6d1 bellard
448 7bfdb6d1 bellard
void OPPROTO op_ldl_T0_A0(void)
449 7bfdb6d1 bellard
{
450 7bfdb6d1 bellard
    T0 = ldl((uint8_t *)A0);
451 7bfdb6d1 bellard
}
452 7bfdb6d1 bellard
453 7bfdb6d1 bellard
void OPPROTO op_ldub_T1_A0(void)
454 7bfdb6d1 bellard
{
455 7bfdb6d1 bellard
    T1 = ldub((uint8_t *)A0);
456 7bfdb6d1 bellard
}
457 7bfdb6d1 bellard
458 7bfdb6d1 bellard
void OPPROTO op_ldsb_T1_A0(void)
459 7bfdb6d1 bellard
{
460 7bfdb6d1 bellard
    T1 = ldsb((int8_t *)A0);
461 7bfdb6d1 bellard
}
462 7bfdb6d1 bellard
463 7bfdb6d1 bellard
void OPPROTO op_lduw_T1_A0(void)
464 7bfdb6d1 bellard
{
465 7bfdb6d1 bellard
    T1 = lduw((uint8_t *)A0);
466 7bfdb6d1 bellard
}
467 7bfdb6d1 bellard
468 7bfdb6d1 bellard
void OPPROTO op_ldsw_T1_A0(void)
469 7bfdb6d1 bellard
{
470 7bfdb6d1 bellard
    T1 = ldsw((int8_t *)A0);
471 7bfdb6d1 bellard
}
472 7bfdb6d1 bellard
473 7bfdb6d1 bellard
void OPPROTO op_ldl_T1_A0(void)
474 7bfdb6d1 bellard
{
475 7bfdb6d1 bellard
    T1 = ldl((uint8_t *)A0);
476 7bfdb6d1 bellard
}
477 7bfdb6d1 bellard
478 7bfdb6d1 bellard
void OPPROTO op_stb_T0_A0(void)
479 7bfdb6d1 bellard
{
480 7bfdb6d1 bellard
    stb((uint8_t *)A0, T0);
481 7bfdb6d1 bellard
}
482 7bfdb6d1 bellard
483 7bfdb6d1 bellard
void OPPROTO op_stw_T0_A0(void)
484 7bfdb6d1 bellard
{
485 7bfdb6d1 bellard
    stw((uint8_t *)A0, T0);
486 7bfdb6d1 bellard
}
487 7bfdb6d1 bellard
488 7bfdb6d1 bellard
void OPPROTO op_stl_T0_A0(void)
489 7bfdb6d1 bellard
{
490 7bfdb6d1 bellard
    stl((uint8_t *)A0, T0);
491 7bfdb6d1 bellard
}
492 7bfdb6d1 bellard
493 4b74fe1f bellard
/* used for bit operations */
494 4b74fe1f bellard
495 4b74fe1f bellard
void OPPROTO op_add_bitw_A0_T1(void)
496 4b74fe1f bellard
{
497 4b74fe1f bellard
    A0 += ((int32_t)T1 >> 4) << 1;
498 4b74fe1f bellard
}
499 4b74fe1f bellard
500 4b74fe1f bellard
void OPPROTO op_add_bitl_A0_T1(void)
501 4b74fe1f bellard
{
502 4b74fe1f bellard
    A0 += ((int32_t)T1 >> 5) << 2;
503 4b74fe1f bellard
}
504 7bfdb6d1 bellard
505 7bfdb6d1 bellard
/* indirect jump */
506 0ecfa993 bellard
507 7bfdb6d1 bellard
void OPPROTO op_jmp_T0(void)
508 7bfdb6d1 bellard
{
509 7bfdb6d1 bellard
    PC = T0;
510 7bfdb6d1 bellard
}
511 7bfdb6d1 bellard
512 7bfdb6d1 bellard
void OPPROTO op_jmp_im(void)
513 7bfdb6d1 bellard
{
514 7bfdb6d1 bellard
    PC = PARAM1;
515 7bfdb6d1 bellard
}
516 7bfdb6d1 bellard
517 0ecfa993 bellard
void OPPROTO op_int_im(void)
518 0ecfa993 bellard
{
519 0ecfa993 bellard
    PC = PARAM1;
520 0ecfa993 bellard
    raise_exception(EXCP0D_GPF);
521 0ecfa993 bellard
}
522 0ecfa993 bellard
523 0ecfa993 bellard
void OPPROTO op_int3(void)
524 0ecfa993 bellard
{
525 0ecfa993 bellard
    PC = PARAM1;
526 0ecfa993 bellard
    raise_exception(EXCP03_INT3);
527 0ecfa993 bellard
}
528 0ecfa993 bellard
529 0ecfa993 bellard
void OPPROTO op_into(void)
530 0ecfa993 bellard
{
531 0ecfa993 bellard
    int eflags;
532 0ecfa993 bellard
    eflags = cc_table[CC_OP].compute_all();
533 0ecfa993 bellard
    if (eflags & CC_O) {
534 0ecfa993 bellard
        PC = PARAM1;
535 0ecfa993 bellard
        raise_exception(EXCP04_INTO);
536 0ecfa993 bellard
    } else {
537 0ecfa993 bellard
        PC = PARAM2;
538 0ecfa993 bellard
    }
539 0ecfa993 bellard
}
540 0ecfa993 bellard
541 7bfdb6d1 bellard
/* string ops */
542 7bfdb6d1 bellard
543 7bfdb6d1 bellard
#define ldul ldl
544 7bfdb6d1 bellard
545 7bfdb6d1 bellard
#define SHIFT 0
546 367e86e8 bellard
#include "ops_template.h"
547 7bfdb6d1 bellard
#undef SHIFT
548 7bfdb6d1 bellard
549 7bfdb6d1 bellard
#define SHIFT 1
550 367e86e8 bellard
#include "ops_template.h"
551 7bfdb6d1 bellard
#undef SHIFT
552 7bfdb6d1 bellard
553 7bfdb6d1 bellard
#define SHIFT 2
554 367e86e8 bellard
#include "ops_template.h"
555 7bfdb6d1 bellard
#undef SHIFT
556 7bfdb6d1 bellard
557 7bfdb6d1 bellard
/* sign extend */
558 7bfdb6d1 bellard
559 7bfdb6d1 bellard
void OPPROTO op_movsbl_T0_T0(void)
560 7bfdb6d1 bellard
{
561 7bfdb6d1 bellard
    T0 = (int8_t)T0;
562 7bfdb6d1 bellard
}
563 7bfdb6d1 bellard
564 7bfdb6d1 bellard
void OPPROTO op_movzbl_T0_T0(void)
565 7bfdb6d1 bellard
{
566 7bfdb6d1 bellard
    T0 = (uint8_t)T0;
567 7bfdb6d1 bellard
}
568 7bfdb6d1 bellard
569 7bfdb6d1 bellard
void OPPROTO op_movswl_T0_T0(void)
570 7bfdb6d1 bellard
{
571 7bfdb6d1 bellard
    T0 = (int16_t)T0;
572 7bfdb6d1 bellard
}
573 7bfdb6d1 bellard
574 7bfdb6d1 bellard
void OPPROTO op_movzwl_T0_T0(void)
575 7bfdb6d1 bellard
{
576 7bfdb6d1 bellard
    T0 = (uint16_t)T0;
577 7bfdb6d1 bellard
}
578 7bfdb6d1 bellard
579 7bfdb6d1 bellard
void OPPROTO op_movswl_EAX_AX(void)
580 7bfdb6d1 bellard
{
581 7bfdb6d1 bellard
    EAX = (int16_t)EAX;
582 7bfdb6d1 bellard
}
583 7bfdb6d1 bellard
584 7bfdb6d1 bellard
void OPPROTO op_movsbw_AX_AL(void)
585 7bfdb6d1 bellard
{
586 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
587 7bfdb6d1 bellard
}
588 7bfdb6d1 bellard
589 7bfdb6d1 bellard
void OPPROTO op_movslq_EDX_EAX(void)
590 7bfdb6d1 bellard
{
591 7bfdb6d1 bellard
    EDX = (int32_t)EAX >> 31;
592 7bfdb6d1 bellard
}
593 7bfdb6d1 bellard
594 7bfdb6d1 bellard
void OPPROTO op_movswl_DX_AX(void)
595 7bfdb6d1 bellard
{
596 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
597 7bfdb6d1 bellard
}
598 7bfdb6d1 bellard
599 7bfdb6d1 bellard
/* push/pop */
600 7bfdb6d1 bellard
/* XXX: add 16 bit operand/16 bit seg variants */
601 7bfdb6d1 bellard
602 7bfdb6d1 bellard
void op_pushl_T0(void)
603 7bfdb6d1 bellard
{
604 7bfdb6d1 bellard
    uint32_t offset;
605 7bfdb6d1 bellard
    offset = ESP - 4;
606 7bfdb6d1 bellard
    stl((void *)offset, T0);
607 7bfdb6d1 bellard
    /* modify ESP after to handle exceptions correctly */
608 7bfdb6d1 bellard
    ESP = offset;
609 7bfdb6d1 bellard
}
610 7bfdb6d1 bellard
611 7bfdb6d1 bellard
void op_pushl_T1(void)
612 7bfdb6d1 bellard
{
613 7bfdb6d1 bellard
    uint32_t offset;
614 7bfdb6d1 bellard
    offset = ESP - 4;
615 7bfdb6d1 bellard
    stl((void *)offset, T1);
616 7bfdb6d1 bellard
    /* modify ESP after to handle exceptions correctly */
617 7bfdb6d1 bellard
    ESP = offset;
618 7bfdb6d1 bellard
}
619 7bfdb6d1 bellard
620 7bfdb6d1 bellard
void op_popl_T0(void)
621 7bfdb6d1 bellard
{
622 7bfdb6d1 bellard
    T0 = ldl((void *)ESP);
623 7bfdb6d1 bellard
    ESP += 4;
624 7bfdb6d1 bellard
}
625 7bfdb6d1 bellard
626 7bfdb6d1 bellard
void op_addl_ESP_im(void)
627 7bfdb6d1 bellard
{
628 7bfdb6d1 bellard
    ESP += PARAM1;
629 7bfdb6d1 bellard
}
630 367e86e8 bellard
631 367e86e8 bellard
/* flags handling */
632 367e86e8 bellard
633 367e86e8 bellard
/* slow jumps cases (compute x86 flags) */
634 367e86e8 bellard
void OPPROTO op_jo_cc(void)
635 367e86e8 bellard
{
636 367e86e8 bellard
    int eflags;
637 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
638 367e86e8 bellard
    if (eflags & CC_O)
639 0ecfa993 bellard
        PC = PARAM1;
640 367e86e8 bellard
    else
641 0ecfa993 bellard
        PC = PARAM2;
642 0ecfa993 bellard
    FORCE_RET();
643 367e86e8 bellard
}
644 367e86e8 bellard
645 367e86e8 bellard
void OPPROTO op_jb_cc(void)
646 367e86e8 bellard
{
647 367e86e8 bellard
    if (cc_table[CC_OP].compute_c())
648 0ecfa993 bellard
        PC = PARAM1;
649 367e86e8 bellard
    else
650 0ecfa993 bellard
        PC = PARAM2;
651 0ecfa993 bellard
    FORCE_RET();
652 367e86e8 bellard
}
653 367e86e8 bellard
654 367e86e8 bellard
void OPPROTO op_jz_cc(void)
655 367e86e8 bellard
{
656 367e86e8 bellard
    int eflags;
657 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
658 367e86e8 bellard
    if (eflags & CC_Z)
659 0ecfa993 bellard
        PC = PARAM1;
660 367e86e8 bellard
    else
661 0ecfa993 bellard
        PC = PARAM2;
662 0ecfa993 bellard
    FORCE_RET();
663 367e86e8 bellard
}
664 367e86e8 bellard
665 367e86e8 bellard
void OPPROTO op_jbe_cc(void)
666 367e86e8 bellard
{
667 367e86e8 bellard
    int eflags;
668 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
669 367e86e8 bellard
    if (eflags & (CC_Z | CC_C))
670 0ecfa993 bellard
        PC = PARAM1;
671 367e86e8 bellard
    else
672 0ecfa993 bellard
        PC = PARAM2;
673 0ecfa993 bellard
    FORCE_RET();
674 367e86e8 bellard
}
675 367e86e8 bellard
676 367e86e8 bellard
void OPPROTO op_js_cc(void)
677 367e86e8 bellard
{
678 367e86e8 bellard
    int eflags;
679 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
680 367e86e8 bellard
    if (eflags & CC_S)
681 0ecfa993 bellard
        PC = PARAM1;
682 367e86e8 bellard
    else
683 0ecfa993 bellard
        PC = PARAM2;
684 0ecfa993 bellard
    FORCE_RET();
685 367e86e8 bellard
}
686 367e86e8 bellard
687 367e86e8 bellard
void OPPROTO op_jp_cc(void)
688 367e86e8 bellard
{
689 367e86e8 bellard
    int eflags;
690 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
691 367e86e8 bellard
    if (eflags & CC_P)
692 0ecfa993 bellard
        PC = PARAM1;
693 367e86e8 bellard
    else
694 0ecfa993 bellard
        PC = PARAM2;
695 0ecfa993 bellard
    FORCE_RET();
696 367e86e8 bellard
}
697 367e86e8 bellard
698 367e86e8 bellard
void OPPROTO op_jl_cc(void)
699 367e86e8 bellard
{
700 367e86e8 bellard
    int eflags;
701 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
702 367e86e8 bellard
    if ((eflags ^ (eflags >> 4)) & 0x80)
703 0ecfa993 bellard
        PC = PARAM1;
704 367e86e8 bellard
    else
705 0ecfa993 bellard
        PC = PARAM2;
706 0ecfa993 bellard
    FORCE_RET();
707 367e86e8 bellard
}
708 367e86e8 bellard
709 367e86e8 bellard
void OPPROTO op_jle_cc(void)
710 367e86e8 bellard
{
711 367e86e8 bellard
    int eflags;
712 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
713 367e86e8 bellard
    if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
714 0ecfa993 bellard
        PC = PARAM1;
715 367e86e8 bellard
    else
716 0ecfa993 bellard
        PC = PARAM2;
717 0ecfa993 bellard
    FORCE_RET();
718 367e86e8 bellard
}
719 367e86e8 bellard
720 367e86e8 bellard
/* slow set cases (compute x86 flags) */
721 367e86e8 bellard
void OPPROTO op_seto_T0_cc(void)
722 367e86e8 bellard
{
723 367e86e8 bellard
    int eflags;
724 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
725 367e86e8 bellard
    T0 = (eflags >> 11) & 1;
726 367e86e8 bellard
}
727 367e86e8 bellard
728 367e86e8 bellard
void OPPROTO op_setb_T0_cc(void)
729 367e86e8 bellard
{
730 367e86e8 bellard
    T0 = cc_table[CC_OP].compute_c();
731 367e86e8 bellard
}
732 367e86e8 bellard
733 367e86e8 bellard
void OPPROTO op_setz_T0_cc(void)
734 367e86e8 bellard
{
735 367e86e8 bellard
    int eflags;
736 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
737 367e86e8 bellard
    T0 = (eflags >> 6) & 1;
738 367e86e8 bellard
}
739 367e86e8 bellard
740 367e86e8 bellard
void OPPROTO op_setbe_T0_cc(void)
741 367e86e8 bellard
{
742 367e86e8 bellard
    int eflags;
743 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
744 367e86e8 bellard
    T0 = (eflags & (CC_Z | CC_C)) != 0;
745 367e86e8 bellard
}
746 367e86e8 bellard
747 367e86e8 bellard
void OPPROTO op_sets_T0_cc(void)
748 367e86e8 bellard
{
749 367e86e8 bellard
    int eflags;
750 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
751 367e86e8 bellard
    T0 = (eflags >> 7) & 1;
752 367e86e8 bellard
}
753 367e86e8 bellard
754 367e86e8 bellard
void OPPROTO op_setp_T0_cc(void)
755 367e86e8 bellard
{
756 367e86e8 bellard
    int eflags;
757 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
758 367e86e8 bellard
    T0 = (eflags >> 2) & 1;
759 367e86e8 bellard
}
760 367e86e8 bellard
761 367e86e8 bellard
void OPPROTO op_setl_T0_cc(void)
762 367e86e8 bellard
{
763 367e86e8 bellard
    int eflags;
764 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
765 367e86e8 bellard
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
766 367e86e8 bellard
}
767 367e86e8 bellard
768 367e86e8 bellard
void OPPROTO op_setle_T0_cc(void)
769 367e86e8 bellard
{
770 367e86e8 bellard
    int eflags;
771 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
772 367e86e8 bellard
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
773 367e86e8 bellard
}
774 367e86e8 bellard
775 367e86e8 bellard
void OPPROTO op_xor_T0_1(void)
776 367e86e8 bellard
{
777 367e86e8 bellard
    T0 ^= 1;
778 367e86e8 bellard
}
779 367e86e8 bellard
780 367e86e8 bellard
void OPPROTO op_set_cc_op(void)
781 367e86e8 bellard
{
782 367e86e8 bellard
    CC_OP = PARAM1;
783 367e86e8 bellard
}
784 367e86e8 bellard
785 367e86e8 bellard
void OPPROTO op_movl_eflags_T0(void)
786 367e86e8 bellard
{
787 367e86e8 bellard
    CC_SRC = T0;
788 367e86e8 bellard
    DF = 1 - (2 * ((T0 >> 10) & 1));
789 367e86e8 bellard
}
790 367e86e8 bellard
791 367e86e8 bellard
/* XXX: compute only O flag */
792 367e86e8 bellard
void OPPROTO op_movb_eflags_T0(void)
793 367e86e8 bellard
{
794 367e86e8 bellard
    int of;
795 367e86e8 bellard
    of = cc_table[CC_OP].compute_all() & CC_O;
796 367e86e8 bellard
    CC_SRC = T0 | of;
797 367e86e8 bellard
}
798 367e86e8 bellard
799 367e86e8 bellard
void OPPROTO op_movl_T0_eflags(void)
800 367e86e8 bellard
{
801 367e86e8 bellard
    T0 = cc_table[CC_OP].compute_all();
802 367e86e8 bellard
    T0 |= (DF & DIRECTION_FLAG);
803 367e86e8 bellard
}
804 367e86e8 bellard
805 367e86e8 bellard
void OPPROTO op_cld(void)
806 367e86e8 bellard
{
807 367e86e8 bellard
    DF = 1;
808 367e86e8 bellard
}
809 367e86e8 bellard
810 367e86e8 bellard
void OPPROTO op_std(void)
811 367e86e8 bellard
{
812 367e86e8 bellard
    DF = -1;
813 367e86e8 bellard
}
814 367e86e8 bellard
815 367e86e8 bellard
void OPPROTO op_clc(void)
816 367e86e8 bellard
{
817 367e86e8 bellard
    int eflags;
818 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
819 367e86e8 bellard
    eflags &= ~CC_C;
820 367e86e8 bellard
    CC_SRC = eflags;
821 367e86e8 bellard
}
822 367e86e8 bellard
823 367e86e8 bellard
void OPPROTO op_stc(void)
824 367e86e8 bellard
{
825 367e86e8 bellard
    int eflags;
826 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
827 367e86e8 bellard
    eflags |= CC_C;
828 367e86e8 bellard
    CC_SRC = eflags;
829 367e86e8 bellard
}
830 367e86e8 bellard
831 367e86e8 bellard
void OPPROTO op_cmc(void)
832 367e86e8 bellard
{
833 367e86e8 bellard
    int eflags;
834 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
835 367e86e8 bellard
    eflags ^= CC_C;
836 367e86e8 bellard
    CC_SRC = eflags;
837 367e86e8 bellard
}
838 367e86e8 bellard
839 367e86e8 bellard
static int compute_all_eflags(void)
840 367e86e8 bellard
{
841 367e86e8 bellard
    return CC_SRC;
842 367e86e8 bellard
}
843 367e86e8 bellard
844 367e86e8 bellard
static int compute_c_eflags(void)
845 367e86e8 bellard
{
846 367e86e8 bellard
    return CC_SRC & CC_C;
847 367e86e8 bellard
}
848 367e86e8 bellard
849 367e86e8 bellard
static int compute_c_mul(void)
850 367e86e8 bellard
{
851 367e86e8 bellard
    int cf;
852 367e86e8 bellard
    cf = (CC_SRC != 0);
853 367e86e8 bellard
    return cf;
854 367e86e8 bellard
}
855 367e86e8 bellard
856 367e86e8 bellard
static int compute_all_mul(void)
857 367e86e8 bellard
{
858 367e86e8 bellard
    int cf, pf, af, zf, sf, of;
859 367e86e8 bellard
    cf = (CC_SRC != 0);
860 367e86e8 bellard
    pf = 0; /* undefined */
861 367e86e8 bellard
    af = 0; /* undefined */
862 367e86e8 bellard
    zf = 0; /* undefined */
863 367e86e8 bellard
    sf = 0; /* undefined */
864 367e86e8 bellard
    of = cf << 11;
865 367e86e8 bellard
    return cf | pf | af | zf | sf | of;
866 367e86e8 bellard
}
867 367e86e8 bellard
    
868 367e86e8 bellard
CCTable cc_table[CC_OP_NB] = {
869 367e86e8 bellard
    [CC_OP_DYNAMIC] = { /* should never happen */ },
870 367e86e8 bellard
871 367e86e8 bellard
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
872 367e86e8 bellard
873 367e86e8 bellard
    [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
874 367e86e8 bellard
875 367e86e8 bellard
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
876 367e86e8 bellard
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
877 367e86e8 bellard
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
878 367e86e8 bellard
879 4b74fe1f bellard
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
880 4b74fe1f bellard
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
881 4b74fe1f bellard
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
882 4b74fe1f bellard
883 367e86e8 bellard
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
884 367e86e8 bellard
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
885 367e86e8 bellard
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
886 367e86e8 bellard
    
887 4b74fe1f bellard
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
888 4b74fe1f bellard
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
889 4b74fe1f bellard
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
890 4b74fe1f bellard
    
891 367e86e8 bellard
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
892 367e86e8 bellard
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
893 367e86e8 bellard
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
894 367e86e8 bellard
    
895 4b74fe1f bellard
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
896 4b74fe1f bellard
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
897 367e86e8 bellard
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
898 367e86e8 bellard
    
899 4b74fe1f bellard
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
900 4b74fe1f bellard
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
901 367e86e8 bellard
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
902 367e86e8 bellard
    
903 4b74fe1f bellard
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
904 4b74fe1f bellard
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
905 367e86e8 bellard
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
906 4b74fe1f bellard
907 4b74fe1f bellard
    [CC_OP_SARB] = { compute_all_sarb, compute_c_shll },
908 4b74fe1f bellard
    [CC_OP_SARW] = { compute_all_sarw, compute_c_shll },
909 4b74fe1f bellard
    [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
910 367e86e8 bellard
};
911 927f621e bellard
912 927f621e bellard
/* floating point support */
913 927f621e bellard
914 927f621e bellard
#ifdef USE_X86LDOUBLE
915 927f621e bellard
/* use long double functions */
916 927f621e bellard
#define lrint lrintl
917 927f621e bellard
#define llrint llrintl
918 927f621e bellard
#define fabs fabsl
919 927f621e bellard
#define sin sinl
920 927f621e bellard
#define cos cosl
921 927f621e bellard
#define sqrt sqrtl
922 927f621e bellard
#define pow powl
923 927f621e bellard
#define log logl
924 927f621e bellard
#define tan tanl
925 927f621e bellard
#define atan2 atan2l
926 927f621e bellard
#define floor floorl
927 927f621e bellard
#define ceil ceill
928 927f621e bellard
#define rint rintl
929 927f621e bellard
#endif
930 927f621e bellard
931 927f621e bellard
extern int lrint(CPU86_LDouble x);
932 927f621e bellard
extern int64_t llrint(CPU86_LDouble x);
933 927f621e bellard
extern CPU86_LDouble fabs(CPU86_LDouble x);
934 927f621e bellard
extern CPU86_LDouble sin(CPU86_LDouble x);
935 927f621e bellard
extern CPU86_LDouble cos(CPU86_LDouble x);
936 927f621e bellard
extern CPU86_LDouble sqrt(CPU86_LDouble x);
937 927f621e bellard
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
938 927f621e bellard
extern CPU86_LDouble log(CPU86_LDouble x);
939 927f621e bellard
extern CPU86_LDouble tan(CPU86_LDouble x);
940 927f621e bellard
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
941 927f621e bellard
extern CPU86_LDouble floor(CPU86_LDouble x);
942 927f621e bellard
extern CPU86_LDouble ceil(CPU86_LDouble x);
943 927f621e bellard
extern CPU86_LDouble rint(CPU86_LDouble x);
944 927f621e bellard
945 927f621e bellard
#define RC_MASK         0xc00
946 927f621e bellard
#define RC_NEAR                0x000
947 927f621e bellard
#define RC_DOWN                0x400
948 927f621e bellard
#define RC_UP                0x800
949 927f621e bellard
#define RC_CHOP                0xc00
950 927f621e bellard
951 927f621e bellard
#define MAXTAN 9223372036854775808.0
952 927f621e bellard
953 927f621e bellard
#ifdef USE_X86LDOUBLE
954 927f621e bellard
955 927f621e bellard
/* only for x86 */
956 927f621e bellard
typedef union {
957 927f621e bellard
    long double d;
958 927f621e bellard
    struct {
959 927f621e bellard
        unsigned long long lower;
960 927f621e bellard
        unsigned short upper;
961 927f621e bellard
    } l;
962 927f621e bellard
} CPU86_LDoubleU;
963 927f621e bellard
964 927f621e bellard
/* the following deal with x86 long double-precision numbers */
965 927f621e bellard
#define MAXEXPD 0x7fff
966 927f621e bellard
#define EXPBIAS 16383
967 927f621e bellard
#define EXPD(fp)        (fp.l.upper & 0x7fff)
968 927f621e bellard
#define SIGND(fp)        ((fp.l.upper) & 0x8000)
969 927f621e bellard
#define MANTD(fp)       (fp.l.lower)
970 927f621e bellard
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
971 927f621e bellard
972 927f621e bellard
#else
973 927f621e bellard
974 77f8dd5a bellard
typedef union {
975 927f621e bellard
    double d;
976 927f621e bellard
#ifndef WORDS_BIGENDIAN
977 927f621e bellard
    struct {
978 927f621e bellard
        unsigned long lower;
979 927f621e bellard
        long upper;
980 927f621e bellard
    } l;
981 927f621e bellard
#else
982 927f621e bellard
    struct {
983 927f621e bellard
        long upper;
984 927f621e bellard
        unsigned long lower;
985 927f621e bellard
    } l;
986 927f621e bellard
#endif
987 927f621e bellard
    long long ll;
988 927f621e bellard
} CPU86_LDoubleU;
989 927f621e bellard
990 927f621e bellard
/* the following deal with IEEE double-precision numbers */
991 927f621e bellard
#define MAXEXPD 0x7ff
992 927f621e bellard
#define EXPBIAS 1023
993 927f621e bellard
#define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)
994 927f621e bellard
#define SIGND(fp)        ((fp.l.upper) & 0x80000000)
995 927f621e bellard
#define MANTD(fp)        (fp.ll & ((1LL << 52) - 1))
996 927f621e bellard
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
997 927f621e bellard
#endif
998 927f621e bellard
999 927f621e bellard
/* fp load FT0 */
1000 927f621e bellard
1001 927f621e bellard
void OPPROTO op_flds_FT0_A0(void)
1002 927f621e bellard
{
1003 927f621e bellard
    FT0 = ldfl((void *)A0);
1004 927f621e bellard
}
1005 927f621e bellard
1006 927f621e bellard
void OPPROTO op_fldl_FT0_A0(void)
1007 927f621e bellard
{
1008 927f621e bellard
    FT0 = ldfq((void *)A0);
1009 927f621e bellard
}
1010 927f621e bellard
1011 927f621e bellard
void OPPROTO op_fild_FT0_A0(void)
1012 927f621e bellard
{
1013 927f621e bellard
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1014 927f621e bellard
}
1015 927f621e bellard
1016 927f621e bellard
void OPPROTO op_fildl_FT0_A0(void)
1017 927f621e bellard
{
1018 927f621e bellard
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1019 927f621e bellard
}
1020 927f621e bellard
1021 927f621e bellard
void OPPROTO op_fildll_FT0_A0(void)
1022 927f621e bellard
{
1023 927f621e bellard
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1024 927f621e bellard
}
1025 927f621e bellard
1026 927f621e bellard
/* fp load ST0 */
1027 927f621e bellard
1028 927f621e bellard
void OPPROTO op_flds_ST0_A0(void)
1029 927f621e bellard
{
1030 927f621e bellard
    ST0 = ldfl((void *)A0);
1031 927f621e bellard
}
1032 927f621e bellard
1033 927f621e bellard
void OPPROTO op_fldl_ST0_A0(void)
1034 927f621e bellard
{
1035 927f621e bellard
    ST0 = ldfq((void *)A0);
1036 927f621e bellard
}
1037 927f621e bellard
1038 77f8dd5a bellard
#ifdef USE_X86LDOUBLE
1039 77f8dd5a bellard
void OPPROTO op_fldt_ST0_A0(void)
1040 77f8dd5a bellard
{
1041 77f8dd5a bellard
    ST0 = *(long double *)A0;
1042 77f8dd5a bellard
}
1043 77f8dd5a bellard
#else
1044 77f8dd5a bellard
void helper_fldt_ST0_A0(void)
1045 77f8dd5a bellard
{
1046 77f8dd5a bellard
    CPU86_LDoubleU temp;
1047 77f8dd5a bellard
    int upper, e;
1048 77f8dd5a bellard
    /* mantissa */
1049 77f8dd5a bellard
    upper = lduw((uint8_t *)A0 + 8);
1050 77f8dd5a bellard
    /* XXX: handle overflow ? */
1051 77f8dd5a bellard
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1052 77f8dd5a bellard
    e |= (upper >> 4) & 0x800; /* sign */
1053 77f8dd5a bellard
    temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
1054 77f8dd5a bellard
    ST0 = temp.d;
1055 77f8dd5a bellard
}
1056 77f8dd5a bellard
1057 77f8dd5a bellard
void OPPROTO op_fldt_ST0_A0(void)
1058 77f8dd5a bellard
{
1059 77f8dd5a bellard
    helper_fldt_ST0_A0();
1060 77f8dd5a bellard
}
1061 77f8dd5a bellard
#endif
1062 77f8dd5a bellard
1063 927f621e bellard
void OPPROTO op_fild_ST0_A0(void)
1064 927f621e bellard
{
1065 927f621e bellard
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1066 927f621e bellard
}
1067 927f621e bellard
1068 927f621e bellard
void OPPROTO op_fildl_ST0_A0(void)
1069 927f621e bellard
{
1070 927f621e bellard
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1071 927f621e bellard
}
1072 927f621e bellard
1073 927f621e bellard
void OPPROTO op_fildll_ST0_A0(void)
1074 927f621e bellard
{
1075 927f621e bellard
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1076 927f621e bellard
}
1077 927f621e bellard
1078 927f621e bellard
/* fp store */
1079 927f621e bellard
1080 927f621e bellard
void OPPROTO op_fsts_ST0_A0(void)
1081 927f621e bellard
{
1082 927f621e bellard
    stfl((void *)A0, (float)ST0);
1083 927f621e bellard
}
1084 927f621e bellard
1085 927f621e bellard
void OPPROTO op_fstl_ST0_A0(void)
1086 927f621e bellard
{
1087 77f8dd5a bellard
    stfq((void *)A0, (double)ST0);
1088 927f621e bellard
}
1089 927f621e bellard
1090 77f8dd5a bellard
#ifdef USE_X86LDOUBLE
1091 77f8dd5a bellard
void OPPROTO op_fstt_ST0_A0(void)
1092 77f8dd5a bellard
{
1093 77f8dd5a bellard
    *(long double *)A0 = ST0;
1094 77f8dd5a bellard
}
1095 77f8dd5a bellard
#else
1096 77f8dd5a bellard
void helper_fstt_ST0_A0(void)
1097 77f8dd5a bellard
{
1098 77f8dd5a bellard
    CPU86_LDoubleU temp;
1099 77f8dd5a bellard
    int e;
1100 77f8dd5a bellard
    temp.d = ST0;
1101 77f8dd5a bellard
    /* mantissa */
1102 77f8dd5a bellard
    stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63));
1103 77f8dd5a bellard
    /* exponent + sign */
1104 77f8dd5a bellard
    e = EXPD(temp) - EXPBIAS + 16383;
1105 77f8dd5a bellard
    e |= SIGND(temp) >> 16;
1106 77f8dd5a bellard
    stw((uint8_t *)A0 + 8, e);
1107 77f8dd5a bellard
}
1108 77f8dd5a bellard
1109 77f8dd5a bellard
void OPPROTO op_fstt_ST0_A0(void)
1110 77f8dd5a bellard
{
1111 77f8dd5a bellard
    helper_fstt_ST0_A0();
1112 77f8dd5a bellard
}
1113 77f8dd5a bellard
#endif
1114 77f8dd5a bellard
1115 927f621e bellard
void OPPROTO op_fist_ST0_A0(void)
1116 927f621e bellard
{
1117 927f621e bellard
    int val;
1118 927f621e bellard
    val = lrint(ST0);
1119 927f621e bellard
    stw((void *)A0, val);
1120 927f621e bellard
}
1121 927f621e bellard
1122 927f621e bellard
void OPPROTO op_fistl_ST0_A0(void)
1123 927f621e bellard
{
1124 927f621e bellard
    int val;
1125 927f621e bellard
    val = lrint(ST0);
1126 927f621e bellard
    stl((void *)A0, val);
1127 927f621e bellard
}
1128 927f621e bellard
1129 927f621e bellard
void OPPROTO op_fistll_ST0_A0(void)
1130 927f621e bellard
{
1131 927f621e bellard
    int64_t val;
1132 927f621e bellard
    val = llrint(ST0);
1133 927f621e bellard
    stq((void *)A0, val);
1134 927f621e bellard
}
1135 927f621e bellard
1136 77f8dd5a bellard
/* BCD ops */
1137 77f8dd5a bellard
1138 77f8dd5a bellard
#define MUL10(iv) ( iv + iv + (iv << 3) )
1139 77f8dd5a bellard
1140 77f8dd5a bellard
void helper_fbld_ST0_A0(void)
1141 77f8dd5a bellard
{
1142 77f8dd5a bellard
    uint8_t *seg;
1143 77f8dd5a bellard
    CPU86_LDouble fpsrcop;
1144 77f8dd5a bellard
    int m32i;
1145 77f8dd5a bellard
    unsigned int v;
1146 77f8dd5a bellard
1147 77f8dd5a bellard
    /* in this code, seg/m32i will be used as temporary ptr/int */
1148 77f8dd5a bellard
    seg = (uint8_t *)A0 + 8;
1149 77f8dd5a bellard
    v = ldub(seg--);
1150 77f8dd5a bellard
    /* XXX: raise exception */
1151 77f8dd5a bellard
    if (v != 0)
1152 77f8dd5a bellard
        return;
1153 77f8dd5a bellard
    v = ldub(seg--);
1154 77f8dd5a bellard
    /* XXX: raise exception */
1155 77f8dd5a bellard
    if ((v & 0xf0) != 0)
1156 77f8dd5a bellard
        return;
1157 77f8dd5a bellard
    m32i = v;  /* <-- d14 */
1158 77f8dd5a bellard
    v = ldub(seg--);
1159 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
1160 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
1161 77f8dd5a bellard
    v = ldub(seg--);
1162 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
1163 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
1164 77f8dd5a bellard
    v = ldub(seg--);
1165 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
1166 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
1167 77f8dd5a bellard
    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
1168 77f8dd5a bellard
1169 77f8dd5a bellard
    v = ldub(seg--);
1170 77f8dd5a bellard
    m32i = (v >> 4);  /* <-- d7 */
1171 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
1172 77f8dd5a bellard
    v = ldub(seg--);
1173 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
1174 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
1175 77f8dd5a bellard
    v = ldub(seg--);
1176 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
1177 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
1178 77f8dd5a bellard
    v = ldub(seg);
1179 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
1180 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
1181 77f8dd5a bellard
    fpsrcop += ((CPU86_LDouble)m32i);
1182 77f8dd5a bellard
    if ( ldub(seg+9) & 0x80 )
1183 77f8dd5a bellard
        fpsrcop = -fpsrcop;
1184 77f8dd5a bellard
    ST0 = fpsrcop;
1185 77f8dd5a bellard
}
1186 77f8dd5a bellard
1187 77f8dd5a bellard
void OPPROTO op_fbld_ST0_A0(void)
1188 77f8dd5a bellard
{
1189 77f8dd5a bellard
    helper_fbld_ST0_A0();
1190 77f8dd5a bellard
}
1191 77f8dd5a bellard
1192 77f8dd5a bellard
void helper_fbst_ST0_A0(void)
1193 77f8dd5a bellard
{
1194 77f8dd5a bellard
    CPU86_LDouble fptemp;
1195 77f8dd5a bellard
    CPU86_LDouble fpsrcop;
1196 77f8dd5a bellard
    int v;
1197 77f8dd5a bellard
    uint8_t *mem_ref, *mem_end;
1198 77f8dd5a bellard
1199 77f8dd5a bellard
    fpsrcop = rint(ST0);
1200 77f8dd5a bellard
    mem_ref = (uint8_t *)A0;
1201 77f8dd5a bellard
    mem_end = mem_ref + 8;
1202 77f8dd5a bellard
    if ( fpsrcop < 0.0 ) {
1203 77f8dd5a bellard
        stw(mem_end, 0x8000);
1204 77f8dd5a bellard
        fpsrcop = -fpsrcop;
1205 77f8dd5a bellard
    } else {
1206 77f8dd5a bellard
        stw(mem_end, 0x0000);
1207 77f8dd5a bellard
    }
1208 77f8dd5a bellard
    while (mem_ref < mem_end) {
1209 77f8dd5a bellard
        if (fpsrcop == 0.0)
1210 77f8dd5a bellard
            break;
1211 77f8dd5a bellard
        fptemp = floor(fpsrcop/10.0);
1212 77f8dd5a bellard
        v = ((int)(fpsrcop - fptemp*10.0));
1213 77f8dd5a bellard
        if  (fptemp == 0.0)  { 
1214 77f8dd5a bellard
            stb(mem_ref++, v); 
1215 77f8dd5a bellard
            break; 
1216 77f8dd5a bellard
        }
1217 77f8dd5a bellard
        fpsrcop = fptemp;
1218 77f8dd5a bellard
        fptemp = floor(fpsrcop/10.0);
1219 77f8dd5a bellard
        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
1220 77f8dd5a bellard
        stb(mem_ref++, v);
1221 77f8dd5a bellard
        fpsrcop = fptemp;
1222 77f8dd5a bellard
    }
1223 77f8dd5a bellard
    while (mem_ref < mem_end) {
1224 77f8dd5a bellard
        stb(mem_ref++, 0);
1225 77f8dd5a bellard
    }
1226 77f8dd5a bellard
}
1227 77f8dd5a bellard
1228 77f8dd5a bellard
void OPPROTO op_fbst_ST0_A0(void)
1229 77f8dd5a bellard
{
1230 77f8dd5a bellard
    helper_fbst_ST0_A0();
1231 77f8dd5a bellard
}
1232 77f8dd5a bellard
1233 927f621e bellard
/* FPU move */
1234 927f621e bellard
1235 927f621e bellard
static inline void fpush(void)
1236 927f621e bellard
{
1237 927f621e bellard
    env->fpstt = (env->fpstt - 1) & 7;
1238 927f621e bellard
    env->fptags[env->fpstt] = 0; /* validate stack entry */
1239 927f621e bellard
}
1240 927f621e bellard
1241 927f621e bellard
static inline void fpop(void)
1242 927f621e bellard
{
1243 927f621e bellard
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
1244 927f621e bellard
    env->fpstt = (env->fpstt + 1) & 7;
1245 927f621e bellard
}
1246 927f621e bellard
1247 927f621e bellard
void OPPROTO op_fpush(void)
1248 927f621e bellard
{
1249 927f621e bellard
    fpush();
1250 927f621e bellard
}
1251 927f621e bellard
1252 927f621e bellard
void OPPROTO op_fpop(void)
1253 927f621e bellard
{
1254 927f621e bellard
    fpop();
1255 927f621e bellard
}
1256 927f621e bellard
1257 927f621e bellard
void OPPROTO op_fdecstp(void)
1258 927f621e bellard
{
1259 927f621e bellard
    env->fpstt = (env->fpstt - 1) & 7;
1260 927f621e bellard
    env->fpus &= (~0x4700);
1261 927f621e bellard
}
1262 927f621e bellard
1263 927f621e bellard
void OPPROTO op_fincstp(void)
1264 927f621e bellard
{
1265 927f621e bellard
    env->fpstt = (env->fpstt + 1) & 7;
1266 927f621e bellard
    env->fpus &= (~0x4700);
1267 927f621e bellard
}
1268 927f621e bellard
1269 927f621e bellard
void OPPROTO op_fmov_ST0_FT0(void)
1270 927f621e bellard
{
1271 927f621e bellard
    ST0 = FT0;
1272 927f621e bellard
}
1273 927f621e bellard
1274 927f621e bellard
void OPPROTO op_fmov_FT0_STN(void)
1275 927f621e bellard
{
1276 927f621e bellard
    FT0 = ST(PARAM1);
1277 927f621e bellard
}
1278 927f621e bellard
1279 927f621e bellard
void OPPROTO op_fmov_ST0_STN(void)
1280 927f621e bellard
{
1281 927f621e bellard
    ST0 = ST(PARAM1);
1282 927f621e bellard
}
1283 927f621e bellard
1284 927f621e bellard
void OPPROTO op_fmov_STN_ST0(void)
1285 927f621e bellard
{
1286 927f621e bellard
    ST(PARAM1) = ST0;
1287 927f621e bellard
}
1288 927f621e bellard
1289 927f621e bellard
void OPPROTO op_fxchg_ST0_STN(void)
1290 927f621e bellard
{
1291 927f621e bellard
    CPU86_LDouble tmp;
1292 927f621e bellard
    tmp = ST(PARAM1);
1293 927f621e bellard
    ST(PARAM1) = ST0;
1294 927f621e bellard
    ST0 = tmp;
1295 927f621e bellard
}
1296 927f621e bellard
1297 927f621e bellard
/* FPU operations */
1298 927f621e bellard
1299 927f621e bellard
/* XXX: handle nans */
1300 927f621e bellard
void OPPROTO op_fcom_ST0_FT0(void)
1301 927f621e bellard
{
1302 927f621e bellard
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1303 927f621e bellard
    if (ST0 < FT0)
1304 927f621e bellard
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1305 927f621e bellard
    else if (ST0 == FT0)
1306 927f621e bellard
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1307 927f621e bellard
    FORCE_RET();
1308 927f621e bellard
}
1309 927f621e bellard
1310 77f8dd5a bellard
/* XXX: handle nans */
1311 77f8dd5a bellard
void OPPROTO op_fucom_ST0_FT0(void)
1312 77f8dd5a bellard
{
1313 77f8dd5a bellard
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
1314 77f8dd5a bellard
    if (ST0 < FT0)
1315 77f8dd5a bellard
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
1316 77f8dd5a bellard
    else if (ST0 == FT0)
1317 77f8dd5a bellard
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1318 77f8dd5a bellard
    FORCE_RET();
1319 77f8dd5a bellard
}
1320 77f8dd5a bellard
1321 927f621e bellard
void OPPROTO op_fadd_ST0_FT0(void)
1322 927f621e bellard
{
1323 927f621e bellard
    ST0 += FT0;
1324 927f621e bellard
}
1325 927f621e bellard
1326 927f621e bellard
void OPPROTO op_fmul_ST0_FT0(void)
1327 927f621e bellard
{
1328 927f621e bellard
    ST0 *= FT0;
1329 927f621e bellard
}
1330 927f621e bellard
1331 927f621e bellard
void OPPROTO op_fsub_ST0_FT0(void)
1332 927f621e bellard
{
1333 927f621e bellard
    ST0 -= FT0;
1334 927f621e bellard
}
1335 927f621e bellard
1336 927f621e bellard
void OPPROTO op_fsubr_ST0_FT0(void)
1337 927f621e bellard
{
1338 927f621e bellard
    ST0 = FT0 - ST0;
1339 927f621e bellard
}
1340 927f621e bellard
1341 927f621e bellard
void OPPROTO op_fdiv_ST0_FT0(void)
1342 927f621e bellard
{
1343 927f621e bellard
    ST0 /= FT0;
1344 927f621e bellard
}
1345 927f621e bellard
1346 927f621e bellard
void OPPROTO op_fdivr_ST0_FT0(void)
1347 927f621e bellard
{
1348 927f621e bellard
    ST0 = FT0 / ST0;
1349 927f621e bellard
}
1350 927f621e bellard
1351 927f621e bellard
/* fp operations between STN and ST0 */
1352 927f621e bellard
1353 927f621e bellard
void OPPROTO op_fadd_STN_ST0(void)
1354 927f621e bellard
{
1355 927f621e bellard
    ST(PARAM1) += ST0;
1356 927f621e bellard
}
1357 927f621e bellard
1358 927f621e bellard
void OPPROTO op_fmul_STN_ST0(void)
1359 927f621e bellard
{
1360 927f621e bellard
    ST(PARAM1) *= ST0;
1361 927f621e bellard
}
1362 927f621e bellard
1363 927f621e bellard
void OPPROTO op_fsub_STN_ST0(void)
1364 927f621e bellard
{
1365 927f621e bellard
    ST(PARAM1) -= ST0;
1366 927f621e bellard
}
1367 927f621e bellard
1368 927f621e bellard
void OPPROTO op_fsubr_STN_ST0(void)
1369 927f621e bellard
{
1370 927f621e bellard
    CPU86_LDouble *p;
1371 927f621e bellard
    p = &ST(PARAM1);
1372 927f621e bellard
    *p = ST0 - *p;
1373 927f621e bellard
}
1374 927f621e bellard
1375 927f621e bellard
void OPPROTO op_fdiv_STN_ST0(void)
1376 927f621e bellard
{
1377 927f621e bellard
    ST(PARAM1) /= ST0;
1378 927f621e bellard
}
1379 927f621e bellard
1380 927f621e bellard
void OPPROTO op_fdivr_STN_ST0(void)
1381 927f621e bellard
{
1382 927f621e bellard
    CPU86_LDouble *p;
1383 927f621e bellard
    p = &ST(PARAM1);
1384 927f621e bellard
    *p = ST0 / *p;
1385 927f621e bellard
}
1386 927f621e bellard
1387 927f621e bellard
/* misc FPU operations */
1388 927f621e bellard
void OPPROTO op_fchs_ST0(void)
1389 927f621e bellard
{
1390 927f621e bellard
    ST0 = -ST0;
1391 927f621e bellard
}
1392 927f621e bellard
1393 927f621e bellard
void OPPROTO op_fabs_ST0(void)
1394 927f621e bellard
{
1395 927f621e bellard
    ST0 = fabs(ST0);
1396 927f621e bellard
}
1397 927f621e bellard
1398 77f8dd5a bellard
void helper_fxam_ST0(void)
1399 927f621e bellard
{
1400 927f621e bellard
    CPU86_LDoubleU temp;
1401 927f621e bellard
    int expdif;
1402 927f621e bellard
1403 927f621e bellard
    temp.d = ST0;
1404 927f621e bellard
1405 927f621e bellard
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1406 927f621e bellard
    if (SIGND(temp))
1407 927f621e bellard
        env->fpus |= 0x200; /* C1 <-- 1 */
1408 927f621e bellard
1409 927f621e bellard
    expdif = EXPD(temp);
1410 927f621e bellard
    if (expdif == MAXEXPD) {
1411 927f621e bellard
        if (MANTD(temp) == 0)
1412 927f621e bellard
            env->fpus |=  0x500 /*Infinity*/;
1413 927f621e bellard
        else
1414 927f621e bellard
            env->fpus |=  0x100 /*NaN*/;
1415 927f621e bellard
    } else if (expdif == 0) {
1416 927f621e bellard
        if (MANTD(temp) == 0)
1417 927f621e bellard
            env->fpus |=  0x4000 /*Zero*/;
1418 927f621e bellard
        else
1419 927f621e bellard
            env->fpus |= 0x4400 /*Denormal*/;
1420 927f621e bellard
    } else {
1421 927f621e bellard
        env->fpus |= 0x400;
1422 927f621e bellard
    }
1423 77f8dd5a bellard
}
1424 77f8dd5a bellard
1425 77f8dd5a bellard
void OPPROTO op_fxam_ST0(void)
1426 77f8dd5a bellard
{
1427 77f8dd5a bellard
    helper_fxam_ST0();
1428 927f621e bellard
}
1429 927f621e bellard
1430 927f621e bellard
void OPPROTO op_fld1_ST0(void)
1431 927f621e bellard
{
1432 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[1];
1433 927f621e bellard
}
1434 927f621e bellard
1435 77f8dd5a bellard
void OPPROTO op_fldl2t_ST0(void)
1436 927f621e bellard
{
1437 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[6];
1438 927f621e bellard
}
1439 927f621e bellard
1440 77f8dd5a bellard
void OPPROTO op_fldl2e_ST0(void)
1441 927f621e bellard
{
1442 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[5];
1443 927f621e bellard
}
1444 927f621e bellard
1445 927f621e bellard
void OPPROTO op_fldpi_ST0(void)
1446 927f621e bellard
{
1447 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[2];
1448 927f621e bellard
}
1449 927f621e bellard
1450 927f621e bellard
void OPPROTO op_fldlg2_ST0(void)
1451 927f621e bellard
{
1452 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[3];
1453 927f621e bellard
}
1454 927f621e bellard
1455 927f621e bellard
void OPPROTO op_fldln2_ST0(void)
1456 927f621e bellard
{
1457 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[4];
1458 927f621e bellard
}
1459 927f621e bellard
1460 927f621e bellard
void OPPROTO op_fldz_ST0(void)
1461 927f621e bellard
{
1462 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1463 927f621e bellard
}
1464 927f621e bellard
1465 927f621e bellard
void OPPROTO op_fldz_FT0(void)
1466 927f621e bellard
{
1467 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[0];
1468 927f621e bellard
}
1469 927f621e bellard
1470 927f621e bellard
void helper_f2xm1(void)
1471 927f621e bellard
{
1472 927f621e bellard
    ST0 = pow(2.0,ST0) - 1.0;
1473 927f621e bellard
}
1474 927f621e bellard
1475 927f621e bellard
void helper_fyl2x(void)
1476 927f621e bellard
{
1477 927f621e bellard
    CPU86_LDouble fptemp;
1478 927f621e bellard
    
1479 927f621e bellard
    fptemp = ST0;
1480 927f621e bellard
    if (fptemp>0.0){
1481 927f621e bellard
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
1482 927f621e bellard
        ST1 *= fptemp;
1483 927f621e bellard
        fpop();
1484 927f621e bellard
    } else { 
1485 927f621e bellard
        env->fpus &= (~0x4700);
1486 927f621e bellard
        env->fpus |= 0x400;
1487 927f621e bellard
    }
1488 927f621e bellard
}
1489 927f621e bellard
1490 927f621e bellard
void helper_fptan(void)
1491 927f621e bellard
{
1492 927f621e bellard
    CPU86_LDouble fptemp;
1493 927f621e bellard
1494 927f621e bellard
    fptemp = ST0;
1495 927f621e bellard
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1496 927f621e bellard
        env->fpus |= 0x400;
1497 927f621e bellard
    } else {
1498 927f621e bellard
        ST0 = tan(fptemp);
1499 927f621e bellard
        fpush();
1500 927f621e bellard
        ST0 = 1.0;
1501 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1502 927f621e bellard
        /* the above code is for  |arg| < 2**52 only */
1503 927f621e bellard
    }
1504 927f621e bellard
}
1505 927f621e bellard
1506 927f621e bellard
void helper_fpatan(void)
1507 927f621e bellard
{
1508 927f621e bellard
    CPU86_LDouble fptemp, fpsrcop;
1509 927f621e bellard
1510 927f621e bellard
    fpsrcop = ST1;
1511 927f621e bellard
    fptemp = ST0;
1512 927f621e bellard
    ST1 = atan2(fpsrcop,fptemp);
1513 927f621e bellard
    fpop();
1514 927f621e bellard
}
1515 927f621e bellard
1516 927f621e bellard
void helper_fxtract(void)
1517 927f621e bellard
{
1518 927f621e bellard
    CPU86_LDoubleU temp;
1519 927f621e bellard
    unsigned int expdif;
1520 927f621e bellard
1521 927f621e bellard
    temp.d = ST0;
1522 927f621e bellard
    expdif = EXPD(temp) - EXPBIAS;
1523 927f621e bellard
    /*DP exponent bias*/
1524 927f621e bellard
    ST0 = expdif;
1525 927f621e bellard
    fpush();
1526 927f621e bellard
    BIASEXPONENT(temp);
1527 927f621e bellard
    ST0 = temp.d;
1528 927f621e bellard
}
1529 927f621e bellard
1530 927f621e bellard
void helper_fprem1(void)
1531 927f621e bellard
{
1532 927f621e bellard
    CPU86_LDouble dblq, fpsrcop, fptemp;
1533 927f621e bellard
    CPU86_LDoubleU fpsrcop1, fptemp1;
1534 927f621e bellard
    int expdif;
1535 927f621e bellard
    int q;
1536 927f621e bellard
1537 927f621e bellard
    fpsrcop = ST0;
1538 927f621e bellard
    fptemp = ST1;
1539 927f621e bellard
    fpsrcop1.d = fpsrcop;
1540 927f621e bellard
    fptemp1.d = fptemp;
1541 927f621e bellard
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1542 927f621e bellard
    if (expdif < 53) {
1543 927f621e bellard
        dblq = fpsrcop / fptemp;
1544 927f621e bellard
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1545 927f621e bellard
        ST0 = fpsrcop - fptemp*dblq;
1546 927f621e bellard
        q = (int)dblq; /* cutting off top bits is assumed here */
1547 927f621e bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1548 927f621e bellard
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1549 927f621e bellard
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1550 927f621e bellard
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1551 927f621e bellard
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1552 927f621e bellard
    } else {
1553 927f621e bellard
        env->fpus |= 0x400;  /* C2 <-- 1 */
1554 927f621e bellard
        fptemp = pow(2.0, expdif-50);
1555 927f621e bellard
        fpsrcop = (ST0 / ST1) / fptemp;
1556 927f621e bellard
        /* fpsrcop = integer obtained by rounding to the nearest */
1557 927f621e bellard
        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
1558 927f621e bellard
            floor(fpsrcop): ceil(fpsrcop);
1559 927f621e bellard
        ST0 -= (ST1 * fpsrcop * fptemp);
1560 927f621e bellard
    }
1561 927f621e bellard
}
1562 927f621e bellard
1563 927f621e bellard
void helper_fprem(void)
1564 927f621e bellard
{
1565 927f621e bellard
    CPU86_LDouble dblq, fpsrcop, fptemp;
1566 927f621e bellard
    CPU86_LDoubleU fpsrcop1, fptemp1;
1567 927f621e bellard
    int expdif;
1568 927f621e bellard
    int q;
1569 927f621e bellard
    
1570 927f621e bellard
    fpsrcop = ST0;
1571 927f621e bellard
    fptemp = ST1;
1572 927f621e bellard
    fpsrcop1.d = fpsrcop;
1573 927f621e bellard
    fptemp1.d = fptemp;
1574 927f621e bellard
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1575 927f621e bellard
    if ( expdif < 53 ) {
1576 927f621e bellard
        dblq = fpsrcop / fptemp;
1577 927f621e bellard
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
1578 927f621e bellard
        ST0 = fpsrcop - fptemp*dblq;
1579 927f621e bellard
        q = (int)dblq; /* cutting off top bits is assumed here */
1580 927f621e bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1581 927f621e bellard
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
1582 927f621e bellard
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
1583 927f621e bellard
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
1584 927f621e bellard
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
1585 927f621e bellard
    } else {
1586 927f621e bellard
        env->fpus |= 0x400;  /* C2 <-- 1 */
1587 927f621e bellard
        fptemp = pow(2.0, expdif-50);
1588 927f621e bellard
        fpsrcop = (ST0 / ST1) / fptemp;
1589 927f621e bellard
        /* fpsrcop = integer obtained by chopping */
1590 927f621e bellard
        fpsrcop = (fpsrcop < 0.0)?
1591 927f621e bellard
            -(floor(fabs(fpsrcop))): floor(fpsrcop);
1592 927f621e bellard
        ST0 -= (ST1 * fpsrcop * fptemp);
1593 927f621e bellard
    }
1594 927f621e bellard
}
1595 927f621e bellard
1596 927f621e bellard
void helper_fyl2xp1(void)
1597 927f621e bellard
{
1598 927f621e bellard
    CPU86_LDouble fptemp;
1599 927f621e bellard
1600 927f621e bellard
    fptemp = ST0;
1601 927f621e bellard
    if ((fptemp+1.0)>0.0) {
1602 927f621e bellard
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
1603 927f621e bellard
        ST1 *= fptemp;
1604 927f621e bellard
        fpop();
1605 927f621e bellard
    } else { 
1606 927f621e bellard
        env->fpus &= (~0x4700);
1607 927f621e bellard
        env->fpus |= 0x400;
1608 927f621e bellard
    }
1609 927f621e bellard
}
1610 927f621e bellard
1611 927f621e bellard
void helper_fsqrt(void)
1612 927f621e bellard
{
1613 927f621e bellard
    CPU86_LDouble fptemp;
1614 927f621e bellard
1615 927f621e bellard
    fptemp = ST0;
1616 927f621e bellard
    if (fptemp<0.0) { 
1617 927f621e bellard
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
1618 927f621e bellard
        env->fpus |= 0x400;
1619 927f621e bellard
    }
1620 927f621e bellard
    ST0 = sqrt(fptemp);
1621 927f621e bellard
}
1622 927f621e bellard
1623 927f621e bellard
void helper_fsincos(void)
1624 927f621e bellard
{
1625 927f621e bellard
    CPU86_LDouble fptemp;
1626 927f621e bellard
1627 927f621e bellard
    fptemp = ST0;
1628 927f621e bellard
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1629 927f621e bellard
        env->fpus |= 0x400;
1630 927f621e bellard
    } else {
1631 927f621e bellard
        ST0 = sin(fptemp);
1632 927f621e bellard
        fpush();
1633 927f621e bellard
        ST0 = cos(fptemp);
1634 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1635 927f621e bellard
        /* the above code is for  |arg| < 2**63 only */
1636 927f621e bellard
    }
1637 927f621e bellard
}
1638 927f621e bellard
1639 927f621e bellard
void helper_frndint(void)
1640 927f621e bellard
{
1641 927f621e bellard
    ST0 = rint(ST0);
1642 927f621e bellard
}
1643 927f621e bellard
1644 927f621e bellard
void helper_fscale(void)
1645 927f621e bellard
{
1646 927f621e bellard
    CPU86_LDouble fpsrcop, fptemp;
1647 927f621e bellard
1648 927f621e bellard
    fpsrcop = 2.0;
1649 927f621e bellard
    fptemp = pow(fpsrcop,ST1);
1650 927f621e bellard
    ST0 *= fptemp;
1651 927f621e bellard
}
1652 927f621e bellard
1653 927f621e bellard
void helper_fsin(void)
1654 927f621e bellard
{
1655 927f621e bellard
    CPU86_LDouble fptemp;
1656 927f621e bellard
1657 927f621e bellard
    fptemp = ST0;
1658 927f621e bellard
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1659 927f621e bellard
        env->fpus |= 0x400;
1660 927f621e bellard
    } else {
1661 927f621e bellard
        ST0 = sin(fptemp);
1662 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1663 927f621e bellard
        /* the above code is for  |arg| < 2**53 only */
1664 927f621e bellard
    }
1665 927f621e bellard
}
1666 927f621e bellard
1667 927f621e bellard
void helper_fcos(void)
1668 927f621e bellard
{
1669 927f621e bellard
    CPU86_LDouble fptemp;
1670 927f621e bellard
1671 927f621e bellard
    fptemp = ST0;
1672 927f621e bellard
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
1673 927f621e bellard
        env->fpus |= 0x400;
1674 927f621e bellard
    } else {
1675 927f621e bellard
        ST0 = cos(fptemp);
1676 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
1677 927f621e bellard
        /* the above code is for  |arg5 < 2**63 only */
1678 927f621e bellard
    }
1679 927f621e bellard
}
1680 927f621e bellard
1681 927f621e bellard
/* associated heplers to reduce generated code length and to simplify
1682 927f621e bellard
   relocation (FP constants are usually stored in .rodata section) */
1683 927f621e bellard
1684 927f621e bellard
void OPPROTO op_f2xm1(void)
1685 927f621e bellard
{
1686 927f621e bellard
    helper_f2xm1();
1687 927f621e bellard
}
1688 927f621e bellard
1689 927f621e bellard
void OPPROTO op_fyl2x(void)
1690 927f621e bellard
{
1691 927f621e bellard
    helper_fyl2x();
1692 927f621e bellard
}
1693 927f621e bellard
1694 927f621e bellard
void OPPROTO op_fptan(void)
1695 927f621e bellard
{
1696 927f621e bellard
    helper_fptan();
1697 927f621e bellard
}
1698 927f621e bellard
1699 927f621e bellard
void OPPROTO op_fpatan(void)
1700 927f621e bellard
{
1701 927f621e bellard
    helper_fpatan();
1702 927f621e bellard
}
1703 927f621e bellard
1704 927f621e bellard
void OPPROTO op_fxtract(void)
1705 927f621e bellard
{
1706 927f621e bellard
    helper_fxtract();
1707 927f621e bellard
}
1708 927f621e bellard
1709 927f621e bellard
void OPPROTO op_fprem1(void)
1710 927f621e bellard
{
1711 927f621e bellard
    helper_fprem1();
1712 927f621e bellard
}
1713 927f621e bellard
1714 927f621e bellard
1715 927f621e bellard
void OPPROTO op_fprem(void)
1716 927f621e bellard
{
1717 927f621e bellard
    helper_fprem();
1718 927f621e bellard
}
1719 927f621e bellard
1720 927f621e bellard
void OPPROTO op_fyl2xp1(void)
1721 927f621e bellard
{
1722 927f621e bellard
    helper_fyl2xp1();
1723 927f621e bellard
}
1724 927f621e bellard
1725 927f621e bellard
void OPPROTO op_fsqrt(void)
1726 927f621e bellard
{
1727 927f621e bellard
    helper_fsqrt();
1728 927f621e bellard
}
1729 927f621e bellard
1730 927f621e bellard
void OPPROTO op_fsincos(void)
1731 927f621e bellard
{
1732 927f621e bellard
    helper_fsincos();
1733 927f621e bellard
}
1734 927f621e bellard
1735 927f621e bellard
void OPPROTO op_frndint(void)
1736 927f621e bellard
{
1737 927f621e bellard
    helper_frndint();
1738 927f621e bellard
}
1739 927f621e bellard
1740 927f621e bellard
void OPPROTO op_fscale(void)
1741 927f621e bellard
{
1742 927f621e bellard
    helper_fscale();
1743 927f621e bellard
}
1744 927f621e bellard
1745 927f621e bellard
void OPPROTO op_fsin(void)
1746 927f621e bellard
{
1747 927f621e bellard
    helper_fsin();
1748 927f621e bellard
}
1749 927f621e bellard
1750 927f621e bellard
void OPPROTO op_fcos(void)
1751 927f621e bellard
{
1752 927f621e bellard
    helper_fcos();
1753 927f621e bellard
}
1754 927f621e bellard
1755 4b74fe1f bellard
void OPPROTO op_fnstsw_A0(void)
1756 4b74fe1f bellard
{
1757 4b74fe1f bellard
    int fpus;
1758 4b74fe1f bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1759 4b74fe1f bellard
    stw((void *)A0, fpus);
1760 4b74fe1f bellard
}
1761 4b74fe1f bellard
1762 77f8dd5a bellard
void OPPROTO op_fnstsw_EAX(void)
1763 77f8dd5a bellard
{
1764 77f8dd5a bellard
    int fpus;
1765 77f8dd5a bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1766 77f8dd5a bellard
    EAX = (EAX & 0xffff0000) | fpus;
1767 77f8dd5a bellard
}
1768 77f8dd5a bellard
1769 4b74fe1f bellard
void OPPROTO op_fnstcw_A0(void)
1770 4b74fe1f bellard
{
1771 4b74fe1f bellard
    stw((void *)A0, env->fpuc);
1772 4b74fe1f bellard
}
1773 4b74fe1f bellard
1774 4b74fe1f bellard
void OPPROTO op_fldcw_A0(void)
1775 4b74fe1f bellard
{
1776 4b74fe1f bellard
    int rnd_type;
1777 4b74fe1f bellard
    env->fpuc = lduw((void *)A0);
1778 4b74fe1f bellard
    /* set rounding mode */
1779 4b74fe1f bellard
    switch(env->fpuc & RC_MASK) {
1780 4b74fe1f bellard
    default:
1781 4b74fe1f bellard
    case RC_NEAR:
1782 4b74fe1f bellard
        rnd_type = FE_TONEAREST;
1783 4b74fe1f bellard
        break;
1784 4b74fe1f bellard
    case RC_DOWN:
1785 4b74fe1f bellard
        rnd_type = FE_DOWNWARD;
1786 4b74fe1f bellard
        break;
1787 4b74fe1f bellard
    case RC_UP:
1788 4b74fe1f bellard
        rnd_type = FE_UPWARD;
1789 4b74fe1f bellard
        break;
1790 4b74fe1f bellard
    case RC_CHOP:
1791 4b74fe1f bellard
        rnd_type = FE_TOWARDZERO;
1792 4b74fe1f bellard
        break;
1793 4b74fe1f bellard
    }
1794 4b74fe1f bellard
    fesetround(rnd_type);
1795 4b74fe1f bellard
}