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