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