VirtualBox

source: vbox/trunk/src/recompiler_new/target-i386/translate.c@ 13357

Last change on this file since 13357 was 13357, checked in by vboxsync, 16 years ago

new codegen compiles, very unlikely works

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

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