VirtualBox

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

最後變更 在這個檔案從39014是 38364,由 vboxsync 提交於 13 年 前

REM: Try fix the broken sysexit (and partially sysenter).

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

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