VirtualBox

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

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

REM: Do not block writes to port 80h.

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

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