]> git.proxmox.com Git - mirror_qemu.git/blob - target-i386/translate.c
target-i386: Implement ANDN
[mirror_qemu.git] / target-i386 / translate.c
1 /*
2 * i386 translation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <signal.h>
25
26 #include "qemu/host-utils.h"
27 #include "cpu.h"
28 #include "disas/disas.h"
29 #include "tcg-op.h"
30
31 #include "helper.h"
32 #define GEN_HELPER 1
33 #include "helper.h"
34
35 #define PREFIX_REPZ 0x01
36 #define PREFIX_REPNZ 0x02
37 #define PREFIX_LOCK 0x04
38 #define PREFIX_DATA 0x08
39 #define PREFIX_ADR 0x10
40 #define PREFIX_VEX 0x20
41
42 #ifdef TARGET_X86_64
43 #define CODE64(s) ((s)->code64)
44 #define REX_X(s) ((s)->rex_x)
45 #define REX_B(s) ((s)->rex_b)
46 #else
47 #define CODE64(s) 0
48 #define REX_X(s) 0
49 #define REX_B(s) 0
50 #endif
51
52 #ifdef TARGET_X86_64
53 # define ctztl ctz64
54 # define clztl clz64
55 #else
56 # define ctztl ctz32
57 # define clztl clz32
58 #endif
59
60 //#define MACRO_TEST 1
61
62 /* global register indexes */
63 static TCGv_ptr cpu_env;
64 static TCGv cpu_A0;
65 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
66 static TCGv_i32 cpu_cc_op;
67 static TCGv cpu_regs[CPU_NB_REGS];
68 /* local temps */
69 static TCGv cpu_T[2];
70 /* local register indexes (only used inside old micro ops) */
71 static TCGv cpu_tmp0, cpu_tmp4;
72 static TCGv_ptr cpu_ptr0, cpu_ptr1;
73 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
74 static TCGv_i64 cpu_tmp1_i64;
75 static TCGv cpu_tmp5;
76
77 static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
78
79 #include "exec/gen-icount.h"
80
81 #ifdef TARGET_X86_64
82 static int x86_64_hregs;
83 #endif
84
85 typedef struct DisasContext {
86 /* current insn context */
87 int override; /* -1 if no override */
88 int prefix;
89 int aflag, dflag;
90 target_ulong pc; /* pc = eip + cs_base */
91 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
92 static state change (stop translation) */
93 /* current block context */
94 target_ulong cs_base; /* base of CS segment */
95 int pe; /* protected mode */
96 int code32; /* 32 bit code segment */
97 #ifdef TARGET_X86_64
98 int lma; /* long mode active */
99 int code64; /* 64 bit code segment */
100 int rex_x, rex_b;
101 #endif
102 int vex_l; /* vex vector length */
103 int vex_v; /* vex vvvv register, without 1's compliment. */
104 int ss32; /* 32 bit stack segment */
105 CCOp cc_op; /* current CC operation */
106 bool cc_op_dirty;
107 int addseg; /* non zero if either DS/ES/SS have a non zero base */
108 int f_st; /* currently unused */
109 int vm86; /* vm86 mode */
110 int cpl;
111 int iopl;
112 int tf; /* TF cpu flag */
113 int singlestep_enabled; /* "hardware" single step enabled */
114 int jmp_opt; /* use direct block chaining for direct jumps */
115 int mem_index; /* select memory access functions */
116 uint64_t flags; /* all execution flags */
117 struct TranslationBlock *tb;
118 int popl_esp_hack; /* for correct popl with esp base handling */
119 int rip_offset; /* only used in x86_64, but left for simplicity */
120 int cpuid_features;
121 int cpuid_ext_features;
122 int cpuid_ext2_features;
123 int cpuid_ext3_features;
124 int cpuid_7_0_ebx_features;
125 } DisasContext;
126
127 static void gen_eob(DisasContext *s);
128 static void gen_jmp(DisasContext *s, target_ulong eip);
129 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
130 static void gen_op(DisasContext *s1, int op, int ot, int d);
131
132 /* i386 arith/logic operations */
133 enum {
134 OP_ADDL,
135 OP_ORL,
136 OP_ADCL,
137 OP_SBBL,
138 OP_ANDL,
139 OP_SUBL,
140 OP_XORL,
141 OP_CMPL,
142 };
143
144 /* i386 shift ops */
145 enum {
146 OP_ROL,
147 OP_ROR,
148 OP_RCL,
149 OP_RCR,
150 OP_SHL,
151 OP_SHR,
152 OP_SHL1, /* undocumented */
153 OP_SAR = 7,
154 };
155
156 enum {
157 JCC_O,
158 JCC_B,
159 JCC_Z,
160 JCC_BE,
161 JCC_S,
162 JCC_P,
163 JCC_L,
164 JCC_LE,
165 };
166
167 /* operand size */
168 enum {
169 OT_BYTE = 0,
170 OT_WORD,
171 OT_LONG,
172 OT_QUAD,
173 };
174
175 enum {
176 /* I386 int registers */
177 OR_EAX, /* MUST be even numbered */
178 OR_ECX,
179 OR_EDX,
180 OR_EBX,
181 OR_ESP,
182 OR_EBP,
183 OR_ESI,
184 OR_EDI,
185
186 OR_TMP0 = 16, /* temporary operand register */
187 OR_TMP1,
188 OR_A0, /* temporary register used when doing address evaluation */
189 };
190
191 enum {
192 USES_CC_DST = 1,
193 USES_CC_SRC = 2,
194 USES_CC_SRC2 = 4,
195 USES_CC_SRCT = 8,
196 };
197
198 /* Bit set if the global variable is live after setting CC_OP to X. */
199 static const uint8_t cc_op_live[CC_OP_NB] = {
200 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
201 [CC_OP_EFLAGS] = USES_CC_SRC,
202 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
203 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
204 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
205 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
206 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
207 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
208 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
209 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
210 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
211 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
212 };
213
214 static void set_cc_op(DisasContext *s, CCOp op)
215 {
216 int dead;
217
218 if (s->cc_op == op) {
219 return;
220 }
221
222 /* Discard CC computation that will no longer be used. */
223 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
224 if (dead & USES_CC_DST) {
225 tcg_gen_discard_tl(cpu_cc_dst);
226 }
227 if (dead & USES_CC_SRC) {
228 tcg_gen_discard_tl(cpu_cc_src);
229 }
230 if (dead & USES_CC_SRC2) {
231 tcg_gen_discard_tl(cpu_cc_src2);
232 }
233 if (dead & USES_CC_SRCT) {
234 tcg_gen_discard_tl(cpu_cc_srcT);
235 }
236
237 s->cc_op = op;
238 /* The DYNAMIC setting is translator only, and should never be
239 stored. Thus we always consider it clean. */
240 s->cc_op_dirty = (op != CC_OP_DYNAMIC);
241 }
242
243 static void gen_update_cc_op(DisasContext *s)
244 {
245 if (s->cc_op_dirty) {
246 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
247 s->cc_op_dirty = false;
248 }
249 }
250
251 static inline void gen_op_movl_T0_0(void)
252 {
253 tcg_gen_movi_tl(cpu_T[0], 0);
254 }
255
256 static inline void gen_op_movl_T0_im(int32_t val)
257 {
258 tcg_gen_movi_tl(cpu_T[0], val);
259 }
260
261 static inline void gen_op_movl_T0_imu(uint32_t val)
262 {
263 tcg_gen_movi_tl(cpu_T[0], val);
264 }
265
266 static inline void gen_op_movl_T1_im(int32_t val)
267 {
268 tcg_gen_movi_tl(cpu_T[1], val);
269 }
270
271 static inline void gen_op_movl_T1_imu(uint32_t val)
272 {
273 tcg_gen_movi_tl(cpu_T[1], val);
274 }
275
276 static inline void gen_op_movl_A0_im(uint32_t val)
277 {
278 tcg_gen_movi_tl(cpu_A0, val);
279 }
280
281 #ifdef TARGET_X86_64
282 static inline void gen_op_movq_A0_im(int64_t val)
283 {
284 tcg_gen_movi_tl(cpu_A0, val);
285 }
286 #endif
287
288 static inline void gen_movtl_T0_im(target_ulong val)
289 {
290 tcg_gen_movi_tl(cpu_T[0], val);
291 }
292
293 static inline void gen_movtl_T1_im(target_ulong val)
294 {
295 tcg_gen_movi_tl(cpu_T[1], val);
296 }
297
298 static inline void gen_op_andl_T0_ffff(void)
299 {
300 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
301 }
302
303 static inline void gen_op_andl_T0_im(uint32_t val)
304 {
305 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
306 }
307
308 static inline void gen_op_movl_T0_T1(void)
309 {
310 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
311 }
312
313 static inline void gen_op_andl_A0_ffff(void)
314 {
315 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
316 }
317
318 #ifdef TARGET_X86_64
319
320 #define NB_OP_SIZES 4
321
322 #else /* !TARGET_X86_64 */
323
324 #define NB_OP_SIZES 3
325
326 #endif /* !TARGET_X86_64 */
327
328 #if defined(HOST_WORDS_BIGENDIAN)
329 #define REG_B_OFFSET (sizeof(target_ulong) - 1)
330 #define REG_H_OFFSET (sizeof(target_ulong) - 2)
331 #define REG_W_OFFSET (sizeof(target_ulong) - 2)
332 #define REG_L_OFFSET (sizeof(target_ulong) - 4)
333 #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
334 #else
335 #define REG_B_OFFSET 0
336 #define REG_H_OFFSET 1
337 #define REG_W_OFFSET 0
338 #define REG_L_OFFSET 0
339 #define REG_LH_OFFSET 4
340 #endif
341
342 /* In instruction encodings for byte register accesses the
343 * register number usually indicates "low 8 bits of register N";
344 * however there are some special cases where N 4..7 indicates
345 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
346 * true for this special case, false otherwise.
347 */
348 static inline bool byte_reg_is_xH(int reg)
349 {
350 if (reg < 4) {
351 return false;
352 }
353 #ifdef TARGET_X86_64
354 if (reg >= 8 || x86_64_hregs) {
355 return false;
356 }
357 #endif
358 return true;
359 }
360
361 static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
362 {
363 switch(ot) {
364 case OT_BYTE:
365 if (!byte_reg_is_xH(reg)) {
366 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
367 } else {
368 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
369 }
370 break;
371 case OT_WORD:
372 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
373 break;
374 default: /* XXX this shouldn't be reached; abort? */
375 case OT_LONG:
376 /* For x86_64, this sets the higher half of register to zero.
377 For i386, this is equivalent to a mov. */
378 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
379 break;
380 #ifdef TARGET_X86_64
381 case OT_QUAD:
382 tcg_gen_mov_tl(cpu_regs[reg], t0);
383 break;
384 #endif
385 }
386 }
387
388 static inline void gen_op_mov_reg_T0(int ot, int reg)
389 {
390 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
391 }
392
393 static inline void gen_op_mov_reg_T1(int ot, int reg)
394 {
395 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
396 }
397
398 static inline void gen_op_mov_reg_A0(int size, int reg)
399 {
400 switch(size) {
401 case OT_BYTE:
402 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
403 break;
404 default: /* XXX this shouldn't be reached; abort? */
405 case OT_WORD:
406 /* For x86_64, this sets the higher half of register to zero.
407 For i386, this is equivalent to a mov. */
408 tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
409 break;
410 #ifdef TARGET_X86_64
411 case OT_LONG:
412 tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
413 break;
414 #endif
415 }
416 }
417
418 static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
419 {
420 if (ot == OT_BYTE && byte_reg_is_xH(reg)) {
421 tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
422 tcg_gen_ext8u_tl(t0, t0);
423 } else {
424 tcg_gen_mov_tl(t0, cpu_regs[reg]);
425 }
426 }
427
428 static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
429 {
430 gen_op_mov_v_reg(ot, cpu_T[t_index], reg);
431 }
432
433 static inline void gen_op_movl_A0_reg(int reg)
434 {
435 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
436 }
437
438 static inline void gen_op_addl_A0_im(int32_t val)
439 {
440 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
441 #ifdef TARGET_X86_64
442 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
443 #endif
444 }
445
446 #ifdef TARGET_X86_64
447 static inline void gen_op_addq_A0_im(int64_t val)
448 {
449 tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
450 }
451 #endif
452
453 static void gen_add_A0_im(DisasContext *s, int val)
454 {
455 #ifdef TARGET_X86_64
456 if (CODE64(s))
457 gen_op_addq_A0_im(val);
458 else
459 #endif
460 gen_op_addl_A0_im(val);
461 }
462
463 static inline void gen_op_addl_T0_T1(void)
464 {
465 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
466 }
467
468 static inline void gen_op_jmp_T0(void)
469 {
470 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
471 }
472
473 static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
474 {
475 switch(size) {
476 case OT_BYTE:
477 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
478 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
479 break;
480 case OT_WORD:
481 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
482 /* For x86_64, this sets the higher half of register to zero.
483 For i386, this is equivalent to a nop. */
484 tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
485 tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
486 break;
487 #ifdef TARGET_X86_64
488 case OT_LONG:
489 tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
490 break;
491 #endif
492 }
493 }
494
495 static inline void gen_op_add_reg_T0(int size, int reg)
496 {
497 switch(size) {
498 case OT_BYTE:
499 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
500 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
501 break;
502 case OT_WORD:
503 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
504 /* For x86_64, this sets the higher half of register to zero.
505 For i386, this is equivalent to a nop. */
506 tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
507 tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
508 break;
509 #ifdef TARGET_X86_64
510 case OT_LONG:
511 tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
512 break;
513 #endif
514 }
515 }
516
517 static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
518 {
519 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
520 if (shift != 0)
521 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
522 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
523 /* For x86_64, this sets the higher half of register to zero.
524 For i386, this is equivalent to a nop. */
525 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
526 }
527
528 static inline void gen_op_movl_A0_seg(int reg)
529 {
530 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
531 }
532
533 static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
534 {
535 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
536 #ifdef TARGET_X86_64
537 if (CODE64(s)) {
538 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
539 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
540 } else {
541 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
542 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
543 }
544 #else
545 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
546 #endif
547 }
548
549 #ifdef TARGET_X86_64
550 static inline void gen_op_movq_A0_seg(int reg)
551 {
552 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
553 }
554
555 static inline void gen_op_addq_A0_seg(int reg)
556 {
557 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
558 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
559 }
560
561 static inline void gen_op_movq_A0_reg(int reg)
562 {
563 tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
564 }
565
566 static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
567 {
568 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
569 if (shift != 0)
570 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
571 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
572 }
573 #endif
574
575 static inline void gen_op_lds_T0_A0(int idx)
576 {
577 int mem_index = (idx >> 2) - 1;
578 switch(idx & 3) {
579 case OT_BYTE:
580 tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index);
581 break;
582 case OT_WORD:
583 tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index);
584 break;
585 default:
586 case OT_LONG:
587 tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index);
588 break;
589 }
590 }
591
592 static inline void gen_op_ld_v(int idx, TCGv t0, TCGv a0)
593 {
594 int mem_index = (idx >> 2) - 1;
595 switch(idx & 3) {
596 case OT_BYTE:
597 tcg_gen_qemu_ld8u(t0, a0, mem_index);
598 break;
599 case OT_WORD:
600 tcg_gen_qemu_ld16u(t0, a0, mem_index);
601 break;
602 case OT_LONG:
603 tcg_gen_qemu_ld32u(t0, a0, mem_index);
604 break;
605 default:
606 case OT_QUAD:
607 /* Should never happen on 32-bit targets. */
608 #ifdef TARGET_X86_64
609 tcg_gen_qemu_ld64(t0, a0, mem_index);
610 #endif
611 break;
612 }
613 }
614
615 /* XXX: always use ldu or lds */
616 static inline void gen_op_ld_T0_A0(int idx)
617 {
618 gen_op_ld_v(idx, cpu_T[0], cpu_A0);
619 }
620
621 static inline void gen_op_ldu_T0_A0(int idx)
622 {
623 gen_op_ld_v(idx, cpu_T[0], cpu_A0);
624 }
625
626 static inline void gen_op_ld_T1_A0(int idx)
627 {
628 gen_op_ld_v(idx, cpu_T[1], cpu_A0);
629 }
630
631 static inline void gen_op_st_v(int idx, TCGv t0, TCGv a0)
632 {
633 int mem_index = (idx >> 2) - 1;
634 switch(idx & 3) {
635 case OT_BYTE:
636 tcg_gen_qemu_st8(t0, a0, mem_index);
637 break;
638 case OT_WORD:
639 tcg_gen_qemu_st16(t0, a0, mem_index);
640 break;
641 case OT_LONG:
642 tcg_gen_qemu_st32(t0, a0, mem_index);
643 break;
644 default:
645 case OT_QUAD:
646 /* Should never happen on 32-bit targets. */
647 #ifdef TARGET_X86_64
648 tcg_gen_qemu_st64(t0, a0, mem_index);
649 #endif
650 break;
651 }
652 }
653
654 static inline void gen_op_st_T0_A0(int idx)
655 {
656 gen_op_st_v(idx, cpu_T[0], cpu_A0);
657 }
658
659 static inline void gen_op_st_T1_A0(int idx)
660 {
661 gen_op_st_v(idx, cpu_T[1], cpu_A0);
662 }
663
664 static inline void gen_jmp_im(target_ulong pc)
665 {
666 tcg_gen_movi_tl(cpu_tmp0, pc);
667 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, eip));
668 }
669
670 static inline void gen_string_movl_A0_ESI(DisasContext *s)
671 {
672 int override;
673
674 override = s->override;
675 #ifdef TARGET_X86_64
676 if (s->aflag == 2) {
677 if (override >= 0) {
678 gen_op_movq_A0_seg(override);
679 gen_op_addq_A0_reg_sN(0, R_ESI);
680 } else {
681 gen_op_movq_A0_reg(R_ESI);
682 }
683 } else
684 #endif
685 if (s->aflag) {
686 /* 32 bit address */
687 if (s->addseg && override < 0)
688 override = R_DS;
689 if (override >= 0) {
690 gen_op_movl_A0_seg(override);
691 gen_op_addl_A0_reg_sN(0, R_ESI);
692 } else {
693 gen_op_movl_A0_reg(R_ESI);
694 }
695 } else {
696 /* 16 address, always override */
697 if (override < 0)
698 override = R_DS;
699 gen_op_movl_A0_reg(R_ESI);
700 gen_op_andl_A0_ffff();
701 gen_op_addl_A0_seg(s, override);
702 }
703 }
704
705 static inline void gen_string_movl_A0_EDI(DisasContext *s)
706 {
707 #ifdef TARGET_X86_64
708 if (s->aflag == 2) {
709 gen_op_movq_A0_reg(R_EDI);
710 } else
711 #endif
712 if (s->aflag) {
713 if (s->addseg) {
714 gen_op_movl_A0_seg(R_ES);
715 gen_op_addl_A0_reg_sN(0, R_EDI);
716 } else {
717 gen_op_movl_A0_reg(R_EDI);
718 }
719 } else {
720 gen_op_movl_A0_reg(R_EDI);
721 gen_op_andl_A0_ffff();
722 gen_op_addl_A0_seg(s, R_ES);
723 }
724 }
725
726 static inline void gen_op_movl_T0_Dshift(int ot)
727 {
728 tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
729 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
730 };
731
732 static TCGv gen_ext_tl(TCGv dst, TCGv src, int size, bool sign)
733 {
734 switch (size) {
735 case OT_BYTE:
736 if (sign) {
737 tcg_gen_ext8s_tl(dst, src);
738 } else {
739 tcg_gen_ext8u_tl(dst, src);
740 }
741 return dst;
742 case OT_WORD:
743 if (sign) {
744 tcg_gen_ext16s_tl(dst, src);
745 } else {
746 tcg_gen_ext16u_tl(dst, src);
747 }
748 return dst;
749 #ifdef TARGET_X86_64
750 case OT_LONG:
751 if (sign) {
752 tcg_gen_ext32s_tl(dst, src);
753 } else {
754 tcg_gen_ext32u_tl(dst, src);
755 }
756 return dst;
757 #endif
758 default:
759 return src;
760 }
761 }
762
763 static void gen_extu(int ot, TCGv reg)
764 {
765 gen_ext_tl(reg, reg, ot, false);
766 }
767
768 static void gen_exts(int ot, TCGv reg)
769 {
770 gen_ext_tl(reg, reg, ot, true);
771 }
772
773 static inline void gen_op_jnz_ecx(int size, int label1)
774 {
775 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
776 gen_extu(size + 1, cpu_tmp0);
777 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
778 }
779
780 static inline void gen_op_jz_ecx(int size, int label1)
781 {
782 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
783 gen_extu(size + 1, cpu_tmp0);
784 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
785 }
786
787 static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
788 {
789 switch (ot) {
790 case OT_BYTE:
791 gen_helper_inb(v, n);
792 break;
793 case OT_WORD:
794 gen_helper_inw(v, n);
795 break;
796 case OT_LONG:
797 gen_helper_inl(v, n);
798 break;
799 }
800 }
801
802 static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
803 {
804 switch (ot) {
805 case OT_BYTE:
806 gen_helper_outb(v, n);
807 break;
808 case OT_WORD:
809 gen_helper_outw(v, n);
810 break;
811 case OT_LONG:
812 gen_helper_outl(v, n);
813 break;
814 }
815 }
816
817 static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
818 uint32_t svm_flags)
819 {
820 int state_saved;
821 target_ulong next_eip;
822
823 state_saved = 0;
824 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
825 gen_update_cc_op(s);
826 gen_jmp_im(cur_eip);
827 state_saved = 1;
828 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
829 switch (ot) {
830 case OT_BYTE:
831 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
832 break;
833 case OT_WORD:
834 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
835 break;
836 case OT_LONG:
837 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
838 break;
839 }
840 }
841 if(s->flags & HF_SVMI_MASK) {
842 if (!state_saved) {
843 gen_update_cc_op(s);
844 gen_jmp_im(cur_eip);
845 }
846 svm_flags |= (1 << (4 + ot));
847 next_eip = s->pc - s->cs_base;
848 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
849 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
850 tcg_const_i32(svm_flags),
851 tcg_const_i32(next_eip - cur_eip));
852 }
853 }
854
855 static inline void gen_movs(DisasContext *s, int ot)
856 {
857 gen_string_movl_A0_ESI(s);
858 gen_op_ld_T0_A0(ot + s->mem_index);
859 gen_string_movl_A0_EDI(s);
860 gen_op_st_T0_A0(ot + s->mem_index);
861 gen_op_movl_T0_Dshift(ot);
862 gen_op_add_reg_T0(s->aflag, R_ESI);
863 gen_op_add_reg_T0(s->aflag, R_EDI);
864 }
865
866 static void gen_op_update1_cc(void)
867 {
868 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
869 }
870
871 static void gen_op_update2_cc(void)
872 {
873 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
874 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
875 }
876
877 static void gen_op_update3_cc(TCGv reg)
878 {
879 tcg_gen_mov_tl(cpu_cc_src2, reg);
880 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
881 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
882 }
883
884 static inline void gen_op_testl_T0_T1_cc(void)
885 {
886 tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
887 }
888
889 static void gen_op_update_neg_cc(void)
890 {
891 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
892 tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]);
893 tcg_gen_movi_tl(cpu_cc_srcT, 0);
894 }
895
896 /* compute all eflags to cc_src */
897 static void gen_compute_eflags(DisasContext *s)
898 {
899 TCGv zero, dst, src1, src2;
900 int live, dead;
901
902 if (s->cc_op == CC_OP_EFLAGS) {
903 return;
904 }
905
906 TCGV_UNUSED(zero);
907 dst = cpu_cc_dst;
908 src1 = cpu_cc_src;
909 src2 = cpu_cc_src2;
910
911 /* Take care to not read values that are not live. */
912 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
913 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
914 if (dead) {
915 zero = tcg_const_tl(0);
916 if (dead & USES_CC_DST) {
917 dst = zero;
918 }
919 if (dead & USES_CC_SRC) {
920 src1 = zero;
921 }
922 if (dead & USES_CC_SRC2) {
923 src2 = zero;
924 }
925 }
926
927 gen_update_cc_op(s);
928 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
929 set_cc_op(s, CC_OP_EFLAGS);
930
931 if (dead) {
932 tcg_temp_free(zero);
933 }
934 }
935
936 typedef struct CCPrepare {
937 TCGCond cond;
938 TCGv reg;
939 TCGv reg2;
940 target_ulong imm;
941 target_ulong mask;
942 bool use_reg2;
943 bool no_setcond;
944 } CCPrepare;
945
946 /* compute eflags.C to reg */
947 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
948 {
949 TCGv t0, t1;
950 int size, shift;
951
952 switch (s->cc_op) {
953 case CC_OP_SUBB ... CC_OP_SUBQ:
954 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
955 size = s->cc_op - CC_OP_SUBB;
956 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
957 /* If no temporary was used, be careful not to alias t1 and t0. */
958 t0 = TCGV_EQUAL(t1, cpu_cc_src) ? cpu_tmp0 : reg;
959 tcg_gen_mov_tl(t0, cpu_cc_srcT);
960 gen_extu(size, t0);
961 goto add_sub;
962
963 case CC_OP_ADDB ... CC_OP_ADDQ:
964 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
965 size = s->cc_op - CC_OP_ADDB;
966 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
967 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
968 add_sub:
969 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
970 .reg2 = t1, .mask = -1, .use_reg2 = true };
971
972 case CC_OP_LOGICB ... CC_OP_LOGICQ:
973 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
974
975 case CC_OP_INCB ... CC_OP_INCQ:
976 case CC_OP_DECB ... CC_OP_DECQ:
977 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
978 .mask = -1, .no_setcond = true };
979
980 case CC_OP_SHLB ... CC_OP_SHLQ:
981 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
982 size = s->cc_op - CC_OP_SHLB;
983 shift = (8 << size) - 1;
984 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
985 .mask = (target_ulong)1 << shift };
986
987 case CC_OP_MULB ... CC_OP_MULQ:
988 return (CCPrepare) { .cond = TCG_COND_NE,
989 .reg = cpu_cc_src, .mask = -1 };
990
991 case CC_OP_EFLAGS:
992 case CC_OP_SARB ... CC_OP_SARQ:
993 /* CC_SRC & 1 */
994 return (CCPrepare) { .cond = TCG_COND_NE,
995 .reg = cpu_cc_src, .mask = CC_C };
996
997 default:
998 /* The need to compute only C from CC_OP_DYNAMIC is important
999 in efficiently implementing e.g. INC at the start of a TB. */
1000 gen_update_cc_op(s);
1001 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
1002 cpu_cc_src2, cpu_cc_op);
1003 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1004 .mask = -1, .no_setcond = true };
1005 }
1006 }
1007
1008 /* compute eflags.P to reg */
1009 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
1010 {
1011 gen_compute_eflags(s);
1012 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1013 .mask = CC_P };
1014 }
1015
1016 /* compute eflags.S to reg */
1017 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
1018 {
1019 switch (s->cc_op) {
1020 case CC_OP_DYNAMIC:
1021 gen_compute_eflags(s);
1022 /* FALLTHRU */
1023 case CC_OP_EFLAGS:
1024 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1025 .mask = CC_S };
1026 default:
1027 {
1028 int size = (s->cc_op - CC_OP_ADDB) & 3;
1029 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
1030 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
1031 }
1032 }
1033 }
1034
1035 /* compute eflags.O to reg */
1036 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
1037 {
1038 gen_compute_eflags(s);
1039 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1040 .mask = CC_O };
1041 }
1042
1043 /* compute eflags.Z to reg */
1044 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
1045 {
1046 switch (s->cc_op) {
1047 case CC_OP_DYNAMIC:
1048 gen_compute_eflags(s);
1049 /* FALLTHRU */
1050 case CC_OP_EFLAGS:
1051 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1052 .mask = CC_Z };
1053 default:
1054 {
1055 int size = (s->cc_op - CC_OP_ADDB) & 3;
1056 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
1057 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
1058 }
1059 }
1060 }
1061
1062 /* perform a conditional store into register 'reg' according to jump opcode
1063 value 'b'. In the fast case, T0 is guaranted not to be used. */
1064 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
1065 {
1066 int inv, jcc_op, size, cond;
1067 CCPrepare cc;
1068 TCGv t0;
1069
1070 inv = b & 1;
1071 jcc_op = (b >> 1) & 7;
1072
1073 switch (s->cc_op) {
1074 case CC_OP_SUBB ... CC_OP_SUBQ:
1075 /* We optimize relational operators for the cmp/jcc case. */
1076 size = s->cc_op - CC_OP_SUBB;
1077 switch (jcc_op) {
1078 case JCC_BE:
1079 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
1080 gen_extu(size, cpu_tmp4);
1081 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
1082 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
1083 .reg2 = t0, .mask = -1, .use_reg2 = true };
1084 break;
1085
1086 case JCC_L:
1087 cond = TCG_COND_LT;
1088 goto fast_jcc_l;
1089 case JCC_LE:
1090 cond = TCG_COND_LE;
1091 fast_jcc_l:
1092 tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT);
1093 gen_exts(size, cpu_tmp4);
1094 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
1095 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
1096 .reg2 = t0, .mask = -1, .use_reg2 = true };
1097 break;
1098
1099 default:
1100 goto slow_jcc;
1101 }
1102 break;
1103
1104 default:
1105 slow_jcc:
1106 /* This actually generates good code for JC, JZ and JS. */
1107 switch (jcc_op) {
1108 case JCC_O:
1109 cc = gen_prepare_eflags_o(s, reg);
1110 break;
1111 case JCC_B:
1112 cc = gen_prepare_eflags_c(s, reg);
1113 break;
1114 case JCC_Z:
1115 cc = gen_prepare_eflags_z(s, reg);
1116 break;
1117 case JCC_BE:
1118 gen_compute_eflags(s);
1119 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
1120 .mask = CC_Z | CC_C };
1121 break;
1122 case JCC_S:
1123 cc = gen_prepare_eflags_s(s, reg);
1124 break;
1125 case JCC_P:
1126 cc = gen_prepare_eflags_p(s, reg);
1127 break;
1128 case JCC_L:
1129 gen_compute_eflags(s);
1130 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1131 reg = cpu_tmp0;
1132 }
1133 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1134 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1135 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1136 .mask = CC_S };
1137 break;
1138 default:
1139 case JCC_LE:
1140 gen_compute_eflags(s);
1141 if (TCGV_EQUAL(reg, cpu_cc_src)) {
1142 reg = cpu_tmp0;
1143 }
1144 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
1145 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
1146 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
1147 .mask = CC_S | CC_Z };
1148 break;
1149 }
1150 break;
1151 }
1152
1153 if (inv) {
1154 cc.cond = tcg_invert_cond(cc.cond);
1155 }
1156 return cc;
1157 }
1158
1159 static void gen_setcc1(DisasContext *s, int b, TCGv reg)
1160 {
1161 CCPrepare cc = gen_prepare_cc(s, b, reg);
1162
1163 if (cc.no_setcond) {
1164 if (cc.cond == TCG_COND_EQ) {
1165 tcg_gen_xori_tl(reg, cc.reg, 1);
1166 } else {
1167 tcg_gen_mov_tl(reg, cc.reg);
1168 }
1169 return;
1170 }
1171
1172 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1173 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1174 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1175 tcg_gen_andi_tl(reg, reg, 1);
1176 return;
1177 }
1178 if (cc.mask != -1) {
1179 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1180 cc.reg = reg;
1181 }
1182 if (cc.use_reg2) {
1183 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1184 } else {
1185 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1186 }
1187 }
1188
1189 static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1190 {
1191 gen_setcc1(s, JCC_B << 1, reg);
1192 }
1193
1194 /* generate a conditional jump to label 'l1' according to jump opcode
1195 value 'b'. In the fast case, T0 is guaranted not to be used. */
1196 static inline void gen_jcc1_noeob(DisasContext *s, int b, int l1)
1197 {
1198 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1199
1200 if (cc.mask != -1) {
1201 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1202 cc.reg = cpu_T[0];
1203 }
1204 if (cc.use_reg2) {
1205 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1206 } else {
1207 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1208 }
1209 }
1210
1211 /* Generate a conditional jump to label 'l1' according to jump opcode
1212 value 'b'. In the fast case, T0 is guaranted not to be used.
1213 A translation block must end soon. */
1214 static inline void gen_jcc1(DisasContext *s, int b, int l1)
1215 {
1216 CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
1217
1218 gen_update_cc_op(s);
1219 if (cc.mask != -1) {
1220 tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
1221 cc.reg = cpu_T[0];
1222 }
1223 set_cc_op(s, CC_OP_DYNAMIC);
1224 if (cc.use_reg2) {
1225 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1226 } else {
1227 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1228 }
1229 }
1230
1231 /* XXX: does not work with gdbstub "ice" single step - not a
1232 serious problem */
1233 static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1234 {
1235 int l1, l2;
1236
1237 l1 = gen_new_label();
1238 l2 = gen_new_label();
1239 gen_op_jnz_ecx(s->aflag, l1);
1240 gen_set_label(l2);
1241 gen_jmp_tb(s, next_eip, 1);
1242 gen_set_label(l1);
1243 return l2;
1244 }
1245
1246 static inline void gen_stos(DisasContext *s, int ot)
1247 {
1248 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
1249 gen_string_movl_A0_EDI(s);
1250 gen_op_st_T0_A0(ot + s->mem_index);
1251 gen_op_movl_T0_Dshift(ot);
1252 gen_op_add_reg_T0(s->aflag, R_EDI);
1253 }
1254
1255 static inline void gen_lods(DisasContext *s, int ot)
1256 {
1257 gen_string_movl_A0_ESI(s);
1258 gen_op_ld_T0_A0(ot + s->mem_index);
1259 gen_op_mov_reg_T0(ot, R_EAX);
1260 gen_op_movl_T0_Dshift(ot);
1261 gen_op_add_reg_T0(s->aflag, R_ESI);
1262 }
1263
1264 static inline void gen_scas(DisasContext *s, int ot)
1265 {
1266 gen_string_movl_A0_EDI(s);
1267 gen_op_ld_T1_A0(ot + s->mem_index);
1268 gen_op(s, OP_CMPL, ot, R_EAX);
1269 gen_op_movl_T0_Dshift(ot);
1270 gen_op_add_reg_T0(s->aflag, R_EDI);
1271 }
1272
1273 static inline void gen_cmps(DisasContext *s, int ot)
1274 {
1275 gen_string_movl_A0_EDI(s);
1276 gen_op_ld_T1_A0(ot + s->mem_index);
1277 gen_string_movl_A0_ESI(s);
1278 gen_op(s, OP_CMPL, ot, OR_TMP0);
1279 gen_op_movl_T0_Dshift(ot);
1280 gen_op_add_reg_T0(s->aflag, R_ESI);
1281 gen_op_add_reg_T0(s->aflag, R_EDI);
1282 }
1283
1284 static inline void gen_ins(DisasContext *s, int ot)
1285 {
1286 if (use_icount)
1287 gen_io_start();
1288 gen_string_movl_A0_EDI(s);
1289 /* Note: we must do this dummy write first to be restartable in
1290 case of page fault. */
1291 gen_op_movl_T0_0();
1292 gen_op_st_T0_A0(ot + s->mem_index);
1293 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
1294 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1295 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1296 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
1297 gen_op_st_T0_A0(ot + s->mem_index);
1298 gen_op_movl_T0_Dshift(ot);
1299 gen_op_add_reg_T0(s->aflag, R_EDI);
1300 if (use_icount)
1301 gen_io_end();
1302 }
1303
1304 static inline void gen_outs(DisasContext *s, int ot)
1305 {
1306 if (use_icount)
1307 gen_io_start();
1308 gen_string_movl_A0_ESI(s);
1309 gen_op_ld_T0_A0(ot + s->mem_index);
1310
1311 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
1312 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1313 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1314 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
1315 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1316
1317 gen_op_movl_T0_Dshift(ot);
1318 gen_op_add_reg_T0(s->aflag, R_ESI);
1319 if (use_icount)
1320 gen_io_end();
1321 }
1322
1323 /* same method as Valgrind : we generate jumps to current or next
1324 instruction */
1325 #define GEN_REPZ(op) \
1326 static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1327 target_ulong cur_eip, target_ulong next_eip) \
1328 { \
1329 int l2;\
1330 gen_update_cc_op(s); \
1331 l2 = gen_jz_ecx_string(s, next_eip); \
1332 gen_ ## op(s, ot); \
1333 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1334 /* a loop would cause two single step exceptions if ECX = 1 \
1335 before rep string_insn */ \
1336 if (!s->jmp_opt) \
1337 gen_op_jz_ecx(s->aflag, l2); \
1338 gen_jmp(s, cur_eip); \
1339 }
1340
1341 #define GEN_REPZ2(op) \
1342 static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1343 target_ulong cur_eip, \
1344 target_ulong next_eip, \
1345 int nz) \
1346 { \
1347 int l2;\
1348 gen_update_cc_op(s); \
1349 l2 = gen_jz_ecx_string(s, next_eip); \
1350 gen_ ## op(s, ot); \
1351 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1352 gen_update_cc_op(s); \
1353 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
1354 if (!s->jmp_opt) \
1355 gen_op_jz_ecx(s->aflag, l2); \
1356 gen_jmp(s, cur_eip); \
1357 }
1358
1359 GEN_REPZ(movs)
1360 GEN_REPZ(stos)
1361 GEN_REPZ(lods)
1362 GEN_REPZ(ins)
1363 GEN_REPZ(outs)
1364 GEN_REPZ2(scas)
1365 GEN_REPZ2(cmps)
1366
1367 static void gen_helper_fp_arith_ST0_FT0(int op)
1368 {
1369 switch (op) {
1370 case 0:
1371 gen_helper_fadd_ST0_FT0(cpu_env);
1372 break;
1373 case 1:
1374 gen_helper_fmul_ST0_FT0(cpu_env);
1375 break;
1376 case 2:
1377 gen_helper_fcom_ST0_FT0(cpu_env);
1378 break;
1379 case 3:
1380 gen_helper_fcom_ST0_FT0(cpu_env);
1381 break;
1382 case 4:
1383 gen_helper_fsub_ST0_FT0(cpu_env);
1384 break;
1385 case 5:
1386 gen_helper_fsubr_ST0_FT0(cpu_env);
1387 break;
1388 case 6:
1389 gen_helper_fdiv_ST0_FT0(cpu_env);
1390 break;
1391 case 7:
1392 gen_helper_fdivr_ST0_FT0(cpu_env);
1393 break;
1394 }
1395 }
1396
1397 /* NOTE the exception in "r" op ordering */
1398 static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1399 {
1400 TCGv_i32 tmp = tcg_const_i32(opreg);
1401 switch (op) {
1402 case 0:
1403 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1404 break;
1405 case 1:
1406 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1407 break;
1408 case 4:
1409 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1410 break;
1411 case 5:
1412 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1413 break;
1414 case 6:
1415 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1416 break;
1417 case 7:
1418 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1419 break;
1420 }
1421 }
1422
1423 /* if d == OR_TMP0, it means memory operand (address in A0) */
1424 static void gen_op(DisasContext *s1, int op, int ot, int d)
1425 {
1426 if (d != OR_TMP0) {
1427 gen_op_mov_TN_reg(ot, 0, d);
1428 } else {
1429 gen_op_ld_T0_A0(ot + s1->mem_index);
1430 }
1431 switch(op) {
1432 case OP_ADCL:
1433 gen_compute_eflags_c(s1, cpu_tmp4);
1434 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1435 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1436 if (d != OR_TMP0)
1437 gen_op_mov_reg_T0(ot, d);
1438 else
1439 gen_op_st_T0_A0(ot + s1->mem_index);
1440 gen_op_update3_cc(cpu_tmp4);
1441 set_cc_op(s1, CC_OP_ADCB + ot);
1442 break;
1443 case OP_SBBL:
1444 gen_compute_eflags_c(s1, cpu_tmp4);
1445 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1446 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1447 if (d != OR_TMP0)
1448 gen_op_mov_reg_T0(ot, d);
1449 else
1450 gen_op_st_T0_A0(ot + s1->mem_index);
1451 gen_op_update3_cc(cpu_tmp4);
1452 set_cc_op(s1, CC_OP_SBBB + ot);
1453 break;
1454 case OP_ADDL:
1455 gen_op_addl_T0_T1();
1456 if (d != OR_TMP0)
1457 gen_op_mov_reg_T0(ot, d);
1458 else
1459 gen_op_st_T0_A0(ot + s1->mem_index);
1460 gen_op_update2_cc();
1461 set_cc_op(s1, CC_OP_ADDB + ot);
1462 break;
1463 case OP_SUBL:
1464 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1465 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1466 if (d != OR_TMP0)
1467 gen_op_mov_reg_T0(ot, d);
1468 else
1469 gen_op_st_T0_A0(ot + s1->mem_index);
1470 gen_op_update2_cc();
1471 set_cc_op(s1, CC_OP_SUBB + ot);
1472 break;
1473 default:
1474 case OP_ANDL:
1475 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1476 if (d != OR_TMP0)
1477 gen_op_mov_reg_T0(ot, d);
1478 else
1479 gen_op_st_T0_A0(ot + s1->mem_index);
1480 gen_op_update1_cc();
1481 set_cc_op(s1, CC_OP_LOGICB + ot);
1482 break;
1483 case OP_ORL:
1484 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1485 if (d != OR_TMP0)
1486 gen_op_mov_reg_T0(ot, d);
1487 else
1488 gen_op_st_T0_A0(ot + s1->mem_index);
1489 gen_op_update1_cc();
1490 set_cc_op(s1, CC_OP_LOGICB + ot);
1491 break;
1492 case OP_XORL:
1493 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1494 if (d != OR_TMP0)
1495 gen_op_mov_reg_T0(ot, d);
1496 else
1497 gen_op_st_T0_A0(ot + s1->mem_index);
1498 gen_op_update1_cc();
1499 set_cc_op(s1, CC_OP_LOGICB + ot);
1500 break;
1501 case OP_CMPL:
1502 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
1503 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
1504 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
1505 set_cc_op(s1, CC_OP_SUBB + ot);
1506 break;
1507 }
1508 }
1509
1510 /* if d == OR_TMP0, it means memory operand (address in A0) */
1511 static void gen_inc(DisasContext *s1, int ot, int d, int c)
1512 {
1513 if (d != OR_TMP0)
1514 gen_op_mov_TN_reg(ot, 0, d);
1515 else
1516 gen_op_ld_T0_A0(ot + s1->mem_index);
1517 gen_compute_eflags_c(s1, cpu_cc_src);
1518 if (c > 0) {
1519 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
1520 set_cc_op(s1, CC_OP_INCB + ot);
1521 } else {
1522 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
1523 set_cc_op(s1, CC_OP_DECB + ot);
1524 }
1525 if (d != OR_TMP0)
1526 gen_op_mov_reg_T0(ot, d);
1527 else
1528 gen_op_st_T0_A0(ot + s1->mem_index);
1529 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1530 }
1531
1532 static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
1533 int is_right, int is_arith)
1534 {
1535 target_ulong mask;
1536 int shift_label;
1537 TCGv t0, t1, t2;
1538
1539 if (ot == OT_QUAD) {
1540 mask = 0x3f;
1541 } else {
1542 mask = 0x1f;
1543 }
1544
1545 /* load */
1546 if (op1 == OR_TMP0) {
1547 gen_op_ld_T0_A0(ot + s->mem_index);
1548 } else {
1549 gen_op_mov_TN_reg(ot, 0, op1);
1550 }
1551
1552 t0 = tcg_temp_local_new();
1553 t1 = tcg_temp_local_new();
1554 t2 = tcg_temp_local_new();
1555
1556 tcg_gen_andi_tl(t2, cpu_T[1], mask);
1557
1558 if (is_right) {
1559 if (is_arith) {
1560 gen_exts(ot, cpu_T[0]);
1561 tcg_gen_mov_tl(t0, cpu_T[0]);
1562 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], t2);
1563 } else {
1564 gen_extu(ot, cpu_T[0]);
1565 tcg_gen_mov_tl(t0, cpu_T[0]);
1566 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], t2);
1567 }
1568 } else {
1569 tcg_gen_mov_tl(t0, cpu_T[0]);
1570 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], t2);
1571 }
1572
1573 /* store */
1574 if (op1 == OR_TMP0) {
1575 gen_op_st_T0_A0(ot + s->mem_index);
1576 } else {
1577 gen_op_mov_reg_T0(ot, op1);
1578 }
1579
1580 /* Update eflags data because we cannot predict flags afterward. */
1581 gen_update_cc_op(s);
1582 set_cc_op(s, CC_OP_DYNAMIC);
1583
1584 tcg_gen_mov_tl(t1, cpu_T[0]);
1585
1586 shift_label = gen_new_label();
1587 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, shift_label);
1588
1589 tcg_gen_addi_tl(t2, t2, -1);
1590 tcg_gen_mov_tl(cpu_cc_dst, t1);
1591
1592 if (is_right) {
1593 if (is_arith) {
1594 tcg_gen_sar_tl(cpu_cc_src, t0, t2);
1595 } else {
1596 tcg_gen_shr_tl(cpu_cc_src, t0, t2);
1597 }
1598 } else {
1599 tcg_gen_shl_tl(cpu_cc_src, t0, t2);
1600 }
1601
1602 if (is_right) {
1603 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot);
1604 } else {
1605 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot);
1606 }
1607
1608 gen_set_label(shift_label);
1609
1610 tcg_temp_free(t0);
1611 tcg_temp_free(t1);
1612 tcg_temp_free(t2);
1613 }
1614
1615 static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
1616 int is_right, int is_arith)
1617 {
1618 int mask;
1619
1620 if (ot == OT_QUAD)
1621 mask = 0x3f;
1622 else
1623 mask = 0x1f;
1624
1625 /* load */
1626 if (op1 == OR_TMP0)
1627 gen_op_ld_T0_A0(ot + s->mem_index);
1628 else
1629 gen_op_mov_TN_reg(ot, 0, op1);
1630
1631 op2 &= mask;
1632 if (op2 != 0) {
1633 if (is_right) {
1634 if (is_arith) {
1635 gen_exts(ot, cpu_T[0]);
1636 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1637 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
1638 } else {
1639 gen_extu(ot, cpu_T[0]);
1640 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1641 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
1642 }
1643 } else {
1644 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1645 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
1646 }
1647 }
1648
1649 /* store */
1650 if (op1 == OR_TMP0)
1651 gen_op_st_T0_A0(ot + s->mem_index);
1652 else
1653 gen_op_mov_reg_T0(ot, op1);
1654
1655 /* update eflags if non zero shift */
1656 if (op2 != 0) {
1657 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1658 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1659 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1660 }
1661 }
1662
1663 static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2)
1664 {
1665 if (arg2 >= 0)
1666 tcg_gen_shli_tl(ret, arg1, arg2);
1667 else
1668 tcg_gen_shri_tl(ret, arg1, -arg2);
1669 }
1670
1671 static void gen_rot_rm_T1(DisasContext *s, int ot, int op1,
1672 int is_right)
1673 {
1674 target_ulong mask;
1675 int label1, label2, data_bits;
1676 TCGv t0, t1, t2, a0;
1677
1678 /* XXX: inefficient, but we must use local temps */
1679 t0 = tcg_temp_local_new();
1680 t1 = tcg_temp_local_new();
1681 t2 = tcg_temp_local_new();
1682 a0 = tcg_temp_local_new();
1683
1684 if (ot == OT_QUAD)
1685 mask = 0x3f;
1686 else
1687 mask = 0x1f;
1688
1689 /* load */
1690 if (op1 == OR_TMP0) {
1691 tcg_gen_mov_tl(a0, cpu_A0);
1692 gen_op_ld_v(ot + s->mem_index, t0, a0);
1693 } else {
1694 gen_op_mov_v_reg(ot, t0, op1);
1695 }
1696
1697 tcg_gen_mov_tl(t1, cpu_T[1]);
1698
1699 tcg_gen_andi_tl(t1, t1, mask);
1700
1701 /* Must test zero case to avoid using undefined behaviour in TCG
1702 shifts. */
1703 label1 = gen_new_label();
1704 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label1);
1705
1706 if (ot <= OT_WORD)
1707 tcg_gen_andi_tl(cpu_tmp0, t1, (1 << (3 + ot)) - 1);
1708 else
1709 tcg_gen_mov_tl(cpu_tmp0, t1);
1710
1711 gen_extu(ot, t0);
1712 tcg_gen_mov_tl(t2, t0);
1713
1714 data_bits = 8 << ot;
1715 /* XXX: rely on behaviour of shifts when operand 2 overflows (XXX:
1716 fix TCG definition) */
1717 if (is_right) {
1718 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp0);
1719 tcg_gen_subfi_tl(cpu_tmp0, data_bits, cpu_tmp0);
1720 tcg_gen_shl_tl(t0, t0, cpu_tmp0);
1721 } else {
1722 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp0);
1723 tcg_gen_subfi_tl(cpu_tmp0, data_bits, cpu_tmp0);
1724 tcg_gen_shr_tl(t0, t0, cpu_tmp0);
1725 }
1726 tcg_gen_or_tl(t0, t0, cpu_tmp4);
1727
1728 gen_set_label(label1);
1729 /* store */
1730 if (op1 == OR_TMP0) {
1731 gen_op_st_v(ot + s->mem_index, t0, a0);
1732 } else {
1733 gen_op_mov_reg_v(ot, op1, t0);
1734 }
1735
1736 /* update eflags. It is needed anyway most of the time, do it always. */
1737 gen_compute_eflags(s);
1738 assert(s->cc_op == CC_OP_EFLAGS);
1739
1740 label2 = gen_new_label();
1741 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label2);
1742
1743 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C));
1744 tcg_gen_xor_tl(cpu_tmp0, t2, t0);
1745 tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1));
1746 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O);
1747 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);
1748 if (is_right) {
1749 tcg_gen_shri_tl(t0, t0, data_bits - 1);
1750 }
1751 tcg_gen_andi_tl(t0, t0, CC_C);
1752 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
1753
1754 gen_set_label(label2);
1755
1756 tcg_temp_free(t0);
1757 tcg_temp_free(t1);
1758 tcg_temp_free(t2);
1759 tcg_temp_free(a0);
1760 }
1761
1762 static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
1763 int is_right)
1764 {
1765 int mask;
1766 int data_bits;
1767 TCGv t0, t1, a0;
1768
1769 /* XXX: inefficient, but we must use local temps */
1770 t0 = tcg_temp_local_new();
1771 t1 = tcg_temp_local_new();
1772 a0 = tcg_temp_local_new();
1773
1774 if (ot == OT_QUAD)
1775 mask = 0x3f;
1776 else
1777 mask = 0x1f;
1778
1779 /* load */
1780 if (op1 == OR_TMP0) {
1781 tcg_gen_mov_tl(a0, cpu_A0);
1782 gen_op_ld_v(ot + s->mem_index, t0, a0);
1783 } else {
1784 gen_op_mov_v_reg(ot, t0, op1);
1785 }
1786
1787 gen_extu(ot, t0);
1788 tcg_gen_mov_tl(t1, t0);
1789
1790 op2 &= mask;
1791 data_bits = 8 << ot;
1792 if (op2 != 0) {
1793 int shift = op2 & ((1 << (3 + ot)) - 1);
1794 if (is_right) {
1795 tcg_gen_shri_tl(cpu_tmp4, t0, shift);
1796 tcg_gen_shli_tl(t0, t0, data_bits - shift);
1797 }
1798 else {
1799 tcg_gen_shli_tl(cpu_tmp4, t0, shift);
1800 tcg_gen_shri_tl(t0, t0, data_bits - shift);
1801 }
1802 tcg_gen_or_tl(t0, t0, cpu_tmp4);
1803 }
1804
1805 /* store */
1806 if (op1 == OR_TMP0) {
1807 gen_op_st_v(ot + s->mem_index, t0, a0);
1808 } else {
1809 gen_op_mov_reg_v(ot, op1, t0);
1810 }
1811
1812 if (op2 != 0) {
1813 /* update eflags */
1814 gen_compute_eflags(s);
1815 assert(s->cc_op == CC_OP_EFLAGS);
1816
1817 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C));
1818 tcg_gen_xor_tl(cpu_tmp0, t1, t0);
1819 tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1));
1820 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O);
1821 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);
1822 if (is_right) {
1823 tcg_gen_shri_tl(t0, t0, data_bits - 1);
1824 }
1825 tcg_gen_andi_tl(t0, t0, CC_C);
1826 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
1827 }
1828
1829 tcg_temp_free(t0);
1830 tcg_temp_free(t1);
1831 tcg_temp_free(a0);
1832 }
1833
1834 /* XXX: add faster immediate = 1 case */
1835 static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
1836 int is_right)
1837 {
1838 gen_compute_eflags(s);
1839 assert(s->cc_op == CC_OP_EFLAGS);
1840
1841 /* load */
1842 if (op1 == OR_TMP0)
1843 gen_op_ld_T0_A0(ot + s->mem_index);
1844 else
1845 gen_op_mov_TN_reg(ot, 0, op1);
1846
1847 if (is_right) {
1848 switch (ot) {
1849 case OT_BYTE:
1850 gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1851 break;
1852 case OT_WORD:
1853 gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1854 break;
1855 case OT_LONG:
1856 gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1857 break;
1858 #ifdef TARGET_X86_64
1859 case OT_QUAD:
1860 gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1861 break;
1862 #endif
1863 }
1864 } else {
1865 switch (ot) {
1866 case OT_BYTE:
1867 gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1868 break;
1869 case OT_WORD:
1870 gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1871 break;
1872 case OT_LONG:
1873 gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1874 break;
1875 #ifdef TARGET_X86_64
1876 case OT_QUAD:
1877 gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1878 break;
1879 #endif
1880 }
1881 }
1882 /* store */
1883 if (op1 == OR_TMP0)
1884 gen_op_st_T0_A0(ot + s->mem_index);
1885 else
1886 gen_op_mov_reg_T0(ot, op1);
1887 }
1888
1889 /* XXX: add faster immediate case */
1890 static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
1891 int is_right, TCGv count)
1892 {
1893 int label1, label2, data_bits;
1894 target_ulong mask;
1895 TCGv t0, t1, t2, a0;
1896
1897 t0 = tcg_temp_local_new();
1898 t1 = tcg_temp_local_new();
1899 t2 = tcg_temp_local_new();
1900 a0 = tcg_temp_local_new();
1901
1902 if (ot == OT_QUAD)
1903 mask = 0x3f;
1904 else
1905 mask = 0x1f;
1906
1907 /* load */
1908 if (op1 == OR_TMP0) {
1909 tcg_gen_mov_tl(a0, cpu_A0);
1910 gen_op_ld_v(ot + s->mem_index, t0, a0);
1911 } else {
1912 gen_op_mov_v_reg(ot, t0, op1);
1913 }
1914
1915 tcg_gen_andi_tl(t2, count, mask);
1916 tcg_gen_mov_tl(t1, cpu_T[1]);
1917
1918 /* Must test zero case to avoid using undefined behaviour in TCG
1919 shifts. */
1920 label1 = gen_new_label();
1921 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
1922
1923 tcg_gen_addi_tl(cpu_tmp5, t2, -1);
1924 if (ot == OT_WORD) {
1925 /* Note: we implement the Intel behaviour for shift count > 16 */
1926 if (is_right) {
1927 tcg_gen_andi_tl(t0, t0, 0xffff);
1928 tcg_gen_shli_tl(cpu_tmp0, t1, 16);
1929 tcg_gen_or_tl(t0, t0, cpu_tmp0);
1930 tcg_gen_ext32u_tl(t0, t0);
1931
1932 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5);
1933
1934 /* only needed if count > 16, but a test would complicate */
1935 tcg_gen_subfi_tl(cpu_tmp5, 32, t2);
1936 tcg_gen_shl_tl(cpu_tmp0, t0, cpu_tmp5);
1937
1938 tcg_gen_shr_tl(t0, t0, t2);
1939
1940 tcg_gen_or_tl(t0, t0, cpu_tmp0);
1941 } else {
1942 /* XXX: not optimal */
1943 tcg_gen_andi_tl(t0, t0, 0xffff);
1944 tcg_gen_shli_tl(t1, t1, 16);
1945 tcg_gen_or_tl(t1, t1, t0);
1946 tcg_gen_ext32u_tl(t1, t1);
1947
1948 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5);
1949 tcg_gen_subfi_tl(cpu_tmp0, 32, cpu_tmp5);
1950 tcg_gen_shr_tl(cpu_tmp5, t1, cpu_tmp0);
1951 tcg_gen_or_tl(cpu_tmp4, cpu_tmp4, cpu_tmp5);
1952
1953 tcg_gen_shl_tl(t0, t0, t2);
1954 tcg_gen_subfi_tl(cpu_tmp5, 32, t2);
1955 tcg_gen_shr_tl(t1, t1, cpu_tmp5);
1956 tcg_gen_or_tl(t0, t0, t1);
1957 }
1958 } else {
1959 data_bits = 8 << ot;
1960 if (is_right) {
1961 if (ot == OT_LONG)
1962 tcg_gen_ext32u_tl(t0, t0);
1963
1964 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5);
1965
1966 tcg_gen_shr_tl(t0, t0, t2);
1967 tcg_gen_subfi_tl(cpu_tmp5, data_bits, t2);
1968 tcg_gen_shl_tl(t1, t1, cpu_tmp5);
1969 tcg_gen_or_tl(t0, t0, t1);
1970
1971 } else {
1972 if (ot == OT_LONG)
1973 tcg_gen_ext32u_tl(t1, t1);
1974
1975 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5);
1976
1977 tcg_gen_shl_tl(t0, t0, t2);
1978 tcg_gen_subfi_tl(cpu_tmp5, data_bits, t2);
1979 tcg_gen_shr_tl(t1, t1, cpu_tmp5);
1980 tcg_gen_or_tl(t0, t0, t1);
1981 }
1982 }
1983 tcg_gen_mov_tl(t1, cpu_tmp4);
1984
1985 gen_set_label(label1);
1986 /* store */
1987 if (op1 == OR_TMP0) {
1988 gen_op_st_v(ot + s->mem_index, t0, a0);
1989 } else {
1990 gen_op_mov_reg_v(ot, op1, t0);
1991 }
1992
1993 /* Update eflags data because we cannot predict flags afterward. */
1994 gen_update_cc_op(s);
1995 set_cc_op(s, CC_OP_DYNAMIC);
1996
1997 label2 = gen_new_label();
1998 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label2);
1999
2000 tcg_gen_mov_tl(cpu_cc_src, t1);
2001 tcg_gen_mov_tl(cpu_cc_dst, t0);
2002 if (is_right) {
2003 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot);
2004 } else {
2005 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot);
2006 }
2007 gen_set_label(label2);
2008
2009 tcg_temp_free(t0);
2010 tcg_temp_free(t1);
2011 tcg_temp_free(t2);
2012 tcg_temp_free(a0);
2013 }
2014
2015 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
2016 {
2017 if (s != OR_TMP1)
2018 gen_op_mov_TN_reg(ot, 1, s);
2019 switch(op) {
2020 case OP_ROL:
2021 gen_rot_rm_T1(s1, ot, d, 0);
2022 break;
2023 case OP_ROR:
2024 gen_rot_rm_T1(s1, ot, d, 1);
2025 break;
2026 case OP_SHL:
2027 case OP_SHL1:
2028 gen_shift_rm_T1(s1, ot, d, 0, 0);
2029 break;
2030 case OP_SHR:
2031 gen_shift_rm_T1(s1, ot, d, 1, 0);
2032 break;
2033 case OP_SAR:
2034 gen_shift_rm_T1(s1, ot, d, 1, 1);
2035 break;
2036 case OP_RCL:
2037 gen_rotc_rm_T1(s1, ot, d, 0);
2038 break;
2039 case OP_RCR:
2040 gen_rotc_rm_T1(s1, ot, d, 1);
2041 break;
2042 }
2043 }
2044
2045 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
2046 {
2047 switch(op) {
2048 case OP_ROL:
2049 gen_rot_rm_im(s1, ot, d, c, 0);
2050 break;
2051 case OP_ROR:
2052 gen_rot_rm_im(s1, ot, d, c, 1);
2053 break;
2054 case OP_SHL:
2055 case OP_SHL1:
2056 gen_shift_rm_im(s1, ot, d, c, 0, 0);
2057 break;
2058 case OP_SHR:
2059 gen_shift_rm_im(s1, ot, d, c, 1, 0);
2060 break;
2061 case OP_SAR:
2062 gen_shift_rm_im(s1, ot, d, c, 1, 1);
2063 break;
2064 default:
2065 /* currently not optimized */
2066 gen_op_movl_T1_im(c);
2067 gen_shift(s1, op, ot, d, OR_TMP1);
2068 break;
2069 }
2070 }
2071
2072 static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm,
2073 int *reg_ptr, int *offset_ptr)
2074 {
2075 target_long disp;
2076 int havesib;
2077 int base;
2078 int index;
2079 int scale;
2080 int opreg;
2081 int mod, rm, code, override, must_add_seg;
2082
2083 override = s->override;
2084 must_add_seg = s->addseg;
2085 if (override >= 0)
2086 must_add_seg = 1;
2087 mod = (modrm >> 6) & 3;
2088 rm = modrm & 7;
2089
2090 if (s->aflag) {
2091
2092 havesib = 0;
2093 base = rm;
2094 index = 0;
2095 scale = 0;
2096
2097 if (base == 4) {
2098 havesib = 1;
2099 code = cpu_ldub_code(env, s->pc++);
2100 scale = (code >> 6) & 3;
2101 index = ((code >> 3) & 7) | REX_X(s);
2102 base = (code & 7);
2103 }
2104 base |= REX_B(s);
2105
2106 switch (mod) {
2107 case 0:
2108 if ((base & 7) == 5) {
2109 base = -1;
2110 disp = (int32_t)cpu_ldl_code(env, s->pc);
2111 s->pc += 4;
2112 if (CODE64(s) && !havesib) {
2113 disp += s->pc + s->rip_offset;
2114 }
2115 } else {
2116 disp = 0;
2117 }
2118 break;
2119 case 1:
2120 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2121 break;
2122 default:
2123 case 2:
2124 disp = (int32_t)cpu_ldl_code(env, s->pc);
2125 s->pc += 4;
2126 break;
2127 }
2128
2129 if (base >= 0) {
2130 /* for correct popl handling with esp */
2131 if (base == 4 && s->popl_esp_hack)
2132 disp += s->popl_esp_hack;
2133 #ifdef TARGET_X86_64
2134 if (s->aflag == 2) {
2135 gen_op_movq_A0_reg(base);
2136 if (disp != 0) {
2137 gen_op_addq_A0_im(disp);
2138 }
2139 } else
2140 #endif
2141 {
2142 gen_op_movl_A0_reg(base);
2143 if (disp != 0)
2144 gen_op_addl_A0_im(disp);
2145 }
2146 } else {
2147 #ifdef TARGET_X86_64
2148 if (s->aflag == 2) {
2149 gen_op_movq_A0_im(disp);
2150 } else
2151 #endif
2152 {
2153 gen_op_movl_A0_im(disp);
2154 }
2155 }
2156 /* index == 4 means no index */
2157 if (havesib && (index != 4)) {
2158 #ifdef TARGET_X86_64
2159 if (s->aflag == 2) {
2160 gen_op_addq_A0_reg_sN(scale, index);
2161 } else
2162 #endif
2163 {
2164 gen_op_addl_A0_reg_sN(scale, index);
2165 }
2166 }
2167 if (must_add_seg) {
2168 if (override < 0) {
2169 if (base == R_EBP || base == R_ESP)
2170 override = R_SS;
2171 else
2172 override = R_DS;
2173 }
2174 #ifdef TARGET_X86_64
2175 if (s->aflag == 2) {
2176 gen_op_addq_A0_seg(override);
2177 } else
2178 #endif
2179 {
2180 gen_op_addl_A0_seg(s, override);
2181 }
2182 }
2183 } else {
2184 switch (mod) {
2185 case 0:
2186 if (rm == 6) {
2187 disp = cpu_lduw_code(env, s->pc);
2188 s->pc += 2;
2189 gen_op_movl_A0_im(disp);
2190 rm = 0; /* avoid SS override */
2191 goto no_rm;
2192 } else {
2193 disp = 0;
2194 }
2195 break;
2196 case 1:
2197 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2198 break;
2199 default:
2200 case 2:
2201 disp = cpu_lduw_code(env, s->pc);
2202 s->pc += 2;
2203 break;
2204 }
2205 switch(rm) {
2206 case 0:
2207 gen_op_movl_A0_reg(R_EBX);
2208 gen_op_addl_A0_reg_sN(0, R_ESI);
2209 break;
2210 case 1:
2211 gen_op_movl_A0_reg(R_EBX);
2212 gen_op_addl_A0_reg_sN(0, R_EDI);
2213 break;
2214 case 2:
2215 gen_op_movl_A0_reg(R_EBP);
2216 gen_op_addl_A0_reg_sN(0, R_ESI);
2217 break;
2218 case 3:
2219 gen_op_movl_A0_reg(R_EBP);
2220 gen_op_addl_A0_reg_sN(0, R_EDI);
2221 break;
2222 case 4:
2223 gen_op_movl_A0_reg(R_ESI);
2224 break;
2225 case 5:
2226 gen_op_movl_A0_reg(R_EDI);
2227 break;
2228 case 6:
2229 gen_op_movl_A0_reg(R_EBP);
2230 break;
2231 default:
2232 case 7:
2233 gen_op_movl_A0_reg(R_EBX);
2234 break;
2235 }
2236 if (disp != 0)
2237 gen_op_addl_A0_im(disp);
2238 gen_op_andl_A0_ffff();
2239 no_rm:
2240 if (must_add_seg) {
2241 if (override < 0) {
2242 if (rm == 2 || rm == 3 || rm == 6)
2243 override = R_SS;
2244 else
2245 override = R_DS;
2246 }
2247 gen_op_addl_A0_seg(s, override);
2248 }
2249 }
2250
2251 opreg = OR_A0;
2252 disp = 0;
2253 *reg_ptr = opreg;
2254 *offset_ptr = disp;
2255 }
2256
2257 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2258 {
2259 int mod, rm, base, code;
2260
2261 mod = (modrm >> 6) & 3;
2262 if (mod == 3)
2263 return;
2264 rm = modrm & 7;
2265
2266 if (s->aflag) {
2267
2268 base = rm;
2269
2270 if (base == 4) {
2271 code = cpu_ldub_code(env, s->pc++);
2272 base = (code & 7);
2273 }
2274
2275 switch (mod) {
2276 case 0:
2277 if (base == 5) {
2278 s->pc += 4;
2279 }
2280 break;
2281 case 1:
2282 s->pc++;
2283 break;
2284 default:
2285 case 2:
2286 s->pc += 4;
2287 break;
2288 }
2289 } else {
2290 switch (mod) {
2291 case 0:
2292 if (rm == 6) {
2293 s->pc += 2;
2294 }
2295 break;
2296 case 1:
2297 s->pc++;
2298 break;
2299 default:
2300 case 2:
2301 s->pc += 2;
2302 break;
2303 }
2304 }
2305 }
2306
2307 /* used for LEA and MOV AX, mem */
2308 static void gen_add_A0_ds_seg(DisasContext *s)
2309 {
2310 int override, must_add_seg;
2311 must_add_seg = s->addseg;
2312 override = R_DS;
2313 if (s->override >= 0) {
2314 override = s->override;
2315 must_add_seg = 1;
2316 }
2317 if (must_add_seg) {
2318 #ifdef TARGET_X86_64
2319 if (CODE64(s)) {
2320 gen_op_addq_A0_seg(override);
2321 } else
2322 #endif
2323 {
2324 gen_op_addl_A0_seg(s, override);
2325 }
2326 }
2327 }
2328
2329 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2330 OR_TMP0 */
2331 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
2332 int ot, int reg, int is_store)
2333 {
2334 int mod, rm, opreg, disp;
2335
2336 mod = (modrm >> 6) & 3;
2337 rm = (modrm & 7) | REX_B(s);
2338 if (mod == 3) {
2339 if (is_store) {
2340 if (reg != OR_TMP0)
2341 gen_op_mov_TN_reg(ot, 0, reg);
2342 gen_op_mov_reg_T0(ot, rm);
2343 } else {
2344 gen_op_mov_TN_reg(ot, 0, rm);
2345 if (reg != OR_TMP0)
2346 gen_op_mov_reg_T0(ot, reg);
2347 }
2348 } else {
2349 gen_lea_modrm(env, s, modrm, &opreg, &disp);
2350 if (is_store) {
2351 if (reg != OR_TMP0)
2352 gen_op_mov_TN_reg(ot, 0, reg);
2353 gen_op_st_T0_A0(ot + s->mem_index);
2354 } else {
2355 gen_op_ld_T0_A0(ot + s->mem_index);
2356 if (reg != OR_TMP0)
2357 gen_op_mov_reg_T0(ot, reg);
2358 }
2359 }
2360 }
2361
2362 static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
2363 {
2364 uint32_t ret;
2365
2366 switch(ot) {
2367 case OT_BYTE:
2368 ret = cpu_ldub_code(env, s->pc);
2369 s->pc++;
2370 break;
2371 case OT_WORD:
2372 ret = cpu_lduw_code(env, s->pc);
2373 s->pc += 2;
2374 break;
2375 default:
2376 case OT_LONG:
2377 ret = cpu_ldl_code(env, s->pc);
2378 s->pc += 4;
2379 break;
2380 }
2381 return ret;
2382 }
2383
2384 static inline int insn_const_size(unsigned int ot)
2385 {
2386 if (ot <= OT_LONG)
2387 return 1 << ot;
2388 else
2389 return 4;
2390 }
2391
2392 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2393 {
2394 TranslationBlock *tb;
2395 target_ulong pc;
2396
2397 pc = s->cs_base + eip;
2398 tb = s->tb;
2399 /* NOTE: we handle the case where the TB spans two pages here */
2400 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2401 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2402 /* jump to same page: we can use a direct jump */
2403 tcg_gen_goto_tb(tb_num);
2404 gen_jmp_im(eip);
2405 tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
2406 } else {
2407 /* jump to another page: currently not optimized */
2408 gen_jmp_im(eip);
2409 gen_eob(s);
2410 }
2411 }
2412
2413 static inline void gen_jcc(DisasContext *s, int b,
2414 target_ulong val, target_ulong next_eip)
2415 {
2416 int l1, l2;
2417
2418 if (s->jmp_opt) {
2419 l1 = gen_new_label();
2420 gen_jcc1(s, b, l1);
2421
2422 gen_goto_tb(s, 0, next_eip);
2423
2424 gen_set_label(l1);
2425 gen_goto_tb(s, 1, val);
2426 s->is_jmp = DISAS_TB_JUMP;
2427 } else {
2428 l1 = gen_new_label();
2429 l2 = gen_new_label();
2430 gen_jcc1(s, b, l1);
2431
2432 gen_jmp_im(next_eip);
2433 tcg_gen_br(l2);
2434
2435 gen_set_label(l1);
2436 gen_jmp_im(val);
2437 gen_set_label(l2);
2438 gen_eob(s);
2439 }
2440 }
2441
2442 static void gen_cmovcc1(CPUX86State *env, DisasContext *s, int ot, int b,
2443 int modrm, int reg)
2444 {
2445 CCPrepare cc;
2446
2447 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2448
2449 cc = gen_prepare_cc(s, b, cpu_T[1]);
2450 if (cc.mask != -1) {
2451 TCGv t0 = tcg_temp_new();
2452 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2453 cc.reg = t0;
2454 }
2455 if (!cc.use_reg2) {
2456 cc.reg2 = tcg_const_tl(cc.imm);
2457 }
2458
2459 tcg_gen_movcond_tl(cc.cond, cpu_T[0], cc.reg, cc.reg2,
2460 cpu_T[0], cpu_regs[reg]);
2461 gen_op_mov_reg_T0(ot, reg);
2462
2463 if (cc.mask != -1) {
2464 tcg_temp_free(cc.reg);
2465 }
2466 if (!cc.use_reg2) {
2467 tcg_temp_free(cc.reg2);
2468 }
2469 }
2470
2471 static inline void gen_op_movl_T0_seg(int seg_reg)
2472 {
2473 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
2474 offsetof(CPUX86State,segs[seg_reg].selector));
2475 }
2476
2477 static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2478 {
2479 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
2480 tcg_gen_st32_tl(cpu_T[0], cpu_env,
2481 offsetof(CPUX86State,segs[seg_reg].selector));
2482 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
2483 tcg_gen_st_tl(cpu_T[0], cpu_env,
2484 offsetof(CPUX86State,segs[seg_reg].base));
2485 }
2486
2487 /* move T0 to seg_reg and compute if the CPU state may change. Never
2488 call this function with seg_reg == R_CS */
2489 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2490 {
2491 if (s->pe && !s->vm86) {
2492 /* XXX: optimize by finding processor state dynamically */
2493 gen_update_cc_op(s);
2494 gen_jmp_im(cur_eip);
2495 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2496 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
2497 /* abort translation because the addseg value may change or
2498 because ss32 may change. For R_SS, translation must always
2499 stop as a special handling must be done to disable hardware
2500 interrupts for the next instruction */
2501 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
2502 s->is_jmp = DISAS_TB_JUMP;
2503 } else {
2504 gen_op_movl_seg_T0_vm(seg_reg);
2505 if (seg_reg == R_SS)
2506 s->is_jmp = DISAS_TB_JUMP;
2507 }
2508 }
2509
2510 static inline int svm_is_rep(int prefixes)
2511 {
2512 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2513 }
2514
2515 static inline void
2516 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2517 uint32_t type, uint64_t param)
2518 {
2519 /* no SVM activated; fast case */
2520 if (likely(!(s->flags & HF_SVMI_MASK)))
2521 return;
2522 gen_update_cc_op(s);
2523 gen_jmp_im(pc_start - s->cs_base);
2524 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
2525 tcg_const_i64(param));
2526 }
2527
2528 static inline void
2529 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2530 {
2531 gen_svm_check_intercept_param(s, pc_start, type, 0);
2532 }
2533
2534 static inline void gen_stack_update(DisasContext *s, int addend)
2535 {
2536 #ifdef TARGET_X86_64
2537 if (CODE64(s)) {
2538 gen_op_add_reg_im(2, R_ESP, addend);
2539 } else
2540 #endif
2541 if (s->ss32) {
2542 gen_op_add_reg_im(1, R_ESP, addend);
2543 } else {
2544 gen_op_add_reg_im(0, R_ESP, addend);
2545 }
2546 }
2547
2548 /* generate a push. It depends on ss32, addseg and dflag */
2549 static void gen_push_T0(DisasContext *s)
2550 {
2551 #ifdef TARGET_X86_64
2552 if (CODE64(s)) {
2553 gen_op_movq_A0_reg(R_ESP);
2554 if (s->dflag) {
2555 gen_op_addq_A0_im(-8);
2556 gen_op_st_T0_A0(OT_QUAD + s->mem_index);
2557 } else {
2558 gen_op_addq_A0_im(-2);
2559 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2560 }
2561 gen_op_mov_reg_A0(2, R_ESP);
2562 } else
2563 #endif
2564 {
2565 gen_op_movl_A0_reg(R_ESP);
2566 if (!s->dflag)
2567 gen_op_addl_A0_im(-2);
2568 else
2569 gen_op_addl_A0_im(-4);
2570 if (s->ss32) {
2571 if (s->addseg) {
2572 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2573 gen_op_addl_A0_seg(s, R_SS);
2574 }
2575 } else {
2576 gen_op_andl_A0_ffff();
2577 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2578 gen_op_addl_A0_seg(s, R_SS);
2579 }
2580 gen_op_st_T0_A0(s->dflag + 1 + s->mem_index);
2581 if (s->ss32 && !s->addseg)
2582 gen_op_mov_reg_A0(1, R_ESP);
2583 else
2584 gen_op_mov_reg_T1(s->ss32 + 1, R_ESP);
2585 }
2586 }
2587
2588 /* generate a push. It depends on ss32, addseg and dflag */
2589 /* slower version for T1, only used for call Ev */
2590 static void gen_push_T1(DisasContext *s)
2591 {
2592 #ifdef TARGET_X86_64
2593 if (CODE64(s)) {
2594 gen_op_movq_A0_reg(R_ESP);
2595 if (s->dflag) {
2596 gen_op_addq_A0_im(-8);
2597 gen_op_st_T1_A0(OT_QUAD + s->mem_index);
2598 } else {
2599 gen_op_addq_A0_im(-2);
2600 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2601 }
2602 gen_op_mov_reg_A0(2, R_ESP);
2603 } else
2604 #endif
2605 {
2606 gen_op_movl_A0_reg(R_ESP);
2607 if (!s->dflag)
2608 gen_op_addl_A0_im(-2);
2609 else
2610 gen_op_addl_A0_im(-4);
2611 if (s->ss32) {
2612 if (s->addseg) {
2613 gen_op_addl_A0_seg(s, R_SS);
2614 }
2615 } else {
2616 gen_op_andl_A0_ffff();
2617 gen_op_addl_A0_seg(s, R_SS);
2618 }
2619 gen_op_st_T1_A0(s->dflag + 1 + s->mem_index);
2620
2621 if (s->ss32 && !s->addseg)
2622 gen_op_mov_reg_A0(1, R_ESP);
2623 else
2624 gen_stack_update(s, (-2) << s->dflag);
2625 }
2626 }
2627
2628 /* two step pop is necessary for precise exceptions */
2629 static void gen_pop_T0(DisasContext *s)
2630 {
2631 #ifdef TARGET_X86_64
2632 if (CODE64(s)) {
2633 gen_op_movq_A0_reg(R_ESP);
2634 gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index);
2635 } else
2636 #endif
2637 {
2638 gen_op_movl_A0_reg(R_ESP);
2639 if (s->ss32) {
2640 if (s->addseg)
2641 gen_op_addl_A0_seg(s, R_SS);
2642 } else {
2643 gen_op_andl_A0_ffff();
2644 gen_op_addl_A0_seg(s, R_SS);
2645 }
2646 gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index);
2647 }
2648 }
2649
2650 static void gen_pop_update(DisasContext *s)
2651 {
2652 #ifdef TARGET_X86_64
2653 if (CODE64(s) && s->dflag) {
2654 gen_stack_update(s, 8);
2655 } else
2656 #endif
2657 {
2658 gen_stack_update(s, 2 << s->dflag);
2659 }
2660 }
2661
2662 static void gen_stack_A0(DisasContext *s)
2663 {
2664 gen_op_movl_A0_reg(R_ESP);
2665 if (!s->ss32)
2666 gen_op_andl_A0_ffff();
2667 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2668 if (s->addseg)
2669 gen_op_addl_A0_seg(s, R_SS);
2670 }
2671
2672 /* NOTE: wrap around in 16 bit not fully handled */
2673 static void gen_pusha(DisasContext *s)
2674 {
2675 int i;
2676 gen_op_movl_A0_reg(R_ESP);
2677 gen_op_addl_A0_im(-16 << s->dflag);
2678 if (!s->ss32)
2679 gen_op_andl_A0_ffff();
2680 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2681 if (s->addseg)
2682 gen_op_addl_A0_seg(s, R_SS);
2683 for(i = 0;i < 8; i++) {
2684 gen_op_mov_TN_reg(OT_LONG, 0, 7 - i);
2685 gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index);
2686 gen_op_addl_A0_im(2 << s->dflag);
2687 }
2688 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2689 }
2690
2691 /* NOTE: wrap around in 16 bit not fully handled */
2692 static void gen_popa(DisasContext *s)
2693 {
2694 int i;
2695 gen_op_movl_A0_reg(R_ESP);
2696 if (!s->ss32)
2697 gen_op_andl_A0_ffff();
2698 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2699 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 << s->dflag);
2700 if (s->addseg)
2701 gen_op_addl_A0_seg(s, R_SS);
2702 for(i = 0;i < 8; i++) {
2703 /* ESP is not reloaded */
2704 if (i != 3) {
2705 gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index);
2706 gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i);
2707 }
2708 gen_op_addl_A0_im(2 << s->dflag);
2709 }
2710 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2711 }
2712
2713 static void gen_enter(DisasContext *s, int esp_addend, int level)
2714 {
2715 int ot, opsize;
2716
2717 level &= 0x1f;
2718 #ifdef TARGET_X86_64
2719 if (CODE64(s)) {
2720 ot = s->dflag ? OT_QUAD : OT_WORD;
2721 opsize = 1 << ot;
2722
2723 gen_op_movl_A0_reg(R_ESP);
2724 gen_op_addq_A0_im(-opsize);
2725 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2726
2727 /* push bp */
2728 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2729 gen_op_st_T0_A0(ot + s->mem_index);
2730 if (level) {
2731 /* XXX: must save state */
2732 gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
2733 tcg_const_i32((ot == OT_QUAD)),
2734 cpu_T[1]);
2735 }
2736 gen_op_mov_reg_T1(ot, R_EBP);
2737 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2738 gen_op_mov_reg_T1(OT_QUAD, R_ESP);
2739 } else
2740 #endif
2741 {
2742 ot = s->dflag + OT_WORD;
2743 opsize = 2 << s->dflag;
2744
2745 gen_op_movl_A0_reg(R_ESP);
2746 gen_op_addl_A0_im(-opsize);
2747 if (!s->ss32)
2748 gen_op_andl_A0_ffff();
2749 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2750 if (s->addseg)
2751 gen_op_addl_A0_seg(s, R_SS);
2752 /* push bp */
2753 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2754 gen_op_st_T0_A0(ot + s->mem_index);
2755 if (level) {
2756 /* XXX: must save state */
2757 gen_helper_enter_level(cpu_env, tcg_const_i32(level),
2758 tcg_const_i32(s->dflag),
2759 cpu_T[1]);
2760 }
2761 gen_op_mov_reg_T1(ot, R_EBP);
2762 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2763 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
2764 }
2765 }
2766
2767 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2768 {
2769 gen_update_cc_op(s);
2770 gen_jmp_im(cur_eip);
2771 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
2772 s->is_jmp = DISAS_TB_JUMP;
2773 }
2774
2775 /* an interrupt is different from an exception because of the
2776 privilege checks */
2777 static void gen_interrupt(DisasContext *s, int intno,
2778 target_ulong cur_eip, target_ulong next_eip)
2779 {
2780 gen_update_cc_op(s);
2781 gen_jmp_im(cur_eip);
2782 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
2783 tcg_const_i32(next_eip - cur_eip));
2784 s->is_jmp = DISAS_TB_JUMP;
2785 }
2786
2787 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2788 {
2789 gen_update_cc_op(s);
2790 gen_jmp_im(cur_eip);
2791 gen_helper_debug(cpu_env);
2792 s->is_jmp = DISAS_TB_JUMP;
2793 }
2794
2795 /* generate a generic end of block. Trace exception is also generated
2796 if needed */
2797 static void gen_eob(DisasContext *s)
2798 {
2799 gen_update_cc_op(s);
2800 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2801 gen_helper_reset_inhibit_irq(cpu_env);
2802 }
2803 if (s->tb->flags & HF_RF_MASK) {
2804 gen_helper_reset_rf(cpu_env);
2805 }
2806 if (s->singlestep_enabled) {
2807 gen_helper_debug(cpu_env);
2808 } else if (s->tf) {
2809 gen_helper_single_step(cpu_env);
2810 } else {
2811 tcg_gen_exit_tb(0);
2812 }
2813 s->is_jmp = DISAS_TB_JUMP;
2814 }
2815
2816 /* generate a jump to eip. No segment change must happen before as a
2817 direct call to the next block may occur */
2818 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2819 {
2820 gen_update_cc_op(s);
2821 set_cc_op(s, CC_OP_DYNAMIC);
2822 if (s->jmp_opt) {
2823 gen_goto_tb(s, tb_num, eip);
2824 s->is_jmp = DISAS_TB_JUMP;
2825 } else {
2826 gen_jmp_im(eip);
2827 gen_eob(s);
2828 }
2829 }
2830
2831 static void gen_jmp(DisasContext *s, target_ulong eip)
2832 {
2833 gen_jmp_tb(s, eip, 0);
2834 }
2835
2836 static inline void gen_ldq_env_A0(int idx, int offset)
2837 {
2838 int mem_index = (idx >> 2) - 1;
2839 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
2840 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
2841 }
2842
2843 static inline void gen_stq_env_A0(int idx, int offset)
2844 {
2845 int mem_index = (idx >> 2) - 1;
2846 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2847 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
2848 }
2849
2850 static inline void gen_ldo_env_A0(int idx, int offset)
2851 {
2852 int mem_index = (idx >> 2) - 1;
2853 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
2854 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2855 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2856 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_tmp0, mem_index);
2857 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2858 }
2859
2860 static inline void gen_sto_env_A0(int idx, int offset)
2861 {
2862 int mem_index = (idx >> 2) - 1;
2863 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2864 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
2865 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2866 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2867 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_tmp0, mem_index);
2868 }
2869
2870 static inline void gen_op_movo(int d_offset, int s_offset)
2871 {
2872 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2873 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2874 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8);
2875 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8);
2876 }
2877
2878 static inline void gen_op_movq(int d_offset, int s_offset)
2879 {
2880 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2881 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2882 }
2883
2884 static inline void gen_op_movl(int d_offset, int s_offset)
2885 {
2886 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2887 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2888 }
2889
2890 static inline void gen_op_movq_env_0(int d_offset)
2891 {
2892 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2893 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2894 }
2895
2896 typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2897 typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2898 typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2899 typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2900 typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2901 typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2902 TCGv_i32 val);
2903 typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
2904 typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2905 TCGv val);
2906
2907 #define SSE_SPECIAL ((void *)1)
2908 #define SSE_DUMMY ((void *)2)
2909
2910 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2911 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2912 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
2913
2914 static const SSEFunc_0_epp sse_op_table1[256][4] = {
2915 /* 3DNow! extensions */
2916 [0x0e] = { SSE_DUMMY }, /* femms */
2917 [0x0f] = { SSE_DUMMY }, /* pf... */
2918 /* pure SSE operations */
2919 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2920 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2921 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2922 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2923 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2924 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
2925 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2926 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2927
2928 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2929 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2930 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2931 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
2932 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2933 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2934 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2935 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
2936 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2937 [0x51] = SSE_FOP(sqrt),
2938 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2939 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2940 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2941 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2942 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2943 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
2944 [0x58] = SSE_FOP(add),
2945 [0x59] = SSE_FOP(mul),
2946 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2947 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2948 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
2949 [0x5c] = SSE_FOP(sub),
2950 [0x5d] = SSE_FOP(min),
2951 [0x5e] = SSE_FOP(div),
2952 [0x5f] = SSE_FOP(max),
2953
2954 [0xc2] = SSE_FOP(cmpeq),
2955 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2956 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
2957
2958 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2959 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2960 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2961
2962 /* MMX ops and their SSE extensions */
2963 [0x60] = MMX_OP2(punpcklbw),
2964 [0x61] = MMX_OP2(punpcklwd),
2965 [0x62] = MMX_OP2(punpckldq),
2966 [0x63] = MMX_OP2(packsswb),
2967 [0x64] = MMX_OP2(pcmpgtb),
2968 [0x65] = MMX_OP2(pcmpgtw),
2969 [0x66] = MMX_OP2(pcmpgtl),
2970 [0x67] = MMX_OP2(packuswb),
2971 [0x68] = MMX_OP2(punpckhbw),
2972 [0x69] = MMX_OP2(punpckhwd),
2973 [0x6a] = MMX_OP2(punpckhdq),
2974 [0x6b] = MMX_OP2(packssdw),
2975 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2976 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
2977 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2978 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2979 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2980 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2981 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2982 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
2983 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2984 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2985 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2986 [0x74] = MMX_OP2(pcmpeqb),
2987 [0x75] = MMX_OP2(pcmpeqw),
2988 [0x76] = MMX_OP2(pcmpeql),
2989 [0x77] = { SSE_DUMMY }, /* emms */
2990 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2991 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
2992 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2993 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
2994 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2995 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2996 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2997 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2998 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
2999 [0xd1] = MMX_OP2(psrlw),
3000 [0xd2] = MMX_OP2(psrld),
3001 [0xd3] = MMX_OP2(psrlq),
3002 [0xd4] = MMX_OP2(paddq),
3003 [0xd5] = MMX_OP2(pmullw),
3004 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
3005 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
3006 [0xd8] = MMX_OP2(psubusb),
3007 [0xd9] = MMX_OP2(psubusw),
3008 [0xda] = MMX_OP2(pminub),
3009 [0xdb] = MMX_OP2(pand),
3010 [0xdc] = MMX_OP2(paddusb),
3011 [0xdd] = MMX_OP2(paddusw),
3012 [0xde] = MMX_OP2(pmaxub),
3013 [0xdf] = MMX_OP2(pandn),
3014 [0xe0] = MMX_OP2(pavgb),
3015 [0xe1] = MMX_OP2(psraw),
3016 [0xe2] = MMX_OP2(psrad),
3017 [0xe3] = MMX_OP2(pavgw),
3018 [0xe4] = MMX_OP2(pmulhuw),
3019 [0xe5] = MMX_OP2(pmulhw),
3020 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
3021 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
3022 [0xe8] = MMX_OP2(psubsb),
3023 [0xe9] = MMX_OP2(psubsw),
3024 [0xea] = MMX_OP2(pminsw),
3025 [0xeb] = MMX_OP2(por),
3026 [0xec] = MMX_OP2(paddsb),
3027 [0xed] = MMX_OP2(paddsw),
3028 [0xee] = MMX_OP2(pmaxsw),
3029 [0xef] = MMX_OP2(pxor),
3030 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
3031 [0xf1] = MMX_OP2(psllw),
3032 [0xf2] = MMX_OP2(pslld),
3033 [0xf3] = MMX_OP2(psllq),
3034 [0xf4] = MMX_OP2(pmuludq),
3035 [0xf5] = MMX_OP2(pmaddwd),
3036 [0xf6] = MMX_OP2(psadbw),
3037 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
3038 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
3039 [0xf8] = MMX_OP2(psubb),
3040 [0xf9] = MMX_OP2(psubw),
3041 [0xfa] = MMX_OP2(psubl),
3042 [0xfb] = MMX_OP2(psubq),
3043 [0xfc] = MMX_OP2(paddb),
3044 [0xfd] = MMX_OP2(paddw),
3045 [0xfe] = MMX_OP2(paddl),
3046 };
3047
3048 static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
3049 [0 + 2] = MMX_OP2(psrlw),
3050 [0 + 4] = MMX_OP2(psraw),
3051 [0 + 6] = MMX_OP2(psllw),
3052 [8 + 2] = MMX_OP2(psrld),
3053 [8 + 4] = MMX_OP2(psrad),
3054 [8 + 6] = MMX_OP2(pslld),
3055 [16 + 2] = MMX_OP2(psrlq),
3056 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
3057 [16 + 6] = MMX_OP2(psllq),
3058 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
3059 };
3060
3061 static const SSEFunc_0_epi sse_op_table3ai[] = {
3062 gen_helper_cvtsi2ss,
3063 gen_helper_cvtsi2sd
3064 };
3065
3066 #ifdef TARGET_X86_64
3067 static const SSEFunc_0_epl sse_op_table3aq[] = {
3068 gen_helper_cvtsq2ss,
3069 gen_helper_cvtsq2sd
3070 };
3071 #endif
3072
3073 static const SSEFunc_i_ep sse_op_table3bi[] = {
3074 gen_helper_cvttss2si,
3075 gen_helper_cvtss2si,
3076 gen_helper_cvttsd2si,
3077 gen_helper_cvtsd2si
3078 };
3079
3080 #ifdef TARGET_X86_64
3081 static const SSEFunc_l_ep sse_op_table3bq[] = {
3082 gen_helper_cvttss2sq,
3083 gen_helper_cvtss2sq,
3084 gen_helper_cvttsd2sq,
3085 gen_helper_cvtsd2sq
3086 };
3087 #endif
3088
3089 static const SSEFunc_0_epp sse_op_table4[8][4] = {
3090 SSE_FOP(cmpeq),
3091 SSE_FOP(cmplt),
3092 SSE_FOP(cmple),
3093 SSE_FOP(cmpunord),
3094 SSE_FOP(cmpneq),
3095 SSE_FOP(cmpnlt),
3096 SSE_FOP(cmpnle),
3097 SSE_FOP(cmpord),
3098 };
3099
3100 static const SSEFunc_0_epp sse_op_table5[256] = {
3101 [0x0c] = gen_helper_pi2fw,
3102 [0x0d] = gen_helper_pi2fd,
3103 [0x1c] = gen_helper_pf2iw,
3104 [0x1d] = gen_helper_pf2id,
3105 [0x8a] = gen_helper_pfnacc,
3106 [0x8e] = gen_helper_pfpnacc,
3107 [0x90] = gen_helper_pfcmpge,
3108 [0x94] = gen_helper_pfmin,
3109 [0x96] = gen_helper_pfrcp,
3110 [0x97] = gen_helper_pfrsqrt,
3111 [0x9a] = gen_helper_pfsub,
3112 [0x9e] = gen_helper_pfadd,
3113 [0xa0] = gen_helper_pfcmpgt,
3114 [0xa4] = gen_helper_pfmax,
3115 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
3116 [0xa7] = gen_helper_movq, /* pfrsqit1 */
3117 [0xaa] = gen_helper_pfsubr,
3118 [0xae] = gen_helper_pfacc,
3119 [0xb0] = gen_helper_pfcmpeq,
3120 [0xb4] = gen_helper_pfmul,
3121 [0xb6] = gen_helper_movq, /* pfrcpit2 */
3122 [0xb7] = gen_helper_pmulhrw_mmx,
3123 [0xbb] = gen_helper_pswapd,
3124 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
3125 };
3126
3127 struct SSEOpHelper_epp {
3128 SSEFunc_0_epp op[2];
3129 uint32_t ext_mask;
3130 };
3131
3132 struct SSEOpHelper_eppi {
3133 SSEFunc_0_eppi op[2];
3134 uint32_t ext_mask;
3135 };
3136
3137 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
3138 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
3139 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
3140 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
3141
3142 static const struct SSEOpHelper_epp sse_op_table6[256] = {
3143 [0x00] = SSSE3_OP(pshufb),
3144 [0x01] = SSSE3_OP(phaddw),
3145 [0x02] = SSSE3_OP(phaddd),
3146 [0x03] = SSSE3_OP(phaddsw),
3147 [0x04] = SSSE3_OP(pmaddubsw),
3148 [0x05] = SSSE3_OP(phsubw),
3149 [0x06] = SSSE3_OP(phsubd),
3150 [0x07] = SSSE3_OP(phsubsw),
3151 [0x08] = SSSE3_OP(psignb),
3152 [0x09] = SSSE3_OP(psignw),
3153 [0x0a] = SSSE3_OP(psignd),
3154 [0x0b] = SSSE3_OP(pmulhrsw),
3155 [0x10] = SSE41_OP(pblendvb),
3156 [0x14] = SSE41_OP(blendvps),
3157 [0x15] = SSE41_OP(blendvpd),
3158 [0x17] = SSE41_OP(ptest),
3159 [0x1c] = SSSE3_OP(pabsb),
3160 [0x1d] = SSSE3_OP(pabsw),
3161 [0x1e] = SSSE3_OP(pabsd),
3162 [0x20] = SSE41_OP(pmovsxbw),
3163 [0x21] = SSE41_OP(pmovsxbd),
3164 [0x22] = SSE41_OP(pmovsxbq),
3165 [0x23] = SSE41_OP(pmovsxwd),
3166 [0x24] = SSE41_OP(pmovsxwq),
3167 [0x25] = SSE41_OP(pmovsxdq),
3168 [0x28] = SSE41_OP(pmuldq),
3169 [0x29] = SSE41_OP(pcmpeqq),
3170 [0x2a] = SSE41_SPECIAL, /* movntqda */
3171 [0x2b] = SSE41_OP(packusdw),
3172 [0x30] = SSE41_OP(pmovzxbw),
3173 [0x31] = SSE41_OP(pmovzxbd),
3174 [0x32] = SSE41_OP(pmovzxbq),
3175 [0x33] = SSE41_OP(pmovzxwd),
3176 [0x34] = SSE41_OP(pmovzxwq),
3177 [0x35] = SSE41_OP(pmovzxdq),
3178 [0x37] = SSE42_OP(pcmpgtq),
3179 [0x38] = SSE41_OP(pminsb),
3180 [0x39] = SSE41_OP(pminsd),
3181 [0x3a] = SSE41_OP(pminuw),
3182 [0x3b] = SSE41_OP(pminud),
3183 [0x3c] = SSE41_OP(pmaxsb),
3184 [0x3d] = SSE41_OP(pmaxsd),
3185 [0x3e] = SSE41_OP(pmaxuw),
3186 [0x3f] = SSE41_OP(pmaxud),
3187 [0x40] = SSE41_OP(pmulld),
3188 [0x41] = SSE41_OP(phminposuw),
3189 };
3190
3191 static const struct SSEOpHelper_eppi sse_op_table7[256] = {
3192 [0x08] = SSE41_OP(roundps),
3193 [0x09] = SSE41_OP(roundpd),
3194 [0x0a] = SSE41_OP(roundss),
3195 [0x0b] = SSE41_OP(roundsd),
3196 [0x0c] = SSE41_OP(blendps),
3197 [0x0d] = SSE41_OP(blendpd),
3198 [0x0e] = SSE41_OP(pblendw),
3199 [0x0f] = SSSE3_OP(palignr),
3200 [0x14] = SSE41_SPECIAL, /* pextrb */
3201 [0x15] = SSE41_SPECIAL, /* pextrw */
3202 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3203 [0x17] = SSE41_SPECIAL, /* extractps */
3204 [0x20] = SSE41_SPECIAL, /* pinsrb */
3205 [0x21] = SSE41_SPECIAL, /* insertps */
3206 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3207 [0x40] = SSE41_OP(dpps),
3208 [0x41] = SSE41_OP(dppd),
3209 [0x42] = SSE41_OP(mpsadbw),
3210 [0x60] = SSE42_OP(pcmpestrm),
3211 [0x61] = SSE42_OP(pcmpestri),
3212 [0x62] = SSE42_OP(pcmpistrm),
3213 [0x63] = SSE42_OP(pcmpistri),
3214 };
3215
3216 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3217 target_ulong pc_start, int rex_r)
3218 {
3219 int b1, op1_offset, op2_offset, is_xmm, val, ot;
3220 int modrm, mod, rm, reg, reg_addr, offset_addr;
3221 SSEFunc_0_epp sse_fn_epp;
3222 SSEFunc_0_eppi sse_fn_eppi;
3223 SSEFunc_0_ppi sse_fn_ppi;
3224 SSEFunc_0_eppt sse_fn_eppt;
3225
3226 b &= 0xff;
3227 if (s->prefix & PREFIX_DATA)
3228 b1 = 1;
3229 else if (s->prefix & PREFIX_REPZ)
3230 b1 = 2;
3231 else if (s->prefix & PREFIX_REPNZ)
3232 b1 = 3;
3233 else
3234 b1 = 0;
3235 sse_fn_epp = sse_op_table1[b][b1];
3236 if (!sse_fn_epp) {
3237 goto illegal_op;
3238 }
3239 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
3240 is_xmm = 1;
3241 } else {
3242 if (b1 == 0) {
3243 /* MMX case */
3244 is_xmm = 0;
3245 } else {
3246 is_xmm = 1;
3247 }
3248 }
3249 /* simple MMX/SSE operation */
3250 if (s->flags & HF_TS_MASK) {
3251 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3252 return;
3253 }
3254 if (s->flags & HF_EM_MASK) {
3255 illegal_op:
3256 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
3257 return;
3258 }
3259 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
3260 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
3261 goto illegal_op;
3262 if (b == 0x0e) {
3263 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3264 goto illegal_op;
3265 /* femms */
3266 gen_helper_emms(cpu_env);
3267 return;
3268 }
3269 if (b == 0x77) {
3270 /* emms */
3271 gen_helper_emms(cpu_env);
3272 return;
3273 }
3274 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3275 the static cpu state) */
3276 if (!is_xmm) {
3277 gen_helper_enter_mmx(cpu_env);
3278 }
3279
3280 modrm = cpu_ldub_code(env, s->pc++);
3281 reg = ((modrm >> 3) & 7);
3282 if (is_xmm)
3283 reg |= rex_r;
3284 mod = (modrm >> 6) & 3;
3285 if (sse_fn_epp == SSE_SPECIAL) {
3286 b |= (b1 << 8);
3287 switch(b) {
3288 case 0x0e7: /* movntq */
3289 if (mod == 3)
3290 goto illegal_op;
3291 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3292 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
3293 break;
3294 case 0x1e7: /* movntdq */
3295 case 0x02b: /* movntps */
3296 case 0x12b: /* movntps */
3297 if (mod == 3)
3298 goto illegal_op;
3299 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3300 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3301 break;
3302 case 0x3f0: /* lddqu */
3303 if (mod == 3)
3304 goto illegal_op;
3305 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3306 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3307 break;
3308 case 0x22b: /* movntss */
3309 case 0x32b: /* movntsd */
3310 if (mod == 3)
3311 goto illegal_op;
3312 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3313 if (b1 & 1) {
3314 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,
3315 xmm_regs[reg]));
3316 } else {
3317 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3318 xmm_regs[reg].XMM_L(0)));
3319 gen_op_st_T0_A0(OT_LONG + s->mem_index);
3320 }
3321 break;
3322 case 0x6e: /* movd mm, ea */
3323 #ifdef TARGET_X86_64
3324 if (s->dflag == 2) {
3325 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
3326 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
3327 } else
3328 #endif
3329 {
3330 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
3331 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3332 offsetof(CPUX86State,fpregs[reg].mmx));
3333 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3334 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
3335 }
3336 break;
3337 case 0x16e: /* movd xmm, ea */
3338 #ifdef TARGET_X86_64
3339 if (s->dflag == 2) {
3340 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
3341 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3342 offsetof(CPUX86State,xmm_regs[reg]));
3343 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
3344 } else
3345 #endif
3346 {
3347 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
3348 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3349 offsetof(CPUX86State,xmm_regs[reg]));
3350 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3351 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
3352 }
3353 break;
3354 case 0x6f: /* movq mm, ea */
3355 if (mod != 3) {
3356 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3357 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
3358 } else {
3359 rm = (modrm & 7);
3360 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3361 offsetof(CPUX86State,fpregs[rm].mmx));
3362 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3363 offsetof(CPUX86State,fpregs[reg].mmx));
3364 }
3365 break;
3366 case 0x010: /* movups */
3367 case 0x110: /* movupd */
3368 case 0x028: /* movaps */
3369 case 0x128: /* movapd */
3370 case 0x16f: /* movdqa xmm, ea */
3371 case 0x26f: /* movdqu xmm, ea */
3372 if (mod != 3) {
3373 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3374 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3375 } else {
3376 rm = (modrm & 7) | REX_B(s);
3377 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3378 offsetof(CPUX86State,xmm_regs[rm]));
3379 }
3380 break;
3381 case 0x210: /* movss xmm, ea */
3382 if (mod != 3) {
3383 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3384 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3385 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3386 gen_op_movl_T0_0();
3387 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3388 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3389 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3390 } else {
3391 rm = (modrm & 7) | REX_B(s);
3392 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3393 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3394 }
3395 break;
3396 case 0x310: /* movsd xmm, ea */
3397 if (mod != 3) {
3398 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3399 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3400 gen_op_movl_T0_0();
3401 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3402 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3403 } else {
3404 rm = (modrm & 7) | REX_B(s);
3405 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3406 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3407 }
3408 break;
3409 case 0x012: /* movlps */
3410 case 0x112: /* movlpd */
3411 if (mod != 3) {
3412 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3413 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3414 } else {
3415 /* movhlps */
3416 rm = (modrm & 7) | REX_B(s);
3417 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3418 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3419 }
3420 break;
3421 case 0x212: /* movsldup */
3422 if (mod != 3) {
3423 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3424 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3425 } else {
3426 rm = (modrm & 7) | REX_B(s);
3427 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3428 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3429 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3430 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3431 }
3432 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3433 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3434 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3435 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3436 break;
3437 case 0x312: /* movddup */
3438 if (mod != 3) {
3439 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3440 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3441 } else {
3442 rm = (modrm & 7) | REX_B(s);
3443 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3444 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3445 }
3446 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3447 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3448 break;
3449 case 0x016: /* movhps */
3450 case 0x116: /* movhpd */
3451 if (mod != 3) {
3452 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3453 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3454 } else {
3455 /* movlhps */
3456 rm = (modrm & 7) | REX_B(s);
3457 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3458 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3459 }
3460 break;
3461 case 0x216: /* movshdup */
3462 if (mod != 3) {
3463 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3464 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3465 } else {
3466 rm = (modrm & 7) | REX_B(s);
3467 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3468 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3469 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3470 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3471 }
3472 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3473 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3474 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3475 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3476 break;
3477 case 0x178:
3478 case 0x378:
3479 {
3480 int bit_index, field_length;
3481
3482 if (b1 == 1 && reg != 0)
3483 goto illegal_op;
3484 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3485 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
3486 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3487 offsetof(CPUX86State,xmm_regs[reg]));
3488 if (b1 == 1)
3489 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3490 tcg_const_i32(bit_index),
3491 tcg_const_i32(field_length));
3492 else
3493 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3494 tcg_const_i32(bit_index),
3495 tcg_const_i32(field_length));
3496 }
3497 break;
3498 case 0x7e: /* movd ea, mm */
3499 #ifdef TARGET_X86_64
3500 if (s->dflag == 2) {
3501 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3502 offsetof(CPUX86State,fpregs[reg].mmx));
3503 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
3504 } else
3505 #endif
3506 {
3507 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3508 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
3509 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
3510 }
3511 break;
3512 case 0x17e: /* movd ea, xmm */
3513 #ifdef TARGET_X86_64
3514 if (s->dflag == 2) {
3515 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3516 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3517 gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
3518 } else
3519 #endif
3520 {
3521 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3522 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3523 gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
3524 }
3525 break;
3526 case 0x27e: /* movq xmm, ea */
3527 if (mod != 3) {
3528 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3529 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3530 } else {
3531 rm = (modrm & 7) | REX_B(s);
3532 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3533 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3534 }
3535 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3536 break;
3537 case 0x7f: /* movq ea, mm */
3538 if (mod != 3) {
3539 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3540 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
3541 } else {
3542 rm = (modrm & 7);
3543 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3544 offsetof(CPUX86State,fpregs[reg].mmx));
3545 }
3546 break;
3547 case 0x011: /* movups */
3548 case 0x111: /* movupd */
3549 case 0x029: /* movaps */
3550 case 0x129: /* movapd */
3551 case 0x17f: /* movdqa ea, xmm */
3552 case 0x27f: /* movdqu ea, xmm */
3553 if (mod != 3) {
3554 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3555 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3556 } else {
3557 rm = (modrm & 7) | REX_B(s);
3558 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3559 offsetof(CPUX86State,xmm_regs[reg]));
3560 }
3561 break;
3562 case 0x211: /* movss ea, xmm */
3563 if (mod != 3) {
3564 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3565 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3566 gen_op_st_T0_A0(OT_LONG + s->mem_index);
3567 } else {
3568 rm = (modrm & 7) | REX_B(s);
3569 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3570 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3571 }
3572 break;
3573 case 0x311: /* movsd ea, xmm */
3574 if (mod != 3) {
3575 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3576 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3577 } else {
3578 rm = (modrm & 7) | REX_B(s);
3579 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3580 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3581 }
3582 break;
3583 case 0x013: /* movlps */
3584 case 0x113: /* movlpd */
3585 if (mod != 3) {
3586 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3587 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3588 } else {
3589 goto illegal_op;
3590 }
3591 break;
3592 case 0x017: /* movhps */
3593 case 0x117: /* movhpd */
3594 if (mod != 3) {
3595 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3596 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3597 } else {
3598 goto illegal_op;
3599 }
3600 break;
3601 case 0x71: /* shift mm, im */
3602 case 0x72:
3603 case 0x73:
3604 case 0x171: /* shift xmm, im */
3605 case 0x172:
3606 case 0x173:
3607 if (b1 >= 2) {
3608 goto illegal_op;
3609 }
3610 val = cpu_ldub_code(env, s->pc++);
3611 if (is_xmm) {
3612 gen_op_movl_T0_im(val);
3613 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3614 gen_op_movl_T0_0();
3615 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
3616 op1_offset = offsetof(CPUX86State,xmm_t0);
3617 } else {
3618 gen_op_movl_T0_im(val);
3619 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
3620 gen_op_movl_T0_0();
3621 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
3622 op1_offset = offsetof(CPUX86State,mmx_t0);
3623 }
3624 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3625 (((modrm >> 3)) & 7)][b1];
3626 if (!sse_fn_epp) {
3627 goto illegal_op;
3628 }
3629 if (is_xmm) {
3630 rm = (modrm & 7) | REX_B(s);
3631 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3632 } else {
3633 rm = (modrm & 7);
3634 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3635 }
3636 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3637 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3638 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3639 break;
3640 case 0x050: /* movmskps */
3641 rm = (modrm & 7) | REX_B(s);
3642 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3643 offsetof(CPUX86State,xmm_regs[rm]));
3644 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3645 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3646 gen_op_mov_reg_T0(OT_LONG, reg);
3647 break;
3648 case 0x150: /* movmskpd */
3649 rm = (modrm & 7) | REX_B(s);
3650 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3651 offsetof(CPUX86State,xmm_regs[rm]));
3652 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3653 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3654 gen_op_mov_reg_T0(OT_LONG, reg);
3655 break;
3656 case 0x02a: /* cvtpi2ps */
3657 case 0x12a: /* cvtpi2pd */
3658 gen_helper_enter_mmx(cpu_env);
3659 if (mod != 3) {
3660 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3661 op2_offset = offsetof(CPUX86State,mmx_t0);
3662 gen_ldq_env_A0(s->mem_index, op2_offset);
3663 } else {
3664 rm = (modrm & 7);
3665 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3666 }
3667 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3668 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3669 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3670 switch(b >> 8) {
3671 case 0x0:
3672 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
3673 break;
3674 default:
3675 case 0x1:
3676 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
3677 break;
3678 }
3679 break;
3680 case 0x22a: /* cvtsi2ss */
3681 case 0x32a: /* cvtsi2sd */
3682 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3683 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3684 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3685 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3686 if (ot == OT_LONG) {
3687 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
3688 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3689 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
3690 } else {
3691 #ifdef TARGET_X86_64
3692 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3693 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T[0]);
3694 #else
3695 goto illegal_op;
3696 #endif
3697 }
3698 break;
3699 case 0x02c: /* cvttps2pi */
3700 case 0x12c: /* cvttpd2pi */
3701 case 0x02d: /* cvtps2pi */
3702 case 0x12d: /* cvtpd2pi */
3703 gen_helper_enter_mmx(cpu_env);
3704 if (mod != 3) {
3705 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3706 op2_offset = offsetof(CPUX86State,xmm_t0);
3707 gen_ldo_env_A0(s->mem_index, op2_offset);
3708 } else {
3709 rm = (modrm & 7) | REX_B(s);
3710 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3711 }
3712 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3713 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3714 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3715 switch(b) {
3716 case 0x02c:
3717 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3718 break;
3719 case 0x12c:
3720 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3721 break;
3722 case 0x02d:
3723 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3724 break;
3725 case 0x12d:
3726 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
3727 break;
3728 }
3729 break;
3730 case 0x22c: /* cvttss2si */
3731 case 0x32c: /* cvttsd2si */
3732 case 0x22d: /* cvtss2si */
3733 case 0x32d: /* cvtsd2si */
3734 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3735 if (mod != 3) {
3736 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3737 if ((b >> 8) & 1) {
3738 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
3739 } else {
3740 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3741 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3742 }
3743 op2_offset = offsetof(CPUX86State,xmm_t0);
3744 } else {
3745 rm = (modrm & 7) | REX_B(s);
3746 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3747 }
3748 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3749 if (ot == OT_LONG) {
3750 SSEFunc_i_ep sse_fn_i_ep =
3751 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
3752 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3753 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3754 } else {
3755 #ifdef TARGET_X86_64
3756 SSEFunc_l_ep sse_fn_l_ep =
3757 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
3758 sse_fn_l_ep(cpu_T[0], cpu_env, cpu_ptr0);
3759 #else
3760 goto illegal_op;
3761 #endif
3762 }
3763 gen_op_mov_reg_T0(ot, reg);
3764 break;
3765 case 0xc4: /* pinsrw */
3766 case 0x1c4:
3767 s->rip_offset = 1;
3768 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
3769 val = cpu_ldub_code(env, s->pc++);
3770 if (b1) {
3771 val &= 7;
3772 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3773 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
3774 } else {
3775 val &= 3;
3776 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3777 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
3778 }
3779 break;
3780 case 0xc5: /* pextrw */
3781 case 0x1c5:
3782 if (mod != 3)
3783 goto illegal_op;
3784 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3785 val = cpu_ldub_code(env, s->pc++);
3786 if (b1) {
3787 val &= 7;
3788 rm = (modrm & 7) | REX_B(s);
3789 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3790 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
3791 } else {
3792 val &= 3;
3793 rm = (modrm & 7);
3794 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3795 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
3796 }
3797 reg = ((modrm >> 3) & 7) | rex_r;
3798 gen_op_mov_reg_T0(ot, reg);
3799 break;
3800 case 0x1d6: /* movq ea, xmm */
3801 if (mod != 3) {
3802 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3803 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3804 } else {
3805 rm = (modrm & 7) | REX_B(s);
3806 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3807 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3808 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3809 }
3810 break;
3811 case 0x2d6: /* movq2dq */
3812 gen_helper_enter_mmx(cpu_env);
3813 rm = (modrm & 7);
3814 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3815 offsetof(CPUX86State,fpregs[rm].mmx));
3816 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3817 break;
3818 case 0x3d6: /* movdq2q */
3819 gen_helper_enter_mmx(cpu_env);
3820 rm = (modrm & 7) | REX_B(s);
3821 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3822 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3823 break;
3824 case 0xd7: /* pmovmskb */
3825 case 0x1d7:
3826 if (mod != 3)
3827 goto illegal_op;
3828 if (b1) {
3829 rm = (modrm & 7) | REX_B(s);
3830 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3831 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3832 } else {
3833 rm = (modrm & 7);
3834 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3835 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
3836 }
3837 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3838 reg = ((modrm >> 3) & 7) | rex_r;
3839 gen_op_mov_reg_T0(OT_LONG, reg);
3840 break;
3841
3842 case 0x138:
3843 case 0x038:
3844 b = modrm;
3845 if ((b & 0xf0) == 0xf0) {
3846 goto do_0f_38_fx;
3847 }
3848 modrm = cpu_ldub_code(env, s->pc++);
3849 rm = modrm & 7;
3850 reg = ((modrm >> 3) & 7) | rex_r;
3851 mod = (modrm >> 6) & 3;
3852 if (b1 >= 2) {
3853 goto illegal_op;
3854 }
3855
3856 sse_fn_epp = sse_op_table6[b].op[b1];
3857 if (!sse_fn_epp) {
3858 goto illegal_op;
3859 }
3860 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3861 goto illegal_op;
3862
3863 if (b1) {
3864 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3865 if (mod == 3) {
3866 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3867 } else {
3868 op2_offset = offsetof(CPUX86State,xmm_t0);
3869 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3870 switch (b) {
3871 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3872 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3873 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3874 gen_ldq_env_A0(s->mem_index, op2_offset +
3875 offsetof(XMMReg, XMM_Q(0)));
3876 break;
3877 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3878 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3879 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
3880 (s->mem_index >> 2) - 1);
3881 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
3882 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3883 offsetof(XMMReg, XMM_L(0)));
3884 break;
3885 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3886 tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0,
3887 (s->mem_index >> 2) - 1);
3888 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3889 offsetof(XMMReg, XMM_W(0)));
3890 break;
3891 case 0x2a: /* movntqda */
3892 gen_ldo_env_A0(s->mem_index, op1_offset);
3893 return;
3894 default:
3895 gen_ldo_env_A0(s->mem_index, op2_offset);
3896 }
3897 }
3898 } else {
3899 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3900 if (mod == 3) {
3901 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3902 } else {
3903 op2_offset = offsetof(CPUX86State,mmx_t0);
3904 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
3905 gen_ldq_env_A0(s->mem_index, op2_offset);
3906 }
3907 }
3908 if (sse_fn_epp == SSE_SPECIAL) {
3909 goto illegal_op;
3910 }
3911
3912 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3913 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3914 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
3915
3916 if (b == 0x17) {
3917 set_cc_op(s, CC_OP_EFLAGS);
3918 }
3919 break;
3920
3921 case 0x238:
3922 case 0x338:
3923 do_0f_38_fx:
3924 /* Various integer extensions at 0f 38 f[0-f]. */
3925 b = modrm | (b1 << 8);
3926 modrm = cpu_ldub_code(env, s->pc++);
3927 reg = ((modrm >> 3) & 7) | rex_r;
3928
3929 switch (b) {
3930 case 0x3f0: /* crc32 Gd,Eb */
3931 case 0x3f1: /* crc32 Gd,Ey */
3932 do_crc32:
3933 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3934 goto illegal_op;
3935 }
3936 if ((b & 0xff) == 0xf0) {
3937 ot = OT_BYTE;
3938 } else if (s->dflag != 2) {
3939 ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
3940 } else {
3941 ot = OT_QUAD;
3942 }
3943
3944 gen_op_mov_TN_reg(OT_LONG, 0, reg);
3945 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3946 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3947 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
3948 cpu_T[0], tcg_const_i32(8 << ot));
3949
3950 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3951 gen_op_mov_reg_T0(ot, reg);
3952 break;
3953
3954 case 0x1f0: /* crc32 or movbe */
3955 case 0x1f1:
3956 /* For these insns, the f3 prefix is supposed to have priority
3957 over the 66 prefix, but that's not what we implement above
3958 setting b1. */
3959 if (s->prefix & PREFIX_REPNZ) {
3960 goto do_crc32;
3961 }
3962 /* FALLTHRU */
3963 case 0x0f0: /* movbe Gy,My */
3964 case 0x0f1: /* movbe My,Gy */
3965 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3966 goto illegal_op;
3967 }
3968 if (s->dflag != 2) {
3969 ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
3970 } else {
3971 ot = OT_QUAD;
3972 }
3973
3974 /* Load the data incoming to the bswap. Note that the TCG
3975 implementation of bswap requires the input be zero
3976 extended. In the case of the loads, we simply know that
3977 gen_op_ld_v via gen_ldst_modrm does that already. */
3978 if ((b & 1) == 0) {
3979 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3980 } else {
3981 switch (ot) {
3982 case OT_WORD:
3983 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[reg]);
3984 break;
3985 default:
3986 tcg_gen_ext32u_tl(cpu_T[0], cpu_regs[reg]);
3987 break;
3988 case OT_QUAD:
3989 tcg_gen_mov_tl(cpu_T[0], cpu_regs[reg]);
3990 break;
3991 }
3992 }
3993
3994 switch (ot) {
3995 case OT_WORD:
3996 tcg_gen_bswap16_tl(cpu_T[0], cpu_T[0]);
3997 break;
3998 default:
3999 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
4000 break;
4001 #ifdef TARGET_X86_64
4002 case OT_QUAD:
4003 tcg_gen_bswap64_tl(cpu_T[0], cpu_T[0]);
4004 break;
4005 #endif
4006 }
4007
4008 if ((b & 1) == 0) {
4009 gen_op_mov_reg_T0(ot, reg);
4010 } else {
4011 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
4012 }
4013 break;
4014
4015 case 0x0f2: /* andn Gy, By, Ey */
4016 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4017 || !(s->prefix & PREFIX_VEX)
4018 || s->vex_l != 0) {
4019 goto illegal_op;
4020 }
4021 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4022 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4023 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
4024 gen_op_mov_reg_T0(ot, reg);
4025 gen_op_update1_cc();
4026 set_cc_op(s, CC_OP_LOGICB + ot);
4027 break;
4028
4029 default:
4030 goto illegal_op;
4031 }
4032 break;
4033
4034 case 0x03a:
4035 case 0x13a:
4036 b = modrm;
4037 modrm = cpu_ldub_code(env, s->pc++);
4038 rm = modrm & 7;
4039 reg = ((modrm >> 3) & 7) | rex_r;
4040 mod = (modrm >> 6) & 3;
4041 if (b1 >= 2) {
4042 goto illegal_op;
4043 }
4044
4045 sse_fn_eppi = sse_op_table7[b].op[b1];
4046 if (!sse_fn_eppi) {
4047 goto illegal_op;
4048 }
4049 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4050 goto illegal_op;
4051
4052 if (sse_fn_eppi == SSE_SPECIAL) {
4053 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
4054 rm = (modrm & 7) | REX_B(s);
4055 if (mod != 3)
4056 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4057 reg = ((modrm >> 3) & 7) | rex_r;
4058 val = cpu_ldub_code(env, s->pc++);
4059 switch (b) {
4060 case 0x14: /* pextrb */
4061 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4062 xmm_regs[reg].XMM_B(val & 15)));
4063 if (mod == 3)
4064 gen_op_mov_reg_T0(ot, rm);
4065 else
4066 tcg_gen_qemu_st8(cpu_T[0], cpu_A0,
4067 (s->mem_index >> 2) - 1);
4068 break;
4069 case 0x15: /* pextrw */
4070 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4071 xmm_regs[reg].XMM_W(val & 7)));
4072 if (mod == 3)
4073 gen_op_mov_reg_T0(ot, rm);
4074 else
4075 tcg_gen_qemu_st16(cpu_T[0], cpu_A0,
4076 (s->mem_index >> 2) - 1);
4077 break;
4078 case 0x16:
4079 if (ot == OT_LONG) { /* pextrd */
4080 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4081 offsetof(CPUX86State,
4082 xmm_regs[reg].XMM_L(val & 3)));
4083 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4084 if (mod == 3)
4085 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
4086 else
4087 tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
4088 (s->mem_index >> 2) - 1);
4089 } else { /* pextrq */
4090 #ifdef TARGET_X86_64
4091 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4092 offsetof(CPUX86State,
4093 xmm_regs[reg].XMM_Q(val & 1)));
4094 if (mod == 3)
4095 gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
4096 else
4097 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
4098 (s->mem_index >> 2) - 1);
4099 #else
4100 goto illegal_op;
4101 #endif
4102 }
4103 break;
4104 case 0x17: /* extractps */
4105 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4106 xmm_regs[reg].XMM_L(val & 3)));
4107 if (mod == 3)
4108 gen_op_mov_reg_T0(ot, rm);
4109 else
4110 tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
4111 (s->mem_index >> 2) - 1);
4112 break;
4113 case 0x20: /* pinsrb */
4114 if (mod == 3)
4115 gen_op_mov_TN_reg(OT_LONG, 0, rm);
4116 else
4117 tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0,
4118 (s->mem_index >> 2) - 1);
4119 tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State,
4120 xmm_regs[reg].XMM_B(val & 15)));
4121 break;
4122 case 0x21: /* insertps */
4123 if (mod == 3) {
4124 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4125 offsetof(CPUX86State,xmm_regs[rm]
4126 .XMM_L((val >> 6) & 3)));
4127 } else {
4128 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
4129 (s->mem_index >> 2) - 1);
4130 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
4131 }
4132 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4133 offsetof(CPUX86State,xmm_regs[reg]
4134 .XMM_L((val >> 4) & 3)));
4135 if ((val >> 0) & 1)
4136 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4137 cpu_env, offsetof(CPUX86State,
4138 xmm_regs[reg].XMM_L(0)));
4139 if ((val >> 1) & 1)
4140 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4141 cpu_env, offsetof(CPUX86State,
4142 xmm_regs[reg].XMM_L(1)));
4143 if ((val >> 2) & 1)
4144 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4145 cpu_env, offsetof(CPUX86State,
4146 xmm_regs[reg].XMM_L(2)));
4147 if ((val >> 3) & 1)
4148 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4149 cpu_env, offsetof(CPUX86State,
4150 xmm_regs[reg].XMM_L(3)));
4151 break;
4152 case 0x22:
4153 if (ot == OT_LONG) { /* pinsrd */
4154 if (mod == 3)
4155 gen_op_mov_v_reg(ot, cpu_tmp0, rm);
4156 else
4157 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
4158 (s->mem_index >> 2) - 1);
4159 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
4160 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4161 offsetof(CPUX86State,
4162 xmm_regs[reg].XMM_L(val & 3)));
4163 } else { /* pinsrq */
4164 #ifdef TARGET_X86_64
4165 if (mod == 3)
4166 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4167 else
4168 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
4169 (s->mem_index >> 2) - 1);
4170 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4171 offsetof(CPUX86State,
4172 xmm_regs[reg].XMM_Q(val & 1)));
4173 #else
4174 goto illegal_op;
4175 #endif
4176 }
4177 break;
4178 }
4179 return;
4180 }
4181
4182 if (b1) {
4183 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4184 if (mod == 3) {
4185 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4186 } else {
4187 op2_offset = offsetof(CPUX86State,xmm_t0);
4188 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4189 gen_ldo_env_A0(s->mem_index, op2_offset);
4190 }
4191 } else {
4192 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4193 if (mod == 3) {
4194 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4195 } else {
4196 op2_offset = offsetof(CPUX86State,mmx_t0);
4197 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4198 gen_ldq_env_A0(s->mem_index, op2_offset);
4199 }
4200 }
4201 val = cpu_ldub_code(env, s->pc++);
4202
4203 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
4204 set_cc_op(s, CC_OP_EFLAGS);
4205
4206 if (s->dflag == 2)
4207 /* The helper must use entire 64-bit gp registers */
4208 val |= 1 << 8;
4209 }
4210
4211 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4212 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4213 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4214 break;
4215 default:
4216 goto illegal_op;
4217 }
4218 } else {
4219 /* generic MMX or SSE operation */
4220 switch(b) {
4221 case 0x70: /* pshufx insn */
4222 case 0xc6: /* pshufx insn */
4223 case 0xc2: /* compare insns */
4224 s->rip_offset = 1;
4225 break;
4226 default:
4227 break;
4228 }
4229 if (is_xmm) {
4230 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4231 if (mod != 3) {
4232 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4233 op2_offset = offsetof(CPUX86State,xmm_t0);
4234 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
4235 b == 0xc2)) {
4236 /* specific case for SSE single instructions */
4237 if (b1 == 2) {
4238 /* 32 bit access */
4239 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
4240 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
4241 } else {
4242 /* 64 bit access */
4243 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
4244 }
4245 } else {
4246 gen_ldo_env_A0(s->mem_index, op2_offset);
4247 }
4248 } else {
4249 rm = (modrm & 7) | REX_B(s);
4250 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4251 }
4252 } else {
4253 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4254 if (mod != 3) {
4255 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4256 op2_offset = offsetof(CPUX86State,mmx_t0);
4257 gen_ldq_env_A0(s->mem_index, op2_offset);
4258 } else {
4259 rm = (modrm & 7);
4260 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4261 }
4262 }
4263 switch(b) {
4264 case 0x0f: /* 3DNow! data insns */
4265 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4266 goto illegal_op;
4267 val = cpu_ldub_code(env, s->pc++);
4268 sse_fn_epp = sse_op_table5[val];
4269 if (!sse_fn_epp) {
4270 goto illegal_op;
4271 }
4272 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4273 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4274 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4275 break;
4276 case 0x70: /* pshufx insn */
4277 case 0xc6: /* pshufx insn */
4278 val = cpu_ldub_code(env, s->pc++);
4279 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4280 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4281 /* XXX: introduce a new table? */
4282 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
4283 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4284 break;
4285 case 0xc2:
4286 /* compare insns */
4287 val = cpu_ldub_code(env, s->pc++);
4288 if (val >= 8)
4289 goto illegal_op;
4290 sse_fn_epp = sse_op_table4[val][b1];
4291
4292 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4293 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4294 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4295 break;
4296 case 0xf7:
4297 /* maskmov : we must prepare A0 */
4298 if (mod != 3)
4299 goto illegal_op;
4300 #ifdef TARGET_X86_64
4301 if (s->aflag == 2) {
4302 gen_op_movq_A0_reg(R_EDI);
4303 } else
4304 #endif
4305 {
4306 gen_op_movl_A0_reg(R_EDI);
4307 if (s->aflag == 0)
4308 gen_op_andl_A0_ffff();
4309 }
4310 gen_add_A0_ds_seg(s);
4311
4312 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4313 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4314 /* XXX: introduce a new table? */
4315 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4316 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
4317 break;
4318 default:
4319 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4320 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4321 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
4322 break;
4323 }
4324 if (b == 0x2e || b == 0x2f) {
4325 set_cc_op(s, CC_OP_EFLAGS);
4326 }
4327 }
4328 }
4329
4330 /* convert one instruction. s->is_jmp is set if the translation must
4331 be stopped. Return the next pc value */
4332 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4333 target_ulong pc_start)
4334 {
4335 int b, prefixes, aflag, dflag;
4336 int shift, ot;
4337 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
4338 target_ulong next_eip, tval;
4339 int rex_w, rex_r;
4340
4341 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
4342 tcg_gen_debug_insn_start(pc_start);
4343 }
4344 s->pc = pc_start;
4345 prefixes = 0;
4346 aflag = s->code32;
4347 dflag = s->code32;
4348 s->override = -1;
4349 rex_w = -1;
4350 rex_r = 0;
4351 #ifdef TARGET_X86_64
4352 s->rex_x = 0;
4353 s->rex_b = 0;
4354 x86_64_hregs = 0;
4355 #endif
4356 s->rip_offset = 0; /* for relative ip address */
4357 s->vex_l = 0;
4358 s->vex_v = 0;
4359 next_byte:
4360 b = cpu_ldub_code(env, s->pc);
4361 s->pc++;
4362 /* Collect prefixes. */
4363 switch (b) {
4364 case 0xf3:
4365 prefixes |= PREFIX_REPZ;
4366 goto next_byte;
4367 case 0xf2:
4368 prefixes |= PREFIX_REPNZ;
4369 goto next_byte;
4370 case 0xf0:
4371 prefixes |= PREFIX_LOCK;
4372 goto next_byte;
4373 case 0x2e:
4374 s->override = R_CS;
4375 goto next_byte;
4376 case 0x36:
4377 s->override = R_SS;
4378 goto next_byte;
4379 case 0x3e:
4380 s->override = R_DS;
4381 goto next_byte;
4382 case 0x26:
4383 s->override = R_ES;
4384 goto next_byte;
4385 case 0x64:
4386 s->override = R_FS;
4387 goto next_byte;
4388 case 0x65:
4389 s->override = R_GS;
4390 goto next_byte;
4391 case 0x66:
4392 prefixes |= PREFIX_DATA;
4393 goto next_byte;
4394 case 0x67:
4395 prefixes |= PREFIX_ADR;
4396 goto next_byte;
4397 #ifdef TARGET_X86_64
4398 case 0x40 ... 0x4f:
4399 if (CODE64(s)) {
4400 /* REX prefix */
4401 rex_w = (b >> 3) & 1;
4402 rex_r = (b & 0x4) << 1;
4403 s->rex_x = (b & 0x2) << 2;
4404 REX_B(s) = (b & 0x1) << 3;
4405 x86_64_hregs = 1; /* select uniform byte register addressing */
4406 goto next_byte;
4407 }
4408 break;
4409 #endif
4410 case 0xc5: /* 2-byte VEX */
4411 case 0xc4: /* 3-byte VEX */
4412 /* VEX prefixes cannot be used except in 32-bit mode.
4413 Otherwise the instruction is LES or LDS. */
4414 if (s->code32 && !s->vm86) {
4415 static const int pp_prefix[4] = {
4416 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4417 };
4418 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4419
4420 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4421 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4422 otherwise the instruction is LES or LDS. */
4423 break;
4424 }
4425 s->pc++;
4426
4427 /* 4.1.1-4.1.3: No preceeding lock, 66, f2, f3, or rex prefixes. */
4428 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4429 | PREFIX_LOCK | PREFIX_DATA)) {
4430 goto illegal_op;
4431 }
4432 #ifdef TARGET_X86_64
4433 if (x86_64_hregs) {
4434 goto illegal_op;
4435 }
4436 #endif
4437 rex_r = (~vex2 >> 4) & 8;
4438 if (b == 0xc5) {
4439 vex3 = vex2;
4440 b = cpu_ldub_code(env, s->pc++);
4441 } else {
4442 #ifdef TARGET_X86_64
4443 s->rex_x = (~vex2 >> 3) & 8;
4444 s->rex_b = (~vex2 >> 2) & 8;
4445 #endif
4446 vex3 = cpu_ldub_code(env, s->pc++);
4447 rex_w = (vex3 >> 7) & 1;
4448 switch (vex2 & 0x1f) {
4449 case 0x01: /* Implied 0f leading opcode bytes. */
4450 b = cpu_ldub_code(env, s->pc++) | 0x100;
4451 break;
4452 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4453 b = 0x138;
4454 break;
4455 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4456 b = 0x13a;
4457 break;
4458 default: /* Reserved for future use. */
4459 goto illegal_op;
4460 }
4461 }
4462 s->vex_v = (~vex3 >> 3) & 0xf;
4463 s->vex_l = (vex3 >> 2) & 1;
4464 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4465 }
4466 break;
4467 }
4468
4469 /* Post-process prefixes. */
4470 if (prefixes & PREFIX_DATA) {
4471 dflag ^= 1;
4472 }
4473 if (prefixes & PREFIX_ADR) {
4474 aflag ^= 1;
4475 }
4476 #ifdef TARGET_X86_64
4477 if (CODE64(s)) {
4478 if (rex_w == 1) {
4479 /* 0x66 is ignored if rex.w is set */
4480 dflag = 2;
4481 }
4482 if (!(prefixes & PREFIX_ADR)) {
4483 aflag = 2;
4484 }
4485 }
4486 #endif
4487
4488 s->prefix = prefixes;
4489 s->aflag = aflag;
4490 s->dflag = dflag;
4491
4492 /* lock generation */
4493 if (prefixes & PREFIX_LOCK)
4494 gen_helper_lock();
4495
4496 /* now check op code */
4497 reswitch:
4498 switch(b) {
4499 case 0x0f:
4500 /**************************/
4501 /* extended op code */
4502 b = cpu_ldub_code(env, s->pc++) | 0x100;
4503 goto reswitch;
4504
4505 /**************************/
4506 /* arith & logic */
4507 case 0x00 ... 0x05:
4508 case 0x08 ... 0x0d:
4509 case 0x10 ... 0x15:
4510 case 0x18 ... 0x1d:
4511 case 0x20 ... 0x25:
4512 case 0x28 ... 0x2d:
4513 case 0x30 ... 0x35:
4514 case 0x38 ... 0x3d:
4515 {
4516 int op, f, val;
4517 op = (b >> 3) & 7;
4518 f = (b >> 1) & 3;
4519
4520 if ((b & 1) == 0)
4521 ot = OT_BYTE;
4522 else
4523 ot = dflag + OT_WORD;
4524
4525 switch(f) {
4526 case 0: /* OP Ev, Gv */
4527 modrm = cpu_ldub_code(env, s->pc++);
4528 reg = ((modrm >> 3) & 7) | rex_r;
4529 mod = (modrm >> 6) & 3;
4530 rm = (modrm & 7) | REX_B(s);
4531 if (mod != 3) {
4532 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4533 opreg = OR_TMP0;
4534 } else if (op == OP_XORL && rm == reg) {
4535 xor_zero:
4536 /* xor reg, reg optimisation */
4537 gen_op_movl_T0_0();
4538 set_cc_op(s, CC_OP_LOGICB + ot);
4539 gen_op_mov_reg_T0(ot, reg);
4540 gen_op_update1_cc();
4541 break;
4542 } else {
4543 opreg = rm;
4544 }
4545 gen_op_mov_TN_reg(ot, 1, reg);
4546 gen_op(s, op, ot, opreg);
4547 break;
4548 case 1: /* OP Gv, Ev */
4549 modrm = cpu_ldub_code(env, s->pc++);
4550 mod = (modrm >> 6) & 3;
4551 reg = ((modrm >> 3) & 7) | rex_r;
4552 rm = (modrm & 7) | REX_B(s);
4553 if (mod != 3) {
4554 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4555 gen_op_ld_T1_A0(ot + s->mem_index);
4556 } else if (op == OP_XORL && rm == reg) {
4557 goto xor_zero;
4558 } else {
4559 gen_op_mov_TN_reg(ot, 1, rm);
4560 }
4561 gen_op(s, op, ot, reg);
4562 break;
4563 case 2: /* OP A, Iv */
4564 val = insn_get(env, s, ot);
4565 gen_op_movl_T1_im(val);
4566 gen_op(s, op, ot, OR_EAX);
4567 break;
4568 }
4569 }
4570 break;
4571
4572 case 0x82:
4573 if (CODE64(s))
4574 goto illegal_op;
4575 case 0x80: /* GRP1 */
4576 case 0x81:
4577 case 0x83:
4578 {
4579 int val;
4580
4581 if ((b & 1) == 0)
4582 ot = OT_BYTE;
4583 else
4584 ot = dflag + OT_WORD;
4585
4586 modrm = cpu_ldub_code(env, s->pc++);
4587 mod = (modrm >> 6) & 3;
4588 rm = (modrm & 7) | REX_B(s);
4589 op = (modrm >> 3) & 7;
4590
4591 if (mod != 3) {
4592 if (b == 0x83)
4593 s->rip_offset = 1;
4594 else
4595 s->rip_offset = insn_const_size(ot);
4596 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4597 opreg = OR_TMP0;
4598 } else {
4599 opreg = rm;
4600 }
4601
4602 switch(b) {
4603 default:
4604 case 0x80:
4605 case 0x81:
4606 case 0x82:
4607 val = insn_get(env, s, ot);
4608 break;
4609 case 0x83:
4610 val = (int8_t)insn_get(env, s, OT_BYTE);
4611 break;
4612 }
4613 gen_op_movl_T1_im(val);
4614 gen_op(s, op, ot, opreg);
4615 }
4616 break;
4617
4618 /**************************/
4619 /* inc, dec, and other misc arith */
4620 case 0x40 ... 0x47: /* inc Gv */
4621 ot = dflag ? OT_LONG : OT_WORD;
4622 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4623 break;
4624 case 0x48 ... 0x4f: /* dec Gv */
4625 ot = dflag ? OT_LONG : OT_WORD;
4626 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4627 break;
4628 case 0xf6: /* GRP3 */
4629 case 0xf7:
4630 if ((b & 1) == 0)
4631 ot = OT_BYTE;
4632 else
4633 ot = dflag + OT_WORD;
4634
4635 modrm = cpu_ldub_code(env, s->pc++);
4636 mod = (modrm >> 6) & 3;
4637 rm = (modrm & 7) | REX_B(s);
4638 op = (modrm >> 3) & 7;
4639 if (mod != 3) {
4640 if (op == 0)
4641 s->rip_offset = insn_const_size(ot);
4642 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4643 gen_op_ld_T0_A0(ot + s->mem_index);
4644 } else {
4645 gen_op_mov_TN_reg(ot, 0, rm);
4646 }
4647
4648 switch(op) {
4649 case 0: /* test */
4650 val = insn_get(env, s, ot);
4651 gen_op_movl_T1_im(val);
4652 gen_op_testl_T0_T1_cc();
4653 set_cc_op(s, CC_OP_LOGICB + ot);
4654 break;
4655 case 2: /* not */
4656 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
4657 if (mod != 3) {
4658 gen_op_st_T0_A0(ot + s->mem_index);
4659 } else {
4660 gen_op_mov_reg_T0(ot, rm);
4661 }
4662 break;
4663 case 3: /* neg */
4664 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
4665 if (mod != 3) {
4666 gen_op_st_T0_A0(ot + s->mem_index);
4667 } else {
4668 gen_op_mov_reg_T0(ot, rm);
4669 }
4670 gen_op_update_neg_cc();
4671 set_cc_op(s, CC_OP_SUBB + ot);
4672 break;
4673 case 4: /* mul */
4674 switch(ot) {
4675 case OT_BYTE:
4676 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
4677 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4678 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4679 /* XXX: use 32 bit mul which could be faster */
4680 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4681 gen_op_mov_reg_T0(OT_WORD, R_EAX);
4682 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4683 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
4684 set_cc_op(s, CC_OP_MULB);
4685 break;
4686 case OT_WORD:
4687 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
4688 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4689 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4690 /* XXX: use 32 bit mul which could be faster */
4691 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4692 gen_op_mov_reg_T0(OT_WORD, R_EAX);
4693 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4694 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4695 gen_op_mov_reg_T0(OT_WORD, R_EDX);
4696 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4697 set_cc_op(s, CC_OP_MULW);
4698 break;
4699 default:
4700 case OT_LONG:
4701 #ifdef TARGET_X86_64
4702 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4703 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
4704 tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
4705 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4706 gen_op_mov_reg_T0(OT_LONG, R_EAX);
4707 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4708 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
4709 gen_op_mov_reg_T0(OT_LONG, R_EDX);
4710 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4711 #else
4712 {
4713 TCGv_i64 t0, t1;
4714 t0 = tcg_temp_new_i64();
4715 t1 = tcg_temp_new_i64();
4716 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4717 tcg_gen_extu_i32_i64(t0, cpu_T[0]);
4718 tcg_gen_extu_i32_i64(t1, cpu_T[1]);
4719 tcg_gen_mul_i64(t0, t0, t1);
4720 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4721 gen_op_mov_reg_T0(OT_LONG, R_EAX);
4722 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4723 tcg_gen_shri_i64(t0, t0, 32);
4724 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4725 gen_op_mov_reg_T0(OT_LONG, R_EDX);
4726 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4727 }
4728 #endif
4729 set_cc_op(s, CC_OP_MULL);
4730 break;
4731 #ifdef TARGET_X86_64
4732 case OT_QUAD:
4733 gen_helper_mulq_EAX_T0(cpu_env, cpu_T[0]);
4734 set_cc_op(s, CC_OP_MULQ);
4735 break;
4736 #endif
4737 }
4738 break;
4739 case 5: /* imul */
4740 switch(ot) {
4741 case OT_BYTE:
4742 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
4743 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4744 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
4745 /* XXX: use 32 bit mul which could be faster */
4746 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4747 gen_op_mov_reg_T0(OT_WORD, R_EAX);
4748 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4749 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
4750 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4751 set_cc_op(s, CC_OP_MULB);
4752 break;
4753 case OT_WORD:
4754 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
4755 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4756 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4757 /* XXX: use 32 bit mul which could be faster */
4758 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4759 gen_op_mov_reg_T0(OT_WORD, R_EAX);
4760 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4761 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4762 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4763 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4764 gen_op_mov_reg_T0(OT_WORD, R_EDX);
4765 set_cc_op(s, CC_OP_MULW);
4766 break;
4767 default:
4768 case OT_LONG:
4769 #ifdef TARGET_X86_64
4770 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4771 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4772 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
4773 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4774 gen_op_mov_reg_T0(OT_LONG, R_EAX);
4775 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4776 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
4777 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4778 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
4779 gen_op_mov_reg_T0(OT_LONG, R_EDX);
4780 #else
4781 {
4782 TCGv_i64 t0, t1;
4783 t0 = tcg_temp_new_i64();
4784 t1 = tcg_temp_new_i64();
4785 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4786 tcg_gen_ext_i32_i64(t0, cpu_T[0]);
4787 tcg_gen_ext_i32_i64(t1, cpu_T[1]);
4788 tcg_gen_mul_i64(t0, t0, t1);
4789 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4790 gen_op_mov_reg_T0(OT_LONG, R_EAX);
4791 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4792 tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
4793 tcg_gen_shri_i64(t0, t0, 32);
4794 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4795 gen_op_mov_reg_T0(OT_LONG, R_EDX);
4796 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4797 }
4798 #endif
4799 set_cc_op(s, CC_OP_MULL);
4800 break;
4801 #ifdef TARGET_X86_64
4802 case OT_QUAD:
4803 gen_helper_imulq_EAX_T0(cpu_env, cpu_T[0]);
4804 set_cc_op(s, CC_OP_MULQ);
4805 break;
4806 #endif
4807 }
4808 break;
4809 case 6: /* div */
4810 switch(ot) {
4811 case OT_BYTE:
4812 gen_jmp_im(pc_start - s->cs_base);
4813 gen_helper_divb_AL(cpu_env, cpu_T[0]);
4814 break;
4815 case OT_WORD:
4816 gen_jmp_im(pc_start - s->cs_base);
4817 gen_helper_divw_AX(cpu_env, cpu_T[0]);
4818 break;
4819 default:
4820 case OT_LONG:
4821 gen_jmp_im(pc_start - s->cs_base);
4822 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
4823 break;
4824 #ifdef TARGET_X86_64
4825 case OT_QUAD:
4826 gen_jmp_im(pc_start - s->cs_base);
4827 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
4828 break;
4829 #endif
4830 }
4831 break;
4832 case 7: /* idiv */
4833 switch(ot) {
4834 case OT_BYTE:
4835 gen_jmp_im(pc_start - s->cs_base);
4836 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
4837 break;
4838 case OT_WORD:
4839 gen_jmp_im(pc_start - s->cs_base);
4840 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
4841 break;
4842 default:
4843 case OT_LONG:
4844 gen_jmp_im(pc_start - s->cs_base);
4845 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
4846 break;
4847 #ifdef TARGET_X86_64
4848 case OT_QUAD:
4849 gen_jmp_im(pc_start - s->cs_base);
4850 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
4851 break;
4852 #endif
4853 }
4854 break;
4855 default:
4856 goto illegal_op;
4857 }
4858 break;
4859
4860 case 0xfe: /* GRP4 */
4861 case 0xff: /* GRP5 */
4862 if ((b & 1) == 0)
4863 ot = OT_BYTE;
4864 else
4865 ot = dflag + OT_WORD;
4866
4867 modrm = cpu_ldub_code(env, s->pc++);
4868 mod = (modrm >> 6) & 3;
4869 rm = (modrm & 7) | REX_B(s);
4870 op = (modrm >> 3) & 7;
4871 if (op >= 2 && b == 0xfe) {
4872 goto illegal_op;
4873 }
4874 if (CODE64(s)) {
4875 if (op == 2 || op == 4) {
4876 /* operand size for jumps is 64 bit */
4877 ot = OT_QUAD;
4878 } else if (op == 3 || op == 5) {
4879 ot = dflag ? OT_LONG + (rex_w == 1) : OT_WORD;
4880 } else if (op == 6) {
4881 /* default push size is 64 bit */
4882 ot = dflag ? OT_QUAD : OT_WORD;
4883 }
4884 }
4885 if (mod != 3) {
4886 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4887 if (op >= 2 && op != 3 && op != 5)
4888 gen_op_ld_T0_A0(ot + s->mem_index);
4889 } else {
4890 gen_op_mov_TN_reg(ot, 0, rm);
4891 }
4892
4893 switch(op) {
4894 case 0: /* inc Ev */
4895 if (mod != 3)
4896 opreg = OR_TMP0;
4897 else
4898 opreg = rm;
4899 gen_inc(s, ot, opreg, 1);
4900 break;
4901 case 1: /* dec Ev */
4902 if (mod != 3)
4903 opreg = OR_TMP0;
4904 else
4905 opreg = rm;
4906 gen_inc(s, ot, opreg, -1);
4907 break;
4908 case 2: /* call Ev */
4909 /* XXX: optimize if memory (no 'and' is necessary) */
4910 if (s->dflag == 0)
4911 gen_op_andl_T0_ffff();
4912 next_eip = s->pc - s->cs_base;
4913 gen_movtl_T1_im(next_eip);
4914 gen_push_T1(s);
4915 gen_op_jmp_T0();
4916 gen_eob(s);
4917 break;
4918 case 3: /* lcall Ev */
4919 gen_op_ld_T1_A0(ot + s->mem_index);
4920 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4921 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
4922 do_lcall:
4923 if (s->pe && !s->vm86) {
4924 gen_update_cc_op(s);
4925 gen_jmp_im(pc_start - s->cs_base);
4926 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4927 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4928 tcg_const_i32(dflag),
4929 tcg_const_i32(s->pc - pc_start));
4930 } else {
4931 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4932 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
4933 tcg_const_i32(dflag),
4934 tcg_const_i32(s->pc - s->cs_base));
4935 }
4936 gen_eob(s);
4937 break;
4938 case 4: /* jmp Ev */
4939 if (s->dflag == 0)
4940 gen_op_andl_T0_ffff();
4941 gen_op_jmp_T0();
4942 gen_eob(s);
4943 break;
4944 case 5: /* ljmp Ev */
4945 gen_op_ld_T1_A0(ot + s->mem_index);
4946 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4947 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
4948 do_ljmp:
4949 if (s->pe && !s->vm86) {
4950 gen_update_cc_op(s);
4951 gen_jmp_im(pc_start - s->cs_base);
4952 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4953 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4954 tcg_const_i32(s->pc - pc_start));
4955 } else {
4956 gen_op_movl_seg_T0_vm(R_CS);
4957 gen_op_movl_T0_T1();
4958 gen_op_jmp_T0();
4959 }
4960 gen_eob(s);
4961 break;
4962 case 6: /* push Ev */
4963 gen_push_T0(s);
4964 break;
4965 default:
4966 goto illegal_op;
4967 }
4968 break;
4969
4970 case 0x84: /* test Ev, Gv */
4971 case 0x85:
4972 if ((b & 1) == 0)
4973 ot = OT_BYTE;
4974 else
4975 ot = dflag + OT_WORD;
4976
4977 modrm = cpu_ldub_code(env, s->pc++);
4978 reg = ((modrm >> 3) & 7) | rex_r;
4979
4980 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4981 gen_op_mov_TN_reg(ot, 1, reg);
4982 gen_op_testl_T0_T1_cc();
4983 set_cc_op(s, CC_OP_LOGICB + ot);
4984 break;
4985
4986 case 0xa8: /* test eAX, Iv */
4987 case 0xa9:
4988 if ((b & 1) == 0)
4989 ot = OT_BYTE;
4990 else
4991 ot = dflag + OT_WORD;
4992 val = insn_get(env, s, ot);
4993
4994 gen_op_mov_TN_reg(ot, 0, OR_EAX);
4995 gen_op_movl_T1_im(val);
4996 gen_op_testl_T0_T1_cc();
4997 set_cc_op(s, CC_OP_LOGICB + ot);
4998 break;
4999
5000 case 0x98: /* CWDE/CBW */
5001 #ifdef TARGET_X86_64
5002 if (dflag == 2) {
5003 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5004 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5005 gen_op_mov_reg_T0(OT_QUAD, R_EAX);
5006 } else
5007 #endif
5008 if (dflag == 1) {
5009 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
5010 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5011 gen_op_mov_reg_T0(OT_LONG, R_EAX);
5012 } else {
5013 gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX);
5014 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5015 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5016 }
5017 break;
5018 case 0x99: /* CDQ/CWD */
5019 #ifdef TARGET_X86_64
5020 if (dflag == 2) {
5021 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5022 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
5023 gen_op_mov_reg_T0(OT_QUAD, R_EDX);
5024 } else
5025 #endif
5026 if (dflag == 1) {
5027 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5028 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5029 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
5030 gen_op_mov_reg_T0(OT_LONG, R_EDX);
5031 } else {
5032 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
5033 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5034 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
5035 gen_op_mov_reg_T0(OT_WORD, R_EDX);
5036 }
5037 break;
5038 case 0x1af: /* imul Gv, Ev */
5039 case 0x69: /* imul Gv, Ev, I */
5040 case 0x6b:
5041 ot = dflag + OT_WORD;
5042 modrm = cpu_ldub_code(env, s->pc++);
5043 reg = ((modrm >> 3) & 7) | rex_r;
5044 if (b == 0x69)
5045 s->rip_offset = insn_const_size(ot);
5046 else if (b == 0x6b)
5047 s->rip_offset = 1;
5048 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5049 if (b == 0x69) {
5050 val = insn_get(env, s, ot);
5051 gen_op_movl_T1_im(val);
5052 } else if (b == 0x6b) {
5053 val = (int8_t)insn_get(env, s, OT_BYTE);
5054 gen_op_movl_T1_im(val);
5055 } else {
5056 gen_op_mov_TN_reg(ot, 1, reg);
5057 }
5058
5059 #ifdef TARGET_X86_64
5060 if (ot == OT_QUAD) {
5061 gen_helper_imulq_T0_T1(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
5062 } else
5063 #endif
5064 if (ot == OT_LONG) {
5065 #ifdef TARGET_X86_64
5066 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5067 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
5068 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5069 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5070 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
5071 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5072 #else
5073 {
5074 TCGv_i64 t0, t1;
5075 t0 = tcg_temp_new_i64();
5076 t1 = tcg_temp_new_i64();
5077 tcg_gen_ext_i32_i64(t0, cpu_T[0]);
5078 tcg_gen_ext_i32_i64(t1, cpu_T[1]);
5079 tcg_gen_mul_i64(t0, t0, t1);
5080 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
5081 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5082 tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
5083 tcg_gen_shri_i64(t0, t0, 32);
5084 tcg_gen_trunc_i64_i32(cpu_T[1], t0);
5085 tcg_gen_sub_tl(cpu_cc_src, cpu_T[1], cpu_tmp0);
5086 }
5087 #endif
5088 } else {
5089 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5090 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5091 /* XXX: use 32 bit mul which could be faster */
5092 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5093 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5094 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5095 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5096 }
5097 gen_op_mov_reg_T0(ot, reg);
5098 set_cc_op(s, CC_OP_MULB + ot);
5099 break;
5100 case 0x1c0:
5101 case 0x1c1: /* xadd Ev, Gv */
5102 if ((b & 1) == 0)
5103 ot = OT_BYTE;
5104 else
5105 ot = dflag + OT_WORD;
5106 modrm = cpu_ldub_code(env, s->pc++);
5107 reg = ((modrm >> 3) & 7) | rex_r;
5108 mod = (modrm >> 6) & 3;
5109 if (mod == 3) {
5110 rm = (modrm & 7) | REX_B(s);
5111 gen_op_mov_TN_reg(ot, 0, reg);
5112 gen_op_mov_TN_reg(ot, 1, rm);
5113 gen_op_addl_T0_T1();
5114 gen_op_mov_reg_T1(ot, reg);
5115 gen_op_mov_reg_T0(ot, rm);
5116 } else {
5117 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5118 gen_op_mov_TN_reg(ot, 0, reg);
5119 gen_op_ld_T1_A0(ot + s->mem_index);
5120 gen_op_addl_T0_T1();
5121 gen_op_st_T0_A0(ot + s->mem_index);
5122 gen_op_mov_reg_T1(ot, reg);
5123 }
5124 gen_op_update2_cc();
5125 set_cc_op(s, CC_OP_ADDB + ot);
5126 break;
5127 case 0x1b0:
5128 case 0x1b1: /* cmpxchg Ev, Gv */
5129 {
5130 int label1, label2;
5131 TCGv t0, t1, t2, a0;
5132
5133 if ((b & 1) == 0)
5134 ot = OT_BYTE;
5135 else
5136 ot = dflag + OT_WORD;
5137 modrm = cpu_ldub_code(env, s->pc++);
5138 reg = ((modrm >> 3) & 7) | rex_r;
5139 mod = (modrm >> 6) & 3;
5140 t0 = tcg_temp_local_new();
5141 t1 = tcg_temp_local_new();
5142 t2 = tcg_temp_local_new();
5143 a0 = tcg_temp_local_new();
5144 gen_op_mov_v_reg(ot, t1, reg);
5145 if (mod == 3) {
5146 rm = (modrm & 7) | REX_B(s);
5147 gen_op_mov_v_reg(ot, t0, rm);
5148 } else {
5149 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5150 tcg_gen_mov_tl(a0, cpu_A0);
5151 gen_op_ld_v(ot + s->mem_index, t0, a0);
5152 rm = 0; /* avoid warning */
5153 }
5154 label1 = gen_new_label();
5155 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5156 gen_extu(ot, t0);
5157 gen_extu(ot, t2);
5158 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
5159 label2 = gen_new_label();
5160 if (mod == 3) {
5161 gen_op_mov_reg_v(ot, R_EAX, t0);
5162 tcg_gen_br(label2);
5163 gen_set_label(label1);
5164 gen_op_mov_reg_v(ot, rm, t1);
5165 } else {
5166 /* perform no-op store cycle like physical cpu; must be
5167 before changing accumulator to ensure idempotency if
5168 the store faults and the instruction is restarted */
5169 gen_op_st_v(ot + s->mem_index, t0, a0);
5170 gen_op_mov_reg_v(ot, R_EAX, t0);
5171 tcg_gen_br(label2);
5172 gen_set_label(label1);
5173 gen_op_st_v(ot + s->mem_index, t1, a0);
5174 }
5175 gen_set_label(label2);
5176 tcg_gen_mov_tl(cpu_cc_src, t0);
5177 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5178 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
5179 set_cc_op(s, CC_OP_SUBB + ot);
5180 tcg_temp_free(t0);
5181 tcg_temp_free(t1);
5182 tcg_temp_free(t2);
5183 tcg_temp_free(a0);
5184 }
5185 break;
5186 case 0x1c7: /* cmpxchg8b */
5187 modrm = cpu_ldub_code(env, s->pc++);
5188 mod = (modrm >> 6) & 3;
5189 if ((mod == 3) || ((modrm & 0x38) != 0x8))
5190 goto illegal_op;
5191 #ifdef TARGET_X86_64
5192 if (dflag == 2) {
5193 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5194 goto illegal_op;
5195 gen_jmp_im(pc_start - s->cs_base);
5196 gen_update_cc_op(s);
5197 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5198 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
5199 } else
5200 #endif
5201 {
5202 if (!(s->cpuid_features & CPUID_CX8))
5203 goto illegal_op;
5204 gen_jmp_im(pc_start - s->cs_base);
5205 gen_update_cc_op(s);
5206 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5207 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
5208 }
5209 set_cc_op(s, CC_OP_EFLAGS);
5210 break;
5211
5212 /**************************/
5213 /* push/pop */
5214 case 0x50 ... 0x57: /* push */
5215 gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
5216 gen_push_T0(s);
5217 break;
5218 case 0x58 ... 0x5f: /* pop */
5219 if (CODE64(s)) {
5220 ot = dflag ? OT_QUAD : OT_WORD;
5221 } else {
5222 ot = dflag + OT_WORD;
5223 }
5224 gen_pop_T0(s);
5225 /* NOTE: order is important for pop %sp */
5226 gen_pop_update(s);
5227 gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
5228 break;
5229 case 0x60: /* pusha */
5230 if (CODE64(s))
5231 goto illegal_op;
5232 gen_pusha(s);
5233 break;
5234 case 0x61: /* popa */
5235 if (CODE64(s))
5236 goto illegal_op;
5237 gen_popa(s);
5238 break;
5239 case 0x68: /* push Iv */
5240 case 0x6a:
5241 if (CODE64(s)) {
5242 ot = dflag ? OT_QUAD : OT_WORD;
5243 } else {
5244 ot = dflag + OT_WORD;
5245 }
5246 if (b == 0x68)
5247 val = insn_get(env, s, ot);
5248 else
5249 val = (int8_t)insn_get(env, s, OT_BYTE);
5250 gen_op_movl_T0_im(val);
5251 gen_push_T0(s);
5252 break;
5253 case 0x8f: /* pop Ev */
5254 if (CODE64(s)) {
5255 ot = dflag ? OT_QUAD : OT_WORD;
5256 } else {
5257 ot = dflag + OT_WORD;
5258 }
5259 modrm = cpu_ldub_code(env, s->pc++);
5260 mod = (modrm >> 6) & 3;
5261 gen_pop_T0(s);
5262 if (mod == 3) {
5263 /* NOTE: order is important for pop %sp */
5264 gen_pop_update(s);
5265 rm = (modrm & 7) | REX_B(s);
5266 gen_op_mov_reg_T0(ot, rm);
5267 } else {
5268 /* NOTE: order is important too for MMU exceptions */
5269 s->popl_esp_hack = 1 << ot;
5270 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5271 s->popl_esp_hack = 0;
5272 gen_pop_update(s);
5273 }
5274 break;
5275 case 0xc8: /* enter */
5276 {
5277 int level;
5278 val = cpu_lduw_code(env, s->pc);
5279 s->pc += 2;
5280 level = cpu_ldub_code(env, s->pc++);
5281 gen_enter(s, val, level);
5282 }
5283 break;
5284 case 0xc9: /* leave */
5285 /* XXX: exception not precise (ESP is updated before potential exception) */
5286 if (CODE64(s)) {
5287 gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
5288 gen_op_mov_reg_T0(OT_QUAD, R_ESP);
5289 } else if (s->ss32) {
5290 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
5291 gen_op_mov_reg_T0(OT_LONG, R_ESP);
5292 } else {
5293 gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
5294 gen_op_mov_reg_T0(OT_WORD, R_ESP);
5295 }
5296 gen_pop_T0(s);
5297 if (CODE64(s)) {
5298 ot = dflag ? OT_QUAD : OT_WORD;
5299 } else {
5300 ot = dflag + OT_WORD;
5301 }
5302 gen_op_mov_reg_T0(ot, R_EBP);
5303 gen_pop_update(s);
5304 break;
5305 case 0x06: /* push es */
5306 case 0x0e: /* push cs */
5307 case 0x16: /* push ss */
5308 case 0x1e: /* push ds */
5309 if (CODE64(s))
5310 goto illegal_op;
5311 gen_op_movl_T0_seg(b >> 3);
5312 gen_push_T0(s);
5313 break;
5314 case 0x1a0: /* push fs */
5315 case 0x1a8: /* push gs */
5316 gen_op_movl_T0_seg((b >> 3) & 7);
5317 gen_push_T0(s);
5318 break;
5319 case 0x07: /* pop es */
5320 case 0x17: /* pop ss */
5321 case 0x1f: /* pop ds */
5322 if (CODE64(s))
5323 goto illegal_op;
5324 reg = b >> 3;
5325 gen_pop_T0(s);
5326 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5327 gen_pop_update(s);
5328 if (reg == R_SS) {
5329 /* if reg == SS, inhibit interrupts/trace. */
5330 /* If several instructions disable interrupts, only the
5331 _first_ does it */
5332 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5333 gen_helper_set_inhibit_irq(cpu_env);
5334 s->tf = 0;
5335 }
5336 if (s->is_jmp) {
5337 gen_jmp_im(s->pc - s->cs_base);
5338 gen_eob(s);
5339 }
5340 break;
5341 case 0x1a1: /* pop fs */
5342 case 0x1a9: /* pop gs */
5343 gen_pop_T0(s);
5344 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
5345 gen_pop_update(s);
5346 if (s->is_jmp) {
5347 gen_jmp_im(s->pc - s->cs_base);
5348 gen_eob(s);
5349 }
5350 break;
5351
5352 /**************************/
5353 /* mov */
5354 case 0x88:
5355 case 0x89: /* mov Gv, Ev */
5356 if ((b & 1) == 0)
5357 ot = OT_BYTE;
5358 else
5359 ot = dflag + OT_WORD;
5360 modrm = cpu_ldub_code(env, s->pc++);
5361 reg = ((modrm >> 3) & 7) | rex_r;
5362
5363 /* generate a generic store */
5364 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
5365 break;
5366 case 0xc6:
5367 case 0xc7: /* mov Ev, Iv */
5368 if ((b & 1) == 0)
5369 ot = OT_BYTE;
5370 else
5371 ot = dflag + OT_WORD;
5372 modrm = cpu_ldub_code(env, s->pc++);
5373 mod = (modrm >> 6) & 3;
5374 if (mod != 3) {
5375 s->rip_offset = insn_const_size(ot);
5376 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5377 }
5378 val = insn_get(env, s, ot);
5379 gen_op_movl_T0_im(val);
5380 if (mod != 3)
5381 gen_op_st_T0_A0(ot + s->mem_index);
5382 else
5383 gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
5384 break;
5385 case 0x8a:
5386 case 0x8b: /* mov Ev, Gv */
5387 if ((b & 1) == 0)
5388 ot = OT_BYTE;
5389 else
5390 ot = OT_WORD + dflag;
5391 modrm = cpu_ldub_code(env, s->pc++);
5392 reg = ((modrm >> 3) & 7) | rex_r;
5393
5394 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
5395 gen_op_mov_reg_T0(ot, reg);
5396 break;
5397 case 0x8e: /* mov seg, Gv */
5398 modrm = cpu_ldub_code(env, s->pc++);
5399 reg = (modrm >> 3) & 7;
5400 if (reg >= 6 || reg == R_CS)
5401 goto illegal_op;
5402 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
5403 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5404 if (reg == R_SS) {
5405 /* if reg == SS, inhibit interrupts/trace */
5406 /* If several instructions disable interrupts, only the
5407 _first_ does it */
5408 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5409 gen_helper_set_inhibit_irq(cpu_env);
5410 s->tf = 0;
5411 }
5412 if (s->is_jmp) {
5413 gen_jmp_im(s->pc - s->cs_base);
5414 gen_eob(s);
5415 }
5416 break;
5417 case 0x8c: /* mov Gv, seg */
5418 modrm = cpu_ldub_code(env, s->pc++);
5419 reg = (modrm >> 3) & 7;
5420 mod = (modrm >> 6) & 3;
5421 if (reg >= 6)
5422 goto illegal_op;
5423 gen_op_movl_T0_seg(reg);
5424 if (mod == 3)
5425 ot = OT_WORD + dflag;
5426 else
5427 ot = OT_WORD;
5428 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
5429 break;
5430
5431 case 0x1b6: /* movzbS Gv, Eb */
5432 case 0x1b7: /* movzwS Gv, Eb */
5433 case 0x1be: /* movsbS Gv, Eb */
5434 case 0x1bf: /* movswS Gv, Eb */
5435 {
5436 int d_ot;
5437 /* d_ot is the size of destination */
5438 d_ot = dflag + OT_WORD;
5439 /* ot is the size of source */
5440 ot = (b & 1) + OT_BYTE;
5441 modrm = cpu_ldub_code(env, s->pc++);
5442 reg = ((modrm >> 3) & 7) | rex_r;
5443 mod = (modrm >> 6) & 3;
5444 rm = (modrm & 7) | REX_B(s);
5445
5446 if (mod == 3) {
5447 gen_op_mov_TN_reg(ot, 0, rm);
5448 switch(ot | (b & 8)) {
5449 case OT_BYTE:
5450 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
5451 break;
5452 case OT_BYTE | 8:
5453 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5454 break;
5455 case OT_WORD:
5456 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
5457 break;
5458 default:
5459 case OT_WORD | 8:
5460 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5461 break;
5462 }
5463 gen_op_mov_reg_T0(d_ot, reg);
5464 } else {
5465 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5466 if (b & 8) {
5467 gen_op_lds_T0_A0(ot + s->mem_index);
5468 } else {
5469 gen_op_ldu_T0_A0(ot + s->mem_index);
5470 }
5471 gen_op_mov_reg_T0(d_ot, reg);
5472 }
5473 }
5474 break;
5475
5476 case 0x8d: /* lea */
5477 ot = dflag + OT_WORD;
5478 modrm = cpu_ldub_code(env, s->pc++);
5479 mod = (modrm >> 6) & 3;
5480 if (mod == 3)
5481 goto illegal_op;
5482 reg = ((modrm >> 3) & 7) | rex_r;
5483 /* we must ensure that no segment is added */
5484 s->override = -1;
5485 val = s->addseg;
5486 s->addseg = 0;
5487 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5488 s->addseg = val;
5489 gen_op_mov_reg_A0(ot - OT_WORD, reg);
5490 break;
5491
5492 case 0xa0: /* mov EAX, Ov */
5493 case 0xa1:
5494 case 0xa2: /* mov Ov, EAX */
5495 case 0xa3:
5496 {
5497 target_ulong offset_addr;
5498
5499 if ((b & 1) == 0)
5500 ot = OT_BYTE;
5501 else
5502 ot = dflag + OT_WORD;
5503 #ifdef TARGET_X86_64
5504 if (s->aflag == 2) {
5505 offset_addr = cpu_ldq_code(env, s->pc);
5506 s->pc += 8;
5507 gen_op_movq_A0_im(offset_addr);
5508 } else
5509 #endif
5510 {
5511 if (s->aflag) {
5512 offset_addr = insn_get(env, s, OT_LONG);
5513 } else {
5514 offset_addr = insn_get(env, s, OT_WORD);
5515 }
5516 gen_op_movl_A0_im(offset_addr);
5517 }
5518 gen_add_A0_ds_seg(s);
5519 if ((b & 2) == 0) {
5520 gen_op_ld_T0_A0(ot + s->mem_index);
5521 gen_op_mov_reg_T0(ot, R_EAX);
5522 } else {
5523 gen_op_mov_TN_reg(ot, 0, R_EAX);
5524 gen_op_st_T0_A0(ot + s->mem_index);
5525 }
5526 }
5527 break;
5528 case 0xd7: /* xlat */
5529 #ifdef TARGET_X86_64
5530 if (s->aflag == 2) {
5531 gen_op_movq_A0_reg(R_EBX);
5532 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5533 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5534 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5535 } else
5536 #endif
5537 {
5538 gen_op_movl_A0_reg(R_EBX);
5539 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5540 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5541 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5542 if (s->aflag == 0)
5543 gen_op_andl_A0_ffff();
5544 else
5545 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
5546 }
5547 gen_add_A0_ds_seg(s);
5548 gen_op_ldu_T0_A0(OT_BYTE + s->mem_index);
5549 gen_op_mov_reg_T0(OT_BYTE, R_EAX);
5550 break;
5551 case 0xb0 ... 0xb7: /* mov R, Ib */
5552 val = insn_get(env, s, OT_BYTE);
5553 gen_op_movl_T0_im(val);
5554 gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
5555 break;
5556 case 0xb8 ... 0xbf: /* mov R, Iv */
5557 #ifdef TARGET_X86_64
5558 if (dflag == 2) {
5559 uint64_t tmp;
5560 /* 64 bit case */
5561 tmp = cpu_ldq_code(env, s->pc);
5562 s->pc += 8;
5563 reg = (b & 7) | REX_B(s);
5564 gen_movtl_T0_im(tmp);
5565 gen_op_mov_reg_T0(OT_QUAD, reg);
5566 } else
5567 #endif
5568 {
5569 ot = dflag ? OT_LONG : OT_WORD;
5570 val = insn_get(env, s, ot);
5571 reg = (b & 7) | REX_B(s);
5572 gen_op_movl_T0_im(val);
5573 gen_op_mov_reg_T0(ot, reg);
5574 }
5575 break;
5576
5577 case 0x91 ... 0x97: /* xchg R, EAX */
5578 do_xchg_reg_eax:
5579 ot = dflag + OT_WORD;
5580 reg = (b & 7) | REX_B(s);
5581 rm = R_EAX;
5582 goto do_xchg_reg;
5583 case 0x86:
5584 case 0x87: /* xchg Ev, Gv */
5585 if ((b & 1) == 0)
5586 ot = OT_BYTE;
5587 else
5588 ot = dflag + OT_WORD;
5589 modrm = cpu_ldub_code(env, s->pc++);
5590 reg = ((modrm >> 3) & 7) | rex_r;
5591 mod = (modrm >> 6) & 3;
5592 if (mod == 3) {
5593 rm = (modrm & 7) | REX_B(s);
5594 do_xchg_reg:
5595 gen_op_mov_TN_reg(ot, 0, reg);
5596 gen_op_mov_TN_reg(ot, 1, rm);
5597 gen_op_mov_reg_T0(ot, rm);
5598 gen_op_mov_reg_T1(ot, reg);
5599 } else {
5600 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5601 gen_op_mov_TN_reg(ot, 0, reg);
5602 /* for xchg, lock is implicit */
5603 if (!(prefixes & PREFIX_LOCK))
5604 gen_helper_lock();
5605 gen_op_ld_T1_A0(ot + s->mem_index);
5606 gen_op_st_T0_A0(ot + s->mem_index);
5607 if (!(prefixes & PREFIX_LOCK))
5608 gen_helper_unlock();
5609 gen_op_mov_reg_T1(ot, reg);
5610 }
5611 break;
5612 case 0xc4: /* les Gv */
5613 /* In CODE64 this is VEX3; see above. */
5614 op = R_ES;
5615 goto do_lxx;
5616 case 0xc5: /* lds Gv */
5617 /* In CODE64 this is VEX2; see above. */
5618 op = R_DS;
5619 goto do_lxx;
5620 case 0x1b2: /* lss Gv */
5621 op = R_SS;
5622 goto do_lxx;
5623 case 0x1b4: /* lfs Gv */
5624 op = R_FS;
5625 goto do_lxx;
5626 case 0x1b5: /* lgs Gv */
5627 op = R_GS;
5628 do_lxx:
5629 ot = dflag ? OT_LONG : OT_WORD;
5630 modrm = cpu_ldub_code(env, s->pc++);
5631 reg = ((modrm >> 3) & 7) | rex_r;
5632 mod = (modrm >> 6) & 3;
5633 if (mod == 3)
5634 goto illegal_op;
5635 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5636 gen_op_ld_T1_A0(ot + s->mem_index);
5637 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
5638 /* load the segment first to handle exceptions properly */
5639 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
5640 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5641 /* then put the data */
5642 gen_op_mov_reg_T1(ot, reg);
5643 if (s->is_jmp) {
5644 gen_jmp_im(s->pc - s->cs_base);
5645 gen_eob(s);
5646 }
5647 break;
5648
5649 /************************/
5650 /* shifts */
5651 case 0xc0:
5652 case 0xc1:
5653 /* shift Ev,Ib */
5654 shift = 2;
5655 grp2:
5656 {
5657 if ((b & 1) == 0)
5658 ot = OT_BYTE;
5659 else
5660 ot = dflag + OT_WORD;
5661
5662 modrm = cpu_ldub_code(env, s->pc++);
5663 mod = (modrm >> 6) & 3;
5664 op = (modrm >> 3) & 7;
5665
5666 if (mod != 3) {
5667 if (shift == 2) {
5668 s->rip_offset = 1;
5669 }
5670 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5671 opreg = OR_TMP0;
5672 } else {
5673 opreg = (modrm & 7) | REX_B(s);
5674 }
5675
5676 /* simpler op */
5677 if (shift == 0) {
5678 gen_shift(s, op, ot, opreg, OR_ECX);
5679 } else {
5680 if (shift == 2) {
5681 shift = cpu_ldub_code(env, s->pc++);
5682 }
5683 gen_shifti(s, op, ot, opreg, shift);
5684 }
5685 }
5686 break;
5687 case 0xd0:
5688 case 0xd1:
5689 /* shift Ev,1 */
5690 shift = 1;
5691 goto grp2;
5692 case 0xd2:
5693 case 0xd3:
5694 /* shift Ev,cl */
5695 shift = 0;
5696 goto grp2;
5697
5698 case 0x1a4: /* shld imm */
5699 op = 0;
5700 shift = 1;
5701 goto do_shiftd;
5702 case 0x1a5: /* shld cl */
5703 op = 0;
5704 shift = 0;
5705 goto do_shiftd;
5706 case 0x1ac: /* shrd imm */
5707 op = 1;
5708 shift = 1;
5709 goto do_shiftd;
5710 case 0x1ad: /* shrd cl */
5711 op = 1;
5712 shift = 0;
5713 do_shiftd:
5714 ot = dflag + OT_WORD;
5715 modrm = cpu_ldub_code(env, s->pc++);
5716 mod = (modrm >> 6) & 3;
5717 rm = (modrm & 7) | REX_B(s);
5718 reg = ((modrm >> 3) & 7) | rex_r;
5719 if (mod != 3) {
5720 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5721 opreg = OR_TMP0;
5722 } else {
5723 opreg = rm;
5724 }
5725 gen_op_mov_TN_reg(ot, 1, reg);
5726
5727 if (shift) {
5728 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5729 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5730 tcg_temp_free(imm);
5731 } else {
5732 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
5733 }
5734 break;
5735
5736 /************************/
5737 /* floats */
5738 case 0xd8 ... 0xdf:
5739 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5740 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5741 /* XXX: what to do if illegal op ? */
5742 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5743 break;
5744 }
5745 modrm = cpu_ldub_code(env, s->pc++);
5746 mod = (modrm >> 6) & 3;
5747 rm = modrm & 7;
5748 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5749 if (mod != 3) {
5750 /* memory op */
5751 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
5752 switch(op) {
5753 case 0x00 ... 0x07: /* fxxxs */
5754 case 0x10 ... 0x17: /* fixxxl */
5755 case 0x20 ... 0x27: /* fxxxl */
5756 case 0x30 ... 0x37: /* fixxx */
5757 {
5758 int op1;
5759 op1 = op & 7;
5760
5761 switch(op >> 4) {
5762 case 0:
5763 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5764 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5765 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
5766 break;
5767 case 1:
5768 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5769 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5770 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5771 break;
5772 case 2:
5773 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
5774 (s->mem_index >> 2) - 1);
5775 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
5776 break;
5777 case 3:
5778 default:
5779 gen_op_lds_T0_A0(OT_WORD + s->mem_index);
5780 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5781 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
5782 break;
5783 }
5784
5785 gen_helper_fp_arith_ST0_FT0(op1);
5786 if (op1 == 3) {
5787 /* fcomp needs pop */
5788 gen_helper_fpop(cpu_env);
5789 }
5790 }
5791 break;
5792 case 0x08: /* flds */
5793 case 0x0a: /* fsts */
5794 case 0x0b: /* fstps */
5795 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5796 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5797 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
5798 switch(op & 7) {
5799 case 0:
5800 switch(op >> 4) {
5801 case 0:
5802 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5803 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5804 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
5805 break;
5806 case 1:
5807 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5808 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5809 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5810 break;
5811 case 2:
5812 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
5813 (s->mem_index >> 2) - 1);
5814 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
5815 break;
5816 case 3:
5817 default:
5818 gen_op_lds_T0_A0(OT_WORD + s->mem_index);
5819 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5820 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
5821 break;
5822 }
5823 break;
5824 case 1:
5825 /* XXX: the corresponding CPUID bit must be tested ! */
5826 switch(op >> 4) {
5827 case 1:
5828 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
5829 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5830 gen_op_st_T0_A0(OT_LONG + s->mem_index);
5831 break;
5832 case 2:
5833 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
5834 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
5835 (s->mem_index >> 2) - 1);
5836 break;
5837 case 3:
5838 default:
5839 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
5840 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5841 gen_op_st_T0_A0(OT_WORD + s->mem_index);
5842 break;
5843 }
5844 gen_helper_fpop(cpu_env);
5845 break;
5846 default:
5847 switch(op >> 4) {
5848 case 0:
5849 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
5850 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5851 gen_op_st_T0_A0(OT_LONG + s->mem_index);
5852 break;
5853 case 1:
5854 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
5855 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5856 gen_op_st_T0_A0(OT_LONG + s->mem_index);
5857 break;
5858 case 2:
5859 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
5860 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
5861 (s->mem_index >> 2) - 1);
5862 break;
5863 case 3:
5864 default:
5865 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
5866 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5867 gen_op_st_T0_A0(OT_WORD + s->mem_index);
5868 break;
5869 }
5870 if ((op & 7) == 3)
5871 gen_helper_fpop(cpu_env);
5872 break;
5873 }
5874 break;
5875 case 0x0c: /* fldenv mem */
5876 gen_update_cc_op(s);
5877 gen_jmp_im(pc_start - s->cs_base);
5878 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
5879 break;
5880 case 0x0d: /* fldcw mem */
5881 gen_op_ld_T0_A0(OT_WORD + s->mem_index);
5882 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5883 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
5884 break;
5885 case 0x0e: /* fnstenv mem */
5886 gen_update_cc_op(s);
5887 gen_jmp_im(pc_start - s->cs_base);
5888 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
5889 break;
5890 case 0x0f: /* fnstcw mem */
5891 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
5892 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5893 gen_op_st_T0_A0(OT_WORD + s->mem_index);
5894 break;
5895 case 0x1d: /* fldt mem */
5896 gen_update_cc_op(s);
5897 gen_jmp_im(pc_start - s->cs_base);
5898 gen_helper_fldt_ST0(cpu_env, cpu_A0);
5899 break;
5900 case 0x1f: /* fstpt mem */
5901 gen_update_cc_op(s);
5902 gen_jmp_im(pc_start - s->cs_base);
5903 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5904 gen_helper_fpop(cpu_env);
5905 break;
5906 case 0x2c: /* frstor mem */
5907 gen_update_cc_op(s);
5908 gen_jmp_im(pc_start - s->cs_base);
5909 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
5910 break;
5911 case 0x2e: /* fnsave mem */
5912 gen_update_cc_op(s);
5913 gen_jmp_im(pc_start - s->cs_base);
5914 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
5915 break;
5916 case 0x2f: /* fnstsw mem */
5917 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
5918 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5919 gen_op_st_T0_A0(OT_WORD + s->mem_index);
5920 break;
5921 case 0x3c: /* fbld */
5922 gen_update_cc_op(s);
5923 gen_jmp_im(pc_start - s->cs_base);
5924 gen_helper_fbld_ST0(cpu_env, cpu_A0);
5925 break;
5926 case 0x3e: /* fbstp */
5927 gen_update_cc_op(s);
5928 gen_jmp_im(pc_start - s->cs_base);
5929 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5930 gen_helper_fpop(cpu_env);
5931 break;
5932 case 0x3d: /* fildll */
5933 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
5934 (s->mem_index >> 2) - 1);
5935 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
5936 break;
5937 case 0x3f: /* fistpll */
5938 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
5939 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
5940 (s->mem_index >> 2) - 1);
5941 gen_helper_fpop(cpu_env);
5942 break;
5943 default:
5944 goto illegal_op;
5945 }
5946 } else {
5947 /* register float ops */
5948 opreg = rm;
5949
5950 switch(op) {
5951 case 0x08: /* fld sti */
5952 gen_helper_fpush(cpu_env);
5953 gen_helper_fmov_ST0_STN(cpu_env,
5954 tcg_const_i32((opreg + 1) & 7));
5955 break;
5956 case 0x09: /* fxchg sti */
5957 case 0x29: /* fxchg4 sti, undocumented op */
5958 case 0x39: /* fxchg7 sti, undocumented op */
5959 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
5960 break;
5961 case 0x0a: /* grp d9/2 */
5962 switch(rm) {
5963 case 0: /* fnop */
5964 /* check exceptions (FreeBSD FPU probe) */
5965 gen_update_cc_op(s);
5966 gen_jmp_im(pc_start - s->cs_base);
5967 gen_helper_fwait(cpu_env);
5968 break;
5969 default:
5970 goto illegal_op;
5971 }
5972 break;
5973 case 0x0c: /* grp d9/4 */
5974 switch(rm) {
5975 case 0: /* fchs */
5976 gen_helper_fchs_ST0(cpu_env);
5977 break;
5978 case 1: /* fabs */
5979 gen_helper_fabs_ST0(cpu_env);
5980 break;
5981 case 4: /* ftst */
5982 gen_helper_fldz_FT0(cpu_env);
5983 gen_helper_fcom_ST0_FT0(cpu_env);
5984 break;
5985 case 5: /* fxam */
5986 gen_helper_fxam_ST0(cpu_env);
5987 break;
5988 default:
5989 goto illegal_op;
5990 }
5991 break;
5992 case 0x0d: /* grp d9/5 */
5993 {
5994 switch(rm) {
5995 case 0:
5996 gen_helper_fpush(cpu_env);
5997 gen_helper_fld1_ST0(cpu_env);
5998 break;
5999 case 1:
6000 gen_helper_fpush(cpu_env);
6001 gen_helper_fldl2t_ST0(cpu_env);
6002 break;
6003 case 2:
6004 gen_helper_fpush(cpu_env);
6005 gen_helper_fldl2e_ST0(cpu_env);
6006 break;
6007 case 3:
6008 gen_helper_fpush(cpu_env);
6009 gen_helper_fldpi_ST0(cpu_env);
6010 break;
6011 case 4:
6012 gen_helper_fpush(cpu_env);
6013 gen_helper_fldlg2_ST0(cpu_env);
6014 break;
6015 case 5:
6016 gen_helper_fpush(cpu_env);
6017 gen_helper_fldln2_ST0(cpu_env);
6018 break;
6019 case 6:
6020 gen_helper_fpush(cpu_env);
6021 gen_helper_fldz_ST0(cpu_env);
6022 break;
6023 default:
6024 goto illegal_op;
6025 }
6026 }
6027 break;
6028 case 0x0e: /* grp d9/6 */
6029 switch(rm) {
6030 case 0: /* f2xm1 */
6031 gen_helper_f2xm1(cpu_env);
6032 break;
6033 case 1: /* fyl2x */
6034 gen_helper_fyl2x(cpu_env);
6035 break;
6036 case 2: /* fptan */
6037 gen_helper_fptan(cpu_env);
6038 break;
6039 case 3: /* fpatan */
6040 gen_helper_fpatan(cpu_env);
6041 break;
6042 case 4: /* fxtract */
6043 gen_helper_fxtract(cpu_env);
6044 break;
6045 case 5: /* fprem1 */
6046 gen_helper_fprem1(cpu_env);
6047 break;
6048 case 6: /* fdecstp */
6049 gen_helper_fdecstp(cpu_env);
6050 break;
6051 default:
6052 case 7: /* fincstp */
6053 gen_helper_fincstp(cpu_env);
6054 break;
6055 }
6056 break;
6057 case 0x0f: /* grp d9/7 */
6058 switch(rm) {
6059 case 0: /* fprem */
6060 gen_helper_fprem(cpu_env);
6061 break;
6062 case 1: /* fyl2xp1 */
6063 gen_helper_fyl2xp1(cpu_env);
6064 break;
6065 case 2: /* fsqrt */
6066 gen_helper_fsqrt(cpu_env);
6067 break;
6068 case 3: /* fsincos */
6069 gen_helper_fsincos(cpu_env);
6070 break;
6071 case 5: /* fscale */
6072 gen_helper_fscale(cpu_env);
6073 break;
6074 case 4: /* frndint */
6075 gen_helper_frndint(cpu_env);
6076 break;
6077 case 6: /* fsin */
6078 gen_helper_fsin(cpu_env);
6079 break;
6080 default:
6081 case 7: /* fcos */
6082 gen_helper_fcos(cpu_env);
6083 break;
6084 }
6085 break;
6086 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6087 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6088 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6089 {
6090 int op1;
6091
6092 op1 = op & 7;
6093 if (op >= 0x20) {
6094 gen_helper_fp_arith_STN_ST0(op1, opreg);
6095 if (op >= 0x30)
6096 gen_helper_fpop(cpu_env);
6097 } else {
6098 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6099 gen_helper_fp_arith_ST0_FT0(op1);
6100 }
6101 }
6102 break;
6103 case 0x02: /* fcom */
6104 case 0x22: /* fcom2, undocumented op */
6105 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6106 gen_helper_fcom_ST0_FT0(cpu_env);
6107 break;
6108 case 0x03: /* fcomp */
6109 case 0x23: /* fcomp3, undocumented op */
6110 case 0x32: /* fcomp5, undocumented op */
6111 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6112 gen_helper_fcom_ST0_FT0(cpu_env);
6113 gen_helper_fpop(cpu_env);
6114 break;
6115 case 0x15: /* da/5 */
6116 switch(rm) {
6117 case 1: /* fucompp */
6118 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6119 gen_helper_fucom_ST0_FT0(cpu_env);
6120 gen_helper_fpop(cpu_env);
6121 gen_helper_fpop(cpu_env);
6122 break;
6123 default:
6124 goto illegal_op;
6125 }
6126 break;
6127 case 0x1c:
6128 switch(rm) {
6129 case 0: /* feni (287 only, just do nop here) */
6130 break;
6131 case 1: /* fdisi (287 only, just do nop here) */
6132 break;
6133 case 2: /* fclex */
6134 gen_helper_fclex(cpu_env);
6135 break;
6136 case 3: /* fninit */
6137 gen_helper_fninit(cpu_env);
6138 break;
6139 case 4: /* fsetpm (287 only, just do nop here) */
6140 break;
6141 default:
6142 goto illegal_op;
6143 }
6144 break;
6145 case 0x1d: /* fucomi */
6146 gen_update_cc_op(s);
6147 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6148 gen_helper_fucomi_ST0_FT0(cpu_env);
6149 set_cc_op(s, CC_OP_EFLAGS);
6150 break;
6151 case 0x1e: /* fcomi */
6152 gen_update_cc_op(s);
6153 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6154 gen_helper_fcomi_ST0_FT0(cpu_env);
6155 set_cc_op(s, CC_OP_EFLAGS);
6156 break;
6157 case 0x28: /* ffree sti */
6158 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6159 break;
6160 case 0x2a: /* fst sti */
6161 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6162 break;
6163 case 0x2b: /* fstp sti */
6164 case 0x0b: /* fstp1 sti, undocumented op */
6165 case 0x3a: /* fstp8 sti, undocumented op */
6166 case 0x3b: /* fstp9 sti, undocumented op */
6167 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6168 gen_helper_fpop(cpu_env);
6169 break;
6170 case 0x2c: /* fucom st(i) */
6171 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6172 gen_helper_fucom_ST0_FT0(cpu_env);
6173 break;
6174 case 0x2d: /* fucomp st(i) */
6175 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6176 gen_helper_fucom_ST0_FT0(cpu_env);
6177 gen_helper_fpop(cpu_env);
6178 break;
6179 case 0x33: /* de/3 */
6180 switch(rm) {
6181 case 1: /* fcompp */
6182 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6183 gen_helper_fcom_ST0_FT0(cpu_env);
6184 gen_helper_fpop(cpu_env);
6185 gen_helper_fpop(cpu_env);
6186 break;
6187 default:
6188 goto illegal_op;
6189 }
6190 break;
6191 case 0x38: /* ffreep sti, undocumented op */
6192 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6193 gen_helper_fpop(cpu_env);
6194 break;
6195 case 0x3c: /* df/4 */
6196 switch(rm) {
6197 case 0:
6198 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6199 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
6200 gen_op_mov_reg_T0(OT_WORD, R_EAX);
6201 break;
6202 default:
6203 goto illegal_op;
6204 }
6205 break;
6206 case 0x3d: /* fucomip */
6207 gen_update_cc_op(s);
6208 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6209 gen_helper_fucomi_ST0_FT0(cpu_env);
6210 gen_helper_fpop(cpu_env);
6211 set_cc_op(s, CC_OP_EFLAGS);
6212 break;
6213 case 0x3e: /* fcomip */
6214 gen_update_cc_op(s);
6215 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6216 gen_helper_fcomi_ST0_FT0(cpu_env);
6217 gen_helper_fpop(cpu_env);
6218 set_cc_op(s, CC_OP_EFLAGS);
6219 break;
6220 case 0x10 ... 0x13: /* fcmovxx */
6221 case 0x18 ... 0x1b:
6222 {
6223 int op1, l1;
6224 static const uint8_t fcmov_cc[8] = {
6225 (JCC_B << 1),
6226 (JCC_Z << 1),
6227 (JCC_BE << 1),
6228 (JCC_P << 1),
6229 };
6230 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
6231 l1 = gen_new_label();
6232 gen_jcc1_noeob(s, op1, l1);
6233 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
6234 gen_set_label(l1);
6235 }
6236 break;
6237 default:
6238 goto illegal_op;
6239 }
6240 }
6241 break;
6242 /************************/
6243 /* string ops */
6244
6245 case 0xa4: /* movsS */
6246 case 0xa5:
6247 if ((b & 1) == 0)
6248 ot = OT_BYTE;
6249 else
6250 ot = dflag + OT_WORD;
6251
6252 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6253 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6254 } else {
6255 gen_movs(s, ot);
6256 }
6257 break;
6258
6259 case 0xaa: /* stosS */
6260 case 0xab:
6261 if ((b & 1) == 0)
6262 ot = OT_BYTE;
6263 else
6264 ot = dflag + OT_WORD;
6265
6266 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6267 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6268 } else {
6269 gen_stos(s, ot);
6270 }
6271 break;
6272 case 0xac: /* lodsS */
6273 case 0xad:
6274 if ((b & 1) == 0)
6275 ot = OT_BYTE;
6276 else
6277 ot = dflag + OT_WORD;
6278 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6279 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6280 } else {
6281 gen_lods(s, ot);
6282 }
6283 break;
6284 case 0xae: /* scasS */
6285 case 0xaf:
6286 if ((b & 1) == 0)
6287 ot = OT_BYTE;
6288 else
6289 ot = dflag + OT_WORD;
6290 if (prefixes & PREFIX_REPNZ) {
6291 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6292 } else if (prefixes & PREFIX_REPZ) {
6293 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6294 } else {
6295 gen_scas(s, ot);
6296 }
6297 break;
6298
6299 case 0xa6: /* cmpsS */
6300 case 0xa7:
6301 if ((b & 1) == 0)
6302 ot = OT_BYTE;
6303 else
6304 ot = dflag + OT_WORD;
6305 if (prefixes & PREFIX_REPNZ) {
6306 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6307 } else if (prefixes & PREFIX_REPZ) {
6308 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6309 } else {
6310 gen_cmps(s, ot);
6311 }
6312 break;
6313 case 0x6c: /* insS */
6314 case 0x6d:
6315 if ((b & 1) == 0)
6316 ot = OT_BYTE;
6317 else
6318 ot = dflag ? OT_LONG : OT_WORD;
6319 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
6320 gen_op_andl_T0_ffff();
6321 gen_check_io(s, ot, pc_start - s->cs_base,
6322 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
6323 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6324 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6325 } else {
6326 gen_ins(s, ot);
6327 if (use_icount) {
6328 gen_jmp(s, s->pc - s->cs_base);
6329 }
6330 }
6331 break;
6332 case 0x6e: /* outsS */
6333 case 0x6f:
6334 if ((b & 1) == 0)
6335 ot = OT_BYTE;
6336 else
6337 ot = dflag ? OT_LONG : OT_WORD;
6338 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
6339 gen_op_andl_T0_ffff();
6340 gen_check_io(s, ot, pc_start - s->cs_base,
6341 svm_is_rep(prefixes) | 4);
6342 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6343 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6344 } else {
6345 gen_outs(s, ot);
6346 if (use_icount) {
6347 gen_jmp(s, s->pc - s->cs_base);
6348 }
6349 }
6350 break;
6351
6352 /************************/
6353 /* port I/O */
6354
6355 case 0xe4:
6356 case 0xe5:
6357 if ((b & 1) == 0)
6358 ot = OT_BYTE;
6359 else
6360 ot = dflag ? OT_LONG : OT_WORD;
6361 val = cpu_ldub_code(env, s->pc++);
6362 gen_op_movl_T0_im(val);
6363 gen_check_io(s, ot, pc_start - s->cs_base,
6364 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6365 if (use_icount)
6366 gen_io_start();
6367 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6368 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6369 gen_op_mov_reg_T1(ot, R_EAX);
6370 if (use_icount) {
6371 gen_io_end();
6372 gen_jmp(s, s->pc - s->cs_base);
6373 }
6374 break;
6375 case 0xe6:
6376 case 0xe7:
6377 if ((b & 1) == 0)
6378 ot = OT_BYTE;
6379 else
6380 ot = dflag ? OT_LONG : OT_WORD;
6381 val = cpu_ldub_code(env, s->pc++);
6382 gen_op_movl_T0_im(val);
6383 gen_check_io(s, ot, pc_start - s->cs_base,
6384 svm_is_rep(prefixes));
6385 gen_op_mov_TN_reg(ot, 1, R_EAX);
6386
6387 if (use_icount)
6388 gen_io_start();
6389 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6390 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6391 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6392 if (use_icount) {
6393 gen_io_end();
6394 gen_jmp(s, s->pc - s->cs_base);
6395 }
6396 break;
6397 case 0xec:
6398 case 0xed:
6399 if ((b & 1) == 0)
6400 ot = OT_BYTE;
6401 else
6402 ot = dflag ? OT_LONG : OT_WORD;
6403 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
6404 gen_op_andl_T0_ffff();
6405 gen_check_io(s, ot, pc_start - s->cs_base,
6406 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6407 if (use_icount)
6408 gen_io_start();
6409 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6410 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6411 gen_op_mov_reg_T1(ot, R_EAX);
6412 if (use_icount) {
6413 gen_io_end();
6414 gen_jmp(s, s->pc - s->cs_base);
6415 }
6416 break;
6417 case 0xee:
6418 case 0xef:
6419 if ((b & 1) == 0)
6420 ot = OT_BYTE;
6421 else
6422 ot = dflag ? OT_LONG : OT_WORD;
6423 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
6424 gen_op_andl_T0_ffff();
6425 gen_check_io(s, ot, pc_start - s->cs_base,
6426 svm_is_rep(prefixes));
6427 gen_op_mov_TN_reg(ot, 1, R_EAX);
6428
6429 if (use_icount)
6430 gen_io_start();
6431 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6432 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6433 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6434 if (use_icount) {
6435 gen_io_end();
6436 gen_jmp(s, s->pc - s->cs_base);
6437 }
6438 break;
6439
6440 /************************/
6441 /* control */
6442 case 0xc2: /* ret im */
6443 val = cpu_ldsw_code(env, s->pc);
6444 s->pc += 2;
6445 gen_pop_T0(s);
6446 if (CODE64(s) && s->dflag)
6447 s->dflag = 2;
6448 gen_stack_update(s, val + (2 << s->dflag));
6449 if (s->dflag == 0)
6450 gen_op_andl_T0_ffff();
6451 gen_op_jmp_T0();
6452 gen_eob(s);
6453 break;
6454 case 0xc3: /* ret */
6455 gen_pop_T0(s);
6456 gen_pop_update(s);
6457 if (s->dflag == 0)
6458 gen_op_andl_T0_ffff();
6459 gen_op_jmp_T0();
6460 gen_eob(s);
6461 break;
6462 case 0xca: /* lret im */
6463 val = cpu_ldsw_code(env, s->pc);
6464 s->pc += 2;
6465 do_lret:
6466 if (s->pe && !s->vm86) {
6467 gen_update_cc_op(s);
6468 gen_jmp_im(pc_start - s->cs_base);
6469 gen_helper_lret_protected(cpu_env, tcg_const_i32(s->dflag),
6470 tcg_const_i32(val));
6471 } else {
6472 gen_stack_A0(s);
6473 /* pop offset */
6474 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
6475 if (s->dflag == 0)
6476 gen_op_andl_T0_ffff();
6477 /* NOTE: keeping EIP updated is not a problem in case of
6478 exception */
6479 gen_op_jmp_T0();
6480 /* pop selector */
6481 gen_op_addl_A0_im(2 << s->dflag);
6482 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
6483 gen_op_movl_seg_T0_vm(R_CS);
6484 /* add stack offset */
6485 gen_stack_update(s, val + (4 << s->dflag));
6486 }
6487 gen_eob(s);
6488 break;
6489 case 0xcb: /* lret */
6490 val = 0;
6491 goto do_lret;
6492 case 0xcf: /* iret */
6493 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
6494 if (!s->pe) {
6495 /* real mode */
6496 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
6497 set_cc_op(s, CC_OP_EFLAGS);
6498 } else if (s->vm86) {
6499 if (s->iopl != 3) {
6500 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6501 } else {
6502 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
6503 set_cc_op(s, CC_OP_EFLAGS);
6504 }
6505 } else {
6506 gen_update_cc_op(s);
6507 gen_jmp_im(pc_start - s->cs_base);
6508 gen_helper_iret_protected(cpu_env, tcg_const_i32(s->dflag),
6509 tcg_const_i32(s->pc - s->cs_base));
6510 set_cc_op(s, CC_OP_EFLAGS);
6511 }
6512 gen_eob(s);
6513 break;
6514 case 0xe8: /* call im */
6515 {
6516 if (dflag)
6517 tval = (int32_t)insn_get(env, s, OT_LONG);
6518 else
6519 tval = (int16_t)insn_get(env, s, OT_WORD);
6520 next_eip = s->pc - s->cs_base;
6521 tval += next_eip;
6522 if (s->dflag == 0)
6523 tval &= 0xffff;
6524 else if(!CODE64(s))
6525 tval &= 0xffffffff;
6526 gen_movtl_T0_im(next_eip);
6527 gen_push_T0(s);
6528 gen_jmp(s, tval);
6529 }
6530 break;
6531 case 0x9a: /* lcall im */
6532 {
6533 unsigned int selector, offset;
6534
6535 if (CODE64(s))
6536 goto illegal_op;
6537 ot = dflag ? OT_LONG : OT_WORD;
6538 offset = insn_get(env, s, ot);
6539 selector = insn_get(env, s, OT_WORD);
6540
6541 gen_op_movl_T0_im(selector);
6542 gen_op_movl_T1_imu(offset);
6543 }
6544 goto do_lcall;
6545 case 0xe9: /* jmp im */
6546 if (dflag)
6547 tval = (int32_t)insn_get(env, s, OT_LONG);
6548 else
6549 tval = (int16_t)insn_get(env, s, OT_WORD);
6550 tval += s->pc - s->cs_base;
6551 if (s->dflag == 0)
6552 tval &= 0xffff;
6553 else if(!CODE64(s))
6554 tval &= 0xffffffff;
6555 gen_jmp(s, tval);
6556 break;
6557 case 0xea: /* ljmp im */
6558 {
6559 unsigned int selector, offset;
6560
6561 if (CODE64(s))
6562 goto illegal_op;
6563 ot = dflag ? OT_LONG : OT_WORD;
6564 offset = insn_get(env, s, ot);
6565 selector = insn_get(env, s, OT_WORD);
6566
6567 gen_op_movl_T0_im(selector);
6568 gen_op_movl_T1_imu(offset);
6569 }
6570 goto do_ljmp;
6571 case 0xeb: /* jmp Jb */
6572 tval = (int8_t)insn_get(env, s, OT_BYTE);
6573 tval += s->pc - s->cs_base;
6574 if (s->dflag == 0)
6575 tval &= 0xffff;
6576 gen_jmp(s, tval);
6577 break;
6578 case 0x70 ... 0x7f: /* jcc Jb */
6579 tval = (int8_t)insn_get(env, s, OT_BYTE);
6580 goto do_jcc;
6581 case 0x180 ... 0x18f: /* jcc Jv */
6582 if (dflag) {
6583 tval = (int32_t)insn_get(env, s, OT_LONG);
6584 } else {
6585 tval = (int16_t)insn_get(env, s, OT_WORD);
6586 }
6587 do_jcc:
6588 next_eip = s->pc - s->cs_base;
6589 tval += next_eip;
6590 if (s->dflag == 0)
6591 tval &= 0xffff;
6592 gen_jcc(s, b, tval, next_eip);
6593 break;
6594
6595 case 0x190 ... 0x19f: /* setcc Gv */
6596 modrm = cpu_ldub_code(env, s->pc++);
6597 gen_setcc1(s, b, cpu_T[0]);
6598 gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1);
6599 break;
6600 case 0x140 ... 0x14f: /* cmov Gv, Ev */
6601 ot = dflag + OT_WORD;
6602 modrm = cpu_ldub_code(env, s->pc++);
6603 reg = ((modrm >> 3) & 7) | rex_r;
6604 gen_cmovcc1(env, s, ot, b, modrm, reg);
6605 break;
6606
6607 /************************/
6608 /* flags */
6609 case 0x9c: /* pushf */
6610 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
6611 if (s->vm86 && s->iopl != 3) {
6612 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6613 } else {
6614 gen_update_cc_op(s);
6615 gen_helper_read_eflags(cpu_T[0], cpu_env);
6616 gen_push_T0(s);
6617 }
6618 break;
6619 case 0x9d: /* popf */
6620 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
6621 if (s->vm86 && s->iopl != 3) {
6622 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6623 } else {
6624 gen_pop_T0(s);
6625 if (s->cpl == 0) {
6626 if (s->dflag) {
6627 gen_helper_write_eflags(cpu_env, cpu_T[0],
6628 tcg_const_i32((TF_MASK | AC_MASK |
6629 ID_MASK | NT_MASK |
6630 IF_MASK |
6631 IOPL_MASK)));
6632 } else {
6633 gen_helper_write_eflags(cpu_env, cpu_T[0],
6634 tcg_const_i32((TF_MASK | AC_MASK |
6635 ID_MASK | NT_MASK |
6636 IF_MASK | IOPL_MASK)
6637 & 0xffff));
6638 }
6639 } else {
6640 if (s->cpl <= s->iopl) {
6641 if (s->dflag) {
6642 gen_helper_write_eflags(cpu_env, cpu_T[0],
6643 tcg_const_i32((TF_MASK |
6644 AC_MASK |
6645 ID_MASK |
6646 NT_MASK |
6647 IF_MASK)));
6648 } else {
6649 gen_helper_write_eflags(cpu_env, cpu_T[0],
6650 tcg_const_i32((TF_MASK |
6651 AC_MASK |
6652 ID_MASK |
6653 NT_MASK |
6654 IF_MASK)
6655 & 0xffff));
6656 }
6657 } else {
6658 if (s->dflag) {
6659 gen_helper_write_eflags(cpu_env, cpu_T[0],
6660 tcg_const_i32((TF_MASK | AC_MASK |
6661 ID_MASK | NT_MASK)));
6662 } else {
6663 gen_helper_write_eflags(cpu_env, cpu_T[0],
6664 tcg_const_i32((TF_MASK | AC_MASK |
6665 ID_MASK | NT_MASK)
6666 & 0xffff));
6667 }
6668 }
6669 }
6670 gen_pop_update(s);
6671 set_cc_op(s, CC_OP_EFLAGS);
6672 /* abort translation because TF/AC flag may change */
6673 gen_jmp_im(s->pc - s->cs_base);
6674 gen_eob(s);
6675 }
6676 break;
6677 case 0x9e: /* sahf */
6678 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6679 goto illegal_op;
6680 gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
6681 gen_compute_eflags(s);
6682 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6683 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6684 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
6685 break;
6686 case 0x9f: /* lahf */
6687 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
6688 goto illegal_op;
6689 gen_compute_eflags(s);
6690 /* Note: gen_compute_eflags() only gives the condition codes */
6691 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
6692 gen_op_mov_reg_T0(OT_BYTE, R_AH);
6693 break;
6694 case 0xf5: /* cmc */
6695 gen_compute_eflags(s);
6696 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6697 break;
6698 case 0xf8: /* clc */
6699 gen_compute_eflags(s);
6700 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
6701 break;
6702 case 0xf9: /* stc */
6703 gen_compute_eflags(s);
6704 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
6705 break;
6706 case 0xfc: /* cld */
6707 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
6708 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6709 break;
6710 case 0xfd: /* std */
6711 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
6712 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
6713 break;
6714
6715 /************************/
6716 /* bit operations */
6717 case 0x1ba: /* bt/bts/btr/btc Gv, im */
6718 ot = dflag + OT_WORD;
6719 modrm = cpu_ldub_code(env, s->pc++);
6720 op = (modrm >> 3) & 7;
6721 mod = (modrm >> 6) & 3;
6722 rm = (modrm & 7) | REX_B(s);
6723 if (mod != 3) {
6724 s->rip_offset = 1;
6725 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
6726 gen_op_ld_T0_A0(ot + s->mem_index);
6727 } else {
6728 gen_op_mov_TN_reg(ot, 0, rm);
6729 }
6730 /* load shift */
6731 val = cpu_ldub_code(env, s->pc++);
6732 gen_op_movl_T1_im(val);
6733 if (op < 4)
6734 goto illegal_op;
6735 op -= 4;
6736 goto bt_op;
6737 case 0x1a3: /* bt Gv, Ev */
6738 op = 0;
6739 goto do_btx;
6740 case 0x1ab: /* bts */
6741 op = 1;
6742 goto do_btx;
6743 case 0x1b3: /* btr */
6744 op = 2;
6745 goto do_btx;
6746 case 0x1bb: /* btc */
6747 op = 3;
6748 do_btx:
6749 ot = dflag + OT_WORD;
6750 modrm = cpu_ldub_code(env, s->pc++);
6751 reg = ((modrm >> 3) & 7) | rex_r;
6752 mod = (modrm >> 6) & 3;
6753 rm = (modrm & 7) | REX_B(s);
6754 gen_op_mov_TN_reg(OT_LONG, 1, reg);
6755 if (mod != 3) {
6756 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
6757 /* specific case: we need to add a displacement */
6758 gen_exts(ot, cpu_T[1]);
6759 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
6760 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6761 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
6762 gen_op_ld_T0_A0(ot + s->mem_index);
6763 } else {
6764 gen_op_mov_TN_reg(ot, 0, rm);
6765 }
6766 bt_op:
6767 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
6768 switch(op) {
6769 case 0:
6770 tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
6771 tcg_gen_movi_tl(cpu_cc_dst, 0);
6772 break;
6773 case 1:
6774 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6775 tcg_gen_movi_tl(cpu_tmp0, 1);
6776 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6777 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6778 break;
6779 case 2:
6780 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6781 tcg_gen_movi_tl(cpu_tmp0, 1);
6782 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6783 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
6784 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6785 break;
6786 default:
6787 case 3:
6788 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6789 tcg_gen_movi_tl(cpu_tmp0, 1);
6790 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6791 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6792 break;
6793 }
6794 set_cc_op(s, CC_OP_SARB + ot);
6795 if (op != 0) {
6796 if (mod != 3)
6797 gen_op_st_T0_A0(ot + s->mem_index);
6798 else
6799 gen_op_mov_reg_T0(ot, rm);
6800 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6801 tcg_gen_movi_tl(cpu_cc_dst, 0);
6802 }
6803 break;
6804 case 0x1bc: /* bsf */
6805 case 0x1bd: /* bsr */
6806 {
6807 int label1;
6808 TCGv t0;
6809
6810 ot = dflag + OT_WORD;
6811 modrm = cpu_ldub_code(env, s->pc++);
6812 reg = ((modrm >> 3) & 7) | rex_r;
6813 gen_ldst_modrm(env, s,modrm, ot, OR_TMP0, 0);
6814 gen_extu(ot, cpu_T[0]);
6815 t0 = tcg_temp_local_new();
6816 tcg_gen_mov_tl(t0, cpu_T[0]);
6817 if ((b & 1) && (prefixes & PREFIX_REPZ) &&
6818 (s->cpuid_ext3_features & CPUID_EXT3_ABM)) {
6819 switch(ot) {
6820 case OT_WORD: gen_helper_lzcnt(cpu_T[0], t0,
6821 tcg_const_i32(16)); break;
6822 case OT_LONG: gen_helper_lzcnt(cpu_T[0], t0,
6823 tcg_const_i32(32)); break;
6824 case OT_QUAD: gen_helper_lzcnt(cpu_T[0], t0,
6825 tcg_const_i32(64)); break;
6826 }
6827 gen_op_mov_reg_T0(ot, reg);
6828 } else {
6829 label1 = gen_new_label();
6830 tcg_gen_movi_tl(cpu_cc_dst, 0);
6831 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1);
6832 if (b & 1) {
6833 gen_helper_bsr(cpu_T[0], t0);
6834 } else {
6835 gen_helper_bsf(cpu_T[0], t0);
6836 }
6837 gen_op_mov_reg_T0(ot, reg);
6838 tcg_gen_movi_tl(cpu_cc_dst, 1);
6839 gen_set_label(label1);
6840 set_cc_op(s, CC_OP_LOGICB + ot);
6841 }
6842 tcg_temp_free(t0);
6843 }
6844 break;
6845 /************************/
6846 /* bcd */
6847 case 0x27: /* daa */
6848 if (CODE64(s))
6849 goto illegal_op;
6850 gen_update_cc_op(s);
6851 gen_helper_daa(cpu_env);
6852 set_cc_op(s, CC_OP_EFLAGS);
6853 break;
6854 case 0x2f: /* das */
6855 if (CODE64(s))
6856 goto illegal_op;
6857 gen_update_cc_op(s);
6858 gen_helper_das(cpu_env);
6859 set_cc_op(s, CC_OP_EFLAGS);
6860 break;
6861 case 0x37: /* aaa */
6862 if (CODE64(s))
6863 goto illegal_op;
6864 gen_update_cc_op(s);
6865 gen_helper_aaa(cpu_env);
6866 set_cc_op(s, CC_OP_EFLAGS);
6867 break;
6868 case 0x3f: /* aas */
6869 if (CODE64(s))
6870 goto illegal_op;
6871 gen_update_cc_op(s);
6872 gen_helper_aas(cpu_env);
6873 set_cc_op(s, CC_OP_EFLAGS);
6874 break;
6875 case 0xd4: /* aam */
6876 if (CODE64(s))
6877 goto illegal_op;
6878 val = cpu_ldub_code(env, s->pc++);
6879 if (val == 0) {
6880 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6881 } else {
6882 gen_helper_aam(cpu_env, tcg_const_i32(val));
6883 set_cc_op(s, CC_OP_LOGICB);
6884 }
6885 break;
6886 case 0xd5: /* aad */
6887 if (CODE64(s))
6888 goto illegal_op;
6889 val = cpu_ldub_code(env, s->pc++);
6890 gen_helper_aad(cpu_env, tcg_const_i32(val));
6891 set_cc_op(s, CC_OP_LOGICB);
6892 break;
6893 /************************/
6894 /* misc */
6895 case 0x90: /* nop */
6896 /* XXX: correct lock test for all insn */
6897 if (prefixes & PREFIX_LOCK) {
6898 goto illegal_op;
6899 }
6900 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6901 if (REX_B(s)) {
6902 goto do_xchg_reg_eax;
6903 }
6904 if (prefixes & PREFIX_REPZ) {
6905 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
6906 }
6907 break;
6908 case 0x9b: /* fwait */
6909 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
6910 (HF_MP_MASK | HF_TS_MASK)) {
6911 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6912 } else {
6913 gen_update_cc_op(s);
6914 gen_jmp_im(pc_start - s->cs_base);
6915 gen_helper_fwait(cpu_env);
6916 }
6917 break;
6918 case 0xcc: /* int3 */
6919 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6920 break;
6921 case 0xcd: /* int N */
6922 val = cpu_ldub_code(env, s->pc++);
6923 if (s->vm86 && s->iopl != 3) {
6924 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6925 } else {
6926 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6927 }
6928 break;
6929 case 0xce: /* into */
6930 if (CODE64(s))
6931 goto illegal_op;
6932 gen_update_cc_op(s);
6933 gen_jmp_im(pc_start - s->cs_base);
6934 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
6935 break;
6936 #ifdef WANT_ICEBP
6937 case 0xf1: /* icebp (undocumented, exits to external debugger) */
6938 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
6939 #if 1
6940 gen_debug(s, pc_start - s->cs_base);
6941 #else
6942 /* start debug */
6943 tb_flush(env);
6944 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6945 #endif
6946 break;
6947 #endif
6948 case 0xfa: /* cli */
6949 if (!s->vm86) {
6950 if (s->cpl <= s->iopl) {
6951 gen_helper_cli(cpu_env);
6952 } else {
6953 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6954 }
6955 } else {
6956 if (s->iopl == 3) {
6957 gen_helper_cli(cpu_env);
6958 } else {
6959 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6960 }
6961 }
6962 break;
6963 case 0xfb: /* sti */
6964 if (!s->vm86) {
6965 if (s->cpl <= s->iopl) {
6966 gen_sti:
6967 gen_helper_sti(cpu_env);
6968 /* interruptions are enabled only the first insn after sti */
6969 /* If several instructions disable interrupts, only the
6970 _first_ does it */
6971 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
6972 gen_helper_set_inhibit_irq(cpu_env);
6973 /* give a chance to handle pending irqs */
6974 gen_jmp_im(s->pc - s->cs_base);
6975 gen_eob(s);
6976 } else {
6977 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6978 }
6979 } else {
6980 if (s->iopl == 3) {
6981 goto gen_sti;
6982 } else {
6983 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6984 }
6985 }
6986 break;
6987 case 0x62: /* bound */
6988 if (CODE64(s))
6989 goto illegal_op;
6990 ot = dflag ? OT_LONG : OT_WORD;
6991 modrm = cpu_ldub_code(env, s->pc++);
6992 reg = (modrm >> 3) & 7;
6993 mod = (modrm >> 6) & 3;
6994 if (mod == 3)
6995 goto illegal_op;
6996 gen_op_mov_TN_reg(ot, 0, reg);
6997 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
6998 gen_jmp_im(pc_start - s->cs_base);
6999 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7000 if (ot == OT_WORD) {
7001 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
7002 } else {
7003 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
7004 }
7005 break;
7006 case 0x1c8 ... 0x1cf: /* bswap reg */
7007 reg = (b & 7) | REX_B(s);
7008 #ifdef TARGET_X86_64
7009 if (dflag == 2) {
7010 gen_op_mov_TN_reg(OT_QUAD, 0, reg);
7011 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
7012 gen_op_mov_reg_T0(OT_QUAD, reg);
7013 } else
7014 #endif
7015 {
7016 gen_op_mov_TN_reg(OT_LONG, 0, reg);
7017 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
7018 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
7019 gen_op_mov_reg_T0(OT_LONG, reg);
7020 }
7021 break;
7022 case 0xd6: /* salc */
7023 if (CODE64(s))
7024 goto illegal_op;
7025 gen_compute_eflags_c(s, cpu_T[0]);
7026 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
7027 gen_op_mov_reg_T0(OT_BYTE, R_EAX);
7028 break;
7029 case 0xe0: /* loopnz */
7030 case 0xe1: /* loopz */
7031 case 0xe2: /* loop */
7032 case 0xe3: /* jecxz */
7033 {
7034 int l1, l2, l3;
7035
7036 tval = (int8_t)insn_get(env, s, OT_BYTE);
7037 next_eip = s->pc - s->cs_base;
7038 tval += next_eip;
7039 if (s->dflag == 0)
7040 tval &= 0xffff;
7041
7042 l1 = gen_new_label();
7043 l2 = gen_new_label();
7044 l3 = gen_new_label();
7045 b &= 3;
7046 switch(b) {
7047 case 0: /* loopnz */
7048 case 1: /* loopz */
7049 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7050 gen_op_jz_ecx(s->aflag, l3);
7051 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
7052 break;
7053 case 2: /* loop */
7054 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7055 gen_op_jnz_ecx(s->aflag, l1);
7056 break;
7057 default:
7058 case 3: /* jcxz */
7059 gen_op_jz_ecx(s->aflag, l1);
7060 break;
7061 }
7062
7063 gen_set_label(l3);
7064 gen_jmp_im(next_eip);
7065 tcg_gen_br(l2);
7066
7067 gen_set_label(l1);
7068 gen_jmp_im(tval);
7069 gen_set_label(l2);
7070 gen_eob(s);
7071 }
7072 break;
7073 case 0x130: /* wrmsr */
7074 case 0x132: /* rdmsr */
7075 if (s->cpl != 0) {
7076 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7077 } else {
7078 gen_update_cc_op(s);
7079 gen_jmp_im(pc_start - s->cs_base);
7080 if (b & 2) {
7081 gen_helper_rdmsr(cpu_env);
7082 } else {
7083 gen_helper_wrmsr(cpu_env);
7084 }
7085 }
7086 break;
7087 case 0x131: /* rdtsc */
7088 gen_update_cc_op(s);
7089 gen_jmp_im(pc_start - s->cs_base);
7090 if (use_icount)
7091 gen_io_start();
7092 gen_helper_rdtsc(cpu_env);
7093 if (use_icount) {
7094 gen_io_end();
7095 gen_jmp(s, s->pc - s->cs_base);
7096 }
7097 break;
7098 case 0x133: /* rdpmc */
7099 gen_update_cc_op(s);
7100 gen_jmp_im(pc_start - s->cs_base);
7101 gen_helper_rdpmc(cpu_env);
7102 break;
7103 case 0x134: /* sysenter */
7104 /* For Intel SYSENTER is valid on 64-bit */
7105 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7106 goto illegal_op;
7107 if (!s->pe) {
7108 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7109 } else {
7110 gen_update_cc_op(s);
7111 gen_jmp_im(pc_start - s->cs_base);
7112 gen_helper_sysenter(cpu_env);
7113 gen_eob(s);
7114 }
7115 break;
7116 case 0x135: /* sysexit */
7117 /* For Intel SYSEXIT is valid on 64-bit */
7118 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
7119 goto illegal_op;
7120 if (!s->pe) {
7121 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7122 } else {
7123 gen_update_cc_op(s);
7124 gen_jmp_im(pc_start - s->cs_base);
7125 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag));
7126 gen_eob(s);
7127 }
7128 break;
7129 #ifdef TARGET_X86_64
7130 case 0x105: /* syscall */
7131 /* XXX: is it usable in real mode ? */
7132 gen_update_cc_op(s);
7133 gen_jmp_im(pc_start - s->cs_base);
7134 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
7135 gen_eob(s);
7136 break;
7137 case 0x107: /* sysret */
7138 if (!s->pe) {
7139 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7140 } else {
7141 gen_update_cc_op(s);
7142 gen_jmp_im(pc_start - s->cs_base);
7143 gen_helper_sysret(cpu_env, tcg_const_i32(s->dflag));
7144 /* condition codes are modified only in long mode */
7145 if (s->lma) {
7146 set_cc_op(s, CC_OP_EFLAGS);
7147 }
7148 gen_eob(s);
7149 }
7150 break;
7151 #endif
7152 case 0x1a2: /* cpuid */
7153 gen_update_cc_op(s);
7154 gen_jmp_im(pc_start - s->cs_base);
7155 gen_helper_cpuid(cpu_env);
7156 break;
7157 case 0xf4: /* hlt */
7158 if (s->cpl != 0) {
7159 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7160 } else {
7161 gen_update_cc_op(s);
7162 gen_jmp_im(pc_start - s->cs_base);
7163 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
7164 s->is_jmp = DISAS_TB_JUMP;
7165 }
7166 break;
7167 case 0x100:
7168 modrm = cpu_ldub_code(env, s->pc++);
7169 mod = (modrm >> 6) & 3;
7170 op = (modrm >> 3) & 7;
7171 switch(op) {
7172 case 0: /* sldt */
7173 if (!s->pe || s->vm86)
7174 goto illegal_op;
7175 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
7176 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
7177 ot = OT_WORD;
7178 if (mod == 3)
7179 ot += s->dflag;
7180 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7181 break;
7182 case 2: /* lldt */
7183 if (!s->pe || s->vm86)
7184 goto illegal_op;
7185 if (s->cpl != 0) {
7186 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7187 } else {
7188 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
7189 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7190 gen_jmp_im(pc_start - s->cs_base);
7191 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7192 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
7193 }
7194 break;
7195 case 1: /* str */
7196 if (!s->pe || s->vm86)
7197 goto illegal_op;
7198 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
7199 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
7200 ot = OT_WORD;
7201 if (mod == 3)
7202 ot += s->dflag;
7203 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
7204 break;
7205 case 3: /* ltr */
7206 if (!s->pe || s->vm86)
7207 goto illegal_op;
7208 if (s->cpl != 0) {
7209 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7210 } else {
7211 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
7212 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7213 gen_jmp_im(pc_start - s->cs_base);
7214 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7215 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
7216 }
7217 break;
7218 case 4: /* verr */
7219 case 5: /* verw */
7220 if (!s->pe || s->vm86)
7221 goto illegal_op;
7222 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7223 gen_update_cc_op(s);
7224 if (op == 4) {
7225 gen_helper_verr(cpu_env, cpu_T[0]);
7226 } else {
7227 gen_helper_verw(cpu_env, cpu_T[0]);
7228 }
7229 set_cc_op(s, CC_OP_EFLAGS);
7230 break;
7231 default:
7232 goto illegal_op;
7233 }
7234 break;
7235 case 0x101:
7236 modrm = cpu_ldub_code(env, s->pc++);
7237 mod = (modrm >> 6) & 3;
7238 op = (modrm >> 3) & 7;
7239 rm = modrm & 7;
7240 switch(op) {
7241 case 0: /* sgdt */
7242 if (mod == 3)
7243 goto illegal_op;
7244 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
7245 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7246 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
7247 gen_op_st_T0_A0(OT_WORD + s->mem_index);
7248 gen_add_A0_im(s, 2);
7249 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
7250 if (!s->dflag)
7251 gen_op_andl_T0_im(0xffffff);
7252 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
7253 break;
7254 case 1:
7255 if (mod == 3) {
7256 switch (rm) {
7257 case 0: /* monitor */
7258 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7259 s->cpl != 0)
7260 goto illegal_op;
7261 gen_update_cc_op(s);
7262 gen_jmp_im(pc_start - s->cs_base);
7263 #ifdef TARGET_X86_64
7264 if (s->aflag == 2) {
7265 gen_op_movq_A0_reg(R_EAX);
7266 } else
7267 #endif
7268 {
7269 gen_op_movl_A0_reg(R_EAX);
7270 if (s->aflag == 0)
7271 gen_op_andl_A0_ffff();
7272 }
7273 gen_add_A0_ds_seg(s);
7274 gen_helper_monitor(cpu_env, cpu_A0);
7275 break;
7276 case 1: /* mwait */
7277 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7278 s->cpl != 0)
7279 goto illegal_op;
7280 gen_update_cc_op(s);
7281 gen_jmp_im(pc_start - s->cs_base);
7282 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7283 gen_eob(s);
7284 break;
7285 case 2: /* clac */
7286 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7287 s->cpl != 0) {
7288 goto illegal_op;
7289 }
7290 gen_helper_clac(cpu_env);
7291 gen_jmp_im(s->pc - s->cs_base);
7292 gen_eob(s);
7293 break;
7294 case 3: /* stac */
7295 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7296 s->cpl != 0) {
7297 goto illegal_op;
7298 }
7299 gen_helper_stac(cpu_env);
7300 gen_jmp_im(s->pc - s->cs_base);
7301 gen_eob(s);
7302 break;
7303 default:
7304 goto illegal_op;
7305 }
7306 } else { /* sidt */
7307 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7308 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7309 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
7310 gen_op_st_T0_A0(OT_WORD + s->mem_index);
7311 gen_add_A0_im(s, 2);
7312 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
7313 if (!s->dflag)
7314 gen_op_andl_T0_im(0xffffff);
7315 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
7316 }
7317 break;
7318 case 2: /* lgdt */
7319 case 3: /* lidt */
7320 if (mod == 3) {
7321 gen_update_cc_op(s);
7322 gen_jmp_im(pc_start - s->cs_base);
7323 switch(rm) {
7324 case 0: /* VMRUN */
7325 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7326 goto illegal_op;
7327 if (s->cpl != 0) {
7328 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7329 break;
7330 } else {
7331 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag),
7332 tcg_const_i32(s->pc - pc_start));
7333 tcg_gen_exit_tb(0);
7334 s->is_jmp = DISAS_TB_JUMP;
7335 }
7336 break;
7337 case 1: /* VMMCALL */
7338 if (!(s->flags & HF_SVME_MASK))
7339 goto illegal_op;
7340 gen_helper_vmmcall(cpu_env);
7341 break;
7342 case 2: /* VMLOAD */
7343 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7344 goto illegal_op;
7345 if (s->cpl != 0) {
7346 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7347 break;
7348 } else {
7349 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag));
7350 }
7351 break;
7352 case 3: /* VMSAVE */
7353 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7354 goto illegal_op;
7355 if (s->cpl != 0) {
7356 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7357 break;
7358 } else {
7359 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag));
7360 }
7361 break;
7362 case 4: /* STGI */
7363 if ((!(s->flags & HF_SVME_MASK) &&
7364 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7365 !s->pe)
7366 goto illegal_op;
7367 if (s->cpl != 0) {
7368 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7369 break;
7370 } else {
7371 gen_helper_stgi(cpu_env);
7372 }
7373 break;
7374 case 5: /* CLGI */
7375 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7376 goto illegal_op;
7377 if (s->cpl != 0) {
7378 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7379 break;
7380 } else {
7381 gen_helper_clgi(cpu_env);
7382 }
7383 break;
7384 case 6: /* SKINIT */
7385 if ((!(s->flags & HF_SVME_MASK) &&
7386 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7387 !s->pe)
7388 goto illegal_op;
7389 gen_helper_skinit(cpu_env);
7390 break;
7391 case 7: /* INVLPGA */
7392 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7393 goto illegal_op;
7394 if (s->cpl != 0) {
7395 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7396 break;
7397 } else {
7398 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag));
7399 }
7400 break;
7401 default:
7402 goto illegal_op;
7403 }
7404 } else if (s->cpl != 0) {
7405 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7406 } else {
7407 gen_svm_check_intercept(s, pc_start,
7408 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
7409 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7410 gen_op_ld_T1_A0(OT_WORD + s->mem_index);
7411 gen_add_A0_im(s, 2);
7412 gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
7413 if (!s->dflag)
7414 gen_op_andl_T0_im(0xffffff);
7415 if (op == 2) {
7416 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7417 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
7418 } else {
7419 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7420 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
7421 }
7422 }
7423 break;
7424 case 4: /* smsw */
7425 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
7426 #if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
7427 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7428 #else
7429 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
7430 #endif
7431 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 1);
7432 break;
7433 case 6: /* lmsw */
7434 if (s->cpl != 0) {
7435 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7436 } else {
7437 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7438 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7439 gen_helper_lmsw(cpu_env, cpu_T[0]);
7440 gen_jmp_im(s->pc - s->cs_base);
7441 gen_eob(s);
7442 }
7443 break;
7444 case 7:
7445 if (mod != 3) { /* invlpg */
7446 if (s->cpl != 0) {
7447 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7448 } else {
7449 gen_update_cc_op(s);
7450 gen_jmp_im(pc_start - s->cs_base);
7451 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7452 gen_helper_invlpg(cpu_env, cpu_A0);
7453 gen_jmp_im(s->pc - s->cs_base);
7454 gen_eob(s);
7455 }
7456 } else {
7457 switch (rm) {
7458 case 0: /* swapgs */
7459 #ifdef TARGET_X86_64
7460 if (CODE64(s)) {
7461 if (s->cpl != 0) {
7462 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7463 } else {
7464 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7465 offsetof(CPUX86State,segs[R_GS].base));
7466 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7467 offsetof(CPUX86State,kernelgsbase));
7468 tcg_gen_st_tl(cpu_T[1], cpu_env,
7469 offsetof(CPUX86State,segs[R_GS].base));
7470 tcg_gen_st_tl(cpu_T[0], cpu_env,
7471 offsetof(CPUX86State,kernelgsbase));
7472 }
7473 } else
7474 #endif
7475 {
7476 goto illegal_op;
7477 }
7478 break;
7479 case 1: /* rdtscp */
7480 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7481 goto illegal_op;
7482 gen_update_cc_op(s);
7483 gen_jmp_im(pc_start - s->cs_base);
7484 if (use_icount)
7485 gen_io_start();
7486 gen_helper_rdtscp(cpu_env);
7487 if (use_icount) {
7488 gen_io_end();
7489 gen_jmp(s, s->pc - s->cs_base);
7490 }
7491 break;
7492 default:
7493 goto illegal_op;
7494 }
7495 }
7496 break;
7497 default:
7498 goto illegal_op;
7499 }
7500 break;
7501 case 0x108: /* invd */
7502 case 0x109: /* wbinvd */
7503 if (s->cpl != 0) {
7504 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7505 } else {
7506 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
7507 /* nothing to do */
7508 }
7509 break;
7510 case 0x63: /* arpl or movslS (x86_64) */
7511 #ifdef TARGET_X86_64
7512 if (CODE64(s)) {
7513 int d_ot;
7514 /* d_ot is the size of destination */
7515 d_ot = dflag + OT_WORD;
7516
7517 modrm = cpu_ldub_code(env, s->pc++);
7518 reg = ((modrm >> 3) & 7) | rex_r;
7519 mod = (modrm >> 6) & 3;
7520 rm = (modrm & 7) | REX_B(s);
7521
7522 if (mod == 3) {
7523 gen_op_mov_TN_reg(OT_LONG, 0, rm);
7524 /* sign extend */
7525 if (d_ot == OT_QUAD)
7526 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
7527 gen_op_mov_reg_T0(d_ot, reg);
7528 } else {
7529 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7530 if (d_ot == OT_QUAD) {
7531 gen_op_lds_T0_A0(OT_LONG + s->mem_index);
7532 } else {
7533 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
7534 }
7535 gen_op_mov_reg_T0(d_ot, reg);
7536 }
7537 } else
7538 #endif
7539 {
7540 int label1;
7541 TCGv t0, t1, t2, a0;
7542
7543 if (!s->pe || s->vm86)
7544 goto illegal_op;
7545 t0 = tcg_temp_local_new();
7546 t1 = tcg_temp_local_new();
7547 t2 = tcg_temp_local_new();
7548 ot = OT_WORD;
7549 modrm = cpu_ldub_code(env, s->pc++);
7550 reg = (modrm >> 3) & 7;
7551 mod = (modrm >> 6) & 3;
7552 rm = modrm & 7;
7553 if (mod != 3) {
7554 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7555 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
7556 a0 = tcg_temp_local_new();
7557 tcg_gen_mov_tl(a0, cpu_A0);
7558 } else {
7559 gen_op_mov_v_reg(ot, t0, rm);
7560 TCGV_UNUSED(a0);
7561 }
7562 gen_op_mov_v_reg(ot, t1, reg);
7563 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7564 tcg_gen_andi_tl(t1, t1, 3);
7565 tcg_gen_movi_tl(t2, 0);
7566 label1 = gen_new_label();
7567 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7568 tcg_gen_andi_tl(t0, t0, ~3);
7569 tcg_gen_or_tl(t0, t0, t1);
7570 tcg_gen_movi_tl(t2, CC_Z);
7571 gen_set_label(label1);
7572 if (mod != 3) {
7573 gen_op_st_v(ot + s->mem_index, t0, a0);
7574 tcg_temp_free(a0);
7575 } else {
7576 gen_op_mov_reg_v(ot, rm, t0);
7577 }
7578 gen_compute_eflags(s);
7579 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7580 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7581 tcg_temp_free(t0);
7582 tcg_temp_free(t1);
7583 tcg_temp_free(t2);
7584 }
7585 break;
7586 case 0x102: /* lar */
7587 case 0x103: /* lsl */
7588 {
7589 int label1;
7590 TCGv t0;
7591 if (!s->pe || s->vm86)
7592 goto illegal_op;
7593 ot = dflag ? OT_LONG : OT_WORD;
7594 modrm = cpu_ldub_code(env, s->pc++);
7595 reg = ((modrm >> 3) & 7) | rex_r;
7596 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
7597 t0 = tcg_temp_local_new();
7598 gen_update_cc_op(s);
7599 if (b == 0x102) {
7600 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7601 } else {
7602 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7603 }
7604 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7605 label1 = gen_new_label();
7606 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7607 gen_op_mov_reg_v(ot, reg, t0);
7608 gen_set_label(label1);
7609 set_cc_op(s, CC_OP_EFLAGS);
7610 tcg_temp_free(t0);
7611 }
7612 break;
7613 case 0x118:
7614 modrm = cpu_ldub_code(env, s->pc++);
7615 mod = (modrm >> 6) & 3;
7616 op = (modrm >> 3) & 7;
7617 switch(op) {
7618 case 0: /* prefetchnta */
7619 case 1: /* prefetchnt0 */
7620 case 2: /* prefetchnt0 */
7621 case 3: /* prefetchnt0 */
7622 if (mod == 3)
7623 goto illegal_op;
7624 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7625 /* nothing more to do */
7626 break;
7627 default: /* nop (multi byte) */
7628 gen_nop_modrm(env, s, modrm);
7629 break;
7630 }
7631 break;
7632 case 0x119 ... 0x11f: /* nop (multi byte) */
7633 modrm = cpu_ldub_code(env, s->pc++);
7634 gen_nop_modrm(env, s, modrm);
7635 break;
7636 case 0x120: /* mov reg, crN */
7637 case 0x122: /* mov crN, reg */
7638 if (s->cpl != 0) {
7639 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7640 } else {
7641 modrm = cpu_ldub_code(env, s->pc++);
7642 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7643 * AMD documentation (24594.pdf) and testing of
7644 * intel 386 and 486 processors all show that the mod bits
7645 * are assumed to be 1's, regardless of actual values.
7646 */
7647 rm = (modrm & 7) | REX_B(s);
7648 reg = ((modrm >> 3) & 7) | rex_r;
7649 if (CODE64(s))
7650 ot = OT_QUAD;
7651 else
7652 ot = OT_LONG;
7653 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7654 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7655 reg = 8;
7656 }
7657 switch(reg) {
7658 case 0:
7659 case 2:
7660 case 3:
7661 case 4:
7662 case 8:
7663 gen_update_cc_op(s);
7664 gen_jmp_im(pc_start - s->cs_base);
7665 if (b & 2) {
7666 gen_op_mov_TN_reg(ot, 0, rm);
7667 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7668 cpu_T[0]);
7669 gen_jmp_im(s->pc - s->cs_base);
7670 gen_eob(s);
7671 } else {
7672 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
7673 gen_op_mov_reg_T0(ot, rm);
7674 }
7675 break;
7676 default:
7677 goto illegal_op;
7678 }
7679 }
7680 break;
7681 case 0x121: /* mov reg, drN */
7682 case 0x123: /* mov drN, reg */
7683 if (s->cpl != 0) {
7684 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7685 } else {
7686 modrm = cpu_ldub_code(env, s->pc++);
7687 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7688 * AMD documentation (24594.pdf) and testing of
7689 * intel 386 and 486 processors all show that the mod bits
7690 * are assumed to be 1's, regardless of actual values.
7691 */
7692 rm = (modrm & 7) | REX_B(s);
7693 reg = ((modrm >> 3) & 7) | rex_r;
7694 if (CODE64(s))
7695 ot = OT_QUAD;
7696 else
7697 ot = OT_LONG;
7698 /* XXX: do it dynamically with CR4.DE bit */
7699 if (reg == 4 || reg == 5 || reg >= 8)
7700 goto illegal_op;
7701 if (b & 2) {
7702 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
7703 gen_op_mov_TN_reg(ot, 0, rm);
7704 gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]);
7705 gen_jmp_im(s->pc - s->cs_base);
7706 gen_eob(s);
7707 } else {
7708 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
7709 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
7710 gen_op_mov_reg_T0(ot, rm);
7711 }
7712 }
7713 break;
7714 case 0x106: /* clts */
7715 if (s->cpl != 0) {
7716 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7717 } else {
7718 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7719 gen_helper_clts(cpu_env);
7720 /* abort block because static cpu state changed */
7721 gen_jmp_im(s->pc - s->cs_base);
7722 gen_eob(s);
7723 }
7724 break;
7725 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
7726 case 0x1c3: /* MOVNTI reg, mem */
7727 if (!(s->cpuid_features & CPUID_SSE2))
7728 goto illegal_op;
7729 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
7730 modrm = cpu_ldub_code(env, s->pc++);
7731 mod = (modrm >> 6) & 3;
7732 if (mod == 3)
7733 goto illegal_op;
7734 reg = ((modrm >> 3) & 7) | rex_r;
7735 /* generate a generic store */
7736 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
7737 break;
7738 case 0x1ae:
7739 modrm = cpu_ldub_code(env, s->pc++);
7740 mod = (modrm >> 6) & 3;
7741 op = (modrm >> 3) & 7;
7742 switch(op) {
7743 case 0: /* fxsave */
7744 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7745 (s->prefix & PREFIX_LOCK))
7746 goto illegal_op;
7747 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7748 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7749 break;
7750 }
7751 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7752 gen_update_cc_op(s);
7753 gen_jmp_im(pc_start - s->cs_base);
7754 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32((s->dflag == 2)));
7755 break;
7756 case 1: /* fxrstor */
7757 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
7758 (s->prefix & PREFIX_LOCK))
7759 goto illegal_op;
7760 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
7761 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7762 break;
7763 }
7764 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7765 gen_update_cc_op(s);
7766 gen_jmp_im(pc_start - s->cs_base);
7767 gen_helper_fxrstor(cpu_env, cpu_A0,
7768 tcg_const_i32((s->dflag == 2)));
7769 break;
7770 case 2: /* ldmxcsr */
7771 case 3: /* stmxcsr */
7772 if (s->flags & HF_TS_MASK) {
7773 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7774 break;
7775 }
7776 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7777 mod == 3)
7778 goto illegal_op;
7779 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7780 if (op == 2) {
7781 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
7782 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
7783 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
7784 } else {
7785 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
7786 gen_op_st_T0_A0(OT_LONG + s->mem_index);
7787 }
7788 break;
7789 case 5: /* lfence */
7790 case 6: /* mfence */
7791 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
7792 goto illegal_op;
7793 break;
7794 case 7: /* sfence / clflush */
7795 if ((modrm & 0xc7) == 0xc0) {
7796 /* sfence */
7797 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
7798 if (!(s->cpuid_features & CPUID_SSE))
7799 goto illegal_op;
7800 } else {
7801 /* clflush */
7802 if (!(s->cpuid_features & CPUID_CLFLUSH))
7803 goto illegal_op;
7804 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7805 }
7806 break;
7807 default:
7808 goto illegal_op;
7809 }
7810 break;
7811 case 0x10d: /* 3DNow! prefetch(w) */
7812 modrm = cpu_ldub_code(env, s->pc++);
7813 mod = (modrm >> 6) & 3;
7814 if (mod == 3)
7815 goto illegal_op;
7816 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
7817 /* ignore for now */
7818 break;
7819 case 0x1aa: /* rsm */
7820 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
7821 if (!(s->flags & HF_SMM_MASK))
7822 goto illegal_op;
7823 gen_update_cc_op(s);
7824 gen_jmp_im(s->pc - s->cs_base);
7825 gen_helper_rsm(cpu_env);
7826 gen_eob(s);
7827 break;
7828 case 0x1b8: /* SSE4.2 popcnt */
7829 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
7830 PREFIX_REPZ)
7831 goto illegal_op;
7832 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
7833 goto illegal_op;
7834
7835 modrm = cpu_ldub_code(env, s->pc++);
7836 reg = ((modrm >> 3) & 7) | rex_r;
7837
7838 if (s->prefix & PREFIX_DATA)
7839 ot = OT_WORD;
7840 else if (s->dflag != 2)
7841 ot = OT_LONG;
7842 else
7843 ot = OT_QUAD;
7844
7845 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
7846 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
7847 gen_op_mov_reg_T0(ot, reg);
7848
7849 set_cc_op(s, CC_OP_EFLAGS);
7850 break;
7851 case 0x10e ... 0x10f:
7852 /* 3DNow! instructions, ignore prefixes */
7853 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
7854 case 0x110 ... 0x117:
7855 case 0x128 ... 0x12f:
7856 case 0x138 ... 0x13a:
7857 case 0x150 ... 0x179:
7858 case 0x17c ... 0x17f:
7859 case 0x1c2:
7860 case 0x1c4 ... 0x1c6:
7861 case 0x1d0 ... 0x1fe:
7862 gen_sse(env, s, b, pc_start, rex_r);
7863 break;
7864 default:
7865 goto illegal_op;
7866 }
7867 /* lock generation */
7868 if (s->prefix & PREFIX_LOCK)
7869 gen_helper_unlock();
7870 return s->pc;
7871 illegal_op:
7872 if (s->prefix & PREFIX_LOCK)
7873 gen_helper_unlock();
7874 /* XXX: ensure that no lock was generated */
7875 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7876 return s->pc;
7877 }
7878
7879 void optimize_flags_init(void)
7880 {
7881 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7882 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
7883 offsetof(CPUX86State, cc_op), "cc_op");
7884 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
7885 "cc_dst");
7886 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
7887 "cc_src");
7888 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
7889 "cc_src2");
7890
7891 #ifdef TARGET_X86_64
7892 cpu_regs[R_EAX] = tcg_global_mem_new_i64(TCG_AREG0,
7893 offsetof(CPUX86State, regs[R_EAX]), "rax");
7894 cpu_regs[R_ECX] = tcg_global_mem_new_i64(TCG_AREG0,
7895 offsetof(CPUX86State, regs[R_ECX]), "rcx");
7896 cpu_regs[R_EDX] = tcg_global_mem_new_i64(TCG_AREG0,
7897 offsetof(CPUX86State, regs[R_EDX]), "rdx");
7898 cpu_regs[R_EBX] = tcg_global_mem_new_i64(TCG_AREG0,
7899 offsetof(CPUX86State, regs[R_EBX]), "rbx");
7900 cpu_regs[R_ESP] = tcg_global_mem_new_i64(TCG_AREG0,
7901 offsetof(CPUX86State, regs[R_ESP]), "rsp");
7902 cpu_regs[R_EBP] = tcg_global_mem_new_i64(TCG_AREG0,
7903 offsetof(CPUX86State, regs[R_EBP]), "rbp");
7904 cpu_regs[R_ESI] = tcg_global_mem_new_i64(TCG_AREG0,
7905 offsetof(CPUX86State, regs[R_ESI]), "rsi");
7906 cpu_regs[R_EDI] = tcg_global_mem_new_i64(TCG_AREG0,
7907 offsetof(CPUX86State, regs[R_EDI]), "rdi");
7908 cpu_regs[8] = tcg_global_mem_new_i64(TCG_AREG0,
7909 offsetof(CPUX86State, regs[8]), "r8");
7910 cpu_regs[9] = tcg_global_mem_new_i64(TCG_AREG0,
7911 offsetof(CPUX86State, regs[9]), "r9");
7912 cpu_regs[10] = tcg_global_mem_new_i64(TCG_AREG0,
7913 offsetof(CPUX86State, regs[10]), "r10");
7914 cpu_regs[11] = tcg_global_mem_new_i64(TCG_AREG0,
7915 offsetof(CPUX86State, regs[11]), "r11");
7916 cpu_regs[12] = tcg_global_mem_new_i64(TCG_AREG0,
7917 offsetof(CPUX86State, regs[12]), "r12");
7918 cpu_regs[13] = tcg_global_mem_new_i64(TCG_AREG0,
7919 offsetof(CPUX86State, regs[13]), "r13");
7920 cpu_regs[14] = tcg_global_mem_new_i64(TCG_AREG0,
7921 offsetof(CPUX86State, regs[14]), "r14");
7922 cpu_regs[15] = tcg_global_mem_new_i64(TCG_AREG0,
7923 offsetof(CPUX86State, regs[15]), "r15");
7924 #else
7925 cpu_regs[R_EAX] = tcg_global_mem_new_i32(TCG_AREG0,
7926 offsetof(CPUX86State, regs[R_EAX]), "eax");
7927 cpu_regs[R_ECX] = tcg_global_mem_new_i32(TCG_AREG0,
7928 offsetof(CPUX86State, regs[R_ECX]), "ecx");
7929 cpu_regs[R_EDX] = tcg_global_mem_new_i32(TCG_AREG0,
7930 offsetof(CPUX86State, regs[R_EDX]), "edx");
7931 cpu_regs[R_EBX] = tcg_global_mem_new_i32(TCG_AREG0,
7932 offsetof(CPUX86State, regs[R_EBX]), "ebx");
7933 cpu_regs[R_ESP] = tcg_global_mem_new_i32(TCG_AREG0,
7934 offsetof(CPUX86State, regs[R_ESP]), "esp");
7935 cpu_regs[R_EBP] = tcg_global_mem_new_i32(TCG_AREG0,
7936 offsetof(CPUX86State, regs[R_EBP]), "ebp");
7937 cpu_regs[R_ESI] = tcg_global_mem_new_i32(TCG_AREG0,
7938 offsetof(CPUX86State, regs[R_ESI]), "esi");
7939 cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
7940 offsetof(CPUX86State, regs[R_EDI]), "edi");
7941 #endif
7942
7943 /* register helpers */
7944 #define GEN_HELPER 2
7945 #include "helper.h"
7946 }
7947
7948 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7949 basic block 'tb'. If search_pc is TRUE, also generate PC
7950 information for each intermediate instruction. */
7951 static inline void gen_intermediate_code_internal(CPUX86State *env,
7952 TranslationBlock *tb,
7953 int search_pc)
7954 {
7955 DisasContext dc1, *dc = &dc1;
7956 target_ulong pc_ptr;
7957 uint16_t *gen_opc_end;
7958 CPUBreakpoint *bp;
7959 int j, lj;
7960 uint64_t flags;
7961 target_ulong pc_start;
7962 target_ulong cs_base;
7963 int num_insns;
7964 int max_insns;
7965
7966 /* generate intermediate code */
7967 pc_start = tb->pc;
7968 cs_base = tb->cs_base;
7969 flags = tb->flags;
7970
7971 dc->pe = (flags >> HF_PE_SHIFT) & 1;
7972 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7973 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7974 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7975 dc->f_st = 0;
7976 dc->vm86 = (flags >> VM_SHIFT) & 1;
7977 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7978 dc->iopl = (flags >> IOPL_SHIFT) & 3;
7979 dc->tf = (flags >> TF_SHIFT) & 1;
7980 dc->singlestep_enabled = env->singlestep_enabled;
7981 dc->cc_op = CC_OP_DYNAMIC;
7982 dc->cc_op_dirty = false;
7983 dc->cs_base = cs_base;
7984 dc->tb = tb;
7985 dc->popl_esp_hack = 0;
7986 /* select memory access functions */
7987 dc->mem_index = 0;
7988 if (flags & HF_SOFTMMU_MASK) {
7989 dc->mem_index = (cpu_mmu_index(env) + 1) << 2;
7990 }
7991 dc->cpuid_features = env->cpuid_features;
7992 dc->cpuid_ext_features = env->cpuid_ext_features;
7993 dc->cpuid_ext2_features = env->cpuid_ext2_features;
7994 dc->cpuid_ext3_features = env->cpuid_ext3_features;
7995 dc->cpuid_7_0_ebx_features = env->cpuid_7_0_ebx_features;
7996 #ifdef TARGET_X86_64
7997 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7998 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7999 #endif
8000 dc->flags = flags;
8001 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
8002 (flags & HF_INHIBIT_IRQ_MASK)
8003 #ifndef CONFIG_SOFTMMU
8004 || (flags & HF_SOFTMMU_MASK)
8005 #endif
8006 );
8007 #if 0
8008 /* check addseg logic */
8009 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
8010 printf("ERROR addseg\n");
8011 #endif
8012
8013 cpu_T[0] = tcg_temp_new();
8014 cpu_T[1] = tcg_temp_new();
8015 cpu_A0 = tcg_temp_new();
8016
8017 cpu_tmp0 = tcg_temp_new();
8018 cpu_tmp1_i64 = tcg_temp_new_i64();
8019 cpu_tmp2_i32 = tcg_temp_new_i32();
8020 cpu_tmp3_i32 = tcg_temp_new_i32();
8021 cpu_tmp4 = tcg_temp_new();
8022 cpu_tmp5 = tcg_temp_new();
8023 cpu_ptr0 = tcg_temp_new_ptr();
8024 cpu_ptr1 = tcg_temp_new_ptr();
8025 cpu_cc_srcT = tcg_temp_local_new();
8026
8027 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
8028
8029 dc->is_jmp = DISAS_NEXT;
8030 pc_ptr = pc_start;
8031 lj = -1;
8032 num_insns = 0;
8033 max_insns = tb->cflags & CF_COUNT_MASK;
8034 if (max_insns == 0)
8035 max_insns = CF_COUNT_MASK;
8036
8037 gen_icount_start();
8038 for(;;) {
8039 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8040 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8041 if (bp->pc == pc_ptr &&
8042 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
8043 gen_debug(dc, pc_ptr - dc->cs_base);
8044 break;
8045 }
8046 }
8047 }
8048 if (search_pc) {
8049 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
8050 if (lj < j) {
8051 lj++;
8052 while (lj < j)
8053 tcg_ctx.gen_opc_instr_start[lj++] = 0;
8054 }
8055 tcg_ctx.gen_opc_pc[lj] = pc_ptr;
8056 gen_opc_cc_op[lj] = dc->cc_op;
8057 tcg_ctx.gen_opc_instr_start[lj] = 1;
8058 tcg_ctx.gen_opc_icount[lj] = num_insns;
8059 }
8060 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8061 gen_io_start();
8062
8063 pc_ptr = disas_insn(env, dc, pc_ptr);
8064 num_insns++;
8065 /* stop translation if indicated */
8066 if (dc->is_jmp)
8067 break;
8068 /* if single step mode, we generate only one instruction and
8069 generate an exception */
8070 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8071 the flag and abort the translation to give the irqs a
8072 change to be happen */
8073 if (dc->tf || dc->singlestep_enabled ||
8074 (flags & HF_INHIBIT_IRQ_MASK)) {
8075 gen_jmp_im(pc_ptr - dc->cs_base);
8076 gen_eob(dc);
8077 break;
8078 }
8079 /* if too long translation, stop generation too */
8080 if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
8081 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8082 num_insns >= max_insns) {
8083 gen_jmp_im(pc_ptr - dc->cs_base);
8084 gen_eob(dc);
8085 break;
8086 }
8087 if (singlestep) {
8088 gen_jmp_im(pc_ptr - dc->cs_base);
8089 gen_eob(dc);
8090 break;
8091 }
8092 }
8093 if (tb->cflags & CF_LAST_IO)
8094 gen_io_end();
8095 gen_icount_end(tb, num_insns);
8096 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
8097 /* we don't forget to fill the last values */
8098 if (search_pc) {
8099 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
8100 lj++;
8101 while (lj <= j)
8102 tcg_ctx.gen_opc_instr_start[lj++] = 0;
8103 }
8104
8105 #ifdef DEBUG_DISAS
8106 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8107 int disas_flags;
8108 qemu_log("----------------\n");
8109 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8110 #ifdef TARGET_X86_64
8111 if (dc->code64)
8112 disas_flags = 2;
8113 else
8114 #endif
8115 disas_flags = !dc->code32;
8116 log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags);
8117 qemu_log("\n");
8118 }
8119 #endif
8120
8121 if (!search_pc) {
8122 tb->size = pc_ptr - pc_start;
8123 tb->icount = num_insns;
8124 }
8125 }
8126
8127 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
8128 {
8129 gen_intermediate_code_internal(env, tb, 0);
8130 }
8131
8132 void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
8133 {
8134 gen_intermediate_code_internal(env, tb, 1);
8135 }
8136
8137 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
8138 {
8139 int cc_op;
8140 #ifdef DEBUG_DISAS
8141 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
8142 int i;
8143 qemu_log("RESTORE:\n");
8144 for(i = 0;i <= pc_pos; i++) {
8145 if (tcg_ctx.gen_opc_instr_start[i]) {
8146 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
8147 tcg_ctx.gen_opc_pc[i]);
8148 }
8149 }
8150 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
8151 pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
8152 (uint32_t)tb->cs_base);
8153 }
8154 #endif
8155 env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
8156 cc_op = gen_opc_cc_op[pc_pos];
8157 if (cc_op != CC_OP_DYNAMIC)
8158 env->cc_op = cc_op;
8159 }