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