VirtualBox

source: vbox/trunk/src/recompiler/target-i386/translate.c@ 40040

Last change on this file since 40040 was 39961, checked in by vboxsync, 13 years ago

REM: Fixed incorrect CR2 value for word or dword instruction fields crossing page boundraries. (Our bug, really ancient.)

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette