]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/op.c
use TCG for MMX/SSE memory accesses
[mirror_qemu.git] / target-i386 / op.c
CommitLineData
2c0262af
FB
1/*
2 * i386 micro operations
5fafdf24 3 *
2c0262af
FB
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
f68dd770 20
f68dd770 21#define ASM_SOFTMMU
2c0262af
FB
22#include "exec.h"
23
24/* n must be a constant to be efficient */
14ce26e7 25static inline target_long lshift(target_long x, int n)
2c0262af
FB
26{
27 if (n >= 0)
28 return x << n;
29 else
30 return x >> (-n);
31}
32
33/* we define the various pieces of code used by the JIT */
34
35#define REG EAX
36#define REGNAME _EAX
37#include "opreg_template.h"
38#undef REG
39#undef REGNAME
40
41#define REG ECX
42#define REGNAME _ECX
43#include "opreg_template.h"
44#undef REG
45#undef REGNAME
46
47#define REG EDX
48#define REGNAME _EDX
49#include "opreg_template.h"
50#undef REG
51#undef REGNAME
52
53#define REG EBX
54#define REGNAME _EBX
55#include "opreg_template.h"
56#undef REG
57#undef REGNAME
58
59#define REG ESP
60#define REGNAME _ESP
61#include "opreg_template.h"
62#undef REG
63#undef REGNAME
64
65#define REG EBP
66#define REGNAME _EBP
67#include "opreg_template.h"
68#undef REG
69#undef REGNAME
70
71#define REG ESI
72#define REGNAME _ESI
73#include "opreg_template.h"
74#undef REG
75#undef REGNAME
76
77#define REG EDI
78#define REGNAME _EDI
79#include "opreg_template.h"
80#undef REG
81#undef REGNAME
82
14ce26e7
FB
83#ifdef TARGET_X86_64
84
85#define REG (env->regs[8])
86#define REGNAME _R8
87#include "opreg_template.h"
88#undef REG
89#undef REGNAME
90
91#define REG (env->regs[9])
92#define REGNAME _R9
93#include "opreg_template.h"
94#undef REG
95#undef REGNAME
96
97#define REG (env->regs[10])
98#define REGNAME _R10
99#include "opreg_template.h"
100#undef REG
101#undef REGNAME
102
103#define REG (env->regs[11])
104#define REGNAME _R11
105#include "opreg_template.h"
106#undef REG
107#undef REGNAME
108
109#define REG (env->regs[12])
110#define REGNAME _R12
111#include "opreg_template.h"
112#undef REG
113#undef REGNAME
114
115#define REG (env->regs[13])
116#define REGNAME _R13
117#include "opreg_template.h"
118#undef REG
119#undef REGNAME
120
121#define REG (env->regs[14])
122#define REGNAME _R14
123#include "opreg_template.h"
124#undef REG
125#undef REGNAME
126
127#define REG (env->regs[15])
128#define REGNAME _R15
129#include "opreg_template.h"
130#undef REG
131#undef REGNAME
132
133#endif
134
2c0262af
FB
135/* operations with flags */
136
137/* update flags with T0 and T1 (add/sub case) */
138void OPPROTO op_update2_cc(void)
139{
140 CC_SRC = T1;
141 CC_DST = T0;
142}
143
144/* update flags with T0 (logic operation case) */
145void OPPROTO op_update1_cc(void)
146{
147 CC_DST = T0;
148}
149
150void OPPROTO op_update_neg_cc(void)
151{
152 CC_SRC = -T0;
153 CC_DST = T0;
154}
155
156void OPPROTO op_cmpl_T0_T1_cc(void)
157{
158 CC_SRC = T1;
159 CC_DST = T0 - T1;
160}
161
162void OPPROTO op_update_inc_cc(void)
163{
164 CC_SRC = cc_table[CC_OP].compute_c();
165 CC_DST = T0;
166}
167
168void OPPROTO op_testl_T0_T1_cc(void)
169{
170 CC_DST = T0 & T1;
171}
172
173/* operations without flags */
174
2c0262af
FB
175void OPPROTO op_negl_T0(void)
176{
177 T0 = -T0;
178}
179
180void OPPROTO op_incl_T0(void)
181{
182 T0++;
183}
184
185void OPPROTO op_decl_T0(void)
186{
187 T0--;
188}
189
190void OPPROTO op_notl_T0(void)
191{
192 T0 = ~T0;
193}
194
2c0262af 195/* multiply/divide */
d36cd60e
FB
196
197/* XXX: add eflags optimizations */
198/* XXX: add non P4 style flags */
199
2c0262af
FB
200void OPPROTO op_mulb_AL_T0(void)
201{
202 unsigned int res;
203 res = (uint8_t)EAX * (uint8_t)T0;
14ce26e7 204 EAX = (EAX & ~0xffff) | res;
d36cd60e 205 CC_DST = res;
2c0262af
FB
206 CC_SRC = (res & 0xff00);
207}
208
209void OPPROTO op_imulb_AL_T0(void)
210{
211 int res;
212 res = (int8_t)EAX * (int8_t)T0;
14ce26e7 213 EAX = (EAX & ~0xffff) | (res & 0xffff);
d36cd60e 214 CC_DST = res;
2c0262af
FB
215 CC_SRC = (res != (int8_t)res);
216}
217
218void OPPROTO op_mulw_AX_T0(void)
219{
220 unsigned int res;
221 res = (uint16_t)EAX * (uint16_t)T0;
14ce26e7
FB
222 EAX = (EAX & ~0xffff) | (res & 0xffff);
223 EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
d36cd60e 224 CC_DST = res;
2c0262af
FB
225 CC_SRC = res >> 16;
226}
227
228void OPPROTO op_imulw_AX_T0(void)
229{
230 int res;
231 res = (int16_t)EAX * (int16_t)T0;
14ce26e7
FB
232 EAX = (EAX & ~0xffff) | (res & 0xffff);
233 EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
d36cd60e 234 CC_DST = res;
2c0262af
FB
235 CC_SRC = (res != (int16_t)res);
236}
237
238void OPPROTO op_mull_EAX_T0(void)
239{
240 uint64_t res;
241 res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
14ce26e7
FB
242 EAX = (uint32_t)res;
243 EDX = (uint32_t)(res >> 32);
244 CC_DST = (uint32_t)res;
245 CC_SRC = (uint32_t)(res >> 32);
2c0262af
FB
246}
247
248void OPPROTO op_imull_EAX_T0(void)
249{
250 int64_t res;
251 res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
31313213
FB
252 EAX = (uint32_t)(res);
253 EDX = (uint32_t)(res >> 32);
d36cd60e 254 CC_DST = res;
2c0262af
FB
255 CC_SRC = (res != (int32_t)res);
256}
257
258void OPPROTO op_imulw_T0_T1(void)
259{
260 int res;
261 res = (int16_t)T0 * (int16_t)T1;
262 T0 = res;
d36cd60e 263 CC_DST = res;
2c0262af
FB
264 CC_SRC = (res != (int16_t)res);
265}
266
267void OPPROTO op_imull_T0_T1(void)
268{
269 int64_t res;
270 res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
271 T0 = res;
d36cd60e 272 CC_DST = res;
2c0262af
FB
273 CC_SRC = (res != (int32_t)res);
274}
275
14ce26e7
FB
276#ifdef TARGET_X86_64
277void OPPROTO op_mulq_EAX_T0(void)
278{
279 helper_mulq_EAX_T0();
280}
281
282void OPPROTO op_imulq_EAX_T0(void)
283{
284 helper_imulq_EAX_T0();
285}
286
287void OPPROTO op_imulq_T0_T1(void)
288{
289 helper_imulq_T0_T1();
290}
291#endif
292
2c0262af 293/* division, flags are undefined */
2c0262af
FB
294
295void OPPROTO op_divb_AL_T0(void)
296{
297 unsigned int num, den, q, r;
298
299 num = (EAX & 0xffff);
300 den = (T0 & 0xff);
301 if (den == 0) {
2c0262af
FB
302 raise_exception(EXCP00_DIVZ);
303 }
45bbbb46
FB
304 q = (num / den);
305 if (q > 0xff)
306 raise_exception(EXCP00_DIVZ);
307 q &= 0xff;
2c0262af 308 r = (num % den) & 0xff;
14ce26e7 309 EAX = (EAX & ~0xffff) | (r << 8) | q;
2c0262af
FB
310}
311
312void OPPROTO op_idivb_AL_T0(void)
313{
314 int num, den, q, r;
315
316 num = (int16_t)EAX;
317 den = (int8_t)T0;
318 if (den == 0) {
2c0262af
FB
319 raise_exception(EXCP00_DIVZ);
320 }
45bbbb46
FB
321 q = (num / den);
322 if (q != (int8_t)q)
323 raise_exception(EXCP00_DIVZ);
324 q &= 0xff;
2c0262af 325 r = (num % den) & 0xff;
14ce26e7 326 EAX = (EAX & ~0xffff) | (r << 8) | q;
2c0262af
FB
327}
328
329void OPPROTO op_divw_AX_T0(void)
330{
331 unsigned int num, den, q, r;
332
333 num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
334 den = (T0 & 0xffff);
335 if (den == 0) {
2c0262af
FB
336 raise_exception(EXCP00_DIVZ);
337 }
45bbbb46
FB
338 q = (num / den);
339 if (q > 0xffff)
340 raise_exception(EXCP00_DIVZ);
341 q &= 0xffff;
2c0262af 342 r = (num % den) & 0xffff;
14ce26e7
FB
343 EAX = (EAX & ~0xffff) | q;
344 EDX = (EDX & ~0xffff) | r;
2c0262af
FB
345}
346
347void OPPROTO op_idivw_AX_T0(void)
348{
349 int num, den, q, r;
350
351 num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
352 den = (int16_t)T0;
353 if (den == 0) {
2c0262af
FB
354 raise_exception(EXCP00_DIVZ);
355 }
45bbbb46
FB
356 q = (num / den);
357 if (q != (int16_t)q)
358 raise_exception(EXCP00_DIVZ);
359 q &= 0xffff;
2c0262af 360 r = (num % den) & 0xffff;
14ce26e7
FB
361 EAX = (EAX & ~0xffff) | q;
362 EDX = (EDX & ~0xffff) | r;
2c0262af
FB
363}
364
14ce26e7
FB
365#ifdef TARGET_X86_64
366void OPPROTO op_divq_EAX_T0(void)
367{
368 helper_divq_EAX_T0();
369}
370
371void OPPROTO op_idivq_EAX_T0(void)
372{
373 helper_idivq_EAX_T0();
374}
375#endif
376
2c0262af
FB
377/* constant load & misc op */
378
14ce26e7 379/* XXX: consistent names */
2c0262af
FB
380void OPPROTO op_addl_T1_im(void)
381{
382 T1 += PARAM1;
383}
384
385void OPPROTO op_movl_T1_A0(void)
386{
387 T1 = A0;
388}
389
2c0262af
FB
390void OPPROTO op_addl_A0_AL(void)
391{
14ce26e7
FB
392 A0 = (uint32_t)(A0 + (EAX & 0xff));
393}
394
395#ifdef WORDS_BIGENDIAN
396typedef union UREG64 {
397 struct { uint16_t v3, v2, v1, v0; } w;
398 struct { uint32_t v1, v0; } l;
399 uint64_t q;
400} UREG64;
401#else
402typedef union UREG64 {
403 struct { uint16_t v0, v1, v2, v3; } w;
404 struct { uint32_t v0, v1; } l;
405 uint64_t q;
406} UREG64;
407#endif
408
14ce26e7
FB
409#define PARAMQ1 \
410({\
411 UREG64 __p;\
412 __p.l.v1 = PARAM1;\
413 __p.l.v0 = PARAM2;\
414 __p.q;\
5fafdf24 415})
14ce26e7 416
0573fbfc
TS
417#ifdef TARGET_X86_64
418
14ce26e7
FB
419void OPPROTO op_addq_A0_AL(void)
420{
421 A0 = (A0 + (EAX & 0xff));
422}
423
424#endif
425
2c0262af
FB
426void OPPROTO op_hlt(void)
427{
3d7374c5
FB
428 helper_hlt();
429}
430
431void OPPROTO op_monitor(void)
432{
433 helper_monitor();
434}
435
436void OPPROTO op_mwait(void)
437{
438 helper_mwait();
2c0262af
FB
439}
440
441void OPPROTO op_debug(void)
442{
443 env->exception_index = EXCP_DEBUG;
444 cpu_loop_exit();
445}
446
447void OPPROTO op_raise_interrupt(void)
448{
a8ede8ba 449 int intno, next_eip_addend;
2c0262af 450 intno = PARAM1;
a8ede8ba
FB
451 next_eip_addend = PARAM2;
452 raise_interrupt(intno, 1, 0, next_eip_addend);
2c0262af
FB
453}
454
455void OPPROTO op_raise_exception(void)
456{
457 int exception_index;
458 exception_index = PARAM1;
459 raise_exception(exception_index);
460}
461
462void OPPROTO op_into(void)
463{
464 int eflags;
465 eflags = cc_table[CC_OP].compute_all();
466 if (eflags & CC_O) {
467 raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
468 }
469 FORCE_RET();
470}
471
472void OPPROTO op_cli(void)
473{
474 env->eflags &= ~IF_MASK;
475}
476
477void OPPROTO op_sti(void)
478{
479 env->eflags |= IF_MASK;
480}
481
482void OPPROTO op_set_inhibit_irq(void)
483{
484 env->hflags |= HF_INHIBIT_IRQ_MASK;
485}
486
487void OPPROTO op_reset_inhibit_irq(void)
488{
489 env->hflags &= ~HF_INHIBIT_IRQ_MASK;
490}
491
3b21e03e
FB
492void OPPROTO op_rsm(void)
493{
494 helper_rsm();
495}
496
2c0262af
FB
497#if 0
498/* vm86plus instructions */
499void OPPROTO op_cli_vm(void)
500{
501 env->eflags &= ~VIF_MASK;
502}
503
504void OPPROTO op_sti_vm(void)
505{
506 env->eflags |= VIF_MASK;
507 if (env->eflags & VIP_MASK) {
508 EIP = PARAM1;
509 raise_exception(EXCP0D_GPF);
510 }
511 FORCE_RET();
512}
513#endif
514
515void OPPROTO op_boundw(void)
516{
517 int low, high, v;
14ce26e7
FB
518 low = ldsw(A0);
519 high = ldsw(A0 + 2);
2c0262af
FB
520 v = (int16_t)T0;
521 if (v < low || v > high) {
2c0262af
FB
522 raise_exception(EXCP05_BOUND);
523 }
524 FORCE_RET();
525}
526
527void OPPROTO op_boundl(void)
528{
529 int low, high, v;
14ce26e7
FB
530 low = ldl(A0);
531 high = ldl(A0 + 4);
2c0262af
FB
532 v = T0;
533 if (v < low || v > high) {
2c0262af
FB
534 raise_exception(EXCP05_BOUND);
535 }
536 FORCE_RET();
537}
538
539void OPPROTO op_cmpxchg8b(void)
540{
541 helper_cmpxchg8b();
542}
543
88fe8a41
TS
544void OPPROTO op_single_step(void)
545{
546 helper_single_step();
547}
548
2c0262af
FB
549/* multiple size ops */
550
551#define ldul ldl
552
553#define SHIFT 0
554#include "ops_template.h"
555#undef SHIFT
556
557#define SHIFT 1
558#include "ops_template.h"
559#undef SHIFT
560
561#define SHIFT 2
562#include "ops_template.h"
563#undef SHIFT
564
14ce26e7
FB
565#ifdef TARGET_X86_64
566
567#define SHIFT 3
568#include "ops_template.h"
569#undef SHIFT
570
571#endif
572
2c0262af
FB
573/* sign extend */
574
575void OPPROTO op_movsbl_T0_T0(void)
576{
577 T0 = (int8_t)T0;
578}
579
580void OPPROTO op_movzbl_T0_T0(void)
581{
582 T0 = (uint8_t)T0;
583}
584
585void OPPROTO op_movswl_T0_T0(void)
586{
587 T0 = (int16_t)T0;
588}
589
590void OPPROTO op_movzwl_T0_T0(void)
591{
592 T0 = (uint16_t)T0;
593}
594
595void OPPROTO op_movswl_EAX_AX(void)
596{
0499e4a0 597 EAX = (uint32_t)((int16_t)EAX);
2c0262af
FB
598}
599
14ce26e7 600#ifdef TARGET_X86_64
664e0f19
FB
601void OPPROTO op_movslq_T0_T0(void)
602{
603 T0 = (int32_t)T0;
604}
605
14ce26e7
FB
606void OPPROTO op_movslq_RAX_EAX(void)
607{
608 EAX = (int32_t)EAX;
609}
610#endif
611
2c0262af
FB
612void OPPROTO op_movsbw_AX_AL(void)
613{
14ce26e7 614 EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff);
2c0262af
FB
615}
616
617void OPPROTO op_movslq_EDX_EAX(void)
618{
0499e4a0 619 EDX = (uint32_t)((int32_t)EAX >> 31);
2c0262af
FB
620}
621
622void OPPROTO op_movswl_DX_AX(void)
623{
14ce26e7
FB
624 EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff);
625}
626
627#ifdef TARGET_X86_64
628void OPPROTO op_movsqo_RDX_RAX(void)
629{
630 EDX = (int64_t)EAX >> 63;
2c0262af 631}
14ce26e7 632#endif
2c0262af
FB
633
634/* string ops helpers */
635
636void OPPROTO op_addl_ESI_T0(void)
637{
14ce26e7 638 ESI = (uint32_t)(ESI + T0);
2c0262af
FB
639}
640
641void OPPROTO op_addw_ESI_T0(void)
642{
643 ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
644}
645
646void OPPROTO op_addl_EDI_T0(void)
647{
14ce26e7 648 EDI = (uint32_t)(EDI + T0);
2c0262af
FB
649}
650
651void OPPROTO op_addw_EDI_T0(void)
652{
653 EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
654}
655
656void OPPROTO op_decl_ECX(void)
657{
14ce26e7 658 ECX = (uint32_t)(ECX - 1);
2c0262af
FB
659}
660
661void OPPROTO op_decw_ECX(void)
662{
663 ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
664}
665
14ce26e7
FB
666#ifdef TARGET_X86_64
667void OPPROTO op_addq_ESI_T0(void)
668{
669 ESI = (ESI + T0);
670}
671
672void OPPROTO op_addq_EDI_T0(void)
673{
674 EDI = (EDI + T0);
675}
676
677void OPPROTO op_decq_ECX(void)
678{
679 ECX--;
680}
681#endif
682
2c0262af
FB
683void OPPROTO op_rdtsc(void)
684{
685 helper_rdtsc();
686}
687
df01e0fc
AZ
688void OPPROTO op_rdpmc(void)
689{
690 helper_rdpmc();
691}
692
2c0262af
FB
693void OPPROTO op_cpuid(void)
694{
695 helper_cpuid();
696}
697
61a8c4ec
FB
698void OPPROTO op_enter_level(void)
699{
700 helper_enter_level(PARAM1, PARAM2);
701}
702
8f091a59
FB
703#ifdef TARGET_X86_64
704void OPPROTO op_enter64_level(void)
705{
706 helper_enter64_level(PARAM1, PARAM2);
707}
708#endif
709
023fe10d
FB
710void OPPROTO op_sysenter(void)
711{
712 helper_sysenter();
713}
714
715void OPPROTO op_sysexit(void)
716{
717 helper_sysexit();
718}
719
14ce26e7
FB
720#ifdef TARGET_X86_64
721void OPPROTO op_syscall(void)
722{
06c2f506 723 helper_syscall(PARAM1);
14ce26e7
FB
724}
725
726void OPPROTO op_sysret(void)
727{
728 helper_sysret(PARAM1);
729}
730#endif
731
2c0262af
FB
732void OPPROTO op_rdmsr(void)
733{
734 helper_rdmsr();
735}
736
737void OPPROTO op_wrmsr(void)
738{
739 helper_wrmsr();
740}
741
742/* bcd */
743
744/* XXX: exception */
745void OPPROTO op_aam(void)
746{
747 int base = PARAM1;
748 int al, ah;
749 al = EAX & 0xff;
750 ah = al / base;
751 al = al % base;
752 EAX = (EAX & ~0xffff) | al | (ah << 8);
753 CC_DST = al;
754}
755
756void OPPROTO op_aad(void)
757{
758 int base = PARAM1;
759 int al, ah;
760 al = EAX & 0xff;
761 ah = (EAX >> 8) & 0xff;
762 al = ((ah * base) + al) & 0xff;
763 EAX = (EAX & ~0xffff) | al;
764 CC_DST = al;
765}
766
767void OPPROTO op_aaa(void)
768{
769 int icarry;
770 int al, ah, af;
771 int eflags;
772
773 eflags = cc_table[CC_OP].compute_all();
774 af = eflags & CC_A;
775 al = EAX & 0xff;
776 ah = (EAX >> 8) & 0xff;
777
778 icarry = (al > 0xf9);
779 if (((al & 0x0f) > 9 ) || af) {
780 al = (al + 6) & 0x0f;
781 ah = (ah + 1 + icarry) & 0xff;
782 eflags |= CC_C | CC_A;
783 } else {
784 eflags &= ~(CC_C | CC_A);
785 al &= 0x0f;
786 }
787 EAX = (EAX & ~0xffff) | al | (ah << 8);
788 CC_SRC = eflags;
647c5930 789 FORCE_RET();
2c0262af
FB
790}
791
792void OPPROTO op_aas(void)
793{
794 int icarry;
795 int al, ah, af;
796 int eflags;
797
798 eflags = cc_table[CC_OP].compute_all();
799 af = eflags & CC_A;
800 al = EAX & 0xff;
801 ah = (EAX >> 8) & 0xff;
802
803 icarry = (al < 6);
804 if (((al & 0x0f) > 9 ) || af) {
805 al = (al - 6) & 0x0f;
806 ah = (ah - 1 - icarry) & 0xff;
807 eflags |= CC_C | CC_A;
808 } else {
809 eflags &= ~(CC_C | CC_A);
810 al &= 0x0f;
811 }
812 EAX = (EAX & ~0xffff) | al | (ah << 8);
813 CC_SRC = eflags;
647c5930 814 FORCE_RET();
2c0262af
FB
815}
816
817void OPPROTO op_daa(void)
818{
819 int al, af, cf;
820 int eflags;
821
822 eflags = cc_table[CC_OP].compute_all();
823 cf = eflags & CC_C;
824 af = eflags & CC_A;
825 al = EAX & 0xff;
826
827 eflags = 0;
828 if (((al & 0x0f) > 9 ) || af) {
829 al = (al + 6) & 0xff;
830 eflags |= CC_A;
831 }
832 if ((al > 0x9f) || cf) {
833 al = (al + 0x60) & 0xff;
834 eflags |= CC_C;
835 }
836 EAX = (EAX & ~0xff) | al;
837 /* well, speed is not an issue here, so we compute the flags by hand */
838 eflags |= (al == 0) << 6; /* zf */
839 eflags |= parity_table[al]; /* pf */
840 eflags |= (al & 0x80); /* sf */
841 CC_SRC = eflags;
647c5930 842 FORCE_RET();
2c0262af
FB
843}
844
845void OPPROTO op_das(void)
846{
847 int al, al1, af, cf;
848 int eflags;
849
850 eflags = cc_table[CC_OP].compute_all();
851 cf = eflags & CC_C;
852 af = eflags & CC_A;
853 al = EAX & 0xff;
854
855 eflags = 0;
856 al1 = al;
857 if (((al & 0x0f) > 9 ) || af) {
858 eflags |= CC_A;
859 if (al < 6 || cf)
860 eflags |= CC_C;
861 al = (al - 6) & 0xff;
862 }
863 if ((al1 > 0x99) || cf) {
864 al = (al - 0x60) & 0xff;
865 eflags |= CC_C;
866 }
867 EAX = (EAX & ~0xff) | al;
868 /* well, speed is not an issue here, so we compute the flags by hand */
869 eflags |= (al == 0) << 6; /* zf */
870 eflags |= parity_table[al]; /* pf */
871 eflags |= (al & 0x80); /* sf */
872 CC_SRC = eflags;
647c5930 873 FORCE_RET();
2c0262af
FB
874}
875
876/* segment handling */
877
878/* never use it with R_CS */
879void OPPROTO op_movl_seg_T0(void)
880{
3415a4dd 881 load_seg(PARAM1, T0);
2c0262af
FB
882}
883
884/* faster VM86 version */
885void OPPROTO op_movl_seg_T0_vm(void)
886{
887 int selector;
888 SegmentCache *sc;
3b46e624 889
2c0262af
FB
890 selector = T0 & 0xffff;
891 /* env->segs[] access */
892 sc = (SegmentCache *)((char *)env + PARAM1);
893 sc->selector = selector;
14ce26e7 894 sc->base = (selector << 4);
2c0262af
FB
895}
896
897void OPPROTO op_movl_T0_seg(void)
898{
899 T0 = env->segs[PARAM1].selector;
900}
901
2c0262af
FB
902void OPPROTO op_lsl(void)
903{
904 helper_lsl();
905}
906
907void OPPROTO op_lar(void)
908{
909 helper_lar();
910}
911
3ab493de
FB
912void OPPROTO op_verr(void)
913{
914 helper_verr();
915}
916
917void OPPROTO op_verw(void)
918{
919 helper_verw();
920}
921
922void OPPROTO op_arpl(void)
923{
924 if ((T0 & 3) < (T1 & 3)) {
925 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
926 T0 = (T0 & ~3) | (T1 & 3);
927 T1 = CC_Z;
928 } else {
929 T1 = 0;
930 }
931 FORCE_RET();
932}
3b46e624 933
3ab493de
FB
934void OPPROTO op_arpl_update(void)
935{
936 int eflags;
937 eflags = cc_table[CC_OP].compute_all();
938 CC_SRC = (eflags & ~CC_Z) | T1;
939}
3b46e624 940
2c0262af
FB
941/* T0: segment, T1:eip */
942void OPPROTO op_ljmp_protected_T0_T1(void)
943{
08cea4ee 944 helper_ljmp_protected_T0_T1(PARAM1);
2c0262af
FB
945}
946
947void OPPROTO op_lcall_real_T0_T1(void)
948{
949 helper_lcall_real_T0_T1(PARAM1, PARAM2);
950}
951
952void OPPROTO op_lcall_protected_T0_T1(void)
953{
954 helper_lcall_protected_T0_T1(PARAM1, PARAM2);
955}
956
957void OPPROTO op_iret_real(void)
958{
959 helper_iret_real(PARAM1);
960}
961
962void OPPROTO op_iret_protected(void)
963{
08cea4ee 964 helper_iret_protected(PARAM1, PARAM2);
2c0262af
FB
965}
966
967void OPPROTO op_lret_protected(void)
968{
969 helper_lret_protected(PARAM1, PARAM2);
970}
971
972void OPPROTO op_lldt_T0(void)
973{
974 helper_lldt_T0();
975}
976
977void OPPROTO op_ltr_T0(void)
978{
979 helper_ltr_T0();
980}
981
0573fbfc 982/* CR registers access. */
2c0262af
FB
983void OPPROTO op_movl_crN_T0(void)
984{
985 helper_movl_crN_T0(PARAM1);
986}
987
0573fbfc
TS
988/* These pseudo-opcodes check for SVM intercepts. */
989void OPPROTO op_svm_check_intercept(void)
990{
991 A0 = PARAM1 & PARAM2;
992 svm_check_intercept(PARAMQ1);
993}
994
995void OPPROTO op_svm_check_intercept_param(void)
996{
997 A0 = PARAM1 & PARAM2;
998 svm_check_intercept_param(PARAMQ1, T1);
999}
1000
1001void OPPROTO op_svm_vmexit(void)
1002{
1003 A0 = PARAM1 & PARAM2;
1004 vmexit(PARAMQ1, T1);
1005}
1006
1007void OPPROTO op_geneflags(void)
1008{
1009 CC_SRC = cc_table[CC_OP].compute_all();
1010}
1011
1012/* This pseudo-opcode checks for IO intercepts. */
1013#if !defined(CONFIG_USER_ONLY)
1014void OPPROTO op_svm_check_intercept_io(void)
1015{
1016 A0 = PARAM1 & PARAM2;
1017 /* PARAMQ1 = TYPE (0 = OUT, 1 = IN; 4 = STRING; 8 = REP)
1018 T0 = PORT
1019 T1 = next eip */
1020 stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), T1);
1021 /* ASIZE does not appear on real hw */
1022 svm_check_intercept_param(SVM_EXIT_IOIO,
1023 (PARAMQ1 & ~SVM_IOIO_ASIZE_MASK) |
1024 ((T0 & 0xffff) << 16));
1025}
1026#endif
1027
5fafdf24 1028#if !defined(CONFIG_USER_ONLY)
39c61f49
FB
1029void OPPROTO op_movtl_T0_cr8(void)
1030{
39c61f49 1031 T0 = cpu_get_apic_tpr(env);
39c61f49 1032}
82e41634 1033#endif
39c61f49 1034
2c0262af
FB
1035/* DR registers access */
1036void OPPROTO op_movl_drN_T0(void)
1037{
1038 helper_movl_drN_T0(PARAM1);
1039}
1040
1041void OPPROTO op_lmsw_T0(void)
1042{
710c15a2
FB
1043 /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
1044 if already set to one. */
1045 T0 = (env->cr[0] & ~0xe) | (T0 & 0xf);
2c0262af
FB
1046 helper_movl_crN_T0(0);
1047}
1048
1049void OPPROTO op_invlpg_A0(void)
1050{
1051 helper_invlpg(A0);
1052}
1053
1054void OPPROTO op_movl_T0_env(void)
1055{
1056 T0 = *(uint32_t *)((char *)env + PARAM1);
1057}
1058
1059void OPPROTO op_movl_env_T0(void)
1060{
1061 *(uint32_t *)((char *)env + PARAM1) = T0;
1062}
1063
1064void OPPROTO op_movl_env_T1(void)
1065{
1066 *(uint32_t *)((char *)env + PARAM1) = T1;
1067}
1068
14ce26e7
FB
1069void OPPROTO op_movtl_T0_env(void)
1070{
1071 T0 = *(target_ulong *)((char *)env + PARAM1);
1072}
1073
1074void OPPROTO op_movtl_env_T0(void)
1075{
1076 *(target_ulong *)((char *)env + PARAM1) = T0;
1077}
1078
1079void OPPROTO op_movtl_T1_env(void)
1080{
1081 T1 = *(target_ulong *)((char *)env + PARAM1);
1082}
1083
1084void OPPROTO op_movtl_env_T1(void)
1085{
1086 *(target_ulong *)((char *)env + PARAM1) = T1;
1087}
1088
2c0262af
FB
1089void OPPROTO op_clts(void)
1090{
1091 env->cr[0] &= ~CR0_TS_MASK;
7eee2a50 1092 env->hflags &= ~HF_TS_MASK;
2c0262af
FB
1093}
1094
1095/* flags handling */
1096
14ce26e7
FB
1097void OPPROTO op_jmp_label(void)
1098{
1099 GOTO_LABEL_PARAM(1);
2c0262af
FB
1100}
1101
14ce26e7 1102void OPPROTO op_jnz_T0_label(void)
2c0262af
FB
1103{
1104 if (T0)
14ce26e7 1105 GOTO_LABEL_PARAM(1);
39c61f49 1106 FORCE_RET();
14ce26e7
FB
1107}
1108
1109void OPPROTO op_jz_T0_label(void)
1110{
1111 if (!T0)
1112 GOTO_LABEL_PARAM(1);
39c61f49 1113 FORCE_RET();
2c0262af
FB
1114}
1115
1116/* slow set cases (compute x86 flags) */
1117void OPPROTO op_seto_T0_cc(void)
1118{
1119 int eflags;
1120 eflags = cc_table[CC_OP].compute_all();
1121 T0 = (eflags >> 11) & 1;
1122}
1123
1124void OPPROTO op_setb_T0_cc(void)
1125{
1126 T0 = cc_table[CC_OP].compute_c();
1127}
1128
1129void OPPROTO op_setz_T0_cc(void)
1130{
1131 int eflags;
1132 eflags = cc_table[CC_OP].compute_all();
1133 T0 = (eflags >> 6) & 1;
1134}
1135
1136void OPPROTO op_setbe_T0_cc(void)
1137{
1138 int eflags;
1139 eflags = cc_table[CC_OP].compute_all();
1140 T0 = (eflags & (CC_Z | CC_C)) != 0;
1141}
1142
1143void OPPROTO op_sets_T0_cc(void)
1144{
1145 int eflags;
1146 eflags = cc_table[CC_OP].compute_all();
1147 T0 = (eflags >> 7) & 1;
1148}
1149
1150void OPPROTO op_setp_T0_cc(void)
1151{
1152 int eflags;
1153 eflags = cc_table[CC_OP].compute_all();
1154 T0 = (eflags >> 2) & 1;
1155}
1156
1157void OPPROTO op_setl_T0_cc(void)
1158{
1159 int eflags;
1160 eflags = cc_table[CC_OP].compute_all();
1161 T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1162}
1163
1164void OPPROTO op_setle_T0_cc(void)
1165{
1166 int eflags;
1167 eflags = cc_table[CC_OP].compute_all();
1168 T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1169}
1170
1171void OPPROTO op_xor_T0_1(void)
1172{
1173 T0 ^= 1;
1174}
1175
0b9dc5e4
FB
1176void OPPROTO op_mov_T0_cc(void)
1177{
1178 T0 = cc_table[CC_OP].compute_all();
1179}
1180
4136f33c 1181/* XXX: clear VIF/VIP in all ops ? */
2c0262af
FB
1182
1183void OPPROTO op_movl_eflags_T0(void)
1184{
4b7aba51 1185 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
2c0262af
FB
1186}
1187
1188void OPPROTO op_movw_eflags_T0(void)
1189{
4b7aba51 1190 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
4136f33c
FB
1191}
1192
1193void OPPROTO op_movl_eflags_T0_io(void)
1194{
4b7aba51 1195 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
4136f33c
FB
1196}
1197
1198void OPPROTO op_movw_eflags_T0_io(void)
1199{
4b7aba51 1200 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
2c0262af
FB
1201}
1202
1203void OPPROTO op_movl_eflags_T0_cpl0(void)
1204{
4b7aba51 1205 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
2c0262af
FB
1206}
1207
1208void OPPROTO op_movw_eflags_T0_cpl0(void)
1209{
4b7aba51 1210 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
2c0262af
FB
1211}
1212
1213#if 0
1214/* vm86plus version */
1215void OPPROTO op_movw_eflags_T0_vm(void)
1216{
1217 int eflags;
1218 eflags = T0;
1219 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1220 DF = 1 - (2 * ((eflags >> 10) & 1));
1221 /* we also update some system flags as in user mode */
1222 env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1223 (eflags & FL_UPDATE_MASK16);
1224 if (eflags & IF_MASK) {
1225 env->eflags |= VIF_MASK;
1226 if (env->eflags & VIP_MASK) {
1227 EIP = PARAM1;
1228 raise_exception(EXCP0D_GPF);
1229 }
1230 }
1231 FORCE_RET();
1232}
1233
1234void OPPROTO op_movl_eflags_T0_vm(void)
1235{
1236 int eflags;
1237 eflags = T0;
1238 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1239 DF = 1 - (2 * ((eflags >> 10) & 1));
1240 /* we also update some system flags as in user mode */
1241 env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1242 (eflags & FL_UPDATE_MASK32);
1243 if (eflags & IF_MASK) {
1244 env->eflags |= VIF_MASK;
1245 if (env->eflags & VIP_MASK) {
1246 EIP = PARAM1;
1247 raise_exception(EXCP0D_GPF);
1248 }
1249 }
1250 FORCE_RET();
1251}
1252#endif
1253
1254/* XXX: compute only O flag */
1255void OPPROTO op_movb_eflags_T0(void)
1256{
1257 int of;
1258 of = cc_table[CC_OP].compute_all() & CC_O;
1259 CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
1260}
1261
1262void OPPROTO op_movl_T0_eflags(void)
1263{
1264 int eflags;
1265 eflags = cc_table[CC_OP].compute_all();
1266 eflags |= (DF & DF_MASK);
1267 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1268 T0 = eflags;
1269}
1270
1271/* vm86plus version */
1272#if 0
1273void OPPROTO op_movl_T0_eflags_vm(void)
1274{
1275 int eflags;
1276 eflags = cc_table[CC_OP].compute_all();
1277 eflags |= (DF & DF_MASK);
1278 eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1279 if (env->eflags & VIF_MASK)
1280 eflags |= IF_MASK;
1281 T0 = eflags;
1282}
1283#endif
1284
1285void OPPROTO op_cld(void)
1286{
1287 DF = 1;
1288}
1289
1290void OPPROTO op_std(void)
1291{
1292 DF = -1;
1293}
1294
1295void OPPROTO op_clc(void)
1296{
1297 int eflags;
1298 eflags = cc_table[CC_OP].compute_all();
1299 eflags &= ~CC_C;
1300 CC_SRC = eflags;
1301}
1302
1303void OPPROTO op_stc(void)
1304{
1305 int eflags;
1306 eflags = cc_table[CC_OP].compute_all();
1307 eflags |= CC_C;
1308 CC_SRC = eflags;
1309}
1310
1311void OPPROTO op_cmc(void)
1312{
1313 int eflags;
1314 eflags = cc_table[CC_OP].compute_all();
1315 eflags ^= CC_C;
1316 CC_SRC = eflags;
1317}
1318
1319void OPPROTO op_salc(void)
1320{
1321 int cf;
1322 cf = cc_table[CC_OP].compute_c();
1323 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1324}
1325
1326static int compute_all_eflags(void)
1327{
1328 return CC_SRC;
1329}
1330
1331static int compute_c_eflags(void)
1332{
1333 return CC_SRC & CC_C;
1334}
1335
2c0262af
FB
1336CCTable cc_table[CC_OP_NB] = {
1337 [CC_OP_DYNAMIC] = { /* should never happen */ },
1338
1339 [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1340
d36cd60e
FB
1341 [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
1342 [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
1343 [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
2c0262af
FB
1344
1345 [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1346 [CC_OP_ADDW] = { compute_all_addw, compute_c_addw },
1347 [CC_OP_ADDL] = { compute_all_addl, compute_c_addl },
1348
1349 [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1350 [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw },
1351 [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl },
1352
1353 [CC_OP_SUBB] = { compute_all_subb, compute_c_subb },
1354 [CC_OP_SUBW] = { compute_all_subw, compute_c_subw },
1355 [CC_OP_SUBL] = { compute_all_subl, compute_c_subl },
3b46e624 1356
2c0262af
FB
1357 [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb },
1358 [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw },
1359 [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl },
3b46e624 1360
2c0262af
FB
1361 [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1362 [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1363 [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
3b46e624 1364
2c0262af
FB
1365 [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1366 [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
1367 [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
3b46e624 1368
2c0262af
FB
1369 [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1370 [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
1371 [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
3b46e624 1372
2c0262af
FB
1373 [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
1374 [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
1375 [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
1376
1377 [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
1378 [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
1379 [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
14ce26e7
FB
1380
1381#ifdef TARGET_X86_64
1382 [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
1383
1384 [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq },
1385
1386 [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq },
1387
1388 [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq },
3b46e624 1389
14ce26e7 1390 [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq },
3b46e624 1391
14ce26e7 1392 [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
3b46e624 1393
14ce26e7
FB
1394 [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
1395
1396 [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
1397
1398 [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
1399
1400 [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
1401#endif
2c0262af
FB
1402};
1403
1404/* floating point support. Some of the code for complicated x87
1405 functions comes from the LGPL'ed x86 emulator found in the Willows
1406 TWIN windows emulator. */
1407
2c0262af
FB
1408/* fp load FT0 */
1409
1410void OPPROTO op_flds_FT0_A0(void)
1411{
1412#ifdef USE_FP_CONVERT
14ce26e7 1413 FP_CONVERT.i32 = ldl(A0);
2c0262af
FB
1414 FT0 = FP_CONVERT.f;
1415#else
14ce26e7 1416 FT0 = ldfl(A0);
2c0262af
FB
1417#endif
1418}
1419
1420void OPPROTO op_fldl_FT0_A0(void)
1421{
1422#ifdef USE_FP_CONVERT
14ce26e7 1423 FP_CONVERT.i64 = ldq(A0);
2c0262af
FB
1424 FT0 = FP_CONVERT.d;
1425#else
14ce26e7 1426 FT0 = ldfq(A0);
2c0262af
FB
1427#endif
1428}
1429
1430/* helpers are needed to avoid static constant reference. XXX: find a better way */
1431#ifdef USE_INT_TO_FLOAT_HELPERS
1432
1433void helper_fild_FT0_A0(void)
1434{
14ce26e7 1435 FT0 = (CPU86_LDouble)ldsw(A0);
2c0262af
FB
1436}
1437
1438void helper_fildl_FT0_A0(void)
1439{
14ce26e7 1440 FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
2c0262af
FB
1441}
1442
1443void helper_fildll_FT0_A0(void)
1444{
14ce26e7 1445 FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
2c0262af
FB
1446}
1447
1448void OPPROTO op_fild_FT0_A0(void)
1449{
1450 helper_fild_FT0_A0();
1451}
1452
1453void OPPROTO op_fildl_FT0_A0(void)
1454{
1455 helper_fildl_FT0_A0();
1456}
1457
1458void OPPROTO op_fildll_FT0_A0(void)
1459{
1460 helper_fildll_FT0_A0();
1461}
1462
1463#else
1464
1465void OPPROTO op_fild_FT0_A0(void)
1466{
1467#ifdef USE_FP_CONVERT
14ce26e7 1468 FP_CONVERT.i32 = ldsw(A0);
2c0262af
FB
1469 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1470#else
14ce26e7 1471 FT0 = (CPU86_LDouble)ldsw(A0);
2c0262af
FB
1472#endif
1473}
1474
1475void OPPROTO op_fildl_FT0_A0(void)
1476{
1477#ifdef USE_FP_CONVERT
14ce26e7 1478 FP_CONVERT.i32 = (int32_t) ldl(A0);
2c0262af
FB
1479 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1480#else
14ce26e7 1481 FT0 = (CPU86_LDouble)((int32_t)ldl(A0));
2c0262af
FB
1482#endif
1483}
1484
1485void OPPROTO op_fildll_FT0_A0(void)
1486{
1487#ifdef USE_FP_CONVERT
14ce26e7 1488 FP_CONVERT.i64 = (int64_t) ldq(A0);
2c0262af
FB
1489 FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1490#else
14ce26e7 1491 FT0 = (CPU86_LDouble)((int64_t)ldq(A0));
2c0262af
FB
1492#endif
1493}
1494#endif
1495
1496/* fp load ST0 */
1497
1498void OPPROTO op_flds_ST0_A0(void)
1499{
1500 int new_fpstt;
1501 new_fpstt = (env->fpstt - 1) & 7;
1502#ifdef USE_FP_CONVERT
14ce26e7 1503 FP_CONVERT.i32 = ldl(A0);
664e0f19 1504 env->fpregs[new_fpstt].d = FP_CONVERT.f;
2c0262af 1505#else
664e0f19 1506 env->fpregs[new_fpstt].d = ldfl(A0);
2c0262af
FB
1507#endif
1508 env->fpstt = new_fpstt;
1509 env->fptags[new_fpstt] = 0; /* validate stack entry */
1510}
1511
1512void OPPROTO op_fldl_ST0_A0(void)
1513{
1514 int new_fpstt;
1515 new_fpstt = (env->fpstt - 1) & 7;
1516#ifdef USE_FP_CONVERT
14ce26e7 1517 FP_CONVERT.i64 = ldq(A0);
664e0f19 1518 env->fpregs[new_fpstt].d = FP_CONVERT.d;
2c0262af 1519#else
664e0f19 1520 env->fpregs[new_fpstt].d = ldfq(A0);
2c0262af
FB
1521#endif
1522 env->fpstt = new_fpstt;
1523 env->fptags[new_fpstt] = 0; /* validate stack entry */
1524}
1525
2c0262af
FB
1526void OPPROTO op_fldt_ST0_A0(void)
1527{
1528 helper_fldt_ST0_A0();
1529}
2c0262af
FB
1530
1531/* helpers are needed to avoid static constant reference. XXX: find a better way */
1532#ifdef USE_INT_TO_FLOAT_HELPERS
1533
1534void helper_fild_ST0_A0(void)
1535{
1536 int new_fpstt;
1537 new_fpstt = (env->fpstt - 1) & 7;
664e0f19 1538 env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0);
2c0262af
FB
1539 env->fpstt = new_fpstt;
1540 env->fptags[new_fpstt] = 0; /* validate stack entry */
1541}
1542
1543void helper_fildl_ST0_A0(void)
1544{
1545 int new_fpstt;
1546 new_fpstt = (env->fpstt - 1) & 7;
664e0f19 1547 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0));
2c0262af
FB
1548 env->fpstt = new_fpstt;
1549 env->fptags[new_fpstt] = 0; /* validate stack entry */
1550}
1551
1552void helper_fildll_ST0_A0(void)
1553{
1554 int new_fpstt;
1555 new_fpstt = (env->fpstt - 1) & 7;
664e0f19 1556 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0));
2c0262af
FB
1557 env->fpstt = new_fpstt;
1558 env->fptags[new_fpstt] = 0; /* validate stack entry */
1559}
1560
1561void OPPROTO op_fild_ST0_A0(void)
1562{
1563 helper_fild_ST0_A0();
1564}
1565
1566void OPPROTO op_fildl_ST0_A0(void)
1567{
1568 helper_fildl_ST0_A0();
1569}
1570
1571void OPPROTO op_fildll_ST0_A0(void)
1572{
1573 helper_fildll_ST0_A0();
1574}
1575
1576#else
1577
1578void OPPROTO op_fild_ST0_A0(void)
1579{
1580 int new_fpstt;
1581 new_fpstt = (env->fpstt - 1) & 7;
1582#ifdef USE_FP_CONVERT
14ce26e7 1583 FP_CONVERT.i32 = ldsw(A0);
664e0f19 1584 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32;
2c0262af 1585#else
664e0f19 1586 env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0);
2c0262af
FB
1587#endif
1588 env->fpstt = new_fpstt;
1589 env->fptags[new_fpstt] = 0; /* validate stack entry */
1590}
1591
1592void OPPROTO op_fildl_ST0_A0(void)
1593{
1594 int new_fpstt;
1595 new_fpstt = (env->fpstt - 1) & 7;
1596#ifdef USE_FP_CONVERT
14ce26e7 1597 FP_CONVERT.i32 = (int32_t) ldl(A0);
664e0f19 1598 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32;
2c0262af 1599#else
664e0f19 1600 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0));
2c0262af
FB
1601#endif
1602 env->fpstt = new_fpstt;
1603 env->fptags[new_fpstt] = 0; /* validate stack entry */
1604}
1605
1606void OPPROTO op_fildll_ST0_A0(void)
1607{
1608 int new_fpstt;
1609 new_fpstt = (env->fpstt - 1) & 7;
1610#ifdef USE_FP_CONVERT
14ce26e7 1611 FP_CONVERT.i64 = (int64_t) ldq(A0);
664e0f19 1612 env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i64;
2c0262af 1613#else
664e0f19 1614 env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0));
2c0262af
FB
1615#endif
1616 env->fpstt = new_fpstt;
1617 env->fptags[new_fpstt] = 0; /* validate stack entry */
1618}
1619
1620#endif
1621
1622/* fp store */
1623
1624void OPPROTO op_fsts_ST0_A0(void)
1625{
1626#ifdef USE_FP_CONVERT
1627 FP_CONVERT.f = (float)ST0;
14ce26e7 1628 stfl(A0, FP_CONVERT.f);
2c0262af 1629#else
14ce26e7 1630 stfl(A0, (float)ST0);
2c0262af 1631#endif
6eea2b1b 1632 FORCE_RET();
2c0262af
FB
1633}
1634
1635void OPPROTO op_fstl_ST0_A0(void)
1636{
14ce26e7 1637 stfq(A0, (double)ST0);
6eea2b1b 1638 FORCE_RET();
2c0262af
FB
1639}
1640
2c0262af
FB
1641void OPPROTO op_fstt_ST0_A0(void)
1642{
1643 helper_fstt_ST0_A0();
1644}
2c0262af
FB
1645
1646void OPPROTO op_fist_ST0_A0(void)
1647{
1648#if defined(__sparc__) && !defined(__sparc_v9__)
1649 register CPU86_LDouble d asm("o0");
1650#else
1651 CPU86_LDouble d;
1652#endif
1653 int val;
1654
1655 d = ST0;
7a0e1f41 1656 val = floatx_to_int32(d, &env->fp_status);
2c0262af
FB
1657 if (val != (int16_t)val)
1658 val = -32768;
14ce26e7 1659 stw(A0, val);
6eea2b1b 1660 FORCE_RET();
2c0262af
FB
1661}
1662
1663void OPPROTO op_fistl_ST0_A0(void)
1664{
1665#if defined(__sparc__) && !defined(__sparc_v9__)
1666 register CPU86_LDouble d asm("o0");
1667#else
1668 CPU86_LDouble d;
1669#endif
1670 int val;
1671
1672 d = ST0;
7a0e1f41 1673 val = floatx_to_int32(d, &env->fp_status);
14ce26e7 1674 stl(A0, val);
6eea2b1b 1675 FORCE_RET();
2c0262af
FB
1676}
1677
1678void OPPROTO op_fistll_ST0_A0(void)
1679{
1680#if defined(__sparc__) && !defined(__sparc_v9__)
1681 register CPU86_LDouble d asm("o0");
1682#else
1683 CPU86_LDouble d;
1684#endif
1685 int64_t val;
1686
1687 d = ST0;
7a0e1f41 1688 val = floatx_to_int64(d, &env->fp_status);
14ce26e7 1689 stq(A0, val);
6eea2b1b 1690 FORCE_RET();
2c0262af
FB
1691}
1692
465e9838
FB
1693void OPPROTO op_fistt_ST0_A0(void)
1694{
1695#if defined(__sparc__) && !defined(__sparc_v9__)
1696 register CPU86_LDouble d asm("o0");
1697#else
1698 CPU86_LDouble d;
1699#endif
1700 int val;
1701
1702 d = ST0;
1703 val = floatx_to_int32_round_to_zero(d, &env->fp_status);
1704 if (val != (int16_t)val)
1705 val = -32768;
1706 stw(A0, val);
1707 FORCE_RET();
1708}
1709
1710void OPPROTO op_fisttl_ST0_A0(void)
1711{
1712#if defined(__sparc__) && !defined(__sparc_v9__)
1713 register CPU86_LDouble d asm("o0");
1714#else
1715 CPU86_LDouble d;
1716#endif
1717 int val;
1718
1719 d = ST0;
1720 val = floatx_to_int32_round_to_zero(d, &env->fp_status);
1721 stl(A0, val);
1722 FORCE_RET();
1723}
1724
1725void OPPROTO op_fisttll_ST0_A0(void)
1726{
1727#if defined(__sparc__) && !defined(__sparc_v9__)
1728 register CPU86_LDouble d asm("o0");
1729#else
1730 CPU86_LDouble d;
1731#endif
1732 int64_t val;
1733
1734 d = ST0;
1735 val = floatx_to_int64_round_to_zero(d, &env->fp_status);
1736 stq(A0, val);
1737 FORCE_RET();
1738}
1739
2c0262af
FB
1740void OPPROTO op_fbld_ST0_A0(void)
1741{
1742 helper_fbld_ST0_A0();
1743}
1744
1745void OPPROTO op_fbst_ST0_A0(void)
1746{
1747 helper_fbst_ST0_A0();
1748}
1749
1750/* FPU move */
1751
1752void OPPROTO op_fpush(void)
1753{
1754 fpush();
1755}
1756
1757void OPPROTO op_fpop(void)
1758{
1759 fpop();
1760}
1761
1762void OPPROTO op_fdecstp(void)
1763{
1764 env->fpstt = (env->fpstt - 1) & 7;
1765 env->fpus &= (~0x4700);
1766}
1767
1768void OPPROTO op_fincstp(void)
1769{
1770 env->fpstt = (env->fpstt + 1) & 7;
1771 env->fpus &= (~0x4700);
1772}
1773
5fef40fb
FB
1774void OPPROTO op_ffree_STN(void)
1775{
1776 env->fptags[(env->fpstt + PARAM1) & 7] = 1;
1777}
1778
2c0262af
FB
1779void OPPROTO op_fmov_ST0_FT0(void)
1780{
1781 ST0 = FT0;
1782}
1783
1784void OPPROTO op_fmov_FT0_STN(void)
1785{
1786 FT0 = ST(PARAM1);
1787}
1788
1789void OPPROTO op_fmov_ST0_STN(void)
1790{
1791 ST0 = ST(PARAM1);
1792}
1793
1794void OPPROTO op_fmov_STN_ST0(void)
1795{
1796 ST(PARAM1) = ST0;
1797}
1798
1799void OPPROTO op_fxchg_ST0_STN(void)
1800{
1801 CPU86_LDouble tmp;
1802 tmp = ST(PARAM1);
1803 ST(PARAM1) = ST0;
1804 ST0 = tmp;
1805}
1806
1807/* FPU operations */
1808
43fb823b
FB
1809const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
1810
2c0262af
FB
1811void OPPROTO op_fcom_ST0_FT0(void)
1812{
43fb823b
FB
1813 int ret;
1814
1815 ret = floatx_compare(ST0, FT0, &env->fp_status);
1816 env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
2c0262af
FB
1817 FORCE_RET();
1818}
1819
2c0262af
FB
1820void OPPROTO op_fucom_ST0_FT0(void)
1821{
43fb823b
FB
1822 int ret;
1823
1824 ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
1825 env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
2c0262af
FB
1826 FORCE_RET();
1827}
1828
43fb823b
FB
1829const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
1830
2c0262af
FB
1831void OPPROTO op_fcomi_ST0_FT0(void)
1832{
43fb823b
FB
1833 int eflags;
1834 int ret;
1835
1836 ret = floatx_compare(ST0, FT0, &env->fp_status);
2c0262af 1837 eflags = cc_table[CC_OP].compute_all();
43fb823b 1838 eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
2c0262af
FB
1839 CC_SRC = eflags;
1840 FORCE_RET();
1841}
1842
2c0262af
FB
1843void OPPROTO op_fucomi_ST0_FT0(void)
1844{
43fb823b
FB
1845 int eflags;
1846 int ret;
1847
1848 ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
2c0262af 1849 eflags = cc_table[CC_OP].compute_all();
43fb823b 1850 eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
2c0262af
FB
1851 CC_SRC = eflags;
1852 FORCE_RET();
1853}
1854
80043406
FB
1855void OPPROTO op_fcmov_ST0_STN_T0(void)
1856{
1857 if (T0) {
1858 ST0 = ST(PARAM1);
1859 }
1860 FORCE_RET();
1861}
1862
2c0262af
FB
1863void OPPROTO op_fadd_ST0_FT0(void)
1864{
1865 ST0 += FT0;
1866}
1867
1868void OPPROTO op_fmul_ST0_FT0(void)
1869{
1870 ST0 *= FT0;
1871}
1872
1873void OPPROTO op_fsub_ST0_FT0(void)
1874{
1875 ST0 -= FT0;
1876}
1877
1878void OPPROTO op_fsubr_ST0_FT0(void)
1879{
1880 ST0 = FT0 - ST0;
1881}
1882
1883void OPPROTO op_fdiv_ST0_FT0(void)
1884{
2ee73ac3 1885 ST0 = helper_fdiv(ST0, FT0);
2c0262af
FB
1886}
1887
1888void OPPROTO op_fdivr_ST0_FT0(void)
1889{
2ee73ac3 1890 ST0 = helper_fdiv(FT0, ST0);
2c0262af
FB
1891}
1892
1893/* fp operations between STN and ST0 */
1894
1895void OPPROTO op_fadd_STN_ST0(void)
1896{
1897 ST(PARAM1) += ST0;
1898}
1899
1900void OPPROTO op_fmul_STN_ST0(void)
1901{
1902 ST(PARAM1) *= ST0;
1903}
1904
1905void OPPROTO op_fsub_STN_ST0(void)
1906{
1907 ST(PARAM1) -= ST0;
1908}
1909
1910void OPPROTO op_fsubr_STN_ST0(void)
1911{
1912 CPU86_LDouble *p;
1913 p = &ST(PARAM1);
1914 *p = ST0 - *p;
1915}
1916
1917void OPPROTO op_fdiv_STN_ST0(void)
1918{
2ee73ac3
FB
1919 CPU86_LDouble *p;
1920 p = &ST(PARAM1);
1921 *p = helper_fdiv(*p, ST0);
2c0262af
FB
1922}
1923
1924void OPPROTO op_fdivr_STN_ST0(void)
1925{
1926 CPU86_LDouble *p;
1927 p = &ST(PARAM1);
2ee73ac3 1928 *p = helper_fdiv(ST0, *p);
2c0262af
FB
1929}
1930
1931/* misc FPU operations */
1932void OPPROTO op_fchs_ST0(void)
1933{
7a0e1f41 1934 ST0 = floatx_chs(ST0);
2c0262af
FB
1935}
1936
1937void OPPROTO op_fabs_ST0(void)
1938{
7a0e1f41 1939 ST0 = floatx_abs(ST0);
2c0262af
FB
1940}
1941
1942void OPPROTO op_fxam_ST0(void)
1943{
1944 helper_fxam_ST0();
1945}
1946
1947void OPPROTO op_fld1_ST0(void)
1948{
1949 ST0 = f15rk[1];
1950}
1951
1952void OPPROTO op_fldl2t_ST0(void)
1953{
1954 ST0 = f15rk[6];
1955}
1956
1957void OPPROTO op_fldl2e_ST0(void)
1958{
1959 ST0 = f15rk[5];
1960}
1961
1962void OPPROTO op_fldpi_ST0(void)
1963{
1964 ST0 = f15rk[2];
1965}
1966
1967void OPPROTO op_fldlg2_ST0(void)
1968{
1969 ST0 = f15rk[3];
1970}
1971
1972void OPPROTO op_fldln2_ST0(void)
1973{
1974 ST0 = f15rk[4];
1975}
1976
1977void OPPROTO op_fldz_ST0(void)
1978{
1979 ST0 = f15rk[0];
1980}
1981
1982void OPPROTO op_fldz_FT0(void)
1983{
6a8c397d 1984 FT0 = f15rk[0];
2c0262af
FB
1985}
1986
1987/* associated heplers to reduce generated code length and to simplify
1988 relocation (FP constants are usually stored in .rodata section) */
1989
1990void OPPROTO op_f2xm1(void)
1991{
1992 helper_f2xm1();
1993}
1994
1995void OPPROTO op_fyl2x(void)
1996{
1997 helper_fyl2x();
1998}
1999
2000void OPPROTO op_fptan(void)
2001{
2002 helper_fptan();
2003}
2004
2005void OPPROTO op_fpatan(void)
2006{
2007 helper_fpatan();
2008}
2009
2010void OPPROTO op_fxtract(void)
2011{
2012 helper_fxtract();
2013}
2014
2015void OPPROTO op_fprem1(void)
2016{
2017 helper_fprem1();
2018}
2019
2020
2021void OPPROTO op_fprem(void)
2022{
2023 helper_fprem();
2024}
2025
2026void OPPROTO op_fyl2xp1(void)
2027{
2028 helper_fyl2xp1();
2029}
2030
2031void OPPROTO op_fsqrt(void)
2032{
2033 helper_fsqrt();
2034}
2035
2036void OPPROTO op_fsincos(void)
2037{
2038 helper_fsincos();
2039}
2040
2041void OPPROTO op_frndint(void)
2042{
2043 helper_frndint();
2044}
2045
2046void OPPROTO op_fscale(void)
2047{
2048 helper_fscale();
2049}
2050
2051void OPPROTO op_fsin(void)
2052{
2053 helper_fsin();
2054}
2055
2056void OPPROTO op_fcos(void)
2057{
2058 helper_fcos();
2059}
2060
2061void OPPROTO op_fnstsw_A0(void)
2062{
2063 int fpus;
2064 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
14ce26e7 2065 stw(A0, fpus);
6eea2b1b 2066 FORCE_RET();
2c0262af
FB
2067}
2068
2069void OPPROTO op_fnstsw_EAX(void)
2070{
2071 int fpus;
2072 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
14ce26e7 2073 EAX = (EAX & ~0xffff) | fpus;
2c0262af
FB
2074}
2075
2076void OPPROTO op_fnstcw_A0(void)
2077{
14ce26e7 2078 stw(A0, env->fpuc);
6eea2b1b 2079 FORCE_RET();
2c0262af
FB
2080}
2081
2082void OPPROTO op_fldcw_A0(void)
2083{
14ce26e7 2084 env->fpuc = lduw(A0);
7a0e1f41 2085 update_fp_status();
2c0262af
FB
2086}
2087
2088void OPPROTO op_fclex(void)
2089{
2090 env->fpus &= 0x7f00;
2091}
2092
2ee73ac3
FB
2093void OPPROTO op_fwait(void)
2094{
2095 if (env->fpus & FPUS_SE)
2096 fpu_raise_exception();
2097 FORCE_RET();
2098}
2099
2c0262af
FB
2100void OPPROTO op_fninit(void)
2101{
2102 env->fpus = 0;
2103 env->fpstt = 0;
2104 env->fpuc = 0x37f;
2105 env->fptags[0] = 1;
2106 env->fptags[1] = 1;
2107 env->fptags[2] = 1;
2108 env->fptags[3] = 1;
2109 env->fptags[4] = 1;
2110 env->fptags[5] = 1;
2111 env->fptags[6] = 1;
2112 env->fptags[7] = 1;
2113}
2114
2115void OPPROTO op_fnstenv_A0(void)
2116{
14ce26e7 2117 helper_fstenv(A0, PARAM1);
2c0262af
FB
2118}
2119
2120void OPPROTO op_fldenv_A0(void)
2121{
14ce26e7 2122 helper_fldenv(A0, PARAM1);
2c0262af
FB
2123}
2124
2125void OPPROTO op_fnsave_A0(void)
2126{
14ce26e7 2127 helper_fsave(A0, PARAM1);
2c0262af
FB
2128}
2129
2130void OPPROTO op_frstor_A0(void)
2131{
14ce26e7 2132 helper_frstor(A0, PARAM1);
2c0262af
FB
2133}
2134
2135/* threading support */
2136void OPPROTO op_lock(void)
2137{
2138 cpu_lock();
2139}
2140
2141void OPPROTO op_unlock(void)
2142{
2143 cpu_unlock();
2144}
2145
14ce26e7
FB
2146/* SSE support */
2147static inline void memcpy16(void *d, void *s)
2148{
2149 ((uint32_t *)d)[0] = ((uint32_t *)s)[0];
2150 ((uint32_t *)d)[1] = ((uint32_t *)s)[1];
2151 ((uint32_t *)d)[2] = ((uint32_t *)s)[2];
2152 ((uint32_t *)d)[3] = ((uint32_t *)s)[3];
2153}
2154
2155void OPPROTO op_movo(void)
2156{
2157 /* XXX: badly generated code */
2158 XMMReg *d, *s;
2159 d = (XMMReg *)((char *)env + PARAM1);
2160 s = (XMMReg *)((char *)env + PARAM2);
2161 memcpy16(d, s);
2162}
2163
664e0f19
FB
2164void OPPROTO op_movq(void)
2165{
2166 uint64_t *d, *s;
2167 d = (uint64_t *)((char *)env + PARAM1);
2168 s = (uint64_t *)((char *)env + PARAM2);
2169 *d = *s;
2170}
2171
2172void OPPROTO op_movl(void)
2173{
2174 uint32_t *d, *s;
2175 d = (uint32_t *)((char *)env + PARAM1);
2176 s = (uint32_t *)((char *)env + PARAM2);
2177 *d = *s;
2178}
2179
2180void OPPROTO op_movq_env_0(void)
2181{
2182 uint64_t *d;
2183 d = (uint64_t *)((char *)env + PARAM1);
2184 *d = 0;
2185}
2186
14ce26e7
FB
2187void OPPROTO op_fxsave_A0(void)
2188{
2189 helper_fxsave(A0, PARAM1);
2190}
2191
2192void OPPROTO op_fxrstor_A0(void)
2193{
2194 helper_fxrstor(A0, PARAM1);
2195}
664e0f19
FB
2196
2197/* XXX: optimize by storing fptt and fptags in the static cpu state */
2198void OPPROTO op_enter_mmx(void)
2199{
2200 env->fpstt = 0;
2201 *(uint32_t *)(env->fptags) = 0;
2202 *(uint32_t *)(env->fptags + 4) = 0;
2203}
2204
2205void OPPROTO op_emms(void)
2206{
2207 /* set to empty state */
2208 *(uint32_t *)(env->fptags) = 0x01010101;
2209 *(uint32_t *)(env->fptags + 4) = 0x01010101;
2210}
2211
2212#define SHIFT 0
2213#include "ops_sse.h"
2214
2215#define SHIFT 1
2216#include "ops_sse.h"
0573fbfc
TS
2217
2218/* Secure Virtual Machine ops */
2219
2220void OPPROTO op_vmrun(void)
2221{
2222 helper_vmrun(EAX);
2223}
2224
2225void OPPROTO op_vmmcall(void)
2226{
2227 helper_vmmcall();
2228}
2229
2230void OPPROTO op_vmload(void)
2231{
2232 helper_vmload(EAX);
2233}
2234
2235void OPPROTO op_vmsave(void)
2236{
2237 helper_vmsave(EAX);
2238}
2239
2240void OPPROTO op_stgi(void)
2241{
2242 helper_stgi();
2243}
2244
2245void OPPROTO op_clgi(void)
2246{
2247 helper_clgi();
2248}
2249
2250void OPPROTO op_skinit(void)
2251{
2252 helper_skinit();
2253}
2254
2255void OPPROTO op_invlpga(void)
2256{
2257 helper_invlpga();
2258}