Fix more typos in softloat code (Eduardo Felipe)
[qemu/qemu_0_9_1_stable.git] / target-i386 / translate.c
blob02dc6cf61cd4c94d432e88727d21cefb5bcbfab3
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 break;
4892 /************************/
4893 /* string ops */
4895 case 0xa4: /* movsS */
4896 case 0xa5:
4897 if ((b & 1) == 0)
4898 ot = OT_BYTE;
4899 else
4900 ot = dflag + OT_WORD;
4902 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4903 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4904 } else {
4905 gen_movs(s, ot);
4907 break;
4909 case 0xaa: /* stosS */
4910 case 0xab:
4911 if ((b & 1) == 0)
4912 ot = OT_BYTE;
4913 else
4914 ot = dflag + OT_WORD;
4916 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4917 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4918 } else {
4919 gen_stos(s, ot);
4921 break;
4922 case 0xac: /* lodsS */
4923 case 0xad:
4924 if ((b & 1) == 0)
4925 ot = OT_BYTE;
4926 else
4927 ot = dflag + OT_WORD;
4928 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4929 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4930 } else {
4931 gen_lods(s, ot);
4933 break;
4934 case 0xae: /* scasS */
4935 case 0xaf:
4936 if ((b & 1) == 0)
4937 ot = OT_BYTE;
4938 else
4939 ot = dflag + OT_WORD;
4940 if (prefixes & PREFIX_REPNZ) {
4941 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4942 } else if (prefixes & PREFIX_REPZ) {
4943 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4944 } else {
4945 gen_scas(s, ot);
4946 s->cc_op = CC_OP_SUBB + ot;
4948 break;
4950 case 0xa6: /* cmpsS */
4951 case 0xa7:
4952 if ((b & 1) == 0)
4953 ot = OT_BYTE;
4954 else
4955 ot = dflag + OT_WORD;
4956 if (prefixes & PREFIX_REPNZ) {
4957 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4958 } else if (prefixes & PREFIX_REPZ) {
4959 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4960 } else {
4961 gen_cmps(s, ot);
4962 s->cc_op = CC_OP_SUBB + ot;
4964 break;
4965 case 0x6c: /* insS */
4966 case 0x6d:
4967 if ((b & 1) == 0)
4968 ot = OT_BYTE;
4969 else
4970 ot = dflag ? OT_LONG : OT_WORD;
4971 gen_check_io(s, ot, 1, pc_start - s->cs_base);
4972 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4973 gen_op_andl_T0_ffff();
4974 if (gen_svm_check_io(s, pc_start,
4975 SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
4976 svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
4977 break;
4978 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4979 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4980 } else {
4981 gen_ins(s, ot);
4983 break;
4984 case 0x6e: /* outsS */
4985 case 0x6f:
4986 if ((b & 1) == 0)
4987 ot = OT_BYTE;
4988 else
4989 ot = dflag ? OT_LONG : OT_WORD;
4990 gen_check_io(s, ot, 1, pc_start - s->cs_base);
4991 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4992 gen_op_andl_T0_ffff();
4993 if (gen_svm_check_io(s, pc_start,
4994 (1 << (4+ot)) | svm_is_rep(prefixes) |
4995 4 | (1 << (7+s->aflag))))
4996 break;
4997 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4998 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4999 } else {
5000 gen_outs(s, ot);
5002 break;
5004 /************************/
5005 /* port I/O */
5007 case 0xe4:
5008 case 0xe5:
5009 if ((b & 1) == 0)
5010 ot = OT_BYTE;
5011 else
5012 ot = dflag ? OT_LONG : OT_WORD;
5013 val = ldub_code(s->pc++);
5014 gen_op_movl_T0_im(val);
5015 gen_check_io(s, ot, 0, pc_start - s->cs_base);
5016 if (gen_svm_check_io(s, pc_start,
5017 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5018 (1 << (4+ot))))
5019 break;
5020 gen_op_in[ot]();
5021 gen_op_mov_reg_T1[ot][R_EAX]();
5022 break;
5023 case 0xe6:
5024 case 0xe7:
5025 if ((b & 1) == 0)
5026 ot = OT_BYTE;
5027 else
5028 ot = dflag ? OT_LONG : OT_WORD;
5029 val = ldub_code(s->pc++);
5030 gen_op_movl_T0_im(val);
5031 gen_check_io(s, ot, 0, pc_start - s->cs_base);
5032 if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) |
5033 (1 << (4+ot))))
5034 break;
5035 gen_op_mov_TN_reg[ot][1][R_EAX]();
5036 gen_op_out[ot]();
5037 break;
5038 case 0xec:
5039 case 0xed:
5040 if ((b & 1) == 0)
5041 ot = OT_BYTE;
5042 else
5043 ot = dflag ? OT_LONG : OT_WORD;
5044 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
5045 gen_op_andl_T0_ffff();
5046 gen_check_io(s, ot, 0, pc_start - s->cs_base);
5047 if (gen_svm_check_io(s, pc_start,
5048 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
5049 (1 << (4+ot))))
5050 break;
5051 gen_op_in[ot]();
5052 gen_op_mov_reg_T1[ot][R_EAX]();
5053 break;
5054 case 0xee:
5055 case 0xef:
5056 if ((b & 1) == 0)
5057 ot = OT_BYTE;
5058 else
5059 ot = dflag ? OT_LONG : OT_WORD;
5060 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
5061 gen_op_andl_T0_ffff();
5062 gen_check_io(s, ot, 0, pc_start - s->cs_base);
5063 if (gen_svm_check_io(s, pc_start,
5064 svm_is_rep(prefixes) | (1 << (4+ot))))
5065 break;
5066 gen_op_mov_TN_reg[ot][1][R_EAX]();
5067 gen_op_out[ot]();
5068 break;
5070 /************************/
5071 /* control */
5072 case 0xc2: /* ret im */
5073 val = ldsw_code(s->pc);
5074 s->pc += 2;
5075 gen_pop_T0(s);
5076 if (CODE64(s) && s->dflag)
5077 s->dflag = 2;
5078 gen_stack_update(s, val + (2 << s->dflag));
5079 if (s->dflag == 0)
5080 gen_op_andl_T0_ffff();
5081 gen_op_jmp_T0();
5082 gen_eob(s);
5083 break;
5084 case 0xc3: /* ret */
5085 gen_pop_T0(s);
5086 gen_pop_update(s);
5087 if (s->dflag == 0)
5088 gen_op_andl_T0_ffff();
5089 gen_op_jmp_T0();
5090 gen_eob(s);
5091 break;
5092 case 0xca: /* lret im */
5093 val = ldsw_code(s->pc);
5094 s->pc += 2;
5095 do_lret:
5096 if (s->pe && !s->vm86) {
5097 if (s->cc_op != CC_OP_DYNAMIC)
5098 gen_op_set_cc_op(s->cc_op);
5099 gen_jmp_im(pc_start - s->cs_base);
5100 gen_op_lret_protected(s->dflag, val);
5101 } else {
5102 gen_stack_A0(s);
5103 /* pop offset */
5104 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5105 if (s->dflag == 0)
5106 gen_op_andl_T0_ffff();
5107 /* NOTE: keeping EIP updated is not a problem in case of
5108 exception */
5109 gen_op_jmp_T0();
5110 /* pop selector */
5111 gen_op_addl_A0_im(2 << s->dflag);
5112 gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5113 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
5114 /* add stack offset */
5115 gen_stack_update(s, val + (4 << s->dflag));
5117 gen_eob(s);
5118 break;
5119 case 0xcb: /* lret */
5120 val = 0;
5121 goto do_lret;
5122 case 0xcf: /* iret */
5123 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET))
5124 break;
5125 if (!s->pe) {
5126 /* real mode */
5127 gen_op_iret_real(s->dflag);
5128 s->cc_op = CC_OP_EFLAGS;
5129 } else if (s->vm86) {
5130 if (s->iopl != 3) {
5131 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5132 } else {
5133 gen_op_iret_real(s->dflag);
5134 s->cc_op = CC_OP_EFLAGS;
5136 } else {
5137 if (s->cc_op != CC_OP_DYNAMIC)
5138 gen_op_set_cc_op(s->cc_op);
5139 gen_jmp_im(pc_start - s->cs_base);
5140 gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
5141 s->cc_op = CC_OP_EFLAGS;
5143 gen_eob(s);
5144 break;
5145 case 0xe8: /* call im */
5147 if (dflag)
5148 tval = (int32_t)insn_get(s, OT_LONG);
5149 else
5150 tval = (int16_t)insn_get(s, OT_WORD);
5151 next_eip = s->pc - s->cs_base;
5152 tval += next_eip;
5153 if (s->dflag == 0)
5154 tval &= 0xffff;
5155 gen_movtl_T0_im(next_eip);
5156 gen_push_T0(s);
5157 gen_jmp(s, tval);
5159 break;
5160 case 0x9a: /* lcall im */
5162 unsigned int selector, offset;
5164 if (CODE64(s))
5165 goto illegal_op;
5166 ot = dflag ? OT_LONG : OT_WORD;
5167 offset = insn_get(s, ot);
5168 selector = insn_get(s, OT_WORD);
5170 gen_op_movl_T0_im(selector);
5171 gen_op_movl_T1_imu(offset);
5173 goto do_lcall;
5174 case 0xe9: /* jmp im */
5175 if (dflag)
5176 tval = (int32_t)insn_get(s, OT_LONG);
5177 else
5178 tval = (int16_t)insn_get(s, OT_WORD);
5179 tval += s->pc - s->cs_base;
5180 if (s->dflag == 0)
5181 tval &= 0xffff;
5182 gen_jmp(s, tval);
5183 break;
5184 case 0xea: /* ljmp im */
5186 unsigned int selector, offset;
5188 if (CODE64(s))
5189 goto illegal_op;
5190 ot = dflag ? OT_LONG : OT_WORD;
5191 offset = insn_get(s, ot);
5192 selector = insn_get(s, OT_WORD);
5194 gen_op_movl_T0_im(selector);
5195 gen_op_movl_T1_imu(offset);
5197 goto do_ljmp;
5198 case 0xeb: /* jmp Jb */
5199 tval = (int8_t)insn_get(s, OT_BYTE);
5200 tval += s->pc - s->cs_base;
5201 if (s->dflag == 0)
5202 tval &= 0xffff;
5203 gen_jmp(s, tval);
5204 break;
5205 case 0x70 ... 0x7f: /* jcc Jb */
5206 tval = (int8_t)insn_get(s, OT_BYTE);
5207 goto do_jcc;
5208 case 0x180 ... 0x18f: /* jcc Jv */
5209 if (dflag) {
5210 tval = (int32_t)insn_get(s, OT_LONG);
5211 } else {
5212 tval = (int16_t)insn_get(s, OT_WORD);
5214 do_jcc:
5215 next_eip = s->pc - s->cs_base;
5216 tval += next_eip;
5217 if (s->dflag == 0)
5218 tval &= 0xffff;
5219 gen_jcc(s, b, tval, next_eip);
5220 break;
5222 case 0x190 ... 0x19f: /* setcc Gv */
5223 modrm = ldub_code(s->pc++);
5224 gen_setcc(s, b);
5225 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
5226 break;
5227 case 0x140 ... 0x14f: /* cmov Gv, Ev */
5228 ot = dflag + OT_WORD;
5229 modrm = ldub_code(s->pc++);
5230 reg = ((modrm >> 3) & 7) | rex_r;
5231 mod = (modrm >> 6) & 3;
5232 gen_setcc(s, b);
5233 if (mod != 3) {
5234 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5235 gen_op_ld_T1_A0[ot + s->mem_index]();
5236 } else {
5237 rm = (modrm & 7) | REX_B(s);
5238 gen_op_mov_TN_reg[ot][1][rm]();
5240 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
5241 break;
5243 /************************/
5244 /* flags */
5245 case 0x9c: /* pushf */
5246 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF))
5247 break;
5248 if (s->vm86 && s->iopl != 3) {
5249 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5250 } else {
5251 if (s->cc_op != CC_OP_DYNAMIC)
5252 gen_op_set_cc_op(s->cc_op);
5253 gen_op_movl_T0_eflags();
5254 gen_push_T0(s);
5256 break;
5257 case 0x9d: /* popf */
5258 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF))
5259 break;
5260 if (s->vm86 && s->iopl != 3) {
5261 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5262 } else {
5263 gen_pop_T0(s);
5264 if (s->cpl == 0) {
5265 if (s->dflag) {
5266 gen_op_movl_eflags_T0_cpl0();
5267 } else {
5268 gen_op_movw_eflags_T0_cpl0();
5270 } else {
5271 if (s->cpl <= s->iopl) {
5272 if (s->dflag) {
5273 gen_op_movl_eflags_T0_io();
5274 } else {
5275 gen_op_movw_eflags_T0_io();
5277 } else {
5278 if (s->dflag) {
5279 gen_op_movl_eflags_T0();
5280 } else {
5281 gen_op_movw_eflags_T0();
5285 gen_pop_update(s);
5286 s->cc_op = CC_OP_EFLAGS;
5287 /* abort translation because TF flag may change */
5288 gen_jmp_im(s->pc - s->cs_base);
5289 gen_eob(s);
5291 break;
5292 case 0x9e: /* sahf */
5293 if (CODE64(s))
5294 goto illegal_op;
5295 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
5296 if (s->cc_op != CC_OP_DYNAMIC)
5297 gen_op_set_cc_op(s->cc_op);
5298 gen_op_movb_eflags_T0();
5299 s->cc_op = CC_OP_EFLAGS;
5300 break;
5301 case 0x9f: /* lahf */
5302 if (CODE64(s))
5303 goto illegal_op;
5304 if (s->cc_op != CC_OP_DYNAMIC)
5305 gen_op_set_cc_op(s->cc_op);
5306 gen_op_movl_T0_eflags();
5307 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
5308 break;
5309 case 0xf5: /* cmc */
5310 if (s->cc_op != CC_OP_DYNAMIC)
5311 gen_op_set_cc_op(s->cc_op);
5312 gen_op_cmc();
5313 s->cc_op = CC_OP_EFLAGS;
5314 break;
5315 case 0xf8: /* clc */
5316 if (s->cc_op != CC_OP_DYNAMIC)
5317 gen_op_set_cc_op(s->cc_op);
5318 gen_op_clc();
5319 s->cc_op = CC_OP_EFLAGS;
5320 break;
5321 case 0xf9: /* stc */
5322 if (s->cc_op != CC_OP_DYNAMIC)
5323 gen_op_set_cc_op(s->cc_op);
5324 gen_op_stc();
5325 s->cc_op = CC_OP_EFLAGS;
5326 break;
5327 case 0xfc: /* cld */
5328 gen_op_cld();
5329 break;
5330 case 0xfd: /* std */
5331 gen_op_std();
5332 break;
5334 /************************/
5335 /* bit operations */
5336 case 0x1ba: /* bt/bts/btr/btc Gv, im */
5337 ot = dflag + OT_WORD;
5338 modrm = ldub_code(s->pc++);
5339 op = (modrm >> 3) & 7;
5340 mod = (modrm >> 6) & 3;
5341 rm = (modrm & 7) | REX_B(s);
5342 if (mod != 3) {
5343 s->rip_offset = 1;
5344 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5345 gen_op_ld_T0_A0[ot + s->mem_index]();
5346 } else {
5347 gen_op_mov_TN_reg[ot][0][rm]();
5349 /* load shift */
5350 val = ldub_code(s->pc++);
5351 gen_op_movl_T1_im(val);
5352 if (op < 4)
5353 goto illegal_op;
5354 op -= 4;
5355 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5356 s->cc_op = CC_OP_SARB + ot;
5357 if (op != 0) {
5358 if (mod != 3)
5359 gen_op_st_T0_A0[ot + s->mem_index]();
5360 else
5361 gen_op_mov_reg_T0[ot][rm]();
5362 gen_op_update_bt_cc();
5364 break;
5365 case 0x1a3: /* bt Gv, Ev */
5366 op = 0;
5367 goto do_btx;
5368 case 0x1ab: /* bts */
5369 op = 1;
5370 goto do_btx;
5371 case 0x1b3: /* btr */
5372 op = 2;
5373 goto do_btx;
5374 case 0x1bb: /* btc */
5375 op = 3;
5376 do_btx:
5377 ot = dflag + OT_WORD;
5378 modrm = ldub_code(s->pc++);
5379 reg = ((modrm >> 3) & 7) | rex_r;
5380 mod = (modrm >> 6) & 3;
5381 rm = (modrm & 7) | REX_B(s);
5382 gen_op_mov_TN_reg[OT_LONG][1][reg]();
5383 if (mod != 3) {
5384 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5385 /* specific case: we need to add a displacement */
5386 gen_op_add_bit_A0_T1[ot - OT_WORD]();
5387 gen_op_ld_T0_A0[ot + s->mem_index]();
5388 } else {
5389 gen_op_mov_TN_reg[ot][0][rm]();
5391 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5392 s->cc_op = CC_OP_SARB + ot;
5393 if (op != 0) {
5394 if (mod != 3)
5395 gen_op_st_T0_A0[ot + s->mem_index]();
5396 else
5397 gen_op_mov_reg_T0[ot][rm]();
5398 gen_op_update_bt_cc();
5400 break;
5401 case 0x1bc: /* bsf */
5402 case 0x1bd: /* bsr */
5403 ot = dflag + OT_WORD;
5404 modrm = ldub_code(s->pc++);
5405 reg = ((modrm >> 3) & 7) | rex_r;
5406 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5407 /* NOTE: in order to handle the 0 case, we must load the
5408 result. It could be optimized with a generated jump */
5409 gen_op_mov_TN_reg[ot][1][reg]();
5410 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
5411 gen_op_mov_reg_T1[ot][reg]();
5412 s->cc_op = CC_OP_LOGICB + ot;
5413 break;
5414 /************************/
5415 /* bcd */
5416 case 0x27: /* daa */
5417 if (CODE64(s))
5418 goto illegal_op;
5419 if (s->cc_op != CC_OP_DYNAMIC)
5420 gen_op_set_cc_op(s->cc_op);
5421 gen_op_daa();
5422 s->cc_op = CC_OP_EFLAGS;
5423 break;
5424 case 0x2f: /* das */
5425 if (CODE64(s))
5426 goto illegal_op;
5427 if (s->cc_op != CC_OP_DYNAMIC)
5428 gen_op_set_cc_op(s->cc_op);
5429 gen_op_das();
5430 s->cc_op = CC_OP_EFLAGS;
5431 break;
5432 case 0x37: /* aaa */
5433 if (CODE64(s))
5434 goto illegal_op;
5435 if (s->cc_op != CC_OP_DYNAMIC)
5436 gen_op_set_cc_op(s->cc_op);
5437 gen_op_aaa();
5438 s->cc_op = CC_OP_EFLAGS;
5439 break;
5440 case 0x3f: /* aas */
5441 if (CODE64(s))
5442 goto illegal_op;
5443 if (s->cc_op != CC_OP_DYNAMIC)
5444 gen_op_set_cc_op(s->cc_op);
5445 gen_op_aas();
5446 s->cc_op = CC_OP_EFLAGS;
5447 break;
5448 case 0xd4: /* aam */
5449 if (CODE64(s))
5450 goto illegal_op;
5451 val = ldub_code(s->pc++);
5452 if (val == 0) {
5453 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
5454 } else {
5455 gen_op_aam(val);
5456 s->cc_op = CC_OP_LOGICB;
5458 break;
5459 case 0xd5: /* aad */
5460 if (CODE64(s))
5461 goto illegal_op;
5462 val = ldub_code(s->pc++);
5463 gen_op_aad(val);
5464 s->cc_op = CC_OP_LOGICB;
5465 break;
5466 /************************/
5467 /* misc */
5468 case 0x90: /* nop */
5469 /* XXX: xchg + rex handling */
5470 /* XXX: correct lock test for all insn */
5471 if (prefixes & PREFIX_LOCK)
5472 goto illegal_op;
5473 if (prefixes & PREFIX_REPZ) {
5474 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
5476 break;
5477 case 0x9b: /* fwait */
5478 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
5479 (HF_MP_MASK | HF_TS_MASK)) {
5480 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5481 } else {
5482 if (s->cc_op != CC_OP_DYNAMIC)
5483 gen_op_set_cc_op(s->cc_op);
5484 gen_jmp_im(pc_start - s->cs_base);
5485 gen_op_fwait();
5487 break;
5488 case 0xcc: /* int3 */
5489 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5490 break;
5491 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5492 break;
5493 case 0xcd: /* int N */
5494 val = ldub_code(s->pc++);
5495 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5496 break;
5497 if (s->vm86 && s->iopl != 3) {
5498 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5499 } else {
5500 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5502 break;
5503 case 0xce: /* into */
5504 if (CODE64(s))
5505 goto illegal_op;
5506 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
5507 break;
5508 if (s->cc_op != CC_OP_DYNAMIC)
5509 gen_op_set_cc_op(s->cc_op);
5510 gen_jmp_im(pc_start - s->cs_base);
5511 gen_op_into(s->pc - pc_start);
5512 break;
5513 case 0xf1: /* icebp (undocumented, exits to external debugger) */
5514 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP))
5515 break;
5516 #if 1
5517 gen_debug(s, pc_start - s->cs_base);
5518 #else
5519 /* start debug */
5520 tb_flush(cpu_single_env);
5521 cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5522 #endif
5523 break;
5524 case 0xfa: /* cli */
5525 if (!s->vm86) {
5526 if (s->cpl <= s->iopl) {
5527 gen_op_cli();
5528 } else {
5529 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5531 } else {
5532 if (s->iopl == 3) {
5533 gen_op_cli();
5534 } else {
5535 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5538 break;
5539 case 0xfb: /* sti */
5540 if (!s->vm86) {
5541 if (s->cpl <= s->iopl) {
5542 gen_sti:
5543 gen_op_sti();
5544 /* interruptions are enabled only the first insn after sti */
5545 /* If several instructions disable interrupts, only the
5546 _first_ does it */
5547 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5548 gen_op_set_inhibit_irq();
5549 /* give a chance to handle pending irqs */
5550 gen_jmp_im(s->pc - s->cs_base);
5551 gen_eob(s);
5552 } else {
5553 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5555 } else {
5556 if (s->iopl == 3) {
5557 goto gen_sti;
5558 } else {
5559 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5562 break;
5563 case 0x62: /* bound */
5564 if (CODE64(s))
5565 goto illegal_op;
5566 ot = dflag ? OT_LONG : OT_WORD;
5567 modrm = ldub_code(s->pc++);
5568 reg = (modrm >> 3) & 7;
5569 mod = (modrm >> 6) & 3;
5570 if (mod == 3)
5571 goto illegal_op;
5572 gen_op_mov_TN_reg[ot][0][reg]();
5573 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5574 gen_jmp_im(pc_start - s->cs_base);
5575 if (ot == OT_WORD)
5576 gen_op_boundw();
5577 else
5578 gen_op_boundl();
5579 break;
5580 case 0x1c8 ... 0x1cf: /* bswap reg */
5581 reg = (b & 7) | REX_B(s);
5582 #ifdef TARGET_X86_64
5583 if (dflag == 2) {
5584 gen_op_mov_TN_reg[OT_QUAD][0][reg]();
5585 gen_op_bswapq_T0();
5586 gen_op_mov_reg_T0[OT_QUAD][reg]();
5587 } else
5588 #endif
5590 gen_op_mov_TN_reg[OT_LONG][0][reg]();
5591 gen_op_bswapl_T0();
5592 gen_op_mov_reg_T0[OT_LONG][reg]();
5594 break;
5595 case 0xd6: /* salc */
5596 if (CODE64(s))
5597 goto illegal_op;
5598 if (s->cc_op != CC_OP_DYNAMIC)
5599 gen_op_set_cc_op(s->cc_op);
5600 gen_op_salc();
5601 break;
5602 case 0xe0: /* loopnz */
5603 case 0xe1: /* loopz */
5604 if (s->cc_op != CC_OP_DYNAMIC)
5605 gen_op_set_cc_op(s->cc_op);
5606 /* FALL THRU */
5607 case 0xe2: /* loop */
5608 case 0xe3: /* jecxz */
5610 int l1, l2;
5612 tval = (int8_t)insn_get(s, OT_BYTE);
5613 next_eip = s->pc - s->cs_base;
5614 tval += next_eip;
5615 if (s->dflag == 0)
5616 tval &= 0xffff;
5618 l1 = gen_new_label();
5619 l2 = gen_new_label();
5620 b &= 3;
5621 if (b == 3) {
5622 gen_op_jz_ecx[s->aflag](l1);
5623 } else {
5624 gen_op_dec_ECX[s->aflag]();
5625 if (b <= 1)
5626 gen_op_mov_T0_cc();
5627 gen_op_loop[s->aflag][b](l1);
5630 gen_jmp_im(next_eip);
5631 gen_op_jmp_label(l2);
5632 gen_set_label(l1);
5633 gen_jmp_im(tval);
5634 gen_set_label(l2);
5635 gen_eob(s);
5637 break;
5638 case 0x130: /* wrmsr */
5639 case 0x132: /* rdmsr */
5640 if (s->cpl != 0) {
5641 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5642 } else {
5643 int retval = 0;
5644 if (b & 2) {
5645 retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0);
5646 gen_op_rdmsr();
5647 } else {
5648 retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1);
5649 gen_op_wrmsr();
5651 if(retval)
5652 gen_eob(s);
5654 break;
5655 case 0x131: /* rdtsc */
5656 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC))
5657 break;
5658 gen_jmp_im(pc_start - s->cs_base);
5659 gen_op_rdtsc();
5660 break;
5661 case 0x134: /* sysenter */
5662 if (CODE64(s))
5663 goto illegal_op;
5664 if (!s->pe) {
5665 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5666 } else {
5667 if (s->cc_op != CC_OP_DYNAMIC) {
5668 gen_op_set_cc_op(s->cc_op);
5669 s->cc_op = CC_OP_DYNAMIC;
5671 gen_jmp_im(pc_start - s->cs_base);
5672 gen_op_sysenter();
5673 gen_eob(s);
5675 break;
5676 case 0x135: /* sysexit */
5677 if (CODE64(s))
5678 goto illegal_op;
5679 if (!s->pe) {
5680 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5681 } else {
5682 if (s->cc_op != CC_OP_DYNAMIC) {
5683 gen_op_set_cc_op(s->cc_op);
5684 s->cc_op = CC_OP_DYNAMIC;
5686 gen_jmp_im(pc_start - s->cs_base);
5687 gen_op_sysexit();
5688 gen_eob(s);
5690 break;
5691 #ifdef TARGET_X86_64
5692 case 0x105: /* syscall */
5693 /* XXX: is it usable in real mode ? */
5694 if (s->cc_op != CC_OP_DYNAMIC) {
5695 gen_op_set_cc_op(s->cc_op);
5696 s->cc_op = CC_OP_DYNAMIC;
5698 gen_jmp_im(pc_start - s->cs_base);
5699 gen_op_syscall(s->pc - pc_start);
5700 gen_eob(s);
5701 break;
5702 case 0x107: /* sysret */
5703 if (!s->pe) {
5704 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5705 } else {
5706 if (s->cc_op != CC_OP_DYNAMIC) {
5707 gen_op_set_cc_op(s->cc_op);
5708 s->cc_op = CC_OP_DYNAMIC;
5710 gen_jmp_im(pc_start - s->cs_base);
5711 gen_op_sysret(s->dflag);
5712 /* condition codes are modified only in long mode */
5713 if (s->lma)
5714 s->cc_op = CC_OP_EFLAGS;
5715 gen_eob(s);
5717 break;
5718 #endif
5719 case 0x1a2: /* cpuid */
5720 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID))
5721 break;
5722 gen_op_cpuid();
5723 break;
5724 case 0xf4: /* hlt */
5725 if (s->cpl != 0) {
5726 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5727 } else {
5728 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT))
5729 break;
5730 if (s->cc_op != CC_OP_DYNAMIC)
5731 gen_op_set_cc_op(s->cc_op);
5732 gen_jmp_im(s->pc - s->cs_base);
5733 gen_op_hlt();
5734 s->is_jmp = 3;
5736 break;
5737 case 0x100:
5738 modrm = ldub_code(s->pc++);
5739 mod = (modrm >> 6) & 3;
5740 op = (modrm >> 3) & 7;
5741 switch(op) {
5742 case 0: /* sldt */
5743 if (!s->pe || s->vm86)
5744 goto illegal_op;
5745 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ))
5746 break;
5747 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5748 ot = OT_WORD;
5749 if (mod == 3)
5750 ot += s->dflag;
5751 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5752 break;
5753 case 2: /* lldt */
5754 if (!s->pe || s->vm86)
5755 goto illegal_op;
5756 if (s->cpl != 0) {
5757 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5758 } else {
5759 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE))
5760 break;
5761 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5762 gen_jmp_im(pc_start - s->cs_base);
5763 gen_op_lldt_T0();
5765 break;
5766 case 1: /* str */
5767 if (!s->pe || s->vm86)
5768 goto illegal_op;
5769 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ))
5770 break;
5771 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5772 ot = OT_WORD;
5773 if (mod == 3)
5774 ot += s->dflag;
5775 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5776 break;
5777 case 3: /* ltr */
5778 if (!s->pe || s->vm86)
5779 goto illegal_op;
5780 if (s->cpl != 0) {
5781 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5782 } else {
5783 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE))
5784 break;
5785 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5786 gen_jmp_im(pc_start - s->cs_base);
5787 gen_op_ltr_T0();
5789 break;
5790 case 4: /* verr */
5791 case 5: /* verw */
5792 if (!s->pe || s->vm86)
5793 goto illegal_op;
5794 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5795 if (s->cc_op != CC_OP_DYNAMIC)
5796 gen_op_set_cc_op(s->cc_op);
5797 if (op == 4)
5798 gen_op_verr();
5799 else
5800 gen_op_verw();
5801 s->cc_op = CC_OP_EFLAGS;
5802 break;
5803 default:
5804 goto illegal_op;
5806 break;
5807 case 0x101:
5808 modrm = ldub_code(s->pc++);
5809 mod = (modrm >> 6) & 3;
5810 op = (modrm >> 3) & 7;
5811 rm = modrm & 7;
5812 switch(op) {
5813 case 0: /* sgdt */
5814 if (mod == 3)
5815 goto illegal_op;
5816 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ))
5817 break;
5818 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5819 gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
5820 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5821 gen_add_A0_im(s, 2);
5822 gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base));
5823 if (!s->dflag)
5824 gen_op_andl_T0_im(0xffffff);
5825 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5826 break;
5827 case 1:
5828 if (mod == 3) {
5829 switch (rm) {
5830 case 0: /* monitor */
5831 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5832 s->cpl != 0)
5833 goto illegal_op;
5834 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR))
5835 break;
5836 gen_jmp_im(pc_start - s->cs_base);
5837 #ifdef TARGET_X86_64
5838 if (s->aflag == 2) {
5839 gen_op_movq_A0_reg[R_EBX]();
5840 gen_op_addq_A0_AL();
5841 } else
5842 #endif
5844 gen_op_movl_A0_reg[R_EBX]();
5845 gen_op_addl_A0_AL();
5846 if (s->aflag == 0)
5847 gen_op_andl_A0_ffff();
5849 gen_add_A0_ds_seg(s);
5850 gen_op_monitor();
5851 break;
5852 case 1: /* mwait */
5853 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5854 s->cpl != 0)
5855 goto illegal_op;
5856 if (s->cc_op != CC_OP_DYNAMIC) {
5857 gen_op_set_cc_op(s->cc_op);
5858 s->cc_op = CC_OP_DYNAMIC;
5860 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT))
5861 break;
5862 gen_jmp_im(s->pc - s->cs_base);
5863 gen_op_mwait();
5864 gen_eob(s);
5865 break;
5866 default:
5867 goto illegal_op;
5869 } else { /* sidt */
5870 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ))
5871 break;
5872 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5873 gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
5874 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5875 gen_add_A0_im(s, 2);
5876 gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base));
5877 if (!s->dflag)
5878 gen_op_andl_T0_im(0xffffff);
5879 gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5881 break;
5882 case 2: /* lgdt */
5883 case 3: /* lidt */
5884 if (mod == 3) {
5885 switch(rm) {
5886 case 0: /* VMRUN */
5887 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN))
5888 break;
5889 if (s->cc_op != CC_OP_DYNAMIC)
5890 gen_op_set_cc_op(s->cc_op);
5891 gen_jmp_im(s->pc - s->cs_base);
5892 gen_op_vmrun();
5893 s->cc_op = CC_OP_EFLAGS;
5894 gen_eob(s);
5895 break;
5896 case 1: /* VMMCALL */
5897 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL))
5898 break;
5899 /* FIXME: cause #UD if hflags & SVM */
5900 gen_op_vmmcall();
5901 break;
5902 case 2: /* VMLOAD */
5903 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD))
5904 break;
5905 gen_op_vmload();
5906 break;
5907 case 3: /* VMSAVE */
5908 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE))
5909 break;
5910 gen_op_vmsave();
5911 break;
5912 case 4: /* STGI */
5913 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI))
5914 break;
5915 gen_op_stgi();
5916 break;
5917 case 5: /* CLGI */
5918 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI))
5919 break;
5920 gen_op_clgi();
5921 break;
5922 case 6: /* SKINIT */
5923 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT))
5924 break;
5925 gen_op_skinit();
5926 break;
5927 case 7: /* INVLPGA */
5928 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA))
5929 break;
5930 gen_op_invlpga();
5931 break;
5932 default:
5933 goto illegal_op;
5935 } else if (s->cpl != 0) {
5936 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5937 } else {
5938 if (gen_svm_check_intercept(s, pc_start,
5939 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE))
5940 break;
5941 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5942 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
5943 gen_add_A0_im(s, 2);
5944 gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5945 if (!s->dflag)
5946 gen_op_andl_T0_im(0xffffff);
5947 if (op == 2) {
5948 gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
5949 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5950 } else {
5951 gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
5952 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5955 break;
5956 case 4: /* smsw */
5957 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0))
5958 break;
5959 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5960 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5961 break;
5962 case 6: /* lmsw */
5963 if (s->cpl != 0) {
5964 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5965 } else {
5966 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0))
5967 break;
5968 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5969 gen_op_lmsw_T0();
5970 gen_jmp_im(s->pc - s->cs_base);
5971 gen_eob(s);
5973 break;
5974 case 7: /* invlpg */
5975 if (s->cpl != 0) {
5976 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5977 } else {
5978 if (mod == 3) {
5979 #ifdef TARGET_X86_64
5980 if (CODE64(s) && rm == 0) {
5981 /* swapgs */
5982 gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5983 gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5984 gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5985 gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
5986 } else
5987 #endif
5989 goto illegal_op;
5991 } else {
5992 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG))
5993 break;
5994 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5995 gen_op_invlpg_A0();
5996 gen_jmp_im(s->pc - s->cs_base);
5997 gen_eob(s);
6000 break;
6001 default:
6002 goto illegal_op;
6004 break;
6005 case 0x108: /* invd */
6006 case 0x109: /* wbinvd */
6007 if (s->cpl != 0) {
6008 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6009 } else {
6010 if (gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD))
6011 break;
6012 /* nothing to do */
6014 break;
6015 case 0x63: /* arpl or movslS (x86_64) */
6016 #ifdef TARGET_X86_64
6017 if (CODE64(s)) {
6018 int d_ot;
6019 /* d_ot is the size of destination */
6020 d_ot = dflag + OT_WORD;
6022 modrm = ldub_code(s->pc++);
6023 reg = ((modrm >> 3) & 7) | rex_r;
6024 mod = (modrm >> 6) & 3;
6025 rm = (modrm & 7) | REX_B(s);
6027 if (mod == 3) {
6028 gen_op_mov_TN_reg[OT_LONG][0][rm]();
6029 /* sign extend */
6030 if (d_ot == OT_QUAD)
6031 gen_op_movslq_T0_T0();
6032 gen_op_mov_reg_T0[d_ot][reg]();
6033 } else {
6034 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6035 if (d_ot == OT_QUAD) {
6036 gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
6037 } else {
6038 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6040 gen_op_mov_reg_T0[d_ot][reg]();
6042 } else
6043 #endif
6045 if (!s->pe || s->vm86)
6046 goto illegal_op;
6047 ot = dflag ? OT_LONG : OT_WORD;
6048 modrm = ldub_code(s->pc++);
6049 reg = (modrm >> 3) & 7;
6050 mod = (modrm >> 6) & 3;
6051 rm = modrm & 7;
6052 if (mod != 3) {
6053 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6054 gen_op_ld_T0_A0[ot + s->mem_index]();
6055 } else {
6056 gen_op_mov_TN_reg[ot][0][rm]();
6058 if (s->cc_op != CC_OP_DYNAMIC)
6059 gen_op_set_cc_op(s->cc_op);
6060 gen_op_arpl();
6061 s->cc_op = CC_OP_EFLAGS;
6062 if (mod != 3) {
6063 gen_op_st_T0_A0[ot + s->mem_index]();
6064 } else {
6065 gen_op_mov_reg_T0[ot][rm]();
6067 gen_op_arpl_update();
6069 break;
6070 case 0x102: /* lar */
6071 case 0x103: /* lsl */
6072 if (!s->pe || s->vm86)
6073 goto illegal_op;
6074 ot = dflag ? OT_LONG : OT_WORD;
6075 modrm = ldub_code(s->pc++);
6076 reg = ((modrm >> 3) & 7) | rex_r;
6077 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
6078 gen_op_mov_TN_reg[ot][1][reg]();
6079 if (s->cc_op != CC_OP_DYNAMIC)
6080 gen_op_set_cc_op(s->cc_op);
6081 if (b == 0x102)
6082 gen_op_lar();
6083 else
6084 gen_op_lsl();
6085 s->cc_op = CC_OP_EFLAGS;
6086 gen_op_mov_reg_T1[ot][reg]();
6087 break;
6088 case 0x118:
6089 modrm = ldub_code(s->pc++);
6090 mod = (modrm >> 6) & 3;
6091 op = (modrm >> 3) & 7;
6092 switch(op) {
6093 case 0: /* prefetchnta */
6094 case 1: /* prefetchnt0 */
6095 case 2: /* prefetchnt0 */
6096 case 3: /* prefetchnt0 */
6097 if (mod == 3)
6098 goto illegal_op;
6099 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6100 /* nothing more to do */
6101 break;
6102 default: /* nop (multi byte) */
6103 gen_nop_modrm(s, modrm);
6104 break;
6106 break;
6107 case 0x119 ... 0x11f: /* nop (multi byte) */
6108 modrm = ldub_code(s->pc++);
6109 gen_nop_modrm(s, modrm);
6110 break;
6111 case 0x120: /* mov reg, crN */
6112 case 0x122: /* mov crN, reg */
6113 if (s->cpl != 0) {
6114 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6115 } else {
6116 modrm = ldub_code(s->pc++);
6117 if ((modrm & 0xc0) != 0xc0)
6118 goto illegal_op;
6119 rm = (modrm & 7) | REX_B(s);
6120 reg = ((modrm >> 3) & 7) | rex_r;
6121 if (CODE64(s))
6122 ot = OT_QUAD;
6123 else
6124 ot = OT_LONG;
6125 switch(reg) {
6126 case 0:
6127 case 2:
6128 case 3:
6129 case 4:
6130 case 8:
6131 if (b & 2) {
6132 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg);
6133 gen_op_mov_TN_reg[ot][0][rm]();
6134 gen_op_movl_crN_T0(reg);
6135 gen_jmp_im(s->pc - s->cs_base);
6136 gen_eob(s);
6137 } else {
6138 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg);
6139 #if !defined(CONFIG_USER_ONLY)
6140 if (reg == 8)
6141 gen_op_movtl_T0_cr8();
6142 else
6143 #endif
6144 gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
6145 gen_op_mov_reg_T0[ot][rm]();
6147 break;
6148 default:
6149 goto illegal_op;
6152 break;
6153 case 0x121: /* mov reg, drN */
6154 case 0x123: /* mov drN, reg */
6155 if (s->cpl != 0) {
6156 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6157 } else {
6158 modrm = ldub_code(s->pc++);
6159 if ((modrm & 0xc0) != 0xc0)
6160 goto illegal_op;
6161 rm = (modrm & 7) | REX_B(s);
6162 reg = ((modrm >> 3) & 7) | rex_r;
6163 if (CODE64(s))
6164 ot = OT_QUAD;
6165 else
6166 ot = OT_LONG;
6167 /* XXX: do it dynamically with CR4.DE bit */
6168 if (reg == 4 || reg == 5 || reg >= 8)
6169 goto illegal_op;
6170 if (b & 2) {
6171 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
6172 gen_op_mov_TN_reg[ot][0][rm]();
6173 gen_op_movl_drN_T0(reg);
6174 gen_jmp_im(s->pc - s->cs_base);
6175 gen_eob(s);
6176 } else {
6177 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
6178 gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
6179 gen_op_mov_reg_T0[ot][rm]();
6182 break;
6183 case 0x106: /* clts */
6184 if (s->cpl != 0) {
6185 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6186 } else {
6187 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
6188 gen_op_clts();
6189 /* abort block because static cpu state changed */
6190 gen_jmp_im(s->pc - s->cs_base);
6191 gen_eob(s);
6193 break;
6194 /* MMX/SSE/SSE2/PNI support */
6195 case 0x1c3: /* MOVNTI reg, mem */
6196 if (!(s->cpuid_features & CPUID_SSE2))
6197 goto illegal_op;
6198 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
6199 modrm = ldub_code(s->pc++);
6200 mod = (modrm >> 6) & 3;
6201 if (mod == 3)
6202 goto illegal_op;
6203 reg = ((modrm >> 3) & 7) | rex_r;
6204 /* generate a generic store */
6205 gen_ldst_modrm(s, modrm, ot, reg, 1);
6206 break;
6207 case 0x1ae:
6208 modrm = ldub_code(s->pc++);
6209 mod = (modrm >> 6) & 3;
6210 op = (modrm >> 3) & 7;
6211 switch(op) {
6212 case 0: /* fxsave */
6213 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
6214 (s->flags & HF_EM_MASK))
6215 goto illegal_op;
6216 if (s->flags & HF_TS_MASK) {
6217 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6218 break;
6220 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6221 gen_op_fxsave_A0((s->dflag == 2));
6222 break;
6223 case 1: /* fxrstor */
6224 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
6225 (s->flags & HF_EM_MASK))
6226 goto illegal_op;
6227 if (s->flags & HF_TS_MASK) {
6228 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6229 break;
6231 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6232 gen_op_fxrstor_A0((s->dflag == 2));
6233 break;
6234 case 2: /* ldmxcsr */
6235 case 3: /* stmxcsr */
6236 if (s->flags & HF_TS_MASK) {
6237 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6238 break;
6240 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
6241 mod == 3)
6242 goto illegal_op;
6243 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6244 if (op == 2) {
6245 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6246 gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
6247 } else {
6248 gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
6249 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
6251 break;
6252 case 5: /* lfence */
6253 case 6: /* mfence */
6254 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
6255 goto illegal_op;
6256 break;
6257 case 7: /* sfence / clflush */
6258 if ((modrm & 0xc7) == 0xc0) {
6259 /* sfence */
6260 if (!(s->cpuid_features & CPUID_SSE))
6261 goto illegal_op;
6262 } else {
6263 /* clflush */
6264 if (!(s->cpuid_features & CPUID_CLFLUSH))
6265 goto illegal_op;
6266 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6268 break;
6269 default:
6270 goto illegal_op;
6272 break;
6273 case 0x10d: /* prefetch */
6274 modrm = ldub_code(s->pc++);
6275 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6276 /* ignore for now */
6277 break;
6278 case 0x1aa: /* rsm */
6279 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM))
6280 break;
6281 if (!(s->flags & HF_SMM_MASK))
6282 goto illegal_op;
6283 if (s->cc_op != CC_OP_DYNAMIC) {
6284 gen_op_set_cc_op(s->cc_op);
6285 s->cc_op = CC_OP_DYNAMIC;
6287 gen_jmp_im(s->pc - s->cs_base);
6288 gen_op_rsm();
6289 gen_eob(s);
6290 break;
6291 case 0x110 ... 0x117:
6292 case 0x128 ... 0x12f:
6293 case 0x150 ... 0x177:
6294 case 0x17c ... 0x17f:
6295 case 0x1c2:
6296 case 0x1c4 ... 0x1c6:
6297 case 0x1d0 ... 0x1fe:
6298 gen_sse(s, b, pc_start, rex_r);
6299 break;
6300 default:
6301 goto illegal_op;
6303 /* lock generation */
6304 if (s->prefix & PREFIX_LOCK)
6305 gen_op_unlock();
6306 return s->pc;
6307 illegal_op:
6308 if (s->prefix & PREFIX_LOCK)
6309 gen_op_unlock();
6310 /* XXX: ensure that no lock was generated */
6311 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
6312 return s->pc;
6315 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
6316 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
6318 /* flags read by an operation */
6319 static uint16_t opc_read_flags[NB_OPS] = {
6320 [INDEX_op_aas] = CC_A,
6321 [INDEX_op_aaa] = CC_A,
6322 [INDEX_op_das] = CC_A | CC_C,
6323 [INDEX_op_daa] = CC_A | CC_C,
6325 /* subtle: due to the incl/decl implementation, C is used */
6326 [INDEX_op_update_inc_cc] = CC_C,
6328 [INDEX_op_into] = CC_O,
6330 [INDEX_op_jb_subb] = CC_C,
6331 [INDEX_op_jb_subw] = CC_C,
6332 [INDEX_op_jb_subl] = CC_C,
6334 [INDEX_op_jz_subb] = CC_Z,
6335 [INDEX_op_jz_subw] = CC_Z,
6336 [INDEX_op_jz_subl] = CC_Z,
6338 [INDEX_op_jbe_subb] = CC_Z | CC_C,
6339 [INDEX_op_jbe_subw] = CC_Z | CC_C,
6340 [INDEX_op_jbe_subl] = CC_Z | CC_C,
6342 [INDEX_op_js_subb] = CC_S,
6343 [INDEX_op_js_subw] = CC_S,
6344 [INDEX_op_js_subl] = CC_S,
6346 [INDEX_op_jl_subb] = CC_O | CC_S,
6347 [INDEX_op_jl_subw] = CC_O | CC_S,
6348 [INDEX_op_jl_subl] = CC_O | CC_S,
6350 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
6351 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
6352 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
6354 [INDEX_op_loopnzw] = CC_Z,
6355 [INDEX_op_loopnzl] = CC_Z,
6356 [INDEX_op_loopzw] = CC_Z,
6357 [INDEX_op_loopzl] = CC_Z,
6359 [INDEX_op_seto_T0_cc] = CC_O,
6360 [INDEX_op_setb_T0_cc] = CC_C,
6361 [INDEX_op_setz_T0_cc] = CC_Z,
6362 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
6363 [INDEX_op_sets_T0_cc] = CC_S,
6364 [INDEX_op_setp_T0_cc] = CC_P,
6365 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
6366 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
6368 [INDEX_op_setb_T0_subb] = CC_C,
6369 [INDEX_op_setb_T0_subw] = CC_C,
6370 [INDEX_op_setb_T0_subl] = CC_C,
6372 [INDEX_op_setz_T0_subb] = CC_Z,
6373 [INDEX_op_setz_T0_subw] = CC_Z,
6374 [INDEX_op_setz_T0_subl] = CC_Z,
6376 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
6377 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
6378 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
6380 [INDEX_op_sets_T0_subb] = CC_S,
6381 [INDEX_op_sets_T0_subw] = CC_S,
6382 [INDEX_op_sets_T0_subl] = CC_S,
6384 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
6385 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
6386 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
6388 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
6389 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
6390 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
6392 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
6393 [INDEX_op_cmc] = CC_C,
6394 [INDEX_op_salc] = CC_C,
6396 /* needed for correct flag optimisation before string ops */
6397 [INDEX_op_jnz_ecxw] = CC_OSZAPC,
6398 [INDEX_op_jnz_ecxl] = CC_OSZAPC,
6399 [INDEX_op_jz_ecxw] = CC_OSZAPC,
6400 [INDEX_op_jz_ecxl] = CC_OSZAPC,
6402 #ifdef TARGET_X86_64
6403 [INDEX_op_jb_subq] = CC_C,
6404 [INDEX_op_jz_subq] = CC_Z,
6405 [INDEX_op_jbe_subq] = CC_Z | CC_C,
6406 [INDEX_op_js_subq] = CC_S,
6407 [INDEX_op_jl_subq] = CC_O | CC_S,
6408 [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
6410 [INDEX_op_loopnzq] = CC_Z,
6411 [INDEX_op_loopzq] = CC_Z,
6413 [INDEX_op_setb_T0_subq] = CC_C,
6414 [INDEX_op_setz_T0_subq] = CC_Z,
6415 [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
6416 [INDEX_op_sets_T0_subq] = CC_S,
6417 [INDEX_op_setl_T0_subq] = CC_O | CC_S,
6418 [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
6420 [INDEX_op_jnz_ecxq] = CC_OSZAPC,
6421 [INDEX_op_jz_ecxq] = CC_OSZAPC,
6422 #endif
6424 #define DEF_READF(SUFFIX)\
6425 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6426 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6427 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6428 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6429 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6430 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6431 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6432 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6434 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6435 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6436 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
6437 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6438 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6439 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6440 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6441 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
6443 DEF_READF( )
6444 DEF_READF(_raw)
6445 #ifndef CONFIG_USER_ONLY
6446 DEF_READF(_kernel)
6447 DEF_READF(_user)
6448 #endif
6451 /* flags written by an operation */
6452 static uint16_t opc_write_flags[NB_OPS] = {
6453 [INDEX_op_update2_cc] = CC_OSZAPC,
6454 [INDEX_op_update1_cc] = CC_OSZAPC,
6455 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6456 [INDEX_op_update_neg_cc] = CC_OSZAPC,
6457 /* subtle: due to the incl/decl implementation, C is used */
6458 [INDEX_op_update_inc_cc] = CC_OSZAPC,
6459 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6461 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
6462 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
6463 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
6464 X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6465 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6466 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
6467 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
6468 X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
6469 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6470 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
6471 X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6473 /* sse */
6474 [INDEX_op_ucomiss] = CC_OSZAPC,
6475 [INDEX_op_ucomisd] = CC_OSZAPC,
6476 [INDEX_op_comiss] = CC_OSZAPC,
6477 [INDEX_op_comisd] = CC_OSZAPC,
6479 /* bcd */
6480 [INDEX_op_aam] = CC_OSZAPC,
6481 [INDEX_op_aad] = CC_OSZAPC,
6482 [INDEX_op_aas] = CC_OSZAPC,
6483 [INDEX_op_aaa] = CC_OSZAPC,
6484 [INDEX_op_das] = CC_OSZAPC,
6485 [INDEX_op_daa] = CC_OSZAPC,
6487 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6488 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6489 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
6490 [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6491 [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6492 [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6493 [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
6494 [INDEX_op_clc] = CC_C,
6495 [INDEX_op_stc] = CC_C,
6496 [INDEX_op_cmc] = CC_C,
6498 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6499 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
6500 X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
6501 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6502 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
6503 X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
6504 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6505 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
6506 X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
6507 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6508 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
6509 X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
6511 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6512 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
6513 X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
6514 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6515 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
6516 X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
6518 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6519 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6520 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
6521 X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
6523 [INDEX_op_cmpxchg8b] = CC_Z,
6524 [INDEX_op_lar] = CC_Z,
6525 [INDEX_op_lsl] = CC_Z,
6526 [INDEX_op_verr] = CC_Z,
6527 [INDEX_op_verw] = CC_Z,
6528 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6529 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6531 #define DEF_WRITEF(SUFFIX)\
6532 [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6533 [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6534 [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6535 X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6536 [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6537 [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6538 [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6539 X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6541 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6542 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6543 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6544 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6545 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6546 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6547 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6548 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6550 [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6551 [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6552 [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6553 X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6554 [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6555 [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6556 [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6557 X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6559 [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6560 [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6561 [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6562 X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6564 [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6565 [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6566 [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6567 X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6569 [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6570 [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6571 [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6572 X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6574 [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6575 [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6576 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6577 [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6578 [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6579 X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6581 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6582 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6583 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6584 [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6585 [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6586 X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6588 [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6589 [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6590 [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6591 X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
6594 DEF_WRITEF( )
6595 DEF_WRITEF(_raw)
6596 #ifndef CONFIG_USER_ONLY
6597 DEF_WRITEF(_kernel)
6598 DEF_WRITEF(_user)
6599 #endif
6602 /* simpler form of an operation if no flags need to be generated */
6603 static uint16_t opc_simpler[NB_OPS] = {
6604 [INDEX_op_update2_cc] = INDEX_op_nop,
6605 [INDEX_op_update1_cc] = INDEX_op_nop,
6606 [INDEX_op_update_neg_cc] = INDEX_op_nop,
6607 #if 0
6608 /* broken: CC_OP logic must be rewritten */
6609 [INDEX_op_update_inc_cc] = INDEX_op_nop,
6610 #endif
6612 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6613 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6614 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
6615 X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
6617 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6618 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6619 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
6620 X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
6622 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6623 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6624 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
6625 X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
6627 #define DEF_SIMPLER(SUFFIX)\
6628 [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6629 [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6630 [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
6631 X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
6633 [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6634 [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
6635 [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6636 X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
6638 DEF_SIMPLER( )
6639 DEF_SIMPLER(_raw)
6640 #ifndef CONFIG_USER_ONLY
6641 DEF_SIMPLER(_kernel)
6642 DEF_SIMPLER(_user)
6643 #endif
6646 void optimize_flags_init(void)
6648 int i;
6649 /* put default values in arrays */
6650 for(i = 0; i < NB_OPS; i++) {
6651 if (opc_simpler[i] == 0)
6652 opc_simpler[i] = i;
6656 /* CPU flags computation optimization: we move backward thru the
6657 generated code to see which flags are needed. The operation is
6658 modified if suitable */
6659 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6661 uint16_t *opc_ptr;
6662 int live_flags, write_flags, op;
6664 opc_ptr = opc_buf + opc_buf_len;
6665 /* live_flags contains the flags needed by the next instructions
6666 in the code. At the end of the block, we consider that all the
6667 flags are live. */
6668 live_flags = CC_OSZAPC;
6669 while (opc_ptr > opc_buf) {
6670 op = *--opc_ptr;
6671 /* if none of the flags written by the instruction is used,
6672 then we can try to find a simpler instruction */
6673 write_flags = opc_write_flags[op];
6674 if ((live_flags & write_flags) == 0) {
6675 *opc_ptr = opc_simpler[op];
6677 /* compute the live flags before the instruction */
6678 live_flags &= ~write_flags;
6679 live_flags |= opc_read_flags[op];
6683 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6684 basic block 'tb'. If search_pc is TRUE, also generate PC
6685 information for each intermediate instruction. */
6686 static inline int gen_intermediate_code_internal(CPUState *env,
6687 TranslationBlock *tb,
6688 int search_pc)
6690 DisasContext dc1, *dc = &dc1;
6691 target_ulong pc_ptr;
6692 uint16_t *gen_opc_end;
6693 int j, lj, cflags;
6694 uint64_t flags;
6695 target_ulong pc_start;
6696 target_ulong cs_base;
6698 /* generate intermediate code */
6699 pc_start = tb->pc;
6700 cs_base = tb->cs_base;
6701 flags = tb->flags;
6702 cflags = tb->cflags;
6704 dc->pe = (flags >> HF_PE_SHIFT) & 1;
6705 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6706 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6707 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6708 dc->f_st = 0;
6709 dc->vm86 = (flags >> VM_SHIFT) & 1;
6710 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6711 dc->iopl = (flags >> IOPL_SHIFT) & 3;
6712 dc->tf = (flags >> TF_SHIFT) & 1;
6713 dc->singlestep_enabled = env->singlestep_enabled;
6714 dc->cc_op = CC_OP_DYNAMIC;
6715 dc->cs_base = cs_base;
6716 dc->tb = tb;
6717 dc->popl_esp_hack = 0;
6718 /* select memory access functions */
6719 dc->mem_index = 0;
6720 if (flags & HF_SOFTMMU_MASK) {
6721 if (dc->cpl == 3)
6722 dc->mem_index = 2 * 4;
6723 else
6724 dc->mem_index = 1 * 4;
6726 dc->cpuid_features = env->cpuid_features;
6727 dc->cpuid_ext_features = env->cpuid_ext_features;
6728 #ifdef TARGET_X86_64
6729 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6730 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6731 #endif
6732 dc->flags = flags;
6733 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6734 (flags & HF_INHIBIT_IRQ_MASK)
6735 #ifndef CONFIG_SOFTMMU
6736 || (flags & HF_SOFTMMU_MASK)
6737 #endif
6739 #if 0
6740 /* check addseg logic */
6741 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
6742 printf("ERROR addseg\n");
6743 #endif
6745 gen_opc_ptr = gen_opc_buf;
6746 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6747 gen_opparam_ptr = gen_opparam_buf;
6748 nb_gen_labels = 0;
6750 dc->is_jmp = DISAS_NEXT;
6751 pc_ptr = pc_start;
6752 lj = -1;
6754 for(;;) {
6755 if (env->nb_breakpoints > 0) {
6756 for(j = 0; j < env->nb_breakpoints; j++) {
6757 if (env->breakpoints[j] == pc_ptr) {
6758 gen_debug(dc, pc_ptr - dc->cs_base);
6759 break;
6763 if (search_pc) {
6764 j = gen_opc_ptr - gen_opc_buf;
6765 if (lj < j) {
6766 lj++;
6767 while (lj < j)
6768 gen_opc_instr_start[lj++] = 0;
6770 gen_opc_pc[lj] = pc_ptr;
6771 gen_opc_cc_op[lj] = dc->cc_op;
6772 gen_opc_instr_start[lj] = 1;
6774 pc_ptr = disas_insn(dc, pc_ptr);
6775 /* stop translation if indicated */
6776 if (dc->is_jmp)
6777 break;
6778 /* if single step mode, we generate only one instruction and
6779 generate an exception */
6780 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6781 the flag and abort the translation to give the irqs a
6782 change to be happen */
6783 if (dc->tf || dc->singlestep_enabled ||
6784 (flags & HF_INHIBIT_IRQ_MASK) ||
6785 (cflags & CF_SINGLE_INSN)) {
6786 gen_jmp_im(pc_ptr - dc->cs_base);
6787 gen_eob(dc);
6788 break;
6790 /* if too long translation, stop generation too */
6791 if (gen_opc_ptr >= gen_opc_end ||
6792 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
6793 gen_jmp_im(pc_ptr - dc->cs_base);
6794 gen_eob(dc);
6795 break;
6798 *gen_opc_ptr = INDEX_op_end;
6799 /* we don't forget to fill the last values */
6800 if (search_pc) {
6801 j = gen_opc_ptr - gen_opc_buf;
6802 lj++;
6803 while (lj <= j)
6804 gen_opc_instr_start[lj++] = 0;
6807 #ifdef DEBUG_DISAS
6808 if (loglevel & CPU_LOG_TB_CPU) {
6809 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
6811 if (loglevel & CPU_LOG_TB_IN_ASM) {
6812 int disas_flags;
6813 fprintf(logfile, "----------------\n");
6814 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6815 #ifdef TARGET_X86_64
6816 if (dc->code64)
6817 disas_flags = 2;
6818 else
6819 #endif
6820 disas_flags = !dc->code32;
6821 target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
6822 fprintf(logfile, "\n");
6823 if (loglevel & CPU_LOG_TB_OP) {
6824 fprintf(logfile, "OP:\n");
6825 dump_ops(gen_opc_buf, gen_opparam_buf);
6826 fprintf(logfile, "\n");
6829 #endif
6831 /* optimize flag computations */
6832 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6834 #ifdef DEBUG_DISAS
6835 if (loglevel & CPU_LOG_TB_OP_OPT) {
6836 fprintf(logfile, "AFTER FLAGS OPT:\n");
6837 dump_ops(gen_opc_buf, gen_opparam_buf);
6838 fprintf(logfile, "\n");
6840 #endif
6841 if (!search_pc)
6842 tb->size = pc_ptr - pc_start;
6843 return 0;
6846 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6848 return gen_intermediate_code_internal(env, tb, 0);
6851 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6853 return gen_intermediate_code_internal(env, tb, 1);