VirtualBox

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

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

recompiler: Removing traces of attempts at making the recompiler compile with the microsoft compiler. (untested)

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

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