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