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