Fix configurations with more than 4GB of memory
[qemu-kvm/fedora.git] / target-i386 / translate.c
blobcd9541265ac91668f8e841acb334777c2414dfdc
1 /*
2 * i386 translation
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
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <signal.h>
26 #include <assert.h>
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "disas.h"
32 /* XXX: move that elsewhere */
33 static uint16_t *gen_opc_ptr;
34 static uint32_t *gen_opparam_ptr;
36 #define PREFIX_REPZ 0x01
37 #define PREFIX_REPNZ 0x02
38 #define PREFIX_LOCK 0x04
39 #define PREFIX_DATA 0x08
40 #define PREFIX_ADR 0x10
42 #ifdef TARGET_X86_64
43 #define X86_64_ONLY(x) x
44 #define X86_64_DEF(x...) x
45 #define CODE64(s) ((s)->code64)
46 #define REX_X(s) ((s)->rex_x)
47 #define REX_B(s) ((s)->rex_b)
48 /* XXX: gcc generates push/pop in some opcodes, so we cannot use them */
49 #if 1
50 #define BUGGY_64(x) NULL
51 #endif
52 #else
53 #define X86_64_ONLY(x) NULL
54 #define X86_64_DEF(x...)
55 #define CODE64(s) 0
56 #define REX_X(s) 0
57 #define REX_B(s) 0
58 #endif
60 #ifdef TARGET_X86_64
61 static int x86_64_hregs;
62 #endif
64 #ifdef USE_DIRECT_JUMP
65 #define TBPARAM(x)
66 #else
67 #define TBPARAM(x) (long)(x)
68 #endif
70 typedef struct DisasContext {
71 /* current insn context */
72 int override; /* -1 if no override */
73 int prefix;
74 int aflag, dflag;
75 target_ulong pc; /* pc = eip + cs_base */
76 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
77 static state change (stop translation) */
78 /* current block context */
79 target_ulong cs_base; /* base of CS segment */
80 int pe; /* protected mode */
81 int code32; /* 32 bit code segment */
82 #ifdef TARGET_X86_64
83 int lma; /* long mode active */
84 int code64; /* 64 bit code segment */
85 int rex_x, rex_b;
86 #endif
87 int ss32; /* 32 bit stack segment */
88 int cc_op; /* current CC operation */
89 int addseg; /* non zero if either DS/ES/SS have a non zero base */
90 int f_st; /* currently unused */
91 int vm86; /* vm86 mode */
92 int cpl;
93 int iopl;
94 int tf; /* TF cpu flag */
95 int singlestep_enabled; /* "hardware" single step enabled */
96 int jmp_opt; /* use direct block chaining for direct jumps */
97 int mem_index; /* select memory access functions */
98 uint64_t flags; /* all execution flags */
99 struct TranslationBlock *tb;
100 int popl_esp_hack; /* for correct popl with esp base handling */
101 int rip_offset; /* only used in x86_64, but left for simplicity */
102 int cpuid_features;
103 int cpuid_ext_features;
104 } DisasContext;
106 static void gen_eob(DisasContext *s);
107 static void gen_jmp(DisasContext *s, target_ulong eip);
108 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
110 /* i386 arith/logic operations */
111 enum {
112 OP_ADDL,
113 OP_ORL,
114 OP_ADCL,
115 OP_SBBL,
116 OP_ANDL,
117 OP_SUBL,
118 OP_XORL,
119 OP_CMPL,
122 /* i386 shift ops */
123 enum {
124 OP_ROL,
125 OP_ROR,
126 OP_RCL,
127 OP_RCR,
128 OP_SHL,
129 OP_SHR,
130 OP_SHL1, /* undocumented */
131 OP_SAR = 7,
134 enum {
135 #define DEF(s, n, copy_size) INDEX_op_ ## s,
136 #include "opc.h"
137 #undef DEF
138 NB_OPS,
141 #include "gen-op.h"
143 /* operand size */
144 enum {
145 OT_BYTE = 0,
146 OT_WORD,
147 OT_LONG,
148 OT_QUAD,
151 enum {
152 /* I386 int registers */
153 OR_EAX, /* MUST be even numbered */
154 OR_ECX,
155 OR_EDX,
156 OR_EBX,
157 OR_ESP,
158 OR_EBP,
159 OR_ESI,
160 OR_EDI,
162 OR_TMP0 = 16, /* temporary operand register */
163 OR_TMP1,
164 OR_A0, /* temporary register used when doing address evaluation */
167 #ifdef TARGET_X86_64
169 #define NB_OP_SIZES 4
171 #define DEF_REGS(prefix, suffix) \
172 prefix ## EAX ## suffix,\
173 prefix ## ECX ## suffix,\
174 prefix ## EDX ## suffix,\
175 prefix ## EBX ## suffix,\
176 prefix ## ESP ## suffix,\
177 prefix ## EBP ## suffix,\
178 prefix ## ESI ## suffix,\
179 prefix ## EDI ## suffix,\
180 prefix ## R8 ## suffix,\
181 prefix ## R9 ## suffix,\
182 prefix ## R10 ## suffix,\
183 prefix ## R11 ## suffix,\
184 prefix ## R12 ## suffix,\
185 prefix ## R13 ## suffix,\
186 prefix ## R14 ## suffix,\
187 prefix ## R15 ## suffix,
189 #define DEF_BREGS(prefixb, prefixh, suffix) \
191 static void prefixb ## ESP ## suffix ## _wrapper(void) \
193 if (x86_64_hregs) \
194 prefixb ## ESP ## suffix (); \
195 else \
196 prefixh ## EAX ## suffix (); \
199 static void prefixb ## EBP ## suffix ## _wrapper(void) \
201 if (x86_64_hregs) \
202 prefixb ## EBP ## suffix (); \
203 else \
204 prefixh ## ECX ## suffix (); \
207 static void prefixb ## ESI ## suffix ## _wrapper(void) \
209 if (x86_64_hregs) \
210 prefixb ## ESI ## suffix (); \
211 else \
212 prefixh ## EDX ## suffix (); \
215 static void prefixb ## EDI ## suffix ## _wrapper(void) \
217 if (x86_64_hregs) \
218 prefixb ## EDI ## suffix (); \
219 else \
220 prefixh ## EBX ## suffix (); \
223 DEF_BREGS(gen_op_movb_, gen_op_movh_, _T0)
224 DEF_BREGS(gen_op_movb_, gen_op_movh_, _T1)
225 DEF_BREGS(gen_op_movl_T0_, gen_op_movh_T0_, )
226 DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, )
228 #else /* !TARGET_X86_64 */
230 #define NB_OP_SIZES 3
232 #define DEF_REGS(prefix, suffix) \
233 prefix ## EAX ## suffix,\
234 prefix ## ECX ## suffix,\
235 prefix ## EDX ## suffix,\
236 prefix ## EBX ## suffix,\
237 prefix ## ESP ## suffix,\
238 prefix ## EBP ## suffix,\
239 prefix ## ESI ## suffix,\
240 prefix ## EDI ## suffix,
242 #endif /* !TARGET_X86_64 */
244 static GenOpFunc *gen_op_mov_reg_T0[NB_OP_SIZES][CPU_NB_REGS] = {
245 [OT_BYTE] = {
246 gen_op_movb_EAX_T0,
247 gen_op_movb_ECX_T0,
248 gen_op_movb_EDX_T0,
249 gen_op_movb_EBX_T0,
250 #ifdef TARGET_X86_64
251 gen_op_movb_ESP_T0_wrapper,
252 gen_op_movb_EBP_T0_wrapper,
253 gen_op_movb_ESI_T0_wrapper,
254 gen_op_movb_EDI_T0_wrapper,
255 gen_op_movb_R8_T0,
256 gen_op_movb_R9_T0,
257 gen_op_movb_R10_T0,
258 gen_op_movb_R11_T0,
259 gen_op_movb_R12_T0,
260 gen_op_movb_R13_T0,
261 gen_op_movb_R14_T0,
262 gen_op_movb_R15_T0,
263 #else
264 gen_op_movh_EAX_T0,
265 gen_op_movh_ECX_T0,
266 gen_op_movh_EDX_T0,
267 gen_op_movh_EBX_T0,
268 #endif
270 [OT_WORD] = {
271 DEF_REGS(gen_op_movw_, _T0)
273 [OT_LONG] = {
274 DEF_REGS(gen_op_movl_, _T0)
276 #ifdef TARGET_X86_64
277 [OT_QUAD] = {
278 DEF_REGS(gen_op_movq_, _T0)
280 #endif
283 static GenOpFunc *gen_op_mov_reg_T1[NB_OP_SIZES][CPU_NB_REGS] = {
284 [OT_BYTE] = {
285 gen_op_movb_EAX_T1,
286 gen_op_movb_ECX_T1,
287 gen_op_movb_EDX_T1,
288 gen_op_movb_EBX_T1,
289 #ifdef TARGET_X86_64
290 gen_op_movb_ESP_T1_wrapper,
291 gen_op_movb_EBP_T1_wrapper,
292 gen_op_movb_ESI_T1_wrapper,
293 gen_op_movb_EDI_T1_wrapper,
294 gen_op_movb_R8_T1,
295 gen_op_movb_R9_T1,
296 gen_op_movb_R10_T1,
297 gen_op_movb_R11_T1,
298 gen_op_movb_R12_T1,
299 gen_op_movb_R13_T1,
300 gen_op_movb_R14_T1,
301 gen_op_movb_R15_T1,
302 #else
303 gen_op_movh_EAX_T1,
304 gen_op_movh_ECX_T1,
305 gen_op_movh_EDX_T1,
306 gen_op_movh_EBX_T1,
307 #endif
309 [OT_WORD] = {
310 DEF_REGS(gen_op_movw_, _T1)
312 [OT_LONG] = {
313 DEF_REGS(gen_op_movl_, _T1)
315 #ifdef TARGET_X86_64
316 [OT_QUAD] = {
317 DEF_REGS(gen_op_movq_, _T1)
319 #endif
322 static GenOpFunc *gen_op_mov_reg_A0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
323 [0] = {
324 DEF_REGS(gen_op_movw_, _A0)
326 [1] = {
327 DEF_REGS(gen_op_movl_, _A0)
329 #ifdef TARGET_X86_64
330 [2] = {
331 DEF_REGS(gen_op_movq_, _A0)
333 #endif
336 static GenOpFunc *gen_op_mov_TN_reg[NB_OP_SIZES][2][CPU_NB_REGS] =
338 [OT_BYTE] = {
340 gen_op_movl_T0_EAX,
341 gen_op_movl_T0_ECX,
342 gen_op_movl_T0_EDX,
343 gen_op_movl_T0_EBX,
344 #ifdef TARGET_X86_64
345 gen_op_movl_T0_ESP_wrapper,
346 gen_op_movl_T0_EBP_wrapper,
347 gen_op_movl_T0_ESI_wrapper,
348 gen_op_movl_T0_EDI_wrapper,
349 gen_op_movl_T0_R8,
350 gen_op_movl_T0_R9,
351 gen_op_movl_T0_R10,
352 gen_op_movl_T0_R11,
353 gen_op_movl_T0_R12,
354 gen_op_movl_T0_R13,
355 gen_op_movl_T0_R14,
356 gen_op_movl_T0_R15,
357 #else
358 gen_op_movh_T0_EAX,
359 gen_op_movh_T0_ECX,
360 gen_op_movh_T0_EDX,
361 gen_op_movh_T0_EBX,
362 #endif
365 gen_op_movl_T1_EAX,
366 gen_op_movl_T1_ECX,
367 gen_op_movl_T1_EDX,
368 gen_op_movl_T1_EBX,
369 #ifdef TARGET_X86_64
370 gen_op_movl_T1_ESP_wrapper,
371 gen_op_movl_T1_EBP_wrapper,
372 gen_op_movl_T1_ESI_wrapper,
373 gen_op_movl_T1_EDI_wrapper,
374 gen_op_movl_T1_R8,
375 gen_op_movl_T1_R9,
376 gen_op_movl_T1_R10,
377 gen_op_movl_T1_R11,
378 gen_op_movl_T1_R12,
379 gen_op_movl_T1_R13,
380 gen_op_movl_T1_R14,
381 gen_op_movl_T1_R15,
382 #else
383 gen_op_movh_T1_EAX,
384 gen_op_movh_T1_ECX,
385 gen_op_movh_T1_EDX,
386 gen_op_movh_T1_EBX,
387 #endif
390 [OT_WORD] = {
392 DEF_REGS(gen_op_movl_T0_, )
395 DEF_REGS(gen_op_movl_T1_, )
398 [OT_LONG] = {
400 DEF_REGS(gen_op_movl_T0_, )
403 DEF_REGS(gen_op_movl_T1_, )
406 #ifdef TARGET_X86_64
407 [OT_QUAD] = {
409 DEF_REGS(gen_op_movl_T0_, )
412 DEF_REGS(gen_op_movl_T1_, )
415 #endif
418 static GenOpFunc *gen_op_movl_A0_reg[CPU_NB_REGS] = {
419 DEF_REGS(gen_op_movl_A0_, )
422 static GenOpFunc *gen_op_addl_A0_reg_sN[4][CPU_NB_REGS] = {
423 [0] = {
424 DEF_REGS(gen_op_addl_A0_, )
426 [1] = {
427 DEF_REGS(gen_op_addl_A0_, _s1)
429 [2] = {
430 DEF_REGS(gen_op_addl_A0_, _s2)
432 [3] = {
433 DEF_REGS(gen_op_addl_A0_, _s3)
437 #ifdef TARGET_X86_64
438 static GenOpFunc *gen_op_movq_A0_reg[CPU_NB_REGS] = {
439 DEF_REGS(gen_op_movq_A0_, )
442 static GenOpFunc *gen_op_addq_A0_reg_sN[4][CPU_NB_REGS] = {
443 [0] = {
444 DEF_REGS(gen_op_addq_A0_, )
446 [1] = {
447 DEF_REGS(gen_op_addq_A0_, _s1)
449 [2] = {
450 DEF_REGS(gen_op_addq_A0_, _s2)
452 [3] = {
453 DEF_REGS(gen_op_addq_A0_, _s3)
456 #endif
458 static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
459 [0] = {
460 DEF_REGS(gen_op_cmovw_, _T1_T0)
462 [1] = {
463 DEF_REGS(gen_op_cmovl_, _T1_T0)
465 #ifdef TARGET_X86_64
466 [2] = {
467 DEF_REGS(gen_op_cmovq_, _T1_T0)
469 #endif
472 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
473 NULL,
474 gen_op_orl_T0_T1,
475 NULL,
476 NULL,
477 gen_op_andl_T0_T1,
478 NULL,
479 gen_op_xorl_T0_T1,
480 NULL,
483 #define DEF_ARITHC(SUFFIX)\
485 gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
486 gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
489 gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
490 gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
493 gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
494 gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
497 X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\
498 X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\
501 static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = {
502 DEF_ARITHC( )
505 static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = {
506 DEF_ARITHC(_raw)
507 #ifndef CONFIG_USER_ONLY
508 DEF_ARITHC(_kernel)
509 DEF_ARITHC(_user)
510 #endif
513 static const int cc_op_arithb[8] = {
514 CC_OP_ADDB,
515 CC_OP_LOGICB,
516 CC_OP_ADDB,
517 CC_OP_SUBB,
518 CC_OP_LOGICB,
519 CC_OP_SUBB,
520 CC_OP_LOGICB,
521 CC_OP_SUBB,
524 #define DEF_CMPXCHG(SUFFIX)\
525 gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
526 gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
527 gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\
528 X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc),
530 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = {
531 DEF_CMPXCHG( )
534 static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = {
535 DEF_CMPXCHG(_raw)
536 #ifndef CONFIG_USER_ONLY
537 DEF_CMPXCHG(_kernel)
538 DEF_CMPXCHG(_user)
539 #endif
542 #define DEF_SHIFT(SUFFIX)\
544 gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
545 gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
546 gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
547 gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
548 gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
549 gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
550 gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
551 gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
554 gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
555 gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
556 gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
557 gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
558 gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
559 gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
560 gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
561 gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
564 gen_op_roll ## SUFFIX ## _T0_T1_cc,\
565 gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
566 gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
567 gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
568 gen_op_shll ## SUFFIX ## _T0_T1_cc,\
569 gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
570 gen_op_shll ## SUFFIX ## _T0_T1_cc,\
571 gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
574 X86_64_ONLY(gen_op_rolq ## SUFFIX ## _T0_T1_cc),\
575 X86_64_ONLY(gen_op_rorq ## SUFFIX ## _T0_T1_cc),\
576 X86_64_ONLY(gen_op_rclq ## SUFFIX ## _T0_T1_cc),\
577 X86_64_ONLY(gen_op_rcrq ## SUFFIX ## _T0_T1_cc),\
578 X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
579 X86_64_ONLY(gen_op_shrq ## SUFFIX ## _T0_T1_cc),\
580 X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
581 X86_64_ONLY(gen_op_sarq ## SUFFIX ## _T0_T1_cc),\
584 static GenOpFunc *gen_op_shift_T0_T1_cc[4][8] = {
585 DEF_SHIFT( )
588 static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3 * 4][8] = {
589 DEF_SHIFT(_raw)
590 #ifndef CONFIG_USER_ONLY
591 DEF_SHIFT(_kernel)
592 DEF_SHIFT(_user)
593 #endif
596 #define DEF_SHIFTD(SUFFIX, op)\
598 NULL,\
599 NULL,\
602 gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
603 gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
606 gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
607 gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
610 X86_64_DEF(gen_op_shldq ## SUFFIX ## _T0_T1_ ## op ## _cc,\
611 gen_op_shrdq ## SUFFIX ## _T0_T1_ ## op ## _cc,)\
614 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[4][2] = {
615 DEF_SHIFTD(, im)
618 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[4][2] = {
619 DEF_SHIFTD(, ECX)
622 static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[3 * 4][2] = {
623 DEF_SHIFTD(_raw, im)
624 #ifndef CONFIG_USER_ONLY
625 DEF_SHIFTD(_kernel, im)
626 DEF_SHIFTD(_user, im)
627 #endif
630 static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[3 * 4][2] = {
631 DEF_SHIFTD(_raw, ECX)
632 #ifndef CONFIG_USER_ONLY
633 DEF_SHIFTD(_kernel, ECX)
634 DEF_SHIFTD(_user, ECX)
635 #endif
638 static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = {
639 [0] = {
640 gen_op_btw_T0_T1_cc,
641 gen_op_btsw_T0_T1_cc,
642 gen_op_btrw_T0_T1_cc,
643 gen_op_btcw_T0_T1_cc,
645 [1] = {
646 gen_op_btl_T0_T1_cc,
647 gen_op_btsl_T0_T1_cc,
648 gen_op_btrl_T0_T1_cc,
649 gen_op_btcl_T0_T1_cc,
651 #ifdef TARGET_X86_64
652 [2] = {
653 gen_op_btq_T0_T1_cc,
654 gen_op_btsq_T0_T1_cc,
655 gen_op_btrq_T0_T1_cc,
656 gen_op_btcq_T0_T1_cc,
658 #endif
661 static GenOpFunc *gen_op_add_bit_A0_T1[3] = {
662 gen_op_add_bitw_A0_T1,
663 gen_op_add_bitl_A0_T1,
664 X86_64_ONLY(gen_op_add_bitq_A0_T1),
667 static GenOpFunc *gen_op_bsx_T0_cc[3][2] = {
668 [0] = {
669 gen_op_bsfw_T0_cc,
670 gen_op_bsrw_T0_cc,
672 [1] = {
673 gen_op_bsfl_T0_cc,
674 gen_op_bsrl_T0_cc,
676 #ifdef TARGET_X86_64
677 [2] = {
678 gen_op_bsfq_T0_cc,
679 gen_op_bsrq_T0_cc,
681 #endif
684 static GenOpFunc *gen_op_lds_T0_A0[3 * 4] = {
685 gen_op_ldsb_raw_T0_A0,
686 gen_op_ldsw_raw_T0_A0,
687 X86_64_ONLY(gen_op_ldsl_raw_T0_A0),
688 NULL,
689 #ifndef CONFIG_USER_ONLY
690 gen_op_ldsb_kernel_T0_A0,
691 gen_op_ldsw_kernel_T0_A0,
692 X86_64_ONLY(gen_op_ldsl_kernel_T0_A0),
693 NULL,
695 gen_op_ldsb_user_T0_A0,
696 gen_op_ldsw_user_T0_A0,
697 X86_64_ONLY(gen_op_ldsl_user_T0_A0),
698 NULL,
699 #endif
702 static GenOpFunc *gen_op_ldu_T0_A0[3 * 4] = {
703 gen_op_ldub_raw_T0_A0,
704 gen_op_lduw_raw_T0_A0,
705 NULL,
706 NULL,
708 #ifndef CONFIG_USER_ONLY
709 gen_op_ldub_kernel_T0_A0,
710 gen_op_lduw_kernel_T0_A0,
711 NULL,
712 NULL,
714 gen_op_ldub_user_T0_A0,
715 gen_op_lduw_user_T0_A0,
716 NULL,
717 NULL,
718 #endif
721 /* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
722 static GenOpFunc *gen_op_ld_T0_A0[3 * 4] = {
723 gen_op_ldub_raw_T0_A0,
724 gen_op_lduw_raw_T0_A0,
725 gen_op_ldl_raw_T0_A0,
726 X86_64_ONLY(gen_op_ldq_raw_T0_A0),
728 #ifndef CONFIG_USER_ONLY
729 gen_op_ldub_kernel_T0_A0,
730 gen_op_lduw_kernel_T0_A0,
731 gen_op_ldl_kernel_T0_A0,
732 X86_64_ONLY(gen_op_ldq_kernel_T0_A0),
734 gen_op_ldub_user_T0_A0,
735 gen_op_lduw_user_T0_A0,
736 gen_op_ldl_user_T0_A0,
737 X86_64_ONLY(gen_op_ldq_user_T0_A0),
738 #endif
741 static GenOpFunc *gen_op_ld_T1_A0[3 * 4] = {
742 gen_op_ldub_raw_T1_A0,
743 gen_op_lduw_raw_T1_A0,
744 gen_op_ldl_raw_T1_A0,
745 X86_64_ONLY(gen_op_ldq_raw_T1_A0),
747 #ifndef CONFIG_USER_ONLY
748 gen_op_ldub_kernel_T1_A0,
749 gen_op_lduw_kernel_T1_A0,
750 gen_op_ldl_kernel_T1_A0,
751 X86_64_ONLY(gen_op_ldq_kernel_T1_A0),
753 gen_op_ldub_user_T1_A0,
754 gen_op_lduw_user_T1_A0,
755 gen_op_ldl_user_T1_A0,
756 X86_64_ONLY(gen_op_ldq_user_T1_A0),
757 #endif
760 static GenOpFunc *gen_op_st_T0_A0[3 * 4] = {
761 gen_op_stb_raw_T0_A0,
762 gen_op_stw_raw_T0_A0,
763 gen_op_stl_raw_T0_A0,
764 X86_64_ONLY(gen_op_stq_raw_T0_A0),
766 #ifndef CONFIG_USER_ONLY
767 gen_op_stb_kernel_T0_A0,
768 gen_op_stw_kernel_T0_A0,
769 gen_op_stl_kernel_T0_A0,
770 X86_64_ONLY(gen_op_stq_kernel_T0_A0),
772 gen_op_stb_user_T0_A0,
773 gen_op_stw_user_T0_A0,
774 gen_op_stl_user_T0_A0,
775 X86_64_ONLY(gen_op_stq_user_T0_A0),
776 #endif
779 static GenOpFunc *gen_op_st_T1_A0[3 * 4] = {
780 NULL,
781 gen_op_stw_raw_T1_A0,
782 gen_op_stl_raw_T1_A0,
783 X86_64_ONLY(gen_op_stq_raw_T1_A0),
785 #ifndef CONFIG_USER_ONLY
786 NULL,
787 gen_op_stw_kernel_T1_A0,
788 gen_op_stl_kernel_T1_A0,
789 X86_64_ONLY(gen_op_stq_kernel_T1_A0),
791 NULL,
792 gen_op_stw_user_T1_A0,
793 gen_op_stl_user_T1_A0,
794 X86_64_ONLY(gen_op_stq_user_T1_A0),
795 #endif
798 static inline void gen_jmp_im(target_ulong pc)
800 #ifdef TARGET_X86_64
801 if (pc == (uint32_t)pc) {
802 gen_op_movl_eip_im(pc);
803 } else if (pc == (int32_t)pc) {
804 gen_op_movq_eip_im(pc);
805 } else {
806 gen_op_movq_eip_im64(pc >> 32, pc);
808 #else
809 gen_op_movl_eip_im(pc);
810 #endif
813 static inline void gen_string_movl_A0_ESI(DisasContext *s)
815 int override;
817 override = s->override;
818 #ifdef TARGET_X86_64
819 if (s->aflag == 2) {
820 if (override >= 0) {
821 gen_op_movq_A0_seg(offsetof(CPUX86State,segs[override].base));
822 gen_op_addq_A0_reg_sN[0][R_ESI]();
823 } else {
824 gen_op_movq_A0_reg[R_ESI]();
826 } else
827 #endif
828 if (s->aflag) {
829 /* 32 bit address */
830 if (s->addseg && override < 0)
831 override = R_DS;
832 if (override >= 0) {
833 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
834 gen_op_addl_A0_reg_sN[0][R_ESI]();
835 } else {
836 gen_op_movl_A0_reg[R_ESI]();
838 } else {
839 /* 16 address, always override */
840 if (override < 0)
841 override = R_DS;
842 gen_op_movl_A0_reg[R_ESI]();
843 gen_op_andl_A0_ffff();
844 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
848 static inline void gen_string_movl_A0_EDI(DisasContext *s)
850 #ifdef TARGET_X86_64
851 if (s->aflag == 2) {
852 gen_op_movq_A0_reg[R_EDI]();
853 } else
854 #endif
855 if (s->aflag) {
856 if (s->addseg) {
857 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
858 gen_op_addl_A0_reg_sN[0][R_EDI]();
859 } else {
860 gen_op_movl_A0_reg[R_EDI]();
862 } else {
863 gen_op_movl_A0_reg[R_EDI]();
864 gen_op_andl_A0_ffff();
865 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
869 static GenOpFunc *gen_op_movl_T0_Dshift[4] = {
870 gen_op_movl_T0_Dshiftb,
871 gen_op_movl_T0_Dshiftw,
872 gen_op_movl_T0_Dshiftl,
873 X86_64_ONLY(gen_op_movl_T0_Dshiftq),
876 static GenOpFunc1 *gen_op_jnz_ecx[3] = {
877 gen_op_jnz_ecxw,
878 gen_op_jnz_ecxl,
879 X86_64_ONLY(gen_op_jnz_ecxq),
882 static GenOpFunc1 *gen_op_jz_ecx[3] = {
883 gen_op_jz_ecxw,
884 gen_op_jz_ecxl,
885 X86_64_ONLY(gen_op_jz_ecxq),
888 static GenOpFunc *gen_op_dec_ECX[3] = {
889 gen_op_decw_ECX,
890 gen_op_decl_ECX,
891 X86_64_ONLY(gen_op_decq_ECX),
894 static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = {
896 gen_op_jnz_subb,
897 gen_op_jnz_subw,
898 gen_op_jnz_subl,
899 X86_64_ONLY(gen_op_jnz_subq),
902 gen_op_jz_subb,
903 gen_op_jz_subw,
904 gen_op_jz_subl,
905 X86_64_ONLY(gen_op_jz_subq),
909 static GenOpFunc *gen_op_in_DX_T0[3] = {
910 gen_op_inb_DX_T0,
911 gen_op_inw_DX_T0,
912 gen_op_inl_DX_T0,
915 static GenOpFunc *gen_op_out_DX_T0[3] = {
916 gen_op_outb_DX_T0,
917 gen_op_outw_DX_T0,
918 gen_op_outl_DX_T0,
921 static GenOpFunc *gen_op_in[3] = {
922 gen_op_inb_T0_T1,
923 gen_op_inw_T0_T1,
924 gen_op_inl_T0_T1,
927 static GenOpFunc *gen_op_out[3] = {
928 gen_op_outb_T0_T1,
929 gen_op_outw_T0_T1,
930 gen_op_outl_T0_T1,
933 static GenOpFunc *gen_check_io_T0[3] = {
934 gen_op_check_iob_T0,
935 gen_op_check_iow_T0,
936 gen_op_check_iol_T0,
939 static GenOpFunc *gen_check_io_DX[3] = {
940 gen_op_check_iob_DX,
941 gen_op_check_iow_DX,
942 gen_op_check_iol_DX,
945 static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip)
947 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
948 if (s->cc_op != CC_OP_DYNAMIC)
949 gen_op_set_cc_op(s->cc_op);
950 gen_jmp_im(cur_eip);
951 if (use_dx)
952 gen_check_io_DX[ot]();
953 else
954 gen_check_io_T0[ot]();
958 static inline void gen_movs(DisasContext *s, int ot)
960 gen_string_movl_A0_ESI(s);
961 gen_op_ld_T0_A0[ot + s->mem_index]();
962 gen_string_movl_A0_EDI(s);
963 gen_op_st_T0_A0[ot + s->mem_index]();
964 gen_op_movl_T0_Dshift[ot]();
965 #ifdef TARGET_X86_64
966 if (s->aflag == 2) {
967 gen_op_addq_ESI_T0();
968 gen_op_addq_EDI_T0();
969 } else
970 #endif
971 if (s->aflag) {
972 gen_op_addl_ESI_T0();
973 gen_op_addl_EDI_T0();
974 } else {
975 gen_op_addw_ESI_T0();
976 gen_op_addw_EDI_T0();
980 static inline void gen_update_cc_op(DisasContext *s)
982 if (s->cc_op != CC_OP_DYNAMIC) {
983 gen_op_set_cc_op(s->cc_op);
984 s->cc_op = CC_OP_DYNAMIC;
988 /* XXX: does not work with gdbstub "ice" single step - not a
989 serious problem */
990 static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
992 int l1, l2;
994 l1 = gen_new_label();
995 l2 = gen_new_label();
996 gen_op_jnz_ecx[s->aflag](l1);
997 gen_set_label(l2);
998 gen_jmp_tb(s, next_eip, 1);
999 gen_set_label(l1);
1000 return l2;
1003 static inline void gen_stos(DisasContext *s, int ot)
1005 gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1006 gen_string_movl_A0_EDI(s);
1007 gen_op_st_T0_A0[ot + s->mem_index]();
1008 gen_op_movl_T0_Dshift[ot]();
1009 #ifdef TARGET_X86_64
1010 if (s->aflag == 2) {
1011 gen_op_addq_EDI_T0();
1012 } else
1013 #endif
1014 if (s->aflag) {
1015 gen_op_addl_EDI_T0();
1016 } else {
1017 gen_op_addw_EDI_T0();
1021 static inline void gen_lods(DisasContext *s, int ot)
1023 gen_string_movl_A0_ESI(s);
1024 gen_op_ld_T0_A0[ot + s->mem_index]();
1025 gen_op_mov_reg_T0[ot][R_EAX]();
1026 gen_op_movl_T0_Dshift[ot]();
1027 #ifdef TARGET_X86_64
1028 if (s->aflag == 2) {
1029 gen_op_addq_ESI_T0();
1030 } else
1031 #endif
1032 if (s->aflag) {
1033 gen_op_addl_ESI_T0();
1034 } else {
1035 gen_op_addw_ESI_T0();
1039 static inline void gen_scas(DisasContext *s, int ot)
1041 gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1042 gen_string_movl_A0_EDI(s);
1043 gen_op_ld_T1_A0[ot + s->mem_index]();
1044 gen_op_cmpl_T0_T1_cc();
1045 gen_op_movl_T0_Dshift[ot]();
1046 #ifdef TARGET_X86_64
1047 if (s->aflag == 2) {
1048 gen_op_addq_EDI_T0();
1049 } else
1050 #endif
1051 if (s->aflag) {
1052 gen_op_addl_EDI_T0();
1053 } else {
1054 gen_op_addw_EDI_T0();
1058 static inline void gen_cmps(DisasContext *s, int ot)
1060 gen_string_movl_A0_ESI(s);
1061 gen_op_ld_T0_A0[ot + s->mem_index]();
1062 gen_string_movl_A0_EDI(s);
1063 gen_op_ld_T1_A0[ot + s->mem_index]();
1064 gen_op_cmpl_T0_T1_cc();
1065 gen_op_movl_T0_Dshift[ot]();
1066 #ifdef TARGET_X86_64
1067 if (s->aflag == 2) {
1068 gen_op_addq_ESI_T0();
1069 gen_op_addq_EDI_T0();
1070 } else
1071 #endif
1072 if (s->aflag) {
1073 gen_op_addl_ESI_T0();
1074 gen_op_addl_EDI_T0();
1075 } else {
1076 gen_op_addw_ESI_T0();
1077 gen_op_addw_EDI_T0();
1081 static inline void gen_ins(DisasContext *s, int ot)
1083 gen_string_movl_A0_EDI(s);
1084 gen_op_movl_T0_0();
1085 gen_op_st_T0_A0[ot + s->mem_index]();
1086 gen_op_in_DX_T0[ot]();
1087 gen_op_st_T0_A0[ot + s->mem_index]();
1088 gen_op_movl_T0_Dshift[ot]();
1089 #ifdef TARGET_X86_64
1090 if (s->aflag == 2) {
1091 gen_op_addq_EDI_T0();
1092 } else
1093 #endif
1094 if (s->aflag) {
1095 gen_op_addl_EDI_T0();
1096 } else {
1097 gen_op_addw_EDI_T0();
1101 static inline void gen_outs(DisasContext *s, int ot)
1103 gen_string_movl_A0_ESI(s);
1104 gen_op_ld_T0_A0[ot + s->mem_index]();
1105 gen_op_out_DX_T0[ot]();
1106 gen_op_movl_T0_Dshift[ot]();
1107 #ifdef TARGET_X86_64
1108 if (s->aflag == 2) {
1109 gen_op_addq_ESI_T0();
1110 } else
1111 #endif
1112 if (s->aflag) {
1113 gen_op_addl_ESI_T0();
1114 } else {
1115 gen_op_addw_ESI_T0();
1119 /* same method as Valgrind : we generate jumps to current or next
1120 instruction */
1121 #define GEN_REPZ(op) \
1122 static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1123 target_ulong cur_eip, target_ulong next_eip) \
1125 int l2;\
1126 gen_update_cc_op(s); \
1127 l2 = gen_jz_ecx_string(s, next_eip); \
1128 gen_ ## op(s, ot); \
1129 gen_op_dec_ECX[s->aflag](); \
1130 /* a loop would cause two single step exceptions if ECX = 1 \
1131 before rep string_insn */ \
1132 if (!s->jmp_opt) \
1133 gen_op_jz_ecx[s->aflag](l2); \
1134 gen_jmp(s, cur_eip); \
1137 #define GEN_REPZ2(op) \
1138 static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1139 target_ulong cur_eip, \
1140 target_ulong next_eip, \
1141 int nz) \
1143 int l2;\
1144 gen_update_cc_op(s); \
1145 l2 = gen_jz_ecx_string(s, next_eip); \
1146 gen_ ## op(s, ot); \
1147 gen_op_dec_ECX[s->aflag](); \
1148 gen_op_set_cc_op(CC_OP_SUBB + ot); \
1149 gen_op_string_jnz_sub[nz][ot](l2);\
1150 if (!s->jmp_opt) \
1151 gen_op_jz_ecx[s->aflag](l2); \
1152 gen_jmp(s, cur_eip); \
1155 GEN_REPZ(movs)
1156 GEN_REPZ(stos)
1157 GEN_REPZ(lods)
1158 GEN_REPZ(ins)
1159 GEN_REPZ(outs)
1160 GEN_REPZ2(scas)
1161 GEN_REPZ2(cmps)
1163 enum {
1164 JCC_O,
1165 JCC_B,
1166 JCC_Z,
1167 JCC_BE,
1168 JCC_S,
1169 JCC_P,
1170 JCC_L,
1171 JCC_LE,
1174 static GenOpFunc1 *gen_jcc_sub[4][8] = {
1175 [OT_BYTE] = {
1176 NULL,
1177 gen_op_jb_subb,
1178 gen_op_jz_subb,
1179 gen_op_jbe_subb,
1180 gen_op_js_subb,
1181 NULL,
1182 gen_op_jl_subb,
1183 gen_op_jle_subb,
1185 [OT_WORD] = {
1186 NULL,
1187 gen_op_jb_subw,
1188 gen_op_jz_subw,
1189 gen_op_jbe_subw,
1190 gen_op_js_subw,
1191 NULL,
1192 gen_op_jl_subw,
1193 gen_op_jle_subw,
1195 [OT_LONG] = {
1196 NULL,
1197 gen_op_jb_subl,
1198 gen_op_jz_subl,
1199 gen_op_jbe_subl,
1200 gen_op_js_subl,
1201 NULL,
1202 gen_op_jl_subl,
1203 gen_op_jle_subl,
1205 #ifdef TARGET_X86_64
1206 [OT_QUAD] = {
1207 NULL,
1208 BUGGY_64(gen_op_jb_subq),
1209 gen_op_jz_subq,
1210 BUGGY_64(gen_op_jbe_subq),
1211 gen_op_js_subq,
1212 NULL,
1213 BUGGY_64(gen_op_jl_subq),
1214 BUGGY_64(gen_op_jle_subq),
1216 #endif
1218 static GenOpFunc1 *gen_op_loop[3][4] = {
1219 [0] = {
1220 gen_op_loopnzw,
1221 gen_op_loopzw,
1222 gen_op_jnz_ecxw,
1224 [1] = {
1225 gen_op_loopnzl,
1226 gen_op_loopzl,
1227 gen_op_jnz_ecxl,
1229 #ifdef TARGET_X86_64
1230 [2] = {
1231 gen_op_loopnzq,
1232 gen_op_loopzq,
1233 gen_op_jnz_ecxq,
1235 #endif
1238 static GenOpFunc *gen_setcc_slow[8] = {
1239 gen_op_seto_T0_cc,
1240 gen_op_setb_T0_cc,
1241 gen_op_setz_T0_cc,
1242 gen_op_setbe_T0_cc,
1243 gen_op_sets_T0_cc,
1244 gen_op_setp_T0_cc,
1245 gen_op_setl_T0_cc,
1246 gen_op_setle_T0_cc,
1249 static GenOpFunc *gen_setcc_sub[4][8] = {
1250 [OT_BYTE] = {
1251 NULL,
1252 gen_op_setb_T0_subb,
1253 gen_op_setz_T0_subb,
1254 gen_op_setbe_T0_subb,
1255 gen_op_sets_T0_subb,
1256 NULL,
1257 gen_op_setl_T0_subb,
1258 gen_op_setle_T0_subb,
1260 [OT_WORD] = {
1261 NULL,
1262 gen_op_setb_T0_subw,
1263 gen_op_setz_T0_subw,
1264 gen_op_setbe_T0_subw,
1265 gen_op_sets_T0_subw,
1266 NULL,
1267 gen_op_setl_T0_subw,
1268 gen_op_setle_T0_subw,
1270 [OT_LONG] = {
1271 NULL,
1272 gen_op_setb_T0_subl,
1273 gen_op_setz_T0_subl,
1274 gen_op_setbe_T0_subl,
1275 gen_op_sets_T0_subl,
1276 NULL,
1277 gen_op_setl_T0_subl,
1278 gen_op_setle_T0_subl,
1280 #ifdef TARGET_X86_64
1281 [OT_QUAD] = {
1282 NULL,
1283 gen_op_setb_T0_subq,
1284 gen_op_setz_T0_subq,
1285 gen_op_setbe_T0_subq,
1286 gen_op_sets_T0_subq,
1287 NULL,
1288 gen_op_setl_T0_subq,
1289 gen_op_setle_T0_subq,
1291 #endif
1294 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1295 gen_op_fadd_ST0_FT0,
1296 gen_op_fmul_ST0_FT0,
1297 gen_op_fcom_ST0_FT0,
1298 gen_op_fcom_ST0_FT0,
1299 gen_op_fsub_ST0_FT0,
1300 gen_op_fsubr_ST0_FT0,
1301 gen_op_fdiv_ST0_FT0,
1302 gen_op_fdivr_ST0_FT0,
1305 /* NOTE the exception in "r" op ordering */
1306 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1307 gen_op_fadd_STN_ST0,
1308 gen_op_fmul_STN_ST0,
1309 NULL,
1310 NULL,
1311 gen_op_fsubr_STN_ST0,
1312 gen_op_fsub_STN_ST0,
1313 gen_op_fdivr_STN_ST0,
1314 gen_op_fdiv_STN_ST0,
1317 /* if d == OR_TMP0, it means memory operand (address in A0) */
1318 static void gen_op(DisasContext *s1, int op, int ot, int d)
1320 GenOpFunc *gen_update_cc;
1322 if (d != OR_TMP0) {
1323 gen_op_mov_TN_reg[ot][0][d]();
1324 } else {
1325 gen_op_ld_T0_A0[ot + s1->mem_index]();
1327 switch(op) {
1328 case OP_ADCL:
1329 case OP_SBBL:
1330 if (s1->cc_op != CC_OP_DYNAMIC)
1331 gen_op_set_cc_op(s1->cc_op);
1332 if (d != OR_TMP0) {
1333 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1334 gen_op_mov_reg_T0[ot][d]();
1335 } else {
1336 gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
1338 s1->cc_op = CC_OP_DYNAMIC;
1339 goto the_end;
1340 case OP_ADDL:
1341 gen_op_addl_T0_T1();
1342 s1->cc_op = CC_OP_ADDB + ot;
1343 gen_update_cc = gen_op_update2_cc;
1344 break;
1345 case OP_SUBL:
1346 gen_op_subl_T0_T1();
1347 s1->cc_op = CC_OP_SUBB + ot;
1348 gen_update_cc = gen_op_update2_cc;
1349 break;
1350 default:
1351 case OP_ANDL:
1352 case OP_ORL:
1353 case OP_XORL:
1354 gen_op_arith_T0_T1_cc[op]();
1355 s1->cc_op = CC_OP_LOGICB + ot;
1356 gen_update_cc = gen_op_update1_cc;
1357 break;
1358 case OP_CMPL:
1359 gen_op_cmpl_T0_T1_cc();
1360 s1->cc_op = CC_OP_SUBB + ot;
1361 gen_update_cc = NULL;
1362 break;
1364 if (op != OP_CMPL) {
1365 if (d != OR_TMP0)
1366 gen_op_mov_reg_T0[ot][d]();
1367 else
1368 gen_op_st_T0_A0[ot + s1->mem_index]();
1370 /* the flags update must happen after the memory write (precise
1371 exception support) */
1372 if (gen_update_cc)
1373 gen_update_cc();
1374 the_end: ;
1377 /* if d == OR_TMP0, it means memory operand (address in A0) */
1378 static void gen_inc(DisasContext *s1, int ot, int d, int c)
1380 if (d != OR_TMP0)
1381 gen_op_mov_TN_reg[ot][0][d]();
1382 else
1383 gen_op_ld_T0_A0[ot + s1->mem_index]();
1384 if (s1->cc_op != CC_OP_DYNAMIC)
1385 gen_op_set_cc_op(s1->cc_op);
1386 if (c > 0) {
1387 gen_op_incl_T0();
1388 s1->cc_op = CC_OP_INCB + ot;
1389 } else {
1390 gen_op_decl_T0();
1391 s1->cc_op = CC_OP_DECB + ot;
1393 if (d != OR_TMP0)
1394 gen_op_mov_reg_T0[ot][d]();
1395 else
1396 gen_op_st_T0_A0[ot + s1->mem_index]();
1397 gen_op_update_inc_cc();
1400 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1402 if (d != OR_TMP0)
1403 gen_op_mov_TN_reg[ot][0][d]();
1404 else
1405 gen_op_ld_T0_A0[ot + s1->mem_index]();
1406 if (s != OR_TMP1)
1407 gen_op_mov_TN_reg[ot][1][s]();
1408 /* for zero counts, flags are not updated, so must do it dynamically */
1409 if (s1->cc_op != CC_OP_DYNAMIC)
1410 gen_op_set_cc_op(s1->cc_op);
1412 if (d != OR_TMP0)
1413 gen_op_shift_T0_T1_cc[ot][op]();
1414 else
1415 gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
1416 if (d != OR_TMP0)
1417 gen_op_mov_reg_T0[ot][d]();
1418 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1421 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1423 /* currently not optimized */
1424 gen_op_movl_T1_im(c);
1425 gen_shift(s1, op, ot, d, OR_TMP1);
1428 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1430 target_long disp;
1431 int havesib;
1432 int base;
1433 int index;
1434 int scale;
1435 int opreg;
1436 int mod, rm, code, override, must_add_seg;
1438 override = s->override;
1439 must_add_seg = s->addseg;
1440 if (override >= 0)
1441 must_add_seg = 1;
1442 mod = (modrm >> 6) & 3;
1443 rm = modrm & 7;
1445 if (s->aflag) {
1447 havesib = 0;
1448 base = rm;
1449 index = 0;
1450 scale = 0;
1452 if (base == 4) {
1453 havesib = 1;
1454 code = ldub_code(s->pc++);
1455 scale = (code >> 6) & 3;
1456 index = ((code >> 3) & 7) | REX_X(s);
1457 base = (code & 7);
1459 base |= REX_B(s);
1461 switch (mod) {
1462 case 0:
1463 if ((base & 7) == 5) {
1464 base = -1;
1465 disp = (int32_t)ldl_code(s->pc);
1466 s->pc += 4;
1467 if (CODE64(s) && !havesib) {
1468 disp += s->pc + s->rip_offset;
1470 } else {
1471 disp = 0;
1473 break;
1474 case 1:
1475 disp = (int8_t)ldub_code(s->pc++);
1476 break;
1477 default:
1478 case 2:
1479 disp = ldl_code(s->pc);
1480 s->pc += 4;
1481 break;
1484 if (base >= 0) {
1485 /* for correct popl handling with esp */
1486 if (base == 4 && s->popl_esp_hack)
1487 disp += s->popl_esp_hack;
1488 #ifdef TARGET_X86_64
1489 if (s->aflag == 2) {
1490 gen_op_movq_A0_reg[base]();
1491 if (disp != 0) {
1492 if ((int32_t)disp == disp)
1493 gen_op_addq_A0_im(disp);
1494 else
1495 gen_op_addq_A0_im64(disp >> 32, disp);
1497 } else
1498 #endif
1500 gen_op_movl_A0_reg[base]();
1501 if (disp != 0)
1502 gen_op_addl_A0_im(disp);
1504 } else {
1505 #ifdef TARGET_X86_64
1506 if (s->aflag == 2) {
1507 if ((int32_t)disp == disp)
1508 gen_op_movq_A0_im(disp);
1509 else
1510 gen_op_movq_A0_im64(disp >> 32, disp);
1511 } else
1512 #endif
1514 gen_op_movl_A0_im(disp);
1517 /* XXX: index == 4 is always invalid */
1518 if (havesib && (index != 4 || scale != 0)) {
1519 #ifdef TARGET_X86_64
1520 if (s->aflag == 2) {
1521 gen_op_addq_A0_reg_sN[scale][index]();
1522 } else
1523 #endif
1525 gen_op_addl_A0_reg_sN[scale][index]();
1528 if (must_add_seg) {
1529 if (override < 0) {
1530 if (base == R_EBP || base == R_ESP)
1531 override = R_SS;
1532 else
1533 override = R_DS;
1535 #ifdef TARGET_X86_64
1536 if (s->aflag == 2) {
1537 gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
1538 } else
1539 #endif
1541 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1544 } else {
1545 switch (mod) {
1546 case 0:
1547 if (rm == 6) {
1548 disp = lduw_code(s->pc);
1549 s->pc += 2;
1550 gen_op_movl_A0_im(disp);
1551 rm = 0; /* avoid SS override */
1552 goto no_rm;
1553 } else {
1554 disp = 0;
1556 break;
1557 case 1:
1558 disp = (int8_t)ldub_code(s->pc++);
1559 break;
1560 default:
1561 case 2:
1562 disp = lduw_code(s->pc);
1563 s->pc += 2;
1564 break;
1566 switch(rm) {
1567 case 0:
1568 gen_op_movl_A0_reg[R_EBX]();
1569 gen_op_addl_A0_reg_sN[0][R_ESI]();
1570 break;
1571 case 1:
1572 gen_op_movl_A0_reg[R_EBX]();
1573 gen_op_addl_A0_reg_sN[0][R_EDI]();
1574 break;
1575 case 2:
1576 gen_op_movl_A0_reg[R_EBP]();
1577 gen_op_addl_A0_reg_sN[0][R_ESI]();
1578 break;
1579 case 3:
1580 gen_op_movl_A0_reg[R_EBP]();
1581 gen_op_addl_A0_reg_sN[0][R_EDI]();
1582 break;
1583 case 4:
1584 gen_op_movl_A0_reg[R_ESI]();
1585 break;
1586 case 5:
1587 gen_op_movl_A0_reg[R_EDI]();
1588 break;
1589 case 6:
1590 gen_op_movl_A0_reg[R_EBP]();
1591 break;
1592 default:
1593 case 7:
1594 gen_op_movl_A0_reg[R_EBX]();
1595 break;
1597 if (disp != 0)
1598 gen_op_addl_A0_im(disp);
1599 gen_op_andl_A0_ffff();
1600 no_rm:
1601 if (must_add_seg) {
1602 if (override < 0) {
1603 if (rm == 2 || rm == 3 || rm == 6)
1604 override = R_SS;
1605 else
1606 override = R_DS;
1608 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1612 opreg = OR_A0;
1613 disp = 0;
1614 *reg_ptr = opreg;
1615 *offset_ptr = disp;
1618 static void gen_nop_modrm(DisasContext *s, int modrm)
1620 int mod, rm, base, code;
1622 mod = (modrm >> 6) & 3;
1623 if (mod == 3)
1624 return;
1625 rm = modrm & 7;
1627 if (s->aflag) {
1629 base = rm;
1631 if (base == 4) {
1632 code = ldub_code(s->pc++);
1633 base = (code & 7);
1636 switch (mod) {
1637 case 0:
1638 if (base == 5) {
1639 s->pc += 4;
1641 break;
1642 case 1:
1643 s->pc++;
1644 break;
1645 default:
1646 case 2:
1647 s->pc += 4;
1648 break;
1650 } else {
1651 switch (mod) {
1652 case 0:
1653 if (rm == 6) {
1654 s->pc += 2;
1656 break;
1657 case 1:
1658 s->pc++;
1659 break;
1660 default:
1661 case 2:
1662 s->pc += 2;
1663 break;
1668 /* used for LEA and MOV AX, mem */
1669 static void gen_add_A0_ds_seg(DisasContext *s)
1671 int override, must_add_seg;
1672 must_add_seg = s->addseg;
1673 override = R_DS;
1674 if (s->override >= 0) {
1675 override = s->override;
1676 must_add_seg = 1;
1677 } else {
1678 override = R_DS;
1680 if (must_add_seg) {
1681 #ifdef TARGET_X86_64
1682 if (CODE64(s)) {
1683 gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
1684 } else
1685 #endif
1687 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1692 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1693 OR_TMP0 */
1694 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1696 int mod, rm, opreg, disp;
1698 mod = (modrm >> 6) & 3;
1699 rm = (modrm & 7) | REX_B(s);
1700 if (mod == 3) {
1701 if (is_store) {
1702 if (reg != OR_TMP0)
1703 gen_op_mov_TN_reg[ot][0][reg]();
1704 gen_op_mov_reg_T0[ot][rm]();
1705 } else {
1706 gen_op_mov_TN_reg[ot][0][rm]();
1707 if (reg != OR_TMP0)
1708 gen_op_mov_reg_T0[ot][reg]();
1710 } else {
1711 gen_lea_modrm(s, modrm, &opreg, &disp);
1712 if (is_store) {
1713 if (reg != OR_TMP0)
1714 gen_op_mov_TN_reg[ot][0][reg]();
1715 gen_op_st_T0_A0[ot + s->mem_index]();
1716 } else {
1717 gen_op_ld_T0_A0[ot + s->mem_index]();
1718 if (reg != OR_TMP0)
1719 gen_op_mov_reg_T0[ot][reg]();
1724 static inline uint32_t insn_get(DisasContext *s, int ot)
1726 uint32_t ret;
1728 switch(ot) {
1729 case OT_BYTE:
1730 ret = ldub_code(s->pc);
1731 s->pc++;
1732 break;
1733 case OT_WORD:
1734 ret = lduw_code(s->pc);
1735 s->pc += 2;
1736 break;
1737 default:
1738 case OT_LONG:
1739 ret = ldl_code(s->pc);
1740 s->pc += 4;
1741 break;
1743 return ret;
1746 static inline int insn_const_size(unsigned int ot)
1748 if (ot <= OT_LONG)
1749 return 1 << ot;
1750 else
1751 return 4;
1754 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
1756 TranslationBlock *tb;
1757 target_ulong pc;
1759 pc = s->cs_base + eip;
1760 tb = s->tb;
1761 /* NOTE: we handle the case where the TB spans two pages here */
1762 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
1763 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
1764 /* jump to same page: we can use a direct jump */
1765 if (tb_num == 0)
1766 gen_op_goto_tb0(TBPARAM(tb));
1767 else
1768 gen_op_goto_tb1(TBPARAM(tb));
1769 gen_jmp_im(eip);
1770 gen_op_movl_T0_im((long)tb + tb_num);
1771 gen_op_exit_tb();
1772 } else {
1773 /* jump to another page: currently not optimized */
1774 gen_jmp_im(eip);
1775 gen_eob(s);
1779 static inline void gen_jcc(DisasContext *s, int b,
1780 target_ulong val, target_ulong next_eip)
1782 TranslationBlock *tb;
1783 int inv, jcc_op;
1784 GenOpFunc1 *func;
1785 target_ulong tmp;
1786 int l1, l2;
1788 inv = b & 1;
1789 jcc_op = (b >> 1) & 7;
1791 if (s->jmp_opt) {
1792 switch(s->cc_op) {
1793 /* we optimize the cmp/jcc case */
1794 case CC_OP_SUBB:
1795 case CC_OP_SUBW:
1796 case CC_OP_SUBL:
1797 case CC_OP_SUBQ:
1798 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1799 break;
1801 /* some jumps are easy to compute */
1802 case CC_OP_ADDB:
1803 case CC_OP_ADDW:
1804 case CC_OP_ADDL:
1805 case CC_OP_ADDQ:
1807 case CC_OP_ADCB:
1808 case CC_OP_ADCW:
1809 case CC_OP_ADCL:
1810 case CC_OP_ADCQ:
1812 case CC_OP_SBBB:
1813 case CC_OP_SBBW:
1814 case CC_OP_SBBL:
1815 case CC_OP_SBBQ:
1817 case CC_OP_LOGICB:
1818 case CC_OP_LOGICW:
1819 case CC_OP_LOGICL:
1820 case CC_OP_LOGICQ:
1822 case CC_OP_INCB:
1823 case CC_OP_INCW:
1824 case CC_OP_INCL:
1825 case CC_OP_INCQ:
1827 case CC_OP_DECB:
1828 case CC_OP_DECW:
1829 case CC_OP_DECL:
1830 case CC_OP_DECQ:
1832 case CC_OP_SHLB:
1833 case CC_OP_SHLW:
1834 case CC_OP_SHLL:
1835 case CC_OP_SHLQ:
1837 case CC_OP_SARB:
1838 case CC_OP_SARW:
1839 case CC_OP_SARL:
1840 case CC_OP_SARQ:
1841 switch(jcc_op) {
1842 case JCC_Z:
1843 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1844 break;
1845 case JCC_S:
1846 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1847 break;
1848 default:
1849 func = NULL;
1850 break;
1852 break;
1853 default:
1854 func = NULL;
1855 break;
1858 if (s->cc_op != CC_OP_DYNAMIC) {
1859 gen_op_set_cc_op(s->cc_op);
1860 s->cc_op = CC_OP_DYNAMIC;
1863 if (!func) {
1864 gen_setcc_slow[jcc_op]();
1865 func = gen_op_jnz_T0_label;
1868 if (inv) {
1869 tmp = val;
1870 val = next_eip;
1871 next_eip = tmp;
1873 tb = s->tb;
1875 l1 = gen_new_label();
1876 func(l1);
1878 gen_goto_tb(s, 0, next_eip);
1880 gen_set_label(l1);
1881 gen_goto_tb(s, 1, val);
1883 s->is_jmp = 3;
1884 } else {
1886 if (s->cc_op != CC_OP_DYNAMIC) {
1887 gen_op_set_cc_op(s->cc_op);
1888 s->cc_op = CC_OP_DYNAMIC;
1890 gen_setcc_slow[jcc_op]();
1891 if (inv) {
1892 tmp = val;
1893 val = next_eip;
1894 next_eip = tmp;
1896 l1 = gen_new_label();
1897 l2 = gen_new_label();
1898 gen_op_jnz_T0_label(l1);
1899 gen_jmp_im(next_eip);
1900 gen_op_jmp_label(l2);
1901 gen_set_label(l1);
1902 gen_jmp_im(val);
1903 gen_set_label(l2);
1904 gen_eob(s);
1908 static void gen_setcc(DisasContext *s, int b)
1910 int inv, jcc_op;
1911 GenOpFunc *func;
1913 inv = b & 1;
1914 jcc_op = (b >> 1) & 7;
1915 switch(s->cc_op) {
1916 /* we optimize the cmp/jcc case */
1917 case CC_OP_SUBB:
1918 case CC_OP_SUBW:
1919 case CC_OP_SUBL:
1920 case CC_OP_SUBQ:
1921 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1922 if (!func)
1923 goto slow_jcc;
1924 break;
1926 /* some jumps are easy to compute */
1927 case CC_OP_ADDB:
1928 case CC_OP_ADDW:
1929 case CC_OP_ADDL:
1930 case CC_OP_ADDQ:
1932 case CC_OP_LOGICB:
1933 case CC_OP_LOGICW:
1934 case CC_OP_LOGICL:
1935 case CC_OP_LOGICQ:
1937 case CC_OP_INCB:
1938 case CC_OP_INCW:
1939 case CC_OP_INCL:
1940 case CC_OP_INCQ:
1942 case CC_OP_DECB:
1943 case CC_OP_DECW:
1944 case CC_OP_DECL:
1945 case CC_OP_DECQ:
1947 case CC_OP_SHLB:
1948 case CC_OP_SHLW:
1949 case CC_OP_SHLL:
1950 case CC_OP_SHLQ:
1951 switch(jcc_op) {
1952 case JCC_Z:
1953 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1954 break;
1955 case JCC_S:
1956 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1957 break;
1958 default:
1959 goto slow_jcc;
1961 break;
1962 default:
1963 slow_jcc:
1964 if (s->cc_op != CC_OP_DYNAMIC)
1965 gen_op_set_cc_op(s->cc_op);
1966 func = gen_setcc_slow[jcc_op];
1967 break;
1969 func();
1970 if (inv) {
1971 gen_op_xor_T0_1();
1975 /* move T0 to seg_reg and compute if the CPU state may change. Never
1976 call this function with seg_reg == R_CS */
1977 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
1979 if (s->pe && !s->vm86) {
1980 /* XXX: optimize by finding processor state dynamically */
1981 if (s->cc_op != CC_OP_DYNAMIC)
1982 gen_op_set_cc_op(s->cc_op);
1983 gen_jmp_im(cur_eip);
1984 gen_op_movl_seg_T0(seg_reg);
1985 /* abort translation because the addseg value may change or
1986 because ss32 may change. For R_SS, translation must always
1987 stop as a special handling must be done to disable hardware
1988 interrupts for the next instruction */
1989 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1990 s->is_jmp = 3;
1991 } else {
1992 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1993 if (seg_reg == R_SS)
1994 s->is_jmp = 3;
1998 #ifdef TARGET_X86_64
1999 #define SVM_movq_T1_im(x) gen_op_movq_T1_im64((x) >> 32, x)
2000 #else
2001 #define SVM_movq_T1_im(x) gen_op_movl_T1_im(x)
2002 #endif
2004 static inline int
2005 gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type)
2007 #if !defined(CONFIG_USER_ONLY)
2008 if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) {
2009 if (s->cc_op != CC_OP_DYNAMIC)
2010 gen_op_set_cc_op(s->cc_op);
2011 SVM_movq_T1_im(s->pc - s->cs_base);
2012 gen_jmp_im(pc_start - s->cs_base);
2013 gen_op_geneflags();
2014 gen_op_svm_check_intercept_io((uint32_t)(type >> 32), (uint32_t)type);
2015 s->cc_op = CC_OP_DYNAMIC;
2016 /* FIXME: maybe we could move the io intercept vector to the TB as well
2017 so we know if this is an EOB or not ... let's assume it's not
2018 for now. */
2020 #endif
2021 return 0;
2024 static inline int svm_is_rep(int prefixes)
2026 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2029 static inline int
2030 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2031 uint64_t type, uint64_t param)
2033 if(!(s->flags & (INTERCEPT_SVM_MASK)))
2034 /* no SVM activated */
2035 return 0;
2036 switch(type) {
2037 /* CRx and DRx reads/writes */
2038 case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1:
2039 if (s->cc_op != CC_OP_DYNAMIC) {
2040 gen_op_set_cc_op(s->cc_op);
2041 s->cc_op = CC_OP_DYNAMIC;
2043 gen_jmp_im(pc_start - s->cs_base);
2044 SVM_movq_T1_im(param);
2045 gen_op_geneflags();
2046 gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
2047 /* this is a special case as we do not know if the interception occurs
2048 so we assume there was none */
2049 return 0;
2050 case SVM_EXIT_MSR:
2051 if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) {
2052 if (s->cc_op != CC_OP_DYNAMIC) {
2053 gen_op_set_cc_op(s->cc_op);
2054 s->cc_op = CC_OP_DYNAMIC;
2056 gen_jmp_im(pc_start - s->cs_base);
2057 SVM_movq_T1_im(param);
2058 gen_op_geneflags();
2059 gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
2060 /* this is a special case as we do not know if the interception occurs
2061 so we assume there was none */
2062 return 0;
2064 break;
2065 default:
2066 if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) {
2067 if (s->cc_op != CC_OP_DYNAMIC) {
2068 gen_op_set_cc_op(s->cc_op);
2069 s->cc_op = CC_OP_EFLAGS;
2071 gen_jmp_im(pc_start - s->cs_base);
2072 SVM_movq_T1_im(param);
2073 gen_op_geneflags();
2074 gen_op_svm_vmexit(type >> 32, type);
2075 /* we can optimize this one so TBs don't get longer
2076 than up to vmexit */
2077 gen_eob(s);
2078 return 1;
2081 return 0;
2084 static inline int
2085 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2087 return gen_svm_check_intercept_param(s, pc_start, type, 0);
2090 static inline void gen_stack_update(DisasContext *s, int addend)
2092 #ifdef TARGET_X86_64
2093 if (CODE64(s)) {
2094 if (addend == 8)
2095 gen_op_addq_ESP_8();
2096 else
2097 gen_op_addq_ESP_im(addend);
2098 } else
2099 #endif
2100 if (s->ss32) {
2101 if (addend == 2)
2102 gen_op_addl_ESP_2();
2103 else if (addend == 4)
2104 gen_op_addl_ESP_4();
2105 else
2106 gen_op_addl_ESP_im(addend);
2107 } else {
2108 if (addend == 2)
2109 gen_op_addw_ESP_2();
2110 else if (addend == 4)
2111 gen_op_addw_ESP_4();
2112 else
2113 gen_op_addw_ESP_im(addend);
2117 /* generate a push. It depends on ss32, addseg and dflag */
2118 static void gen_push_T0(DisasContext *s)
2120 #ifdef TARGET_X86_64
2121 if (CODE64(s)) {
2122 gen_op_movq_A0_reg[R_ESP]();
2123 if (s->dflag) {
2124 gen_op_subq_A0_8();
2125 gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
2126 } else {
2127 gen_op_subq_A0_2();
2128 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2130 gen_op_movq_ESP_A0();
2131 } else
2132 #endif
2134 gen_op_movl_A0_reg[R_ESP]();
2135 if (!s->dflag)
2136 gen_op_subl_A0_2();
2137 else
2138 gen_op_subl_A0_4();
2139 if (s->ss32) {
2140 if (s->addseg) {
2141 gen_op_movl_T1_A0();
2142 gen_op_addl_A0_SS();
2144 } else {
2145 gen_op_andl_A0_ffff();
2146 gen_op_movl_T1_A0();
2147 gen_op_addl_A0_SS();
2149 gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
2150 if (s->ss32 && !s->addseg)
2151 gen_op_movl_ESP_A0();
2152 else
2153 gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
2157 /* generate a push. It depends on ss32, addseg and dflag */
2158 /* slower version for T1, only used for call Ev */
2159 static void gen_push_T1(DisasContext *s)
2161 #ifdef TARGET_X86_64
2162 if (CODE64(s)) {
2163 gen_op_movq_A0_reg[R_ESP]();
2164 if (s->dflag) {
2165 gen_op_subq_A0_8();
2166 gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
2167 } else {
2168 gen_op_subq_A0_2();
2169 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2171 gen_op_movq_ESP_A0();
2172 } else
2173 #endif
2175 gen_op_movl_A0_reg[R_ESP]();
2176 if (!s->dflag)
2177 gen_op_subl_A0_2();
2178 else
2179 gen_op_subl_A0_4();
2180 if (s->ss32) {
2181 if (s->addseg) {
2182 gen_op_addl_A0_SS();
2184 } else {
2185 gen_op_andl_A0_ffff();
2186 gen_op_addl_A0_SS();
2188 gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
2190 if (s->ss32 && !s->addseg)
2191 gen_op_movl_ESP_A0();
2192 else
2193 gen_stack_update(s, (-2) << s->dflag);
2197 /* two step pop is necessary for precise exceptions */
2198 static void gen_pop_T0(DisasContext *s)
2200 #ifdef TARGET_X86_64
2201 if (CODE64(s)) {
2202 gen_op_movq_A0_reg[R_ESP]();
2203 gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index]();
2204 } else
2205 #endif
2207 gen_op_movl_A0_reg[R_ESP]();
2208 if (s->ss32) {
2209 if (s->addseg)
2210 gen_op_addl_A0_SS();
2211 } else {
2212 gen_op_andl_A0_ffff();
2213 gen_op_addl_A0_SS();
2215 gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2219 static void gen_pop_update(DisasContext *s)
2221 #ifdef TARGET_X86_64
2222 if (CODE64(s) && s->dflag) {
2223 gen_stack_update(s, 8);
2224 } else
2225 #endif
2227 gen_stack_update(s, 2 << s->dflag);
2231 static void gen_stack_A0(DisasContext *s)
2233 gen_op_movl_A0_ESP();
2234 if (!s->ss32)
2235 gen_op_andl_A0_ffff();
2236 gen_op_movl_T1_A0();
2237 if (s->addseg)
2238 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2241 /* NOTE: wrap around in 16 bit not fully handled */
2242 static void gen_pusha(DisasContext *s)
2244 int i;
2245 gen_op_movl_A0_ESP();
2246 gen_op_addl_A0_im(-16 << s->dflag);
2247 if (!s->ss32)
2248 gen_op_andl_A0_ffff();
2249 gen_op_movl_T1_A0();
2250 if (s->addseg)
2251 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2252 for(i = 0;i < 8; i++) {
2253 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
2254 gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2255 gen_op_addl_A0_im(2 << s->dflag);
2257 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2260 /* NOTE: wrap around in 16 bit not fully handled */
2261 static void gen_popa(DisasContext *s)
2263 int i;
2264 gen_op_movl_A0_ESP();
2265 if (!s->ss32)
2266 gen_op_andl_A0_ffff();
2267 gen_op_movl_T1_A0();
2268 gen_op_addl_T1_im(16 << s->dflag);
2269 if (s->addseg)
2270 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2271 for(i = 0;i < 8; i++) {
2272 /* ESP is not reloaded */
2273 if (i != 3) {
2274 gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2275 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
2277 gen_op_addl_A0_im(2 << s->dflag);
2279 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2282 static void gen_enter(DisasContext *s, int esp_addend, int level)
2284 int ot, opsize;
2286 level &= 0x1f;
2287 #ifdef TARGET_X86_64
2288 if (CODE64(s)) {
2289 ot = s->dflag ? OT_QUAD : OT_WORD;
2290 opsize = 1 << ot;
2292 gen_op_movl_A0_ESP();
2293 gen_op_addq_A0_im(-opsize);
2294 gen_op_movl_T1_A0();
2296 /* push bp */
2297 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2298 gen_op_st_T0_A0[ot + s->mem_index]();
2299 if (level) {
2300 gen_op_enter64_level(level, (ot == OT_QUAD));
2302 gen_op_mov_reg_T1[ot][R_EBP]();
2303 gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2304 gen_op_mov_reg_T1[OT_QUAD][R_ESP]();
2305 } else
2306 #endif
2308 ot = s->dflag + OT_WORD;
2309 opsize = 2 << s->dflag;
2311 gen_op_movl_A0_ESP();
2312 gen_op_addl_A0_im(-opsize);
2313 if (!s->ss32)
2314 gen_op_andl_A0_ffff();
2315 gen_op_movl_T1_A0();
2316 if (s->addseg)
2317 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2318 /* push bp */
2319 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2320 gen_op_st_T0_A0[ot + s->mem_index]();
2321 if (level) {
2322 gen_op_enter_level(level, s->dflag);
2324 gen_op_mov_reg_T1[ot][R_EBP]();
2325 gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2326 gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2330 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2332 if (s->cc_op != CC_OP_DYNAMIC)
2333 gen_op_set_cc_op(s->cc_op);
2334 gen_jmp_im(cur_eip);
2335 gen_op_raise_exception(trapno);
2336 s->is_jmp = 3;
2339 /* an interrupt is different from an exception because of the
2340 privilege checks */
2341 static void gen_interrupt(DisasContext *s, int intno,
2342 target_ulong cur_eip, target_ulong next_eip)
2344 if (s->cc_op != CC_OP_DYNAMIC)
2345 gen_op_set_cc_op(s->cc_op);
2346 gen_jmp_im(cur_eip);
2347 gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
2348 s->is_jmp = 3;
2351 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2353 if (s->cc_op != CC_OP_DYNAMIC)
2354 gen_op_set_cc_op(s->cc_op);
2355 gen_jmp_im(cur_eip);
2356 gen_op_debug();
2357 s->is_jmp = 3;
2360 /* generate a generic end of block. Trace exception is also generated
2361 if needed */
2362 static void gen_eob(DisasContext *s)
2364 if (s->cc_op != CC_OP_DYNAMIC)
2365 gen_op_set_cc_op(s->cc_op);
2366 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2367 gen_op_reset_inhibit_irq();
2369 if (s->singlestep_enabled) {
2370 gen_op_debug();
2371 } else if (s->tf) {
2372 gen_op_single_step();
2373 } else {
2374 gen_op_movl_T0_0();
2375 gen_op_exit_tb();
2377 s->is_jmp = 3;
2380 /* generate a jump to eip. No segment change must happen before as a
2381 direct call to the next block may occur */
2382 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2384 if (s->jmp_opt) {
2385 if (s->cc_op != CC_OP_DYNAMIC) {
2386 gen_op_set_cc_op(s->cc_op);
2387 s->cc_op = CC_OP_DYNAMIC;
2389 gen_goto_tb(s, tb_num, eip);
2390 s->is_jmp = 3;
2391 } else {
2392 gen_jmp_im(eip);
2393 gen_eob(s);
2397 static void gen_jmp(DisasContext *s, target_ulong eip)
2399 gen_jmp_tb(s, eip, 0);
2402 static void gen_movtl_T0_im(target_ulong val)
2404 #ifdef TARGET_X86_64
2405 if ((int32_t)val == val) {
2406 gen_op_movl_T0_im(val);
2407 } else {
2408 gen_op_movq_T0_im64(val >> 32, val);
2410 #else
2411 gen_op_movl_T0_im(val);
2412 #endif
2415 static void gen_movtl_T1_im(target_ulong val)
2417 #ifdef TARGET_X86_64
2418 if ((int32_t)val == val) {
2419 gen_op_movl_T1_im(val);
2420 } else {
2421 gen_op_movq_T1_im64(val >> 32, val);
2423 #else
2424 gen_op_movl_T1_im(val);
2425 #endif
2428 static void gen_add_A0_im(DisasContext *s, int val)
2430 #ifdef TARGET_X86_64
2431 if (CODE64(s))
2432 gen_op_addq_A0_im(val);
2433 else
2434 #endif
2435 gen_op_addl_A0_im(val);
2438 static GenOpFunc1 *gen_ldq_env_A0[3] = {
2439 gen_op_ldq_raw_env_A0,
2440 #ifndef CONFIG_USER_ONLY
2441 gen_op_ldq_kernel_env_A0,
2442 gen_op_ldq_user_env_A0,
2443 #endif
2446 static GenOpFunc1 *gen_stq_env_A0[3] = {
2447 gen_op_stq_raw_env_A0,
2448 #ifndef CONFIG_USER_ONLY
2449 gen_op_stq_kernel_env_A0,
2450 gen_op_stq_user_env_A0,
2451 #endif
2454 static GenOpFunc1 *gen_ldo_env_A0[3] = {
2455 gen_op_ldo_raw_env_A0,
2456 #ifndef CONFIG_USER_ONLY
2457 gen_op_ldo_kernel_env_A0,
2458 gen_op_ldo_user_env_A0,
2459 #endif
2462 static GenOpFunc1 *gen_sto_env_A0[3] = {
2463 gen_op_sto_raw_env_A0,
2464 #ifndef CONFIG_USER_ONLY
2465 gen_op_sto_kernel_env_A0,
2466 gen_op_sto_user_env_A0,
2467 #endif
2470 #define SSE_SPECIAL ((GenOpFunc2 *)1)
2472 #define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm }
2473 #define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \
2474 gen_op_ ## x ## ss, gen_op_ ## x ## sd, }
2476 static GenOpFunc2 *sse_op_table1[256][4] = {
2477 /* pure SSE operations */
2478 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2479 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2480 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2481 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2482 [0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm },
2483 [0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm },
2484 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2485 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2487 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2488 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2489 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2490 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd */
2491 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2492 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2493 [0x2e] = { gen_op_ucomiss, gen_op_ucomisd },
2494 [0x2f] = { gen_op_comiss, gen_op_comisd },
2495 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2496 [0x51] = SSE_FOP(sqrt),
2497 [0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL },
2498 [0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL },
2499 [0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */
2500 [0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */
2501 [0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */
2502 [0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */
2503 [0x58] = SSE_FOP(add),
2504 [0x59] = SSE_FOP(mul),
2505 [0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps,
2506 gen_op_cvtss2sd, gen_op_cvtsd2ss },
2507 [0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq },
2508 [0x5c] = SSE_FOP(sub),
2509 [0x5d] = SSE_FOP(min),
2510 [0x5e] = SSE_FOP(div),
2511 [0x5f] = SSE_FOP(max),
2513 [0xc2] = SSE_FOP(cmpeq),
2514 [0xc6] = { (GenOpFunc2 *)gen_op_shufps, (GenOpFunc2 *)gen_op_shufpd },
2516 /* MMX ops and their SSE extensions */
2517 [0x60] = MMX_OP2(punpcklbw),
2518 [0x61] = MMX_OP2(punpcklwd),
2519 [0x62] = MMX_OP2(punpckldq),
2520 [0x63] = MMX_OP2(packsswb),
2521 [0x64] = MMX_OP2(pcmpgtb),
2522 [0x65] = MMX_OP2(pcmpgtw),
2523 [0x66] = MMX_OP2(pcmpgtl),
2524 [0x67] = MMX_OP2(packuswb),
2525 [0x68] = MMX_OP2(punpckhbw),
2526 [0x69] = MMX_OP2(punpckhwd),
2527 [0x6a] = MMX_OP2(punpckhdq),
2528 [0x6b] = MMX_OP2(packssdw),
2529 [0x6c] = { NULL, gen_op_punpcklqdq_xmm },
2530 [0x6d] = { NULL, gen_op_punpckhqdq_xmm },
2531 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2532 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2533 [0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx,
2534 (GenOpFunc2 *)gen_op_pshufd_xmm,
2535 (GenOpFunc2 *)gen_op_pshufhw_xmm,
2536 (GenOpFunc2 *)gen_op_pshuflw_xmm },
2537 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2538 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2539 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2540 [0x74] = MMX_OP2(pcmpeqb),
2541 [0x75] = MMX_OP2(pcmpeqw),
2542 [0x76] = MMX_OP2(pcmpeql),
2543 [0x77] = { SSE_SPECIAL }, /* emms */
2544 [0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps },
2545 [0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps },
2546 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2547 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2548 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2549 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2550 [0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps },
2551 [0xd1] = MMX_OP2(psrlw),
2552 [0xd2] = MMX_OP2(psrld),
2553 [0xd3] = MMX_OP2(psrlq),
2554 [0xd4] = MMX_OP2(paddq),
2555 [0xd5] = MMX_OP2(pmullw),
2556 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2557 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2558 [0xd8] = MMX_OP2(psubusb),
2559 [0xd9] = MMX_OP2(psubusw),
2560 [0xda] = MMX_OP2(pminub),
2561 [0xdb] = MMX_OP2(pand),
2562 [0xdc] = MMX_OP2(paddusb),
2563 [0xdd] = MMX_OP2(paddusw),
2564 [0xde] = MMX_OP2(pmaxub),
2565 [0xdf] = MMX_OP2(pandn),
2566 [0xe0] = MMX_OP2(pavgb),
2567 [0xe1] = MMX_OP2(psraw),
2568 [0xe2] = MMX_OP2(psrad),
2569 [0xe3] = MMX_OP2(pavgw),
2570 [0xe4] = MMX_OP2(pmulhuw),
2571 [0xe5] = MMX_OP2(pmulhw),
2572 [0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq },
2573 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2574 [0xe8] = MMX_OP2(psubsb),
2575 [0xe9] = MMX_OP2(psubsw),
2576 [0xea] = MMX_OP2(pminsw),
2577 [0xeb] = MMX_OP2(por),
2578 [0xec] = MMX_OP2(paddsb),
2579 [0xed] = MMX_OP2(paddsw),
2580 [0xee] = MMX_OP2(pmaxsw),
2581 [0xef] = MMX_OP2(pxor),
2582 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2583 [0xf1] = MMX_OP2(psllw),
2584 [0xf2] = MMX_OP2(pslld),
2585 [0xf3] = MMX_OP2(psllq),
2586 [0xf4] = MMX_OP2(pmuludq),
2587 [0xf5] = MMX_OP2(pmaddwd),
2588 [0xf6] = MMX_OP2(psadbw),
2589 [0xf7] = MMX_OP2(maskmov),
2590 [0xf8] = MMX_OP2(psubb),
2591 [0xf9] = MMX_OP2(psubw),
2592 [0xfa] = MMX_OP2(psubl),
2593 [0xfb] = MMX_OP2(psubq),
2594 [0xfc] = MMX_OP2(paddb),
2595 [0xfd] = MMX_OP2(paddw),
2596 [0xfe] = MMX_OP2(paddl),
2599 static GenOpFunc2 *sse_op_table2[3 * 8][2] = {
2600 [0 + 2] = MMX_OP2(psrlw),
2601 [0 + 4] = MMX_OP2(psraw),
2602 [0 + 6] = MMX_OP2(psllw),
2603 [8 + 2] = MMX_OP2(psrld),
2604 [8 + 4] = MMX_OP2(psrad),
2605 [8 + 6] = MMX_OP2(pslld),
2606 [16 + 2] = MMX_OP2(psrlq),
2607 [16 + 3] = { NULL, gen_op_psrldq_xmm },
2608 [16 + 6] = MMX_OP2(psllq),
2609 [16 + 7] = { NULL, gen_op_pslldq_xmm },
2612 static GenOpFunc1 *sse_op_table3[4 * 3] = {
2613 gen_op_cvtsi2ss,
2614 gen_op_cvtsi2sd,
2615 X86_64_ONLY(gen_op_cvtsq2ss),
2616 X86_64_ONLY(gen_op_cvtsq2sd),
2618 gen_op_cvttss2si,
2619 gen_op_cvttsd2si,
2620 X86_64_ONLY(gen_op_cvttss2sq),
2621 X86_64_ONLY(gen_op_cvttsd2sq),
2623 gen_op_cvtss2si,
2624 gen_op_cvtsd2si,
2625 X86_64_ONLY(gen_op_cvtss2sq),
2626 X86_64_ONLY(gen_op_cvtsd2sq),
2629 static GenOpFunc2 *sse_op_table4[8][4] = {
2630 SSE_FOP(cmpeq),
2631 SSE_FOP(cmplt),
2632 SSE_FOP(cmple),
2633 SSE_FOP(cmpunord),
2634 SSE_FOP(cmpneq),
2635 SSE_FOP(cmpnlt),
2636 SSE_FOP(cmpnle),
2637 SSE_FOP(cmpord),
2640 static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2642 int b1, op1_offset, op2_offset, is_xmm, val, ot;
2643 int modrm, mod, rm, reg, reg_addr, offset_addr;
2644 GenOpFunc2 *sse_op2;
2645 GenOpFunc3 *sse_op3;
2647 b &= 0xff;
2648 if (s->prefix & PREFIX_DATA)
2649 b1 = 1;
2650 else if (s->prefix & PREFIX_REPZ)
2651 b1 = 2;
2652 else if (s->prefix & PREFIX_REPNZ)
2653 b1 = 3;
2654 else
2655 b1 = 0;
2656 sse_op2 = sse_op_table1[b][b1];
2657 if (!sse_op2)
2658 goto illegal_op;
2659 if (b <= 0x5f || b == 0xc6 || b == 0xc2) {
2660 is_xmm = 1;
2661 } else {
2662 if (b1 == 0) {
2663 /* MMX case */
2664 is_xmm = 0;
2665 } else {
2666 is_xmm = 1;
2669 /* simple MMX/SSE operation */
2670 if (s->flags & HF_TS_MASK) {
2671 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2672 return;
2674 if (s->flags & HF_EM_MASK) {
2675 illegal_op:
2676 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2677 return;
2679 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2680 goto illegal_op;
2681 if (b == 0x77) {
2682 /* emms */
2683 gen_op_emms();
2684 return;
2686 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2687 the static cpu state) */
2688 if (!is_xmm) {
2689 gen_op_enter_mmx();
2692 modrm = ldub_code(s->pc++);
2693 reg = ((modrm >> 3) & 7);
2694 if (is_xmm)
2695 reg |= rex_r;
2696 mod = (modrm >> 6) & 3;
2697 if (sse_op2 == SSE_SPECIAL) {
2698 b |= (b1 << 8);
2699 switch(b) {
2700 case 0x0e7: /* movntq */
2701 if (mod == 3)
2702 goto illegal_op;
2703 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2704 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2705 break;
2706 case 0x1e7: /* movntdq */
2707 case 0x02b: /* movntps */
2708 case 0x12b: /* movntps */
2709 case 0x3f0: /* lddqu */
2710 if (mod == 3)
2711 goto illegal_op;
2712 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2713 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2714 break;
2715 case 0x6e: /* movd mm, ea */
2716 #ifdef TARGET_X86_64
2717 if (s->dflag == 2) {
2718 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2719 gen_op_movq_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2720 } else
2721 #endif
2723 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2724 gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2726 break;
2727 case 0x16e: /* movd xmm, ea */
2728 #ifdef TARGET_X86_64
2729 if (s->dflag == 2) {
2730 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2731 gen_op_movq_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2732 } else
2733 #endif
2735 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2736 gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2738 break;
2739 case 0x6f: /* movq mm, ea */
2740 if (mod != 3) {
2741 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2742 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2743 } else {
2744 rm = (modrm & 7);
2745 gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx),
2746 offsetof(CPUX86State,fpregs[rm].mmx));
2748 break;
2749 case 0x010: /* movups */
2750 case 0x110: /* movupd */
2751 case 0x028: /* movaps */
2752 case 0x128: /* movapd */
2753 case 0x16f: /* movdqa xmm, ea */
2754 case 0x26f: /* movdqu xmm, ea */
2755 if (mod != 3) {
2756 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2757 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2758 } else {
2759 rm = (modrm & 7) | REX_B(s);
2760 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2761 offsetof(CPUX86State,xmm_regs[rm]));
2763 break;
2764 case 0x210: /* movss xmm, ea */
2765 if (mod != 3) {
2766 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2767 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2768 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2769 gen_op_movl_T0_0();
2770 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2771 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2772 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2773 } else {
2774 rm = (modrm & 7) | REX_B(s);
2775 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2776 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2778 break;
2779 case 0x310: /* movsd xmm, ea */
2780 if (mod != 3) {
2781 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2782 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2783 gen_op_movl_T0_0();
2784 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2785 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2786 } else {
2787 rm = (modrm & 7) | REX_B(s);
2788 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2789 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2791 break;
2792 case 0x012: /* movlps */
2793 case 0x112: /* movlpd */
2794 if (mod != 3) {
2795 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2796 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2797 } else {
2798 /* movhlps */
2799 rm = (modrm & 7) | REX_B(s);
2800 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2801 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2803 break;
2804 case 0x212: /* movsldup */
2805 if (mod != 3) {
2806 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2807 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2808 } else {
2809 rm = (modrm & 7) | REX_B(s);
2810 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2811 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2812 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2813 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
2815 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2816 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2817 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2818 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2819 break;
2820 case 0x312: /* movddup */
2821 if (mod != 3) {
2822 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2823 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2824 } else {
2825 rm = (modrm & 7) | REX_B(s);
2826 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2827 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2829 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2830 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2831 break;
2832 case 0x016: /* movhps */
2833 case 0x116: /* movhpd */
2834 if (mod != 3) {
2835 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2836 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2837 } else {
2838 /* movlhps */
2839 rm = (modrm & 7) | REX_B(s);
2840 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2841 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2843 break;
2844 case 0x216: /* movshdup */
2845 if (mod != 3) {
2846 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2847 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2848 } else {
2849 rm = (modrm & 7) | REX_B(s);
2850 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2851 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
2852 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2853 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
2855 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2856 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2857 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2858 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2859 break;
2860 case 0x7e: /* movd ea, mm */
2861 #ifdef TARGET_X86_64
2862 if (s->dflag == 2) {
2863 gen_op_movq_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2864 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
2865 } else
2866 #endif
2868 gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2869 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2871 break;
2872 case 0x17e: /* movd ea, xmm */
2873 #ifdef TARGET_X86_64
2874 if (s->dflag == 2) {
2875 gen_op_movq_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2876 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
2877 } else
2878 #endif
2880 gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2881 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2883 break;
2884 case 0x27e: /* movq xmm, ea */
2885 if (mod != 3) {
2886 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2887 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2888 } else {
2889 rm = (modrm & 7) | REX_B(s);
2890 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2891 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2893 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2894 break;
2895 case 0x7f: /* movq ea, mm */
2896 if (mod != 3) {
2897 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2898 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2899 } else {
2900 rm = (modrm & 7);
2901 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2902 offsetof(CPUX86State,fpregs[reg].mmx));
2904 break;
2905 case 0x011: /* movups */
2906 case 0x111: /* movupd */
2907 case 0x029: /* movaps */
2908 case 0x129: /* movapd */
2909 case 0x17f: /* movdqa ea, xmm */
2910 case 0x27f: /* movdqu ea, xmm */
2911 if (mod != 3) {
2912 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2913 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2914 } else {
2915 rm = (modrm & 7) | REX_B(s);
2916 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
2917 offsetof(CPUX86State,xmm_regs[reg]));
2919 break;
2920 case 0x211: /* movss ea, xmm */
2921 if (mod != 3) {
2922 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2923 gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2924 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
2925 } else {
2926 rm = (modrm & 7) | REX_B(s);
2927 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
2928 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2930 break;
2931 case 0x311: /* movsd ea, xmm */
2932 if (mod != 3) {
2933 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2934 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2935 } else {
2936 rm = (modrm & 7) | REX_B(s);
2937 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2938 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2940 break;
2941 case 0x013: /* movlps */
2942 case 0x113: /* movlpd */
2943 if (mod != 3) {
2944 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2945 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2946 } else {
2947 goto illegal_op;
2949 break;
2950 case 0x017: /* movhps */
2951 case 0x117: /* movhpd */
2952 if (mod != 3) {
2953 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2954 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2955 } else {
2956 goto illegal_op;
2958 break;
2959 case 0x71: /* shift mm, im */
2960 case 0x72:
2961 case 0x73:
2962 case 0x171: /* shift xmm, im */
2963 case 0x172:
2964 case 0x173:
2965 val = ldub_code(s->pc++);
2966 if (is_xmm) {
2967 gen_op_movl_T0_im(val);
2968 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2969 gen_op_movl_T0_0();
2970 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1)));
2971 op1_offset = offsetof(CPUX86State,xmm_t0);
2972 } else {
2973 gen_op_movl_T0_im(val);
2974 gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0)));
2975 gen_op_movl_T0_0();
2976 gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1)));
2977 op1_offset = offsetof(CPUX86State,mmx_t0);
2979 sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
2980 if (!sse_op2)
2981 goto illegal_op;
2982 if (is_xmm) {
2983 rm = (modrm & 7) | REX_B(s);
2984 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2985 } else {
2986 rm = (modrm & 7);
2987 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2989 sse_op2(op2_offset, op1_offset);
2990 break;
2991 case 0x050: /* movmskps */
2992 rm = (modrm & 7) | REX_B(s);
2993 gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm]));
2994 gen_op_mov_reg_T0[OT_LONG][reg]();
2995 break;
2996 case 0x150: /* movmskpd */
2997 rm = (modrm & 7) | REX_B(s);
2998 gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm]));
2999 gen_op_mov_reg_T0[OT_LONG][reg]();
3000 break;
3001 case 0x02a: /* cvtpi2ps */
3002 case 0x12a: /* cvtpi2pd */
3003 gen_op_enter_mmx();
3004 if (mod != 3) {
3005 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3006 op2_offset = offsetof(CPUX86State,mmx_t0);
3007 gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3008 } else {
3009 rm = (modrm & 7);
3010 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3012 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3013 switch(b >> 8) {
3014 case 0x0:
3015 gen_op_cvtpi2ps(op1_offset, op2_offset);
3016 break;
3017 default:
3018 case 0x1:
3019 gen_op_cvtpi2pd(op1_offset, op2_offset);
3020 break;
3022 break;
3023 case 0x22a: /* cvtsi2ss */
3024 case 0x32a: /* cvtsi2sd */
3025 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3026 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3027 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3028 sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset);
3029 break;
3030 case 0x02c: /* cvttps2pi */
3031 case 0x12c: /* cvttpd2pi */
3032 case 0x02d: /* cvtps2pi */
3033 case 0x12d: /* cvtpd2pi */
3034 gen_op_enter_mmx();
3035 if (mod != 3) {
3036 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3037 op2_offset = offsetof(CPUX86State,xmm_t0);
3038 gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3039 } else {
3040 rm = (modrm & 7) | REX_B(s);
3041 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3043 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3044 switch(b) {
3045 case 0x02c:
3046 gen_op_cvttps2pi(op1_offset, op2_offset);
3047 break;
3048 case 0x12c:
3049 gen_op_cvttpd2pi(op1_offset, op2_offset);
3050 break;
3051 case 0x02d:
3052 gen_op_cvtps2pi(op1_offset, op2_offset);
3053 break;
3054 case 0x12d:
3055 gen_op_cvtpd2pi(op1_offset, op2_offset);
3056 break;
3058 break;
3059 case 0x22c: /* cvttss2si */
3060 case 0x32c: /* cvttsd2si */
3061 case 0x22d: /* cvtss2si */
3062 case 0x32d: /* cvtsd2si */
3063 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3064 if (mod != 3) {
3065 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3066 if ((b >> 8) & 1) {
3067 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
3068 } else {
3069 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3070 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3072 op2_offset = offsetof(CPUX86State,xmm_t0);
3073 } else {
3074 rm = (modrm & 7) | REX_B(s);
3075 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3077 sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
3078 (b & 1) * 4](op2_offset);
3079 gen_op_mov_reg_T0[ot][reg]();
3080 break;
3081 case 0xc4: /* pinsrw */
3082 case 0x1c4:
3083 s->rip_offset = 1;
3084 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3085 val = ldub_code(s->pc++);
3086 if (b1) {
3087 val &= 7;
3088 gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val);
3089 } else {
3090 val &= 3;
3091 gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val);
3093 break;
3094 case 0xc5: /* pextrw */
3095 case 0x1c5:
3096 if (mod != 3)
3097 goto illegal_op;
3098 val = ldub_code(s->pc++);
3099 if (b1) {
3100 val &= 7;
3101 rm = (modrm & 7) | REX_B(s);
3102 gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val);
3103 } else {
3104 val &= 3;
3105 rm = (modrm & 7);
3106 gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val);
3108 reg = ((modrm >> 3) & 7) | rex_r;
3109 gen_op_mov_reg_T0[OT_LONG][reg]();
3110 break;
3111 case 0x1d6: /* movq ea, xmm */
3112 if (mod != 3) {
3113 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3114 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3115 } else {
3116 rm = (modrm & 7) | REX_B(s);
3117 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3118 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3119 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3121 break;
3122 case 0x2d6: /* movq2dq */
3123 gen_op_enter_mmx();
3124 rm = (modrm & 7);
3125 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3126 offsetof(CPUX86State,fpregs[rm].mmx));
3127 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3128 break;
3129 case 0x3d6: /* movdq2q */
3130 gen_op_enter_mmx();
3131 rm = (modrm & 7) | REX_B(s);
3132 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3133 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3134 break;
3135 case 0xd7: /* pmovmskb */
3136 case 0x1d7:
3137 if (mod != 3)
3138 goto illegal_op;
3139 if (b1) {
3140 rm = (modrm & 7) | REX_B(s);
3141 gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm]));
3142 } else {
3143 rm = (modrm & 7);
3144 gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx));
3146 reg = ((modrm >> 3) & 7) | rex_r;
3147 gen_op_mov_reg_T0[OT_LONG][reg]();
3148 break;
3149 default:
3150 goto illegal_op;
3152 } else {
3153 /* generic MMX or SSE operation */
3154 switch(b) {
3155 case 0xf7:
3156 /* maskmov : we must prepare A0 */
3157 if (mod != 3)
3158 goto illegal_op;
3159 #ifdef TARGET_X86_64
3160 if (s->aflag == 2) {
3161 gen_op_movq_A0_reg[R_EDI]();
3162 } else
3163 #endif
3165 gen_op_movl_A0_reg[R_EDI]();
3166 if (s->aflag == 0)
3167 gen_op_andl_A0_ffff();
3169 gen_add_A0_ds_seg(s);
3170 break;
3171 case 0x70: /* pshufx insn */
3172 case 0xc6: /* pshufx insn */
3173 case 0xc2: /* compare insns */
3174 s->rip_offset = 1;
3175 break;
3176 default:
3177 break;
3179 if (is_xmm) {
3180 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3181 if (mod != 3) {
3182 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3183 op2_offset = offsetof(CPUX86State,xmm_t0);
3184 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
3185 b == 0xc2)) {
3186 /* specific case for SSE single instructions */
3187 if (b1 == 2) {
3188 /* 32 bit access */
3189 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3190 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3191 } else {
3192 /* 64 bit access */
3193 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_D(0)));
3195 } else {
3196 gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3198 } else {
3199 rm = (modrm & 7) | REX_B(s);
3200 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3202 } else {
3203 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3204 if (mod != 3) {
3205 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3206 op2_offset = offsetof(CPUX86State,mmx_t0);
3207 gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3208 } else {
3209 rm = (modrm & 7);
3210 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3213 switch(b) {
3214 case 0x70: /* pshufx insn */
3215 case 0xc6: /* pshufx insn */
3216 val = ldub_code(s->pc++);
3217 sse_op3 = (GenOpFunc3 *)sse_op2;
3218 sse_op3(op1_offset, op2_offset, val);
3219 break;
3220 case 0xc2:
3221 /* compare insns */
3222 val = ldub_code(s->pc++);
3223 if (val >= 8)
3224 goto illegal_op;
3225 sse_op2 = sse_op_table4[val][b1];
3226 sse_op2(op1_offset, op2_offset);
3227 break;
3228 default:
3229 sse_op2(op1_offset, op2_offset);
3230 break;
3232 if (b == 0x2e || b == 0x2f) {
3233 s->cc_op = CC_OP_EFLAGS;
3239 /* convert one instruction. s->is_jmp is set if the translation must
3240 be stopped. Return the next pc value */
3241 static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
3243 int b, prefixes, aflag, dflag;
3244 int shift, ot;
3245 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
3246 target_ulong next_eip, tval;
3247 int rex_w, rex_r;
3249 s->pc = pc_start;
3250 prefixes = 0;
3251 aflag = s->code32;
3252 dflag = s->code32;
3253 s->override = -1;
3254 rex_w = -1;
3255 rex_r = 0;
3256 #ifdef TARGET_X86_64
3257 s->rex_x = 0;
3258 s->rex_b = 0;
3259 x86_64_hregs = 0;
3260 #endif
3261 s->rip_offset = 0; /* for relative ip address */
3262 next_byte:
3263 b = ldub_code(s->pc);
3264 s->pc++;
3265 /* check prefixes */
3266 #ifdef TARGET_X86_64
3267 if (CODE64(s)) {
3268 switch (b) {
3269 case 0xf3:
3270 prefixes |= PREFIX_REPZ;
3271 goto next_byte;
3272 case 0xf2:
3273 prefixes |= PREFIX_REPNZ;
3274 goto next_byte;
3275 case 0xf0:
3276 prefixes |= PREFIX_LOCK;
3277 goto next_byte;
3278 case 0x2e:
3279 s->override = R_CS;
3280 goto next_byte;
3281 case 0x36:
3282 s->override = R_SS;
3283 goto next_byte;
3284 case 0x3e:
3285 s->override = R_DS;
3286 goto next_byte;
3287 case 0x26:
3288 s->override = R_ES;
3289 goto next_byte;
3290 case 0x64:
3291 s->override = R_FS;
3292 goto next_byte;
3293 case 0x65:
3294 s->override = R_GS;
3295 goto next_byte;
3296 case 0x66:
3297 prefixes |= PREFIX_DATA;
3298 goto next_byte;
3299 case 0x67:
3300 prefixes |= PREFIX_ADR;
3301 goto next_byte;
3302 case 0x40 ... 0x4f:
3303 /* REX prefix */
3304 rex_w = (b >> 3) & 1;
3305 rex_r = (b & 0x4) << 1;
3306 s->rex_x = (b & 0x2) << 2;
3307 REX_B(s) = (b & 0x1) << 3;
3308 x86_64_hregs = 1; /* select uniform byte register addressing */
3309 goto next_byte;
3311 if (rex_w == 1) {
3312 /* 0x66 is ignored if rex.w is set */
3313 dflag = 2;
3314 } else {
3315 if (prefixes & PREFIX_DATA)
3316 dflag ^= 1;
3318 if (!(prefixes & PREFIX_ADR))
3319 aflag = 2;
3320 } else
3321 #endif
3323 switch (b) {
3324 case 0xf3:
3325 prefixes |= PREFIX_REPZ;
3326 goto next_byte;
3327 case 0xf2:
3328 prefixes |= PREFIX_REPNZ;
3329 goto next_byte;
3330 case 0xf0:
3331 prefixes |= PREFIX_LOCK;
3332 goto next_byte;
3333 case 0x2e:
3334 s->override = R_CS;
3335 goto next_byte;
3336 case 0x36:
3337 s->override = R_SS;
3338 goto next_byte;
3339 case 0x3e:
3340 s->override = R_DS;
3341 goto next_byte;
3342 case 0x26:
3343 s->override = R_ES;
3344 goto next_byte;
3345 case 0x64:
3346 s->override = R_FS;
3347 goto next_byte;
3348 case 0x65:
3349 s->override = R_GS;
3350 goto next_byte;
3351 case 0x66:
3352 prefixes |= PREFIX_DATA;
3353 goto next_byte;
3354 case 0x67:
3355 prefixes |= PREFIX_ADR;
3356 goto next_byte;
3358 if (prefixes & PREFIX_DATA)
3359 dflag ^= 1;
3360 if (prefixes & PREFIX_ADR)
3361 aflag ^= 1;
3364 s->prefix = prefixes;
3365 s->aflag = aflag;
3366 s->dflag = dflag;
3368 /* lock generation */
3369 if (prefixes & PREFIX_LOCK)
3370 gen_op_lock();
3372 /* now check op code */
3373 reswitch:
3374 switch(b) {
3375 case 0x0f:
3376 /**************************/
3377 /* extended op code */
3378 b = ldub_code(s->pc++) | 0x100;
3379 goto reswitch;
3381 /**************************/
3382 /* arith & logic */
3383 case 0x00 ... 0x05:
3384 case 0x08 ... 0x0d:
3385 case 0x10 ... 0x15:
3386 case 0x18 ... 0x1d:
3387 case 0x20 ... 0x25:
3388 case 0x28 ... 0x2d:
3389 case 0x30 ... 0x35:
3390 case 0x38 ... 0x3d:
3392 int op, f, val;
3393 op = (b >> 3) & 7;
3394 f = (b >> 1) & 3;
3396 if ((b & 1) == 0)
3397 ot = OT_BYTE;
3398 else
3399 ot = dflag + OT_WORD;
3401 switch(f) {
3402 case 0: /* OP Ev, Gv */
3403 modrm = ldub_code(s->pc++);
3404 reg = ((modrm >> 3) & 7) | rex_r;
3405 mod = (modrm >> 6) & 3;
3406 rm = (modrm & 7) | REX_B(s);
3407 if (mod != 3) {
3408 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3409 opreg = OR_TMP0;
3410 } else if (op == OP_XORL && rm == reg) {
3411 xor_zero:
3412 /* xor reg, reg optimisation */
3413 gen_op_movl_T0_0();
3414 s->cc_op = CC_OP_LOGICB + ot;
3415 gen_op_mov_reg_T0[ot][reg]();
3416 gen_op_update1_cc();
3417 break;
3418 } else {
3419 opreg = rm;
3421 gen_op_mov_TN_reg[ot][1][reg]();
3422 gen_op(s, op, ot, opreg);
3423 break;
3424 case 1: /* OP Gv, Ev */
3425 modrm = ldub_code(s->pc++);
3426 mod = (modrm >> 6) & 3;
3427 reg = ((modrm >> 3) & 7) | rex_r;
3428 rm = (modrm & 7) | REX_B(s);
3429 if (mod != 3) {
3430 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3431 gen_op_ld_T1_A0[ot + s->mem_index]();
3432 } else if (op == OP_XORL && rm == reg) {
3433 goto xor_zero;
3434 } else {
3435 gen_op_mov_TN_reg[ot][1][rm]();
3437 gen_op(s, op, ot, reg);
3438 break;
3439 case 2: /* OP A, Iv */
3440 val = insn_get(s, ot);
3441 gen_op_movl_T1_im(val);
3442 gen_op(s, op, ot, OR_EAX);
3443 break;
3446 break;
3448 case 0x80: /* GRP1 */
3449 case 0x81:
3450 case 0x82:
3451 case 0x83:
3453 int val;
3455 if ((b & 1) == 0)
3456 ot = OT_BYTE;
3457 else
3458 ot = dflag + OT_WORD;
3460 modrm = ldub_code(s->pc++);
3461 mod = (modrm >> 6) & 3;
3462 rm = (modrm & 7) | REX_B(s);
3463 op = (modrm >> 3) & 7;
3465 if (mod != 3) {
3466 if (b == 0x83)
3467 s->rip_offset = 1;
3468 else
3469 s->rip_offset = insn_const_size(ot);
3470 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3471 opreg = OR_TMP0;
3472 } else {
3473 opreg = rm;
3476 switch(b) {
3477 default:
3478 case 0x80:
3479 case 0x81:
3480 case 0x82:
3481 val = insn_get(s, ot);
3482 break;
3483 case 0x83:
3484 val = (int8_t)insn_get(s, OT_BYTE);
3485 break;
3487 gen_op_movl_T1_im(val);
3488 gen_op(s, op, ot, opreg);
3490 break;
3492 /**************************/
3493 /* inc, dec, and other misc arith */
3494 case 0x40 ... 0x47: /* inc Gv */
3495 ot = dflag ? OT_LONG : OT_WORD;
3496 gen_inc(s, ot, OR_EAX + (b & 7), 1);
3497 break;
3498 case 0x48 ... 0x4f: /* dec Gv */
3499 ot = dflag ? OT_LONG : OT_WORD;
3500 gen_inc(s, ot, OR_EAX + (b & 7), -1);
3501 break;
3502 case 0xf6: /* GRP3 */
3503 case 0xf7:
3504 if ((b & 1) == 0)
3505 ot = OT_BYTE;
3506 else
3507 ot = dflag + OT_WORD;
3509 modrm = ldub_code(s->pc++);
3510 mod = (modrm >> 6) & 3;
3511 rm = (modrm & 7) | REX_B(s);
3512 op = (modrm >> 3) & 7;
3513 if (mod != 3) {
3514 if (op == 0)
3515 s->rip_offset = insn_const_size(ot);
3516 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3517 gen_op_ld_T0_A0[ot + s->mem_index]();
3518 } else {
3519 gen_op_mov_TN_reg[ot][0][rm]();
3522 switch(op) {
3523 case 0: /* test */
3524 val = insn_get(s, ot);
3525 gen_op_movl_T1_im(val);
3526 gen_op_testl_T0_T1_cc();
3527 s->cc_op = CC_OP_LOGICB + ot;
3528 break;
3529 case 2: /* not */
3530 gen_op_notl_T0();
3531 if (mod != 3) {
3532 gen_op_st_T0_A0[ot + s->mem_index]();
3533 } else {
3534 gen_op_mov_reg_T0[ot][rm]();
3536 break;
3537 case 3: /* neg */
3538 gen_op_negl_T0();
3539 if (mod != 3) {
3540 gen_op_st_T0_A0[ot + s->mem_index]();
3541 } else {
3542 gen_op_mov_reg_T0[ot][rm]();
3544 gen_op_update_neg_cc();
3545 s->cc_op = CC_OP_SUBB + ot;
3546 break;
3547 case 4: /* mul */
3548 switch(ot) {
3549 case OT_BYTE:
3550 gen_op_mulb_AL_T0();
3551 s->cc_op = CC_OP_MULB;
3552 break;
3553 case OT_WORD:
3554 gen_op_mulw_AX_T0();
3555 s->cc_op = CC_OP_MULW;
3556 break;
3557 default:
3558 case OT_LONG:
3559 gen_op_mull_EAX_T0();
3560 s->cc_op = CC_OP_MULL;
3561 break;
3562 #ifdef TARGET_X86_64
3563 case OT_QUAD:
3564 gen_op_mulq_EAX_T0();
3565 s->cc_op = CC_OP_MULQ;
3566 break;
3567 #endif
3569 break;
3570 case 5: /* imul */
3571 switch(ot) {
3572 case OT_BYTE:
3573 gen_op_imulb_AL_T0();
3574 s->cc_op = CC_OP_MULB;
3575 break;
3576 case OT_WORD:
3577 gen_op_imulw_AX_T0();
3578 s->cc_op = CC_OP_MULW;
3579 break;
3580 default:
3581 case OT_LONG:
3582 gen_op_imull_EAX_T0();
3583 s->cc_op = CC_OP_MULL;
3584 break;
3585 #ifdef TARGET_X86_64
3586 case OT_QUAD:
3587 gen_op_imulq_EAX_T0();
3588 s->cc_op = CC_OP_MULQ;
3589 break;
3590 #endif
3592 break;
3593 case 6: /* div */
3594 switch(ot) {
3595 case OT_BYTE:
3596 gen_jmp_im(pc_start - s->cs_base);
3597 gen_op_divb_AL_T0();
3598 break;
3599 case OT_WORD:
3600 gen_jmp_im(pc_start - s->cs_base);
3601 gen_op_divw_AX_T0();
3602 break;
3603 default:
3604 case OT_LONG:
3605 gen_jmp_im(pc_start - s->cs_base);
3606 gen_op_divl_EAX_T0();
3607 break;
3608 #ifdef TARGET_X86_64
3609 case OT_QUAD:
3610 gen_jmp_im(pc_start - s->cs_base);
3611 gen_op_divq_EAX_T0();
3612 break;
3613 #endif
3615 break;
3616 case 7: /* idiv */
3617 switch(ot) {
3618 case OT_BYTE:
3619 gen_jmp_im(pc_start - s->cs_base);
3620 gen_op_idivb_AL_T0();
3621 break;
3622 case OT_WORD:
3623 gen_jmp_im(pc_start - s->cs_base);
3624 gen_op_idivw_AX_T0();
3625 break;
3626 default:
3627 case OT_LONG:
3628 gen_jmp_im(pc_start - s->cs_base);
3629 gen_op_idivl_EAX_T0();
3630 break;
3631 #ifdef TARGET_X86_64
3632 case OT_QUAD:
3633 gen_jmp_im(pc_start - s->cs_base);
3634 gen_op_idivq_EAX_T0();
3635 break;
3636 #endif
3638 break;
3639 default:
3640 goto illegal_op;
3642 break;
3644 case 0xfe: /* GRP4 */
3645 case 0xff: /* GRP5 */
3646 if ((b & 1) == 0)
3647 ot = OT_BYTE;
3648 else
3649 ot = dflag + OT_WORD;
3651 modrm = ldub_code(s->pc++);
3652 mod = (modrm >> 6) & 3;
3653 rm = (modrm & 7) | REX_B(s);
3654 op = (modrm >> 3) & 7;
3655 if (op >= 2 && b == 0xfe) {
3656 goto illegal_op;
3658 if (CODE64(s)) {
3659 if (op == 2 || op == 4) {
3660 /* operand size for jumps is 64 bit */
3661 ot = OT_QUAD;
3662 } else if (op == 3 || op == 5) {
3663 /* for call calls, the operand is 16 or 32 bit, even
3664 in long mode */
3665 ot = dflag ? OT_LONG : OT_WORD;
3666 } else if (op == 6) {
3667 /* default push size is 64 bit */
3668 ot = dflag ? OT_QUAD : OT_WORD;
3671 if (mod != 3) {
3672 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3673 if (op >= 2 && op != 3 && op != 5)
3674 gen_op_ld_T0_A0[ot + s->mem_index]();
3675 } else {
3676 gen_op_mov_TN_reg[ot][0][rm]();
3679 switch(op) {
3680 case 0: /* inc Ev */
3681 if (mod != 3)
3682 opreg = OR_TMP0;
3683 else
3684 opreg = rm;
3685 gen_inc(s, ot, opreg, 1);
3686 break;
3687 case 1: /* dec Ev */
3688 if (mod != 3)
3689 opreg = OR_TMP0;
3690 else
3691 opreg = rm;
3692 gen_inc(s, ot, opreg, -1);
3693 break;
3694 case 2: /* call Ev */
3695 /* XXX: optimize if memory (no 'and' is necessary) */
3696 if (s->dflag == 0)
3697 gen_op_andl_T0_ffff();
3698 next_eip = s->pc - s->cs_base;
3699 gen_movtl_T1_im(next_eip);
3700 gen_push_T1(s);
3701 gen_op_jmp_T0();
3702 gen_eob(s);
3703 break;
3704 case 3: /* lcall Ev */
3705 gen_op_ld_T1_A0[ot + s->mem_index]();
3706 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3707 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3708 do_lcall:
3709 if (s->pe && !s->vm86) {
3710 if (s->cc_op != CC_OP_DYNAMIC)
3711 gen_op_set_cc_op(s->cc_op);
3712 gen_jmp_im(pc_start - s->cs_base);
3713 gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
3714 } else {
3715 gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
3717 gen_eob(s);
3718 break;
3719 case 4: /* jmp Ev */
3720 if (s->dflag == 0)
3721 gen_op_andl_T0_ffff();
3722 gen_op_jmp_T0();
3723 gen_eob(s);
3724 break;
3725 case 5: /* ljmp Ev */
3726 gen_op_ld_T1_A0[ot + s->mem_index]();
3727 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3728 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3729 do_ljmp:
3730 if (s->pe && !s->vm86) {
3731 if (s->cc_op != CC_OP_DYNAMIC)
3732 gen_op_set_cc_op(s->cc_op);
3733 gen_jmp_im(pc_start - s->cs_base);
3734 gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
3735 } else {
3736 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3737 gen_op_movl_T0_T1();
3738 gen_op_jmp_T0();
3740 gen_eob(s);
3741 break;
3742 case 6: /* push Ev */
3743 gen_push_T0(s);
3744 break;
3745 default:
3746 goto illegal_op;
3748 break;
3750 case 0x84: /* test Ev, Gv */
3751 case 0x85:
3752 if ((b & 1) == 0)
3753 ot = OT_BYTE;
3754 else
3755 ot = dflag + OT_WORD;
3757 modrm = ldub_code(s->pc++);
3758 mod = (modrm >> 6) & 3;
3759 rm = (modrm & 7) | REX_B(s);
3760 reg = ((modrm >> 3) & 7) | rex_r;
3762 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3763 gen_op_mov_TN_reg[ot][1][reg]();
3764 gen_op_testl_T0_T1_cc();
3765 s->cc_op = CC_OP_LOGICB + ot;
3766 break;
3768 case 0xa8: /* test eAX, Iv */
3769 case 0xa9:
3770 if ((b & 1) == 0)
3771 ot = OT_BYTE;
3772 else
3773 ot = dflag + OT_WORD;
3774 val = insn_get(s, ot);
3776 gen_op_mov_TN_reg[ot][0][OR_EAX]();
3777 gen_op_movl_T1_im(val);
3778 gen_op_testl_T0_T1_cc();
3779 s->cc_op = CC_OP_LOGICB + ot;
3780 break;
3782 case 0x98: /* CWDE/CBW */
3783 #ifdef TARGET_X86_64
3784 if (dflag == 2) {
3785 gen_op_movslq_RAX_EAX();
3786 } else
3787 #endif
3788 if (dflag == 1)
3789 gen_op_movswl_EAX_AX();
3790 else
3791 gen_op_movsbw_AX_AL();
3792 break;
3793 case 0x99: /* CDQ/CWD */
3794 #ifdef TARGET_X86_64
3795 if (dflag == 2) {
3796 gen_op_movsqo_RDX_RAX();
3797 } else
3798 #endif
3799 if (dflag == 1)
3800 gen_op_movslq_EDX_EAX();
3801 else
3802 gen_op_movswl_DX_AX();
3803 break;
3804 case 0x1af: /* imul Gv, Ev */
3805 case 0x69: /* imul Gv, Ev, I */
3806 case 0x6b:
3807 ot = dflag + OT_WORD;
3808 modrm = ldub_code(s->pc++);
3809 reg = ((modrm >> 3) & 7) | rex_r;
3810 if (b == 0x69)
3811 s->rip_offset = insn_const_size(ot);
3812 else if (b == 0x6b)
3813 s->rip_offset = 1;
3814 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3815 if (b == 0x69) {
3816 val = insn_get(s, ot);
3817 gen_op_movl_T1_im(val);
3818 } else if (b == 0x6b) {
3819 val = (int8_t)insn_get(s, OT_BYTE);
3820 gen_op_movl_T1_im(val);
3821 } else {
3822 gen_op_mov_TN_reg[ot][1][reg]();
3825 #ifdef TARGET_X86_64
3826 if (ot == OT_QUAD) {
3827 gen_op_imulq_T0_T1();
3828 } else
3829 #endif
3830 if (ot == OT_LONG) {
3831 gen_op_imull_T0_T1();
3832 } else {
3833 gen_op_imulw_T0_T1();
3835 gen_op_mov_reg_T0[ot][reg]();
3836 s->cc_op = CC_OP_MULB + ot;
3837 break;
3838 case 0x1c0:
3839 case 0x1c1: /* xadd Ev, Gv */
3840 if ((b & 1) == 0)
3841 ot = OT_BYTE;
3842 else
3843 ot = dflag + OT_WORD;
3844 modrm = ldub_code(s->pc++);
3845 reg = ((modrm >> 3) & 7) | rex_r;
3846 mod = (modrm >> 6) & 3;
3847 if (mod == 3) {
3848 rm = (modrm & 7) | REX_B(s);
3849 gen_op_mov_TN_reg[ot][0][reg]();
3850 gen_op_mov_TN_reg[ot][1][rm]();
3851 gen_op_addl_T0_T1();
3852 gen_op_mov_reg_T1[ot][reg]();
3853 gen_op_mov_reg_T0[ot][rm]();
3854 } else {
3855 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3856 gen_op_mov_TN_reg[ot][0][reg]();
3857 gen_op_ld_T1_A0[ot + s->mem_index]();
3858 gen_op_addl_T0_T1();
3859 gen_op_st_T0_A0[ot + s->mem_index]();
3860 gen_op_mov_reg_T1[ot][reg]();
3862 gen_op_update2_cc();
3863 s->cc_op = CC_OP_ADDB + ot;
3864 break;
3865 case 0x1b0:
3866 case 0x1b1: /* cmpxchg Ev, Gv */
3867 if ((b & 1) == 0)
3868 ot = OT_BYTE;
3869 else
3870 ot = dflag + OT_WORD;
3871 modrm = ldub_code(s->pc++);
3872 reg = ((modrm >> 3) & 7) | rex_r;
3873 mod = (modrm >> 6) & 3;
3874 gen_op_mov_TN_reg[ot][1][reg]();
3875 if (mod == 3) {
3876 rm = (modrm & 7) | REX_B(s);
3877 gen_op_mov_TN_reg[ot][0][rm]();
3878 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
3879 gen_op_mov_reg_T0[ot][rm]();
3880 } else {
3881 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3882 gen_op_ld_T0_A0[ot + s->mem_index]();
3883 gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
3885 s->cc_op = CC_OP_SUBB + ot;
3886 break;
3887 case 0x1c7: /* cmpxchg8b */
3888 modrm = ldub_code(s->pc++);
3889 mod = (modrm >> 6) & 3;
3890 if (mod == 3)
3891 goto illegal_op;
3892 gen_jmp_im(pc_start - s->cs_base);
3893 if (s->cc_op != CC_OP_DYNAMIC)
3894 gen_op_set_cc_op(s->cc_op);
3895 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3896 gen_op_cmpxchg8b();
3897 s->cc_op = CC_OP_EFLAGS;
3898 break;
3900 /**************************/
3901 /* push/pop */
3902 case 0x50 ... 0x57: /* push */
3903 gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
3904 gen_push_T0(s);
3905 break;
3906 case 0x58 ... 0x5f: /* pop */
3907 if (CODE64(s)) {
3908 ot = dflag ? OT_QUAD : OT_WORD;
3909 } else {
3910 ot = dflag + OT_WORD;
3912 gen_pop_T0(s);
3913 /* NOTE: order is important for pop %sp */
3914 gen_pop_update(s);
3915 gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)]();
3916 break;
3917 case 0x60: /* pusha */
3918 if (CODE64(s))
3919 goto illegal_op;
3920 gen_pusha(s);
3921 break;
3922 case 0x61: /* popa */
3923 if (CODE64(s))
3924 goto illegal_op;
3925 gen_popa(s);
3926 break;
3927 case 0x68: /* push Iv */
3928 case 0x6a:
3929 if (CODE64(s)) {
3930 ot = dflag ? OT_QUAD : OT_WORD;
3931 } else {
3932 ot = dflag + OT_WORD;
3934 if (b == 0x68)
3935 val = insn_get(s, ot);
3936 else
3937 val = (int8_t)insn_get(s, OT_BYTE);
3938 gen_op_movl_T0_im(val);
3939 gen_push_T0(s);
3940 break;
3941 case 0x8f: /* pop Ev */
3942 if (CODE64(s)) {
3943 ot = dflag ? OT_QUAD : OT_WORD;
3944 } else {
3945 ot = dflag + OT_WORD;
3947 modrm = ldub_code(s->pc++);
3948 mod = (modrm >> 6) & 3;
3949 gen_pop_T0(s);
3950 if (mod == 3) {
3951 /* NOTE: order is important for pop %sp */
3952 gen_pop_update(s);
3953 rm = (modrm & 7) | REX_B(s);
3954 gen_op_mov_reg_T0[ot][rm]();
3955 } else {
3956 /* NOTE: order is important too for MMU exceptions */
3957 s->popl_esp_hack = 1 << ot;
3958 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3959 s->popl_esp_hack = 0;
3960 gen_pop_update(s);
3962 break;
3963 case 0xc8: /* enter */
3965 int level;
3966 val = lduw_code(s->pc);
3967 s->pc += 2;
3968 level = ldub_code(s->pc++);
3969 gen_enter(s, val, level);
3971 break;
3972 case 0xc9: /* leave */
3973 /* XXX: exception not precise (ESP is updated before potential exception) */
3974 if (CODE64(s)) {
3975 gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
3976 gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
3977 } else if (s->ss32) {
3978 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
3979 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
3980 } else {
3981 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
3982 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
3984 gen_pop_T0(s);
3985 if (CODE64(s)) {
3986 ot = dflag ? OT_QUAD : OT_WORD;
3987 } else {
3988 ot = dflag + OT_WORD;
3990 gen_op_mov_reg_T0[ot][R_EBP]();
3991 gen_pop_update(s);
3992 break;
3993 case 0x06: /* push es */
3994 case 0x0e: /* push cs */
3995 case 0x16: /* push ss */
3996 case 0x1e: /* push ds */
3997 if (CODE64(s))
3998 goto illegal_op;
3999 gen_op_movl_T0_seg(b >> 3);
4000 gen_push_T0(s);
4001 break;
4002 case 0x1a0: /* push fs */
4003 case 0x1a8: /* push gs */
4004 gen_op_movl_T0_seg((b >> 3) & 7);
4005 gen_push_T0(s);
4006 break;
4007 case 0x07: /* pop es */
4008 case 0x17: /* pop ss */
4009 case 0x1f: /* pop ds */
4010 if (CODE64(s))
4011 goto illegal_op;
4012 reg = b >> 3;
4013 gen_pop_T0(s);
4014 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4015 gen_pop_update(s);
4016 if (reg == R_SS) {
4017 /* if reg == SS, inhibit interrupts/trace. */
4018 /* If several instructions disable interrupts, only the
4019 _first_ does it */
4020 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4021 gen_op_set_inhibit_irq();
4022 s->tf = 0;
4024 if (s->is_jmp) {
4025 gen_jmp_im(s->pc - s->cs_base);
4026 gen_eob(s);
4028 break;
4029 case 0x1a1: /* pop fs */
4030 case 0x1a9: /* pop gs */
4031 gen_pop_T0(s);
4032 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
4033 gen_pop_update(s);
4034 if (s->is_jmp) {
4035 gen_jmp_im(s->pc - s->cs_base);
4036 gen_eob(s);
4038 break;
4040 /**************************/
4041 /* mov */
4042 case 0x88:
4043 case 0x89: /* mov Gv, Ev */
4044 if ((b & 1) == 0)
4045 ot = OT_BYTE;
4046 else
4047 ot = dflag + OT_WORD;
4048 modrm = ldub_code(s->pc++);
4049 reg = ((modrm >> 3) & 7) | rex_r;
4051 /* generate a generic store */
4052 gen_ldst_modrm(s, modrm, ot, reg, 1);
4053 break;
4054 case 0xc6:
4055 case 0xc7: /* mov Ev, Iv */
4056 if ((b & 1) == 0)
4057 ot = OT_BYTE;
4058 else
4059 ot = dflag + OT_WORD;
4060 modrm = ldub_code(s->pc++);
4061 mod = (modrm >> 6) & 3;
4062 if (mod != 3) {
4063 s->rip_offset = insn_const_size(ot);
4064 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4066 val = insn_get(s, ot);
4067 gen_op_movl_T0_im(val);
4068 if (mod != 3)
4069 gen_op_st_T0_A0[ot + s->mem_index]();
4070 else
4071 gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)]();
4072 break;
4073 case 0x8a:
4074 case 0x8b: /* mov Ev, Gv */
4075 if ((b & 1) == 0)
4076 ot = OT_BYTE;
4077 else
4078 ot = OT_WORD + dflag;
4079 modrm = ldub_code(s->pc++);
4080 reg = ((modrm >> 3) & 7) | rex_r;
4082 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4083 gen_op_mov_reg_T0[ot][reg]();
4084 break;
4085 case 0x8e: /* mov seg, Gv */
4086 modrm = ldub_code(s->pc++);
4087 reg = (modrm >> 3) & 7;
4088 if (reg >= 6 || reg == R_CS)
4089 goto illegal_op;
4090 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4091 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4092 if (reg == R_SS) {
4093 /* if reg == SS, inhibit interrupts/trace */
4094 /* If several instructions disable interrupts, only the
4095 _first_ does it */
4096 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4097 gen_op_set_inhibit_irq();
4098 s->tf = 0;
4100 if (s->is_jmp) {
4101 gen_jmp_im(s->pc - s->cs_base);
4102 gen_eob(s);
4104 break;
4105 case 0x8c: /* mov Gv, seg */
4106 modrm = ldub_code(s->pc++);
4107 reg = (modrm >> 3) & 7;
4108 mod = (modrm >> 6) & 3;
4109 if (reg >= 6)
4110 goto illegal_op;
4111 gen_op_movl_T0_seg(reg);
4112 if (mod == 3)
4113 ot = OT_WORD + dflag;
4114 else
4115 ot = OT_WORD;
4116 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4117 break;
4119 case 0x1b6: /* movzbS Gv, Eb */
4120 case 0x1b7: /* movzwS Gv, Eb */
4121 case 0x1be: /* movsbS Gv, Eb */
4122 case 0x1bf: /* movswS Gv, Eb */
4124 int d_ot;
4125 /* d_ot is the size of destination */
4126 d_ot = dflag + OT_WORD;
4127 /* ot is the size of source */
4128 ot = (b & 1) + OT_BYTE;
4129 modrm = ldub_code(s->pc++);
4130 reg = ((modrm >> 3) & 7) | rex_r;
4131 mod = (modrm >> 6) & 3;
4132 rm = (modrm & 7) | REX_B(s);
4134 if (mod == 3) {
4135 gen_op_mov_TN_reg[ot][0][rm]();
4136 switch(ot | (b & 8)) {
4137 case OT_BYTE:
4138 gen_op_movzbl_T0_T0();
4139 break;
4140 case OT_BYTE | 8:
4141 gen_op_movsbl_T0_T0();
4142 break;
4143 case OT_WORD:
4144 gen_op_movzwl_T0_T0();
4145 break;
4146 default:
4147 case OT_WORD | 8:
4148 gen_op_movswl_T0_T0();
4149 break;
4151 gen_op_mov_reg_T0[d_ot][reg]();
4152 } else {
4153 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4154 if (b & 8) {
4155 gen_op_lds_T0_A0[ot + s->mem_index]();
4156 } else {
4157 gen_op_ldu_T0_A0[ot + s->mem_index]();
4159 gen_op_mov_reg_T0[d_ot][reg]();
4162 break;
4164 case 0x8d: /* lea */
4165 ot = dflag + OT_WORD;
4166 modrm = ldub_code(s->pc++);
4167 mod = (modrm >> 6) & 3;
4168 if (mod == 3)
4169 goto illegal_op;
4170 reg = ((modrm >> 3) & 7) | rex_r;
4171 /* we must ensure that no segment is added */
4172 s->override = -1;
4173 val = s->addseg;
4174 s->addseg = 0;
4175 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4176 s->addseg = val;
4177 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
4178 break;
4180 case 0xa0: /* mov EAX, Ov */
4181 case 0xa1:
4182 case 0xa2: /* mov Ov, EAX */
4183 case 0xa3:
4185 target_ulong offset_addr;
4187 if ((b & 1) == 0)
4188 ot = OT_BYTE;
4189 else
4190 ot = dflag + OT_WORD;
4191 #ifdef TARGET_X86_64
4192 if (s->aflag == 2) {
4193 offset_addr = ldq_code(s->pc);
4194 s->pc += 8;
4195 if (offset_addr == (int32_t)offset_addr)
4196 gen_op_movq_A0_im(offset_addr);
4197 else
4198 gen_op_movq_A0_im64(offset_addr >> 32, offset_addr);
4199 } else
4200 #endif
4202 if (s->aflag) {
4203 offset_addr = insn_get(s, OT_LONG);
4204 } else {
4205 offset_addr = insn_get(s, OT_WORD);
4207 gen_op_movl_A0_im(offset_addr);
4209 gen_add_A0_ds_seg(s);
4210 if ((b & 2) == 0) {
4211 gen_op_ld_T0_A0[ot + s->mem_index]();
4212 gen_op_mov_reg_T0[ot][R_EAX]();
4213 } else {
4214 gen_op_mov_TN_reg[ot][0][R_EAX]();
4215 gen_op_st_T0_A0[ot + s->mem_index]();
4218 break;
4219 case 0xd7: /* xlat */
4220 #ifdef TARGET_X86_64
4221 if (s->aflag == 2) {
4222 gen_op_movq_A0_reg[R_EBX]();
4223 gen_op_addq_A0_AL();
4224 } else
4225 #endif
4227 gen_op_movl_A0_reg[R_EBX]();
4228 gen_op_addl_A0_AL();
4229 if (s->aflag == 0)
4230 gen_op_andl_A0_ffff();
4232 gen_add_A0_ds_seg(s);
4233 gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
4234 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
4235 break;
4236 case 0xb0 ... 0xb7: /* mov R, Ib */
4237 val = insn_get(s, OT_BYTE);
4238 gen_op_movl_T0_im(val);
4239 gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)]();
4240 break;
4241 case 0xb8 ... 0xbf: /* mov R, Iv */
4242 #ifdef TARGET_X86_64
4243 if (dflag == 2) {
4244 uint64_t tmp;
4245 /* 64 bit case */
4246 tmp = ldq_code(s->pc);
4247 s->pc += 8;
4248 reg = (b & 7) | REX_B(s);
4249 gen_movtl_T0_im(tmp);
4250 gen_op_mov_reg_T0[OT_QUAD][reg]();
4251 } else
4252 #endif
4254 ot = dflag ? OT_LONG : OT_WORD;
4255 val = insn_get(s, ot);
4256 reg = (b & 7) | REX_B(s);
4257 gen_op_movl_T0_im(val);
4258 gen_op_mov_reg_T0[ot][reg]();
4260 break;
4262 case 0x91 ... 0x97: /* xchg R, EAX */
4263 ot = dflag + OT_WORD;
4264 reg = (b & 7) | REX_B(s);
4265 rm = R_EAX;
4266 goto do_xchg_reg;
4267 case 0x86:
4268 case 0x87: /* xchg Ev, Gv */
4269 if ((b & 1) == 0)
4270 ot = OT_BYTE;
4271 else
4272 ot = dflag + OT_WORD;
4273 modrm = ldub_code(s->pc++);
4274 reg = ((modrm >> 3) & 7) | rex_r;
4275 mod = (modrm >> 6) & 3;
4276 if (mod == 3) {
4277 rm = (modrm & 7) | REX_B(s);
4278 do_xchg_reg:
4279 gen_op_mov_TN_reg[ot][0][reg]();
4280 gen_op_mov_TN_reg[ot][1][rm]();
4281 gen_op_mov_reg_T0[ot][rm]();
4282 gen_op_mov_reg_T1[ot][reg]();
4283 } else {
4284 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4285 gen_op_mov_TN_reg[ot][0][reg]();
4286 /* for xchg, lock is implicit */
4287 if (!(prefixes & PREFIX_LOCK))
4288 gen_op_lock();
4289 gen_op_ld_T1_A0[ot + s->mem_index]();
4290 gen_op_st_T0_A0[ot + s->mem_index]();
4291 if (!(prefixes & PREFIX_LOCK))
4292 gen_op_unlock();
4293 gen_op_mov_reg_T1[ot][reg]();
4295 break;
4296 case 0xc4: /* les Gv */
4297 if (CODE64(s))
4298 goto illegal_op;
4299 op = R_ES;
4300 goto do_lxx;
4301 case 0xc5: /* lds Gv */
4302 if (CODE64(s))
4303 goto illegal_op;
4304 op = R_DS;
4305 goto do_lxx;
4306 case 0x1b2: /* lss Gv */
4307 op = R_SS;
4308 goto do_lxx;
4309 case 0x1b4: /* lfs Gv */
4310 op = R_FS;
4311 goto do_lxx;
4312 case 0x1b5: /* lgs Gv */
4313 op = R_GS;
4314 do_lxx:
4315 ot = dflag ? OT_LONG : OT_WORD;
4316 modrm = ldub_code(s->pc++);
4317 reg = ((modrm >> 3) & 7) | rex_r;
4318 mod = (modrm >> 6) & 3;
4319 if (mod == 3)
4320 goto illegal_op;
4321 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4322 gen_op_ld_T1_A0[ot + s->mem_index]();
4323 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4324 /* load the segment first to handle exceptions properly */
4325 gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
4326 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4327 /* then put the data */
4328 gen_op_mov_reg_T1[ot][reg]();
4329 if (s->is_jmp) {
4330 gen_jmp_im(s->pc - s->cs_base);
4331 gen_eob(s);
4333 break;
4335 /************************/
4336 /* shifts */
4337 case 0xc0:
4338 case 0xc1:
4339 /* shift Ev,Ib */
4340 shift = 2;
4341 grp2:
4343 if ((b & 1) == 0)
4344 ot = OT_BYTE;
4345 else
4346 ot = dflag + OT_WORD;
4348 modrm = ldub_code(s->pc++);
4349 mod = (modrm >> 6) & 3;
4350 op = (modrm >> 3) & 7;
4352 if (mod != 3) {
4353 if (shift == 2) {
4354 s->rip_offset = 1;
4356 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4357 opreg = OR_TMP0;
4358 } else {
4359 opreg = (modrm & 7) | REX_B(s);
4362 /* simpler op */
4363 if (shift == 0) {
4364 gen_shift(s, op, ot, opreg, OR_ECX);
4365 } else {
4366 if (shift == 2) {
4367 shift = ldub_code(s->pc++);
4369 gen_shifti(s, op, ot, opreg, shift);
4372 break;
4373 case 0xd0:
4374 case 0xd1:
4375 /* shift Ev,1 */
4376 shift = 1;
4377 goto grp2;
4378 case 0xd2:
4379 case 0xd3:
4380 /* shift Ev,cl */
4381 shift = 0;
4382 goto grp2;
4384 case 0x1a4: /* shld imm */
4385 op = 0;
4386 shift = 1;
4387 goto do_shiftd;
4388 case 0x1a5: /* shld cl */
4389 op = 0;
4390 shift = 0;
4391 goto do_shiftd;
4392 case 0x1ac: /* shrd imm */
4393 op = 1;
4394 shift = 1;
4395 goto do_shiftd;
4396 case 0x1ad: /* shrd cl */
4397 op = 1;
4398 shift = 0;
4399 do_shiftd:
4400 ot = dflag + OT_WORD;
4401 modrm = ldub_code(s->pc++);
4402 mod = (modrm >> 6) & 3;
4403 rm = (modrm & 7) | REX_B(s);
4404 reg = ((modrm >> 3) & 7) | rex_r;
4406 if (mod != 3) {
4407 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4408 gen_op_ld_T0_A0[ot + s->mem_index]();
4409 } else {
4410 gen_op_mov_TN_reg[ot][0][rm]();
4412 gen_op_mov_TN_reg[ot][1][reg]();
4414 if (shift) {
4415 val = ldub_code(s->pc++);
4416 if (ot == OT_QUAD)
4417 val &= 0x3f;
4418 else
4419 val &= 0x1f;
4420 if (val) {
4421 if (mod == 3)
4422 gen_op_shiftd_T0_T1_im_cc[ot][op](val);
4423 else
4424 gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
4425 if (op == 0 && ot != OT_WORD)
4426 s->cc_op = CC_OP_SHLB + ot;
4427 else
4428 s->cc_op = CC_OP_SARB + ot;
4430 } else {
4431 if (s->cc_op != CC_OP_DYNAMIC)
4432 gen_op_set_cc_op(s->cc_op);
4433 if (mod == 3)
4434 gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
4435 else
4436 gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
4437 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
4439 if (mod == 3) {
4440 gen_op_mov_reg_T0[ot][rm]();
4442 break;
4444 /************************/
4445 /* floats */
4446 case 0xd8 ... 0xdf:
4447 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4448 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4449 /* XXX: what to do if illegal op ? */
4450 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4451 break;
4453 modrm = ldub_code(s->pc++);
4454 mod = (modrm >> 6) & 3;
4455 rm = modrm & 7;
4456 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
4457 if (mod != 3) {
4458 /* memory op */
4459 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4460 switch(op) {
4461 case 0x00 ... 0x07: /* fxxxs */
4462 case 0x10 ... 0x17: /* fixxxl */
4463 case 0x20 ... 0x27: /* fxxxl */
4464 case 0x30 ... 0x37: /* fixxx */
4466 int op1;
4467 op1 = op & 7;
4469 switch(op >> 4) {
4470 case 0:
4471 gen_op_flds_FT0_A0();
4472 break;
4473 case 1:
4474 gen_op_fildl_FT0_A0();
4475 break;
4476 case 2:
4477 gen_op_fldl_FT0_A0();
4478 break;
4479 case 3:
4480 default:
4481 gen_op_fild_FT0_A0();
4482 break;
4485 gen_op_fp_arith_ST0_FT0[op1]();
4486 if (op1 == 3) {
4487 /* fcomp needs pop */
4488 gen_op_fpop();
4491 break;
4492 case 0x08: /* flds */
4493 case 0x0a: /* fsts */
4494 case 0x0b: /* fstps */
4495 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
4496 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
4497 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
4498 switch(op & 7) {
4499 case 0:
4500 switch(op >> 4) {
4501 case 0:
4502 gen_op_flds_ST0_A0();
4503 break;
4504 case 1:
4505 gen_op_fildl_ST0_A0();
4506 break;
4507 case 2:
4508 gen_op_fldl_ST0_A0();
4509 break;
4510 case 3:
4511 default:
4512 gen_op_fild_ST0_A0();
4513 break;
4515 break;
4516 case 1:
4517 switch(op >> 4) {
4518 case 1:
4519 gen_op_fisttl_ST0_A0();
4520 break;
4521 case 2:
4522 gen_op_fisttll_ST0_A0();
4523 break;
4524 case 3:
4525 default:
4526 gen_op_fistt_ST0_A0();
4528 gen_op_fpop();
4529 break;
4530 default:
4531 switch(op >> 4) {
4532 case 0:
4533 gen_op_fsts_ST0_A0();
4534 break;
4535 case 1:
4536 gen_op_fistl_ST0_A0();
4537 break;
4538 case 2:
4539 gen_op_fstl_ST0_A0();
4540 break;
4541 case 3:
4542 default:
4543 gen_op_fist_ST0_A0();
4544 break;
4546 if ((op & 7) == 3)
4547 gen_op_fpop();
4548 break;
4550 break;
4551 case 0x0c: /* fldenv mem */
4552 gen_op_fldenv_A0(s->dflag);
4553 break;
4554 case 0x0d: /* fldcw mem */
4555 gen_op_fldcw_A0();
4556 break;
4557 case 0x0e: /* fnstenv mem */
4558 gen_op_fnstenv_A0(s->dflag);
4559 break;
4560 case 0x0f: /* fnstcw mem */
4561 gen_op_fnstcw_A0();
4562 break;
4563 case 0x1d: /* fldt mem */
4564 gen_op_fldt_ST0_A0();
4565 break;
4566 case 0x1f: /* fstpt mem */
4567 gen_op_fstt_ST0_A0();
4568 gen_op_fpop();
4569 break;
4570 case 0x2c: /* frstor mem */
4571 gen_op_frstor_A0(s->dflag);
4572 break;
4573 case 0x2e: /* fnsave mem */
4574 gen_op_fnsave_A0(s->dflag);
4575 break;
4576 case 0x2f: /* fnstsw mem */
4577 gen_op_fnstsw_A0();
4578 break;
4579 case 0x3c: /* fbld */
4580 gen_op_fbld_ST0_A0();
4581 break;
4582 case 0x3e: /* fbstp */
4583 gen_op_fbst_ST0_A0();
4584 gen_op_fpop();
4585 break;
4586 case 0x3d: /* fildll */
4587 gen_op_fildll_ST0_A0();
4588 break;
4589 case 0x3f: /* fistpll */
4590 gen_op_fistll_ST0_A0();
4591 gen_op_fpop();
4592 break;
4593 default:
4594 goto illegal_op;
4596 } else {
4597 /* register float ops */
4598 opreg = rm;
4600 switch(op) {
4601 case 0x08: /* fld sti */
4602 gen_op_fpush();
4603 gen_op_fmov_ST0_STN((opreg + 1) & 7);
4604 break;
4605 case 0x09: /* fxchg sti */
4606 case 0x29: /* fxchg4 sti, undocumented op */
4607 case 0x39: /* fxchg7 sti, undocumented op */
4608 gen_op_fxchg_ST0_STN(opreg);
4609 break;
4610 case 0x0a: /* grp d9/2 */
4611 switch(rm) {
4612 case 0: /* fnop */
4613 /* check exceptions (FreeBSD FPU probe) */
4614 if (s->cc_op != CC_OP_DYNAMIC)
4615 gen_op_set_cc_op(s->cc_op);
4616 gen_jmp_im(pc_start - s->cs_base);
4617 gen_op_fwait();
4618 break;
4619 default:
4620 goto illegal_op;
4622 break;
4623 case 0x0c: /* grp d9/4 */
4624 switch(rm) {
4625 case 0: /* fchs */
4626 gen_op_fchs_ST0();
4627 break;
4628 case 1: /* fabs */
4629 gen_op_fabs_ST0();
4630 break;
4631 case 4: /* ftst */
4632 gen_op_fldz_FT0();
4633 gen_op_fcom_ST0_FT0();
4634 break;
4635 case 5: /* fxam */
4636 gen_op_fxam_ST0();
4637 break;
4638 default:
4639 goto illegal_op;
4641 break;
4642 case 0x0d: /* grp d9/5 */
4644 switch(rm) {
4645 case 0:
4646 gen_op_fpush();
4647 gen_op_fld1_ST0();
4648 break;
4649 case 1:
4650 gen_op_fpush();
4651 gen_op_fldl2t_ST0();
4652 break;
4653 case 2:
4654 gen_op_fpush();
4655 gen_op_fldl2e_ST0();
4656 break;
4657 case 3:
4658 gen_op_fpush();
4659 gen_op_fldpi_ST0();
4660 break;
4661 case 4:
4662 gen_op_fpush();
4663 gen_op_fldlg2_ST0();
4664 break;
4665 case 5:
4666 gen_op_fpush();
4667 gen_op_fldln2_ST0();
4668 break;
4669 case 6:
4670 gen_op_fpush();
4671 gen_op_fldz_ST0();
4672 break;
4673 default:
4674 goto illegal_op;
4677 break;
4678 case 0x0e: /* grp d9/6 */
4679 switch(rm) {
4680 case 0: /* f2xm1 */
4681 gen_op_f2xm1();
4682 break;
4683 case 1: /* fyl2x */
4684 gen_op_fyl2x();
4685 break;
4686 case 2: /* fptan */
4687 gen_op_fptan();
4688 break;
4689 case 3: /* fpatan */
4690 gen_op_fpatan();
4691 break;
4692 case 4: /* fxtract */
4693 gen_op_fxtract();
4694 break;
4695 case 5: /* fprem1 */
4696 gen_op_fprem1();
4697 break;
4698 case 6: /* fdecstp */
4699 gen_op_fdecstp();
4700 break;
4701 default:
4702 case 7: /* fincstp */
4703 gen_op_fincstp();
4704 break;
4706 break;
4707 case 0x0f: /* grp d9/7 */
4708 switch(rm) {
4709 case 0: /* fprem */
4710 gen_op_fprem();
4711 break;
4712 case 1: /* fyl2xp1 */
4713 gen_op_fyl2xp1();
4714 break;
4715 case 2: /* fsqrt */
4716 gen_op_fsqrt();
4717 break;
4718 case 3: /* fsincos */
4719 gen_op_fsincos();
4720 break;
4721 case 5: /* fscale */
4722 gen_op_fscale();
4723 break;
4724 case 4: /* frndint */
4725 gen_op_frndint();
4726 break;
4727 case 6: /* fsin */
4728 gen_op_fsin();
4729 break;
4730 default:
4731 case 7: /* fcos */
4732 gen_op_fcos();
4733 break;
4735 break;
4736 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4737 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4738 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4740 int op1;
4742 op1 = op & 7;
4743 if (op >= 0x20) {
4744 gen_op_fp_arith_STN_ST0[op1](opreg);
4745 if (op >= 0x30)
4746 gen_op_fpop();
4747 } else {
4748 gen_op_fmov_FT0_STN(opreg);
4749 gen_op_fp_arith_ST0_FT0[op1]();
4752 break;
4753 case 0x02: /* fcom */
4754 case 0x22: /* fcom2, undocumented op */
4755 gen_op_fmov_FT0_STN(opreg);
4756 gen_op_fcom_ST0_FT0();
4757 break;
4758 case 0x03: /* fcomp */
4759 case 0x23: /* fcomp3, undocumented op */
4760 case 0x32: /* fcomp5, undocumented op */
4761 gen_op_fmov_FT0_STN(opreg);
4762 gen_op_fcom_ST0_FT0();
4763 gen_op_fpop();
4764 break;
4765 case 0x15: /* da/5 */
4766 switch(rm) {
4767 case 1: /* fucompp */
4768 gen_op_fmov_FT0_STN(1);
4769 gen_op_fucom_ST0_FT0();
4770 gen_op_fpop();
4771 gen_op_fpop();
4772 break;
4773 default:
4774 goto illegal_op;
4776 break;
4777 case 0x1c:
4778 switch(rm) {
4779 case 0: /* feni (287 only, just do nop here) */
4780 break;
4781 case 1: /* fdisi (287 only, just do nop here) */
4782 break;
4783 case 2: /* fclex */
4784 gen_op_fclex();
4785 break;
4786 case 3: /* fninit */
4787 gen_op_fninit();
4788 break;
4789 case 4: /* fsetpm (287 only, just do nop here) */
4790 break;
4791 default:
4792 goto illegal_op;
4794 break;
4795 case 0x1d: /* fucomi */
4796 if (s->cc_op != CC_OP_DYNAMIC)
4797 gen_op_set_cc_op(s->cc_op);
4798 gen_op_fmov_FT0_STN(opreg);
4799 gen_op_fucomi_ST0_FT0();
4800 s->cc_op = CC_OP_EFLAGS;
4801 break;
4802 case 0x1e: /* fcomi */
4803 if (s->cc_op != CC_OP_DYNAMIC)
4804 gen_op_set_cc_op(s->cc_op);
4805 gen_op_fmov_FT0_STN(opreg);
4806 gen_op_fcomi_ST0_FT0();
4807 s->cc_op = CC_OP_EFLAGS;
4808 break;
4809 case 0x28: /* ffree sti */
4810 gen_op_ffree_STN(opreg);
4811 break;
4812 case 0x2a: /* fst sti */
4813 gen_op_fmov_STN_ST0(opreg);
4814 break;
4815 case 0x2b: /* fstp sti */
4816 case 0x0b: /* fstp1 sti, undocumented op */
4817 case 0x3a: /* fstp8 sti, undocumented op */
4818 case 0x3b: /* fstp9 sti, undocumented op */
4819 gen_op_fmov_STN_ST0(opreg);
4820 gen_op_fpop();
4821 break;
4822 case 0x2c: /* fucom st(i) */
4823 gen_op_fmov_FT0_STN(opreg);
4824 gen_op_fucom_ST0_FT0();
4825 break;
4826 case 0x2d: /* fucomp st(i) */
4827 gen_op_fmov_FT0_STN(opreg);
4828 gen_op_fucom_ST0_FT0();
4829 gen_op_fpop();
4830 break;
4831 case 0x33: /* de/3 */
4832 switch(rm) {
4833 case 1: /* fcompp */
4834 gen_op_fmov_FT0_STN(1);
4835 gen_op_fcom_ST0_FT0();
4836 gen_op_fpop();
4837 gen_op_fpop();
4838 break;
4839 default:
4840 goto illegal_op;
4842 break;
4843 case 0x38: /* ffreep sti, undocumented op */
4844 gen_op_ffree_STN(opreg);
4845 gen_op_fpop();
4846 break;
4847 case 0x3c: /* df/4 */
4848 switch(rm) {
4849 case 0:
4850 gen_op_fnstsw_EAX();
4851 break;
4852 default:
4853 goto illegal_op;
4855 break;
4856 case 0x3d: /* fucomip */
4857 if (s->cc_op != CC_OP_DYNAMIC)
4858 gen_op_set_cc_op(s->cc_op);
4859 gen_op_fmov_FT0_STN(opreg);
4860 gen_op_fucomi_ST0_FT0();
4861 gen_op_fpop();
4862 s->cc_op = CC_OP_EFLAGS;
4863 break;
4864 case 0x3e: /* fcomip */
4865 if (s->cc_op != CC_OP_DYNAMIC)
4866 gen_op_set_cc_op(s->cc_op);
4867 gen_op_fmov_FT0_STN(opreg);
4868 gen_op_fcomi_ST0_FT0();
4869 gen_op_fpop();
4870 s->cc_op = CC_OP_EFLAGS;
4871 break;
4872 case 0x10 ... 0x13: /* fcmovxx */
4873 case 0x18 ... 0x1b:
4875 int op1;
4876 const static uint8_t fcmov_cc[8] = {
4877 (JCC_B << 1),
4878 (JCC_Z << 1),
4879 (JCC_BE << 1),
4880 (JCC_P << 1),
4882 op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
4883 gen_setcc(s, op1);
4884 gen_op_fcmov_ST0_STN_T0(opreg);
4886 break;
4887 default:
4888 goto illegal_op;
4891 #ifdef USE_CODE_COPY
4892 s->tb->cflags |= CF_TB_FP_USED;
4893 #endif
4894 break;
4895 /************************/
4896 /* string ops */
4898 case 0xa4: /* movsS */
4899 case 0xa5:
4900 if ((b & 1) == 0)
4901 ot = OT_BYTE;
4902 else
4903 ot = dflag + OT_WORD;
4905 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4906 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4907 } else {
4908 gen_movs(s, ot);
4910 break;
4912 case 0xaa: /* stosS */
4913 case 0xab:
4914 if ((b & 1) == 0)
4915 ot = OT_BYTE;
4916 else
4917 ot = dflag + OT_WORD;
4919 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4920 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4921 } else {
4922 gen_stos(s, ot);
4924 break;
4925 case 0xac: /* lodsS */
4926 case 0xad:
4927 if ((b & 1) == 0)
4928 ot = OT_BYTE;
4929 else
4930 ot = dflag + OT_WORD;
4931 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4932 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4933 } else {
4934 gen_lods(s, ot);
4936 break;
4937 case 0xae: /* scasS */
4938 case 0xaf:
4939 if ((b & 1) == 0)
4940 ot = OT_BYTE;
4941 else
4942 ot = dflag + OT_WORD;
4943 if (prefixes & PREFIX_REPNZ) {
4944 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4945 } else if (prefixes & PREFIX_REPZ) {
4946 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4947 } else {
4948 gen_scas(s, ot);
4949 s->cc_op = CC_OP_SUBB + ot;
4951 break;
4953 case 0xa6: /* cmpsS */
4954 case 0xa7:
4955 if ((b & 1) == 0)
4956 ot = OT_BYTE;
4957 else
4958 ot = dflag + OT_WORD;
4959 if (prefixes & PREFIX_REPNZ) {
4960 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4961 } else if (prefixes & PREFIX_REPZ) {
4962 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4963 } else {
4964 gen_cmps(s, ot);
4965 s->cc_op = CC_OP_SUBB + ot;
4967 break;
4968 case 0x6c: /* insS */
4969 case 0x6d:
4970 if ((b & 1) == 0)
4971 ot = OT_BYTE;
4972 else
4973 ot = dflag ? OT_LONG : OT_WORD;
4974 gen_check_io(s, ot, 1, pc_start - s->cs_base);
4975 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4976 gen_op_andl_T0_ffff();
4977 if (gen_svm_check_io(s, pc_start,
4978 SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
4979 svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
4980 break;
4981 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4982 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4983 } else {
4984 gen_ins(s, ot);
4986 break;
4987 case 0x6e: /* outsS */
4988 case 0x6f:
4989 if ((b & 1) == 0)
4990 ot = OT_BYTE;
4991 else
4992 ot = dflag ? OT_LONG : OT_WORD;
4993 gen_check_io(s, ot, 1, pc_start - s->cs_base);
4994 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4995 gen_op_andl_T0_ffff();
4996 if (gen_svm_check_io(s, pc_start,
4997 (1 << (4+ot)) | svm_is_rep(prefixes) |
4998 4 | (1 << (7+s->aflag))))
4999 break;
5000 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5001 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
5002 } else {
5003 gen_outs(s, ot);
5005 break;
5007 /************************/
5008 /* port I/O */
5010 case 0xe4:
5011 case 0xe5:
5012 if ((b & 1) == 0)
5013 ot = OT_BYTE;
5014 else
5015 ot = dflag ? OT_LONG : OT_WORD;
5016 val = ldub_code(s->pc++);
5017 gen_op_movl_T0_im(val);
5018 gen_check_io(s, ot, 0, pc_start - s->cs_base);
5019 if (gen_svm_check_io(s, pc_start,
5020 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5021 (1 << (4+ot))))
5022 break;
5023 gen_op_in[ot]();
5024 gen_op_mov_reg_T1[ot][R_EAX]();
5025 break;
5026 case 0xe6:
5027 case 0xe7:
5028 if ((b & 1) == 0)
5029 ot = OT_BYTE;
5030 else
5031 ot = dflag ? OT_LONG : OT_WORD;
5032 val = ldub_code(s->pc++);
5033 gen_op_movl_T0_im(val);
5034 gen_check_io(s, ot, 0, pc_start - s->cs_base);
5035 if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) |
5036 (1 << (4+ot))))
5037 break;
5038 gen_op_mov_TN_reg[ot][1][R_EAX]();
5039 gen_op_out[ot]();
5040 break;
5041 case 0xec:
5042 case 0xed:
5043 if ((b & 1) == 0)
5044 ot = OT_BYTE;
5045 else
5046 ot = dflag ? OT_LONG : OT_WORD;
5047 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
5048 gen_op_andl_T0_ffff();
5049 gen_check_io(s, ot, 0, pc_start - s->cs_base);
5050 if (gen_svm_check_io(s, pc_start,
5051 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5052 (1 << (4+ot))))
5053 break;
5054 gen_op_in[ot]();
5055 gen_op_mov_reg_T1[ot][R_EAX]();
5056 break;
5057 case 0xee:
5058 case 0xef:
5059 if ((b & 1) == 0)
5060 ot = OT_BYTE;
5061 else
5062 ot = dflag ? OT_LONG : OT_WORD;
5063 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
5064 gen_op_andl_T0_ffff();
5065 gen_check_io(s, ot, 0, pc_start - s->cs_base);
5066 if (gen_svm_check_io(s, pc_start,
5067 svm_is_rep(prefixes) | (1 << (4+ot))))
5068 break;
5069 gen_op_mov_TN_reg[ot][1][R_EAX]();
5070 gen_op_out[ot]();
5071 break;
5073 /************************/
5074 /* control */
5075 case 0xc2: /* ret im */
5076 val = ldsw_code(s->pc);
5077 s->pc += 2;
5078 gen_pop_T0(s);
5079 if (CODE64(s) && s->dflag)
5080 s->dflag = 2;
5081 gen_stack_update(s, val + (2 << s->dflag));
5082 if (s->dflag == 0)
5083 gen_op_andl_T0_ffff();
5084 gen_op_jmp_T0();
5085 gen_eob(s);
5086 break;
5087 case 0xc3: /* ret */
5088 gen_pop_T0(s);
5089 gen_pop_update(s);
5090 if (s->dflag == 0)
5091 gen_op_andl_T0_ffff();
5092 gen_op_jmp_T0();
5093 gen_eob(s);
5094 break;
5095 case 0xca: /* lret im */
5096 val = ldsw_code(s->pc);
5097 s->pc += 2;
5098 do_lret:
5099 if (s->pe && !s->vm86) {
5100 if (s->cc_op != CC_OP_DYNAMIC)
5101 gen_op_set_cc_op(s->cc_op);
5102 gen_jmp_im(pc_start - s->cs_base);
5103 gen_op_lret_protected(s->dflag, val);
5104 } else {
5105 gen_stack_A0(s);
5106 /* pop offset */
5107 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5108 if (s->dflag == 0)
5109 gen_op_andl_T0_ffff();
5110 /* NOTE: keeping EIP updated is not a problem in case of
5111 exception */
5112 gen_op_jmp_T0();
5113 /* pop selector */
5114 gen_op_addl_A0_im(2 << s->dflag);
5115 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5116 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
5117 /* add stack offset */
5118 gen_stack_update(s, val + (4 << s->dflag));
5120 gen_eob(s);
5121 break;
5122 case 0xcb: /* lret */
5123 val = 0;
5124 goto do_lret;
5125 case 0xcf: /* iret */
5126 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET))
5127 break;
5128 if (!s->pe) {
5129 /* real mode */
5130 gen_op_iret_real(s->dflag);
5131 s->cc_op = CC_OP_EFLAGS;
5132 } else if (s->vm86) {
5133 if (s->iopl != 3) {
5134 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5135 } else {
5136 gen_op_iret_real(s->dflag);
5137 s->cc_op = CC_OP_EFLAGS;
5139 } else {
5140 if (s->cc_op != CC_OP_DYNAMIC)
5141 gen_op_set_cc_op(s->cc_op);
5142 gen_jmp_im(pc_start - s->cs_base);
5143 gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
5144 s->cc_op = CC_OP_EFLAGS;
5146 gen_eob(s);
5147 break;
5148 case 0xe8: /* call im */
5150 if (dflag)
5151 tval = (int32_t)insn_get(s, OT_LONG);
5152 else
5153 tval = (int16_t)insn_get(s, OT_WORD);
5154 next_eip = s->pc - s->cs_base;
5155 tval += next_eip;
5156 if (s->dflag == 0)
5157 tval &= 0xffff;
5158 gen_movtl_T0_im(next_eip);
5159 gen_push_T0(s);
5160 gen_jmp(s, tval);
5162 break;
5163 case 0x9a: /* lcall im */
5165 unsigned int selector, offset;
5167 if (CODE64(s))
5168 goto illegal_op;
5169 ot = dflag ? OT_LONG : OT_WORD;
5170 offset = insn_get(s, ot);
5171 selector = insn_get(s, OT_WORD);
5173 gen_op_movl_T0_im(selector);
5174 gen_op_movl_T1_imu(offset);
5176 goto do_lcall;
5177 case 0xe9: /* jmp im */
5178 if (dflag)
5179 tval = (int32_t)insn_get(s, OT_LONG);
5180 else
5181 tval = (int16_t)insn_get(s, OT_WORD);
5182 tval += s->pc - s->cs_base;
5183 if (s->dflag == 0)
5184 tval &= 0xffff;
5185 gen_jmp(s, tval);
5186 break;
5187 case 0xea: /* ljmp im */
5189 unsigned int selector, offset;
5191 if (CODE64(s))
5192 goto illegal_op;
5193 ot = dflag ? OT_LONG : OT_WORD;
5194 offset = insn_get(s, ot);
5195 selector = insn_get(s, OT_WORD);
5197 gen_op_movl_T0_im(selector);
5198 gen_op_movl_T1_imu(offset);
5200 goto do_ljmp;
5201 case 0xeb: /* jmp Jb */
5202 tval = (int8_t)insn_get(s, OT_BYTE);
5203 tval += s->pc - s->cs_base;
5204 if (s->dflag == 0)
5205 tval &= 0xffff;
5206 gen_jmp(s, tval);
5207 break;
5208 case 0x70 ... 0x7f: /* jcc Jb */
5209 tval = (int8_t)insn_get(s, OT_BYTE);
5210 goto do_jcc;
5211 case 0x180 ... 0x18f: /* jcc Jv */
5212 if (dflag) {
5213 tval = (int32_t)insn_get(s, OT_LONG);
5214 } else {
5215 tval = (int16_t)insn_get(s, OT_WORD);
5217 do_jcc:
5218 next_eip = s->pc - s->cs_base;
5219 tval += next_eip;
5220 if (s->dflag == 0)
5221 tval &= 0xffff;
5222 gen_jcc(s, b, tval, next_eip);
5223 break;
5225 case 0x190 ... 0x19f: /* setcc Gv */
5226 modrm = ldub_code(s->pc++);
5227 gen_setcc(s, b);
5228 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
5229 break;
5230 case 0x140 ... 0x14f: /* cmov Gv, Ev */
5231 ot = dflag + OT_WORD;
5232 modrm = ldub_code(s->pc++);
5233 reg = ((modrm >> 3) & 7) | rex_r;
5234 mod = (modrm >> 6) & 3;
5235 gen_setcc(s, b);
5236 if (mod != 3) {
5237 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5238 gen_op_ld_T1_A0[ot + s->mem_index]();
5239 } else {
5240 rm = (modrm & 7) | REX_B(s);
5241 gen_op_mov_TN_reg[ot][1][rm]();
5243 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
5244 break;
5246 /************************/
5247 /* flags */
5248 case 0x9c: /* pushf */
5249 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF))
5250 break;
5251 if (s->vm86 && s->iopl != 3) {
5252 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5253 } else {
5254 if (s->cc_op != CC_OP_DYNAMIC)
5255 gen_op_set_cc_op(s->cc_op);
5256 gen_op_movl_T0_eflags();
5257 gen_push_T0(s);
5259 break;
5260 case 0x9d: /* popf */
5261 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF))
5262 break;
5263 if (s->vm86 && s->iopl != 3) {
5264 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5265 } else {
5266 gen_pop_T0(s);
5267 if (s->cpl == 0) {
5268 if (s->dflag) {
5269 gen_op_movl_eflags_T0_cpl0();
5270 } else {
5271 gen_op_movw_eflags_T0_cpl0();
5273 } else {
5274 if (s->cpl <= s->iopl) {
5275 if (s->dflag) {
5276 gen_op_movl_eflags_T0_io();
5277 } else {
5278 gen_op_movw_eflags_T0_io();
5280 } else {
5281 if (s->dflag) {
5282 gen_op_movl_eflags_T0();
5283 } else {
5284 gen_op_movw_eflags_T0();
5288 gen_pop_update(s);
5289 s->cc_op = CC_OP_EFLAGS;
5290 /* abort translation because TF flag may change */
5291 gen_jmp_im(s->pc - s->cs_base);
5292 gen_eob(s);
5294 break;
5295 case 0x9e: /* sahf */
5296 if (CODE64(s))
5297 goto illegal_op;
5298 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
5299 if (s->cc_op != CC_OP_DYNAMIC)
5300 gen_op_set_cc_op(s->cc_op);
5301 gen_op_movb_eflags_T0();
5302 s->cc_op = CC_OP_EFLAGS;
5303 break;
5304 case 0x9f: /* lahf */
5305 if (CODE64(s))
5306 goto illegal_op;
5307 if (s->cc_op != CC_OP_DYNAMIC)
5308 gen_op_set_cc_op(s->cc_op);
5309 gen_op_movl_T0_eflags();
5310 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
5311 break;
5312 case 0xf5: /* cmc */
5313 if (s->cc_op != CC_OP_DYNAMIC)
5314 gen_op_set_cc_op(s->cc_op);
5315 gen_op_cmc();
5316 s->cc_op = CC_OP_EFLAGS;
5317 break;
5318 case 0xf8: /* clc */
5319 if (s->cc_op != CC_OP_DYNAMIC)
5320 gen_op_set_cc_op(s->cc_op);
5321 gen_op_clc();
5322 s->cc_op = CC_OP_EFLAGS;
5323 break;
5324 case 0xf9: /* stc */
5325 if (s->cc_op != CC_OP_DYNAMIC)
5326 gen_op_set_cc_op(s->cc_op);
5327 gen_op_stc();
5328 s->cc_op = CC_OP_EFLAGS;
5329 break;
5330 case 0xfc: /* cld */
5331 gen_op_cld();
5332 break;
5333 case 0xfd: /* std */
5334 gen_op_std();
5335 break;
5337 /************************/
5338 /* bit operations */
5339 case 0x1ba: /* bt/bts/btr/btc Gv, im */
5340 ot = dflag + OT_WORD;
5341 modrm = ldub_code(s->pc++);
5342 op = (modrm >> 3) & 7;
5343 mod = (modrm >> 6) & 3;
5344 rm = (modrm & 7) | REX_B(s);
5345 if (mod != 3) {
5346 s->rip_offset = 1;
5347 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5348 gen_op_ld_T0_A0[ot + s->mem_index]();
5349 } else {
5350 gen_op_mov_TN_reg[ot][0][rm]();
5352 /* load shift */
5353 val = ldub_code(s->pc++);
5354 gen_op_movl_T1_im(val);
5355 if (op < 4)
5356 goto illegal_op;
5357 op -= 4;
5358 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5359 s->cc_op = CC_OP_SARB + ot;
5360 if (op != 0) {
5361 if (mod != 3)
5362 gen_op_st_T0_A0[ot + s->mem_index]();
5363 else
5364 gen_op_mov_reg_T0[ot][rm]();
5365 gen_op_update_bt_cc();
5367 break;
5368 case 0x1a3: /* bt Gv, Ev */
5369 op = 0;
5370 goto do_btx;
5371 case 0x1ab: /* bts */
5372 op = 1;
5373 goto do_btx;
5374 case 0x1b3: /* btr */
5375 op = 2;
5376 goto do_btx;
5377 case 0x1bb: /* btc */
5378 op = 3;
5379 do_btx:
5380 ot = dflag + OT_WORD;
5381 modrm = ldub_code(s->pc++);
5382 reg = ((modrm >> 3) & 7) | rex_r;
5383 mod = (modrm >> 6) & 3;
5384 rm = (modrm & 7) | REX_B(s);
5385 gen_op_mov_TN_reg[OT_LONG][1][reg]();
5386 if (mod != 3) {
5387 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5388 /* specific case: we need to add a displacement */
5389 gen_op_add_bit_A0_T1[ot - OT_WORD]();
5390 gen_op_ld_T0_A0[ot + s->mem_index]();
5391 } else {
5392 gen_op_mov_TN_reg[ot][0][rm]();
5394 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5395 s->cc_op = CC_OP_SARB + ot;
5396 if (op != 0) {
5397 if (mod != 3)
5398 gen_op_st_T0_A0[ot + s->mem_index]();
5399 else
5400 gen_op_mov_reg_T0[ot][rm]();
5401 gen_op_update_bt_cc();
5403 break;
5404 case 0x1bc: /* bsf */
5405 case 0x1bd: /* bsr */
5406 ot = dflag + OT_WORD;
5407 modrm = ldub_code(s->pc++);
5408 reg = ((modrm >> 3) & 7) | rex_r;
5409 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5410 /* NOTE: in order to handle the 0 case, we must load the
5411 result. It could be optimized with a generated jump */
5412 gen_op_mov_TN_reg[ot][1][reg]();
5413 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
5414 gen_op_mov_reg_T1[ot][reg]();
5415 s->cc_op = CC_OP_LOGICB + ot;
5416 break;
5417 /************************/
5418 /* bcd */
5419 case 0x27: /* daa */
5420 if (CODE64(s))
5421 goto illegal_op;
5422 if (s->cc_op != CC_OP_DYNAMIC)
5423 gen_op_set_cc_op(s->cc_op);
5424 gen_op_daa();
5425 s->cc_op = CC_OP_EFLAGS;
5426 break;
5427 case 0x2f: /* das */
5428 if (CODE64(s))
5429 goto illegal_op;
5430 if (s->cc_op != CC_OP_DYNAMIC)
5431 gen_op_set_cc_op(s->cc_op);
5432 gen_op_das();
5433 s->cc_op = CC_OP_EFLAGS;
5434 break;
5435 case 0x37: /* aaa */
5436 if (CODE64(s))
5437 goto illegal_op;
5438 if (s->cc_op != CC_OP_DYNAMIC)
5439 gen_op_set_cc_op(s->cc_op);
5440 gen_op_aaa();
5441 s->cc_op = CC_OP_EFLAGS;
5442 break;
5443 case 0x3f: /* aas */
5444 if (CODE64(s))
5445 goto illegal_op;
5446 if (s->cc_op != CC_OP_DYNAMIC)
5447 gen_op_set_cc_op(s->cc_op);
5448 gen_op_aas();
5449 s->cc_op = CC_OP_EFLAGS;
5450 break;
5451 case 0xd4: /* aam */
5452 if (CODE64(s))
5453 goto illegal_op;
5454 val = ldub_code(s->pc++);
5455 if (val == 0) {
5456 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
5457 } else {
5458 gen_op_aam(val);
5459 s->cc_op = CC_OP_LOGICB;
5461 break;
5462 case 0xd5: /* aad */
5463 if (CODE64(s))
5464 goto illegal_op;
5465 val = ldub_code(s->pc++);
5466 gen_op_aad(val);
5467 s->cc_op = CC_OP_LOGICB;
5468 break;
5469 /************************/
5470 /* misc */
5471 case 0x90: /* nop */
5472 /* XXX: xchg + rex handling */
5473 /* XXX: correct lock test for all insn */
5474 if (prefixes & PREFIX_LOCK)
5475 goto illegal_op;
5476 if (prefixes & PREFIX_REPZ) {
5477 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
5479 break;
5480 case 0x9b: /* fwait */
5481 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
5482 (HF_MP_MASK | HF_TS_MASK)) {
5483 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5484 } else {
5485 if (s->cc_op != CC_OP_DYNAMIC)
5486 gen_op_set_cc_op(s->cc_op);
5487 gen_jmp_im(pc_start - s->cs_base);
5488 gen_op_fwait();
5490 break;
5491 case 0xcc: /* int3 */
5492 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5493 break;
5494 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5495 break;
5496 case 0xcd: /* int N */
5497 val = ldub_code(s->pc++);
5498 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5499 break;
5500 if (s->vm86 && s->iopl != 3) {
5501 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5502 } else {
5503 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5505 break;
5506 case 0xce: /* into */
5507 if (CODE64(s))
5508 goto illegal_op;
5509 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5510 break;
5511 if (s->cc_op != CC_OP_DYNAMIC)
5512 gen_op_set_cc_op(s->cc_op);
5513 gen_jmp_im(pc_start - s->cs_base);
5514 gen_op_into(s->pc - pc_start);
5515 break;
5516 case 0xf1: /* icebp (undocumented, exits to external debugger) */
5517 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP))
5518 break;
5519 #if 1
5520 gen_debug(s, pc_start - s->cs_base);
5521 #else
5522 /* start debug */
5523 tb_flush(cpu_single_env);
5524 cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5525 #endif
5526 break;
5527 case 0xfa: /* cli */
5528 if (!s->vm86) {
5529 if (s->cpl <= s->iopl) {
5530 gen_op_cli();
5531 } else {
5532 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5534 } else {
5535 if (s->iopl == 3) {
5536 gen_op_cli();
5537 } else {
5538 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5541 break;
5542 case 0xfb: /* sti */
5543 if (!s->vm86) {
5544 if (s->cpl <= s->iopl) {
5545 gen_sti:
5546 gen_op_sti();
5547 /* interruptions are enabled only the first insn after sti */
5548 /* If several instructions disable interrupts, only the
5549 _first_ does it */
5550 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5551 gen_op_set_inhibit_irq();
5552 /* give a chance to handle pending irqs */
5553 gen_jmp_im(s->pc - s->cs_base);
5554 gen_eob(s);
5555 } else {
5556 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5558 } else {
5559 if (s->iopl == 3) {
5560 goto gen_sti;
5561 } else {
5562 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5565 break;
5566 case 0x62: /* bound */
5567 if (CODE64(s))
5568 goto illegal_op;
5569 ot = dflag ? OT_LONG : OT_WORD;
5570 modrm = ldub_code(s->pc++);
5571 reg = (modrm >> 3) & 7;
5572 mod = (modrm >> 6) & 3;
5573 if (mod == 3)
5574 goto illegal_op;
5575 gen_op_mov_TN_reg[ot][0][reg]();
5576 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5577 gen_jmp_im(pc_start - s->cs_base);
5578 if (ot == OT_WORD)
5579 gen_op_boundw();
5580 else
5581 gen_op_boundl();
5582 break;
5583 case 0x1c8 ... 0x1cf: /* bswap reg */
5584 reg = (b & 7) | REX_B(s);
5585 #ifdef TARGET_X86_64
5586 if (dflag == 2) {
5587 gen_op_mov_TN_reg[OT_QUAD][0][reg]();
5588 gen_op_bswapq_T0();
5589 gen_op_mov_reg_T0[OT_QUAD][reg]();
5590 } else
5591 #endif
5593 gen_op_mov_TN_reg[OT_LONG][0][reg]();
5594 gen_op_bswapl_T0();
5595 gen_op_mov_reg_T0[OT_LONG][reg]();
5597 break;
5598 case 0xd6: /* salc */
5599 if (CODE64(s))
5600 goto illegal_op;
5601 if (s->cc_op != CC_OP_DYNAMIC)
5602 gen_op_set_cc_op(s->cc_op);
5603 gen_op_salc();
5604 break;
5605 case 0xe0: /* loopnz */
5606 case 0xe1: /* loopz */
5607 if (s->cc_op != CC_OP_DYNAMIC)
5608 gen_op_set_cc_op(s->cc_op);
5609 /* FALL THRU */
5610 case 0xe2: /* loop */
5611 case 0xe3: /* jecxz */
5613 int l1, l2;
5615 tval = (int8_t)insn_get(s, OT_BYTE);
5616 next_eip = s->pc - s->cs_base;
5617 tval += next_eip;
5618 if (s->dflag == 0)
5619 tval &= 0xffff;
5621 l1 = gen_new_label();
5622 l2 = gen_new_label();
5623 b &= 3;
5624 if (b == 3) {
5625 gen_op_jz_ecx[s->aflag](l1);
5626 } else {
5627 gen_op_dec_ECX[s->aflag]();
5628 if (b <= 1)
5629 gen_op_mov_T0_cc();
5630 gen_op_loop[s->aflag][b](l1);
5633 gen_jmp_im(next_eip);
5634 gen_op_jmp_label(l2);
5635 gen_set_label(l1);
5636 gen_jmp_im(tval);
5637 gen_set_label(l2);
5638 gen_eob(s);
5640 break;
5641 case 0x130: /* wrmsr */
5642 case 0x132: /* rdmsr */
5643 if (s->cpl != 0) {
5644 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5645 } else {
5646 int retval = 0;
5647 if (b & 2) {
5648 retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0);
5649 gen_op_rdmsr();
5650 } else {
5651 retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1);
5652 gen_op_wrmsr();
5654 if(retval)
5655 gen_eob(s);
5657 break;
5658 case 0x131: /* rdtsc */
5659 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC))
5660 break;
5661 gen_jmp_im(pc_start - s->cs_base);
5662 gen_op_rdtsc();
5663 break;
5664 case 0x134: /* sysenter */
5665 if (CODE64(s))
5666 goto illegal_op;
5667 if (!s->pe) {
5668 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5669 } else {
5670 if (s->cc_op != CC_OP_DYNAMIC) {
5671 gen_op_set_cc_op(s->cc_op);
5672 s->cc_op = CC_OP_DYNAMIC;
5674 gen_jmp_im(pc_start - s->cs_base);
5675 gen_op_sysenter();
5676 gen_eob(s);
5678 break;
5679 case 0x135: /* sysexit */
5680 if (CODE64(s))
5681 goto illegal_op;
5682 if (!s->pe) {
5683 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5684 } else {
5685 if (s->cc_op != CC_OP_DYNAMIC) {
5686 gen_op_set_cc_op(s->cc_op);
5687 s->cc_op = CC_OP_DYNAMIC;
5689 gen_jmp_im(pc_start - s->cs_base);
5690 gen_op_sysexit();
5691 gen_eob(s);
5693 break;
5694 #ifdef TARGET_X86_64
5695 case 0x105: /* syscall */
5696 /* XXX: is it usable in real mode ? */
5697 if (s->cc_op != CC_OP_DYNAMIC) {
5698 gen_op_set_cc_op(s->cc_op);
5699 s->cc_op = CC_OP_DYNAMIC;
5701 gen_jmp_im(pc_start - s->cs_base);
5702 gen_op_syscall(s->pc - pc_start);
5703 gen_eob(s);
5704 break;
5705 case 0x107: /* sysret */
5706 if (!s->pe) {
5707 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5708 } else {
5709 if (s->cc_op != CC_OP_DYNAMIC) {
5710 gen_op_set_cc_op(s->cc_op);
5711 s->cc_op = CC_OP_DYNAMIC;
5713 gen_jmp_im(pc_start - s->cs_base);
5714 gen_op_sysret(s->dflag);
5715 /* condition codes are modified only in long mode */
5716 if (s->lma)
5717 s->cc_op = CC_OP_EFLAGS;
5718 gen_eob(s);
5720 break;
5721 #endif
5722 case 0x1a2: /* cpuid */
5723 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID))
5724 break;
5725 gen_op_cpuid();
5726 break;
5727 case 0xf4: /* hlt */
5728 if (s->cpl != 0) {
5729 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5730 } else {
5731 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT))
5732 break;
5733 if (s->cc_op != CC_OP_DYNAMIC)
5734 gen_op_set_cc_op(s->cc_op);
5735 gen_jmp_im(s->pc - s->cs_base);
5736 gen_op_hlt();
5737 s->is_jmp = 3;
5739 break;
5740 case 0x100:
5741 modrm = ldub_code(s->pc++);
5742 mod = (modrm >> 6) & 3;
5743 op = (modrm >> 3) & 7;
5744 switch(op) {
5745 case 0: /* sldt */
5746 if (!s->pe || s->vm86)
5747 goto illegal_op;
5748 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ))
5749 break;
5750 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5751 ot = OT_WORD;
5752 if (mod == 3)
5753 ot += s->dflag;
5754 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5755 break;
5756 case 2: /* lldt */
5757 if (!s->pe || s->vm86)
5758 goto illegal_op;
5759 if (s->cpl != 0) {
5760 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5761 } else {
5762 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE))
5763 break;
5764 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5765 gen_jmp_im(pc_start - s->cs_base);
5766 gen_op_lldt_T0();
5768 break;
5769 case 1: /* str */
5770 if (!s->pe || s->vm86)
5771 goto illegal_op;
5772 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ))
5773 break;
5774 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5775 ot = OT_WORD;
5776 if (mod == 3)
5777 ot += s->dflag;
5778 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5779 break;
5780 case 3: /* ltr */
5781 if (!s->pe || s->vm86)
5782 goto illegal_op;
5783 if (s->cpl != 0) {
5784 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5785 } else {
5786 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE))
5787 break;
5788 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5789 gen_jmp_im(pc_start - s->cs_base);
5790 gen_op_ltr_T0();
5792 break;
5793 case 4: /* verr */
5794 case 5: /* verw */
5795 if (!s->pe || s->vm86)
5796 goto illegal_op;
5797 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5798 if (s->cc_op != CC_OP_DYNAMIC)
5799 gen_op_set_cc_op(s->cc_op);
5800 if (op == 4)
5801 gen_op_verr();
5802 else
5803 gen_op_verw();
5804 s->cc_op = CC_OP_EFLAGS;
5805 break;
5806 default:
5807 goto illegal_op;
5809 break;
5810 case 0x101:
5811 modrm = ldub_code(s->pc++);
5812 mod = (modrm >> 6) & 3;
5813 op = (modrm >> 3) & 7;
5814 rm = modrm & 7;
5815 switch(op) {
5816 case 0: /* sgdt */
5817 if (mod == 3)
5818 goto illegal_op;
5819 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ))
5820 break;
5821 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5822 gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
5823 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5824 gen_add_A0_im(s, 2);
5825 gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base));
5826 if (!s->dflag)
5827 gen_op_andl_T0_im(0xffffff);
5828 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5829 break;
5830 case 1:
5831 if (mod == 3) {
5832 switch (rm) {
5833 case 0: /* monitor */
5834 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5835 s->cpl != 0)
5836 goto illegal_op;
5837 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR))
5838 break;
5839 gen_jmp_im(pc_start - s->cs_base);
5840 #ifdef TARGET_X86_64
5841 if (s->aflag == 2) {
5842 gen_op_movq_A0_reg[R_EBX]();
5843 gen_op_addq_A0_AL();
5844 } else
5845 #endif
5847 gen_op_movl_A0_reg[R_EBX]();
5848 gen_op_addl_A0_AL();
5849 if (s->aflag == 0)
5850 gen_op_andl_A0_ffff();
5852 gen_add_A0_ds_seg(s);
5853 gen_op_monitor();
5854 break;
5855 case 1: /* mwait */
5856 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5857 s->cpl != 0)
5858 goto illegal_op;
5859 if (s->cc_op != CC_OP_DYNAMIC) {
5860 gen_op_set_cc_op(s->cc_op);
5861 s->cc_op = CC_OP_DYNAMIC;
5863 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT))
5864 break;
5865 gen_jmp_im(s->pc - s->cs_base);
5866 gen_op_mwait();
5867 gen_eob(s);
5868 break;
5869 default:
5870 goto illegal_op;
5872 } else { /* sidt */
5873 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ))
5874 break;
5875 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5876 gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
5877 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5878 gen_add_A0_im(s, 2);
5879 gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base));
5880 if (!s->dflag)
5881 gen_op_andl_T0_im(0xffffff);
5882 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5884 break;
5885 case 2: /* lgdt */
5886 case 3: /* lidt */
5887 if (mod == 3) {
5888 switch(rm) {
5889 case 0: /* VMRUN */
5890 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN))
5891 break;
5892 if (s->cc_op != CC_OP_DYNAMIC)
5893 gen_op_set_cc_op(s->cc_op);
5894 gen_jmp_im(s->pc - s->cs_base);
5895 gen_op_vmrun();
5896 s->cc_op = CC_OP_EFLAGS;
5897 gen_eob(s);
5898 break;
5899 case 1: /* VMMCALL */
5900 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL))
5901 break;
5902 /* FIXME: cause #UD if hflags & SVM */
5903 gen_op_vmmcall();
5904 break;
5905 case 2: /* VMLOAD */
5906 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD))
5907 break;
5908 gen_op_vmload();
5909 break;
5910 case 3: /* VMSAVE */
5911 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE))
5912 break;
5913 gen_op_vmsave();
5914 break;
5915 case 4: /* STGI */
5916 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI))
5917 break;
5918 gen_op_stgi();
5919 break;
5920 case 5: /* CLGI */
5921 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI))
5922 break;
5923 gen_op_clgi();
5924 break;
5925 case 6: /* SKINIT */
5926 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT))
5927 break;
5928 gen_op_skinit();
5929 break;
5930 case 7: /* INVLPGA */
5931 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA))
5932 break;
5933 gen_op_invlpga();
5934 break;
5935 default:
5936 goto illegal_op;
5938 } else if (s->cpl != 0) {
5939 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5940 } else {
5941 if (gen_svm_check_intercept(s, pc_start,
5942 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE))
5943 break;
5944 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5945 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
5946 gen_add_A0_im(s, 2);
5947 gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5948 if (!s->dflag)
5949 gen_op_andl_T0_im(0xffffff);
5950 if (op == 2) {
5951 gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
5952 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5953 } else {
5954 gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
5955 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5958 break;
5959 case 4: /* smsw */
5960 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0))
5961 break;
5962 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5963 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5964 break;
5965 case 6: /* lmsw */
5966 if (s->cpl != 0) {
5967 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5968 } else {
5969 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0))
5970 break;
5971 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5972 gen_op_lmsw_T0();
5973 gen_jmp_im(s->pc - s->cs_base);
5974 gen_eob(s);
5976 break;
5977 case 7: /* invlpg */
5978 if (s->cpl != 0) {
5979 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5980 } else {
5981 if (mod == 3) {
5982 #ifdef TARGET_X86_64
5983 if (CODE64(s) && rm == 0) {
5984 /* swapgs */
5985 gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5986 gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5987 gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5988 gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
5989 } else
5990 #endif
5992 goto illegal_op;
5994 } else {
5995 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG))
5996 break;
5997 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5998 gen_op_invlpg_A0();
5999 gen_jmp_im(s->pc - s->cs_base);
6000 gen_eob(s);
6003 break;
6004 default:
6005 goto illegal_op;
6007 break;
6008 case 0x108: /* invd */
6009 case 0x109: /* wbinvd */
6010 if (s->cpl != 0) {
6011 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6012 } else {
6013 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVD))
6014 break;
6015 /* nothing to do */
6017 break;
6018 case 0x63: /* arpl or movslS (x86_64) */
6019 #ifdef TARGET_X86_64
6020 if (CODE64(s)) {
6021 int d_ot;
6022 /* d_ot is the size of destination */
6023 d_ot = dflag + OT_WORD;
6025 modrm = ldub_code(s->pc++);
6026 reg = ((modrm >> 3) & 7) | rex_r;
6027 mod = (modrm >> 6) & 3;
6028 rm = (modrm & 7) | REX_B(s);
6030 if (mod == 3) {
6031 gen_op_mov_TN_reg[OT_LONG][0][rm]();
6032 /* sign extend */
6033 if (d_ot == OT_QUAD)
6034 gen_op_movslq_T0_T0();
6035 gen_op_mov_reg_T0[d_ot][reg]();
6036 } else {
6037 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6038 if (d_ot == OT_QUAD) {
6039 gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
6040 } else {
6041 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6043 gen_op_mov_reg_T0[d_ot][reg]();
6045 } else
6046 #endif
6048 if (!s->pe || s->vm86)
6049 goto illegal_op;
6050 ot = dflag ? OT_LONG : OT_WORD;
6051 modrm = ldub_code(s->pc++);
6052 reg = (modrm >> 3) & 7;
6053 mod = (modrm >> 6) & 3;
6054 rm = modrm & 7;
6055 if (mod != 3) {
6056 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6057 gen_op_ld_T0_A0[ot + s->mem_index]();
6058 } else {
6059 gen_op_mov_TN_reg[ot][0][rm]();
6061 if (s->cc_op != CC_OP_DYNAMIC)
6062 gen_op_set_cc_op(s->cc_op);
6063 gen_op_arpl();
6064 s->cc_op = CC_OP_EFLAGS;
6065 if (mod != 3) {
6066 gen_op_st_T0_A0[ot + s->mem_index]();
6067 } else {
6068 gen_op_mov_reg_T0[ot][rm]();
6070 gen_op_arpl_update();
6072 break;
6073 case 0x102: /* lar */
6074 case 0x103: /* lsl */
6075 if (!s->pe || s->vm86)
6076 goto illegal_op;
6077 ot = dflag ? OT_LONG : OT_WORD;
6078 modrm = ldub_code(s->pc++);
6079 reg = ((modrm >> 3) & 7) | rex_r;
6080 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
6081 gen_op_mov_TN_reg[ot][1][reg]();
6082 if (s->cc_op != CC_OP_DYNAMIC)
6083 gen_op_set_cc_op(s->cc_op);
6084 if (b == 0x102)
6085 gen_op_lar();
6086 else
6087 gen_op_lsl();
6088 s->cc_op = CC_OP_EFLAGS;
6089 gen_op_mov_reg_T1[ot][reg]();
6090 break;
6091 case 0x118:
6092 modrm = ldub_code(s->pc++);
6093 mod = (modrm >> 6) & 3;
6094 op = (modrm >> 3) & 7;
6095 switch(op) {
6096 case 0: /* prefetchnta */
6097 case 1: /* prefetchnt0 */
6098 case 2: /* prefetchnt0 */
6099 case 3: /* prefetchnt0 */
6100 if (mod == 3)
6101 goto illegal_op;
6102 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6103 /* nothing more to do */
6104 break;
6105 default: /* nop (multi byte) */
6106 gen_nop_modrm(s, modrm);
6107 break;
6109 break;
6110 case 0x119 ... 0x11f: /* nop (multi byte) */
6111 modrm = ldub_code(s->pc++);
6112 gen_nop_modrm(s, modrm);
6113 break;
6114 case 0x120: /* mov reg, crN */
6115 case 0x122: /* mov crN, reg */
6116 if (s->cpl != 0) {
6117 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6118 } else {
6119 modrm = ldub_code(s->pc++);
6120 if ((modrm & 0xc0) != 0xc0)
6121 goto illegal_op;
6122 rm = (modrm & 7) | REX_B(s);
6123 reg = ((modrm >> 3) & 7) | rex_r;
6124 if (CODE64(s))
6125 ot = OT_QUAD;
6126 else
6127 ot = OT_LONG;
6128 switch(reg) {
6129 case 0:
6130 case 2:
6131 case 3:
6132 case 4:
6133 case 8:
6134 if (b & 2) {
6135 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg);
6136 gen_op_mov_TN_reg[ot][0][rm]();
6137 gen_op_movl_crN_T0(reg);
6138 gen_jmp_im(s->pc - s->cs_base);
6139 gen_eob(s);
6140 } else {
6141 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg);
6142 #if !defined(CONFIG_USER_ONLY)
6143 if (reg == 8)
6144 gen_op_movtl_T0_cr8();
6145 else
6146 #endif
6147 gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
6148 gen_op_mov_reg_T0[ot][rm]();
6150 break;
6151 default:
6152 goto illegal_op;
6155 break;
6156 case 0x121: /* mov reg, drN */
6157 case 0x123: /* mov drN, reg */
6158 if (s->cpl != 0) {
6159 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6160 } else {
6161 modrm = ldub_code(s->pc++);
6162 if ((modrm & 0xc0) != 0xc0)
6163 goto illegal_op;
6164 rm = (modrm & 7) | REX_B(s);
6165 reg = ((modrm >> 3) & 7) | rex_r;
6166 if (CODE64(s))
6167 ot = OT_QUAD;
6168 else
6169 ot = OT_LONG;
6170 /* XXX: do it dynamically with CR4.DE bit */
6171 if (reg == 4 || reg == 5 || reg >= 8)
6172 goto illegal_op;
6173 if (b & 2) {
6174 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
6175 gen_op_mov_TN_reg[ot][0][rm]();
6176 gen_op_movl_drN_T0(reg);
6177 gen_jmp_im(s->pc - s->cs_base);
6178 gen_eob(s);
6179 } else {
6180 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
6181 gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
6182 gen_op_mov_reg_T0[ot][rm]();
6185 break;
6186 case 0x106: /* clts */
6187 if (s->cpl != 0) {
6188 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6189 } else {
6190 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
6191 gen_op_clts();
6192 /* abort block because static cpu state changed */
6193 gen_jmp_im(s->pc - s->cs_base);
6194 gen_eob(s);
6196 break;
6197 /* MMX/SSE/SSE2/PNI support */
6198 case 0x1c3: /* MOVNTI reg, mem */
6199 if (!(s->cpuid_features & CPUID_SSE2))
6200 goto illegal_op;
6201 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
6202 modrm = ldub_code(s->pc++);
6203 mod = (modrm >> 6) & 3;
6204 if (mod == 3)
6205 goto illegal_op;
6206 reg = ((modrm >> 3) & 7) | rex_r;
6207 /* generate a generic store */
6208 gen_ldst_modrm(s, modrm, ot, reg, 1);
6209 break;
6210 case 0x1ae:
6211 modrm = ldub_code(s->pc++);
6212 mod = (modrm >> 6) & 3;
6213 op = (modrm >> 3) & 7;
6214 switch(op) {
6215 case 0: /* fxsave */
6216 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
6217 (s->flags & HF_EM_MASK))
6218 goto illegal_op;
6219 if (s->flags & HF_TS_MASK) {
6220 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6221 break;
6223 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6224 gen_op_fxsave_A0((s->dflag == 2));
6225 break;
6226 case 1: /* fxrstor */
6227 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
6228 (s->flags & HF_EM_MASK))
6229 goto illegal_op;
6230 if (s->flags & HF_TS_MASK) {
6231 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6232 break;
6234 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6235 gen_op_fxrstor_A0((s->dflag == 2));
6236 break;
6237 case 2: /* ldmxcsr */
6238 case 3: /* stmxcsr */
6239 if (s->flags & HF_TS_MASK) {
6240 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6241 break;
6243 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
6244 mod == 3)
6245 goto illegal_op;
6246 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6247 if (op == 2) {
6248 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6249 gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
6250 } else {
6251 gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
6252 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
6254 break;
6255 case 5: /* lfence */
6256 case 6: /* mfence */
6257 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
6258 goto illegal_op;
6259 break;
6260 case 7: /* sfence / clflush */
6261 if ((modrm & 0xc7) == 0xc0) {
6262 /* sfence */
6263 if (!(s->cpuid_features & CPUID_SSE))
6264 goto illegal_op;
6265 } else {
6266 /* clflush */
6267 if (!(s->cpuid_features & CPUID_CLFLUSH))
6268 goto illegal_op;
6269 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6271 break;
6272 default:
6273 goto illegal_op;
6275 break;
6276 case 0x10d: /* prefetch */
6277 modrm = ldub_code(s->pc++);
6278 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6279 /* ignore for now */
6280 break;
6281 case 0x1aa: /* rsm */
6282 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM))
6283 break;
6284 if (!(s->flags & HF_SMM_MASK))
6285 goto illegal_op;
6286 if (s->cc_op != CC_OP_DYNAMIC) {
6287 gen_op_set_cc_op(s->cc_op);
6288 s->cc_op = CC_OP_DYNAMIC;
6290 gen_jmp_im(s->pc - s->cs_base);
6291 gen_op_rsm();
6292 gen_eob(s);
6293 break;
6294 case 0x110 ... 0x117:
6295 case 0x128 ... 0x12f:
6296 case 0x150 ... 0x177:
6297 case 0x17c ... 0x17f:
6298 case 0x1c2:
6299 case 0x1c4 ... 0x1c6:
6300 case 0x1d0 ... 0x1fe:
6301 gen_sse(s, b, pc_start, rex_r);
6302 break;
6303 default:
6304 goto illegal_op;
6306 /* lock generation */
6307 if (s->prefix & PREFIX_LOCK)
6308 gen_op_unlock();
6309 return s->pc;
6310 illegal_op:
6311 if (s->prefix & PREFIX_LOCK)
6312 gen_op_unlock();
6313 /* XXX: ensure that no lock was generated */
6314 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
6315 return s->pc;
6318 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
6319 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
6321 /* flags read by an operation */
6322 static uint16_t opc_read_flags[NB_OPS] = {
6323 [INDEX_op_aas] = CC_A,
6324 [INDEX_op_aaa] = CC_A,
6325 [INDEX_op_das] = CC_A | CC_C,
6326 [INDEX_op_daa] = CC_A | CC_C,
6328 /* subtle: due to the incl/decl implementation, C is used */
6329 [INDEX_op_update_inc_cc] = CC_C,
6331 [INDEX_op_into] = CC_O,
6333 [INDEX_op_jb_subb] = CC_C,
6334 [INDEX_op_jb_subw] = CC_C,
6335 [INDEX_op_jb_subl] = CC_C,
6337 [INDEX_op_jz_subb] = CC_Z,
6338 [INDEX_op_jz_subw] = CC_Z,
6339 [INDEX_op_jz_subl] = CC_Z,
6341 [INDEX_op_jbe_subb] = CC_Z | CC_C,
6342 [INDEX_op_jbe_subw] = CC_Z | CC_C,
6343 [INDEX_op_jbe_subl] = CC_Z | CC_C,
6345 [INDEX_op_js_subb] = CC_S,
6346 [INDEX_op_js_subw] = CC_S,
6347 [INDEX_op_js_subl] = CC_S,
6349 [INDEX_op_jl_subb] = CC_O | CC_S,
6350 [INDEX_op_jl_subw] = CC_O | CC_S,
6351 [INDEX_op_jl_subl] = CC_O | CC_S,
6353 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
6354 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
6355 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
6357 [INDEX_op_loopnzw] = CC_Z,
6358 [INDEX_op_loopnzl] = CC_Z,
6359 [INDEX_op_loopzw] = CC_Z,
6360 [INDEX_op_loopzl] = CC_Z,
6362 [INDEX_op_seto_T0_cc] = CC_O,
6363 [INDEX_op_setb_T0_cc] = CC_C,
6364 [INDEX_op_setz_T0_cc] = CC_Z,
6365 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
6366 [INDEX_op_sets_T0_cc] = CC_S,
6367 [INDEX_op_setp_T0_cc] = CC_P,
6368 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
6369 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
6371 [INDEX_op_setb_T0_subb] = CC_C,
6372 [INDEX_op_setb_T0_subw] = CC_C,
6373 [INDEX_op_setb_T0_subl] = CC_C,
6375 [INDEX_op_setz_T0_subb] = CC_Z,
6376 [INDEX_op_setz_T0_subw] = CC_Z,
6377 [INDEX_op_setz_T0_subl] = CC_Z,
6379 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
6380 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
6381 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
6383 [INDEX_op_sets_T0_subb] = CC_S,
6384 [INDEX_op_sets_T0_subw] = CC_S,
6385 [INDEX_op_sets_T0_subl] = CC_S,
6387 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
6388 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
6389 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
6391 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
6392 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
6393 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
6395 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
6396 [INDEX_op_cmc] = CC_C,
6397 [INDEX_op_salc] = CC_C,
6399 /* needed for correct flag optimisation before string ops */
6400 [INDEX_op_jnz_ecxw] = CC_OSZAPC,
6401 [INDEX_op_jnz_ecxl] = CC_OSZAPC,
6402 [INDEX_op_jz_ecxw] = CC_OSZAPC,
6403 [INDEX_op_jz_ecxl] = CC_OSZAPC,
6405 #ifdef TARGET_X86_64
6406 [INDEX_op_jb_subq] = CC_C,
6407 [INDEX_op_jz_subq] = CC_Z,
6408 [INDEX_op_jbe_subq] = CC_Z | CC_C,
6409 [INDEX_op_js_subq] = CC_S,
6410 [INDEX_op_jl_subq] = CC_O | CC_S,
6411 [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
6413 [INDEX_op_loopnzq] = CC_Z,
6414 [INDEX_op_loopzq] = CC_Z,
6416 [INDEX_op_setb_T0_subq] = CC_C,
6417 [INDEX_op_setz_T0_subq] = CC_Z,
6418 [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
6419 [INDEX_op_sets_T0_subq] = CC_S,
6420 [INDEX_op_setl_T0_subq] = CC_O | CC_S,
6421 [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
6423 [INDEX_op_jnz_ecxq] = CC_OSZAPC,
6424 [INDEX_op_jz_ecxq] = CC_OSZAPC,
6425 #endif
6427 #define DEF_READF(SUFFIX)\
6428 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6429 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6430 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6431 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6432 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6433 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6434 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6435 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6437 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6438 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6439 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
6440 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6441 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6442 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6443 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6444 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
6446 DEF_READF( )
6447 DEF_READF(_raw)
6448 #ifndef CONFIG_USER_ONLY
6449 DEF_READF(_kernel)
6450 DEF_READF(_user)
6451 #endif
6454 /* flags written by an operation */
6455 static uint16_t opc_write_flags[NB_OPS] = {
6456 [INDEX_op_update2_cc] = CC_OSZAPC,
6457 [INDEX_op_update1_cc] = CC_OSZAPC,
6458 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6459 [INDEX_op_update_neg_cc] = CC_OSZAPC,
6460 /* subtle: due to the incl/decl implementation, C is used */
6461 [INDEX_op_update_inc_cc] = CC_OSZAPC,
6462 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6464 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
6465 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
6466 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
6467 X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6468 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6469 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
6470 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
6471 X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
6472 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6473 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
6474 X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6476 /* sse */
6477 [INDEX_op_ucomiss] = CC_OSZAPC,
6478 [INDEX_op_ucomisd] = CC_OSZAPC,
6479 [INDEX_op_comiss] = CC_OSZAPC,
6480 [INDEX_op_comisd] = CC_OSZAPC,
6482 /* bcd */
6483 [INDEX_op_aam] = CC_OSZAPC,
6484 [INDEX_op_aad] = CC_OSZAPC,
6485 [INDEX_op_aas] = CC_OSZAPC,
6486 [INDEX_op_aaa] = CC_OSZAPC,
6487 [INDEX_op_das] = CC_OSZAPC,
6488 [INDEX_op_daa] = CC_OSZAPC,
6490 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6491 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6492 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
6493 [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6494 [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6495 [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6496 [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
6497 [INDEX_op_clc] = CC_C,
6498 [INDEX_op_stc] = CC_C,
6499 [INDEX_op_cmc] = CC_C,
6501 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6502 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
6503 X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
6504 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6505 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
6506 X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
6507 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6508 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
6509 X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
6510 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6511 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
6512 X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
6514 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6515 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
6516 X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
6517 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6518 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
6519 X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
6521 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6522 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6523 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
6524 X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
6526 [INDEX_op_cmpxchg8b] = CC_Z,
6527 [INDEX_op_lar] = CC_Z,
6528 [INDEX_op_lsl] = CC_Z,
6529 [INDEX_op_verr] = CC_Z,
6530 [INDEX_op_verw] = CC_Z,
6531 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6532 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6534 #define DEF_WRITEF(SUFFIX)\
6535 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6536 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6537 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6538 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6539 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6540 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6541 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6542 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6544 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6545 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6546 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6547 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6548 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6549 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6550 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6551 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6553 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6554 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6555 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6556 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6557 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6558 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6559 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6560 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6562 [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6563 [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6564 [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6565 X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6567 [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6568 [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6569 [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6570 X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6572 [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6573 [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6574 [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6575 X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6577 [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6578 [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6579 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6580 [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6581 [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6582 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6584 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6585 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6586 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6587 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6588 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6589 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6591 [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6592 [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6593 [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6594 X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
6597 DEF_WRITEF( )
6598 DEF_WRITEF(_raw)
6599 #ifndef CONFIG_USER_ONLY
6600 DEF_WRITEF(_kernel)
6601 DEF_WRITEF(_user)
6602 #endif
6605 /* simpler form of an operation if no flags need to be generated */
6606 static uint16_t opc_simpler[NB_OPS] = {
6607 [INDEX_op_update2_cc] = INDEX_op_nop,
6608 [INDEX_op_update1_cc] = INDEX_op_nop,
6609 [INDEX_op_update_neg_cc] = INDEX_op_nop,
6610 #if 0
6611 /* broken: CC_OP logic must be rewritten */
6612 [INDEX_op_update_inc_cc] = INDEX_op_nop,
6613 #endif
6615 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6616 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6617 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
6618 X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
6620 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6621 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6622 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
6623 X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
6625 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6626 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6627 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
6628 X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
6630 #define DEF_SIMPLER(SUFFIX)\
6631 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6632 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6633 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
6634 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
6636 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6637 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
6638 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6639 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
6641 DEF_SIMPLER( )
6642 DEF_SIMPLER(_raw)
6643 #ifndef CONFIG_USER_ONLY
6644 DEF_SIMPLER(_kernel)
6645 DEF_SIMPLER(_user)
6646 #endif
6649 void optimize_flags_init(void)
6651 int i;
6652 /* put default values in arrays */
6653 for(i = 0; i < NB_OPS; i++) {
6654 if (opc_simpler[i] == 0)
6655 opc_simpler[i] = i;
6659 /* CPU flags computation optimization: we move backward thru the
6660 generated code to see which flags are needed. The operation is
6661 modified if suitable */
6662 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6664 uint16_t *opc_ptr;
6665 int live_flags, write_flags, op;
6667 opc_ptr = opc_buf + opc_buf_len;
6668 /* live_flags contains the flags needed by the next instructions
6669 in the code. At the end of the block, we consider that all the
6670 flags are live. */
6671 live_flags = CC_OSZAPC;
6672 while (opc_ptr > opc_buf) {
6673 op = *--opc_ptr;
6674 /* if none of the flags written by the instruction is used,
6675 then we can try to find a simpler instruction */
6676 write_flags = opc_write_flags[op];
6677 if ((live_flags & write_flags) == 0) {
6678 *opc_ptr = opc_simpler[op];
6680 /* compute the live flags before the instruction */
6681 live_flags &= ~write_flags;
6682 live_flags |= opc_read_flags[op];
6686 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6687 basic block 'tb'. If search_pc is TRUE, also generate PC
6688 information for each intermediate instruction. */
6689 static inline int gen_intermediate_code_internal(CPUState *env,
6690 TranslationBlock *tb,
6691 int search_pc)
6693 DisasContext dc1, *dc = &dc1;
6694 target_ulong pc_ptr;
6695 uint16_t *gen_opc_end;
6696 int j, lj, cflags;
6697 uint64_t flags;
6698 target_ulong pc_start;
6699 target_ulong cs_base;
6701 /* generate intermediate code */
6702 pc_start = tb->pc;
6703 cs_base = tb->cs_base;
6704 flags = tb->flags;
6705 cflags = tb->cflags;
6707 dc->pe = (flags >> HF_PE_SHIFT) & 1;
6708 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6709 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6710 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6711 dc->f_st = 0;
6712 dc->vm86 = (flags >> VM_SHIFT) & 1;
6713 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6714 dc->iopl = (flags >> IOPL_SHIFT) & 3;
6715 dc->tf = (flags >> TF_SHIFT) & 1;
6716 dc->singlestep_enabled = env->singlestep_enabled;
6717 dc->cc_op = CC_OP_DYNAMIC;
6718 dc->cs_base = cs_base;
6719 dc->tb = tb;
6720 dc->popl_esp_hack = 0;
6721 /* select memory access functions */
6722 dc->mem_index = 0;
6723 if (flags & HF_SOFTMMU_MASK) {
6724 if (dc->cpl == 3)
6725 dc->mem_index = 2 * 4;
6726 else
6727 dc->mem_index = 1 * 4;
6729 dc->cpuid_features = env->cpuid_features;
6730 dc->cpuid_ext_features = env->cpuid_ext_features;
6731 #ifdef TARGET_X86_64
6732 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6733 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6734 #endif
6735 dc->flags = flags;
6736 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6737 (flags & HF_INHIBIT_IRQ_MASK)
6738 #ifndef CONFIG_SOFTMMU
6739 || (flags & HF_SOFTMMU_MASK)
6740 #endif
6742 #if 0
6743 /* check addseg logic */
6744 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
6745 printf("ERROR addseg\n");
6746 #endif
6748 gen_opc_ptr = gen_opc_buf;
6749 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6750 gen_opparam_ptr = gen_opparam_buf;
6751 nb_gen_labels = 0;
6753 dc->is_jmp = DISAS_NEXT;
6754 pc_ptr = pc_start;
6755 lj = -1;
6757 for(;;) {
6758 if (env->nb_breakpoints > 0) {
6759 for(j = 0; j < env->nb_breakpoints; j++) {
6760 if (env->breakpoints[j] == pc_ptr) {
6761 gen_debug(dc, pc_ptr - dc->cs_base);
6762 break;
6766 if (search_pc) {
6767 j = gen_opc_ptr - gen_opc_buf;
6768 if (lj < j) {
6769 lj++;
6770 while (lj < j)
6771 gen_opc_instr_start[lj++] = 0;
6773 gen_opc_pc[lj] = pc_ptr;
6774 gen_opc_cc_op[lj] = dc->cc_op;
6775 gen_opc_instr_start[lj] = 1;
6777 pc_ptr = disas_insn(dc, pc_ptr);
6778 /* stop translation if indicated */
6779 if (dc->is_jmp)
6780 break;
6781 /* if single step mode, we generate only one instruction and
6782 generate an exception */
6783 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6784 the flag and abort the translation to give the irqs a
6785 change to be happen */
6786 if (dc->tf || dc->singlestep_enabled ||
6787 (flags & HF_INHIBIT_IRQ_MASK) ||
6788 (cflags & CF_SINGLE_INSN)) {
6789 gen_jmp_im(pc_ptr - dc->cs_base);
6790 gen_eob(dc);
6791 break;
6793 /* if too long translation, stop generation too */
6794 if (gen_opc_ptr >= gen_opc_end ||
6795 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
6796 gen_jmp_im(pc_ptr - dc->cs_base);
6797 gen_eob(dc);
6798 break;
6801 *gen_opc_ptr = INDEX_op_end;
6802 /* we don't forget to fill the last values */
6803 if (search_pc) {
6804 j = gen_opc_ptr - gen_opc_buf;
6805 lj++;
6806 while (lj <= j)
6807 gen_opc_instr_start[lj++] = 0;
6810 #ifdef DEBUG_DISAS
6811 if (loglevel & CPU_LOG_TB_CPU) {
6812 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
6814 if (loglevel & CPU_LOG_TB_IN_ASM) {
6815 int disas_flags;
6816 fprintf(logfile, "----------------\n");
6817 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6818 #ifdef TARGET_X86_64
6819 if (dc->code64)
6820 disas_flags = 2;
6821 else
6822 #endif
6823 disas_flags = !dc->code32;
6824 target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
6825 fprintf(logfile, "\n");
6826 if (loglevel & CPU_LOG_TB_OP) {
6827 fprintf(logfile, "OP:\n");
6828 dump_ops(gen_opc_buf, gen_opparam_buf);
6829 fprintf(logfile, "\n");
6832 #endif
6834 /* optimize flag computations */
6835 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6837 #ifdef DEBUG_DISAS
6838 if (loglevel & CPU_LOG_TB_OP_OPT) {
6839 fprintf(logfile, "AFTER FLAGS OPT:\n");
6840 dump_ops(gen_opc_buf, gen_opparam_buf);
6841 fprintf(logfile, "\n");
6843 #endif
6844 if (!search_pc)
6845 tb->size = pc_ptr - pc_start;
6846 return 0;
6849 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6851 return gen_intermediate_code_internal(env, tb, 0);
6854 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6856 return gen_intermediate_code_internal(env, tb, 1);