VirtualBox

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

最後變更 在這個檔案從38117是 37689,由 vboxsync 提交於 14 年 前

recompiler: Merged in changes from 0.13.0.

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

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