Statistics
| Branch: | Revision:

root / op-i386.c @ e3b32540

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

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