Statistics
| Branch: | Revision:

root / op-i386.c @ 504e56eb

History | View | Annotate | Download (50.1 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 3ef693a0 bellard
 * This library is free software; you can redistribute it and/or
7 3ef693a0 bellard
 * modify it under the terms of the GNU Lesser General Public
8 3ef693a0 bellard
 * License as published by the Free Software Foundation; either
9 3ef693a0 bellard
 * version 2 of the License, or (at your option) any later version.
10 7d13299d bellard
 *
11 3ef693a0 bellard
 * This library is distributed in the hope that it will be useful,
12 3ef693a0 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 3ef693a0 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3ef693a0 bellard
 * Lesser General Public License for more details.
15 7d13299d bellard
 *
16 3ef693a0 bellard
 * You should have received a copy of the GNU Lesser General Public
17 3ef693a0 bellard
 * License along with this library; if not, write to the Free Software
18 3ef693a0 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 7bfdb6d1 bellard
/* we define the various pieces of code used by the JIT */
123 7bfdb6d1 bellard
124 7bfdb6d1 bellard
#define REG EAX
125 7bfdb6d1 bellard
#define REGNAME _EAX
126 7bfdb6d1 bellard
#include "opreg_template.h"
127 7bfdb6d1 bellard
#undef REG
128 7bfdb6d1 bellard
#undef REGNAME
129 7bfdb6d1 bellard
130 7bfdb6d1 bellard
#define REG ECX
131 7bfdb6d1 bellard
#define REGNAME _ECX
132 7bfdb6d1 bellard
#include "opreg_template.h"
133 7bfdb6d1 bellard
#undef REG
134 7bfdb6d1 bellard
#undef REGNAME
135 7bfdb6d1 bellard
136 7bfdb6d1 bellard
#define REG EDX
137 7bfdb6d1 bellard
#define REGNAME _EDX
138 7bfdb6d1 bellard
#include "opreg_template.h"
139 7bfdb6d1 bellard
#undef REG
140 7bfdb6d1 bellard
#undef REGNAME
141 7bfdb6d1 bellard
142 7bfdb6d1 bellard
#define REG EBX
143 7bfdb6d1 bellard
#define REGNAME _EBX
144 7bfdb6d1 bellard
#include "opreg_template.h"
145 7bfdb6d1 bellard
#undef REG
146 7bfdb6d1 bellard
#undef REGNAME
147 7bfdb6d1 bellard
148 7bfdb6d1 bellard
#define REG ESP
149 7bfdb6d1 bellard
#define REGNAME _ESP
150 7bfdb6d1 bellard
#include "opreg_template.h"
151 7bfdb6d1 bellard
#undef REG
152 7bfdb6d1 bellard
#undef REGNAME
153 7bfdb6d1 bellard
154 7bfdb6d1 bellard
#define REG EBP
155 7bfdb6d1 bellard
#define REGNAME _EBP
156 7bfdb6d1 bellard
#include "opreg_template.h"
157 7bfdb6d1 bellard
#undef REG
158 7bfdb6d1 bellard
#undef REGNAME
159 7bfdb6d1 bellard
160 7bfdb6d1 bellard
#define REG ESI
161 7bfdb6d1 bellard
#define REGNAME _ESI
162 7bfdb6d1 bellard
#include "opreg_template.h"
163 7bfdb6d1 bellard
#undef REG
164 7bfdb6d1 bellard
#undef REGNAME
165 7bfdb6d1 bellard
166 7bfdb6d1 bellard
#define REG EDI
167 7bfdb6d1 bellard
#define REGNAME _EDI
168 7bfdb6d1 bellard
#include "opreg_template.h"
169 7bfdb6d1 bellard
#undef REG
170 7bfdb6d1 bellard
#undef REGNAME
171 7bfdb6d1 bellard
172 dc99065b bellard
/* operations with flags */
173 7bfdb6d1 bellard
174 7bfdb6d1 bellard
void OPPROTO op_addl_T0_T1_cc(void)
175 7bfdb6d1 bellard
{
176 7bfdb6d1 bellard
    CC_SRC = T0;
177 7bfdb6d1 bellard
    T0 += T1;
178 7bfdb6d1 bellard
    CC_DST = T0;
179 7bfdb6d1 bellard
}
180 7bfdb6d1 bellard
181 7bfdb6d1 bellard
void OPPROTO op_orl_T0_T1_cc(void)
182 7bfdb6d1 bellard
{
183 7bfdb6d1 bellard
    T0 |= T1;
184 7bfdb6d1 bellard
    CC_DST = T0;
185 7bfdb6d1 bellard
}
186 7bfdb6d1 bellard
187 7bfdb6d1 bellard
void OPPROTO op_andl_T0_T1_cc(void)
188 7bfdb6d1 bellard
{
189 7bfdb6d1 bellard
    T0 &= T1;
190 7bfdb6d1 bellard
    CC_DST = T0;
191 7bfdb6d1 bellard
}
192 7bfdb6d1 bellard
193 7bfdb6d1 bellard
void OPPROTO op_subl_T0_T1_cc(void)
194 7bfdb6d1 bellard
{
195 7bfdb6d1 bellard
    CC_SRC = T0;
196 7bfdb6d1 bellard
    T0 -= T1;
197 7bfdb6d1 bellard
    CC_DST = T0;
198 7bfdb6d1 bellard
}
199 7bfdb6d1 bellard
200 7bfdb6d1 bellard
void OPPROTO op_xorl_T0_T1_cc(void)
201 7bfdb6d1 bellard
{
202 7bfdb6d1 bellard
    T0 ^= T1;
203 7bfdb6d1 bellard
    CC_DST = T0;
204 7bfdb6d1 bellard
}
205 7bfdb6d1 bellard
206 7bfdb6d1 bellard
void OPPROTO op_cmpl_T0_T1_cc(void)
207 7bfdb6d1 bellard
{
208 7bfdb6d1 bellard
    CC_SRC = T0;
209 7bfdb6d1 bellard
    CC_DST = T0 - T1;
210 7bfdb6d1 bellard
}
211 7bfdb6d1 bellard
212 7bfdb6d1 bellard
void OPPROTO op_negl_T0_cc(void)
213 7bfdb6d1 bellard
{
214 7bfdb6d1 bellard
    CC_SRC = 0;
215 7bfdb6d1 bellard
    T0 = -T0;
216 7bfdb6d1 bellard
    CC_DST = T0;
217 7bfdb6d1 bellard
}
218 7bfdb6d1 bellard
219 7bfdb6d1 bellard
void OPPROTO op_incl_T0_cc(void)
220 7bfdb6d1 bellard
{
221 4b74fe1f bellard
    CC_SRC = cc_table[CC_OP].compute_c();
222 7bfdb6d1 bellard
    T0++;
223 7bfdb6d1 bellard
    CC_DST = T0;
224 7bfdb6d1 bellard
}
225 7bfdb6d1 bellard
226 7bfdb6d1 bellard
void OPPROTO op_decl_T0_cc(void)
227 7bfdb6d1 bellard
{
228 4b74fe1f bellard
    CC_SRC = cc_table[CC_OP].compute_c();
229 7bfdb6d1 bellard
    T0--;
230 7bfdb6d1 bellard
    CC_DST = T0;
231 7bfdb6d1 bellard
}
232 7bfdb6d1 bellard
233 7bfdb6d1 bellard
void OPPROTO op_testl_T0_T1_cc(void)
234 7bfdb6d1 bellard
{
235 7bfdb6d1 bellard
    CC_DST = T0 & T1;
236 7bfdb6d1 bellard
}
237 7bfdb6d1 bellard
238 dc99065b bellard
/* operations without flags */
239 dc99065b bellard
240 dc99065b bellard
void OPPROTO op_addl_T0_T1(void)
241 dc99065b bellard
{
242 dc99065b bellard
    T0 += T1;
243 dc99065b bellard
}
244 dc99065b bellard
245 dc99065b bellard
void OPPROTO op_orl_T0_T1(void)
246 dc99065b bellard
{
247 dc99065b bellard
    T0 |= T1;
248 dc99065b bellard
}
249 dc99065b bellard
250 dc99065b bellard
void OPPROTO op_andl_T0_T1(void)
251 dc99065b bellard
{
252 dc99065b bellard
    T0 &= T1;
253 dc99065b bellard
}
254 dc99065b bellard
255 dc99065b bellard
void OPPROTO op_subl_T0_T1(void)
256 dc99065b bellard
{
257 dc99065b bellard
    T0 -= T1;
258 dc99065b bellard
}
259 dc99065b bellard
260 dc99065b bellard
void OPPROTO op_xorl_T0_T1(void)
261 dc99065b bellard
{
262 dc99065b bellard
    T0 ^= T1;
263 dc99065b bellard
}
264 dc99065b bellard
265 dc99065b bellard
void OPPROTO op_negl_T0(void)
266 dc99065b bellard
{
267 dc99065b bellard
    T0 = -T0;
268 dc99065b bellard
}
269 dc99065b bellard
270 dc99065b bellard
void OPPROTO op_incl_T0(void)
271 dc99065b bellard
{
272 dc99065b bellard
    T0++;
273 dc99065b bellard
}
274 dc99065b bellard
275 dc99065b bellard
void OPPROTO op_decl_T0(void)
276 dc99065b bellard
{
277 dc99065b bellard
    T0--;
278 dc99065b bellard
}
279 dc99065b bellard
280 dc99065b bellard
void OPPROTO op_notl_T0(void)
281 dc99065b bellard
{
282 dc99065b bellard
    T0 = ~T0;
283 dc99065b bellard
}
284 dc99065b bellard
285 4b74fe1f bellard
void OPPROTO op_bswapl_T0(void)
286 4b74fe1f bellard
{
287 4b74fe1f bellard
    T0 = bswap32(T0);
288 4b74fe1f bellard
}
289 4b74fe1f bellard
290 7bfdb6d1 bellard
/* multiply/divide */
291 7bfdb6d1 bellard
void OPPROTO op_mulb_AL_T0(void)
292 7bfdb6d1 bellard
{
293 7bfdb6d1 bellard
    unsigned int res;
294 7bfdb6d1 bellard
    res = (uint8_t)EAX * (uint8_t)T0;
295 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | res;
296 7bfdb6d1 bellard
    CC_SRC = (res & 0xff00);
297 7bfdb6d1 bellard
}
298 7bfdb6d1 bellard
299 7bfdb6d1 bellard
void OPPROTO op_imulb_AL_T0(void)
300 7bfdb6d1 bellard
{
301 7bfdb6d1 bellard
    int res;
302 7bfdb6d1 bellard
    res = (int8_t)EAX * (int8_t)T0;
303 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
304 7bfdb6d1 bellard
    CC_SRC = (res != (int8_t)res);
305 7bfdb6d1 bellard
}
306 7bfdb6d1 bellard
307 7bfdb6d1 bellard
void OPPROTO op_mulw_AX_T0(void)
308 7bfdb6d1 bellard
{
309 7bfdb6d1 bellard
    unsigned int res;
310 7bfdb6d1 bellard
    res = (uint16_t)EAX * (uint16_t)T0;
311 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
312 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
313 7bfdb6d1 bellard
    CC_SRC = res >> 16;
314 7bfdb6d1 bellard
}
315 7bfdb6d1 bellard
316 7bfdb6d1 bellard
void OPPROTO op_imulw_AX_T0(void)
317 7bfdb6d1 bellard
{
318 7bfdb6d1 bellard
    int res;
319 7bfdb6d1 bellard
    res = (int16_t)EAX * (int16_t)T0;
320 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (res & 0xffff);
321 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
322 7bfdb6d1 bellard
    CC_SRC = (res != (int16_t)res);
323 7bfdb6d1 bellard
}
324 7bfdb6d1 bellard
325 7bfdb6d1 bellard
void OPPROTO op_mull_EAX_T0(void)
326 7bfdb6d1 bellard
{
327 7bfdb6d1 bellard
    uint64_t res;
328 7bfdb6d1 bellard
    res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
329 7bfdb6d1 bellard
    EAX = res;
330 7bfdb6d1 bellard
    EDX = res >> 32;
331 7bfdb6d1 bellard
    CC_SRC = res >> 32;
332 7bfdb6d1 bellard
}
333 7bfdb6d1 bellard
334 7bfdb6d1 bellard
void OPPROTO op_imull_EAX_T0(void)
335 7bfdb6d1 bellard
{
336 7bfdb6d1 bellard
    int64_t res;
337 7bfdb6d1 bellard
    res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
338 7bfdb6d1 bellard
    EAX = res;
339 7bfdb6d1 bellard
    EDX = res >> 32;
340 7bfdb6d1 bellard
    CC_SRC = (res != (int32_t)res);
341 7bfdb6d1 bellard
}
342 7bfdb6d1 bellard
343 7bfdb6d1 bellard
void OPPROTO op_imulw_T0_T1(void)
344 7bfdb6d1 bellard
{
345 7bfdb6d1 bellard
    int res;
346 7bfdb6d1 bellard
    res = (int16_t)T0 * (int16_t)T1;
347 7bfdb6d1 bellard
    T0 = res;
348 7bfdb6d1 bellard
    CC_SRC = (res != (int16_t)res);
349 7bfdb6d1 bellard
}
350 7bfdb6d1 bellard
351 7bfdb6d1 bellard
void OPPROTO op_imull_T0_T1(void)
352 7bfdb6d1 bellard
{
353 7bfdb6d1 bellard
    int64_t res;
354 4b74fe1f bellard
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
355 7bfdb6d1 bellard
    T0 = res;
356 7bfdb6d1 bellard
    CC_SRC = (res != (int32_t)res);
357 7bfdb6d1 bellard
}
358 7bfdb6d1 bellard
359 7bfdb6d1 bellard
/* division, flags are undefined */
360 9de5e440 bellard
/* XXX: add exceptions for overflow */
361 7bfdb6d1 bellard
void OPPROTO op_divb_AL_T0(void)
362 7bfdb6d1 bellard
{
363 7bfdb6d1 bellard
    unsigned int num, den, q, r;
364 7bfdb6d1 bellard
365 7bfdb6d1 bellard
    num = (EAX & 0xffff);
366 7bfdb6d1 bellard
    den = (T0 & 0xff);
367 9de5e440 bellard
    if (den == 0)
368 9de5e440 bellard
        raise_exception(EXCP00_DIVZ);
369 7bfdb6d1 bellard
    q = (num / den) & 0xff;
370 7bfdb6d1 bellard
    r = (num % den) & 0xff;
371 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
372 7bfdb6d1 bellard
}
373 7bfdb6d1 bellard
374 7bfdb6d1 bellard
void OPPROTO op_idivb_AL_T0(void)
375 7bfdb6d1 bellard
{
376 7bfdb6d1 bellard
    int num, den, q, r;
377 7bfdb6d1 bellard
378 7bfdb6d1 bellard
    num = (int16_t)EAX;
379 7bfdb6d1 bellard
    den = (int8_t)T0;
380 9de5e440 bellard
    if (den == 0)
381 9de5e440 bellard
        raise_exception(EXCP00_DIVZ);
382 7bfdb6d1 bellard
    q = (num / den) & 0xff;
383 7bfdb6d1 bellard
    r = (num % den) & 0xff;
384 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | (r << 8) | q;
385 7bfdb6d1 bellard
}
386 7bfdb6d1 bellard
387 7bfdb6d1 bellard
void OPPROTO op_divw_AX_T0(void)
388 7bfdb6d1 bellard
{
389 7bfdb6d1 bellard
    unsigned int num, den, q, r;
390 7bfdb6d1 bellard
391 7bfdb6d1 bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
392 7bfdb6d1 bellard
    den = (T0 & 0xffff);
393 9de5e440 bellard
    if (den == 0)
394 9de5e440 bellard
        raise_exception(EXCP00_DIVZ);
395 7bfdb6d1 bellard
    q = (num / den) & 0xffff;
396 7bfdb6d1 bellard
    r = (num % den) & 0xffff;
397 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | q;
398 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | r;
399 7bfdb6d1 bellard
}
400 7bfdb6d1 bellard
401 7bfdb6d1 bellard
void OPPROTO op_idivw_AX_T0(void)
402 7bfdb6d1 bellard
{
403 7bfdb6d1 bellard
    int num, den, q, r;
404 7bfdb6d1 bellard
405 7bfdb6d1 bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
406 7bfdb6d1 bellard
    den = (int16_t)T0;
407 9de5e440 bellard
    if (den == 0)
408 9de5e440 bellard
        raise_exception(EXCP00_DIVZ);
409 7bfdb6d1 bellard
    q = (num / den) & 0xffff;
410 7bfdb6d1 bellard
    r = (num % den) & 0xffff;
411 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | q;
412 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | r;
413 7bfdb6d1 bellard
}
414 7bfdb6d1 bellard
415 51fe6890 bellard
#ifdef BUGGY_GCC_DIV64
416 51fe6890 bellard
/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
417 51fe6890 bellard
   call it from another function */
418 51fe6890 bellard
uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den)
419 51fe6890 bellard
{
420 51fe6890 bellard
    *q_ptr = num / den;
421 51fe6890 bellard
    return num % den;
422 51fe6890 bellard
}
423 51fe6890 bellard
424 51fe6890 bellard
int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den)
425 51fe6890 bellard
{
426 51fe6890 bellard
    *q_ptr = num / den;
427 51fe6890 bellard
    return num % den;
428 51fe6890 bellard
}
429 51fe6890 bellard
#endif
430 51fe6890 bellard
431 7bfdb6d1 bellard
void OPPROTO op_divl_EAX_T0(void)
432 7bfdb6d1 bellard
{
433 7bfdb6d1 bellard
    unsigned int den, q, r;
434 7bfdb6d1 bellard
    uint64_t num;
435 7bfdb6d1 bellard
    
436 7bfdb6d1 bellard
    num = EAX | ((uint64_t)EDX << 32);
437 7bfdb6d1 bellard
    den = T0;
438 9de5e440 bellard
    if (den == 0)
439 9de5e440 bellard
        raise_exception(EXCP00_DIVZ);
440 51fe6890 bellard
#ifdef BUGGY_GCC_DIV64
441 51fe6890 bellard
    r = div64(&q, num, den);
442 51fe6890 bellard
#else
443 7bfdb6d1 bellard
    q = (num / den);
444 7bfdb6d1 bellard
    r = (num % den);
445 51fe6890 bellard
#endif
446 7bfdb6d1 bellard
    EAX = q;
447 7bfdb6d1 bellard
    EDX = r;
448 7bfdb6d1 bellard
}
449 7bfdb6d1 bellard
450 7bfdb6d1 bellard
void OPPROTO op_idivl_EAX_T0(void)
451 7bfdb6d1 bellard
{
452 7bfdb6d1 bellard
    int den, q, r;
453 4b74fe1f bellard
    int64_t num;
454 7bfdb6d1 bellard
    
455 7bfdb6d1 bellard
    num = EAX | ((uint64_t)EDX << 32);
456 4b74fe1f bellard
    den = T0;
457 9de5e440 bellard
    if (den == 0)
458 9de5e440 bellard
        raise_exception(EXCP00_DIVZ);
459 51fe6890 bellard
#ifdef BUGGY_GCC_DIV64
460 51fe6890 bellard
    r = idiv64(&q, num, den);
461 51fe6890 bellard
#else
462 7bfdb6d1 bellard
    q = (num / den);
463 7bfdb6d1 bellard
    r = (num % den);
464 51fe6890 bellard
#endif
465 7bfdb6d1 bellard
    EAX = q;
466 7bfdb6d1 bellard
    EDX = r;
467 7bfdb6d1 bellard
}
468 7bfdb6d1 bellard
469 dab2ed99 bellard
/* constant load & misc op */
470 7bfdb6d1 bellard
471 ba1c6e37 bellard
void OPPROTO op_movl_T0_im(void)
472 7bfdb6d1 bellard
{
473 7bfdb6d1 bellard
    T0 = PARAM1;
474 7bfdb6d1 bellard
}
475 7bfdb6d1 bellard
476 dab2ed99 bellard
void OPPROTO op_addl_T0_im(void)
477 dab2ed99 bellard
{
478 dab2ed99 bellard
    T0 += PARAM1;
479 dab2ed99 bellard
}
480 dab2ed99 bellard
481 dab2ed99 bellard
void OPPROTO op_andl_T0_ffff(void)
482 dab2ed99 bellard
{
483 dab2ed99 bellard
    T0 = T0 & 0xffff;
484 dab2ed99 bellard
}
485 dab2ed99 bellard
486 dab2ed99 bellard
void OPPROTO op_movl_T0_T1(void)
487 dab2ed99 bellard
{
488 dab2ed99 bellard
    T0 = T1;
489 dab2ed99 bellard
}
490 dab2ed99 bellard
491 ba1c6e37 bellard
void OPPROTO op_movl_T1_im(void)
492 7bfdb6d1 bellard
{
493 7bfdb6d1 bellard
    T1 = PARAM1;
494 7bfdb6d1 bellard
}
495 7bfdb6d1 bellard
496 dab2ed99 bellard
void OPPROTO op_addl_T1_im(void)
497 dab2ed99 bellard
{
498 dab2ed99 bellard
    T1 += PARAM1;
499 dab2ed99 bellard
}
500 dab2ed99 bellard
501 dab2ed99 bellard
void OPPROTO op_movl_T1_A0(void)
502 dab2ed99 bellard
{
503 dab2ed99 bellard
    T1 = A0;
504 dab2ed99 bellard
}
505 dab2ed99 bellard
506 ba1c6e37 bellard
void OPPROTO op_movl_A0_im(void)
507 7bfdb6d1 bellard
{
508 7bfdb6d1 bellard
    A0 = PARAM1;
509 7bfdb6d1 bellard
}
510 7bfdb6d1 bellard
511 4b74fe1f bellard
void OPPROTO op_addl_A0_im(void)
512 4b74fe1f bellard
{
513 4b74fe1f bellard
    A0 += PARAM1;
514 4b74fe1f bellard
}
515 4b74fe1f bellard
516 31bb950b bellard
void OPPROTO op_addl_A0_AL(void)
517 31bb950b bellard
{
518 31bb950b bellard
    A0 += (EAX & 0xff);
519 31bb950b bellard
}
520 31bb950b bellard
521 4b74fe1f bellard
void OPPROTO op_andl_A0_ffff(void)
522 4b74fe1f bellard
{
523 4b74fe1f bellard
    A0 = A0 & 0xffff;
524 4b74fe1f bellard
}
525 4b74fe1f bellard
526 7bfdb6d1 bellard
/* memory access */
527 7bfdb6d1 bellard
528 7bfdb6d1 bellard
void OPPROTO op_ldub_T0_A0(void)
529 7bfdb6d1 bellard
{
530 7bfdb6d1 bellard
    T0 = ldub((uint8_t *)A0);
531 7bfdb6d1 bellard
}
532 7bfdb6d1 bellard
533 7bfdb6d1 bellard
void OPPROTO op_ldsb_T0_A0(void)
534 7bfdb6d1 bellard
{
535 7bfdb6d1 bellard
    T0 = ldsb((int8_t *)A0);
536 7bfdb6d1 bellard
}
537 7bfdb6d1 bellard
538 7bfdb6d1 bellard
void OPPROTO op_lduw_T0_A0(void)
539 7bfdb6d1 bellard
{
540 7bfdb6d1 bellard
    T0 = lduw((uint8_t *)A0);
541 7bfdb6d1 bellard
}
542 7bfdb6d1 bellard
543 7bfdb6d1 bellard
void OPPROTO op_ldsw_T0_A0(void)
544 7bfdb6d1 bellard
{
545 7bfdb6d1 bellard
    T0 = ldsw((int8_t *)A0);
546 7bfdb6d1 bellard
}
547 7bfdb6d1 bellard
548 7bfdb6d1 bellard
void OPPROTO op_ldl_T0_A0(void)
549 7bfdb6d1 bellard
{
550 7bfdb6d1 bellard
    T0 = ldl((uint8_t *)A0);
551 7bfdb6d1 bellard
}
552 7bfdb6d1 bellard
553 7bfdb6d1 bellard
void OPPROTO op_ldub_T1_A0(void)
554 7bfdb6d1 bellard
{
555 7bfdb6d1 bellard
    T1 = ldub((uint8_t *)A0);
556 7bfdb6d1 bellard
}
557 7bfdb6d1 bellard
558 7bfdb6d1 bellard
void OPPROTO op_ldsb_T1_A0(void)
559 7bfdb6d1 bellard
{
560 7bfdb6d1 bellard
    T1 = ldsb((int8_t *)A0);
561 7bfdb6d1 bellard
}
562 7bfdb6d1 bellard
563 7bfdb6d1 bellard
void OPPROTO op_lduw_T1_A0(void)
564 7bfdb6d1 bellard
{
565 7bfdb6d1 bellard
    T1 = lduw((uint8_t *)A0);
566 7bfdb6d1 bellard
}
567 7bfdb6d1 bellard
568 7bfdb6d1 bellard
void OPPROTO op_ldsw_T1_A0(void)
569 7bfdb6d1 bellard
{
570 7bfdb6d1 bellard
    T1 = ldsw((int8_t *)A0);
571 7bfdb6d1 bellard
}
572 7bfdb6d1 bellard
573 7bfdb6d1 bellard
void OPPROTO op_ldl_T1_A0(void)
574 7bfdb6d1 bellard
{
575 7bfdb6d1 bellard
    T1 = ldl((uint8_t *)A0);
576 7bfdb6d1 bellard
}
577 7bfdb6d1 bellard
578 7bfdb6d1 bellard
void OPPROTO op_stb_T0_A0(void)
579 7bfdb6d1 bellard
{
580 7bfdb6d1 bellard
    stb((uint8_t *)A0, T0);
581 7bfdb6d1 bellard
}
582 7bfdb6d1 bellard
583 7bfdb6d1 bellard
void OPPROTO op_stw_T0_A0(void)
584 7bfdb6d1 bellard
{
585 7bfdb6d1 bellard
    stw((uint8_t *)A0, T0);
586 7bfdb6d1 bellard
}
587 7bfdb6d1 bellard
588 7bfdb6d1 bellard
void OPPROTO op_stl_T0_A0(void)
589 7bfdb6d1 bellard
{
590 7bfdb6d1 bellard
    stl((uint8_t *)A0, T0);
591 7bfdb6d1 bellard
}
592 7bfdb6d1 bellard
593 4b74fe1f bellard
/* used for bit operations */
594 4b74fe1f bellard
595 4b74fe1f bellard
void OPPROTO op_add_bitw_A0_T1(void)
596 4b74fe1f bellard
{
597 4b74fe1f bellard
    A0 += ((int32_t)T1 >> 4) << 1;
598 4b74fe1f bellard
}
599 4b74fe1f bellard
600 4b74fe1f bellard
void OPPROTO op_add_bitl_A0_T1(void)
601 4b74fe1f bellard
{
602 4b74fe1f bellard
    A0 += ((int32_t)T1 >> 5) << 2;
603 4b74fe1f bellard
}
604 7bfdb6d1 bellard
605 7bfdb6d1 bellard
/* indirect jump */
606 0ecfa993 bellard
607 7bfdb6d1 bellard
void OPPROTO op_jmp_T0(void)
608 7bfdb6d1 bellard
{
609 dab2ed99 bellard
    EIP = T0;
610 7bfdb6d1 bellard
}
611 7bfdb6d1 bellard
612 7bfdb6d1 bellard
void OPPROTO op_jmp_im(void)
613 7bfdb6d1 bellard
{
614 dab2ed99 bellard
    EIP = PARAM1;
615 7bfdb6d1 bellard
}
616 7bfdb6d1 bellard
617 0ecfa993 bellard
void OPPROTO op_int_im(void)
618 0ecfa993 bellard
{
619 504e56eb bellard
    int intno;
620 504e56eb bellard
    intno = PARAM1;
621 504e56eb bellard
    EIP = PARAM2;
622 504e56eb bellard
    raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
623 0ecfa993 bellard
}
624 0ecfa993 bellard
625 0ecfa993 bellard
void OPPROTO op_int3(void)
626 0ecfa993 bellard
{
627 dab2ed99 bellard
    EIP = PARAM1;
628 0ecfa993 bellard
    raise_exception(EXCP03_INT3);
629 0ecfa993 bellard
}
630 0ecfa993 bellard
631 0ecfa993 bellard
void OPPROTO op_into(void)
632 0ecfa993 bellard
{
633 0ecfa993 bellard
    int eflags;
634 0ecfa993 bellard
    eflags = cc_table[CC_OP].compute_all();
635 0ecfa993 bellard
    if (eflags & CC_O) {
636 0ecfa993 bellard
        raise_exception(EXCP04_INTO);
637 a4a0ffdb bellard
    }
638 504e56eb bellard
    FORCE_RET();
639 a4a0ffdb bellard
}
640 a4a0ffdb bellard
641 504e56eb bellard
void OPPROTO op_gpf(void)
642 f631ef9b bellard
{
643 504e56eb bellard
    EIP = PARAM1;
644 f631ef9b bellard
    raise_exception(EXCP0D_GPF);
645 f631ef9b bellard
}
646 f631ef9b bellard
647 504e56eb bellard
void OPPROTO op_cli(void)
648 504e56eb bellard
{
649 504e56eb bellard
    env->eflags &= ~IF_MASK;
650 504e56eb bellard
}
651 504e56eb bellard
652 f631ef9b bellard
void OPPROTO op_sti(void)
653 f631ef9b bellard
{
654 504e56eb bellard
    env->eflags |= IF_MASK;
655 f631ef9b bellard
}
656 f631ef9b bellard
657 f631ef9b bellard
/* vm86plus instructions */
658 f631ef9b bellard
659 f631ef9b bellard
void OPPROTO op_cli_vm(void)
660 f631ef9b bellard
{
661 f631ef9b bellard
    env->eflags &= ~VIF_MASK;
662 f631ef9b bellard
}
663 f631ef9b bellard
664 f631ef9b bellard
void OPPROTO op_sti_vm(void)
665 f631ef9b bellard
{
666 f631ef9b bellard
    env->eflags |= VIF_MASK;
667 f631ef9b bellard
    if (env->eflags & VIP_MASK) {
668 f631ef9b bellard
        EIP = PARAM1;
669 f631ef9b bellard
        raise_exception(EXCP0D_GPF);
670 f631ef9b bellard
    }
671 f631ef9b bellard
    FORCE_RET();
672 f631ef9b bellard
}
673 f631ef9b bellard
674 a4a0ffdb bellard
void OPPROTO op_boundw(void)
675 a4a0ffdb bellard
{
676 a4a0ffdb bellard
    int low, high, v;
677 a4a0ffdb bellard
    low = ldsw((uint8_t *)A0);
678 a4a0ffdb bellard
    high = ldsw((uint8_t *)A0 + 2);
679 a4a0ffdb bellard
    v = (int16_t)T0;
680 a4a0ffdb bellard
    if (v < low || v > high)
681 a4a0ffdb bellard
        raise_exception(EXCP05_BOUND);
682 a4a0ffdb bellard
    FORCE_RET();
683 a4a0ffdb bellard
}
684 a4a0ffdb bellard
685 a4a0ffdb bellard
void OPPROTO op_boundl(void)
686 a4a0ffdb bellard
{
687 a4a0ffdb bellard
    int low, high, v;
688 a4a0ffdb bellard
    low = ldl((uint8_t *)A0);
689 a4a0ffdb bellard
    high = ldl((uint8_t *)A0 + 4);
690 a4a0ffdb bellard
    v = T0;
691 a4a0ffdb bellard
    if (v < low || v > high)
692 a4a0ffdb bellard
        raise_exception(EXCP05_BOUND);
693 a4a0ffdb bellard
    FORCE_RET();
694 a4a0ffdb bellard
}
695 a4a0ffdb bellard
696 a4a0ffdb bellard
void OPPROTO op_cmpxchg8b(void)
697 a4a0ffdb bellard
{
698 a4a0ffdb bellard
    uint64_t d;
699 a4a0ffdb bellard
    int eflags;
700 a4a0ffdb bellard
701 a4a0ffdb bellard
    eflags = cc_table[CC_OP].compute_all();
702 a4a0ffdb bellard
    d = ldq((uint8_t *)A0);
703 a4a0ffdb bellard
    if (d == (((uint64_t)EDX << 32) | EAX)) {
704 a4a0ffdb bellard
        stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);
705 a4a0ffdb bellard
        eflags |= CC_Z;
706 0ecfa993 bellard
    } else {
707 a4a0ffdb bellard
        EDX = d >> 32;
708 a4a0ffdb bellard
        EAX = d;
709 a4a0ffdb bellard
        eflags &= ~CC_Z;
710 0ecfa993 bellard
    }
711 a4a0ffdb bellard
    CC_SRC = eflags;
712 a4a0ffdb bellard
    FORCE_RET();
713 0ecfa993 bellard
}
714 0ecfa993 bellard
715 7bfdb6d1 bellard
/* string ops */
716 7bfdb6d1 bellard
717 7bfdb6d1 bellard
#define ldul ldl
718 7bfdb6d1 bellard
719 7bfdb6d1 bellard
#define SHIFT 0
720 367e86e8 bellard
#include "ops_template.h"
721 7bfdb6d1 bellard
#undef SHIFT
722 7bfdb6d1 bellard
723 7bfdb6d1 bellard
#define SHIFT 1
724 367e86e8 bellard
#include "ops_template.h"
725 7bfdb6d1 bellard
#undef SHIFT
726 7bfdb6d1 bellard
727 7bfdb6d1 bellard
#define SHIFT 2
728 367e86e8 bellard
#include "ops_template.h"
729 7bfdb6d1 bellard
#undef SHIFT
730 7bfdb6d1 bellard
731 7bfdb6d1 bellard
/* sign extend */
732 7bfdb6d1 bellard
733 7bfdb6d1 bellard
void OPPROTO op_movsbl_T0_T0(void)
734 7bfdb6d1 bellard
{
735 7bfdb6d1 bellard
    T0 = (int8_t)T0;
736 7bfdb6d1 bellard
}
737 7bfdb6d1 bellard
738 7bfdb6d1 bellard
void OPPROTO op_movzbl_T0_T0(void)
739 7bfdb6d1 bellard
{
740 7bfdb6d1 bellard
    T0 = (uint8_t)T0;
741 7bfdb6d1 bellard
}
742 7bfdb6d1 bellard
743 7bfdb6d1 bellard
void OPPROTO op_movswl_T0_T0(void)
744 7bfdb6d1 bellard
{
745 7bfdb6d1 bellard
    T0 = (int16_t)T0;
746 7bfdb6d1 bellard
}
747 7bfdb6d1 bellard
748 7bfdb6d1 bellard
void OPPROTO op_movzwl_T0_T0(void)
749 7bfdb6d1 bellard
{
750 7bfdb6d1 bellard
    T0 = (uint16_t)T0;
751 7bfdb6d1 bellard
}
752 7bfdb6d1 bellard
753 7bfdb6d1 bellard
void OPPROTO op_movswl_EAX_AX(void)
754 7bfdb6d1 bellard
{
755 7bfdb6d1 bellard
    EAX = (int16_t)EAX;
756 7bfdb6d1 bellard
}
757 7bfdb6d1 bellard
758 7bfdb6d1 bellard
void OPPROTO op_movsbw_AX_AL(void)
759 7bfdb6d1 bellard
{
760 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
761 7bfdb6d1 bellard
}
762 7bfdb6d1 bellard
763 7bfdb6d1 bellard
void OPPROTO op_movslq_EDX_EAX(void)
764 7bfdb6d1 bellard
{
765 7bfdb6d1 bellard
    EDX = (int32_t)EAX >> 31;
766 7bfdb6d1 bellard
}
767 7bfdb6d1 bellard
768 7bfdb6d1 bellard
void OPPROTO op_movswl_DX_AX(void)
769 7bfdb6d1 bellard
{
770 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
771 7bfdb6d1 bellard
}
772 7bfdb6d1 bellard
773 7bfdb6d1 bellard
/* push/pop */
774 7bfdb6d1 bellard
775 7bfdb6d1 bellard
void op_pushl_T0(void)
776 7bfdb6d1 bellard
{
777 7bfdb6d1 bellard
    uint32_t offset;
778 7bfdb6d1 bellard
    offset = ESP - 4;
779 7bfdb6d1 bellard
    stl((void *)offset, T0);
780 7bfdb6d1 bellard
    /* modify ESP after to handle exceptions correctly */
781 7bfdb6d1 bellard
    ESP = offset;
782 7bfdb6d1 bellard
}
783 7bfdb6d1 bellard
784 dab2ed99 bellard
void op_pushw_T0(void)
785 dab2ed99 bellard
{
786 dab2ed99 bellard
    uint32_t offset;
787 dab2ed99 bellard
    offset = ESP - 2;
788 dab2ed99 bellard
    stw((void *)offset, T0);
789 dab2ed99 bellard
    /* modify ESP after to handle exceptions correctly */
790 dab2ed99 bellard
    ESP = offset;
791 dab2ed99 bellard
}
792 dab2ed99 bellard
793 dab2ed99 bellard
void op_pushl_ss32_T0(void)
794 7bfdb6d1 bellard
{
795 7bfdb6d1 bellard
    uint32_t offset;
796 7bfdb6d1 bellard
    offset = ESP - 4;
797 dab2ed99 bellard
    stl(env->seg_cache[R_SS].base + offset, T0);
798 dab2ed99 bellard
    /* modify ESP after to handle exceptions correctly */
799 dab2ed99 bellard
    ESP = offset;
800 dab2ed99 bellard
}
801 dab2ed99 bellard
802 dab2ed99 bellard
void op_pushw_ss32_T0(void)
803 dab2ed99 bellard
{
804 dab2ed99 bellard
    uint32_t offset;
805 dab2ed99 bellard
    offset = ESP - 2;
806 dab2ed99 bellard
    stw(env->seg_cache[R_SS].base + offset, T0);
807 7bfdb6d1 bellard
    /* modify ESP after to handle exceptions correctly */
808 7bfdb6d1 bellard
    ESP = offset;
809 7bfdb6d1 bellard
}
810 7bfdb6d1 bellard
811 dab2ed99 bellard
void op_pushl_ss16_T0(void)
812 dab2ed99 bellard
{
813 dab2ed99 bellard
    uint32_t offset;
814 dab2ed99 bellard
    offset = (ESP - 4) & 0xffff;
815 dab2ed99 bellard
    stl(env->seg_cache[R_SS].base + offset, T0);
816 dab2ed99 bellard
    /* modify ESP after to handle exceptions correctly */
817 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | offset;
818 dab2ed99 bellard
}
819 dab2ed99 bellard
820 dab2ed99 bellard
void op_pushw_ss16_T0(void)
821 dab2ed99 bellard
{
822 dab2ed99 bellard
    uint32_t offset;
823 dab2ed99 bellard
    offset = (ESP - 2) & 0xffff;
824 dab2ed99 bellard
    stw(env->seg_cache[R_SS].base + offset, T0);
825 dab2ed99 bellard
    /* modify ESP after to handle exceptions correctly */
826 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | offset;
827 dab2ed99 bellard
}
828 dab2ed99 bellard
829 dab2ed99 bellard
/* NOTE: ESP update is done after */
830 7bfdb6d1 bellard
void op_popl_T0(void)
831 7bfdb6d1 bellard
{
832 7bfdb6d1 bellard
    T0 = ldl((void *)ESP);
833 dab2ed99 bellard
}
834 dab2ed99 bellard
835 dab2ed99 bellard
void op_popw_T0(void)
836 dab2ed99 bellard
{
837 dab2ed99 bellard
    T0 = lduw((void *)ESP);
838 dab2ed99 bellard
}
839 dab2ed99 bellard
840 dab2ed99 bellard
void op_popl_ss32_T0(void)
841 dab2ed99 bellard
{
842 dab2ed99 bellard
    T0 = ldl(env->seg_cache[R_SS].base + ESP);
843 dab2ed99 bellard
}
844 dab2ed99 bellard
845 dab2ed99 bellard
void op_popw_ss32_T0(void)
846 dab2ed99 bellard
{
847 dab2ed99 bellard
    T0 = lduw(env->seg_cache[R_SS].base + ESP);
848 dab2ed99 bellard
}
849 dab2ed99 bellard
850 dab2ed99 bellard
void op_popl_ss16_T0(void)
851 dab2ed99 bellard
{
852 dab2ed99 bellard
    T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff));
853 dab2ed99 bellard
}
854 dab2ed99 bellard
855 dab2ed99 bellard
void op_popw_ss16_T0(void)
856 dab2ed99 bellard
{
857 dab2ed99 bellard
    T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff));
858 dab2ed99 bellard
}
859 dab2ed99 bellard
860 dab2ed99 bellard
void op_addl_ESP_4(void)
861 dab2ed99 bellard
{
862 7bfdb6d1 bellard
    ESP += 4;
863 7bfdb6d1 bellard
}
864 7bfdb6d1 bellard
865 dab2ed99 bellard
void op_addl_ESP_2(void)
866 dab2ed99 bellard
{
867 dab2ed99 bellard
    ESP += 2;
868 dab2ed99 bellard
}
869 dab2ed99 bellard
870 dab2ed99 bellard
void op_addw_ESP_4(void)
871 dab2ed99 bellard
{
872 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
873 dab2ed99 bellard
}
874 dab2ed99 bellard
875 dab2ed99 bellard
void op_addw_ESP_2(void)
876 dab2ed99 bellard
{
877 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
878 dab2ed99 bellard
}
879 dab2ed99 bellard
880 7bfdb6d1 bellard
void op_addl_ESP_im(void)
881 7bfdb6d1 bellard
{
882 7bfdb6d1 bellard
    ESP += PARAM1;
883 7bfdb6d1 bellard
}
884 367e86e8 bellard
885 dab2ed99 bellard
void op_addw_ESP_im(void)
886 dab2ed99 bellard
{
887 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
888 27362c82 bellard
}
889 27362c82 bellard
890 27362c82 bellard
/* rdtsc */
891 27362c82 bellard
#ifndef __i386__
892 27362c82 bellard
uint64_t emu_time;
893 27362c82 bellard
#endif
894 a4a0ffdb bellard
895 a4a0ffdb bellard
void OPPROTO op_rdtsc(void)
896 27362c82 bellard
{
897 27362c82 bellard
    uint64_t val;
898 27362c82 bellard
#ifdef __i386__
899 27362c82 bellard
    asm("rdtsc" : "=A" (val));
900 27362c82 bellard
#else
901 27362c82 bellard
    /* better than nothing: the time increases */
902 27362c82 bellard
    val = emu_time++;
903 27362c82 bellard
#endif
904 27362c82 bellard
    EAX = val;
905 27362c82 bellard
    EDX = val >> 32;
906 27362c82 bellard
}
907 27362c82 bellard
908 a4a0ffdb bellard
/* We simulate a pre-MMX pentium as in valgrind */
909 a4a0ffdb bellard
#define CPUID_FP87 (1 << 0)
910 a4a0ffdb bellard
#define CPUID_VME  (1 << 1)
911 a4a0ffdb bellard
#define CPUID_DE   (1 << 2)
912 a4a0ffdb bellard
#define CPUID_PSE  (1 << 3)
913 a4a0ffdb bellard
#define CPUID_TSC  (1 << 4)
914 a4a0ffdb bellard
#define CPUID_MSR  (1 << 5)
915 a4a0ffdb bellard
#define CPUID_PAE  (1 << 6)
916 a4a0ffdb bellard
#define CPUID_MCE  (1 << 7)
917 a4a0ffdb bellard
#define CPUID_CX8  (1 << 8)
918 a4a0ffdb bellard
#define CPUID_APIC (1 << 9)
919 a4a0ffdb bellard
#define CPUID_SEP  (1 << 11) /* sysenter/sysexit */
920 a4a0ffdb bellard
#define CPUID_MTRR (1 << 12)
921 a4a0ffdb bellard
#define CPUID_PGE  (1 << 13)
922 a4a0ffdb bellard
#define CPUID_MCA  (1 << 14)
923 a4a0ffdb bellard
#define CPUID_CMOV (1 << 15)
924 a4a0ffdb bellard
/* ... */
925 a4a0ffdb bellard
#define CPUID_MMX  (1 << 23)
926 a4a0ffdb bellard
#define CPUID_FXSR (1 << 24)
927 a4a0ffdb bellard
#define CPUID_SSE  (1 << 25)
928 a4a0ffdb bellard
#define CPUID_SSE2 (1 << 26)
929 a4a0ffdb bellard
930 a4a0ffdb bellard
void helper_cpuid(void)
931 a4a0ffdb bellard
{
932 a4a0ffdb bellard
    if (EAX == 0) {
933 a4a0ffdb bellard
        EAX = 1; /* max EAX index supported */
934 a4a0ffdb bellard
        EBX = 0x756e6547;
935 a4a0ffdb bellard
        ECX = 0x6c65746e;
936 a4a0ffdb bellard
        EDX = 0x49656e69;
937 a4a0ffdb bellard
    } else {
938 a4a0ffdb bellard
        /* EAX = 1 info */
939 a4a0ffdb bellard
        EAX = 0x52b;
940 a4a0ffdb bellard
        EBX = 0;
941 a4a0ffdb bellard
        ECX = 0;
942 a4a0ffdb bellard
        EDX = CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE |
943 a4a0ffdb bellard
            CPUID_TSC | CPUID_MSR | CPUID_MCE |
944 a4a0ffdb bellard
            CPUID_CX8;
945 a4a0ffdb bellard
    }
946 a4a0ffdb bellard
}
947 a4a0ffdb bellard
948 a4a0ffdb bellard
void OPPROTO op_cpuid(void)
949 a4a0ffdb bellard
{
950 a4a0ffdb bellard
    helper_cpuid();
951 a4a0ffdb bellard
}
952 a4a0ffdb bellard
953 27362c82 bellard
/* bcd */
954 27362c82 bellard
955 27362c82 bellard
/* XXX: exception */
956 27362c82 bellard
void OPPROTO op_aam(void)
957 27362c82 bellard
{
958 27362c82 bellard
    int base = PARAM1;
959 27362c82 bellard
    int al, ah;
960 27362c82 bellard
    al = EAX & 0xff;
961 27362c82 bellard
    ah = al / base;
962 27362c82 bellard
    al = al % base;
963 27362c82 bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
964 27362c82 bellard
    CC_DST = al;
965 27362c82 bellard
}
966 27362c82 bellard
967 27362c82 bellard
void OPPROTO op_aad(void)
968 27362c82 bellard
{
969 27362c82 bellard
    int base = PARAM1;
970 27362c82 bellard
    int al, ah;
971 27362c82 bellard
    al = EAX & 0xff;
972 27362c82 bellard
    ah = (EAX >> 8) & 0xff;
973 27362c82 bellard
    al = ((ah * base) + al) & 0xff;
974 27362c82 bellard
    EAX = (EAX & ~0xffff) | al;
975 27362c82 bellard
    CC_DST = al;
976 27362c82 bellard
}
977 27362c82 bellard
978 27362c82 bellard
void OPPROTO op_aaa(void)
979 27362c82 bellard
{
980 27362c82 bellard
    int icarry;
981 27362c82 bellard
    int al, ah, af;
982 27362c82 bellard
    int eflags;
983 27362c82 bellard
984 27362c82 bellard
    eflags = cc_table[CC_OP].compute_all();
985 27362c82 bellard
    af = eflags & CC_A;
986 27362c82 bellard
    al = EAX & 0xff;
987 27362c82 bellard
    ah = (EAX >> 8) & 0xff;
988 27362c82 bellard
989 27362c82 bellard
    icarry = (al > 0xf9);
990 27362c82 bellard
    if (((al & 0x0f) > 9 ) || af) {
991 27362c82 bellard
        al = (al + 6) & 0x0f;
992 27362c82 bellard
        ah = (ah + 1 + icarry) & 0xff;
993 27362c82 bellard
        eflags |= CC_C | CC_A;
994 27362c82 bellard
    } else {
995 27362c82 bellard
        eflags &= ~(CC_C | CC_A);
996 27362c82 bellard
        al &= 0x0f;
997 27362c82 bellard
    }
998 27362c82 bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
999 27362c82 bellard
    CC_SRC = eflags;
1000 27362c82 bellard
}
1001 27362c82 bellard
1002 27362c82 bellard
void OPPROTO op_aas(void)
1003 27362c82 bellard
{
1004 27362c82 bellard
    int icarry;
1005 27362c82 bellard
    int al, ah, af;
1006 27362c82 bellard
    int eflags;
1007 27362c82 bellard
1008 27362c82 bellard
    eflags = cc_table[CC_OP].compute_all();
1009 27362c82 bellard
    af = eflags & CC_A;
1010 27362c82 bellard
    al = EAX & 0xff;
1011 27362c82 bellard
    ah = (EAX >> 8) & 0xff;
1012 27362c82 bellard
1013 27362c82 bellard
    icarry = (al < 6);
1014 27362c82 bellard
    if (((al & 0x0f) > 9 ) || af) {
1015 27362c82 bellard
        al = (al - 6) & 0x0f;
1016 27362c82 bellard
        ah = (ah - 1 - icarry) & 0xff;
1017 27362c82 bellard
        eflags |= CC_C | CC_A;
1018 27362c82 bellard
    } else {
1019 27362c82 bellard
        eflags &= ~(CC_C | CC_A);
1020 27362c82 bellard
        al &= 0x0f;
1021 27362c82 bellard
    }
1022 27362c82 bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1023 27362c82 bellard
    CC_SRC = eflags;
1024 27362c82 bellard
}
1025 27362c82 bellard
1026 27362c82 bellard
void OPPROTO op_daa(void)
1027 27362c82 bellard
{
1028 27362c82 bellard
    int al, af, cf;
1029 27362c82 bellard
    int eflags;
1030 27362c82 bellard
1031 27362c82 bellard
    eflags = cc_table[CC_OP].compute_all();
1032 27362c82 bellard
    cf = eflags & CC_C;
1033 27362c82 bellard
    af = eflags & CC_A;
1034 27362c82 bellard
    al = EAX & 0xff;
1035 27362c82 bellard
1036 27362c82 bellard
    eflags = 0;
1037 27362c82 bellard
    if (((al & 0x0f) > 9 ) || af) {
1038 27362c82 bellard
        al = (al + 6) & 0xff;
1039 27362c82 bellard
        eflags |= CC_A;
1040 27362c82 bellard
    }
1041 27362c82 bellard
    if ((al > 0x9f) || cf) {
1042 27362c82 bellard
        al = (al + 0x60) & 0xff;
1043 27362c82 bellard
        eflags |= CC_C;
1044 27362c82 bellard
    }
1045 27362c82 bellard
    EAX = (EAX & ~0xff) | al;
1046 27362c82 bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1047 27362c82 bellard
    eflags |= (al == 0) << 6; /* zf */
1048 27362c82 bellard
    eflags |= parity_table[al]; /* pf */
1049 27362c82 bellard
    eflags |= (al & 0x80); /* sf */
1050 27362c82 bellard
    CC_SRC = eflags;
1051 27362c82 bellard
}
1052 27362c82 bellard
1053 27362c82 bellard
void OPPROTO op_das(void)
1054 27362c82 bellard
{
1055 27362c82 bellard
    int al, al1, af, cf;
1056 27362c82 bellard
    int eflags;
1057 27362c82 bellard
1058 27362c82 bellard
    eflags = cc_table[CC_OP].compute_all();
1059 27362c82 bellard
    cf = eflags & CC_C;
1060 27362c82 bellard
    af = eflags & CC_A;
1061 27362c82 bellard
    al = EAX & 0xff;
1062 27362c82 bellard
1063 27362c82 bellard
    eflags = 0;
1064 27362c82 bellard
    al1 = al;
1065 27362c82 bellard
    if (((al & 0x0f) > 9 ) || af) {
1066 27362c82 bellard
        eflags |= CC_A;
1067 27362c82 bellard
        if (al < 6 || cf)
1068 27362c82 bellard
            eflags |= CC_C;
1069 27362c82 bellard
        al = (al - 6) & 0xff;
1070 27362c82 bellard
    }
1071 27362c82 bellard
    if ((al1 > 0x99) || cf) {
1072 27362c82 bellard
        al = (al - 0x60) & 0xff;
1073 27362c82 bellard
        eflags |= CC_C;
1074 27362c82 bellard
    }
1075 27362c82 bellard
    EAX = (EAX & ~0xff) | al;
1076 27362c82 bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1077 27362c82 bellard
    eflags |= (al == 0) << 6; /* zf */
1078 27362c82 bellard
    eflags |= parity_table[al]; /* pf */
1079 27362c82 bellard
    eflags |= (al & 0x80); /* sf */
1080 27362c82 bellard
    CC_SRC = eflags;
1081 27362c82 bellard
}
1082 27362c82 bellard
1083 6dbad63e bellard
/* segment handling */
1084 6dbad63e bellard
1085 a4a0ffdb bellard
/* XXX: use static VM86 information */
1086 6dbad63e bellard
void load_seg(int seg_reg, int selector)
1087 6dbad63e bellard
{
1088 6dbad63e bellard
    SegmentCache *sc;
1089 6dbad63e bellard
    SegmentDescriptorTable *dt;
1090 6dbad63e bellard
    int index;
1091 6dbad63e bellard
    uint32_t e1, e2;
1092 6dbad63e bellard
    uint8_t *ptr;
1093 6dbad63e bellard
1094 6dbad63e bellard
    env->segs[seg_reg] = selector;
1095 6dbad63e bellard
    sc = &env->seg_cache[seg_reg];
1096 a4a0ffdb bellard
    if (env->eflags & VM_MASK) {
1097 6dbad63e bellard
        sc->base = (void *)(selector << 4);
1098 6dbad63e bellard
        sc->limit = 0xffff;
1099 6dbad63e bellard
        sc->seg_32bit = 0;
1100 6dbad63e bellard
    } else {
1101 6dbad63e bellard
        if (selector & 0x4)
1102 6dbad63e bellard
            dt = &env->ldt;
1103 6dbad63e bellard
        else
1104 6dbad63e bellard
            dt = &env->gdt;
1105 6dbad63e bellard
        index = selector & ~7;
1106 6dbad63e bellard
        if ((index + 7) > dt->limit)
1107 504e56eb bellard
            raise_exception_err(EXCP0D_GPF, selector);
1108 6dbad63e bellard
        ptr = dt->base + index;
1109 6dbad63e bellard
        e1 = ldl(ptr);
1110 6dbad63e bellard
        e2 = ldl(ptr + 4);
1111 6dbad63e bellard
        sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1112 6dbad63e bellard
        sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1113 6dbad63e bellard
        if (e2 & (1 << 23))
1114 6dbad63e bellard
            sc->limit = (sc->limit << 12) | 0xfff;
1115 6dbad63e bellard
        sc->seg_32bit = (e2 >> 22) & 1;
1116 6dbad63e bellard
#if 0
1117 6dbad63e bellard
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", 
1118 6dbad63e bellard
                selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
1119 6dbad63e bellard
#endif
1120 6dbad63e bellard
    }
1121 6dbad63e bellard
}
1122 6dbad63e bellard
1123 6dbad63e bellard
void OPPROTO op_movl_seg_T0(void)
1124 6dbad63e bellard
{
1125 6dbad63e bellard
    load_seg(PARAM1, T0 & 0xffff);
1126 6dbad63e bellard
}
1127 6dbad63e bellard
1128 6dbad63e bellard
void OPPROTO op_movl_T0_seg(void)
1129 6dbad63e bellard
{
1130 6dbad63e bellard
    T0 = env->segs[PARAM1];
1131 6dbad63e bellard
}
1132 6dbad63e bellard
1133 a4a0ffdb bellard
void OPPROTO op_movl_A0_seg(void)
1134 a4a0ffdb bellard
{
1135 a4a0ffdb bellard
    A0 = *(unsigned long *)((char *)env + PARAM1);
1136 a4a0ffdb bellard
}
1137 a4a0ffdb bellard
1138 6dbad63e bellard
void OPPROTO op_addl_A0_seg(void)
1139 6dbad63e bellard
{
1140 6dbad63e bellard
    A0 += *(unsigned long *)((char *)env + PARAM1);
1141 6dbad63e bellard
}
1142 6dbad63e bellard
1143 367e86e8 bellard
/* flags handling */
1144 367e86e8 bellard
1145 367e86e8 bellard
/* slow jumps cases (compute x86 flags) */
1146 367e86e8 bellard
void OPPROTO op_jo_cc(void)
1147 367e86e8 bellard
{
1148 367e86e8 bellard
    int eflags;
1149 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1150 367e86e8 bellard
    if (eflags & CC_O)
1151 dab2ed99 bellard
        EIP = PARAM1;
1152 367e86e8 bellard
    else
1153 dab2ed99 bellard
        EIP = PARAM2;
1154 0ecfa993 bellard
    FORCE_RET();
1155 367e86e8 bellard
}
1156 367e86e8 bellard
1157 367e86e8 bellard
void OPPROTO op_jb_cc(void)
1158 367e86e8 bellard
{
1159 367e86e8 bellard
    if (cc_table[CC_OP].compute_c())
1160 dab2ed99 bellard
        EIP = PARAM1;
1161 367e86e8 bellard
    else
1162 dab2ed99 bellard
        EIP = PARAM2;
1163 0ecfa993 bellard
    FORCE_RET();
1164 367e86e8 bellard
}
1165 367e86e8 bellard
1166 367e86e8 bellard
void OPPROTO op_jz_cc(void)
1167 367e86e8 bellard
{
1168 367e86e8 bellard
    int eflags;
1169 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1170 367e86e8 bellard
    if (eflags & CC_Z)
1171 dab2ed99 bellard
        EIP = PARAM1;
1172 367e86e8 bellard
    else
1173 dab2ed99 bellard
        EIP = PARAM2;
1174 0ecfa993 bellard
    FORCE_RET();
1175 367e86e8 bellard
}
1176 367e86e8 bellard
1177 367e86e8 bellard
void OPPROTO op_jbe_cc(void)
1178 367e86e8 bellard
{
1179 367e86e8 bellard
    int eflags;
1180 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1181 367e86e8 bellard
    if (eflags & (CC_Z | CC_C))
1182 dab2ed99 bellard
        EIP = PARAM1;
1183 367e86e8 bellard
    else
1184 dab2ed99 bellard
        EIP = PARAM2;
1185 0ecfa993 bellard
    FORCE_RET();
1186 367e86e8 bellard
}
1187 367e86e8 bellard
1188 367e86e8 bellard
void OPPROTO op_js_cc(void)
1189 367e86e8 bellard
{
1190 367e86e8 bellard
    int eflags;
1191 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1192 367e86e8 bellard
    if (eflags & CC_S)
1193 dab2ed99 bellard
        EIP = PARAM1;
1194 367e86e8 bellard
    else
1195 dab2ed99 bellard
        EIP = PARAM2;
1196 0ecfa993 bellard
    FORCE_RET();
1197 367e86e8 bellard
}
1198 367e86e8 bellard
1199 367e86e8 bellard
void OPPROTO op_jp_cc(void)
1200 367e86e8 bellard
{
1201 367e86e8 bellard
    int eflags;
1202 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1203 367e86e8 bellard
    if (eflags & CC_P)
1204 dab2ed99 bellard
        EIP = PARAM1;
1205 367e86e8 bellard
    else
1206 dab2ed99 bellard
        EIP = PARAM2;
1207 0ecfa993 bellard
    FORCE_RET();
1208 367e86e8 bellard
}
1209 367e86e8 bellard
1210 367e86e8 bellard
void OPPROTO op_jl_cc(void)
1211 367e86e8 bellard
{
1212 367e86e8 bellard
    int eflags;
1213 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1214 367e86e8 bellard
    if ((eflags ^ (eflags >> 4)) & 0x80)
1215 dab2ed99 bellard
        EIP = PARAM1;
1216 367e86e8 bellard
    else
1217 dab2ed99 bellard
        EIP = PARAM2;
1218 0ecfa993 bellard
    FORCE_RET();
1219 367e86e8 bellard
}
1220 367e86e8 bellard
1221 367e86e8 bellard
void OPPROTO op_jle_cc(void)
1222 367e86e8 bellard
{
1223 367e86e8 bellard
    int eflags;
1224 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1225 367e86e8 bellard
    if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
1226 dab2ed99 bellard
        EIP = PARAM1;
1227 367e86e8 bellard
    else
1228 dab2ed99 bellard
        EIP = PARAM2;
1229 0ecfa993 bellard
    FORCE_RET();
1230 367e86e8 bellard
}
1231 367e86e8 bellard
1232 367e86e8 bellard
/* slow set cases (compute x86 flags) */
1233 367e86e8 bellard
void OPPROTO op_seto_T0_cc(void)
1234 367e86e8 bellard
{
1235 367e86e8 bellard
    int eflags;
1236 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1237 367e86e8 bellard
    T0 = (eflags >> 11) & 1;
1238 367e86e8 bellard
}
1239 367e86e8 bellard
1240 367e86e8 bellard
void OPPROTO op_setb_T0_cc(void)
1241 367e86e8 bellard
{
1242 367e86e8 bellard
    T0 = cc_table[CC_OP].compute_c();
1243 367e86e8 bellard
}
1244 367e86e8 bellard
1245 367e86e8 bellard
void OPPROTO op_setz_T0_cc(void)
1246 367e86e8 bellard
{
1247 367e86e8 bellard
    int eflags;
1248 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1249 367e86e8 bellard
    T0 = (eflags >> 6) & 1;
1250 367e86e8 bellard
}
1251 367e86e8 bellard
1252 367e86e8 bellard
void OPPROTO op_setbe_T0_cc(void)
1253 367e86e8 bellard
{
1254 367e86e8 bellard
    int eflags;
1255 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1256 367e86e8 bellard
    T0 = (eflags & (CC_Z | CC_C)) != 0;
1257 367e86e8 bellard
}
1258 367e86e8 bellard
1259 367e86e8 bellard
void OPPROTO op_sets_T0_cc(void)
1260 367e86e8 bellard
{
1261 367e86e8 bellard
    int eflags;
1262 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1263 367e86e8 bellard
    T0 = (eflags >> 7) & 1;
1264 367e86e8 bellard
}
1265 367e86e8 bellard
1266 367e86e8 bellard
void OPPROTO op_setp_T0_cc(void)
1267 367e86e8 bellard
{
1268 367e86e8 bellard
    int eflags;
1269 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1270 367e86e8 bellard
    T0 = (eflags >> 2) & 1;
1271 367e86e8 bellard
}
1272 367e86e8 bellard
1273 367e86e8 bellard
void OPPROTO op_setl_T0_cc(void)
1274 367e86e8 bellard
{
1275 367e86e8 bellard
    int eflags;
1276 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1277 367e86e8 bellard
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1278 367e86e8 bellard
}
1279 367e86e8 bellard
1280 367e86e8 bellard
void OPPROTO op_setle_T0_cc(void)
1281 367e86e8 bellard
{
1282 367e86e8 bellard
    int eflags;
1283 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1284 367e86e8 bellard
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1285 367e86e8 bellard
}
1286 367e86e8 bellard
1287 367e86e8 bellard
void OPPROTO op_xor_T0_1(void)
1288 367e86e8 bellard
{
1289 367e86e8 bellard
    T0 ^= 1;
1290 367e86e8 bellard
}
1291 367e86e8 bellard
1292 367e86e8 bellard
void OPPROTO op_set_cc_op(void)
1293 367e86e8 bellard
{
1294 367e86e8 bellard
    CC_OP = PARAM1;
1295 367e86e8 bellard
}
1296 367e86e8 bellard
1297 f631ef9b bellard
#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
1298 f631ef9b bellard
#define FL_UPDATE_MASK16 (TF_MASK)
1299 a4a0ffdb bellard
1300 367e86e8 bellard
void OPPROTO op_movl_eflags_T0(void)
1301 367e86e8 bellard
{
1302 a4a0ffdb bellard
    int eflags;
1303 a4a0ffdb bellard
    eflags = T0;
1304 a4a0ffdb bellard
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1305 a4a0ffdb bellard
    DF = 1 - (2 * ((eflags >> 10) & 1));
1306 a4a0ffdb bellard
    /* we also update some system flags as in user mode */
1307 f631ef9b bellard
    env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | (eflags & FL_UPDATE_MASK32);
1308 f631ef9b bellard
}
1309 f631ef9b bellard
1310 f631ef9b bellard
void OPPROTO op_movw_eflags_T0(void)
1311 f631ef9b bellard
{
1312 f631ef9b bellard
    int eflags;
1313 f631ef9b bellard
    eflags = T0;
1314 f631ef9b bellard
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1315 f631ef9b bellard
    DF = 1 - (2 * ((eflags >> 10) & 1));
1316 f631ef9b bellard
    /* we also update some system flags as in user mode */
1317 f631ef9b bellard
    env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | (eflags & FL_UPDATE_MASK16);
1318 f631ef9b bellard
}
1319 f631ef9b bellard
1320 f631ef9b bellard
/* vm86 version */
1321 f631ef9b bellard
void OPPROTO op_movw_eflags_T0_vm(void)
1322 f631ef9b bellard
{
1323 f631ef9b bellard
    int eflags;
1324 f631ef9b bellard
    eflags = T0;
1325 f631ef9b bellard
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1326 f631ef9b bellard
    DF = 1 - (2 * ((eflags >> 10) & 1));
1327 f631ef9b bellard
    /* we also update some system flags as in user mode */
1328 f631ef9b bellard
    env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1329 f631ef9b bellard
        (eflags & FL_UPDATE_MASK16);
1330 f631ef9b bellard
    if (eflags & IF_MASK) {
1331 f631ef9b bellard
        env->eflags |= VIF_MASK;
1332 f631ef9b bellard
        if (env->eflags & VIP_MASK) {
1333 f631ef9b bellard
            EIP = PARAM1;
1334 f631ef9b bellard
            raise_exception(EXCP0D_GPF);
1335 f631ef9b bellard
        }
1336 f631ef9b bellard
    }
1337 f631ef9b bellard
    FORCE_RET();
1338 f631ef9b bellard
}
1339 f631ef9b bellard
1340 f631ef9b bellard
void OPPROTO op_movl_eflags_T0_vm(void)
1341 f631ef9b bellard
{
1342 f631ef9b bellard
    int eflags;
1343 f631ef9b bellard
    eflags = T0;
1344 f631ef9b bellard
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1345 f631ef9b bellard
    DF = 1 - (2 * ((eflags >> 10) & 1));
1346 f631ef9b bellard
    /* we also update some system flags as in user mode */
1347 f631ef9b bellard
    env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1348 f631ef9b bellard
        (eflags & FL_UPDATE_MASK32);
1349 f631ef9b bellard
    if (eflags & IF_MASK) {
1350 f631ef9b bellard
        env->eflags |= VIF_MASK;
1351 f631ef9b bellard
        if (env->eflags & VIP_MASK) {
1352 f631ef9b bellard
            EIP = PARAM1;
1353 f631ef9b bellard
            raise_exception(EXCP0D_GPF);
1354 f631ef9b bellard
        }
1355 f631ef9b bellard
    }
1356 f631ef9b bellard
    FORCE_RET();
1357 367e86e8 bellard
}
1358 367e86e8 bellard
1359 367e86e8 bellard
/* XXX: compute only O flag */
1360 367e86e8 bellard
void OPPROTO op_movb_eflags_T0(void)
1361 367e86e8 bellard
{
1362 367e86e8 bellard
    int of;
1363 367e86e8 bellard
    of = cc_table[CC_OP].compute_all() & CC_O;
1364 a4a0ffdb bellard
    CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1365 367e86e8 bellard
}
1366 367e86e8 bellard
1367 367e86e8 bellard
void OPPROTO op_movl_T0_eflags(void)
1368 367e86e8 bellard
{
1369 a4a0ffdb bellard
    int eflags;
1370 a4a0ffdb bellard
    eflags = cc_table[CC_OP].compute_all();
1371 a4a0ffdb bellard
    eflags |= (DF & DF_MASK);
1372 a4a0ffdb bellard
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1373 a4a0ffdb bellard
    T0 = eflags;
1374 367e86e8 bellard
}
1375 367e86e8 bellard
1376 f631ef9b bellard
/* vm86 version */
1377 f631ef9b bellard
void OPPROTO op_movl_T0_eflags_vm(void)
1378 f631ef9b bellard
{
1379 f631ef9b bellard
    int eflags;
1380 f631ef9b bellard
    eflags = cc_table[CC_OP].compute_all();
1381 f631ef9b bellard
    eflags |= (DF & DF_MASK);
1382 f631ef9b bellard
    eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1383 f631ef9b bellard
    if (env->eflags & VIF_MASK)
1384 f631ef9b bellard
        eflags |= IF_MASK;
1385 f631ef9b bellard
    T0 = eflags;
1386 f631ef9b bellard
}
1387 f631ef9b bellard
1388 367e86e8 bellard
void OPPROTO op_cld(void)
1389 367e86e8 bellard
{
1390 367e86e8 bellard
    DF = 1;
1391 367e86e8 bellard
}
1392 367e86e8 bellard
1393 367e86e8 bellard
void OPPROTO op_std(void)
1394 367e86e8 bellard
{
1395 367e86e8 bellard
    DF = -1;
1396 367e86e8 bellard
}
1397 367e86e8 bellard
1398 367e86e8 bellard
void OPPROTO op_clc(void)
1399 367e86e8 bellard
{
1400 367e86e8 bellard
    int eflags;
1401 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1402 367e86e8 bellard
    eflags &= ~CC_C;
1403 367e86e8 bellard
    CC_SRC = eflags;
1404 367e86e8 bellard
}
1405 367e86e8 bellard
1406 367e86e8 bellard
void OPPROTO op_stc(void)
1407 367e86e8 bellard
{
1408 367e86e8 bellard
    int eflags;
1409 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1410 367e86e8 bellard
    eflags |= CC_C;
1411 367e86e8 bellard
    CC_SRC = eflags;
1412 367e86e8 bellard
}
1413 367e86e8 bellard
1414 367e86e8 bellard
void OPPROTO op_cmc(void)
1415 367e86e8 bellard
{
1416 367e86e8 bellard
    int eflags;
1417 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1418 367e86e8 bellard
    eflags ^= CC_C;
1419 367e86e8 bellard
    CC_SRC = eflags;
1420 367e86e8 bellard
}
1421 367e86e8 bellard
1422 27362c82 bellard
void OPPROTO op_salc(void)
1423 27362c82 bellard
{
1424 27362c82 bellard
    int cf;
1425 27362c82 bellard
    cf = cc_table[CC_OP].compute_c();
1426 27362c82 bellard
    EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1427 27362c82 bellard
}
1428 27362c82 bellard
1429 367e86e8 bellard
static int compute_all_eflags(void)
1430 367e86e8 bellard
{
1431 367e86e8 bellard
    return CC_SRC;
1432 367e86e8 bellard
}
1433 367e86e8 bellard
1434 367e86e8 bellard
static int compute_c_eflags(void)
1435 367e86e8 bellard
{
1436 367e86e8 bellard
    return CC_SRC & CC_C;
1437 367e86e8 bellard
}
1438 367e86e8 bellard
1439 367e86e8 bellard
static int compute_c_mul(void)
1440 367e86e8 bellard
{
1441 367e86e8 bellard
    int cf;
1442 367e86e8 bellard
    cf = (CC_SRC != 0);
1443 367e86e8 bellard
    return cf;
1444 367e86e8 bellard
}
1445 367e86e8 bellard
1446 367e86e8 bellard
static int compute_all_mul(void)
1447 367e86e8 bellard
{
1448 367e86e8 bellard
    int cf, pf, af, zf, sf, of;
1449 367e86e8 bellard
    cf = (CC_SRC != 0);
1450 367e86e8 bellard
    pf = 0; /* undefined */
1451 367e86e8 bellard
    af = 0; /* undefined */
1452 367e86e8 bellard
    zf = 0; /* undefined */
1453 367e86e8 bellard
    sf = 0; /* undefined */
1454 367e86e8 bellard
    of = cf << 11;
1455 367e86e8 bellard
    return cf | pf | af | zf | sf | of;
1456 367e86e8 bellard
}
1457 367e86e8 bellard
    
1458 367e86e8 bellard
CCTable cc_table[CC_OP_NB] = {
1459 367e86e8 bellard
    [CC_OP_DYNAMIC] = { /* should never happen */ },
1460 367e86e8 bellard
1461 367e86e8 bellard
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1462 367e86e8 bellard
1463 367e86e8 bellard
    [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
1464 367e86e8 bellard
1465 367e86e8 bellard
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1466 367e86e8 bellard
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
1467 367e86e8 bellard
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
1468 367e86e8 bellard
1469 4b74fe1f bellard
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1470 4b74fe1f bellard
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
1471 4b74fe1f bellard
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
1472 4b74fe1f bellard
1473 367e86e8 bellard
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
1474 367e86e8 bellard
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
1475 367e86e8 bellard
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
1476 367e86e8 bellard
    
1477 4b74fe1f bellard
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
1478 4b74fe1f bellard
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
1479 4b74fe1f bellard
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
1480 4b74fe1f bellard
    
1481 367e86e8 bellard
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1482 367e86e8 bellard
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1483 367e86e8 bellard
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1484 367e86e8 bellard
    
1485 4b74fe1f bellard
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1486 4b74fe1f bellard
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1487 367e86e8 bellard
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1488 367e86e8 bellard
    
1489 4b74fe1f bellard
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1490 4b74fe1f bellard
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1491 367e86e8 bellard
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1492 367e86e8 bellard
    
1493 4b74fe1f bellard
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
1494 4b74fe1f bellard
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
1495 367e86e8 bellard
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1496 4b74fe1f bellard
1497 4b74fe1f bellard
    [CC_OP_SARB] = { compute_all_sarb, compute_c_shll },
1498 4b74fe1f bellard
    [CC_OP_SARW] = { compute_all_sarw, compute_c_shll },
1499 4b74fe1f bellard
    [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
1500 367e86e8 bellard
};
1501 927f621e bellard
1502 f631ef9b bellard
/* floating point support. Some of the code for complicated x87
1503 f631ef9b bellard
   functions comes from the LGPL'ed x86 emulator found in the Willows
1504 f631ef9b bellard
   TWIN windows emulator. */
1505 927f621e bellard
1506 927f621e bellard
#ifdef USE_X86LDOUBLE
1507 927f621e bellard
/* use long double functions */
1508 927f621e bellard
#define lrint lrintl
1509 927f621e bellard
#define llrint llrintl
1510 927f621e bellard
#define fabs fabsl
1511 927f621e bellard
#define sin sinl
1512 927f621e bellard
#define cos cosl
1513 927f621e bellard
#define sqrt sqrtl
1514 927f621e bellard
#define pow powl
1515 927f621e bellard
#define log logl
1516 927f621e bellard
#define tan tanl
1517 927f621e bellard
#define atan2 atan2l
1518 927f621e bellard
#define floor floorl
1519 927f621e bellard
#define ceil ceill
1520 927f621e bellard
#define rint rintl
1521 927f621e bellard
#endif
1522 927f621e bellard
1523 927f621e bellard
extern int lrint(CPU86_LDouble x);
1524 927f621e bellard
extern int64_t llrint(CPU86_LDouble x);
1525 927f621e bellard
extern CPU86_LDouble fabs(CPU86_LDouble x);
1526 927f621e bellard
extern CPU86_LDouble sin(CPU86_LDouble x);
1527 927f621e bellard
extern CPU86_LDouble cos(CPU86_LDouble x);
1528 927f621e bellard
extern CPU86_LDouble sqrt(CPU86_LDouble x);
1529 927f621e bellard
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
1530 927f621e bellard
extern CPU86_LDouble log(CPU86_LDouble x);
1531 927f621e bellard
extern CPU86_LDouble tan(CPU86_LDouble x);
1532 927f621e bellard
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
1533 927f621e bellard
extern CPU86_LDouble floor(CPU86_LDouble x);
1534 927f621e bellard
extern CPU86_LDouble ceil(CPU86_LDouble x);
1535 927f621e bellard
extern CPU86_LDouble rint(CPU86_LDouble x);
1536 927f621e bellard
1537 51fe6890 bellard
#if defined(__powerpc__)
1538 51fe6890 bellard
extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);
1539 51fe6890 bellard
1540 51fe6890 bellard
/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
1541 51fe6890 bellard
double qemu_rint(double x)
1542 51fe6890 bellard
{
1543 51fe6890 bellard
    double y = 4503599627370496.0;
1544 51fe6890 bellard
    if (fabs(x) >= y)
1545 51fe6890 bellard
        return x;
1546 51fe6890 bellard
    if (x < 0) 
1547 51fe6890 bellard
        y = -y;
1548 51fe6890 bellard
    y = (x + y) - y;
1549 51fe6890 bellard
    if (y == 0.0)
1550 51fe6890 bellard
        y = copysign(y, x);
1551 51fe6890 bellard
    return y;
1552 51fe6890 bellard
}
1553 51fe6890 bellard
1554 51fe6890 bellard
#define rint qemu_rint
1555 51fe6890 bellard
#endif
1556 51fe6890 bellard
1557 927f621e bellard
#define RC_MASK         0xc00
1558 927f621e bellard
#define RC_NEAR                0x000
1559 927f621e bellard
#define RC_DOWN                0x400
1560 927f621e bellard
#define RC_UP                0x800
1561 927f621e bellard
#define RC_CHOP                0xc00
1562 927f621e bellard
1563 927f621e bellard
#define MAXTAN 9223372036854775808.0
1564 927f621e bellard
1565 927f621e bellard
#ifdef USE_X86LDOUBLE
1566 927f621e bellard
1567 927f621e bellard
/* only for x86 */
1568 927f621e bellard
typedef union {
1569 927f621e bellard
    long double d;
1570 927f621e bellard
    struct {
1571 927f621e bellard
        unsigned long long lower;
1572 927f621e bellard
        unsigned short upper;
1573 927f621e bellard
    } l;
1574 927f621e bellard
} CPU86_LDoubleU;
1575 927f621e bellard
1576 927f621e bellard
/* the following deal with x86 long double-precision numbers */
1577 927f621e bellard
#define MAXEXPD 0x7fff
1578 927f621e bellard
#define EXPBIAS 16383
1579 927f621e bellard
#define EXPD(fp)        (fp.l.upper & 0x7fff)
1580 927f621e bellard
#define SIGND(fp)        ((fp.l.upper) & 0x8000)
1581 927f621e bellard
#define MANTD(fp)       (fp.l.lower)
1582 927f621e bellard
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1583 927f621e bellard
1584 927f621e bellard
#else
1585 927f621e bellard
1586 77f8dd5a bellard
typedef union {
1587 927f621e bellard
    double d;
1588 927f621e bellard
#ifndef WORDS_BIGENDIAN
1589 927f621e bellard
    struct {
1590 927f621e bellard
        unsigned long lower;
1591 927f621e bellard
        long upper;
1592 927f621e bellard
    } l;
1593 927f621e bellard
#else
1594 927f621e bellard
    struct {
1595 927f621e bellard
        long upper;
1596 927f621e bellard
        unsigned long lower;
1597 927f621e bellard
    } l;
1598 927f621e bellard
#endif
1599 927f621e bellard
    long long ll;
1600 927f621e bellard
} CPU86_LDoubleU;
1601 927f621e bellard
1602 927f621e bellard
/* the following deal with IEEE double-precision numbers */
1603 927f621e bellard
#define MAXEXPD 0x7ff
1604 927f621e bellard
#define EXPBIAS 1023
1605 927f621e bellard
#define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)
1606 927f621e bellard
#define SIGND(fp)        ((fp.l.upper) & 0x80000000)
1607 927f621e bellard
#define MANTD(fp)        (fp.ll & ((1LL << 52) - 1))
1608 927f621e bellard
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1609 927f621e bellard
#endif
1610 927f621e bellard
1611 927f621e bellard
/* fp load FT0 */
1612 927f621e bellard
1613 927f621e bellard
void OPPROTO op_flds_FT0_A0(void)
1614 927f621e bellard
{
1615 d014c98c bellard
#ifdef USE_FP_CONVERT
1616 d014c98c bellard
    FP_CONVERT.i32 = ldl((void *)A0);
1617 d014c98c bellard
    FT0 = FP_CONVERT.f;
1618 d014c98c bellard
#else
1619 927f621e bellard
    FT0 = ldfl((void *)A0);
1620 d014c98c bellard
#endif
1621 927f621e bellard
}
1622 927f621e bellard
1623 927f621e bellard
void OPPROTO op_fldl_FT0_A0(void)
1624 927f621e bellard
{
1625 d014c98c bellard
#ifdef USE_FP_CONVERT
1626 d014c98c bellard
    FP_CONVERT.i64 = ldq((void *)A0);
1627 d014c98c bellard
    FT0 = FP_CONVERT.d;
1628 d014c98c bellard
#else
1629 927f621e bellard
    FT0 = ldfq((void *)A0);
1630 d014c98c bellard
#endif
1631 927f621e bellard
}
1632 927f621e bellard
1633 04369ff2 bellard
/* helpers are needed to avoid static constant reference. XXX: find a better way */
1634 04369ff2 bellard
#ifdef USE_INT_TO_FLOAT_HELPERS
1635 04369ff2 bellard
1636 04369ff2 bellard
void helper_fild_FT0_A0(void)
1637 04369ff2 bellard
{
1638 04369ff2 bellard
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1639 04369ff2 bellard
}
1640 04369ff2 bellard
1641 04369ff2 bellard
void helper_fildl_FT0_A0(void)
1642 04369ff2 bellard
{
1643 04369ff2 bellard
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1644 04369ff2 bellard
}
1645 04369ff2 bellard
1646 04369ff2 bellard
void helper_fildll_FT0_A0(void)
1647 04369ff2 bellard
{
1648 04369ff2 bellard
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1649 04369ff2 bellard
}
1650 04369ff2 bellard
1651 04369ff2 bellard
void OPPROTO op_fild_FT0_A0(void)
1652 04369ff2 bellard
{
1653 04369ff2 bellard
    helper_fild_FT0_A0();
1654 04369ff2 bellard
}
1655 04369ff2 bellard
1656 04369ff2 bellard
void OPPROTO op_fildl_FT0_A0(void)
1657 04369ff2 bellard
{
1658 04369ff2 bellard
    helper_fildl_FT0_A0();
1659 04369ff2 bellard
}
1660 04369ff2 bellard
1661 04369ff2 bellard
void OPPROTO op_fildll_FT0_A0(void)
1662 04369ff2 bellard
{
1663 04369ff2 bellard
    helper_fildll_FT0_A0();
1664 04369ff2 bellard
}
1665 04369ff2 bellard
1666 04369ff2 bellard
#else
1667 04369ff2 bellard
1668 927f621e bellard
void OPPROTO op_fild_FT0_A0(void)
1669 927f621e bellard
{
1670 d014c98c bellard
#ifdef USE_FP_CONVERT
1671 d014c98c bellard
    FP_CONVERT.i32 = ldsw((void *)A0);
1672 d014c98c bellard
    FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1673 d014c98c bellard
#else
1674 927f621e bellard
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1675 d014c98c bellard
#endif
1676 927f621e bellard
}
1677 927f621e bellard
1678 927f621e bellard
void OPPROTO op_fildl_FT0_A0(void)
1679 927f621e bellard
{
1680 d014c98c bellard
#ifdef USE_FP_CONVERT
1681 d014c98c bellard
    FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
1682 d014c98c bellard
    FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1683 d014c98c bellard
#else
1684 927f621e bellard
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1685 d014c98c bellard
#endif
1686 927f621e bellard
}
1687 927f621e bellard
1688 927f621e bellard
void OPPROTO op_fildll_FT0_A0(void)
1689 927f621e bellard
{
1690 d014c98c bellard
#ifdef USE_FP_CONVERT
1691 d014c98c bellard
    FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
1692 d014c98c bellard
    FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1693 d014c98c bellard
#else
1694 927f621e bellard
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1695 d014c98c bellard
#endif
1696 927f621e bellard
}
1697 04369ff2 bellard
#endif
1698 927f621e bellard
1699 927f621e bellard
/* fp load ST0 */
1700 927f621e bellard
1701 927f621e bellard
void OPPROTO op_flds_ST0_A0(void)
1702 927f621e bellard
{
1703 d014c98c bellard
#ifdef USE_FP_CONVERT
1704 d014c98c bellard
    FP_CONVERT.i32 = ldl((void *)A0);
1705 d014c98c bellard
    ST0 = FP_CONVERT.f;
1706 d014c98c bellard
#else
1707 927f621e bellard
    ST0 = ldfl((void *)A0);
1708 d014c98c bellard
#endif
1709 927f621e bellard
}
1710 927f621e bellard
1711 927f621e bellard
void OPPROTO op_fldl_ST0_A0(void)
1712 927f621e bellard
{
1713 d014c98c bellard
#ifdef USE_FP_CONVERT
1714 d014c98c bellard
    FP_CONVERT.i64 = ldq((void *)A0);
1715 d014c98c bellard
    ST0 = FP_CONVERT.d;
1716 d014c98c bellard
#else
1717 927f621e bellard
    ST0 = ldfq((void *)A0);
1718 d014c98c bellard
#endif
1719 927f621e bellard
}
1720 927f621e bellard
1721 77f8dd5a bellard
#ifdef USE_X86LDOUBLE
1722 77f8dd5a bellard
void OPPROTO op_fldt_ST0_A0(void)
1723 77f8dd5a bellard
{
1724 77f8dd5a bellard
    ST0 = *(long double *)A0;
1725 77f8dd5a bellard
}
1726 77f8dd5a bellard
#else
1727 77f8dd5a bellard
void helper_fldt_ST0_A0(void)
1728 77f8dd5a bellard
{
1729 77f8dd5a bellard
    CPU86_LDoubleU temp;
1730 77f8dd5a bellard
    int upper, e;
1731 77f8dd5a bellard
    /* mantissa */
1732 77f8dd5a bellard
    upper = lduw((uint8_t *)A0 + 8);
1733 77f8dd5a bellard
    /* XXX: handle overflow ? */
1734 77f8dd5a bellard
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1735 77f8dd5a bellard
    e |= (upper >> 4) & 0x800; /* sign */
1736 77f8dd5a bellard
    temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
1737 77f8dd5a bellard
    ST0 = temp.d;
1738 77f8dd5a bellard
}
1739 77f8dd5a bellard
1740 77f8dd5a bellard
void OPPROTO op_fldt_ST0_A0(void)
1741 77f8dd5a bellard
{
1742 77f8dd5a bellard
    helper_fldt_ST0_A0();
1743 77f8dd5a bellard
}
1744 77f8dd5a bellard
#endif
1745 77f8dd5a bellard
1746 04369ff2 bellard
/* helpers are needed to avoid static constant reference. XXX: find a better way */
1747 04369ff2 bellard
#ifdef USE_INT_TO_FLOAT_HELPERS
1748 04369ff2 bellard
1749 04369ff2 bellard
void helper_fild_ST0_A0(void)
1750 04369ff2 bellard
{
1751 04369ff2 bellard
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1752 04369ff2 bellard
}
1753 04369ff2 bellard
1754 04369ff2 bellard
void helper_fildl_ST0_A0(void)
1755 04369ff2 bellard
{
1756 04369ff2 bellard
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1757 04369ff2 bellard
}
1758 04369ff2 bellard
1759 04369ff2 bellard
void helper_fildll_ST0_A0(void)
1760 04369ff2 bellard
{
1761 04369ff2 bellard
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1762 04369ff2 bellard
}
1763 04369ff2 bellard
1764 04369ff2 bellard
void OPPROTO op_fild_ST0_A0(void)
1765 04369ff2 bellard
{
1766 04369ff2 bellard
    helper_fild_ST0_A0();
1767 04369ff2 bellard
}
1768 04369ff2 bellard
1769 04369ff2 bellard
void OPPROTO op_fildl_ST0_A0(void)
1770 04369ff2 bellard
{
1771 04369ff2 bellard
    helper_fildl_ST0_A0();
1772 04369ff2 bellard
}
1773 04369ff2 bellard
1774 04369ff2 bellard
void OPPROTO op_fildll_ST0_A0(void)
1775 04369ff2 bellard
{
1776 04369ff2 bellard
    helper_fildll_ST0_A0();
1777 04369ff2 bellard
}
1778 04369ff2 bellard
1779 04369ff2 bellard
#else
1780 04369ff2 bellard
1781 927f621e bellard
void OPPROTO op_fild_ST0_A0(void)
1782 927f621e bellard
{
1783 d014c98c bellard
#ifdef USE_FP_CONVERT
1784 d014c98c bellard
    FP_CONVERT.i32 = ldsw((void *)A0);
1785 d014c98c bellard
    ST0 = (CPU86_LDouble)FP_CONVERT.i32;
1786 d014c98c bellard
#else
1787 927f621e bellard
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1788 d014c98c bellard
#endif
1789 927f621e bellard
}
1790 927f621e bellard
1791 927f621e bellard
void OPPROTO op_fildl_ST0_A0(void)
1792 927f621e bellard
{
1793 d014c98c bellard
#ifdef USE_FP_CONVERT
1794 d014c98c bellard
    FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
1795 d014c98c bellard
    ST0 = (CPU86_LDouble)FP_CONVERT.i32;
1796 d014c98c bellard
#else
1797 927f621e bellard
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1798 d014c98c bellard
#endif
1799 927f621e bellard
}
1800 927f621e bellard
1801 927f621e bellard
void OPPROTO op_fildll_ST0_A0(void)
1802 927f621e bellard
{
1803 d014c98c bellard
#ifdef USE_FP_CONVERT
1804 d014c98c bellard
    FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
1805 d014c98c bellard
    ST0 = (CPU86_LDouble)FP_CONVERT.i64;
1806 d014c98c bellard
#else
1807 927f621e bellard
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1808 d014c98c bellard
#endif
1809 927f621e bellard
}
1810 927f621e bellard
1811 04369ff2 bellard
#endif
1812 04369ff2 bellard
1813 927f621e bellard
/* fp store */
1814 927f621e bellard
1815 927f621e bellard
void OPPROTO op_fsts_ST0_A0(void)
1816 927f621e bellard
{
1817 d014c98c bellard
#ifdef USE_FP_CONVERT
1818 d014c98c bellard
    FP_CONVERT.d = ST0;
1819 d014c98c bellard
    stfl((void *)A0, FP_CONVERT.f);
1820 d014c98c bellard
#else
1821 927f621e bellard
    stfl((void *)A0, (float)ST0);
1822 d014c98c bellard
#endif
1823 927f621e bellard
}
1824 927f621e bellard
1825 927f621e bellard
void OPPROTO op_fstl_ST0_A0(void)
1826 927f621e bellard
{
1827 77f8dd5a bellard
    stfq((void *)A0, (double)ST0);
1828 927f621e bellard
}
1829 927f621e bellard
1830 77f8dd5a bellard
#ifdef USE_X86LDOUBLE
1831 77f8dd5a bellard
void OPPROTO op_fstt_ST0_A0(void)
1832 77f8dd5a bellard
{
1833 77f8dd5a bellard
    *(long double *)A0 = ST0;
1834 77f8dd5a bellard
}
1835 77f8dd5a bellard
#else
1836 77f8dd5a bellard
void helper_fstt_ST0_A0(void)
1837 77f8dd5a bellard
{
1838 77f8dd5a bellard
    CPU86_LDoubleU temp;
1839 77f8dd5a bellard
    int e;
1840 77f8dd5a bellard
    temp.d = ST0;
1841 77f8dd5a bellard
    /* mantissa */
1842 77f8dd5a bellard
    stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63));
1843 77f8dd5a bellard
    /* exponent + sign */
1844 77f8dd5a bellard
    e = EXPD(temp) - EXPBIAS + 16383;
1845 77f8dd5a bellard
    e |= SIGND(temp) >> 16;
1846 77f8dd5a bellard
    stw((uint8_t *)A0 + 8, e);
1847 77f8dd5a bellard
}
1848 77f8dd5a bellard
1849 77f8dd5a bellard
void OPPROTO op_fstt_ST0_A0(void)
1850 77f8dd5a bellard
{
1851 77f8dd5a bellard
    helper_fstt_ST0_A0();
1852 77f8dd5a bellard
}
1853 77f8dd5a bellard
#endif
1854 77f8dd5a bellard
1855 927f621e bellard
void OPPROTO op_fist_ST0_A0(void)
1856 927f621e bellard
{
1857 d014c98c bellard
#if defined(__sparc__) && !defined(__sparc_v9__)
1858 d014c98c bellard
    register CPU86_LDouble d asm("o0");
1859 d014c98c bellard
#else
1860 d014c98c bellard
    CPU86_LDouble d;
1861 d014c98c bellard
#endif
1862 927f621e bellard
    int val;
1863 d014c98c bellard
1864 d014c98c bellard
    d = ST0;
1865 d014c98c bellard
    val = lrint(d);
1866 927f621e bellard
    stw((void *)A0, val);
1867 927f621e bellard
}
1868 927f621e bellard
1869 927f621e bellard
void OPPROTO op_fistl_ST0_A0(void)
1870 927f621e bellard
{
1871 d014c98c bellard
#if defined(__sparc__) && !defined(__sparc_v9__)
1872 d014c98c bellard
    register CPU86_LDouble d asm("o0");
1873 d014c98c bellard
#else
1874 d014c98c bellard
    CPU86_LDouble d;
1875 d014c98c bellard
#endif
1876 927f621e bellard
    int val;
1877 d014c98c bellard
1878 d014c98c bellard
    d = ST0;
1879 d014c98c bellard
    val = lrint(d);
1880 927f621e bellard
    stl((void *)A0, val);
1881 927f621e bellard
}
1882 927f621e bellard
1883 927f621e bellard
void OPPROTO op_fistll_ST0_A0(void)
1884 927f621e bellard
{
1885 d014c98c bellard
#if defined(__sparc__) && !defined(__sparc_v9__)
1886 d014c98c bellard
    register CPU86_LDouble d asm("o0");
1887 d014c98c bellard
#else
1888 d014c98c bellard
    CPU86_LDouble d;
1889 d014c98c bellard
#endif
1890 927f621e bellard
    int64_t val;
1891 d014c98c bellard
1892 d014c98c bellard
    d = ST0;
1893 d014c98c bellard
    val = llrint(d);
1894 927f621e bellard
    stq((void *)A0, val);
1895 927f621e bellard
}
1896 927f621e bellard
1897 77f8dd5a bellard
/* BCD ops */
1898 77f8dd5a bellard
1899 77f8dd5a bellard
#define MUL10(iv) ( iv + iv + (iv << 3) )
1900 77f8dd5a bellard
1901 77f8dd5a bellard
void helper_fbld_ST0_A0(void)
1902 77f8dd5a bellard
{
1903 77f8dd5a bellard
    uint8_t *seg;
1904 77f8dd5a bellard
    CPU86_LDouble fpsrcop;
1905 77f8dd5a bellard
    int m32i;
1906 77f8dd5a bellard
    unsigned int v;
1907 77f8dd5a bellard
1908 77f8dd5a bellard
    /* in this code, seg/m32i will be used as temporary ptr/int */
1909 77f8dd5a bellard
    seg = (uint8_t *)A0 + 8;
1910 77f8dd5a bellard
    v = ldub(seg--);
1911 77f8dd5a bellard
    /* XXX: raise exception */
1912 77f8dd5a bellard
    if (v != 0)
1913 77f8dd5a bellard
        return;
1914 77f8dd5a bellard
    v = ldub(seg--);
1915 77f8dd5a bellard
    /* XXX: raise exception */
1916 77f8dd5a bellard
    if ((v & 0xf0) != 0)
1917 77f8dd5a bellard
        return;
1918 77f8dd5a bellard
    m32i = v;  /* <-- d14 */
1919 77f8dd5a bellard
    v = ldub(seg--);
1920 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
1921 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
1922 77f8dd5a bellard
    v = ldub(seg--);
1923 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
1924 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
1925 77f8dd5a bellard
    v = ldub(seg--);
1926 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
1927 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
1928 77f8dd5a bellard
    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
1929 77f8dd5a bellard
1930 77f8dd5a bellard
    v = ldub(seg--);
1931 77f8dd5a bellard
    m32i = (v >> 4);  /* <-- d7 */
1932 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
1933 77f8dd5a bellard
    v = ldub(seg--);
1934 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
1935 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
1936 77f8dd5a bellard
    v = ldub(seg--);
1937 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
1938 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
1939 77f8dd5a bellard
    v = ldub(seg);
1940 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
1941 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
1942 77f8dd5a bellard
    fpsrcop += ((CPU86_LDouble)m32i);
1943 77f8dd5a bellard
    if ( ldub(seg+9) & 0x80 )
1944 77f8dd5a bellard
        fpsrcop = -fpsrcop;
1945 77f8dd5a bellard
    ST0 = fpsrcop;
1946 77f8dd5a bellard
}
1947 77f8dd5a bellard
1948 77f8dd5a bellard
void OPPROTO op_fbld_ST0_A0(void)
1949 77f8dd5a bellard
{
1950 77f8dd5a bellard
    helper_fbld_ST0_A0();
1951 77f8dd5a bellard
}
1952 77f8dd5a bellard
1953 77f8dd5a bellard
void helper_fbst_ST0_A0(void)
1954 77f8dd5a bellard
{
1955 77f8dd5a bellard
    CPU86_LDouble fptemp;
1956 77f8dd5a bellard
    CPU86_LDouble fpsrcop;
1957 77f8dd5a bellard
    int v;
1958 77f8dd5a bellard
    uint8_t *mem_ref, *mem_end;
1959 77f8dd5a bellard
1960 77f8dd5a bellard
    fpsrcop = rint(ST0);
1961 77f8dd5a bellard
    mem_ref = (uint8_t *)A0;
1962 77f8dd5a bellard
    mem_end = mem_ref + 8;
1963 77f8dd5a bellard
    if ( fpsrcop < 0.0 ) {
1964 77f8dd5a bellard
        stw(mem_end, 0x8000);
1965 77f8dd5a bellard
        fpsrcop = -fpsrcop;
1966 77f8dd5a bellard
    } else {
1967 77f8dd5a bellard
        stw(mem_end, 0x0000);
1968 77f8dd5a bellard
    }
1969 77f8dd5a bellard
    while (mem_ref < mem_end) {
1970 77f8dd5a bellard
        if (fpsrcop == 0.0)
1971 77f8dd5a bellard
            break;
1972 77f8dd5a bellard
        fptemp = floor(fpsrcop/10.0);
1973 77f8dd5a bellard
        v = ((int)(fpsrcop - fptemp*10.0));
1974 77f8dd5a bellard
        if  (fptemp == 0.0)  { 
1975 77f8dd5a bellard
            stb(mem_ref++, v); 
1976 77f8dd5a bellard
            break; 
1977 77f8dd5a bellard
        }
1978 77f8dd5a bellard
        fpsrcop = fptemp;
1979 77f8dd5a bellard
        fptemp = floor(fpsrcop/10.0);
1980 77f8dd5a bellard
        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
1981 77f8dd5a bellard
        stb(mem_ref++, v);
1982 77f8dd5a bellard
        fpsrcop = fptemp;
1983 77f8dd5a bellard
    }
1984 77f8dd5a bellard
    while (mem_ref < mem_end) {
1985 77f8dd5a bellard
        stb(mem_ref++, 0);
1986 77f8dd5a bellard
    }
1987 77f8dd5a bellard
}
1988 77f8dd5a bellard
1989 77f8dd5a bellard
void OPPROTO op_fbst_ST0_A0(void)
1990 77f8dd5a bellard
{
1991 77f8dd5a bellard
    helper_fbst_ST0_A0();
1992 77f8dd5a bellard
}
1993 77f8dd5a bellard
1994 927f621e bellard
/* FPU move */
1995 927f621e bellard
1996 927f621e bellard
static inline void fpush(void)
1997 927f621e bellard
{
1998 927f621e bellard
    env->fpstt = (env->fpstt - 1) & 7;
1999 927f621e bellard
    env->fptags[env->fpstt] = 0; /* validate stack entry */
2000 927f621e bellard
}
2001 927f621e bellard
2002 927f621e bellard
static inline void fpop(void)
2003 927f621e bellard
{
2004 927f621e bellard
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
2005 927f621e bellard
    env->fpstt = (env->fpstt + 1) & 7;
2006 927f621e bellard
}
2007 927f621e bellard
2008 927f621e bellard
void OPPROTO op_fpush(void)
2009 927f621e bellard
{
2010 927f621e bellard
    fpush();
2011 927f621e bellard
}
2012 927f621e bellard
2013 927f621e bellard
void OPPROTO op_fpop(void)
2014 927f621e bellard
{
2015 927f621e bellard
    fpop();
2016 927f621e bellard
}
2017 927f621e bellard
2018 927f621e bellard
void OPPROTO op_fdecstp(void)
2019 927f621e bellard
{
2020 927f621e bellard
    env->fpstt = (env->fpstt - 1) & 7;
2021 927f621e bellard
    env->fpus &= (~0x4700);
2022 927f621e bellard
}
2023 927f621e bellard
2024 927f621e bellard
void OPPROTO op_fincstp(void)
2025 927f621e bellard
{
2026 927f621e bellard
    env->fpstt = (env->fpstt + 1) & 7;
2027 927f621e bellard
    env->fpus &= (~0x4700);
2028 927f621e bellard
}
2029 927f621e bellard
2030 927f621e bellard
void OPPROTO op_fmov_ST0_FT0(void)
2031 927f621e bellard
{
2032 927f621e bellard
    ST0 = FT0;
2033 927f621e bellard
}
2034 927f621e bellard
2035 927f621e bellard
void OPPROTO op_fmov_FT0_STN(void)
2036 927f621e bellard
{
2037 927f621e bellard
    FT0 = ST(PARAM1);
2038 927f621e bellard
}
2039 927f621e bellard
2040 927f621e bellard
void OPPROTO op_fmov_ST0_STN(void)
2041 927f621e bellard
{
2042 927f621e bellard
    ST0 = ST(PARAM1);
2043 927f621e bellard
}
2044 927f621e bellard
2045 927f621e bellard
void OPPROTO op_fmov_STN_ST0(void)
2046 927f621e bellard
{
2047 927f621e bellard
    ST(PARAM1) = ST0;
2048 927f621e bellard
}
2049 927f621e bellard
2050 927f621e bellard
void OPPROTO op_fxchg_ST0_STN(void)
2051 927f621e bellard
{
2052 927f621e bellard
    CPU86_LDouble tmp;
2053 927f621e bellard
    tmp = ST(PARAM1);
2054 927f621e bellard
    ST(PARAM1) = ST0;
2055 927f621e bellard
    ST0 = tmp;
2056 927f621e bellard
}
2057 927f621e bellard
2058 927f621e bellard
/* FPU operations */
2059 927f621e bellard
2060 927f621e bellard
/* XXX: handle nans */
2061 927f621e bellard
void OPPROTO op_fcom_ST0_FT0(void)
2062 927f621e bellard
{
2063 927f621e bellard
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
2064 927f621e bellard
    if (ST0 < FT0)
2065 927f621e bellard
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
2066 927f621e bellard
    else if (ST0 == FT0)
2067 927f621e bellard
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
2068 927f621e bellard
    FORCE_RET();
2069 927f621e bellard
}
2070 927f621e bellard
2071 77f8dd5a bellard
/* XXX: handle nans */
2072 77f8dd5a bellard
void OPPROTO op_fucom_ST0_FT0(void)
2073 77f8dd5a bellard
{
2074 77f8dd5a bellard
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
2075 77f8dd5a bellard
    if (ST0 < FT0)
2076 77f8dd5a bellard
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
2077 77f8dd5a bellard
    else if (ST0 == FT0)
2078 77f8dd5a bellard
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
2079 77f8dd5a bellard
    FORCE_RET();
2080 77f8dd5a bellard
}
2081 77f8dd5a bellard
2082 927f621e bellard
void OPPROTO op_fadd_ST0_FT0(void)
2083 927f621e bellard
{
2084 927f621e bellard
    ST0 += FT0;
2085 927f621e bellard
}
2086 927f621e bellard
2087 927f621e bellard
void OPPROTO op_fmul_ST0_FT0(void)
2088 927f621e bellard
{
2089 927f621e bellard
    ST0 *= FT0;
2090 927f621e bellard
}
2091 927f621e bellard
2092 927f621e bellard
void OPPROTO op_fsub_ST0_FT0(void)
2093 927f621e bellard
{
2094 927f621e bellard
    ST0 -= FT0;
2095 927f621e bellard
}
2096 927f621e bellard
2097 927f621e bellard
void OPPROTO op_fsubr_ST0_FT0(void)
2098 927f621e bellard
{
2099 927f621e bellard
    ST0 = FT0 - ST0;
2100 927f621e bellard
}
2101 927f621e bellard
2102 927f621e bellard
void OPPROTO op_fdiv_ST0_FT0(void)
2103 927f621e bellard
{
2104 927f621e bellard
    ST0 /= FT0;
2105 927f621e bellard
}
2106 927f621e bellard
2107 927f621e bellard
void OPPROTO op_fdivr_ST0_FT0(void)
2108 927f621e bellard
{
2109 927f621e bellard
    ST0 = FT0 / ST0;
2110 927f621e bellard
}
2111 927f621e bellard
2112 927f621e bellard
/* fp operations between STN and ST0 */
2113 927f621e bellard
2114 927f621e bellard
void OPPROTO op_fadd_STN_ST0(void)
2115 927f621e bellard
{
2116 927f621e bellard
    ST(PARAM1) += ST0;
2117 927f621e bellard
}
2118 927f621e bellard
2119 927f621e bellard
void OPPROTO op_fmul_STN_ST0(void)
2120 927f621e bellard
{
2121 927f621e bellard
    ST(PARAM1) *= ST0;
2122 927f621e bellard
}
2123 927f621e bellard
2124 927f621e bellard
void OPPROTO op_fsub_STN_ST0(void)
2125 927f621e bellard
{
2126 927f621e bellard
    ST(PARAM1) -= ST0;
2127 927f621e bellard
}
2128 927f621e bellard
2129 927f621e bellard
void OPPROTO op_fsubr_STN_ST0(void)
2130 927f621e bellard
{
2131 927f621e bellard
    CPU86_LDouble *p;
2132 927f621e bellard
    p = &ST(PARAM1);
2133 927f621e bellard
    *p = ST0 - *p;
2134 927f621e bellard
}
2135 927f621e bellard
2136 927f621e bellard
void OPPROTO op_fdiv_STN_ST0(void)
2137 927f621e bellard
{
2138 927f621e bellard
    ST(PARAM1) /= ST0;
2139 927f621e bellard
}
2140 927f621e bellard
2141 927f621e bellard
void OPPROTO op_fdivr_STN_ST0(void)
2142 927f621e bellard
{
2143 927f621e bellard
    CPU86_LDouble *p;
2144 927f621e bellard
    p = &ST(PARAM1);
2145 927f621e bellard
    *p = ST0 / *p;
2146 927f621e bellard
}
2147 927f621e bellard
2148 927f621e bellard
/* misc FPU operations */
2149 927f621e bellard
void OPPROTO op_fchs_ST0(void)
2150 927f621e bellard
{
2151 927f621e bellard
    ST0 = -ST0;
2152 927f621e bellard
}
2153 927f621e bellard
2154 927f621e bellard
void OPPROTO op_fabs_ST0(void)
2155 927f621e bellard
{
2156 927f621e bellard
    ST0 = fabs(ST0);
2157 927f621e bellard
}
2158 927f621e bellard
2159 77f8dd5a bellard
void helper_fxam_ST0(void)
2160 927f621e bellard
{
2161 927f621e bellard
    CPU86_LDoubleU temp;
2162 927f621e bellard
    int expdif;
2163 927f621e bellard
2164 927f621e bellard
    temp.d = ST0;
2165 927f621e bellard
2166 927f621e bellard
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2167 927f621e bellard
    if (SIGND(temp))
2168 927f621e bellard
        env->fpus |= 0x200; /* C1 <-- 1 */
2169 927f621e bellard
2170 927f621e bellard
    expdif = EXPD(temp);
2171 927f621e bellard
    if (expdif == MAXEXPD) {
2172 927f621e bellard
        if (MANTD(temp) == 0)
2173 927f621e bellard
            env->fpus |=  0x500 /*Infinity*/;
2174 927f621e bellard
        else
2175 927f621e bellard
            env->fpus |=  0x100 /*NaN*/;
2176 927f621e bellard
    } else if (expdif == 0) {
2177 927f621e bellard
        if (MANTD(temp) == 0)
2178 927f621e bellard
            env->fpus |=  0x4000 /*Zero*/;
2179 927f621e bellard
        else
2180 927f621e bellard
            env->fpus |= 0x4400 /*Denormal*/;
2181 927f621e bellard
    } else {
2182 927f621e bellard
        env->fpus |= 0x400;
2183 927f621e bellard
    }
2184 77f8dd5a bellard
}
2185 77f8dd5a bellard
2186 77f8dd5a bellard
void OPPROTO op_fxam_ST0(void)
2187 77f8dd5a bellard
{
2188 77f8dd5a bellard
    helper_fxam_ST0();
2189 927f621e bellard
}
2190 927f621e bellard
2191 927f621e bellard
void OPPROTO op_fld1_ST0(void)
2192 927f621e bellard
{
2193 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[1];
2194 927f621e bellard
}
2195 927f621e bellard
2196 77f8dd5a bellard
void OPPROTO op_fldl2t_ST0(void)
2197 927f621e bellard
{
2198 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[6];
2199 927f621e bellard
}
2200 927f621e bellard
2201 77f8dd5a bellard
void OPPROTO op_fldl2e_ST0(void)
2202 927f621e bellard
{
2203 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[5];
2204 927f621e bellard
}
2205 927f621e bellard
2206 927f621e bellard
void OPPROTO op_fldpi_ST0(void)
2207 927f621e bellard
{
2208 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[2];
2209 927f621e bellard
}
2210 927f621e bellard
2211 927f621e bellard
void OPPROTO op_fldlg2_ST0(void)
2212 927f621e bellard
{
2213 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[3];
2214 927f621e bellard
}
2215 927f621e bellard
2216 927f621e bellard
void OPPROTO op_fldln2_ST0(void)
2217 927f621e bellard
{
2218 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[4];
2219 927f621e bellard
}
2220 927f621e bellard
2221 927f621e bellard
void OPPROTO op_fldz_ST0(void)
2222 927f621e bellard
{
2223 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[0];
2224 927f621e bellard
}
2225 927f621e bellard
2226 927f621e bellard
void OPPROTO op_fldz_FT0(void)
2227 927f621e bellard
{
2228 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[0];
2229 927f621e bellard
}
2230 927f621e bellard
2231 927f621e bellard
void helper_f2xm1(void)
2232 927f621e bellard
{
2233 927f621e bellard
    ST0 = pow(2.0,ST0) - 1.0;
2234 927f621e bellard
}
2235 927f621e bellard
2236 927f621e bellard
void helper_fyl2x(void)
2237 927f621e bellard
{
2238 927f621e bellard
    CPU86_LDouble fptemp;
2239 927f621e bellard
    
2240 927f621e bellard
    fptemp = ST0;
2241 927f621e bellard
    if (fptemp>0.0){
2242 927f621e bellard
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
2243 927f621e bellard
        ST1 *= fptemp;
2244 927f621e bellard
        fpop();
2245 927f621e bellard
    } else { 
2246 927f621e bellard
        env->fpus &= (~0x4700);
2247 927f621e bellard
        env->fpus |= 0x400;
2248 927f621e bellard
    }
2249 927f621e bellard
}
2250 927f621e bellard
2251 927f621e bellard
void helper_fptan(void)
2252 927f621e bellard
{
2253 927f621e bellard
    CPU86_LDouble fptemp;
2254 927f621e bellard
2255 927f621e bellard
    fptemp = ST0;
2256 927f621e bellard
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2257 927f621e bellard
        env->fpus |= 0x400;
2258 927f621e bellard
    } else {
2259 927f621e bellard
        ST0 = tan(fptemp);
2260 927f621e bellard
        fpush();
2261 927f621e bellard
        ST0 = 1.0;
2262 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2263 927f621e bellard
        /* the above code is for  |arg| < 2**52 only */
2264 927f621e bellard
    }
2265 927f621e bellard
}
2266 927f621e bellard
2267 927f621e bellard
void helper_fpatan(void)
2268 927f621e bellard
{
2269 927f621e bellard
    CPU86_LDouble fptemp, fpsrcop;
2270 927f621e bellard
2271 927f621e bellard
    fpsrcop = ST1;
2272 927f621e bellard
    fptemp = ST0;
2273 927f621e bellard
    ST1 = atan2(fpsrcop,fptemp);
2274 927f621e bellard
    fpop();
2275 927f621e bellard
}
2276 927f621e bellard
2277 927f621e bellard
void helper_fxtract(void)
2278 927f621e bellard
{
2279 927f621e bellard
    CPU86_LDoubleU temp;
2280 927f621e bellard
    unsigned int expdif;
2281 927f621e bellard
2282 927f621e bellard
    temp.d = ST0;
2283 927f621e bellard
    expdif = EXPD(temp) - EXPBIAS;
2284 927f621e bellard
    /*DP exponent bias*/
2285 927f621e bellard
    ST0 = expdif;
2286 927f621e bellard
    fpush();
2287 927f621e bellard
    BIASEXPONENT(temp);
2288 927f621e bellard
    ST0 = temp.d;
2289 927f621e bellard
}
2290 927f621e bellard
2291 927f621e bellard
void helper_fprem1(void)
2292 927f621e bellard
{
2293 927f621e bellard
    CPU86_LDouble dblq, fpsrcop, fptemp;
2294 927f621e bellard
    CPU86_LDoubleU fpsrcop1, fptemp1;
2295 927f621e bellard
    int expdif;
2296 927f621e bellard
    int q;
2297 927f621e bellard
2298 927f621e bellard
    fpsrcop = ST0;
2299 927f621e bellard
    fptemp = ST1;
2300 927f621e bellard
    fpsrcop1.d = fpsrcop;
2301 927f621e bellard
    fptemp1.d = fptemp;
2302 927f621e bellard
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2303 927f621e bellard
    if (expdif < 53) {
2304 927f621e bellard
        dblq = fpsrcop / fptemp;
2305 927f621e bellard
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2306 927f621e bellard
        ST0 = fpsrcop - fptemp*dblq;
2307 927f621e bellard
        q = (int)dblq; /* cutting off top bits is assumed here */
2308 927f621e bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2309 927f621e bellard
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
2310 927f621e bellard
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2311 927f621e bellard
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2312 927f621e bellard
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2313 927f621e bellard
    } else {
2314 927f621e bellard
        env->fpus |= 0x400;  /* C2 <-- 1 */
2315 927f621e bellard
        fptemp = pow(2.0, expdif-50);
2316 927f621e bellard
        fpsrcop = (ST0 / ST1) / fptemp;
2317 927f621e bellard
        /* fpsrcop = integer obtained by rounding to the nearest */
2318 927f621e bellard
        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
2319 927f621e bellard
            floor(fpsrcop): ceil(fpsrcop);
2320 927f621e bellard
        ST0 -= (ST1 * fpsrcop * fptemp);
2321 927f621e bellard
    }
2322 927f621e bellard
}
2323 927f621e bellard
2324 927f621e bellard
void helper_fprem(void)
2325 927f621e bellard
{
2326 927f621e bellard
    CPU86_LDouble dblq, fpsrcop, fptemp;
2327 927f621e bellard
    CPU86_LDoubleU fpsrcop1, fptemp1;
2328 927f621e bellard
    int expdif;
2329 927f621e bellard
    int q;
2330 927f621e bellard
    
2331 927f621e bellard
    fpsrcop = ST0;
2332 927f621e bellard
    fptemp = ST1;
2333 927f621e bellard
    fpsrcop1.d = fpsrcop;
2334 927f621e bellard
    fptemp1.d = fptemp;
2335 927f621e bellard
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2336 927f621e bellard
    if ( expdif < 53 ) {
2337 927f621e bellard
        dblq = fpsrcop / fptemp;
2338 927f621e bellard
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2339 927f621e bellard
        ST0 = fpsrcop - fptemp*dblq;
2340 927f621e bellard
        q = (int)dblq; /* cutting off top bits is assumed here */
2341 927f621e bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2342 927f621e bellard
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
2343 927f621e bellard
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2344 927f621e bellard
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2345 927f621e bellard
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2346 927f621e bellard
    } else {
2347 927f621e bellard
        env->fpus |= 0x400;  /* C2 <-- 1 */
2348 927f621e bellard
        fptemp = pow(2.0, expdif-50);
2349 927f621e bellard
        fpsrcop = (ST0 / ST1) / fptemp;
2350 927f621e bellard
        /* fpsrcop = integer obtained by chopping */
2351 927f621e bellard
        fpsrcop = (fpsrcop < 0.0)?
2352 927f621e bellard
            -(floor(fabs(fpsrcop))): floor(fpsrcop);
2353 927f621e bellard
        ST0 -= (ST1 * fpsrcop * fptemp);
2354 927f621e bellard
    }
2355 927f621e bellard
}
2356 927f621e bellard
2357 927f621e bellard
void helper_fyl2xp1(void)
2358 927f621e bellard
{
2359 927f621e bellard
    CPU86_LDouble fptemp;
2360 927f621e bellard
2361 927f621e bellard
    fptemp = ST0;
2362 927f621e bellard
    if ((fptemp+1.0)>0.0) {
2363 927f621e bellard
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
2364 927f621e bellard
        ST1 *= fptemp;
2365 927f621e bellard
        fpop();
2366 927f621e bellard
    } else { 
2367 927f621e bellard
        env->fpus &= (~0x4700);
2368 927f621e bellard
        env->fpus |= 0x400;
2369 927f621e bellard
    }
2370 927f621e bellard
}
2371 927f621e bellard
2372 927f621e bellard
void helper_fsqrt(void)
2373 927f621e bellard
{
2374 927f621e bellard
    CPU86_LDouble fptemp;
2375 927f621e bellard
2376 927f621e bellard
    fptemp = ST0;
2377 927f621e bellard
    if (fptemp<0.0) { 
2378 927f621e bellard
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2379 927f621e bellard
        env->fpus |= 0x400;
2380 927f621e bellard
    }
2381 927f621e bellard
    ST0 = sqrt(fptemp);
2382 927f621e bellard
}
2383 927f621e bellard
2384 927f621e bellard
void helper_fsincos(void)
2385 927f621e bellard
{
2386 927f621e bellard
    CPU86_LDouble fptemp;
2387 927f621e bellard
2388 927f621e bellard
    fptemp = ST0;
2389 927f621e bellard
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2390 927f621e bellard
        env->fpus |= 0x400;
2391 927f621e bellard
    } else {
2392 927f621e bellard
        ST0 = sin(fptemp);
2393 927f621e bellard
        fpush();
2394 927f621e bellard
        ST0 = cos(fptemp);
2395 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2396 927f621e bellard
        /* the above code is for  |arg| < 2**63 only */
2397 927f621e bellard
    }
2398 927f621e bellard
}
2399 927f621e bellard
2400 927f621e bellard
void helper_frndint(void)
2401 927f621e bellard
{
2402 927f621e bellard
    ST0 = rint(ST0);
2403 927f621e bellard
}
2404 927f621e bellard
2405 927f621e bellard
void helper_fscale(void)
2406 927f621e bellard
{
2407 927f621e bellard
    CPU86_LDouble fpsrcop, fptemp;
2408 927f621e bellard
2409 927f621e bellard
    fpsrcop = 2.0;
2410 927f621e bellard
    fptemp = pow(fpsrcop,ST1);
2411 927f621e bellard
    ST0 *= fptemp;
2412 927f621e bellard
}
2413 927f621e bellard
2414 927f621e bellard
void helper_fsin(void)
2415 927f621e bellard
{
2416 927f621e bellard
    CPU86_LDouble fptemp;
2417 927f621e bellard
2418 927f621e bellard
    fptemp = ST0;
2419 927f621e bellard
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2420 927f621e bellard
        env->fpus |= 0x400;
2421 927f621e bellard
    } else {
2422 927f621e bellard
        ST0 = sin(fptemp);
2423 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2424 927f621e bellard
        /* the above code is for  |arg| < 2**53 only */
2425 927f621e bellard
    }
2426 927f621e bellard
}
2427 927f621e bellard
2428 927f621e bellard
void helper_fcos(void)
2429 927f621e bellard
{
2430 927f621e bellard
    CPU86_LDouble fptemp;
2431 927f621e bellard
2432 927f621e bellard
    fptemp = ST0;
2433 927f621e bellard
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2434 927f621e bellard
        env->fpus |= 0x400;
2435 927f621e bellard
    } else {
2436 927f621e bellard
        ST0 = cos(fptemp);
2437 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2438 927f621e bellard
        /* the above code is for  |arg5 < 2**63 only */
2439 927f621e bellard
    }
2440 927f621e bellard
}
2441 927f621e bellard
2442 927f621e bellard
/* associated heplers to reduce generated code length and to simplify
2443 927f621e bellard
   relocation (FP constants are usually stored in .rodata section) */
2444 927f621e bellard
2445 927f621e bellard
void OPPROTO op_f2xm1(void)
2446 927f621e bellard
{
2447 927f621e bellard
    helper_f2xm1();
2448 927f621e bellard
}
2449 927f621e bellard
2450 927f621e bellard
void OPPROTO op_fyl2x(void)
2451 927f621e bellard
{
2452 927f621e bellard
    helper_fyl2x();
2453 927f621e bellard
}
2454 927f621e bellard
2455 927f621e bellard
void OPPROTO op_fptan(void)
2456 927f621e bellard
{
2457 927f621e bellard
    helper_fptan();
2458 927f621e bellard
}
2459 927f621e bellard
2460 927f621e bellard
void OPPROTO op_fpatan(void)
2461 927f621e bellard
{
2462 927f621e bellard
    helper_fpatan();
2463 927f621e bellard
}
2464 927f621e bellard
2465 927f621e bellard
void OPPROTO op_fxtract(void)
2466 927f621e bellard
{
2467 927f621e bellard
    helper_fxtract();
2468 927f621e bellard
}
2469 927f621e bellard
2470 927f621e bellard
void OPPROTO op_fprem1(void)
2471 927f621e bellard
{
2472 927f621e bellard
    helper_fprem1();
2473 927f621e bellard
}
2474 927f621e bellard
2475 927f621e bellard
2476 927f621e bellard
void OPPROTO op_fprem(void)
2477 927f621e bellard
{
2478 927f621e bellard
    helper_fprem();
2479 927f621e bellard
}
2480 927f621e bellard
2481 927f621e bellard
void OPPROTO op_fyl2xp1(void)
2482 927f621e bellard
{
2483 927f621e bellard
    helper_fyl2xp1();
2484 927f621e bellard
}
2485 927f621e bellard
2486 927f621e bellard
void OPPROTO op_fsqrt(void)
2487 927f621e bellard
{
2488 927f621e bellard
    helper_fsqrt();
2489 927f621e bellard
}
2490 927f621e bellard
2491 927f621e bellard
void OPPROTO op_fsincos(void)
2492 927f621e bellard
{
2493 927f621e bellard
    helper_fsincos();
2494 927f621e bellard
}
2495 927f621e bellard
2496 927f621e bellard
void OPPROTO op_frndint(void)
2497 927f621e bellard
{
2498 927f621e bellard
    helper_frndint();
2499 927f621e bellard
}
2500 927f621e bellard
2501 927f621e bellard
void OPPROTO op_fscale(void)
2502 927f621e bellard
{
2503 927f621e bellard
    helper_fscale();
2504 927f621e bellard
}
2505 927f621e bellard
2506 927f621e bellard
void OPPROTO op_fsin(void)
2507 927f621e bellard
{
2508 927f621e bellard
    helper_fsin();
2509 927f621e bellard
}
2510 927f621e bellard
2511 927f621e bellard
void OPPROTO op_fcos(void)
2512 927f621e bellard
{
2513 927f621e bellard
    helper_fcos();
2514 927f621e bellard
}
2515 927f621e bellard
2516 4b74fe1f bellard
void OPPROTO op_fnstsw_A0(void)
2517 4b74fe1f bellard
{
2518 4b74fe1f bellard
    int fpus;
2519 4b74fe1f bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2520 4b74fe1f bellard
    stw((void *)A0, fpus);
2521 4b74fe1f bellard
}
2522 4b74fe1f bellard
2523 77f8dd5a bellard
void OPPROTO op_fnstsw_EAX(void)
2524 77f8dd5a bellard
{
2525 77f8dd5a bellard
    int fpus;
2526 77f8dd5a bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2527 77f8dd5a bellard
    EAX = (EAX & 0xffff0000) | fpus;
2528 77f8dd5a bellard
}
2529 77f8dd5a bellard
2530 4b74fe1f bellard
void OPPROTO op_fnstcw_A0(void)
2531 4b74fe1f bellard
{
2532 4b74fe1f bellard
    stw((void *)A0, env->fpuc);
2533 4b74fe1f bellard
}
2534 4b74fe1f bellard
2535 4b74fe1f bellard
void OPPROTO op_fldcw_A0(void)
2536 4b74fe1f bellard
{
2537 4b74fe1f bellard
    int rnd_type;
2538 4b74fe1f bellard
    env->fpuc = lduw((void *)A0);
2539 4b74fe1f bellard
    /* set rounding mode */
2540 4b74fe1f bellard
    switch(env->fpuc & RC_MASK) {
2541 4b74fe1f bellard
    default:
2542 4b74fe1f bellard
    case RC_NEAR:
2543 4b74fe1f bellard
        rnd_type = FE_TONEAREST;
2544 4b74fe1f bellard
        break;
2545 4b74fe1f bellard
    case RC_DOWN:
2546 4b74fe1f bellard
        rnd_type = FE_DOWNWARD;
2547 4b74fe1f bellard
        break;
2548 4b74fe1f bellard
    case RC_UP:
2549 4b74fe1f bellard
        rnd_type = FE_UPWARD;
2550 4b74fe1f bellard
        break;
2551 4b74fe1f bellard
    case RC_CHOP:
2552 4b74fe1f bellard
        rnd_type = FE_TOWARDZERO;
2553 4b74fe1f bellard
        break;
2554 4b74fe1f bellard
    }
2555 4b74fe1f bellard
    fesetround(rnd_type);
2556 4b74fe1f bellard
}
2557 4b74fe1f bellard
2558 1a9353d2 bellard
void OPPROTO op_fclex(void)
2559 1a9353d2 bellard
{
2560 1a9353d2 bellard
    env->fpus &= 0x7f00;
2561 1a9353d2 bellard
}
2562 1a9353d2 bellard
2563 1a9353d2 bellard
void OPPROTO op_fninit(void)
2564 1a9353d2 bellard
{
2565 1a9353d2 bellard
    env->fpus = 0;
2566 1a9353d2 bellard
    env->fpstt = 0;
2567 1a9353d2 bellard
    env->fpuc = 0x37f;
2568 1a9353d2 bellard
    env->fptags[0] = 1;
2569 1a9353d2 bellard
    env->fptags[1] = 1;
2570 1a9353d2 bellard
    env->fptags[2] = 1;
2571 1a9353d2 bellard
    env->fptags[3] = 1;
2572 1a9353d2 bellard
    env->fptags[4] = 1;
2573 1a9353d2 bellard
    env->fptags[5] = 1;
2574 1a9353d2 bellard
    env->fptags[6] = 1;
2575 1a9353d2 bellard
    env->fptags[7] = 1;
2576 1a9353d2 bellard
}
2577 1b6b029e bellard
2578 1b6b029e bellard
/* threading support */
2579 1b6b029e bellard
void OPPROTO op_lock(void)
2580 1b6b029e bellard
{
2581 1b6b029e bellard
    cpu_lock();
2582 1b6b029e bellard
}
2583 1b6b029e bellard
2584 1b6b029e bellard
void OPPROTO op_unlock(void)
2585 1b6b029e bellard
{
2586 1b6b029e bellard
    cpu_unlock();
2587 1b6b029e bellard
}