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