]> Git Repo - qemu.git/blame - target-i386/op.c
MONITOR insn address generation fix - converted XLAT to TCG
[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
2c0262af
FB
24/* we define the various pieces of code used by the JIT */
25
26#define REG EAX
27#define REGNAME _EAX
28#include "opreg_template.h"
29#undef REG
30#undef REGNAME
31
32#define REG ECX
33#define REGNAME _ECX
34#include "opreg_template.h"
35#undef REG
36#undef REGNAME
37
38#define REG EDX
39#define REGNAME _EDX
40#include "opreg_template.h"
41#undef REG
42#undef REGNAME
43
44#define REG EBX
45#define REGNAME _EBX
46#include "opreg_template.h"
47#undef REG
48#undef REGNAME
49
50#define REG ESP
51#define REGNAME _ESP
52#include "opreg_template.h"
53#undef REG
54#undef REGNAME
55
56#define REG EBP
57#define REGNAME _EBP
58#include "opreg_template.h"
59#undef REG
60#undef REGNAME
61
62#define REG ESI
63#define REGNAME _ESI
64#include "opreg_template.h"
65#undef REG
66#undef REGNAME
67
68#define REG EDI
69#define REGNAME _EDI
70#include "opreg_template.h"
71#undef REG
72#undef REGNAME
73
14ce26e7
FB
74#ifdef TARGET_X86_64
75
76#define REG (env->regs[8])
77#define REGNAME _R8
78#include "opreg_template.h"
79#undef REG
80#undef REGNAME
81
82#define REG (env->regs[9])
83#define REGNAME _R9
84#include "opreg_template.h"
85#undef REG
86#undef REGNAME
87
88#define REG (env->regs[10])
89#define REGNAME _R10
90#include "opreg_template.h"
91#undef REG
92#undef REGNAME
93
94#define REG (env->regs[11])
95#define REGNAME _R11
96#include "opreg_template.h"
97#undef REG
98#undef REGNAME
99
100#define REG (env->regs[12])
101#define REGNAME _R12
102#include "opreg_template.h"
103#undef REG
104#undef REGNAME
105
106#define REG (env->regs[13])
107#define REGNAME _R13
108#include "opreg_template.h"
109#undef REG
110#undef REGNAME
111
112#define REG (env->regs[14])
113#define REGNAME _R14
114#include "opreg_template.h"
115#undef REG
116#undef REGNAME
117
118#define REG (env->regs[15])
119#define REGNAME _R15
120#include "opreg_template.h"
121#undef REG
122#undef REGNAME
123
124#endif
125
2c0262af 126/* multiply/divide */
d36cd60e
FB
127
128/* XXX: add eflags optimizations */
129/* XXX: add non P4 style flags */
130
2c0262af
FB
131void OPPROTO op_mulb_AL_T0(void)
132{
133 unsigned int res;
134 res = (uint8_t)EAX * (uint8_t)T0;
14ce26e7 135 EAX = (EAX & ~0xffff) | res;
d36cd60e 136 CC_DST = res;
2c0262af
FB
137 CC_SRC = (res & 0xff00);
138}
139
140void OPPROTO op_imulb_AL_T0(void)
141{
142 int res;
143 res = (int8_t)EAX * (int8_t)T0;
14ce26e7 144 EAX = (EAX & ~0xffff) | (res & 0xffff);
d36cd60e 145 CC_DST = res;
2c0262af
FB
146 CC_SRC = (res != (int8_t)res);
147}
148
149void OPPROTO op_mulw_AX_T0(void)
150{
151 unsigned int res;
152 res = (uint16_t)EAX * (uint16_t)T0;
14ce26e7
FB
153 EAX = (EAX & ~0xffff) | (res & 0xffff);
154 EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
d36cd60e 155 CC_DST = res;
2c0262af
FB
156 CC_SRC = res >> 16;
157}
158
159void OPPROTO op_imulw_AX_T0(void)
160{
161 int res;
162 res = (int16_t)EAX * (int16_t)T0;
14ce26e7
FB
163 EAX = (EAX & ~0xffff) | (res & 0xffff);
164 EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
d36cd60e 165 CC_DST = res;
2c0262af
FB
166 CC_SRC = (res != (int16_t)res);
167}
168
169void OPPROTO op_mull_EAX_T0(void)
170{
171 uint64_t res;
172 res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
14ce26e7
FB
173 EAX = (uint32_t)res;
174 EDX = (uint32_t)(res >> 32);
175 CC_DST = (uint32_t)res;
176 CC_SRC = (uint32_t)(res >> 32);
2c0262af
FB
177}
178
179void OPPROTO op_imull_EAX_T0(void)
180{
181 int64_t res;
182 res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
31313213
FB
183 EAX = (uint32_t)(res);
184 EDX = (uint32_t)(res >> 32);
d36cd60e 185 CC_DST = res;
2c0262af
FB
186 CC_SRC = (res != (int32_t)res);
187}
188
189void OPPROTO op_imulw_T0_T1(void)
190{
191 int res;
192 res = (int16_t)T0 * (int16_t)T1;
193 T0 = res;
d36cd60e 194 CC_DST = res;
2c0262af
FB
195 CC_SRC = (res != (int16_t)res);
196}
197
198void OPPROTO op_imull_T0_T1(void)
199{
200 int64_t res;
201 res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
202 T0 = res;
d36cd60e 203 CC_DST = res;
2c0262af
FB
204 CC_SRC = (res != (int32_t)res);
205}
206
14ce26e7
FB
207#ifdef TARGET_X86_64
208void OPPROTO op_mulq_EAX_T0(void)
209{
b8b6a50b 210 helper_mulq_EAX_T0(T0);
14ce26e7
FB
211}
212
213void OPPROTO op_imulq_EAX_T0(void)
214{
b8b6a50b 215 helper_imulq_EAX_T0(T0);
14ce26e7
FB
216}
217
218void OPPROTO op_imulq_T0_T1(void)
219{
b8b6a50b 220 T0 = helper_imulq_T0_T1(T0, T1);
14ce26e7
FB
221}
222#endif
223
2c0262af
FB
224/* constant load & misc op */
225
14ce26e7 226/* XXX: consistent names */
2c0262af
FB
227void OPPROTO op_into(void)
228{
229 int eflags;
230 eflags = cc_table[CC_OP].compute_all();
231 if (eflags & CC_O) {
232 raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
233 }
234 FORCE_RET();
235}
236
2c0262af
FB
237void OPPROTO op_cmpxchg8b(void)
238{
b8b6a50b 239 helper_cmpxchg8b(A0);
2c0262af
FB
240}
241
2c0262af
FB
242/* multiple size ops */
243
244#define ldul ldl
245
246#define SHIFT 0
247#include "ops_template.h"
248#undef SHIFT
249
250#define SHIFT 1
251#include "ops_template.h"
252#undef SHIFT
253
254#define SHIFT 2
255#include "ops_template.h"
256#undef SHIFT
257
14ce26e7
FB
258#ifdef TARGET_X86_64
259
260#define SHIFT 3
261#include "ops_template.h"
262#undef SHIFT
263
264#endif
265
2c0262af
FB
266/* sign extend */
267
268void OPPROTO op_movsbl_T0_T0(void)
269{
270 T0 = (int8_t)T0;
271}
272
273void OPPROTO op_movzbl_T0_T0(void)
274{
275 T0 = (uint8_t)T0;
276}
277
278void OPPROTO op_movswl_T0_T0(void)
279{
280 T0 = (int16_t)T0;
281}
282
283void OPPROTO op_movzwl_T0_T0(void)
284{
285 T0 = (uint16_t)T0;
286}
287
288void OPPROTO op_movswl_EAX_AX(void)
289{
0499e4a0 290 EAX = (uint32_t)((int16_t)EAX);
2c0262af
FB
291}
292
14ce26e7 293#ifdef TARGET_X86_64
664e0f19
FB
294void OPPROTO op_movslq_T0_T0(void)
295{
296 T0 = (int32_t)T0;
297}
298
14ce26e7
FB
299void OPPROTO op_movslq_RAX_EAX(void)
300{
301 EAX = (int32_t)EAX;
302}
303#endif
304
2c0262af
FB
305void OPPROTO op_movsbw_AX_AL(void)
306{
14ce26e7 307 EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff);
2c0262af
FB
308}
309
310void OPPROTO op_movslq_EDX_EAX(void)
311{
0499e4a0 312 EDX = (uint32_t)((int32_t)EAX >> 31);
2c0262af
FB
313}
314
315void OPPROTO op_movswl_DX_AX(void)
316{
14ce26e7
FB
317 EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff);
318}
319
320#ifdef TARGET_X86_64
321void OPPROTO op_movsqo_RDX_RAX(void)
322{
323 EDX = (int64_t)EAX >> 63;
2c0262af 324}
14ce26e7 325#endif
2c0262af
FB
326
327/* string ops helpers */
328
329void OPPROTO op_addl_ESI_T0(void)
330{
14ce26e7 331 ESI = (uint32_t)(ESI + T0);
2c0262af
FB
332}
333
334void OPPROTO op_addw_ESI_T0(void)
335{
336 ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
337}
338
339void OPPROTO op_addl_EDI_T0(void)
340{
14ce26e7 341 EDI = (uint32_t)(EDI + T0);
2c0262af
FB
342}
343
344void OPPROTO op_addw_EDI_T0(void)
345{
346 EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
347}
348
349void OPPROTO op_decl_ECX(void)
350{
14ce26e7 351 ECX = (uint32_t)(ECX - 1);
2c0262af
FB
352}
353
354void OPPROTO op_decw_ECX(void)
355{
356 ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
357}
358
14ce26e7
FB
359#ifdef TARGET_X86_64
360void OPPROTO op_addq_ESI_T0(void)
361{
362 ESI = (ESI + T0);
363}
364
365void OPPROTO op_addq_EDI_T0(void)
366{
367 EDI = (EDI + T0);
368}
369
370void OPPROTO op_decq_ECX(void)
371{
372 ECX--;
373}
374#endif
375
2c0262af
FB
376/* bcd */
377
2c0262af
FB
378void OPPROTO op_aam(void)
379{
b5b38f61 380 helper_aam(PARAM1);
2c0262af
FB
381}
382
383void OPPROTO op_aad(void)
384{
b5b38f61 385 helper_aad(PARAM1);
2c0262af
FB
386}
387
388void OPPROTO op_aaa(void)
389{
b5b38f61 390 helper_aaa();
2c0262af
FB
391}
392
393void OPPROTO op_aas(void)
394{
b5b38f61 395 helper_aas();
2c0262af
FB
396}
397
398void OPPROTO op_daa(void)
399{
b5b38f61 400 helper_daa();
2c0262af
FB
401}
402
403void OPPROTO op_das(void)
404{
b5b38f61 405 helper_das();
2c0262af
FB
406}
407
408/* segment handling */
409
2c0262af
FB
410/* faster VM86 version */
411void OPPROTO op_movl_seg_T0_vm(void)
412{
413 int selector;
414 SegmentCache *sc;
3b46e624 415
2c0262af
FB
416 selector = T0 & 0xffff;
417 /* env->segs[] access */
418 sc = (SegmentCache *)((char *)env + PARAM1);
419 sc->selector = selector;
14ce26e7 420 sc->base = (selector << 4);
2c0262af
FB
421}
422
423void OPPROTO op_movl_T0_seg(void)
424{
425 T0 = env->segs[PARAM1].selector;
426}
427
2c0262af
FB
428void OPPROTO op_lsl(void)
429{
b8b6a50b
FB
430 uint32_t val;
431 val = helper_lsl(T0);
432 if (CC_SRC & CC_Z)
433 T1 = val;
434 FORCE_RET();
2c0262af
FB
435}
436
437void OPPROTO op_lar(void)
438{
b8b6a50b
FB
439 uint32_t val;
440 val = helper_lar(T0);
441 if (CC_SRC & CC_Z)
442 T1 = val;
443 FORCE_RET();
2c0262af
FB
444}
445
3ab493de
FB
446void OPPROTO op_verr(void)
447{
b5b38f61 448 helper_verr(T0);
3ab493de
FB
449}
450
451void OPPROTO op_verw(void)
452{
b5b38f61 453 helper_verw(T0);
3ab493de
FB
454}
455
456void OPPROTO op_arpl(void)
457{
458 if ((T0 & 3) < (T1 & 3)) {
459 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
460 T0 = (T0 & ~3) | (T1 & 3);
461 T1 = CC_Z;
462 } else {
463 T1 = 0;
464 }
465 FORCE_RET();
466}
3b46e624 467
3ab493de
FB
468void OPPROTO op_arpl_update(void)
469{
470 int eflags;
471 eflags = cc_table[CC_OP].compute_all();
472 CC_SRC = (eflags & ~CC_Z) | T1;
473}
3b46e624 474
2c0262af
FB
475void OPPROTO op_movl_T0_env(void)
476{
477 T0 = *(uint32_t *)((char *)env + PARAM1);
478}
479
480void OPPROTO op_movl_env_T0(void)
481{
482 *(uint32_t *)((char *)env + PARAM1) = T0;
483}
484
485void OPPROTO op_movl_env_T1(void)
486{
487 *(uint32_t *)((char *)env + PARAM1) = T1;
488}
489
14ce26e7
FB
490void OPPROTO op_movtl_T0_env(void)
491{
492 T0 = *(target_ulong *)((char *)env + PARAM1);
493}
494
495void OPPROTO op_movtl_env_T0(void)
496{
497 *(target_ulong *)((char *)env + PARAM1) = T0;
498}
499
500void OPPROTO op_movtl_T1_env(void)
501{
502 T1 = *(target_ulong *)((char *)env + PARAM1);
503}
504
505void OPPROTO op_movtl_env_T1(void)
506{
507 *(target_ulong *)((char *)env + PARAM1) = T1;
508}
509
2c0262af
FB
510/* flags handling */
511
14ce26e7
FB
512void OPPROTO op_jmp_label(void)
513{
514 GOTO_LABEL_PARAM(1);
2c0262af
FB
515}
516
14ce26e7 517void OPPROTO op_jnz_T0_label(void)
2c0262af
FB
518{
519 if (T0)
14ce26e7 520 GOTO_LABEL_PARAM(1);
39c61f49 521 FORCE_RET();
14ce26e7
FB
522}
523
524void OPPROTO op_jz_T0_label(void)
525{
526 if (!T0)
527 GOTO_LABEL_PARAM(1);
39c61f49 528 FORCE_RET();
2c0262af
FB
529}
530
531/* slow set cases (compute x86 flags) */
532void OPPROTO op_seto_T0_cc(void)
533{
534 int eflags;
535 eflags = cc_table[CC_OP].compute_all();
536 T0 = (eflags >> 11) & 1;
537}
538
539void OPPROTO op_setb_T0_cc(void)
540{
541 T0 = cc_table[CC_OP].compute_c();
542}
543
544void OPPROTO op_setz_T0_cc(void)
545{
546 int eflags;
547 eflags = cc_table[CC_OP].compute_all();
548 T0 = (eflags >> 6) & 1;
549}
550
551void OPPROTO op_setbe_T0_cc(void)
552{
553 int eflags;
554 eflags = cc_table[CC_OP].compute_all();
555 T0 = (eflags & (CC_Z | CC_C)) != 0;
556}
557
558void OPPROTO op_sets_T0_cc(void)
559{
560 int eflags;
561 eflags = cc_table[CC_OP].compute_all();
562 T0 = (eflags >> 7) & 1;
563}
564
565void OPPROTO op_setp_T0_cc(void)
566{
567 int eflags;
568 eflags = cc_table[CC_OP].compute_all();
569 T0 = (eflags >> 2) & 1;
570}
571
572void OPPROTO op_setl_T0_cc(void)
573{
574 int eflags;
575 eflags = cc_table[CC_OP].compute_all();
576 T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
577}
578
579void OPPROTO op_setle_T0_cc(void)
580{
581 int eflags;
582 eflags = cc_table[CC_OP].compute_all();
583 T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
584}
585
586void OPPROTO op_xor_T0_1(void)
587{
588 T0 ^= 1;
589}
590
0b9dc5e4
FB
591void OPPROTO op_mov_T0_cc(void)
592{
593 T0 = cc_table[CC_OP].compute_all();
594}
595
4136f33c 596/* XXX: clear VIF/VIP in all ops ? */
2c0262af
FB
597
598void OPPROTO op_movl_eflags_T0(void)
599{
4b7aba51 600 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
2c0262af
FB
601}
602
603void OPPROTO op_movw_eflags_T0(void)
604{
4b7aba51 605 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
4136f33c
FB
606}
607
608void OPPROTO op_movl_eflags_T0_io(void)
609{
4b7aba51 610 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
4136f33c
FB
611}
612
613void OPPROTO op_movw_eflags_T0_io(void)
614{
4b7aba51 615 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
2c0262af
FB
616}
617
618void OPPROTO op_movl_eflags_T0_cpl0(void)
619{
4b7aba51 620 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
2c0262af
FB
621}
622
623void OPPROTO op_movw_eflags_T0_cpl0(void)
624{
4b7aba51 625 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
2c0262af
FB
626}
627
628#if 0
629/* vm86plus version */
630void OPPROTO op_movw_eflags_T0_vm(void)
631{
632 int eflags;
633 eflags = T0;
634 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
635 DF = 1 - (2 * ((eflags >> 10) & 1));
636 /* we also update some system flags as in user mode */
637 env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
638 (eflags & FL_UPDATE_MASK16);
639 if (eflags & IF_MASK) {
640 env->eflags |= VIF_MASK;
641 if (env->eflags & VIP_MASK) {
642 EIP = PARAM1;
643 raise_exception(EXCP0D_GPF);
644 }
645 }
646 FORCE_RET();
647}
648
649void OPPROTO op_movl_eflags_T0_vm(void)
650{
651 int eflags;
652 eflags = T0;
653 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
654 DF = 1 - (2 * ((eflags >> 10) & 1));
655 /* we also update some system flags as in user mode */
656 env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
657 (eflags & FL_UPDATE_MASK32);
658 if (eflags & IF_MASK) {
659 env->eflags |= VIF_MASK;
660 if (env->eflags & VIP_MASK) {
661 EIP = PARAM1;
662 raise_exception(EXCP0D_GPF);
663 }
664 }
665 FORCE_RET();
666}
667#endif
668
669/* XXX: compute only O flag */
670void OPPROTO op_movb_eflags_T0(void)
671{
672 int of;
673 of = cc_table[CC_OP].compute_all() & CC_O;
674 CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
675}
676
677void OPPROTO op_movl_T0_eflags(void)
678{
679 int eflags;
680 eflags = cc_table[CC_OP].compute_all();
681 eflags |= (DF & DF_MASK);
682 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
683 T0 = eflags;
684}
685
686/* vm86plus version */
687#if 0
688void OPPROTO op_movl_T0_eflags_vm(void)
689{
690 int eflags;
691 eflags = cc_table[CC_OP].compute_all();
692 eflags |= (DF & DF_MASK);
693 eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
694 if (env->eflags & VIF_MASK)
695 eflags |= IF_MASK;
696 T0 = eflags;
697}
698#endif
699
2c0262af
FB
700void OPPROTO op_clc(void)
701{
702 int eflags;
703 eflags = cc_table[CC_OP].compute_all();
704 eflags &= ~CC_C;
705 CC_SRC = eflags;
706}
707
708void OPPROTO op_stc(void)
709{
710 int eflags;
711 eflags = cc_table[CC_OP].compute_all();
712 eflags |= CC_C;
713 CC_SRC = eflags;
714}
715
716void OPPROTO op_cmc(void)
717{
718 int eflags;
719 eflags = cc_table[CC_OP].compute_all();
720 eflags ^= CC_C;
721 CC_SRC = eflags;
722}
723
724void OPPROTO op_salc(void)
725{
726 int cf;
727 cf = cc_table[CC_OP].compute_c();
728 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
729}
730
19e6c4b8 731void OPPROTO op_fcomi_dummy(void)
2c0262af 732{
19e6c4b8 733 T0 = 0;
2c0262af
FB
734}
735
14ce26e7 736/* SSE support */
5af45186 737void OPPROTO op_com_dummy(void)
14ce26e7 738{
5af45186 739 T0 = 0;
664e0f19 740}
This page took 0.297615 seconds and 4 git commands to generate.