ETRAX: Add support for the ethernet receivers dest addr filters.
[qemu/qemu-JZ.git] / target-i386 / op.c
blob3f3e1f13a331f317d4c9d7cdec04f9197497144a
1 /*
2 * i386 micro operations
4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
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
21 #define ASM_SOFTMMU
22 #include "exec.h"
24 /* we define the various pieces of code used by the JIT */
26 #define REG EAX
27 #define REGNAME _EAX
28 #include "opreg_template.h"
29 #undef REG
30 #undef REGNAME
32 #define REG ECX
33 #define REGNAME _ECX
34 #include "opreg_template.h"
35 #undef REG
36 #undef REGNAME
38 #define REG EDX
39 #define REGNAME _EDX
40 #include "opreg_template.h"
41 #undef REG
42 #undef REGNAME
44 #define REG EBX
45 #define REGNAME _EBX
46 #include "opreg_template.h"
47 #undef REG
48 #undef REGNAME
50 #define REG ESP
51 #define REGNAME _ESP
52 #include "opreg_template.h"
53 #undef REG
54 #undef REGNAME
56 #define REG EBP
57 #define REGNAME _EBP
58 #include "opreg_template.h"
59 #undef REG
60 #undef REGNAME
62 #define REG ESI
63 #define REGNAME _ESI
64 #include "opreg_template.h"
65 #undef REG
66 #undef REGNAME
68 #define REG EDI
69 #define REGNAME _EDI
70 #include "opreg_template.h"
71 #undef REG
72 #undef REGNAME
74 #ifdef TARGET_X86_64
76 #define REG (env->regs[8])
77 #define REGNAME _R8
78 #include "opreg_template.h"
79 #undef REG
80 #undef REGNAME
82 #define REG (env->regs[9])
83 #define REGNAME _R9
84 #include "opreg_template.h"
85 #undef REG
86 #undef REGNAME
88 #define REG (env->regs[10])
89 #define REGNAME _R10
90 #include "opreg_template.h"
91 #undef REG
92 #undef REGNAME
94 #define REG (env->regs[11])
95 #define REGNAME _R11
96 #include "opreg_template.h"
97 #undef REG
98 #undef REGNAME
100 #define REG (env->regs[12])
101 #define REGNAME _R12
102 #include "opreg_template.h"
103 #undef REG
104 #undef REGNAME
106 #define REG (env->regs[13])
107 #define REGNAME _R13
108 #include "opreg_template.h"
109 #undef REG
110 #undef REGNAME
112 #define REG (env->regs[14])
113 #define REGNAME _R14
114 #include "opreg_template.h"
115 #undef REG
116 #undef REGNAME
118 #define REG (env->regs[15])
119 #define REGNAME _R15
120 #include "opreg_template.h"
121 #undef REG
122 #undef REGNAME
124 #endif
126 /* multiply/divide */
128 /* XXX: add eflags optimizations */
129 /* XXX: add non P4 style flags */
131 void OPPROTO op_mulb_AL_T0(void)
133 unsigned int res;
134 res = (uint8_t)EAX * (uint8_t)T0;
135 EAX = (EAX & ~0xffff) | res;
136 CC_DST = res;
137 CC_SRC = (res & 0xff00);
140 void OPPROTO op_imulb_AL_T0(void)
142 int res;
143 res = (int8_t)EAX * (int8_t)T0;
144 EAX = (EAX & ~0xffff) | (res & 0xffff);
145 CC_DST = res;
146 CC_SRC = (res != (int8_t)res);
149 void OPPROTO op_mulw_AX_T0(void)
151 unsigned int res;
152 res = (uint16_t)EAX * (uint16_t)T0;
153 EAX = (EAX & ~0xffff) | (res & 0xffff);
154 EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
155 CC_DST = res;
156 CC_SRC = res >> 16;
159 void OPPROTO op_imulw_AX_T0(void)
161 int res;
162 res = (int16_t)EAX * (int16_t)T0;
163 EAX = (EAX & ~0xffff) | (res & 0xffff);
164 EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
165 CC_DST = res;
166 CC_SRC = (res != (int16_t)res);
169 void OPPROTO op_mull_EAX_T0(void)
171 uint64_t res;
172 res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
173 EAX = (uint32_t)res;
174 EDX = (uint32_t)(res >> 32);
175 CC_DST = (uint32_t)res;
176 CC_SRC = (uint32_t)(res >> 32);
179 void OPPROTO op_imull_EAX_T0(void)
181 int64_t res;
182 res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
183 EAX = (uint32_t)(res);
184 EDX = (uint32_t)(res >> 32);
185 CC_DST = res;
186 CC_SRC = (res != (int32_t)res);
189 void OPPROTO op_imulw_T0_T1(void)
191 int res;
192 res = (int16_t)T0 * (int16_t)T1;
193 T0 = res;
194 CC_DST = res;
195 CC_SRC = (res != (int16_t)res);
198 void OPPROTO op_imull_T0_T1(void)
200 int64_t res;
201 res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
202 T0 = res;
203 CC_DST = res;
204 CC_SRC = (res != (int32_t)res);
207 #ifdef TARGET_X86_64
208 void OPPROTO op_mulq_EAX_T0(void)
210 helper_mulq_EAX_T0(T0);
213 void OPPROTO op_imulq_EAX_T0(void)
215 helper_imulq_EAX_T0(T0);
218 void OPPROTO op_imulq_T0_T1(void)
220 T0 = helper_imulq_T0_T1(T0, T1);
222 #endif
224 /* constant load & misc op */
226 /* XXX: consistent names */
227 void OPPROTO op_into(void)
229 int eflags;
230 eflags = cc_table[CC_OP].compute_all();
231 if (eflags & CC_O) {
232 raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
234 FORCE_RET();
237 void OPPROTO op_cmpxchg8b(void)
239 helper_cmpxchg8b(A0);
242 /* multiple size ops */
244 #define ldul ldl
246 #define SHIFT 0
247 #include "ops_template.h"
248 #undef SHIFT
250 #define SHIFT 1
251 #include "ops_template.h"
252 #undef SHIFT
254 #define SHIFT 2
255 #include "ops_template.h"
256 #undef SHIFT
258 #ifdef TARGET_X86_64
260 #define SHIFT 3
261 #include "ops_template.h"
262 #undef SHIFT
264 #endif
266 /* string ops helpers */
268 void OPPROTO op_addl_ESI_T0(void)
270 ESI = (uint32_t)(ESI + T0);
273 void OPPROTO op_addw_ESI_T0(void)
275 ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
278 void OPPROTO op_addl_EDI_T0(void)
280 EDI = (uint32_t)(EDI + T0);
283 void OPPROTO op_addw_EDI_T0(void)
285 EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
288 void OPPROTO op_decl_ECX(void)
290 ECX = (uint32_t)(ECX - 1);
293 void OPPROTO op_decw_ECX(void)
295 ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
298 #ifdef TARGET_X86_64
299 void OPPROTO op_addq_ESI_T0(void)
301 ESI = (ESI + T0);
304 void OPPROTO op_addq_EDI_T0(void)
306 EDI = (EDI + T0);
309 void OPPROTO op_decq_ECX(void)
311 ECX--;
313 #endif
315 /* bcd */
317 void OPPROTO op_aam(void)
319 helper_aam(PARAM1);
322 void OPPROTO op_aad(void)
324 helper_aad(PARAM1);
327 void OPPROTO op_aaa(void)
329 helper_aaa();
332 void OPPROTO op_aas(void)
334 helper_aas();
337 void OPPROTO op_daa(void)
339 helper_daa();
342 void OPPROTO op_das(void)
344 helper_das();
347 /* segment handling */
349 /* faster VM86 version */
350 void OPPROTO op_movl_seg_T0_vm(void)
352 int selector;
353 SegmentCache *sc;
355 selector = T0 & 0xffff;
356 /* env->segs[] access */
357 sc = (SegmentCache *)((char *)env + PARAM1);
358 sc->selector = selector;
359 sc->base = (selector << 4);
362 void OPPROTO op_movl_T0_seg(void)
364 T0 = env->segs[PARAM1].selector;
367 void OPPROTO op_lsl(void)
369 uint32_t val;
370 val = helper_lsl(T0);
371 if (CC_SRC & CC_Z)
372 T1 = val;
373 FORCE_RET();
376 void OPPROTO op_lar(void)
378 uint32_t val;
379 val = helper_lar(T0);
380 if (CC_SRC & CC_Z)
381 T1 = val;
382 FORCE_RET();
385 void OPPROTO op_verr(void)
387 helper_verr(T0);
390 void OPPROTO op_verw(void)
392 helper_verw(T0);
395 void OPPROTO op_arpl(void)
397 if ((T0 & 3) < (T1 & 3)) {
398 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
399 T0 = (T0 & ~3) | (T1 & 3);
400 T1 = CC_Z;
401 } else {
402 T1 = 0;
404 FORCE_RET();
407 void OPPROTO op_arpl_update(void)
409 int eflags;
410 eflags = cc_table[CC_OP].compute_all();
411 CC_SRC = (eflags & ~CC_Z) | T1;
414 void OPPROTO op_movl_T0_env(void)
416 T0 = *(uint32_t *)((char *)env + PARAM1);
419 void OPPROTO op_movl_env_T0(void)
421 *(uint32_t *)((char *)env + PARAM1) = T0;
424 void OPPROTO op_movl_env_T1(void)
426 *(uint32_t *)((char *)env + PARAM1) = T1;
429 void OPPROTO op_movtl_T0_env(void)
431 T0 = *(target_ulong *)((char *)env + PARAM1);
434 void OPPROTO op_movtl_env_T0(void)
436 *(target_ulong *)((char *)env + PARAM1) = T0;
439 void OPPROTO op_movtl_T1_env(void)
441 T1 = *(target_ulong *)((char *)env + PARAM1);
444 void OPPROTO op_movtl_env_T1(void)
446 *(target_ulong *)((char *)env + PARAM1) = T1;
449 /* flags handling */
451 void OPPROTO op_jmp_label(void)
453 GOTO_LABEL_PARAM(1);
456 void OPPROTO op_jnz_T0_label(void)
458 if (T0)
459 GOTO_LABEL_PARAM(1);
460 FORCE_RET();
463 void OPPROTO op_jz_T0_label(void)
465 if (!T0)
466 GOTO_LABEL_PARAM(1);
467 FORCE_RET();
470 /* slow set cases (compute x86 flags) */
471 void OPPROTO op_seto_T0_cc(void)
473 int eflags;
474 eflags = cc_table[CC_OP].compute_all();
475 T0 = (eflags >> 11) & 1;
478 void OPPROTO op_setb_T0_cc(void)
480 T0 = cc_table[CC_OP].compute_c();
483 void OPPROTO op_setz_T0_cc(void)
485 int eflags;
486 eflags = cc_table[CC_OP].compute_all();
487 T0 = (eflags >> 6) & 1;
490 void OPPROTO op_setbe_T0_cc(void)
492 int eflags;
493 eflags = cc_table[CC_OP].compute_all();
494 T0 = (eflags & (CC_Z | CC_C)) != 0;
497 void OPPROTO op_sets_T0_cc(void)
499 int eflags;
500 eflags = cc_table[CC_OP].compute_all();
501 T0 = (eflags >> 7) & 1;
504 void OPPROTO op_setp_T0_cc(void)
506 int eflags;
507 eflags = cc_table[CC_OP].compute_all();
508 T0 = (eflags >> 2) & 1;
511 void OPPROTO op_setl_T0_cc(void)
513 int eflags;
514 eflags = cc_table[CC_OP].compute_all();
515 T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
518 void OPPROTO op_setle_T0_cc(void)
520 int eflags;
521 eflags = cc_table[CC_OP].compute_all();
522 T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
525 void OPPROTO op_xor_T0_1(void)
527 T0 ^= 1;
530 void OPPROTO op_mov_T0_cc(void)
532 T0 = cc_table[CC_OP].compute_all();
535 /* XXX: clear VIF/VIP in all ops ? */
537 void OPPROTO op_movl_eflags_T0(void)
539 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
542 void OPPROTO op_movw_eflags_T0(void)
544 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
547 void OPPROTO op_movl_eflags_T0_io(void)
549 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
552 void OPPROTO op_movw_eflags_T0_io(void)
554 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
557 void OPPROTO op_movl_eflags_T0_cpl0(void)
559 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
562 void OPPROTO op_movw_eflags_T0_cpl0(void)
564 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
567 #if 0
568 /* vm86plus version */
569 void OPPROTO op_movw_eflags_T0_vm(void)
571 int eflags;
572 eflags = T0;
573 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
574 DF = 1 - (2 * ((eflags >> 10) & 1));
575 /* we also update some system flags as in user mode */
576 env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
577 (eflags & FL_UPDATE_MASK16);
578 if (eflags & IF_MASK) {
579 env->eflags |= VIF_MASK;
580 if (env->eflags & VIP_MASK) {
581 EIP = PARAM1;
582 raise_exception(EXCP0D_GPF);
585 FORCE_RET();
588 void OPPROTO op_movl_eflags_T0_vm(void)
590 int eflags;
591 eflags = T0;
592 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
593 DF = 1 - (2 * ((eflags >> 10) & 1));
594 /* we also update some system flags as in user mode */
595 env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
596 (eflags & FL_UPDATE_MASK32);
597 if (eflags & IF_MASK) {
598 env->eflags |= VIF_MASK;
599 if (env->eflags & VIP_MASK) {
600 EIP = PARAM1;
601 raise_exception(EXCP0D_GPF);
604 FORCE_RET();
606 #endif
608 /* XXX: compute only O flag */
609 void OPPROTO op_movb_eflags_T0(void)
611 int of;
612 of = cc_table[CC_OP].compute_all() & CC_O;
613 CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
616 void OPPROTO op_movl_T0_eflags(void)
618 int eflags;
619 eflags = cc_table[CC_OP].compute_all();
620 eflags |= (DF & DF_MASK);
621 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
622 T0 = eflags;
625 /* vm86plus version */
626 #if 0
627 void OPPROTO op_movl_T0_eflags_vm(void)
629 int eflags;
630 eflags = cc_table[CC_OP].compute_all();
631 eflags |= (DF & DF_MASK);
632 eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
633 if (env->eflags & VIF_MASK)
634 eflags |= IF_MASK;
635 T0 = eflags;
637 #endif
639 void OPPROTO op_clc(void)
641 int eflags;
642 eflags = cc_table[CC_OP].compute_all();
643 eflags &= ~CC_C;
644 CC_SRC = eflags;
647 void OPPROTO op_stc(void)
649 int eflags;
650 eflags = cc_table[CC_OP].compute_all();
651 eflags |= CC_C;
652 CC_SRC = eflags;
655 void OPPROTO op_cmc(void)
657 int eflags;
658 eflags = cc_table[CC_OP].compute_all();
659 eflags ^= CC_C;
660 CC_SRC = eflags;
663 void OPPROTO op_salc(void)
665 int cf;
666 cf = cc_table[CC_OP].compute_c();
667 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
670 void OPPROTO op_fcomi_dummy(void)
672 T0 = 0;
675 /* SSE support */
676 void OPPROTO op_com_dummy(void)
678 T0 = 0;