Statistics
| Branch: | Revision:

root / op-i386.c @ 2792c4f2

History | View | Annotate | Download (51.3 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 564c8f99 bellard
void OPPROTO op_raise_exception(void)
626 0ecfa993 bellard
{
627 564c8f99 bellard
    int exception_index;
628 564c8f99 bellard
    exception_index = PARAM1;
629 564c8f99 bellard
    raise_exception(exception_index);
630 0ecfa993 bellard
}
631 0ecfa993 bellard
632 0ecfa993 bellard
void OPPROTO op_into(void)
633 0ecfa993 bellard
{
634 0ecfa993 bellard
    int eflags;
635 0ecfa993 bellard
    eflags = cc_table[CC_OP].compute_all();
636 0ecfa993 bellard
    if (eflags & CC_O) {
637 2792c4f2 bellard
        EIP = PARAM1;
638 0ecfa993 bellard
        raise_exception(EXCP04_INTO);
639 a4a0ffdb bellard
    }
640 504e56eb bellard
    FORCE_RET();
641 a4a0ffdb bellard
}
642 a4a0ffdb bellard
643 504e56eb bellard
void OPPROTO op_cli(void)
644 504e56eb bellard
{
645 504e56eb bellard
    env->eflags &= ~IF_MASK;
646 504e56eb bellard
}
647 504e56eb bellard
648 f631ef9b bellard
void OPPROTO op_sti(void)
649 f631ef9b bellard
{
650 504e56eb bellard
    env->eflags |= IF_MASK;
651 f631ef9b bellard
}
652 f631ef9b bellard
653 3acace13 bellard
#if 0
654 f631ef9b bellard
/* vm86plus instructions */
655 f631ef9b bellard
void OPPROTO op_cli_vm(void)
656 f631ef9b bellard
{
657 f631ef9b bellard
    env->eflags &= ~VIF_MASK;
658 f631ef9b bellard
}
659 f631ef9b bellard

660 f631ef9b bellard
void OPPROTO op_sti_vm(void)
661 f631ef9b bellard
{
662 f631ef9b bellard
    env->eflags |= VIF_MASK;
663 f631ef9b bellard
    if (env->eflags & VIP_MASK) {
664 f631ef9b bellard
        EIP = PARAM1;
665 f631ef9b bellard
        raise_exception(EXCP0D_GPF);
666 f631ef9b bellard
    }
667 f631ef9b bellard
    FORCE_RET();
668 f631ef9b bellard
}
669 3acace13 bellard
#endif
670 f631ef9b bellard
671 a4a0ffdb bellard
void OPPROTO op_boundw(void)
672 a4a0ffdb bellard
{
673 a4a0ffdb bellard
    int low, high, v;
674 a4a0ffdb bellard
    low = ldsw((uint8_t *)A0);
675 a4a0ffdb bellard
    high = ldsw((uint8_t *)A0 + 2);
676 a4a0ffdb bellard
    v = (int16_t)T0;
677 a4a0ffdb bellard
    if (v < low || v > high)
678 a4a0ffdb bellard
        raise_exception(EXCP05_BOUND);
679 a4a0ffdb bellard
    FORCE_RET();
680 a4a0ffdb bellard
}
681 a4a0ffdb bellard
682 a4a0ffdb bellard
void OPPROTO op_boundl(void)
683 a4a0ffdb bellard
{
684 a4a0ffdb bellard
    int low, high, v;
685 a4a0ffdb bellard
    low = ldl((uint8_t *)A0);
686 a4a0ffdb bellard
    high = ldl((uint8_t *)A0 + 4);
687 a4a0ffdb bellard
    v = T0;
688 a4a0ffdb bellard
    if (v < low || v > high)
689 a4a0ffdb bellard
        raise_exception(EXCP05_BOUND);
690 a4a0ffdb bellard
    FORCE_RET();
691 a4a0ffdb bellard
}
692 a4a0ffdb bellard
693 a4a0ffdb bellard
void OPPROTO op_cmpxchg8b(void)
694 a4a0ffdb bellard
{
695 a4a0ffdb bellard
    uint64_t d;
696 a4a0ffdb bellard
    int eflags;
697 a4a0ffdb bellard
698 a4a0ffdb bellard
    eflags = cc_table[CC_OP].compute_all();
699 a4a0ffdb bellard
    d = ldq((uint8_t *)A0);
700 a4a0ffdb bellard
    if (d == (((uint64_t)EDX << 32) | EAX)) {
701 a4a0ffdb bellard
        stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);
702 a4a0ffdb bellard
        eflags |= CC_Z;
703 0ecfa993 bellard
    } else {
704 a4a0ffdb bellard
        EDX = d >> 32;
705 a4a0ffdb bellard
        EAX = d;
706 a4a0ffdb bellard
        eflags &= ~CC_Z;
707 0ecfa993 bellard
    }
708 a4a0ffdb bellard
    CC_SRC = eflags;
709 a4a0ffdb bellard
    FORCE_RET();
710 0ecfa993 bellard
}
711 0ecfa993 bellard
712 7bfdb6d1 bellard
/* string ops */
713 7bfdb6d1 bellard
714 7bfdb6d1 bellard
#define ldul ldl
715 7bfdb6d1 bellard
716 7bfdb6d1 bellard
#define SHIFT 0
717 367e86e8 bellard
#include "ops_template.h"
718 7bfdb6d1 bellard
#undef SHIFT
719 7bfdb6d1 bellard
720 7bfdb6d1 bellard
#define SHIFT 1
721 367e86e8 bellard
#include "ops_template.h"
722 7bfdb6d1 bellard
#undef SHIFT
723 7bfdb6d1 bellard
724 7bfdb6d1 bellard
#define SHIFT 2
725 367e86e8 bellard
#include "ops_template.h"
726 7bfdb6d1 bellard
#undef SHIFT
727 7bfdb6d1 bellard
728 7bfdb6d1 bellard
/* sign extend */
729 7bfdb6d1 bellard
730 7bfdb6d1 bellard
void OPPROTO op_movsbl_T0_T0(void)
731 7bfdb6d1 bellard
{
732 7bfdb6d1 bellard
    T0 = (int8_t)T0;
733 7bfdb6d1 bellard
}
734 7bfdb6d1 bellard
735 7bfdb6d1 bellard
void OPPROTO op_movzbl_T0_T0(void)
736 7bfdb6d1 bellard
{
737 7bfdb6d1 bellard
    T0 = (uint8_t)T0;
738 7bfdb6d1 bellard
}
739 7bfdb6d1 bellard
740 7bfdb6d1 bellard
void OPPROTO op_movswl_T0_T0(void)
741 7bfdb6d1 bellard
{
742 7bfdb6d1 bellard
    T0 = (int16_t)T0;
743 7bfdb6d1 bellard
}
744 7bfdb6d1 bellard
745 7bfdb6d1 bellard
void OPPROTO op_movzwl_T0_T0(void)
746 7bfdb6d1 bellard
{
747 7bfdb6d1 bellard
    T0 = (uint16_t)T0;
748 7bfdb6d1 bellard
}
749 7bfdb6d1 bellard
750 7bfdb6d1 bellard
void OPPROTO op_movswl_EAX_AX(void)
751 7bfdb6d1 bellard
{
752 7bfdb6d1 bellard
    EAX = (int16_t)EAX;
753 7bfdb6d1 bellard
}
754 7bfdb6d1 bellard
755 7bfdb6d1 bellard
void OPPROTO op_movsbw_AX_AL(void)
756 7bfdb6d1 bellard
{
757 7bfdb6d1 bellard
    EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
758 7bfdb6d1 bellard
}
759 7bfdb6d1 bellard
760 7bfdb6d1 bellard
void OPPROTO op_movslq_EDX_EAX(void)
761 7bfdb6d1 bellard
{
762 7bfdb6d1 bellard
    EDX = (int32_t)EAX >> 31;
763 7bfdb6d1 bellard
}
764 7bfdb6d1 bellard
765 7bfdb6d1 bellard
void OPPROTO op_movswl_DX_AX(void)
766 7bfdb6d1 bellard
{
767 7bfdb6d1 bellard
    EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
768 7bfdb6d1 bellard
}
769 7bfdb6d1 bellard
770 7bfdb6d1 bellard
/* push/pop */
771 7bfdb6d1 bellard
772 7bfdb6d1 bellard
void op_pushl_T0(void)
773 7bfdb6d1 bellard
{
774 7bfdb6d1 bellard
    uint32_t offset;
775 7bfdb6d1 bellard
    offset = ESP - 4;
776 7bfdb6d1 bellard
    stl((void *)offset, T0);
777 7bfdb6d1 bellard
    /* modify ESP after to handle exceptions correctly */
778 7bfdb6d1 bellard
    ESP = offset;
779 7bfdb6d1 bellard
}
780 7bfdb6d1 bellard
781 dab2ed99 bellard
void op_pushw_T0(void)
782 dab2ed99 bellard
{
783 dab2ed99 bellard
    uint32_t offset;
784 dab2ed99 bellard
    offset = ESP - 2;
785 dab2ed99 bellard
    stw((void *)offset, T0);
786 dab2ed99 bellard
    /* modify ESP after to handle exceptions correctly */
787 dab2ed99 bellard
    ESP = offset;
788 dab2ed99 bellard
}
789 dab2ed99 bellard
790 dab2ed99 bellard
void op_pushl_ss32_T0(void)
791 7bfdb6d1 bellard
{
792 7bfdb6d1 bellard
    uint32_t offset;
793 7bfdb6d1 bellard
    offset = ESP - 4;
794 dab2ed99 bellard
    stl(env->seg_cache[R_SS].base + offset, T0);
795 dab2ed99 bellard
    /* modify ESP after to handle exceptions correctly */
796 dab2ed99 bellard
    ESP = offset;
797 dab2ed99 bellard
}
798 dab2ed99 bellard
799 dab2ed99 bellard
void op_pushw_ss32_T0(void)
800 dab2ed99 bellard
{
801 dab2ed99 bellard
    uint32_t offset;
802 dab2ed99 bellard
    offset = ESP - 2;
803 dab2ed99 bellard
    stw(env->seg_cache[R_SS].base + offset, T0);
804 7bfdb6d1 bellard
    /* modify ESP after to handle exceptions correctly */
805 7bfdb6d1 bellard
    ESP = offset;
806 7bfdb6d1 bellard
}
807 7bfdb6d1 bellard
808 dab2ed99 bellard
void op_pushl_ss16_T0(void)
809 dab2ed99 bellard
{
810 dab2ed99 bellard
    uint32_t offset;
811 dab2ed99 bellard
    offset = (ESP - 4) & 0xffff;
812 dab2ed99 bellard
    stl(env->seg_cache[R_SS].base + offset, T0);
813 dab2ed99 bellard
    /* modify ESP after to handle exceptions correctly */
814 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | offset;
815 dab2ed99 bellard
}
816 dab2ed99 bellard
817 dab2ed99 bellard
void op_pushw_ss16_T0(void)
818 dab2ed99 bellard
{
819 dab2ed99 bellard
    uint32_t offset;
820 dab2ed99 bellard
    offset = (ESP - 2) & 0xffff;
821 dab2ed99 bellard
    stw(env->seg_cache[R_SS].base + offset, T0);
822 dab2ed99 bellard
    /* modify ESP after to handle exceptions correctly */
823 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | offset;
824 dab2ed99 bellard
}
825 dab2ed99 bellard
826 dab2ed99 bellard
/* NOTE: ESP update is done after */
827 7bfdb6d1 bellard
void op_popl_T0(void)
828 7bfdb6d1 bellard
{
829 7bfdb6d1 bellard
    T0 = ldl((void *)ESP);
830 dab2ed99 bellard
}
831 dab2ed99 bellard
832 dab2ed99 bellard
void op_popw_T0(void)
833 dab2ed99 bellard
{
834 dab2ed99 bellard
    T0 = lduw((void *)ESP);
835 dab2ed99 bellard
}
836 dab2ed99 bellard
837 dab2ed99 bellard
void op_popl_ss32_T0(void)
838 dab2ed99 bellard
{
839 dab2ed99 bellard
    T0 = ldl(env->seg_cache[R_SS].base + ESP);
840 dab2ed99 bellard
}
841 dab2ed99 bellard
842 dab2ed99 bellard
void op_popw_ss32_T0(void)
843 dab2ed99 bellard
{
844 dab2ed99 bellard
    T0 = lduw(env->seg_cache[R_SS].base + ESP);
845 dab2ed99 bellard
}
846 dab2ed99 bellard
847 dab2ed99 bellard
void op_popl_ss16_T0(void)
848 dab2ed99 bellard
{
849 dab2ed99 bellard
    T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff));
850 dab2ed99 bellard
}
851 dab2ed99 bellard
852 dab2ed99 bellard
void op_popw_ss16_T0(void)
853 dab2ed99 bellard
{
854 dab2ed99 bellard
    T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff));
855 dab2ed99 bellard
}
856 dab2ed99 bellard
857 dab2ed99 bellard
void op_addl_ESP_4(void)
858 dab2ed99 bellard
{
859 7bfdb6d1 bellard
    ESP += 4;
860 7bfdb6d1 bellard
}
861 7bfdb6d1 bellard
862 dab2ed99 bellard
void op_addl_ESP_2(void)
863 dab2ed99 bellard
{
864 dab2ed99 bellard
    ESP += 2;
865 dab2ed99 bellard
}
866 dab2ed99 bellard
867 dab2ed99 bellard
void op_addw_ESP_4(void)
868 dab2ed99 bellard
{
869 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
870 dab2ed99 bellard
}
871 dab2ed99 bellard
872 dab2ed99 bellard
void op_addw_ESP_2(void)
873 dab2ed99 bellard
{
874 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
875 dab2ed99 bellard
}
876 dab2ed99 bellard
877 7bfdb6d1 bellard
void op_addl_ESP_im(void)
878 7bfdb6d1 bellard
{
879 7bfdb6d1 bellard
    ESP += PARAM1;
880 7bfdb6d1 bellard
}
881 367e86e8 bellard
882 dab2ed99 bellard
void op_addw_ESP_im(void)
883 dab2ed99 bellard
{
884 dab2ed99 bellard
    ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
885 27362c82 bellard
}
886 27362c82 bellard
887 27362c82 bellard
/* rdtsc */
888 27362c82 bellard
#ifndef __i386__
889 27362c82 bellard
uint64_t emu_time;
890 27362c82 bellard
#endif
891 a4a0ffdb bellard
892 a4a0ffdb bellard
void OPPROTO op_rdtsc(void)
893 27362c82 bellard
{
894 27362c82 bellard
    uint64_t val;
895 27362c82 bellard
#ifdef __i386__
896 27362c82 bellard
    asm("rdtsc" : "=A" (val));
897 27362c82 bellard
#else
898 27362c82 bellard
    /* better than nothing: the time increases */
899 27362c82 bellard
    val = emu_time++;
900 27362c82 bellard
#endif
901 27362c82 bellard
    EAX = val;
902 27362c82 bellard
    EDX = val >> 32;
903 27362c82 bellard
}
904 27362c82 bellard
905 a4a0ffdb bellard
/* We simulate a pre-MMX pentium as in valgrind */
906 a4a0ffdb bellard
#define CPUID_FP87 (1 << 0)
907 a4a0ffdb bellard
#define CPUID_VME  (1 << 1)
908 a4a0ffdb bellard
#define CPUID_DE   (1 << 2)
909 a4a0ffdb bellard
#define CPUID_PSE  (1 << 3)
910 a4a0ffdb bellard
#define CPUID_TSC  (1 << 4)
911 a4a0ffdb bellard
#define CPUID_MSR  (1 << 5)
912 a4a0ffdb bellard
#define CPUID_PAE  (1 << 6)
913 a4a0ffdb bellard
#define CPUID_MCE  (1 << 7)
914 a4a0ffdb bellard
#define CPUID_CX8  (1 << 8)
915 a4a0ffdb bellard
#define CPUID_APIC (1 << 9)
916 a4a0ffdb bellard
#define CPUID_SEP  (1 << 11) /* sysenter/sysexit */
917 a4a0ffdb bellard
#define CPUID_MTRR (1 << 12)
918 a4a0ffdb bellard
#define CPUID_PGE  (1 << 13)
919 a4a0ffdb bellard
#define CPUID_MCA  (1 << 14)
920 a4a0ffdb bellard
#define CPUID_CMOV (1 << 15)
921 a4a0ffdb bellard
/* ... */
922 a4a0ffdb bellard
#define CPUID_MMX  (1 << 23)
923 a4a0ffdb bellard
#define CPUID_FXSR (1 << 24)
924 a4a0ffdb bellard
#define CPUID_SSE  (1 << 25)
925 a4a0ffdb bellard
#define CPUID_SSE2 (1 << 26)
926 a4a0ffdb bellard
927 a4a0ffdb bellard
void helper_cpuid(void)
928 a4a0ffdb bellard
{
929 a4a0ffdb bellard
    if (EAX == 0) {
930 a4a0ffdb bellard
        EAX = 1; /* max EAX index supported */
931 a4a0ffdb bellard
        EBX = 0x756e6547;
932 a4a0ffdb bellard
        ECX = 0x6c65746e;
933 a4a0ffdb bellard
        EDX = 0x49656e69;
934 a4a0ffdb bellard
    } else {
935 a4a0ffdb bellard
        /* EAX = 1 info */
936 a4a0ffdb bellard
        EAX = 0x52b;
937 a4a0ffdb bellard
        EBX = 0;
938 a4a0ffdb bellard
        ECX = 0;
939 3acace13 bellard
        EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |
940 a4a0ffdb bellard
            CPUID_TSC | CPUID_MSR | CPUID_MCE |
941 a4a0ffdb bellard
            CPUID_CX8;
942 a4a0ffdb bellard
    }
943 a4a0ffdb bellard
}
944 a4a0ffdb bellard
945 a4a0ffdb bellard
void OPPROTO op_cpuid(void)
946 a4a0ffdb bellard
{
947 a4a0ffdb bellard
    helper_cpuid();
948 a4a0ffdb bellard
}
949 a4a0ffdb bellard
950 27362c82 bellard
/* bcd */
951 27362c82 bellard
952 27362c82 bellard
/* XXX: exception */
953 27362c82 bellard
void OPPROTO op_aam(void)
954 27362c82 bellard
{
955 27362c82 bellard
    int base = PARAM1;
956 27362c82 bellard
    int al, ah;
957 27362c82 bellard
    al = EAX & 0xff;
958 27362c82 bellard
    ah = al / base;
959 27362c82 bellard
    al = al % base;
960 27362c82 bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
961 27362c82 bellard
    CC_DST = al;
962 27362c82 bellard
}
963 27362c82 bellard
964 27362c82 bellard
void OPPROTO op_aad(void)
965 27362c82 bellard
{
966 27362c82 bellard
    int base = PARAM1;
967 27362c82 bellard
    int al, ah;
968 27362c82 bellard
    al = EAX & 0xff;
969 27362c82 bellard
    ah = (EAX >> 8) & 0xff;
970 27362c82 bellard
    al = ((ah * base) + al) & 0xff;
971 27362c82 bellard
    EAX = (EAX & ~0xffff) | al;
972 27362c82 bellard
    CC_DST = al;
973 27362c82 bellard
}
974 27362c82 bellard
975 27362c82 bellard
void OPPROTO op_aaa(void)
976 27362c82 bellard
{
977 27362c82 bellard
    int icarry;
978 27362c82 bellard
    int al, ah, af;
979 27362c82 bellard
    int eflags;
980 27362c82 bellard
981 27362c82 bellard
    eflags = cc_table[CC_OP].compute_all();
982 27362c82 bellard
    af = eflags & CC_A;
983 27362c82 bellard
    al = EAX & 0xff;
984 27362c82 bellard
    ah = (EAX >> 8) & 0xff;
985 27362c82 bellard
986 27362c82 bellard
    icarry = (al > 0xf9);
987 27362c82 bellard
    if (((al & 0x0f) > 9 ) || af) {
988 27362c82 bellard
        al = (al + 6) & 0x0f;
989 27362c82 bellard
        ah = (ah + 1 + icarry) & 0xff;
990 27362c82 bellard
        eflags |= CC_C | CC_A;
991 27362c82 bellard
    } else {
992 27362c82 bellard
        eflags &= ~(CC_C | CC_A);
993 27362c82 bellard
        al &= 0x0f;
994 27362c82 bellard
    }
995 27362c82 bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
996 27362c82 bellard
    CC_SRC = eflags;
997 27362c82 bellard
}
998 27362c82 bellard
999 27362c82 bellard
void OPPROTO op_aas(void)
1000 27362c82 bellard
{
1001 27362c82 bellard
    int icarry;
1002 27362c82 bellard
    int al, ah, af;
1003 27362c82 bellard
    int eflags;
1004 27362c82 bellard
1005 27362c82 bellard
    eflags = cc_table[CC_OP].compute_all();
1006 27362c82 bellard
    af = eflags & CC_A;
1007 27362c82 bellard
    al = EAX & 0xff;
1008 27362c82 bellard
    ah = (EAX >> 8) & 0xff;
1009 27362c82 bellard
1010 27362c82 bellard
    icarry = (al < 6);
1011 27362c82 bellard
    if (((al & 0x0f) > 9 ) || af) {
1012 27362c82 bellard
        al = (al - 6) & 0x0f;
1013 27362c82 bellard
        ah = (ah - 1 - icarry) & 0xff;
1014 27362c82 bellard
        eflags |= CC_C | CC_A;
1015 27362c82 bellard
    } else {
1016 27362c82 bellard
        eflags &= ~(CC_C | CC_A);
1017 27362c82 bellard
        al &= 0x0f;
1018 27362c82 bellard
    }
1019 27362c82 bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1020 27362c82 bellard
    CC_SRC = eflags;
1021 27362c82 bellard
}
1022 27362c82 bellard
1023 27362c82 bellard
void OPPROTO op_daa(void)
1024 27362c82 bellard
{
1025 27362c82 bellard
    int al, af, cf;
1026 27362c82 bellard
    int eflags;
1027 27362c82 bellard
1028 27362c82 bellard
    eflags = cc_table[CC_OP].compute_all();
1029 27362c82 bellard
    cf = eflags & CC_C;
1030 27362c82 bellard
    af = eflags & CC_A;
1031 27362c82 bellard
    al = EAX & 0xff;
1032 27362c82 bellard
1033 27362c82 bellard
    eflags = 0;
1034 27362c82 bellard
    if (((al & 0x0f) > 9 ) || af) {
1035 27362c82 bellard
        al = (al + 6) & 0xff;
1036 27362c82 bellard
        eflags |= CC_A;
1037 27362c82 bellard
    }
1038 27362c82 bellard
    if ((al > 0x9f) || cf) {
1039 27362c82 bellard
        al = (al + 0x60) & 0xff;
1040 27362c82 bellard
        eflags |= CC_C;
1041 27362c82 bellard
    }
1042 27362c82 bellard
    EAX = (EAX & ~0xff) | al;
1043 27362c82 bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1044 27362c82 bellard
    eflags |= (al == 0) << 6; /* zf */
1045 27362c82 bellard
    eflags |= parity_table[al]; /* pf */
1046 27362c82 bellard
    eflags |= (al & 0x80); /* sf */
1047 27362c82 bellard
    CC_SRC = eflags;
1048 27362c82 bellard
}
1049 27362c82 bellard
1050 27362c82 bellard
void OPPROTO op_das(void)
1051 27362c82 bellard
{
1052 27362c82 bellard
    int al, al1, af, cf;
1053 27362c82 bellard
    int eflags;
1054 27362c82 bellard
1055 27362c82 bellard
    eflags = cc_table[CC_OP].compute_all();
1056 27362c82 bellard
    cf = eflags & CC_C;
1057 27362c82 bellard
    af = eflags & CC_A;
1058 27362c82 bellard
    al = EAX & 0xff;
1059 27362c82 bellard
1060 27362c82 bellard
    eflags = 0;
1061 27362c82 bellard
    al1 = al;
1062 27362c82 bellard
    if (((al & 0x0f) > 9 ) || af) {
1063 27362c82 bellard
        eflags |= CC_A;
1064 27362c82 bellard
        if (al < 6 || cf)
1065 27362c82 bellard
            eflags |= CC_C;
1066 27362c82 bellard
        al = (al - 6) & 0xff;
1067 27362c82 bellard
    }
1068 27362c82 bellard
    if ((al1 > 0x99) || cf) {
1069 27362c82 bellard
        al = (al - 0x60) & 0xff;
1070 27362c82 bellard
        eflags |= CC_C;
1071 27362c82 bellard
    }
1072 27362c82 bellard
    EAX = (EAX & ~0xff) | al;
1073 27362c82 bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1074 27362c82 bellard
    eflags |= (al == 0) << 6; /* zf */
1075 27362c82 bellard
    eflags |= parity_table[al]; /* pf */
1076 27362c82 bellard
    eflags |= (al & 0x80); /* sf */
1077 27362c82 bellard
    CC_SRC = eflags;
1078 27362c82 bellard
}
1079 27362c82 bellard
1080 6dbad63e bellard
/* segment handling */
1081 6dbad63e bellard
1082 a4a0ffdb bellard
/* XXX: use static VM86 information */
1083 6dbad63e bellard
void load_seg(int seg_reg, int selector)
1084 6dbad63e bellard
{
1085 6dbad63e bellard
    SegmentCache *sc;
1086 6dbad63e bellard
    SegmentDescriptorTable *dt;
1087 6dbad63e bellard
    int index;
1088 6dbad63e bellard
    uint32_t e1, e2;
1089 6dbad63e bellard
    uint8_t *ptr;
1090 6dbad63e bellard
1091 6dbad63e bellard
    sc = &env->seg_cache[seg_reg];
1092 a4a0ffdb bellard
    if (env->eflags & VM_MASK) {
1093 6dbad63e bellard
        sc->base = (void *)(selector << 4);
1094 6dbad63e bellard
        sc->limit = 0xffff;
1095 6dbad63e bellard
        sc->seg_32bit = 0;
1096 6dbad63e bellard
    } else {
1097 6dbad63e bellard
        if (selector & 0x4)
1098 6dbad63e bellard
            dt = &env->ldt;
1099 6dbad63e bellard
        else
1100 6dbad63e bellard
            dt = &env->gdt;
1101 6dbad63e bellard
        index = selector & ~7;
1102 6dbad63e bellard
        if ((index + 7) > dt->limit)
1103 504e56eb bellard
            raise_exception_err(EXCP0D_GPF, selector);
1104 6dbad63e bellard
        ptr = dt->base + index;
1105 6dbad63e bellard
        e1 = ldl(ptr);
1106 6dbad63e bellard
        e2 = ldl(ptr + 4);
1107 6dbad63e bellard
        sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1108 6dbad63e bellard
        sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1109 6dbad63e bellard
        if (e2 & (1 << 23))
1110 6dbad63e bellard
            sc->limit = (sc->limit << 12) | 0xfff;
1111 6dbad63e bellard
        sc->seg_32bit = (e2 >> 22) & 1;
1112 6dbad63e bellard
#if 0
1113 6dbad63e bellard
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", 
1114 6dbad63e bellard
                selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
1115 6dbad63e bellard
#endif
1116 6dbad63e bellard
    }
1117 3acace13 bellard
    env->segs[seg_reg] = selector;
1118 6dbad63e bellard
}
1119 6dbad63e bellard
1120 6dbad63e bellard
void OPPROTO op_movl_seg_T0(void)
1121 6dbad63e bellard
{
1122 6dbad63e bellard
    load_seg(PARAM1, T0 & 0xffff);
1123 6dbad63e bellard
}
1124 6dbad63e bellard
1125 6dbad63e bellard
void OPPROTO op_movl_T0_seg(void)
1126 6dbad63e bellard
{
1127 6dbad63e bellard
    T0 = env->segs[PARAM1];
1128 6dbad63e bellard
}
1129 6dbad63e bellard
1130 a4a0ffdb bellard
void OPPROTO op_movl_A0_seg(void)
1131 a4a0ffdb bellard
{
1132 a4a0ffdb bellard
    A0 = *(unsigned long *)((char *)env + PARAM1);
1133 a4a0ffdb bellard
}
1134 a4a0ffdb bellard
1135 6dbad63e bellard
void OPPROTO op_addl_A0_seg(void)
1136 6dbad63e bellard
{
1137 6dbad63e bellard
    A0 += *(unsigned long *)((char *)env + PARAM1);
1138 6dbad63e bellard
}
1139 6dbad63e bellard
1140 2792c4f2 bellard
void helper_lsl(void)
1141 2792c4f2 bellard
{
1142 2792c4f2 bellard
    unsigned int selector, limit;
1143 2792c4f2 bellard
    SegmentDescriptorTable *dt;
1144 2792c4f2 bellard
    int index;
1145 2792c4f2 bellard
    uint32_t e1, e2;
1146 2792c4f2 bellard
    uint8_t *ptr;
1147 2792c4f2 bellard
1148 2792c4f2 bellard
    CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
1149 2792c4f2 bellard
    selector = T0 & 0xffff;
1150 2792c4f2 bellard
    if (selector & 0x4)
1151 2792c4f2 bellard
        dt = &env->ldt;
1152 2792c4f2 bellard
    else
1153 2792c4f2 bellard
        dt = &env->gdt;
1154 2792c4f2 bellard
    index = selector & ~7;
1155 2792c4f2 bellard
    if ((index + 7) > dt->limit)
1156 2792c4f2 bellard
        return;
1157 2792c4f2 bellard
    ptr = dt->base + index;
1158 2792c4f2 bellard
    e1 = ldl(ptr);
1159 2792c4f2 bellard
    e2 = ldl(ptr + 4);
1160 2792c4f2 bellard
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1161 2792c4f2 bellard
    if (e2 & (1 << 23))
1162 2792c4f2 bellard
        limit = (limit << 12) | 0xfff;
1163 2792c4f2 bellard
    T1 = limit;
1164 2792c4f2 bellard
    CC_SRC |= CC_Z;
1165 2792c4f2 bellard
}
1166 2792c4f2 bellard
1167 2792c4f2 bellard
void OPPROTO op_lsl(void)
1168 2792c4f2 bellard
{
1169 2792c4f2 bellard
    helper_lsl();
1170 2792c4f2 bellard
}
1171 2792c4f2 bellard
1172 2792c4f2 bellard
void helper_lar(void)
1173 2792c4f2 bellard
{
1174 2792c4f2 bellard
    unsigned int selector;
1175 2792c4f2 bellard
    SegmentDescriptorTable *dt;
1176 2792c4f2 bellard
    int index;
1177 2792c4f2 bellard
    uint32_t e2;
1178 2792c4f2 bellard
    uint8_t *ptr;
1179 2792c4f2 bellard
1180 2792c4f2 bellard
    CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
1181 2792c4f2 bellard
    selector = T0 & 0xffff;
1182 2792c4f2 bellard
    if (selector & 0x4)
1183 2792c4f2 bellard
        dt = &env->ldt;
1184 2792c4f2 bellard
    else
1185 2792c4f2 bellard
        dt = &env->gdt;
1186 2792c4f2 bellard
    index = selector & ~7;
1187 2792c4f2 bellard
    if ((index + 7) > dt->limit)
1188 2792c4f2 bellard
        return;
1189 2792c4f2 bellard
    ptr = dt->base + index;
1190 2792c4f2 bellard
    e2 = ldl(ptr + 4);
1191 2792c4f2 bellard
    T1 = e2 & 0x00f0ff00;
1192 2792c4f2 bellard
    CC_SRC |= CC_Z;
1193 2792c4f2 bellard
}
1194 2792c4f2 bellard
1195 2792c4f2 bellard
void OPPROTO op_lar(void)
1196 2792c4f2 bellard
{
1197 2792c4f2 bellard
    helper_lar();
1198 2792c4f2 bellard
}
1199 2792c4f2 bellard
1200 367e86e8 bellard
/* flags handling */
1201 367e86e8 bellard
1202 367e86e8 bellard
/* slow jumps cases (compute x86 flags) */
1203 367e86e8 bellard
void OPPROTO op_jo_cc(void)
1204 367e86e8 bellard
{
1205 367e86e8 bellard
    int eflags;
1206 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1207 367e86e8 bellard
    if (eflags & CC_O)
1208 dab2ed99 bellard
        EIP = PARAM1;
1209 367e86e8 bellard
    else
1210 dab2ed99 bellard
        EIP = PARAM2;
1211 0ecfa993 bellard
    FORCE_RET();
1212 367e86e8 bellard
}
1213 367e86e8 bellard
1214 367e86e8 bellard
void OPPROTO op_jb_cc(void)
1215 367e86e8 bellard
{
1216 367e86e8 bellard
    if (cc_table[CC_OP].compute_c())
1217 dab2ed99 bellard
        EIP = PARAM1;
1218 367e86e8 bellard
    else
1219 dab2ed99 bellard
        EIP = PARAM2;
1220 0ecfa993 bellard
    FORCE_RET();
1221 367e86e8 bellard
}
1222 367e86e8 bellard
1223 367e86e8 bellard
void OPPROTO op_jz_cc(void)
1224 367e86e8 bellard
{
1225 367e86e8 bellard
    int eflags;
1226 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1227 367e86e8 bellard
    if (eflags & CC_Z)
1228 dab2ed99 bellard
        EIP = PARAM1;
1229 367e86e8 bellard
    else
1230 dab2ed99 bellard
        EIP = PARAM2;
1231 0ecfa993 bellard
    FORCE_RET();
1232 367e86e8 bellard
}
1233 367e86e8 bellard
1234 367e86e8 bellard
void OPPROTO op_jbe_cc(void)
1235 367e86e8 bellard
{
1236 367e86e8 bellard
    int eflags;
1237 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1238 367e86e8 bellard
    if (eflags & (CC_Z | CC_C))
1239 dab2ed99 bellard
        EIP = PARAM1;
1240 367e86e8 bellard
    else
1241 dab2ed99 bellard
        EIP = PARAM2;
1242 0ecfa993 bellard
    FORCE_RET();
1243 367e86e8 bellard
}
1244 367e86e8 bellard
1245 367e86e8 bellard
void OPPROTO op_js_cc(void)
1246 367e86e8 bellard
{
1247 367e86e8 bellard
    int eflags;
1248 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1249 367e86e8 bellard
    if (eflags & CC_S)
1250 dab2ed99 bellard
        EIP = PARAM1;
1251 367e86e8 bellard
    else
1252 dab2ed99 bellard
        EIP = PARAM2;
1253 0ecfa993 bellard
    FORCE_RET();
1254 367e86e8 bellard
}
1255 367e86e8 bellard
1256 367e86e8 bellard
void OPPROTO op_jp_cc(void)
1257 367e86e8 bellard
{
1258 367e86e8 bellard
    int eflags;
1259 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1260 367e86e8 bellard
    if (eflags & CC_P)
1261 dab2ed99 bellard
        EIP = PARAM1;
1262 367e86e8 bellard
    else
1263 dab2ed99 bellard
        EIP = PARAM2;
1264 0ecfa993 bellard
    FORCE_RET();
1265 367e86e8 bellard
}
1266 367e86e8 bellard
1267 367e86e8 bellard
void OPPROTO op_jl_cc(void)
1268 367e86e8 bellard
{
1269 367e86e8 bellard
    int eflags;
1270 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1271 367e86e8 bellard
    if ((eflags ^ (eflags >> 4)) & 0x80)
1272 dab2ed99 bellard
        EIP = PARAM1;
1273 367e86e8 bellard
    else
1274 dab2ed99 bellard
        EIP = PARAM2;
1275 0ecfa993 bellard
    FORCE_RET();
1276 367e86e8 bellard
}
1277 367e86e8 bellard
1278 367e86e8 bellard
void OPPROTO op_jle_cc(void)
1279 367e86e8 bellard
{
1280 367e86e8 bellard
    int eflags;
1281 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1282 367e86e8 bellard
    if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
1283 dab2ed99 bellard
        EIP = PARAM1;
1284 367e86e8 bellard
    else
1285 dab2ed99 bellard
        EIP = PARAM2;
1286 0ecfa993 bellard
    FORCE_RET();
1287 367e86e8 bellard
}
1288 367e86e8 bellard
1289 367e86e8 bellard
/* slow set cases (compute x86 flags) */
1290 367e86e8 bellard
void OPPROTO op_seto_T0_cc(void)
1291 367e86e8 bellard
{
1292 367e86e8 bellard
    int eflags;
1293 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1294 367e86e8 bellard
    T0 = (eflags >> 11) & 1;
1295 367e86e8 bellard
}
1296 367e86e8 bellard
1297 367e86e8 bellard
void OPPROTO op_setb_T0_cc(void)
1298 367e86e8 bellard
{
1299 367e86e8 bellard
    T0 = cc_table[CC_OP].compute_c();
1300 367e86e8 bellard
}
1301 367e86e8 bellard
1302 367e86e8 bellard
void OPPROTO op_setz_T0_cc(void)
1303 367e86e8 bellard
{
1304 367e86e8 bellard
    int eflags;
1305 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1306 367e86e8 bellard
    T0 = (eflags >> 6) & 1;
1307 367e86e8 bellard
}
1308 367e86e8 bellard
1309 367e86e8 bellard
void OPPROTO op_setbe_T0_cc(void)
1310 367e86e8 bellard
{
1311 367e86e8 bellard
    int eflags;
1312 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1313 367e86e8 bellard
    T0 = (eflags & (CC_Z | CC_C)) != 0;
1314 367e86e8 bellard
}
1315 367e86e8 bellard
1316 367e86e8 bellard
void OPPROTO op_sets_T0_cc(void)
1317 367e86e8 bellard
{
1318 367e86e8 bellard
    int eflags;
1319 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1320 367e86e8 bellard
    T0 = (eflags >> 7) & 1;
1321 367e86e8 bellard
}
1322 367e86e8 bellard
1323 367e86e8 bellard
void OPPROTO op_setp_T0_cc(void)
1324 367e86e8 bellard
{
1325 367e86e8 bellard
    int eflags;
1326 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1327 367e86e8 bellard
    T0 = (eflags >> 2) & 1;
1328 367e86e8 bellard
}
1329 367e86e8 bellard
1330 367e86e8 bellard
void OPPROTO op_setl_T0_cc(void)
1331 367e86e8 bellard
{
1332 367e86e8 bellard
    int eflags;
1333 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1334 367e86e8 bellard
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1335 367e86e8 bellard
}
1336 367e86e8 bellard
1337 367e86e8 bellard
void OPPROTO op_setle_T0_cc(void)
1338 367e86e8 bellard
{
1339 367e86e8 bellard
    int eflags;
1340 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1341 367e86e8 bellard
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1342 367e86e8 bellard
}
1343 367e86e8 bellard
1344 367e86e8 bellard
void OPPROTO op_xor_T0_1(void)
1345 367e86e8 bellard
{
1346 367e86e8 bellard
    T0 ^= 1;
1347 367e86e8 bellard
}
1348 367e86e8 bellard
1349 367e86e8 bellard
void OPPROTO op_set_cc_op(void)
1350 367e86e8 bellard
{
1351 367e86e8 bellard
    CC_OP = PARAM1;
1352 367e86e8 bellard
}
1353 367e86e8 bellard
1354 f631ef9b bellard
#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
1355 f631ef9b bellard
#define FL_UPDATE_MASK16 (TF_MASK)
1356 a4a0ffdb bellard
1357 367e86e8 bellard
void OPPROTO op_movl_eflags_T0(void)
1358 367e86e8 bellard
{
1359 a4a0ffdb bellard
    int eflags;
1360 a4a0ffdb bellard
    eflags = T0;
1361 a4a0ffdb bellard
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1362 a4a0ffdb bellard
    DF = 1 - (2 * ((eflags >> 10) & 1));
1363 a4a0ffdb bellard
    /* we also update some system flags as in user mode */
1364 f631ef9b bellard
    env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | (eflags & FL_UPDATE_MASK32);
1365 f631ef9b bellard
}
1366 f631ef9b bellard
1367 f631ef9b bellard
void OPPROTO op_movw_eflags_T0(void)
1368 f631ef9b bellard
{
1369 f631ef9b bellard
    int eflags;
1370 f631ef9b bellard
    eflags = T0;
1371 f631ef9b bellard
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1372 f631ef9b bellard
    DF = 1 - (2 * ((eflags >> 10) & 1));
1373 f631ef9b bellard
    /* we also update some system flags as in user mode */
1374 f631ef9b bellard
    env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | (eflags & FL_UPDATE_MASK16);
1375 f631ef9b bellard
}
1376 f631ef9b bellard
1377 3acace13 bellard
#if 0
1378 3acace13 bellard
/* vm86plus version */
1379 f631ef9b bellard
void OPPROTO op_movw_eflags_T0_vm(void)
1380 f631ef9b bellard
{
1381 f631ef9b bellard
    int eflags;
1382 f631ef9b bellard
    eflags = T0;
1383 f631ef9b bellard
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1384 f631ef9b bellard
    DF = 1 - (2 * ((eflags >> 10) & 1));
1385 f631ef9b bellard
    /* we also update some system flags as in user mode */
1386 f631ef9b bellard
    env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1387 f631ef9b bellard
        (eflags & FL_UPDATE_MASK16);
1388 f631ef9b bellard
    if (eflags & IF_MASK) {
1389 f631ef9b bellard
        env->eflags |= VIF_MASK;
1390 f631ef9b bellard
        if (env->eflags & VIP_MASK) {
1391 f631ef9b bellard
            EIP = PARAM1;
1392 f631ef9b bellard
            raise_exception(EXCP0D_GPF);
1393 f631ef9b bellard
        }
1394 f631ef9b bellard
    }
1395 f631ef9b bellard
    FORCE_RET();
1396 f631ef9b bellard
}
1397 f631ef9b bellard

1398 f631ef9b bellard
void OPPROTO op_movl_eflags_T0_vm(void)
1399 f631ef9b bellard
{
1400 f631ef9b bellard
    int eflags;
1401 f631ef9b bellard
    eflags = T0;
1402 f631ef9b bellard
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1403 f631ef9b bellard
    DF = 1 - (2 * ((eflags >> 10) & 1));
1404 f631ef9b bellard
    /* we also update some system flags as in user mode */
1405 f631ef9b bellard
    env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1406 f631ef9b bellard
        (eflags & FL_UPDATE_MASK32);
1407 f631ef9b bellard
    if (eflags & IF_MASK) {
1408 f631ef9b bellard
        env->eflags |= VIF_MASK;
1409 f631ef9b bellard
        if (env->eflags & VIP_MASK) {
1410 f631ef9b bellard
            EIP = PARAM1;
1411 f631ef9b bellard
            raise_exception(EXCP0D_GPF);
1412 f631ef9b bellard
        }
1413 f631ef9b bellard
    }
1414 f631ef9b bellard
    FORCE_RET();
1415 367e86e8 bellard
}
1416 3acace13 bellard
#endif
1417 367e86e8 bellard
1418 367e86e8 bellard
/* XXX: compute only O flag */
1419 367e86e8 bellard
void OPPROTO op_movb_eflags_T0(void)
1420 367e86e8 bellard
{
1421 367e86e8 bellard
    int of;
1422 367e86e8 bellard
    of = cc_table[CC_OP].compute_all() & CC_O;
1423 a4a0ffdb bellard
    CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1424 367e86e8 bellard
}
1425 367e86e8 bellard
1426 367e86e8 bellard
void OPPROTO op_movl_T0_eflags(void)
1427 367e86e8 bellard
{
1428 a4a0ffdb bellard
    int eflags;
1429 a4a0ffdb bellard
    eflags = cc_table[CC_OP].compute_all();
1430 a4a0ffdb bellard
    eflags |= (DF & DF_MASK);
1431 a4a0ffdb bellard
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1432 a4a0ffdb bellard
    T0 = eflags;
1433 367e86e8 bellard
}
1434 367e86e8 bellard
1435 3acace13 bellard
/* vm86plus version */
1436 3acace13 bellard
#if 0
1437 f631ef9b bellard
void OPPROTO op_movl_T0_eflags_vm(void)
1438 f631ef9b bellard
{
1439 f631ef9b bellard
    int eflags;
1440 f631ef9b bellard
    eflags = cc_table[CC_OP].compute_all();
1441 f631ef9b bellard
    eflags |= (DF & DF_MASK);
1442 f631ef9b bellard
    eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1443 f631ef9b bellard
    if (env->eflags & VIF_MASK)
1444 f631ef9b bellard
        eflags |= IF_MASK;
1445 f631ef9b bellard
    T0 = eflags;
1446 f631ef9b bellard
}
1447 3acace13 bellard
#endif
1448 f631ef9b bellard
1449 367e86e8 bellard
void OPPROTO op_cld(void)
1450 367e86e8 bellard
{
1451 367e86e8 bellard
    DF = 1;
1452 367e86e8 bellard
}
1453 367e86e8 bellard
1454 367e86e8 bellard
void OPPROTO op_std(void)
1455 367e86e8 bellard
{
1456 367e86e8 bellard
    DF = -1;
1457 367e86e8 bellard
}
1458 367e86e8 bellard
1459 367e86e8 bellard
void OPPROTO op_clc(void)
1460 367e86e8 bellard
{
1461 367e86e8 bellard
    int eflags;
1462 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1463 367e86e8 bellard
    eflags &= ~CC_C;
1464 367e86e8 bellard
    CC_SRC = eflags;
1465 367e86e8 bellard
}
1466 367e86e8 bellard
1467 367e86e8 bellard
void OPPROTO op_stc(void)
1468 367e86e8 bellard
{
1469 367e86e8 bellard
    int eflags;
1470 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1471 367e86e8 bellard
    eflags |= CC_C;
1472 367e86e8 bellard
    CC_SRC = eflags;
1473 367e86e8 bellard
}
1474 367e86e8 bellard
1475 367e86e8 bellard
void OPPROTO op_cmc(void)
1476 367e86e8 bellard
{
1477 367e86e8 bellard
    int eflags;
1478 367e86e8 bellard
    eflags = cc_table[CC_OP].compute_all();
1479 367e86e8 bellard
    eflags ^= CC_C;
1480 367e86e8 bellard
    CC_SRC = eflags;
1481 367e86e8 bellard
}
1482 367e86e8 bellard
1483 27362c82 bellard
void OPPROTO op_salc(void)
1484 27362c82 bellard
{
1485 27362c82 bellard
    int cf;
1486 27362c82 bellard
    cf = cc_table[CC_OP].compute_c();
1487 27362c82 bellard
    EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1488 27362c82 bellard
}
1489 27362c82 bellard
1490 367e86e8 bellard
static int compute_all_eflags(void)
1491 367e86e8 bellard
{
1492 367e86e8 bellard
    return CC_SRC;
1493 367e86e8 bellard
}
1494 367e86e8 bellard
1495 367e86e8 bellard
static int compute_c_eflags(void)
1496 367e86e8 bellard
{
1497 367e86e8 bellard
    return CC_SRC & CC_C;
1498 367e86e8 bellard
}
1499 367e86e8 bellard
1500 367e86e8 bellard
static int compute_c_mul(void)
1501 367e86e8 bellard
{
1502 367e86e8 bellard
    int cf;
1503 367e86e8 bellard
    cf = (CC_SRC != 0);
1504 367e86e8 bellard
    return cf;
1505 367e86e8 bellard
}
1506 367e86e8 bellard
1507 367e86e8 bellard
static int compute_all_mul(void)
1508 367e86e8 bellard
{
1509 367e86e8 bellard
    int cf, pf, af, zf, sf, of;
1510 367e86e8 bellard
    cf = (CC_SRC != 0);
1511 367e86e8 bellard
    pf = 0; /* undefined */
1512 367e86e8 bellard
    af = 0; /* undefined */
1513 367e86e8 bellard
    zf = 0; /* undefined */
1514 367e86e8 bellard
    sf = 0; /* undefined */
1515 367e86e8 bellard
    of = cf << 11;
1516 367e86e8 bellard
    return cf | pf | af | zf | sf | of;
1517 367e86e8 bellard
}
1518 367e86e8 bellard
    
1519 367e86e8 bellard
CCTable cc_table[CC_OP_NB] = {
1520 367e86e8 bellard
    [CC_OP_DYNAMIC] = { /* should never happen */ },
1521 367e86e8 bellard
1522 367e86e8 bellard
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1523 367e86e8 bellard
1524 367e86e8 bellard
    [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
1525 367e86e8 bellard
1526 367e86e8 bellard
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1527 367e86e8 bellard
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
1528 367e86e8 bellard
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
1529 367e86e8 bellard
1530 4b74fe1f bellard
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1531 4b74fe1f bellard
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
1532 4b74fe1f bellard
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
1533 4b74fe1f bellard
1534 367e86e8 bellard
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
1535 367e86e8 bellard
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
1536 367e86e8 bellard
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
1537 367e86e8 bellard
    
1538 4b74fe1f bellard
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
1539 4b74fe1f bellard
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
1540 4b74fe1f bellard
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
1541 4b74fe1f bellard
    
1542 367e86e8 bellard
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1543 367e86e8 bellard
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1544 367e86e8 bellard
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1545 367e86e8 bellard
    
1546 4b74fe1f bellard
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1547 4b74fe1f bellard
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1548 367e86e8 bellard
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1549 367e86e8 bellard
    
1550 4b74fe1f bellard
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1551 4b74fe1f bellard
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1552 367e86e8 bellard
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1553 367e86e8 bellard
    
1554 2792c4f2 bellard
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
1555 2792c4f2 bellard
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
1556 367e86e8 bellard
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1557 4b74fe1f bellard
1558 2792c4f2 bellard
    [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
1559 2792c4f2 bellard
    [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
1560 2792c4f2 bellard
    [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
1561 367e86e8 bellard
};
1562 927f621e bellard
1563 f631ef9b bellard
/* floating point support. Some of the code for complicated x87
1564 f631ef9b bellard
   functions comes from the LGPL'ed x86 emulator found in the Willows
1565 f631ef9b bellard
   TWIN windows emulator. */
1566 927f621e bellard
1567 927f621e bellard
#ifdef USE_X86LDOUBLE
1568 927f621e bellard
/* use long double functions */
1569 927f621e bellard
#define lrint lrintl
1570 927f621e bellard
#define llrint llrintl
1571 927f621e bellard
#define fabs fabsl
1572 927f621e bellard
#define sin sinl
1573 927f621e bellard
#define cos cosl
1574 927f621e bellard
#define sqrt sqrtl
1575 927f621e bellard
#define pow powl
1576 927f621e bellard
#define log logl
1577 927f621e bellard
#define tan tanl
1578 927f621e bellard
#define atan2 atan2l
1579 927f621e bellard
#define floor floorl
1580 927f621e bellard
#define ceil ceill
1581 927f621e bellard
#define rint rintl
1582 927f621e bellard
#endif
1583 927f621e bellard
1584 927f621e bellard
extern int lrint(CPU86_LDouble x);
1585 927f621e bellard
extern int64_t llrint(CPU86_LDouble x);
1586 927f621e bellard
extern CPU86_LDouble fabs(CPU86_LDouble x);
1587 927f621e bellard
extern CPU86_LDouble sin(CPU86_LDouble x);
1588 927f621e bellard
extern CPU86_LDouble cos(CPU86_LDouble x);
1589 927f621e bellard
extern CPU86_LDouble sqrt(CPU86_LDouble x);
1590 927f621e bellard
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
1591 927f621e bellard
extern CPU86_LDouble log(CPU86_LDouble x);
1592 927f621e bellard
extern CPU86_LDouble tan(CPU86_LDouble x);
1593 927f621e bellard
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
1594 927f621e bellard
extern CPU86_LDouble floor(CPU86_LDouble x);
1595 927f621e bellard
extern CPU86_LDouble ceil(CPU86_LDouble x);
1596 927f621e bellard
extern CPU86_LDouble rint(CPU86_LDouble x);
1597 927f621e bellard
1598 51fe6890 bellard
#if defined(__powerpc__)
1599 51fe6890 bellard
extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);
1600 51fe6890 bellard
1601 51fe6890 bellard
/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
1602 51fe6890 bellard
double qemu_rint(double x)
1603 51fe6890 bellard
{
1604 51fe6890 bellard
    double y = 4503599627370496.0;
1605 51fe6890 bellard
    if (fabs(x) >= y)
1606 51fe6890 bellard
        return x;
1607 51fe6890 bellard
    if (x < 0) 
1608 51fe6890 bellard
        y = -y;
1609 51fe6890 bellard
    y = (x + y) - y;
1610 51fe6890 bellard
    if (y == 0.0)
1611 51fe6890 bellard
        y = copysign(y, x);
1612 51fe6890 bellard
    return y;
1613 51fe6890 bellard
}
1614 51fe6890 bellard
1615 51fe6890 bellard
#define rint qemu_rint
1616 51fe6890 bellard
#endif
1617 51fe6890 bellard
1618 927f621e bellard
#define RC_MASK         0xc00
1619 927f621e bellard
#define RC_NEAR                0x000
1620 927f621e bellard
#define RC_DOWN                0x400
1621 927f621e bellard
#define RC_UP                0x800
1622 927f621e bellard
#define RC_CHOP                0xc00
1623 927f621e bellard
1624 927f621e bellard
#define MAXTAN 9223372036854775808.0
1625 927f621e bellard
1626 927f621e bellard
#ifdef USE_X86LDOUBLE
1627 927f621e bellard
1628 927f621e bellard
/* only for x86 */
1629 927f621e bellard
typedef union {
1630 927f621e bellard
    long double d;
1631 927f621e bellard
    struct {
1632 927f621e bellard
        unsigned long long lower;
1633 927f621e bellard
        unsigned short upper;
1634 927f621e bellard
    } l;
1635 927f621e bellard
} CPU86_LDoubleU;
1636 927f621e bellard
1637 927f621e bellard
/* the following deal with x86 long double-precision numbers */
1638 927f621e bellard
#define MAXEXPD 0x7fff
1639 927f621e bellard
#define EXPBIAS 16383
1640 927f621e bellard
#define EXPD(fp)        (fp.l.upper & 0x7fff)
1641 927f621e bellard
#define SIGND(fp)        ((fp.l.upper) & 0x8000)
1642 927f621e bellard
#define MANTD(fp)       (fp.l.lower)
1643 927f621e bellard
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
1644 927f621e bellard
1645 927f621e bellard
#else
1646 927f621e bellard
1647 77f8dd5a bellard
typedef union {
1648 927f621e bellard
    double d;
1649 927f621e bellard
#ifndef WORDS_BIGENDIAN
1650 927f621e bellard
    struct {
1651 927f621e bellard
        unsigned long lower;
1652 927f621e bellard
        long upper;
1653 927f621e bellard
    } l;
1654 927f621e bellard
#else
1655 927f621e bellard
    struct {
1656 927f621e bellard
        long upper;
1657 927f621e bellard
        unsigned long lower;
1658 927f621e bellard
    } l;
1659 927f621e bellard
#endif
1660 927f621e bellard
    long long ll;
1661 927f621e bellard
} CPU86_LDoubleU;
1662 927f621e bellard
1663 927f621e bellard
/* the following deal with IEEE double-precision numbers */
1664 927f621e bellard
#define MAXEXPD 0x7ff
1665 927f621e bellard
#define EXPBIAS 1023
1666 927f621e bellard
#define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)
1667 927f621e bellard
#define SIGND(fp)        ((fp.l.upper) & 0x80000000)
1668 927f621e bellard
#define MANTD(fp)        (fp.ll & ((1LL << 52) - 1))
1669 927f621e bellard
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
1670 927f621e bellard
#endif
1671 927f621e bellard
1672 927f621e bellard
/* fp load FT0 */
1673 927f621e bellard
1674 927f621e bellard
void OPPROTO op_flds_FT0_A0(void)
1675 927f621e bellard
{
1676 d014c98c bellard
#ifdef USE_FP_CONVERT
1677 d014c98c bellard
    FP_CONVERT.i32 = ldl((void *)A0);
1678 d014c98c bellard
    FT0 = FP_CONVERT.f;
1679 d014c98c bellard
#else
1680 927f621e bellard
    FT0 = ldfl((void *)A0);
1681 d014c98c bellard
#endif
1682 927f621e bellard
}
1683 927f621e bellard
1684 927f621e bellard
void OPPROTO op_fldl_FT0_A0(void)
1685 927f621e bellard
{
1686 d014c98c bellard
#ifdef USE_FP_CONVERT
1687 d014c98c bellard
    FP_CONVERT.i64 = ldq((void *)A0);
1688 d014c98c bellard
    FT0 = FP_CONVERT.d;
1689 d014c98c bellard
#else
1690 927f621e bellard
    FT0 = ldfq((void *)A0);
1691 d014c98c bellard
#endif
1692 927f621e bellard
}
1693 927f621e bellard
1694 04369ff2 bellard
/* helpers are needed to avoid static constant reference. XXX: find a better way */
1695 04369ff2 bellard
#ifdef USE_INT_TO_FLOAT_HELPERS
1696 04369ff2 bellard
1697 04369ff2 bellard
void helper_fild_FT0_A0(void)
1698 04369ff2 bellard
{
1699 04369ff2 bellard
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1700 04369ff2 bellard
}
1701 04369ff2 bellard
1702 04369ff2 bellard
void helper_fildl_FT0_A0(void)
1703 04369ff2 bellard
{
1704 04369ff2 bellard
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1705 04369ff2 bellard
}
1706 04369ff2 bellard
1707 04369ff2 bellard
void helper_fildll_FT0_A0(void)
1708 04369ff2 bellard
{
1709 04369ff2 bellard
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1710 04369ff2 bellard
}
1711 04369ff2 bellard
1712 04369ff2 bellard
void OPPROTO op_fild_FT0_A0(void)
1713 04369ff2 bellard
{
1714 04369ff2 bellard
    helper_fild_FT0_A0();
1715 04369ff2 bellard
}
1716 04369ff2 bellard
1717 04369ff2 bellard
void OPPROTO op_fildl_FT0_A0(void)
1718 04369ff2 bellard
{
1719 04369ff2 bellard
    helper_fildl_FT0_A0();
1720 04369ff2 bellard
}
1721 04369ff2 bellard
1722 04369ff2 bellard
void OPPROTO op_fildll_FT0_A0(void)
1723 04369ff2 bellard
{
1724 04369ff2 bellard
    helper_fildll_FT0_A0();
1725 04369ff2 bellard
}
1726 04369ff2 bellard
1727 04369ff2 bellard
#else
1728 04369ff2 bellard
1729 927f621e bellard
void OPPROTO op_fild_FT0_A0(void)
1730 927f621e bellard
{
1731 d014c98c bellard
#ifdef USE_FP_CONVERT
1732 d014c98c bellard
    FP_CONVERT.i32 = ldsw((void *)A0);
1733 d014c98c bellard
    FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1734 d014c98c bellard
#else
1735 927f621e bellard
    FT0 = (CPU86_LDouble)ldsw((void *)A0);
1736 d014c98c bellard
#endif
1737 927f621e bellard
}
1738 927f621e bellard
1739 927f621e bellard
void OPPROTO op_fildl_FT0_A0(void)
1740 927f621e bellard
{
1741 d014c98c bellard
#ifdef USE_FP_CONVERT
1742 d014c98c bellard
    FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
1743 d014c98c bellard
    FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1744 d014c98c bellard
#else
1745 927f621e bellard
    FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1746 d014c98c bellard
#endif
1747 927f621e bellard
}
1748 927f621e bellard
1749 927f621e bellard
void OPPROTO op_fildll_FT0_A0(void)
1750 927f621e bellard
{
1751 d014c98c bellard
#ifdef USE_FP_CONVERT
1752 d014c98c bellard
    FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
1753 d014c98c bellard
    FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1754 d014c98c bellard
#else
1755 927f621e bellard
    FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1756 d014c98c bellard
#endif
1757 927f621e bellard
}
1758 04369ff2 bellard
#endif
1759 927f621e bellard
1760 927f621e bellard
/* fp load ST0 */
1761 927f621e bellard
1762 927f621e bellard
void OPPROTO op_flds_ST0_A0(void)
1763 927f621e bellard
{
1764 d014c98c bellard
#ifdef USE_FP_CONVERT
1765 d014c98c bellard
    FP_CONVERT.i32 = ldl((void *)A0);
1766 d014c98c bellard
    ST0 = FP_CONVERT.f;
1767 d014c98c bellard
#else
1768 927f621e bellard
    ST0 = ldfl((void *)A0);
1769 d014c98c bellard
#endif
1770 927f621e bellard
}
1771 927f621e bellard
1772 927f621e bellard
void OPPROTO op_fldl_ST0_A0(void)
1773 927f621e bellard
{
1774 d014c98c bellard
#ifdef USE_FP_CONVERT
1775 d014c98c bellard
    FP_CONVERT.i64 = ldq((void *)A0);
1776 d014c98c bellard
    ST0 = FP_CONVERT.d;
1777 d014c98c bellard
#else
1778 927f621e bellard
    ST0 = ldfq((void *)A0);
1779 d014c98c bellard
#endif
1780 927f621e bellard
}
1781 927f621e bellard
1782 77f8dd5a bellard
#ifdef USE_X86LDOUBLE
1783 77f8dd5a bellard
void OPPROTO op_fldt_ST0_A0(void)
1784 77f8dd5a bellard
{
1785 77f8dd5a bellard
    ST0 = *(long double *)A0;
1786 77f8dd5a bellard
}
1787 77f8dd5a bellard
#else
1788 77f8dd5a bellard
void helper_fldt_ST0_A0(void)
1789 77f8dd5a bellard
{
1790 77f8dd5a bellard
    CPU86_LDoubleU temp;
1791 77f8dd5a bellard
    int upper, e;
1792 77f8dd5a bellard
    /* mantissa */
1793 77f8dd5a bellard
    upper = lduw((uint8_t *)A0 + 8);
1794 77f8dd5a bellard
    /* XXX: handle overflow ? */
1795 77f8dd5a bellard
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1796 77f8dd5a bellard
    e |= (upper >> 4) & 0x800; /* sign */
1797 77f8dd5a bellard
    temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
1798 77f8dd5a bellard
    ST0 = temp.d;
1799 77f8dd5a bellard
}
1800 77f8dd5a bellard
1801 77f8dd5a bellard
void OPPROTO op_fldt_ST0_A0(void)
1802 77f8dd5a bellard
{
1803 77f8dd5a bellard
    helper_fldt_ST0_A0();
1804 77f8dd5a bellard
}
1805 77f8dd5a bellard
#endif
1806 77f8dd5a bellard
1807 04369ff2 bellard
/* helpers are needed to avoid static constant reference. XXX: find a better way */
1808 04369ff2 bellard
#ifdef USE_INT_TO_FLOAT_HELPERS
1809 04369ff2 bellard
1810 04369ff2 bellard
void helper_fild_ST0_A0(void)
1811 04369ff2 bellard
{
1812 04369ff2 bellard
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1813 04369ff2 bellard
}
1814 04369ff2 bellard
1815 04369ff2 bellard
void helper_fildl_ST0_A0(void)
1816 04369ff2 bellard
{
1817 04369ff2 bellard
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1818 04369ff2 bellard
}
1819 04369ff2 bellard
1820 04369ff2 bellard
void helper_fildll_ST0_A0(void)
1821 04369ff2 bellard
{
1822 04369ff2 bellard
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1823 04369ff2 bellard
}
1824 04369ff2 bellard
1825 04369ff2 bellard
void OPPROTO op_fild_ST0_A0(void)
1826 04369ff2 bellard
{
1827 04369ff2 bellard
    helper_fild_ST0_A0();
1828 04369ff2 bellard
}
1829 04369ff2 bellard
1830 04369ff2 bellard
void OPPROTO op_fildl_ST0_A0(void)
1831 04369ff2 bellard
{
1832 04369ff2 bellard
    helper_fildl_ST0_A0();
1833 04369ff2 bellard
}
1834 04369ff2 bellard
1835 04369ff2 bellard
void OPPROTO op_fildll_ST0_A0(void)
1836 04369ff2 bellard
{
1837 04369ff2 bellard
    helper_fildll_ST0_A0();
1838 04369ff2 bellard
}
1839 04369ff2 bellard
1840 04369ff2 bellard
#else
1841 04369ff2 bellard
1842 927f621e bellard
void OPPROTO op_fild_ST0_A0(void)
1843 927f621e bellard
{
1844 d014c98c bellard
#ifdef USE_FP_CONVERT
1845 d014c98c bellard
    FP_CONVERT.i32 = ldsw((void *)A0);
1846 d014c98c bellard
    ST0 = (CPU86_LDouble)FP_CONVERT.i32;
1847 d014c98c bellard
#else
1848 927f621e bellard
    ST0 = (CPU86_LDouble)ldsw((void *)A0);
1849 d014c98c bellard
#endif
1850 927f621e bellard
}
1851 927f621e bellard
1852 927f621e bellard
void OPPROTO op_fildl_ST0_A0(void)
1853 927f621e bellard
{
1854 d014c98c bellard
#ifdef USE_FP_CONVERT
1855 d014c98c bellard
    FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
1856 d014c98c bellard
    ST0 = (CPU86_LDouble)FP_CONVERT.i32;
1857 d014c98c bellard
#else
1858 927f621e bellard
    ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1859 d014c98c bellard
#endif
1860 927f621e bellard
}
1861 927f621e bellard
1862 927f621e bellard
void OPPROTO op_fildll_ST0_A0(void)
1863 927f621e bellard
{
1864 d014c98c bellard
#ifdef USE_FP_CONVERT
1865 d014c98c bellard
    FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
1866 d014c98c bellard
    ST0 = (CPU86_LDouble)FP_CONVERT.i64;
1867 d014c98c bellard
#else
1868 927f621e bellard
    ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1869 d014c98c bellard
#endif
1870 927f621e bellard
}
1871 927f621e bellard
1872 04369ff2 bellard
#endif
1873 04369ff2 bellard
1874 927f621e bellard
/* fp store */
1875 927f621e bellard
1876 927f621e bellard
void OPPROTO op_fsts_ST0_A0(void)
1877 927f621e bellard
{
1878 d014c98c bellard
#ifdef USE_FP_CONVERT
1879 d014c98c bellard
    FP_CONVERT.d = ST0;
1880 d014c98c bellard
    stfl((void *)A0, FP_CONVERT.f);
1881 d014c98c bellard
#else
1882 927f621e bellard
    stfl((void *)A0, (float)ST0);
1883 d014c98c bellard
#endif
1884 927f621e bellard
}
1885 927f621e bellard
1886 927f621e bellard
void OPPROTO op_fstl_ST0_A0(void)
1887 927f621e bellard
{
1888 77f8dd5a bellard
    stfq((void *)A0, (double)ST0);
1889 927f621e bellard
}
1890 927f621e bellard
1891 77f8dd5a bellard
#ifdef USE_X86LDOUBLE
1892 77f8dd5a bellard
void OPPROTO op_fstt_ST0_A0(void)
1893 77f8dd5a bellard
{
1894 77f8dd5a bellard
    *(long double *)A0 = ST0;
1895 77f8dd5a bellard
}
1896 77f8dd5a bellard
#else
1897 77f8dd5a bellard
void helper_fstt_ST0_A0(void)
1898 77f8dd5a bellard
{
1899 77f8dd5a bellard
    CPU86_LDoubleU temp;
1900 77f8dd5a bellard
    int e;
1901 77f8dd5a bellard
    temp.d = ST0;
1902 77f8dd5a bellard
    /* mantissa */
1903 77f8dd5a bellard
    stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63));
1904 77f8dd5a bellard
    /* exponent + sign */
1905 77f8dd5a bellard
    e = EXPD(temp) - EXPBIAS + 16383;
1906 77f8dd5a bellard
    e |= SIGND(temp) >> 16;
1907 77f8dd5a bellard
    stw((uint8_t *)A0 + 8, e);
1908 77f8dd5a bellard
}
1909 77f8dd5a bellard
1910 77f8dd5a bellard
void OPPROTO op_fstt_ST0_A0(void)
1911 77f8dd5a bellard
{
1912 77f8dd5a bellard
    helper_fstt_ST0_A0();
1913 77f8dd5a bellard
}
1914 77f8dd5a bellard
#endif
1915 77f8dd5a bellard
1916 927f621e bellard
void OPPROTO op_fist_ST0_A0(void)
1917 927f621e bellard
{
1918 d014c98c bellard
#if defined(__sparc__) && !defined(__sparc_v9__)
1919 d014c98c bellard
    register CPU86_LDouble d asm("o0");
1920 d014c98c bellard
#else
1921 d014c98c bellard
    CPU86_LDouble d;
1922 d014c98c bellard
#endif
1923 927f621e bellard
    int val;
1924 d014c98c bellard
1925 d014c98c bellard
    d = ST0;
1926 d014c98c bellard
    val = lrint(d);
1927 927f621e bellard
    stw((void *)A0, val);
1928 927f621e bellard
}
1929 927f621e bellard
1930 927f621e bellard
void OPPROTO op_fistl_ST0_A0(void)
1931 927f621e bellard
{
1932 d014c98c bellard
#if defined(__sparc__) && !defined(__sparc_v9__)
1933 d014c98c bellard
    register CPU86_LDouble d asm("o0");
1934 d014c98c bellard
#else
1935 d014c98c bellard
    CPU86_LDouble d;
1936 d014c98c bellard
#endif
1937 927f621e bellard
    int val;
1938 d014c98c bellard
1939 d014c98c bellard
    d = ST0;
1940 d014c98c bellard
    val = lrint(d);
1941 927f621e bellard
    stl((void *)A0, val);
1942 927f621e bellard
}
1943 927f621e bellard
1944 927f621e bellard
void OPPROTO op_fistll_ST0_A0(void)
1945 927f621e bellard
{
1946 d014c98c bellard
#if defined(__sparc__) && !defined(__sparc_v9__)
1947 d014c98c bellard
    register CPU86_LDouble d asm("o0");
1948 d014c98c bellard
#else
1949 d014c98c bellard
    CPU86_LDouble d;
1950 d014c98c bellard
#endif
1951 927f621e bellard
    int64_t val;
1952 d014c98c bellard
1953 d014c98c bellard
    d = ST0;
1954 d014c98c bellard
    val = llrint(d);
1955 927f621e bellard
    stq((void *)A0, val);
1956 927f621e bellard
}
1957 927f621e bellard
1958 77f8dd5a bellard
/* BCD ops */
1959 77f8dd5a bellard
1960 77f8dd5a bellard
#define MUL10(iv) ( iv + iv + (iv << 3) )
1961 77f8dd5a bellard
1962 77f8dd5a bellard
void helper_fbld_ST0_A0(void)
1963 77f8dd5a bellard
{
1964 77f8dd5a bellard
    uint8_t *seg;
1965 77f8dd5a bellard
    CPU86_LDouble fpsrcop;
1966 77f8dd5a bellard
    int m32i;
1967 77f8dd5a bellard
    unsigned int v;
1968 77f8dd5a bellard
1969 77f8dd5a bellard
    /* in this code, seg/m32i will be used as temporary ptr/int */
1970 77f8dd5a bellard
    seg = (uint8_t *)A0 + 8;
1971 77f8dd5a bellard
    v = ldub(seg--);
1972 77f8dd5a bellard
    /* XXX: raise exception */
1973 77f8dd5a bellard
    if (v != 0)
1974 77f8dd5a bellard
        return;
1975 77f8dd5a bellard
    v = ldub(seg--);
1976 77f8dd5a bellard
    /* XXX: raise exception */
1977 77f8dd5a bellard
    if ((v & 0xf0) != 0)
1978 77f8dd5a bellard
        return;
1979 77f8dd5a bellard
    m32i = v;  /* <-- d14 */
1980 77f8dd5a bellard
    v = ldub(seg--);
1981 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
1982 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
1983 77f8dd5a bellard
    v = ldub(seg--);
1984 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
1985 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
1986 77f8dd5a bellard
    v = ldub(seg--);
1987 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
1988 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
1989 77f8dd5a bellard
    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
1990 77f8dd5a bellard
1991 77f8dd5a bellard
    v = ldub(seg--);
1992 77f8dd5a bellard
    m32i = (v >> 4);  /* <-- d7 */
1993 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
1994 77f8dd5a bellard
    v = ldub(seg--);
1995 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
1996 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
1997 77f8dd5a bellard
    v = ldub(seg--);
1998 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
1999 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
2000 77f8dd5a bellard
    v = ldub(seg);
2001 77f8dd5a bellard
    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
2002 77f8dd5a bellard
    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
2003 77f8dd5a bellard
    fpsrcop += ((CPU86_LDouble)m32i);
2004 77f8dd5a bellard
    if ( ldub(seg+9) & 0x80 )
2005 77f8dd5a bellard
        fpsrcop = -fpsrcop;
2006 77f8dd5a bellard
    ST0 = fpsrcop;
2007 77f8dd5a bellard
}
2008 77f8dd5a bellard
2009 77f8dd5a bellard
void OPPROTO op_fbld_ST0_A0(void)
2010 77f8dd5a bellard
{
2011 77f8dd5a bellard
    helper_fbld_ST0_A0();
2012 77f8dd5a bellard
}
2013 77f8dd5a bellard
2014 77f8dd5a bellard
void helper_fbst_ST0_A0(void)
2015 77f8dd5a bellard
{
2016 77f8dd5a bellard
    CPU86_LDouble fptemp;
2017 77f8dd5a bellard
    CPU86_LDouble fpsrcop;
2018 77f8dd5a bellard
    int v;
2019 77f8dd5a bellard
    uint8_t *mem_ref, *mem_end;
2020 77f8dd5a bellard
2021 77f8dd5a bellard
    fpsrcop = rint(ST0);
2022 77f8dd5a bellard
    mem_ref = (uint8_t *)A0;
2023 77f8dd5a bellard
    mem_end = mem_ref + 8;
2024 77f8dd5a bellard
    if ( fpsrcop < 0.0 ) {
2025 77f8dd5a bellard
        stw(mem_end, 0x8000);
2026 77f8dd5a bellard
        fpsrcop = -fpsrcop;
2027 77f8dd5a bellard
    } else {
2028 77f8dd5a bellard
        stw(mem_end, 0x0000);
2029 77f8dd5a bellard
    }
2030 77f8dd5a bellard
    while (mem_ref < mem_end) {
2031 77f8dd5a bellard
        if (fpsrcop == 0.0)
2032 77f8dd5a bellard
            break;
2033 77f8dd5a bellard
        fptemp = floor(fpsrcop/10.0);
2034 77f8dd5a bellard
        v = ((int)(fpsrcop - fptemp*10.0));
2035 77f8dd5a bellard
        if  (fptemp == 0.0)  { 
2036 77f8dd5a bellard
            stb(mem_ref++, v); 
2037 77f8dd5a bellard
            break; 
2038 77f8dd5a bellard
        }
2039 77f8dd5a bellard
        fpsrcop = fptemp;
2040 77f8dd5a bellard
        fptemp = floor(fpsrcop/10.0);
2041 77f8dd5a bellard
        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
2042 77f8dd5a bellard
        stb(mem_ref++, v);
2043 77f8dd5a bellard
        fpsrcop = fptemp;
2044 77f8dd5a bellard
    }
2045 77f8dd5a bellard
    while (mem_ref < mem_end) {
2046 77f8dd5a bellard
        stb(mem_ref++, 0);
2047 77f8dd5a bellard
    }
2048 77f8dd5a bellard
}
2049 77f8dd5a bellard
2050 77f8dd5a bellard
void OPPROTO op_fbst_ST0_A0(void)
2051 77f8dd5a bellard
{
2052 77f8dd5a bellard
    helper_fbst_ST0_A0();
2053 77f8dd5a bellard
}
2054 77f8dd5a bellard
2055 927f621e bellard
/* FPU move */
2056 927f621e bellard
2057 927f621e bellard
static inline void fpush(void)
2058 927f621e bellard
{
2059 927f621e bellard
    env->fpstt = (env->fpstt - 1) & 7;
2060 927f621e bellard
    env->fptags[env->fpstt] = 0; /* validate stack entry */
2061 927f621e bellard
}
2062 927f621e bellard
2063 927f621e bellard
static inline void fpop(void)
2064 927f621e bellard
{
2065 927f621e bellard
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
2066 927f621e bellard
    env->fpstt = (env->fpstt + 1) & 7;
2067 927f621e bellard
}
2068 927f621e bellard
2069 927f621e bellard
void OPPROTO op_fpush(void)
2070 927f621e bellard
{
2071 927f621e bellard
    fpush();
2072 927f621e bellard
}
2073 927f621e bellard
2074 927f621e bellard
void OPPROTO op_fpop(void)
2075 927f621e bellard
{
2076 927f621e bellard
    fpop();
2077 927f621e bellard
}
2078 927f621e bellard
2079 927f621e bellard
void OPPROTO op_fdecstp(void)
2080 927f621e bellard
{
2081 927f621e bellard
    env->fpstt = (env->fpstt - 1) & 7;
2082 927f621e bellard
    env->fpus &= (~0x4700);
2083 927f621e bellard
}
2084 927f621e bellard
2085 927f621e bellard
void OPPROTO op_fincstp(void)
2086 927f621e bellard
{
2087 927f621e bellard
    env->fpstt = (env->fpstt + 1) & 7;
2088 927f621e bellard
    env->fpus &= (~0x4700);
2089 927f621e bellard
}
2090 927f621e bellard
2091 927f621e bellard
void OPPROTO op_fmov_ST0_FT0(void)
2092 927f621e bellard
{
2093 927f621e bellard
    ST0 = FT0;
2094 927f621e bellard
}
2095 927f621e bellard
2096 927f621e bellard
void OPPROTO op_fmov_FT0_STN(void)
2097 927f621e bellard
{
2098 927f621e bellard
    FT0 = ST(PARAM1);
2099 927f621e bellard
}
2100 927f621e bellard
2101 927f621e bellard
void OPPROTO op_fmov_ST0_STN(void)
2102 927f621e bellard
{
2103 927f621e bellard
    ST0 = ST(PARAM1);
2104 927f621e bellard
}
2105 927f621e bellard
2106 927f621e bellard
void OPPROTO op_fmov_STN_ST0(void)
2107 927f621e bellard
{
2108 927f621e bellard
    ST(PARAM1) = ST0;
2109 927f621e bellard
}
2110 927f621e bellard
2111 927f621e bellard
void OPPROTO op_fxchg_ST0_STN(void)
2112 927f621e bellard
{
2113 927f621e bellard
    CPU86_LDouble tmp;
2114 927f621e bellard
    tmp = ST(PARAM1);
2115 927f621e bellard
    ST(PARAM1) = ST0;
2116 927f621e bellard
    ST0 = tmp;
2117 927f621e bellard
}
2118 927f621e bellard
2119 927f621e bellard
/* FPU operations */
2120 927f621e bellard
2121 927f621e bellard
/* XXX: handle nans */
2122 927f621e bellard
void OPPROTO op_fcom_ST0_FT0(void)
2123 927f621e bellard
{
2124 927f621e bellard
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
2125 927f621e bellard
    if (ST0 < FT0)
2126 927f621e bellard
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
2127 927f621e bellard
    else if (ST0 == FT0)
2128 927f621e bellard
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
2129 927f621e bellard
    FORCE_RET();
2130 927f621e bellard
}
2131 927f621e bellard
2132 77f8dd5a bellard
/* XXX: handle nans */
2133 77f8dd5a bellard
void OPPROTO op_fucom_ST0_FT0(void)
2134 77f8dd5a bellard
{
2135 77f8dd5a bellard
    env->fpus &= (~0x4500);        /* (C3,C2,C0) <-- 000 */
2136 77f8dd5a bellard
    if (ST0 < FT0)
2137 77f8dd5a bellard
        env->fpus |= 0x100;        /* (C3,C2,C0) <-- 001 */
2138 77f8dd5a bellard
    else if (ST0 == FT0)
2139 77f8dd5a bellard
        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
2140 77f8dd5a bellard
    FORCE_RET();
2141 77f8dd5a bellard
}
2142 77f8dd5a bellard
2143 927f621e bellard
void OPPROTO op_fadd_ST0_FT0(void)
2144 927f621e bellard
{
2145 927f621e bellard
    ST0 += FT0;
2146 927f621e bellard
}
2147 927f621e bellard
2148 927f621e bellard
void OPPROTO op_fmul_ST0_FT0(void)
2149 927f621e bellard
{
2150 927f621e bellard
    ST0 *= FT0;
2151 927f621e bellard
}
2152 927f621e bellard
2153 927f621e bellard
void OPPROTO op_fsub_ST0_FT0(void)
2154 927f621e bellard
{
2155 927f621e bellard
    ST0 -= FT0;
2156 927f621e bellard
}
2157 927f621e bellard
2158 927f621e bellard
void OPPROTO op_fsubr_ST0_FT0(void)
2159 927f621e bellard
{
2160 927f621e bellard
    ST0 = FT0 - ST0;
2161 927f621e bellard
}
2162 927f621e bellard
2163 927f621e bellard
void OPPROTO op_fdiv_ST0_FT0(void)
2164 927f621e bellard
{
2165 927f621e bellard
    ST0 /= FT0;
2166 927f621e bellard
}
2167 927f621e bellard
2168 927f621e bellard
void OPPROTO op_fdivr_ST0_FT0(void)
2169 927f621e bellard
{
2170 927f621e bellard
    ST0 = FT0 / ST0;
2171 927f621e bellard
}
2172 927f621e bellard
2173 927f621e bellard
/* fp operations between STN and ST0 */
2174 927f621e bellard
2175 927f621e bellard
void OPPROTO op_fadd_STN_ST0(void)
2176 927f621e bellard
{
2177 927f621e bellard
    ST(PARAM1) += ST0;
2178 927f621e bellard
}
2179 927f621e bellard
2180 927f621e bellard
void OPPROTO op_fmul_STN_ST0(void)
2181 927f621e bellard
{
2182 927f621e bellard
    ST(PARAM1) *= ST0;
2183 927f621e bellard
}
2184 927f621e bellard
2185 927f621e bellard
void OPPROTO op_fsub_STN_ST0(void)
2186 927f621e bellard
{
2187 927f621e bellard
    ST(PARAM1) -= ST0;
2188 927f621e bellard
}
2189 927f621e bellard
2190 927f621e bellard
void OPPROTO op_fsubr_STN_ST0(void)
2191 927f621e bellard
{
2192 927f621e bellard
    CPU86_LDouble *p;
2193 927f621e bellard
    p = &ST(PARAM1);
2194 927f621e bellard
    *p = ST0 - *p;
2195 927f621e bellard
}
2196 927f621e bellard
2197 927f621e bellard
void OPPROTO op_fdiv_STN_ST0(void)
2198 927f621e bellard
{
2199 927f621e bellard
    ST(PARAM1) /= ST0;
2200 927f621e bellard
}
2201 927f621e bellard
2202 927f621e bellard
void OPPROTO op_fdivr_STN_ST0(void)
2203 927f621e bellard
{
2204 927f621e bellard
    CPU86_LDouble *p;
2205 927f621e bellard
    p = &ST(PARAM1);
2206 927f621e bellard
    *p = ST0 / *p;
2207 927f621e bellard
}
2208 927f621e bellard
2209 927f621e bellard
/* misc FPU operations */
2210 927f621e bellard
void OPPROTO op_fchs_ST0(void)
2211 927f621e bellard
{
2212 927f621e bellard
    ST0 = -ST0;
2213 927f621e bellard
}
2214 927f621e bellard
2215 927f621e bellard
void OPPROTO op_fabs_ST0(void)
2216 927f621e bellard
{
2217 927f621e bellard
    ST0 = fabs(ST0);
2218 927f621e bellard
}
2219 927f621e bellard
2220 77f8dd5a bellard
void helper_fxam_ST0(void)
2221 927f621e bellard
{
2222 927f621e bellard
    CPU86_LDoubleU temp;
2223 927f621e bellard
    int expdif;
2224 927f621e bellard
2225 927f621e bellard
    temp.d = ST0;
2226 927f621e bellard
2227 927f621e bellard
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2228 927f621e bellard
    if (SIGND(temp))
2229 927f621e bellard
        env->fpus |= 0x200; /* C1 <-- 1 */
2230 927f621e bellard
2231 927f621e bellard
    expdif = EXPD(temp);
2232 927f621e bellard
    if (expdif == MAXEXPD) {
2233 927f621e bellard
        if (MANTD(temp) == 0)
2234 927f621e bellard
            env->fpus |=  0x500 /*Infinity*/;
2235 927f621e bellard
        else
2236 927f621e bellard
            env->fpus |=  0x100 /*NaN*/;
2237 927f621e bellard
    } else if (expdif == 0) {
2238 927f621e bellard
        if (MANTD(temp) == 0)
2239 927f621e bellard
            env->fpus |=  0x4000 /*Zero*/;
2240 927f621e bellard
        else
2241 927f621e bellard
            env->fpus |= 0x4400 /*Denormal*/;
2242 927f621e bellard
    } else {
2243 927f621e bellard
        env->fpus |= 0x400;
2244 927f621e bellard
    }
2245 77f8dd5a bellard
}
2246 77f8dd5a bellard
2247 77f8dd5a bellard
void OPPROTO op_fxam_ST0(void)
2248 77f8dd5a bellard
{
2249 77f8dd5a bellard
    helper_fxam_ST0();
2250 927f621e bellard
}
2251 927f621e bellard
2252 927f621e bellard
void OPPROTO op_fld1_ST0(void)
2253 927f621e bellard
{
2254 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[1];
2255 927f621e bellard
}
2256 927f621e bellard
2257 77f8dd5a bellard
void OPPROTO op_fldl2t_ST0(void)
2258 927f621e bellard
{
2259 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[6];
2260 927f621e bellard
}
2261 927f621e bellard
2262 77f8dd5a bellard
void OPPROTO op_fldl2e_ST0(void)
2263 927f621e bellard
{
2264 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[5];
2265 927f621e bellard
}
2266 927f621e bellard
2267 927f621e bellard
void OPPROTO op_fldpi_ST0(void)
2268 927f621e bellard
{
2269 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[2];
2270 927f621e bellard
}
2271 927f621e bellard
2272 927f621e bellard
void OPPROTO op_fldlg2_ST0(void)
2273 927f621e bellard
{
2274 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[3];
2275 927f621e bellard
}
2276 927f621e bellard
2277 927f621e bellard
void OPPROTO op_fldln2_ST0(void)
2278 927f621e bellard
{
2279 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[4];
2280 927f621e bellard
}
2281 927f621e bellard
2282 927f621e bellard
void OPPROTO op_fldz_ST0(void)
2283 927f621e bellard
{
2284 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[0];
2285 927f621e bellard
}
2286 927f621e bellard
2287 927f621e bellard
void OPPROTO op_fldz_FT0(void)
2288 927f621e bellard
{
2289 927f621e bellard
    ST0 = *(CPU86_LDouble *)&f15rk[0];
2290 927f621e bellard
}
2291 927f621e bellard
2292 927f621e bellard
void helper_f2xm1(void)
2293 927f621e bellard
{
2294 927f621e bellard
    ST0 = pow(2.0,ST0) - 1.0;
2295 927f621e bellard
}
2296 927f621e bellard
2297 927f621e bellard
void helper_fyl2x(void)
2298 927f621e bellard
{
2299 927f621e bellard
    CPU86_LDouble fptemp;
2300 927f621e bellard
    
2301 927f621e bellard
    fptemp = ST0;
2302 927f621e bellard
    if (fptemp>0.0){
2303 927f621e bellard
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
2304 927f621e bellard
        ST1 *= fptemp;
2305 927f621e bellard
        fpop();
2306 927f621e bellard
    } else { 
2307 927f621e bellard
        env->fpus &= (~0x4700);
2308 927f621e bellard
        env->fpus |= 0x400;
2309 927f621e bellard
    }
2310 927f621e bellard
}
2311 927f621e bellard
2312 927f621e bellard
void helper_fptan(void)
2313 927f621e bellard
{
2314 927f621e bellard
    CPU86_LDouble fptemp;
2315 927f621e bellard
2316 927f621e bellard
    fptemp = ST0;
2317 927f621e bellard
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2318 927f621e bellard
        env->fpus |= 0x400;
2319 927f621e bellard
    } else {
2320 927f621e bellard
        ST0 = tan(fptemp);
2321 927f621e bellard
        fpush();
2322 927f621e bellard
        ST0 = 1.0;
2323 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2324 927f621e bellard
        /* the above code is for  |arg| < 2**52 only */
2325 927f621e bellard
    }
2326 927f621e bellard
}
2327 927f621e bellard
2328 927f621e bellard
void helper_fpatan(void)
2329 927f621e bellard
{
2330 927f621e bellard
    CPU86_LDouble fptemp, fpsrcop;
2331 927f621e bellard
2332 927f621e bellard
    fpsrcop = ST1;
2333 927f621e bellard
    fptemp = ST0;
2334 927f621e bellard
    ST1 = atan2(fpsrcop,fptemp);
2335 927f621e bellard
    fpop();
2336 927f621e bellard
}
2337 927f621e bellard
2338 927f621e bellard
void helper_fxtract(void)
2339 927f621e bellard
{
2340 927f621e bellard
    CPU86_LDoubleU temp;
2341 927f621e bellard
    unsigned int expdif;
2342 927f621e bellard
2343 927f621e bellard
    temp.d = ST0;
2344 927f621e bellard
    expdif = EXPD(temp) - EXPBIAS;
2345 927f621e bellard
    /*DP exponent bias*/
2346 927f621e bellard
    ST0 = expdif;
2347 927f621e bellard
    fpush();
2348 927f621e bellard
    BIASEXPONENT(temp);
2349 927f621e bellard
    ST0 = temp.d;
2350 927f621e bellard
}
2351 927f621e bellard
2352 927f621e bellard
void helper_fprem1(void)
2353 927f621e bellard
{
2354 927f621e bellard
    CPU86_LDouble dblq, fpsrcop, fptemp;
2355 927f621e bellard
    CPU86_LDoubleU fpsrcop1, fptemp1;
2356 927f621e bellard
    int expdif;
2357 927f621e bellard
    int q;
2358 927f621e bellard
2359 927f621e bellard
    fpsrcop = ST0;
2360 927f621e bellard
    fptemp = ST1;
2361 927f621e bellard
    fpsrcop1.d = fpsrcop;
2362 927f621e bellard
    fptemp1.d = fptemp;
2363 927f621e bellard
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2364 927f621e bellard
    if (expdif < 53) {
2365 927f621e bellard
        dblq = fpsrcop / fptemp;
2366 927f621e bellard
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2367 927f621e bellard
        ST0 = fpsrcop - fptemp*dblq;
2368 927f621e bellard
        q = (int)dblq; /* cutting off top bits is assumed here */
2369 927f621e bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2370 927f621e bellard
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
2371 927f621e bellard
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2372 927f621e bellard
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2373 927f621e bellard
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2374 927f621e bellard
    } else {
2375 927f621e bellard
        env->fpus |= 0x400;  /* C2 <-- 1 */
2376 927f621e bellard
        fptemp = pow(2.0, expdif-50);
2377 927f621e bellard
        fpsrcop = (ST0 / ST1) / fptemp;
2378 927f621e bellard
        /* fpsrcop = integer obtained by rounding to the nearest */
2379 927f621e bellard
        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
2380 927f621e bellard
            floor(fpsrcop): ceil(fpsrcop);
2381 927f621e bellard
        ST0 -= (ST1 * fpsrcop * fptemp);
2382 927f621e bellard
    }
2383 927f621e bellard
}
2384 927f621e bellard
2385 927f621e bellard
void helper_fprem(void)
2386 927f621e bellard
{
2387 927f621e bellard
    CPU86_LDouble dblq, fpsrcop, fptemp;
2388 927f621e bellard
    CPU86_LDoubleU fpsrcop1, fptemp1;
2389 927f621e bellard
    int expdif;
2390 927f621e bellard
    int q;
2391 927f621e bellard
    
2392 927f621e bellard
    fpsrcop = ST0;
2393 927f621e bellard
    fptemp = ST1;
2394 927f621e bellard
    fpsrcop1.d = fpsrcop;
2395 927f621e bellard
    fptemp1.d = fptemp;
2396 927f621e bellard
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2397 927f621e bellard
    if ( expdif < 53 ) {
2398 927f621e bellard
        dblq = fpsrcop / fptemp;
2399 927f621e bellard
        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2400 927f621e bellard
        ST0 = fpsrcop - fptemp*dblq;
2401 927f621e bellard
        q = (int)dblq; /* cutting off top bits is assumed here */
2402 927f621e bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2403 927f621e bellard
                                /* (C0,C1,C3) <-- (q2,q1,q0) */
2404 927f621e bellard
        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2405 927f621e bellard
        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2406 927f621e bellard
        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2407 927f621e bellard
    } else {
2408 927f621e bellard
        env->fpus |= 0x400;  /* C2 <-- 1 */
2409 927f621e bellard
        fptemp = pow(2.0, expdif-50);
2410 927f621e bellard
        fpsrcop = (ST0 / ST1) / fptemp;
2411 927f621e bellard
        /* fpsrcop = integer obtained by chopping */
2412 927f621e bellard
        fpsrcop = (fpsrcop < 0.0)?
2413 927f621e bellard
            -(floor(fabs(fpsrcop))): floor(fpsrcop);
2414 927f621e bellard
        ST0 -= (ST1 * fpsrcop * fptemp);
2415 927f621e bellard
    }
2416 927f621e bellard
}
2417 927f621e bellard
2418 927f621e bellard
void helper_fyl2xp1(void)
2419 927f621e bellard
{
2420 927f621e bellard
    CPU86_LDouble fptemp;
2421 927f621e bellard
2422 927f621e bellard
    fptemp = ST0;
2423 927f621e bellard
    if ((fptemp+1.0)>0.0) {
2424 927f621e bellard
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
2425 927f621e bellard
        ST1 *= fptemp;
2426 927f621e bellard
        fpop();
2427 927f621e bellard
    } else { 
2428 927f621e bellard
        env->fpus &= (~0x4700);
2429 927f621e bellard
        env->fpus |= 0x400;
2430 927f621e bellard
    }
2431 927f621e bellard
}
2432 927f621e bellard
2433 927f621e bellard
void helper_fsqrt(void)
2434 927f621e bellard
{
2435 927f621e bellard
    CPU86_LDouble fptemp;
2436 927f621e bellard
2437 927f621e bellard
    fptemp = ST0;
2438 927f621e bellard
    if (fptemp<0.0) { 
2439 927f621e bellard
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2440 927f621e bellard
        env->fpus |= 0x400;
2441 927f621e bellard
    }
2442 927f621e bellard
    ST0 = sqrt(fptemp);
2443 927f621e bellard
}
2444 927f621e bellard
2445 927f621e bellard
void helper_fsincos(void)
2446 927f621e bellard
{
2447 927f621e bellard
    CPU86_LDouble fptemp;
2448 927f621e bellard
2449 927f621e bellard
    fptemp = ST0;
2450 927f621e bellard
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2451 927f621e bellard
        env->fpus |= 0x400;
2452 927f621e bellard
    } else {
2453 927f621e bellard
        ST0 = sin(fptemp);
2454 927f621e bellard
        fpush();
2455 927f621e bellard
        ST0 = cos(fptemp);
2456 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2457 927f621e bellard
        /* the above code is for  |arg| < 2**63 only */
2458 927f621e bellard
    }
2459 927f621e bellard
}
2460 927f621e bellard
2461 927f621e bellard
void helper_frndint(void)
2462 927f621e bellard
{
2463 927f621e bellard
    ST0 = rint(ST0);
2464 927f621e bellard
}
2465 927f621e bellard
2466 927f621e bellard
void helper_fscale(void)
2467 927f621e bellard
{
2468 927f621e bellard
    CPU86_LDouble fpsrcop, fptemp;
2469 927f621e bellard
2470 927f621e bellard
    fpsrcop = 2.0;
2471 927f621e bellard
    fptemp = pow(fpsrcop,ST1);
2472 927f621e bellard
    ST0 *= fptemp;
2473 927f621e bellard
}
2474 927f621e bellard
2475 927f621e bellard
void helper_fsin(void)
2476 927f621e bellard
{
2477 927f621e bellard
    CPU86_LDouble fptemp;
2478 927f621e bellard
2479 927f621e bellard
    fptemp = ST0;
2480 927f621e bellard
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2481 927f621e bellard
        env->fpus |= 0x400;
2482 927f621e bellard
    } else {
2483 927f621e bellard
        ST0 = sin(fptemp);
2484 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2485 927f621e bellard
        /* the above code is for  |arg| < 2**53 only */
2486 927f621e bellard
    }
2487 927f621e bellard
}
2488 927f621e bellard
2489 927f621e bellard
void helper_fcos(void)
2490 927f621e bellard
{
2491 927f621e bellard
    CPU86_LDouble fptemp;
2492 927f621e bellard
2493 927f621e bellard
    fptemp = ST0;
2494 927f621e bellard
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2495 927f621e bellard
        env->fpus |= 0x400;
2496 927f621e bellard
    } else {
2497 927f621e bellard
        ST0 = cos(fptemp);
2498 927f621e bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
2499 927f621e bellard
        /* the above code is for  |arg5 < 2**63 only */
2500 927f621e bellard
    }
2501 927f621e bellard
}
2502 927f621e bellard
2503 927f621e bellard
/* associated heplers to reduce generated code length and to simplify
2504 927f621e bellard
   relocation (FP constants are usually stored in .rodata section) */
2505 927f621e bellard
2506 927f621e bellard
void OPPROTO op_f2xm1(void)
2507 927f621e bellard
{
2508 927f621e bellard
    helper_f2xm1();
2509 927f621e bellard
}
2510 927f621e bellard
2511 927f621e bellard
void OPPROTO op_fyl2x(void)
2512 927f621e bellard
{
2513 927f621e bellard
    helper_fyl2x();
2514 927f621e bellard
}
2515 927f621e bellard
2516 927f621e bellard
void OPPROTO op_fptan(void)
2517 927f621e bellard
{
2518 927f621e bellard
    helper_fptan();
2519 927f621e bellard
}
2520 927f621e bellard
2521 927f621e bellard
void OPPROTO op_fpatan(void)
2522 927f621e bellard
{
2523 927f621e bellard
    helper_fpatan();
2524 927f621e bellard
}
2525 927f621e bellard
2526 927f621e bellard
void OPPROTO op_fxtract(void)
2527 927f621e bellard
{
2528 927f621e bellard
    helper_fxtract();
2529 927f621e bellard
}
2530 927f621e bellard
2531 927f621e bellard
void OPPROTO op_fprem1(void)
2532 927f621e bellard
{
2533 927f621e bellard
    helper_fprem1();
2534 927f621e bellard
}
2535 927f621e bellard
2536 927f621e bellard
2537 927f621e bellard
void OPPROTO op_fprem(void)
2538 927f621e bellard
{
2539 927f621e bellard
    helper_fprem();
2540 927f621e bellard
}
2541 927f621e bellard
2542 927f621e bellard
void OPPROTO op_fyl2xp1(void)
2543 927f621e bellard
{
2544 927f621e bellard
    helper_fyl2xp1();
2545 927f621e bellard
}
2546 927f621e bellard
2547 927f621e bellard
void OPPROTO op_fsqrt(void)
2548 927f621e bellard
{
2549 927f621e bellard
    helper_fsqrt();
2550 927f621e bellard
}
2551 927f621e bellard
2552 927f621e bellard
void OPPROTO op_fsincos(void)
2553 927f621e bellard
{
2554 927f621e bellard
    helper_fsincos();
2555 927f621e bellard
}
2556 927f621e bellard
2557 927f621e bellard
void OPPROTO op_frndint(void)
2558 927f621e bellard
{
2559 927f621e bellard
    helper_frndint();
2560 927f621e bellard
}
2561 927f621e bellard
2562 927f621e bellard
void OPPROTO op_fscale(void)
2563 927f621e bellard
{
2564 927f621e bellard
    helper_fscale();
2565 927f621e bellard
}
2566 927f621e bellard
2567 927f621e bellard
void OPPROTO op_fsin(void)
2568 927f621e bellard
{
2569 927f621e bellard
    helper_fsin();
2570 927f621e bellard
}
2571 927f621e bellard
2572 927f621e bellard
void OPPROTO op_fcos(void)
2573 927f621e bellard
{
2574 927f621e bellard
    helper_fcos();
2575 927f621e bellard
}
2576 927f621e bellard
2577 4b74fe1f bellard
void OPPROTO op_fnstsw_A0(void)
2578 4b74fe1f bellard
{
2579 4b74fe1f bellard
    int fpus;
2580 4b74fe1f bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2581 4b74fe1f bellard
    stw((void *)A0, fpus);
2582 4b74fe1f bellard
}
2583 4b74fe1f bellard
2584 77f8dd5a bellard
void OPPROTO op_fnstsw_EAX(void)
2585 77f8dd5a bellard
{
2586 77f8dd5a bellard
    int fpus;
2587 77f8dd5a bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2588 77f8dd5a bellard
    EAX = (EAX & 0xffff0000) | fpus;
2589 77f8dd5a bellard
}
2590 77f8dd5a bellard
2591 4b74fe1f bellard
void OPPROTO op_fnstcw_A0(void)
2592 4b74fe1f bellard
{
2593 4b74fe1f bellard
    stw((void *)A0, env->fpuc);
2594 4b74fe1f bellard
}
2595 4b74fe1f bellard
2596 4b74fe1f bellard
void OPPROTO op_fldcw_A0(void)
2597 4b74fe1f bellard
{
2598 4b74fe1f bellard
    int rnd_type;
2599 4b74fe1f bellard
    env->fpuc = lduw((void *)A0);
2600 4b74fe1f bellard
    /* set rounding mode */
2601 4b74fe1f bellard
    switch(env->fpuc & RC_MASK) {
2602 4b74fe1f bellard
    default:
2603 4b74fe1f bellard
    case RC_NEAR:
2604 4b74fe1f bellard
        rnd_type = FE_TONEAREST;
2605 4b74fe1f bellard
        break;
2606 4b74fe1f bellard
    case RC_DOWN:
2607 4b74fe1f bellard
        rnd_type = FE_DOWNWARD;
2608 4b74fe1f bellard
        break;
2609 4b74fe1f bellard
    case RC_UP:
2610 4b74fe1f bellard
        rnd_type = FE_UPWARD;
2611 4b74fe1f bellard
        break;
2612 4b74fe1f bellard
    case RC_CHOP:
2613 4b74fe1f bellard
        rnd_type = FE_TOWARDZERO;
2614 4b74fe1f bellard
        break;
2615 4b74fe1f bellard
    }
2616 4b74fe1f bellard
    fesetround(rnd_type);
2617 4b74fe1f bellard
}
2618 4b74fe1f bellard
2619 1a9353d2 bellard
void OPPROTO op_fclex(void)
2620 1a9353d2 bellard
{
2621 1a9353d2 bellard
    env->fpus &= 0x7f00;
2622 1a9353d2 bellard
}
2623 1a9353d2 bellard
2624 1a9353d2 bellard
void OPPROTO op_fninit(void)
2625 1a9353d2 bellard
{
2626 1a9353d2 bellard
    env->fpus = 0;
2627 1a9353d2 bellard
    env->fpstt = 0;
2628 1a9353d2 bellard
    env->fpuc = 0x37f;
2629 1a9353d2 bellard
    env->fptags[0] = 1;
2630 1a9353d2 bellard
    env->fptags[1] = 1;
2631 1a9353d2 bellard
    env->fptags[2] = 1;
2632 1a9353d2 bellard
    env->fptags[3] = 1;
2633 1a9353d2 bellard
    env->fptags[4] = 1;
2634 1a9353d2 bellard
    env->fptags[5] = 1;
2635 1a9353d2 bellard
    env->fptags[6] = 1;
2636 1a9353d2 bellard
    env->fptags[7] = 1;
2637 1a9353d2 bellard
}
2638 1b6b029e bellard
2639 1b6b029e bellard
/* threading support */
2640 1b6b029e bellard
void OPPROTO op_lock(void)
2641 1b6b029e bellard
{
2642 1b6b029e bellard
    cpu_lock();
2643 1b6b029e bellard
}
2644 1b6b029e bellard
2645 1b6b029e bellard
void OPPROTO op_unlock(void)
2646 1b6b029e bellard
{
2647 1b6b029e bellard
    cpu_unlock();
2648 1b6b029e bellard
}