|
|
1.1 root 1: /*
2: * i386 translation
1.1.1.6 root 3: *
1.1 root 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
1.1.1.8 root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 18: */
19: #include <stdarg.h>
20: #include <stdlib.h>
21: #include <stdio.h>
22: #include <string.h>
23: #include <inttypes.h>
24: #include <signal.h>
25:
26: #include "cpu.h"
27: #include "disas.h"
1.1.1.7 root 28: #include "tcg-op.h"
1.1 root 29:
1.1.1.7 root 30: #include "helper.h"
31: #define GEN_HELPER 1
32: #include "helper.h"
1.1 root 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:
40: #ifdef TARGET_X86_64
41: #define X86_64_ONLY(x) x
1.1.1.8 root 42: #define X86_64_DEF(...) __VA_ARGS__
1.1 root 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
1.1.1.8 root 52: #define X86_64_DEF(...)
1.1 root 53: #define CODE64(s) 0
54: #define REX_X(s) 0
55: #define REX_B(s) 0
56: #endif
57:
1.1.1.7 root 58: //#define MACRO_TEST 1
59:
60: /* global register indexes */
61: static TCGv_ptr cpu_env;
62: static TCGv cpu_A0, cpu_cc_src, cpu_cc_dst, cpu_cc_tmp;
63: static TCGv_i32 cpu_cc_op;
1.1.1.9 root 64: static TCGv cpu_regs[CPU_NB_REGS];
1.1.1.7 root 65: /* local temps */
66: static TCGv cpu_T[2], cpu_T3;
67: /* local register indexes (only used inside old micro ops) */
68: static TCGv cpu_tmp0, cpu_tmp4;
69: static TCGv_ptr cpu_ptr0, cpu_ptr1;
70: static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
71: static TCGv_i64 cpu_tmp1_i64;
1.1.1.9 root 72: static TCGv cpu_tmp5;
1.1.1.7 root 73:
1.1.1.13 root 74: static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
75:
1.1.1.7 root 76: #include "gen-icount.h"
77:
1.1 root 78: #ifdef TARGET_X86_64
79: static int x86_64_hregs;
80: #endif
81:
82: typedef struct DisasContext {
83: /* current insn context */
84: int override; /* -1 if no override */
85: int prefix;
86: int aflag, dflag;
87: target_ulong pc; /* pc = eip + cs_base */
88: int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
89: static state change (stop translation) */
90: /* current block context */
91: target_ulong cs_base; /* base of CS segment */
92: int pe; /* protected mode */
93: int code32; /* 32 bit code segment */
94: #ifdef TARGET_X86_64
95: int lma; /* long mode active */
96: int code64; /* 64 bit code segment */
97: int rex_x, rex_b;
98: #endif
99: int ss32; /* 32 bit stack segment */
100: int cc_op; /* current CC operation */
101: int addseg; /* non zero if either DS/ES/SS have a non zero base */
102: int f_st; /* currently unused */
103: int vm86; /* vm86 mode */
104: int cpl;
105: int iopl;
106: int tf; /* TF cpu flag */
107: int singlestep_enabled; /* "hardware" single step enabled */
108: int jmp_opt; /* use direct block chaining for direct jumps */
109: int mem_index; /* select memory access functions */
1.1.1.6 root 110: uint64_t flags; /* all execution flags */
1.1 root 111: struct TranslationBlock *tb;
112: int popl_esp_hack; /* for correct popl with esp base handling */
113: int rip_offset; /* only used in x86_64, but left for simplicity */
114: int cpuid_features;
1.1.1.4 root 115: int cpuid_ext_features;
1.1.1.7 root 116: int cpuid_ext2_features;
117: int cpuid_ext3_features;
1.1 root 118: } DisasContext;
119:
120: static void gen_eob(DisasContext *s);
121: static void gen_jmp(DisasContext *s, target_ulong eip);
122: static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
123:
124: /* i386 arith/logic operations */
125: enum {
1.1.1.6 root 126: OP_ADDL,
127: OP_ORL,
128: OP_ADCL,
1.1 root 129: OP_SBBL,
1.1.1.6 root 130: OP_ANDL,
131: OP_SUBL,
132: OP_XORL,
1.1 root 133: OP_CMPL,
134: };
135:
136: /* i386 shift ops */
137: enum {
1.1.1.6 root 138: OP_ROL,
139: OP_ROR,
140: OP_RCL,
141: OP_RCR,
142: OP_SHL,
143: OP_SHR,
1.1 root 144: OP_SHL1, /* undocumented */
145: OP_SAR = 7,
146: };
147:
148: enum {
1.1.1.7 root 149: JCC_O,
150: JCC_B,
151: JCC_Z,
152: JCC_BE,
153: JCC_S,
154: JCC_P,
155: JCC_L,
156: JCC_LE,
1.1 root 157: };
158:
159: /* operand size */
160: enum {
161: OT_BYTE = 0,
162: OT_WORD,
1.1.1.6 root 163: OT_LONG,
1.1 root 164: OT_QUAD,
165: };
166:
167: enum {
168: /* I386 int registers */
169: OR_EAX, /* MUST be even numbered */
170: OR_ECX,
171: OR_EDX,
172: OR_EBX,
173: OR_ESP,
174: OR_EBP,
175: OR_ESI,
176: OR_EDI,
177:
178: OR_TMP0 = 16, /* temporary operand register */
179: OR_TMP1,
180: OR_A0, /* temporary register used when doing address evaluation */
181: };
182:
1.1.1.7 root 183: static inline void gen_op_movl_T0_0(void)
184: {
185: tcg_gen_movi_tl(cpu_T[0], 0);
186: }
187:
188: static inline void gen_op_movl_T0_im(int32_t val)
189: {
190: tcg_gen_movi_tl(cpu_T[0], val);
191: }
192:
193: static inline void gen_op_movl_T0_imu(uint32_t val)
194: {
195: tcg_gen_movi_tl(cpu_T[0], val);
196: }
197:
198: static inline void gen_op_movl_T1_im(int32_t val)
199: {
200: tcg_gen_movi_tl(cpu_T[1], val);
201: }
202:
203: static inline void gen_op_movl_T1_imu(uint32_t val)
204: {
205: tcg_gen_movi_tl(cpu_T[1], val);
206: }
207:
208: static inline void gen_op_movl_A0_im(uint32_t val)
209: {
210: tcg_gen_movi_tl(cpu_A0, val);
211: }
212:
1.1 root 213: #ifdef TARGET_X86_64
1.1.1.7 root 214: static inline void gen_op_movq_A0_im(int64_t val)
215: {
216: tcg_gen_movi_tl(cpu_A0, val);
217: }
218: #endif
1.1 root 219:
1.1.1.7 root 220: static inline void gen_movtl_T0_im(target_ulong val)
221: {
222: tcg_gen_movi_tl(cpu_T[0], val);
223: }
224:
225: static inline void gen_movtl_T1_im(target_ulong val)
226: {
227: tcg_gen_movi_tl(cpu_T[1], val);
228: }
229:
230: static inline void gen_op_andl_T0_ffff(void)
231: {
232: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
233: }
234:
235: static inline void gen_op_andl_T0_im(uint32_t val)
236: {
237: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
238: }
1.1 root 239:
1.1.1.7 root 240: static inline void gen_op_movl_T0_T1(void)
241: {
242: tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
243: }
244:
245: static inline void gen_op_andl_A0_ffff(void)
246: {
247: tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
248: }
249:
250: #ifdef TARGET_X86_64
251:
252: #define NB_OP_SIZES 4
1.1 root 253:
254: #else /* !TARGET_X86_64 */
255:
256: #define NB_OP_SIZES 3
257:
258: #endif /* !TARGET_X86_64 */
259:
1.1.1.9 root 260: #if defined(HOST_WORDS_BIGENDIAN)
1.1.1.7 root 261: #define REG_B_OFFSET (sizeof(target_ulong) - 1)
262: #define REG_H_OFFSET (sizeof(target_ulong) - 2)
263: #define REG_W_OFFSET (sizeof(target_ulong) - 2)
264: #define REG_L_OFFSET (sizeof(target_ulong) - 4)
265: #define REG_LH_OFFSET (sizeof(target_ulong) - 8)
1.1 root 266: #else
1.1.1.7 root 267: #define REG_B_OFFSET 0
268: #define REG_H_OFFSET 1
269: #define REG_W_OFFSET 0
270: #define REG_L_OFFSET 0
271: #define REG_LH_OFFSET 4
1.1 root 272: #endif
273:
1.1.1.7 root 274: static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
275: {
276: switch(ot) {
277: case OT_BYTE:
278: if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
1.1.1.14 root 279: tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
1.1.1.7 root 280: } else {
1.1.1.14 root 281: tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
1.1.1.7 root 282: }
283: break;
284: case OT_WORD:
1.1.1.14 root 285: tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
1.1.1.7 root 286: break;
1.1.1.9 root 287: default: /* XXX this shouldn't be reached; abort? */
1.1.1.7 root 288: case OT_LONG:
1.1.1.9 root 289: /* For x86_64, this sets the higher half of register to zero.
290: For i386, this is equivalent to a mov. */
291: tcg_gen_ext32u_tl(cpu_regs[reg], t0);
1.1.1.7 root 292: break;
1.1.1.9 root 293: #ifdef TARGET_X86_64
1.1.1.7 root 294: case OT_QUAD:
1.1.1.9 root 295: tcg_gen_mov_tl(cpu_regs[reg], t0);
1.1.1.7 root 296: break;
1.1 root 297: #endif
1.1.1.7 root 298: }
299: }
1.1 root 300:
1.1.1.7 root 301: static inline void gen_op_mov_reg_T0(int ot, int reg)
302: {
303: gen_op_mov_reg_v(ot, reg, cpu_T[0]);
304: }
1.1 root 305:
1.1.1.7 root 306: static inline void gen_op_mov_reg_T1(int ot, int reg)
1.1 root 307: {
1.1.1.7 root 308: gen_op_mov_reg_v(ot, reg, cpu_T[1]);
309: }
310:
311: static inline void gen_op_mov_reg_A0(int size, int reg)
312: {
313: switch(size) {
314: case 0:
1.1.1.14 root 315: tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
1.1.1.7 root 316: break;
1.1.1.9 root 317: default: /* XXX this shouldn't be reached; abort? */
1.1.1.7 root 318: case 1:
1.1.1.9 root 319: /* For x86_64, this sets the higher half of register to zero.
320: For i386, this is equivalent to a mov. */
321: tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
1.1.1.7 root 322: break;
1.1.1.9 root 323: #ifdef TARGET_X86_64
1.1.1.7 root 324: case 2:
1.1.1.9 root 325: tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
1.1.1.7 root 326: break;
1.1 root 327: #endif
1.1.1.7 root 328: }
329: }
1.1 root 330:
1.1.1.7 root 331: static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
332: {
333: switch(ot) {
334: case OT_BYTE:
335: if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
336: goto std_case;
337: } else {
1.1.1.9 root 338: tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
339: tcg_gen_ext8u_tl(t0, t0);
1.1.1.7 root 340: }
341: break;
342: default:
343: std_case:
1.1.1.9 root 344: tcg_gen_mov_tl(t0, cpu_regs[reg]);
1.1.1.7 root 345: break;
346: }
347: }
1.1 root 348:
1.1.1.7 root 349: static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
350: {
351: gen_op_mov_v_reg(ot, cpu_T[t_index], reg);
352: }
1.1 root 353:
1.1.1.7 root 354: static inline void gen_op_movl_A0_reg(int reg)
355: {
1.1.1.9 root 356: tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
1.1.1.7 root 357: }
1.1 root 358:
1.1.1.7 root 359: static inline void gen_op_addl_A0_im(int32_t val)
360: {
361: tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
362: #ifdef TARGET_X86_64
363: tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
1.1 root 364: #endif
1.1.1.7 root 365: }
1.1 root 366:
1.1.1.7 root 367: #ifdef TARGET_X86_64
368: static inline void gen_op_addq_A0_im(int64_t val)
369: {
370: tcg_gen_addi_tl(cpu_A0, cpu_A0, val);
371: }
1.1 root 372: #endif
1.1.1.7 root 373:
374: static void gen_add_A0_im(DisasContext *s, int val)
375: {
376: #ifdef TARGET_X86_64
377: if (CODE64(s))
378: gen_op_addq_A0_im(val);
379: else
1.1 root 380: #endif
1.1.1.7 root 381: gen_op_addl_A0_im(val);
382: }
1.1 root 383:
1.1.1.7 root 384: static inline void gen_op_addl_T0_T1(void)
385: {
386: tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
387: }
1.1 root 388:
1.1.1.7 root 389: static inline void gen_op_jmp_T0(void)
390: {
1.1.1.17! root 391: tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
1.1.1.7 root 392: }
1.1 root 393:
1.1.1.7 root 394: static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
395: {
396: switch(size) {
397: case 0:
1.1.1.9 root 398: tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
1.1.1.14 root 399: tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
1.1.1.7 root 400: break;
401: case 1:
1.1.1.9 root 402: tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
403: /* For x86_64, this sets the higher half of register to zero.
404: For i386, this is equivalent to a nop. */
405: tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
406: tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
1.1.1.7 root 407: break;
408: #ifdef TARGET_X86_64
409: case 2:
1.1.1.9 root 410: tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
1.1.1.7 root 411: break;
412: #endif
413: }
414: }
1.1 root 415:
1.1.1.7 root 416: static inline void gen_op_add_reg_T0(int size, int reg)
417: {
418: switch(size) {
419: case 0:
1.1.1.9 root 420: tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
1.1.1.14 root 421: tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
1.1.1.7 root 422: break;
423: case 1:
1.1.1.9 root 424: tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
425: /* For x86_64, this sets the higher half of register to zero.
426: For i386, this is equivalent to a nop. */
427: tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
428: tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
1.1.1.7 root 429: break;
430: #ifdef TARGET_X86_64
431: case 2:
1.1.1.9 root 432: tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
1.1.1.7 root 433: break;
434: #endif
435: }
436: }
1.1 root 437:
1.1.1.7 root 438: static inline void gen_op_set_cc_op(int32_t val)
439: {
440: tcg_gen_movi_i32(cpu_cc_op, val);
441: }
1.1 root 442:
1.1.1.7 root 443: static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
444: {
1.1.1.9 root 445: tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
446: if (shift != 0)
1.1.1.7 root 447: tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
448: tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
1.1.1.9 root 449: /* For x86_64, this sets the higher half of register to zero.
450: For i386, this is equivalent to a nop. */
451: tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
1.1.1.7 root 452: }
1.1 root 453:
1.1.1.7 root 454: static inline void gen_op_movl_A0_seg(int reg)
455: {
1.1.1.17! root 456: tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
1.1.1.7 root 457: }
1.1 root 458:
1.1.1.7 root 459: static inline void gen_op_addl_A0_seg(int reg)
460: {
1.1.1.17! root 461: tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
1.1.1.7 root 462: tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
463: #ifdef TARGET_X86_64
464: tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
465: #endif
466: }
1.1 root 467:
1.1.1.7 root 468: #ifdef TARGET_X86_64
469: static inline void gen_op_movq_A0_seg(int reg)
470: {
1.1.1.17! root 471: tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
1.1.1.7 root 472: }
1.1 root 473:
1.1.1.7 root 474: static inline void gen_op_addq_A0_seg(int reg)
475: {
1.1.1.17! root 476: tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
1.1.1.7 root 477: tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
478: }
1.1 root 479:
1.1.1.7 root 480: static inline void gen_op_movq_A0_reg(int reg)
481: {
1.1.1.9 root 482: tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
1.1.1.7 root 483: }
1.1 root 484:
1.1.1.7 root 485: static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
486: {
1.1.1.9 root 487: tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
488: if (shift != 0)
1.1.1.7 root 489: tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
490: tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
491: }
1.1 root 492: #endif
493:
1.1.1.7 root 494: static inline void gen_op_lds_T0_A0(int idx)
495: {
496: int mem_index = (idx >> 2) - 1;
497: switch(idx & 3) {
498: case 0:
499: tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index);
500: break;
501: case 1:
502: tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index);
503: break;
504: default:
505: case 2:
506: tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index);
507: break;
508: }
509: }
1.1 root 510:
1.1.1.7 root 511: static inline void gen_op_ld_v(int idx, TCGv t0, TCGv a0)
512: {
513: int mem_index = (idx >> 2) - 1;
514: switch(idx & 3) {
515: case 0:
516: tcg_gen_qemu_ld8u(t0, a0, mem_index);
517: break;
518: case 1:
519: tcg_gen_qemu_ld16u(t0, a0, mem_index);
520: break;
521: case 2:
522: tcg_gen_qemu_ld32u(t0, a0, mem_index);
523: break;
524: default:
525: case 3:
526: /* Should never happen on 32-bit targets. */
527: #ifdef TARGET_X86_64
528: tcg_gen_qemu_ld64(t0, a0, mem_index);
1.1 root 529: #endif
1.1.1.7 root 530: break;
531: }
532: }
1.1 root 533:
1.1.1.7 root 534: /* XXX: always use ldu or lds */
535: static inline void gen_op_ld_T0_A0(int idx)
536: {
537: gen_op_ld_v(idx, cpu_T[0], cpu_A0);
538: }
1.1 root 539:
1.1.1.7 root 540: static inline void gen_op_ldu_T0_A0(int idx)
541: {
542: gen_op_ld_v(idx, cpu_T[0], cpu_A0);
543: }
1.1 root 544:
1.1.1.7 root 545: static inline void gen_op_ld_T1_A0(int idx)
546: {
547: gen_op_ld_v(idx, cpu_T[1], cpu_A0);
548: }
1.1 root 549:
1.1.1.7 root 550: static inline void gen_op_st_v(int idx, TCGv t0, TCGv a0)
551: {
552: int mem_index = (idx >> 2) - 1;
553: switch(idx & 3) {
554: case 0:
555: tcg_gen_qemu_st8(t0, a0, mem_index);
556: break;
557: case 1:
558: tcg_gen_qemu_st16(t0, a0, mem_index);
559: break;
560: case 2:
561: tcg_gen_qemu_st32(t0, a0, mem_index);
562: break;
563: default:
564: case 3:
565: /* Should never happen on 32-bit targets. */
566: #ifdef TARGET_X86_64
567: tcg_gen_qemu_st64(t0, a0, mem_index);
1.1 root 568: #endif
1.1.1.7 root 569: break;
570: }
571: }
1.1 root 572:
1.1.1.7 root 573: static inline void gen_op_st_T0_A0(int idx)
574: {
575: gen_op_st_v(idx, cpu_T[0], cpu_A0);
576: }
1.1 root 577:
1.1.1.7 root 578: static inline void gen_op_st_T1_A0(int idx)
579: {
580: gen_op_st_v(idx, cpu_T[1], cpu_A0);
581: }
1.1 root 582:
583: static inline void gen_jmp_im(target_ulong pc)
584: {
1.1.1.7 root 585: tcg_gen_movi_tl(cpu_tmp0, pc);
1.1.1.17! root 586: tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, eip));
1.1 root 587: }
588:
589: static inline void gen_string_movl_A0_ESI(DisasContext *s)
590: {
591: int override;
592:
593: override = s->override;
594: #ifdef TARGET_X86_64
595: if (s->aflag == 2) {
596: if (override >= 0) {
1.1.1.7 root 597: gen_op_movq_A0_seg(override);
598: gen_op_addq_A0_reg_sN(0, R_ESI);
1.1 root 599: } else {
1.1.1.7 root 600: gen_op_movq_A0_reg(R_ESI);
1.1 root 601: }
602: } else
603: #endif
604: if (s->aflag) {
605: /* 32 bit address */
606: if (s->addseg && override < 0)
607: override = R_DS;
608: if (override >= 0) {
1.1.1.7 root 609: gen_op_movl_A0_seg(override);
610: gen_op_addl_A0_reg_sN(0, R_ESI);
1.1 root 611: } else {
1.1.1.7 root 612: gen_op_movl_A0_reg(R_ESI);
1.1 root 613: }
614: } else {
615: /* 16 address, always override */
616: if (override < 0)
617: override = R_DS;
1.1.1.7 root 618: gen_op_movl_A0_reg(R_ESI);
1.1 root 619: gen_op_andl_A0_ffff();
1.1.1.7 root 620: gen_op_addl_A0_seg(override);
1.1 root 621: }
622: }
623:
624: static inline void gen_string_movl_A0_EDI(DisasContext *s)
625: {
626: #ifdef TARGET_X86_64
627: if (s->aflag == 2) {
1.1.1.7 root 628: gen_op_movq_A0_reg(R_EDI);
1.1 root 629: } else
630: #endif
631: if (s->aflag) {
632: if (s->addseg) {
1.1.1.7 root 633: gen_op_movl_A0_seg(R_ES);
634: gen_op_addl_A0_reg_sN(0, R_EDI);
1.1 root 635: } else {
1.1.1.7 root 636: gen_op_movl_A0_reg(R_EDI);
1.1 root 637: }
638: } else {
1.1.1.7 root 639: gen_op_movl_A0_reg(R_EDI);
1.1 root 640: gen_op_andl_A0_ffff();
1.1.1.7 root 641: gen_op_addl_A0_seg(R_ES);
1.1 root 642: }
643: }
644:
1.1.1.7 root 645: static inline void gen_op_movl_T0_Dshift(int ot)
646: {
1.1.1.17! root 647: tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
1.1.1.7 root 648: tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
1.1 root 649: };
650:
1.1.1.7 root 651: static void gen_extu(int ot, TCGv reg)
652: {
653: switch(ot) {
654: case OT_BYTE:
655: tcg_gen_ext8u_tl(reg, reg);
656: break;
657: case OT_WORD:
658: tcg_gen_ext16u_tl(reg, reg);
659: break;
660: case OT_LONG:
661: tcg_gen_ext32u_tl(reg, reg);
662: break;
663: default:
664: break;
665: }
666: }
1.1 root 667:
1.1.1.7 root 668: static void gen_exts(int ot, TCGv reg)
669: {
670: switch(ot) {
671: case OT_BYTE:
672: tcg_gen_ext8s_tl(reg, reg);
673: break;
674: case OT_WORD:
675: tcg_gen_ext16s_tl(reg, reg);
676: break;
677: case OT_LONG:
678: tcg_gen_ext32s_tl(reg, reg);
679: break;
680: default:
681: break;
682: }
683: }
1.1 root 684:
1.1.1.7 root 685: static inline void gen_op_jnz_ecx(int size, int label1)
686: {
1.1.1.9 root 687: tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
1.1.1.7 root 688: gen_extu(size + 1, cpu_tmp0);
689: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
690: }
1.1 root 691:
1.1.1.7 root 692: static inline void gen_op_jz_ecx(int size, int label1)
693: {
1.1.1.9 root 694: tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
1.1.1.7 root 695: gen_extu(size + 1, cpu_tmp0);
696: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
697: }
1.1 root 698:
1.1.1.7 root 699: static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
700: {
701: switch (ot) {
702: case 0: gen_helper_inb(v, n); break;
703: case 1: gen_helper_inw(v, n); break;
704: case 2: gen_helper_inl(v, n); break;
705: }
1.1 root 706:
1.1.1.7 root 707: }
1.1 root 708:
1.1.1.7 root 709: static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
710: {
711: switch (ot) {
712: case 0: gen_helper_outb(v, n); break;
713: case 1: gen_helper_outw(v, n); break;
714: case 2: gen_helper_outl(v, n); break;
715: }
1.1 root 716:
1.1.1.7 root 717: }
1.1 root 718:
1.1.1.7 root 719: static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
720: uint32_t svm_flags)
1.1 root 721: {
1.1.1.7 root 722: int state_saved;
723: target_ulong next_eip;
724:
725: state_saved = 0;
1.1 root 726: if (s->pe && (s->cpl > s->iopl || s->vm86)) {
727: if (s->cc_op != CC_OP_DYNAMIC)
728: gen_op_set_cc_op(s->cc_op);
729: gen_jmp_im(cur_eip);
1.1.1.7 root 730: state_saved = 1;
731: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
732: switch (ot) {
733: case 0: gen_helper_check_iob(cpu_tmp2_i32); break;
734: case 1: gen_helper_check_iow(cpu_tmp2_i32); break;
735: case 2: gen_helper_check_iol(cpu_tmp2_i32); break;
736: }
737: }
738: if(s->flags & HF_SVMI_MASK) {
739: if (!state_saved) {
740: if (s->cc_op != CC_OP_DYNAMIC)
741: gen_op_set_cc_op(s->cc_op);
742: gen_jmp_im(cur_eip);
743: }
744: svm_flags |= (1 << (4 + ot));
745: next_eip = s->pc - s->cs_base;
746: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
747: gen_helper_svm_check_io(cpu_tmp2_i32, tcg_const_i32(svm_flags),
748: tcg_const_i32(next_eip - cur_eip));
1.1 root 749: }
750: }
751:
752: static inline void gen_movs(DisasContext *s, int ot)
753: {
754: gen_string_movl_A0_ESI(s);
1.1.1.7 root 755: gen_op_ld_T0_A0(ot + s->mem_index);
1.1 root 756: gen_string_movl_A0_EDI(s);
1.1.1.7 root 757: gen_op_st_T0_A0(ot + s->mem_index);
758: gen_op_movl_T0_Dshift(ot);
759: gen_op_add_reg_T0(s->aflag, R_ESI);
760: gen_op_add_reg_T0(s->aflag, R_EDI);
1.1 root 761: }
762:
763: static inline void gen_update_cc_op(DisasContext *s)
764: {
765: if (s->cc_op != CC_OP_DYNAMIC) {
766: gen_op_set_cc_op(s->cc_op);
767: s->cc_op = CC_OP_DYNAMIC;
768: }
769: }
770:
1.1.1.7 root 771: static void gen_op_update1_cc(void)
772: {
773: tcg_gen_discard_tl(cpu_cc_src);
774: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
775: }
776:
777: static void gen_op_update2_cc(void)
778: {
779: tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
780: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
781: }
782:
783: static inline void gen_op_cmpl_T0_T1_cc(void)
784: {
785: tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
786: tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
787: }
788:
789: static inline void gen_op_testl_T0_T1_cc(void)
790: {
791: tcg_gen_discard_tl(cpu_cc_src);
792: tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
793: }
794:
795: static void gen_op_update_neg_cc(void)
796: {
797: tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]);
798: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
799: }
800:
801: /* compute eflags.C to reg */
802: static void gen_compute_eflags_c(TCGv reg)
803: {
804: gen_helper_cc_compute_c(cpu_tmp2_i32, cpu_cc_op);
805: tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32);
806: }
807:
808: /* compute all eflags to cc_src */
809: static void gen_compute_eflags(TCGv reg)
810: {
811: gen_helper_cc_compute_all(cpu_tmp2_i32, cpu_cc_op);
812: tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32);
813: }
814:
815: static inline void gen_setcc_slow_T0(DisasContext *s, int jcc_op)
816: {
817: if (s->cc_op != CC_OP_DYNAMIC)
818: gen_op_set_cc_op(s->cc_op);
819: switch(jcc_op) {
820: case JCC_O:
821: gen_compute_eflags(cpu_T[0]);
822: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 11);
823: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
824: break;
825: case JCC_B:
826: gen_compute_eflags_c(cpu_T[0]);
827: break;
828: case JCC_Z:
829: gen_compute_eflags(cpu_T[0]);
830: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 6);
831: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
832: break;
833: case JCC_BE:
834: gen_compute_eflags(cpu_tmp0);
835: tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 6);
836: tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
837: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
838: break;
839: case JCC_S:
840: gen_compute_eflags(cpu_T[0]);
841: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 7);
842: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
843: break;
844: case JCC_P:
845: gen_compute_eflags(cpu_T[0]);
846: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 2);
847: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
848: break;
849: case JCC_L:
850: gen_compute_eflags(cpu_tmp0);
851: tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */
852: tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 7); /* CC_S */
853: tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
854: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
855: break;
856: default:
857: case JCC_LE:
858: gen_compute_eflags(cpu_tmp0);
859: tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */
860: tcg_gen_shri_tl(cpu_tmp4, cpu_tmp0, 7); /* CC_S */
861: tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 6); /* CC_Z */
862: tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
863: tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
864: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1);
865: break;
866: }
867: }
868:
869: /* return true if setcc_slow is not needed (WARNING: must be kept in
870: sync with gen_jcc1) */
871: static int is_fast_jcc_case(DisasContext *s, int b)
872: {
873: int jcc_op;
874: jcc_op = (b >> 1) & 7;
875: switch(s->cc_op) {
876: /* we optimize the cmp/jcc case */
877: case CC_OP_SUBB:
878: case CC_OP_SUBW:
879: case CC_OP_SUBL:
880: case CC_OP_SUBQ:
881: if (jcc_op == JCC_O || jcc_op == JCC_P)
882: goto slow_jcc;
883: break;
884:
885: /* some jumps are easy to compute */
886: case CC_OP_ADDB:
887: case CC_OP_ADDW:
888: case CC_OP_ADDL:
889: case CC_OP_ADDQ:
890:
891: case CC_OP_LOGICB:
892: case CC_OP_LOGICW:
893: case CC_OP_LOGICL:
894: case CC_OP_LOGICQ:
895:
896: case CC_OP_INCB:
897: case CC_OP_INCW:
898: case CC_OP_INCL:
899: case CC_OP_INCQ:
900:
901: case CC_OP_DECB:
902: case CC_OP_DECW:
903: case CC_OP_DECL:
904: case CC_OP_DECQ:
905:
906: case CC_OP_SHLB:
907: case CC_OP_SHLW:
908: case CC_OP_SHLL:
909: case CC_OP_SHLQ:
910: if (jcc_op != JCC_Z && jcc_op != JCC_S)
911: goto slow_jcc;
912: break;
913: default:
914: slow_jcc:
915: return 0;
916: }
917: return 1;
918: }
919:
920: /* generate a conditional jump to label 'l1' according to jump opcode
921: value 'b'. In the fast case, T0 is guaranted not to be used. */
922: static inline void gen_jcc1(DisasContext *s, int cc_op, int b, int l1)
923: {
924: int inv, jcc_op, size, cond;
925: TCGv t0;
926:
927: inv = b & 1;
928: jcc_op = (b >> 1) & 7;
929:
930: switch(cc_op) {
931: /* we optimize the cmp/jcc case */
932: case CC_OP_SUBB:
933: case CC_OP_SUBW:
934: case CC_OP_SUBL:
935: case CC_OP_SUBQ:
936:
937: size = cc_op - CC_OP_SUBB;
938: switch(jcc_op) {
939: case JCC_Z:
940: fast_jcc_z:
941: switch(size) {
942: case 0:
943: tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xff);
944: t0 = cpu_tmp0;
945: break;
946: case 1:
947: tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffff);
948: t0 = cpu_tmp0;
949: break;
950: #ifdef TARGET_X86_64
951: case 2:
952: tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffffffff);
953: t0 = cpu_tmp0;
954: break;
955: #endif
956: default:
957: t0 = cpu_cc_dst;
958: break;
959: }
960: tcg_gen_brcondi_tl(inv ? TCG_COND_NE : TCG_COND_EQ, t0, 0, l1);
961: break;
962: case JCC_S:
963: fast_jcc_s:
964: switch(size) {
965: case 0:
966: tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80);
967: tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0,
968: 0, l1);
969: break;
970: case 1:
971: tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x8000);
972: tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0,
973: 0, l1);
974: break;
975: #ifdef TARGET_X86_64
976: case 2:
977: tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80000000);
978: tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0,
979: 0, l1);
980: break;
981: #endif
982: default:
983: tcg_gen_brcondi_tl(inv ? TCG_COND_GE : TCG_COND_LT, cpu_cc_dst,
984: 0, l1);
985: break;
986: }
987: break;
988:
989: case JCC_B:
990: cond = inv ? TCG_COND_GEU : TCG_COND_LTU;
991: goto fast_jcc_b;
992: case JCC_BE:
993: cond = inv ? TCG_COND_GTU : TCG_COND_LEU;
994: fast_jcc_b:
995: tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src);
996: switch(size) {
997: case 0:
998: t0 = cpu_tmp0;
999: tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xff);
1000: tcg_gen_andi_tl(t0, cpu_cc_src, 0xff);
1001: break;
1002: case 1:
1003: t0 = cpu_tmp0;
1004: tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffff);
1005: tcg_gen_andi_tl(t0, cpu_cc_src, 0xffff);
1006: break;
1007: #ifdef TARGET_X86_64
1008: case 2:
1009: t0 = cpu_tmp0;
1010: tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffffffff);
1011: tcg_gen_andi_tl(t0, cpu_cc_src, 0xffffffff);
1012: break;
1013: #endif
1014: default:
1015: t0 = cpu_cc_src;
1016: break;
1017: }
1018: tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1);
1019: break;
1020:
1021: case JCC_L:
1022: cond = inv ? TCG_COND_GE : TCG_COND_LT;
1023: goto fast_jcc_l;
1024: case JCC_LE:
1025: cond = inv ? TCG_COND_GT : TCG_COND_LE;
1026: fast_jcc_l:
1027: tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src);
1028: switch(size) {
1029: case 0:
1030: t0 = cpu_tmp0;
1031: tcg_gen_ext8s_tl(cpu_tmp4, cpu_tmp4);
1032: tcg_gen_ext8s_tl(t0, cpu_cc_src);
1033: break;
1034: case 1:
1035: t0 = cpu_tmp0;
1036: tcg_gen_ext16s_tl(cpu_tmp4, cpu_tmp4);
1037: tcg_gen_ext16s_tl(t0, cpu_cc_src);
1038: break;
1039: #ifdef TARGET_X86_64
1040: case 2:
1041: t0 = cpu_tmp0;
1042: tcg_gen_ext32s_tl(cpu_tmp4, cpu_tmp4);
1043: tcg_gen_ext32s_tl(t0, cpu_cc_src);
1044: break;
1045: #endif
1046: default:
1047: t0 = cpu_cc_src;
1048: break;
1049: }
1050: tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1);
1051: break;
1052:
1053: default:
1054: goto slow_jcc;
1055: }
1056: break;
1057:
1058: /* some jumps are easy to compute */
1059: case CC_OP_ADDB:
1060: case CC_OP_ADDW:
1061: case CC_OP_ADDL:
1062: case CC_OP_ADDQ:
1063:
1064: case CC_OP_ADCB:
1065: case CC_OP_ADCW:
1066: case CC_OP_ADCL:
1067: case CC_OP_ADCQ:
1068:
1069: case CC_OP_SBBB:
1070: case CC_OP_SBBW:
1071: case CC_OP_SBBL:
1072: case CC_OP_SBBQ:
1073:
1074: case CC_OP_LOGICB:
1075: case CC_OP_LOGICW:
1076: case CC_OP_LOGICL:
1077: case CC_OP_LOGICQ:
1078:
1079: case CC_OP_INCB:
1080: case CC_OP_INCW:
1081: case CC_OP_INCL:
1082: case CC_OP_INCQ:
1083:
1084: case CC_OP_DECB:
1085: case CC_OP_DECW:
1086: case CC_OP_DECL:
1087: case CC_OP_DECQ:
1088:
1089: case CC_OP_SHLB:
1090: case CC_OP_SHLW:
1091: case CC_OP_SHLL:
1092: case CC_OP_SHLQ:
1093:
1094: case CC_OP_SARB:
1095: case CC_OP_SARW:
1096: case CC_OP_SARL:
1097: case CC_OP_SARQ:
1098: switch(jcc_op) {
1099: case JCC_Z:
1100: size = (cc_op - CC_OP_ADDB) & 3;
1101: goto fast_jcc_z;
1102: case JCC_S:
1103: size = (cc_op - CC_OP_ADDB) & 3;
1104: goto fast_jcc_s;
1105: default:
1106: goto slow_jcc;
1107: }
1108: break;
1109: default:
1110: slow_jcc:
1111: gen_setcc_slow_T0(s, jcc_op);
1112: tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE,
1113: cpu_T[0], 0, l1);
1114: break;
1115: }
1116: }
1117:
1.1 root 1118: /* XXX: does not work with gdbstub "ice" single step - not a
1119: serious problem */
1120: static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
1121: {
1122: int l1, l2;
1123:
1124: l1 = gen_new_label();
1125: l2 = gen_new_label();
1.1.1.7 root 1126: gen_op_jnz_ecx(s->aflag, l1);
1.1 root 1127: gen_set_label(l2);
1128: gen_jmp_tb(s, next_eip, 1);
1129: gen_set_label(l1);
1130: return l2;
1131: }
1132:
1133: static inline void gen_stos(DisasContext *s, int ot)
1134: {
1.1.1.7 root 1135: gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
1.1 root 1136: gen_string_movl_A0_EDI(s);
1.1.1.7 root 1137: gen_op_st_T0_A0(ot + s->mem_index);
1138: gen_op_movl_T0_Dshift(ot);
1139: gen_op_add_reg_T0(s->aflag, R_EDI);
1.1 root 1140: }
1141:
1142: static inline void gen_lods(DisasContext *s, int ot)
1143: {
1144: gen_string_movl_A0_ESI(s);
1.1.1.7 root 1145: gen_op_ld_T0_A0(ot + s->mem_index);
1146: gen_op_mov_reg_T0(ot, R_EAX);
1147: gen_op_movl_T0_Dshift(ot);
1148: gen_op_add_reg_T0(s->aflag, R_ESI);
1.1 root 1149: }
1150:
1151: static inline void gen_scas(DisasContext *s, int ot)
1152: {
1.1.1.7 root 1153: gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
1.1 root 1154: gen_string_movl_A0_EDI(s);
1.1.1.7 root 1155: gen_op_ld_T1_A0(ot + s->mem_index);
1.1 root 1156: gen_op_cmpl_T0_T1_cc();
1.1.1.7 root 1157: gen_op_movl_T0_Dshift(ot);
1158: gen_op_add_reg_T0(s->aflag, R_EDI);
1.1 root 1159: }
1160:
1161: static inline void gen_cmps(DisasContext *s, int ot)
1162: {
1163: gen_string_movl_A0_ESI(s);
1.1.1.7 root 1164: gen_op_ld_T0_A0(ot + s->mem_index);
1.1 root 1165: gen_string_movl_A0_EDI(s);
1.1.1.7 root 1166: gen_op_ld_T1_A0(ot + s->mem_index);
1.1 root 1167: gen_op_cmpl_T0_T1_cc();
1.1.1.7 root 1168: gen_op_movl_T0_Dshift(ot);
1169: gen_op_add_reg_T0(s->aflag, R_ESI);
1170: gen_op_add_reg_T0(s->aflag, R_EDI);
1.1 root 1171: }
1172:
1173: static inline void gen_ins(DisasContext *s, int ot)
1174: {
1.1.1.7 root 1175: if (use_icount)
1176: gen_io_start();
1.1 root 1177: gen_string_movl_A0_EDI(s);
1.1.1.7 root 1178: /* Note: we must do this dummy write first to be restartable in
1179: case of page fault. */
1.1 root 1180: gen_op_movl_T0_0();
1.1.1.7 root 1181: gen_op_st_T0_A0(ot + s->mem_index);
1182: gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
1183: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1184: tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1185: gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
1186: gen_op_st_T0_A0(ot + s->mem_index);
1187: gen_op_movl_T0_Dshift(ot);
1188: gen_op_add_reg_T0(s->aflag, R_EDI);
1189: if (use_icount)
1190: gen_io_end();
1.1 root 1191: }
1192:
1193: static inline void gen_outs(DisasContext *s, int ot)
1194: {
1.1.1.7 root 1195: if (use_icount)
1196: gen_io_start();
1.1 root 1197: gen_string_movl_A0_ESI(s);
1.1.1.7 root 1198: gen_op_ld_T0_A0(ot + s->mem_index);
1199:
1200: gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
1201: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
1202: tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1203: tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
1204: gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
1205:
1206: gen_op_movl_T0_Dshift(ot);
1207: gen_op_add_reg_T0(s->aflag, R_ESI);
1208: if (use_icount)
1209: gen_io_end();
1.1 root 1210: }
1211:
1212: /* same method as Valgrind : we generate jumps to current or next
1213: instruction */
1214: #define GEN_REPZ(op) \
1215: static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1216: target_ulong cur_eip, target_ulong next_eip) \
1217: { \
1218: int l2;\
1219: gen_update_cc_op(s); \
1220: l2 = gen_jz_ecx_string(s, next_eip); \
1221: gen_ ## op(s, ot); \
1.1.1.7 root 1222: gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1.1 root 1223: /* a loop would cause two single step exceptions if ECX = 1 \
1224: before rep string_insn */ \
1225: if (!s->jmp_opt) \
1.1.1.7 root 1226: gen_op_jz_ecx(s->aflag, l2); \
1.1 root 1227: gen_jmp(s, cur_eip); \
1228: }
1229:
1230: #define GEN_REPZ2(op) \
1231: static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1232: target_ulong cur_eip, \
1233: target_ulong next_eip, \
1234: int nz) \
1235: { \
1236: int l2;\
1237: gen_update_cc_op(s); \
1238: l2 = gen_jz_ecx_string(s, next_eip); \
1239: gen_ ## op(s, ot); \
1.1.1.7 root 1240: gen_op_add_reg_im(s->aflag, R_ECX, -1); \
1.1 root 1241: gen_op_set_cc_op(CC_OP_SUBB + ot); \
1.1.1.7 root 1242: gen_jcc1(s, CC_OP_SUBB + ot, (JCC_Z << 1) | (nz ^ 1), l2); \
1.1 root 1243: if (!s->jmp_opt) \
1.1.1.7 root 1244: gen_op_jz_ecx(s->aflag, l2); \
1.1 root 1245: gen_jmp(s, cur_eip); \
1246: }
1247:
1248: GEN_REPZ(movs)
1249: GEN_REPZ(stos)
1250: GEN_REPZ(lods)
1251: GEN_REPZ(ins)
1252: GEN_REPZ(outs)
1253: GEN_REPZ2(scas)
1254: GEN_REPZ2(cmps)
1255:
1.1.1.7 root 1256: static void gen_helper_fp_arith_ST0_FT0(int op)
1257: {
1258: switch (op) {
1259: case 0: gen_helper_fadd_ST0_FT0(); break;
1260: case 1: gen_helper_fmul_ST0_FT0(); break;
1261: case 2: gen_helper_fcom_ST0_FT0(); break;
1262: case 3: gen_helper_fcom_ST0_FT0(); break;
1263: case 4: gen_helper_fsub_ST0_FT0(); break;
1264: case 5: gen_helper_fsubr_ST0_FT0(); break;
1265: case 6: gen_helper_fdiv_ST0_FT0(); break;
1266: case 7: gen_helper_fdivr_ST0_FT0(); break;
1267: }
1268: }
1.1 root 1269:
1270: /* NOTE the exception in "r" op ordering */
1.1.1.7 root 1271: static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1272: {
1273: TCGv_i32 tmp = tcg_const_i32(opreg);
1274: switch (op) {
1275: case 0: gen_helper_fadd_STN_ST0(tmp); break;
1276: case 1: gen_helper_fmul_STN_ST0(tmp); break;
1277: case 4: gen_helper_fsubr_STN_ST0(tmp); break;
1278: case 5: gen_helper_fsub_STN_ST0(tmp); break;
1279: case 6: gen_helper_fdivr_STN_ST0(tmp); break;
1280: case 7: gen_helper_fdiv_STN_ST0(tmp); break;
1281: }
1282: }
1.1 root 1283:
1284: /* if d == OR_TMP0, it means memory operand (address in A0) */
1285: static void gen_op(DisasContext *s1, int op, int ot, int d)
1286: {
1287: if (d != OR_TMP0) {
1.1.1.7 root 1288: gen_op_mov_TN_reg(ot, 0, d);
1.1 root 1289: } else {
1.1.1.7 root 1290: gen_op_ld_T0_A0(ot + s1->mem_index);
1.1 root 1291: }
1292: switch(op) {
1293: case OP_ADCL:
1.1.1.7 root 1294: if (s1->cc_op != CC_OP_DYNAMIC)
1295: gen_op_set_cc_op(s1->cc_op);
1296: gen_compute_eflags_c(cpu_tmp4);
1297: tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1298: tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1299: if (d != OR_TMP0)
1300: gen_op_mov_reg_T0(ot, d);
1301: else
1302: gen_op_st_T0_A0(ot + s1->mem_index);
1303: tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
1304: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1305: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4);
1306: tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2);
1307: tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_ADDB + ot);
1308: s1->cc_op = CC_OP_DYNAMIC;
1309: break;
1.1 root 1310: case OP_SBBL:
1311: if (s1->cc_op != CC_OP_DYNAMIC)
1312: gen_op_set_cc_op(s1->cc_op);
1.1.1.7 root 1313: gen_compute_eflags_c(cpu_tmp4);
1314: tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1315: tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
1316: if (d != OR_TMP0)
1317: gen_op_mov_reg_T0(ot, d);
1318: else
1319: gen_op_st_T0_A0(ot + s1->mem_index);
1320: tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
1321: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1322: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4);
1323: tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2);
1324: tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_SUBB + ot);
1.1 root 1325: s1->cc_op = CC_OP_DYNAMIC;
1.1.1.7 root 1326: break;
1.1 root 1327: case OP_ADDL:
1328: gen_op_addl_T0_T1();
1.1.1.7 root 1329: if (d != OR_TMP0)
1330: gen_op_mov_reg_T0(ot, d);
1331: else
1332: gen_op_st_T0_A0(ot + s1->mem_index);
1333: gen_op_update2_cc();
1.1 root 1334: s1->cc_op = CC_OP_ADDB + ot;
1335: break;
1336: case OP_SUBL:
1.1.1.7 root 1337: tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1338: if (d != OR_TMP0)
1339: gen_op_mov_reg_T0(ot, d);
1340: else
1341: gen_op_st_T0_A0(ot + s1->mem_index);
1342: gen_op_update2_cc();
1.1 root 1343: s1->cc_op = CC_OP_SUBB + ot;
1344: break;
1345: default:
1346: case OP_ANDL:
1.1.1.7 root 1347: tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1348: if (d != OR_TMP0)
1349: gen_op_mov_reg_T0(ot, d);
1350: else
1351: gen_op_st_T0_A0(ot + s1->mem_index);
1352: gen_op_update1_cc();
1353: s1->cc_op = CC_OP_LOGICB + ot;
1354: break;
1.1 root 1355: case OP_ORL:
1.1.1.7 root 1356: tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1357: if (d != OR_TMP0)
1358: gen_op_mov_reg_T0(ot, d);
1359: else
1360: gen_op_st_T0_A0(ot + s1->mem_index);
1361: gen_op_update1_cc();
1362: s1->cc_op = CC_OP_LOGICB + ot;
1363: break;
1.1 root 1364: case OP_XORL:
1.1.1.7 root 1365: tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1366: if (d != OR_TMP0)
1367: gen_op_mov_reg_T0(ot, d);
1368: else
1369: gen_op_st_T0_A0(ot + s1->mem_index);
1370: gen_op_update1_cc();
1.1 root 1371: s1->cc_op = CC_OP_LOGICB + ot;
1372: break;
1373: case OP_CMPL:
1374: gen_op_cmpl_T0_T1_cc();
1375: s1->cc_op = CC_OP_SUBB + ot;
1376: break;
1377: }
1.1.1.7 root 1378: }
1379:
1380: /* if d == OR_TMP0, it means memory operand (address in A0) */
1381: static void gen_inc(DisasContext *s1, int ot, int d, int c)
1382: {
1383: if (d != OR_TMP0)
1384: gen_op_mov_TN_reg(ot, 0, d);
1385: else
1386: gen_op_ld_T0_A0(ot + s1->mem_index);
1387: if (s1->cc_op != CC_OP_DYNAMIC)
1388: gen_op_set_cc_op(s1->cc_op);
1389: if (c > 0) {
1390: tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
1391: s1->cc_op = CC_OP_INCB + ot;
1392: } else {
1393: tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
1394: s1->cc_op = CC_OP_DECB + ot;
1395: }
1396: if (d != OR_TMP0)
1397: gen_op_mov_reg_T0(ot, d);
1398: else
1399: gen_op_st_T0_A0(ot + s1->mem_index);
1400: gen_compute_eflags_c(cpu_cc_src);
1401: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1402: }
1403:
1404: static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
1405: int is_right, int is_arith)
1406: {
1407: target_ulong mask;
1408: int shift_label;
1.1.1.16 root 1409: TCGv t0, t1, t2;
1.1.1.7 root 1410:
1.1.1.16 root 1411: if (ot == OT_QUAD) {
1.1.1.7 root 1412: mask = 0x3f;
1.1.1.16 root 1413: } else {
1.1.1.7 root 1414: mask = 0x1f;
1.1.1.16 root 1415: }
1.1.1.7 root 1416:
1417: /* load */
1.1.1.16 root 1418: if (op1 == OR_TMP0) {
1.1.1.7 root 1419: gen_op_ld_T0_A0(ot + s->mem_index);
1.1.1.16 root 1420: } else {
1.1.1.7 root 1421: gen_op_mov_TN_reg(ot, 0, op1);
1.1.1.16 root 1422: }
1.1.1.7 root 1423:
1.1.1.16 root 1424: t0 = tcg_temp_local_new();
1425: t1 = tcg_temp_local_new();
1426: t2 = tcg_temp_local_new();
1.1.1.7 root 1427:
1.1.1.16 root 1428: tcg_gen_andi_tl(t2, cpu_T[1], mask);
1.1.1.7 root 1429:
1430: if (is_right) {
1431: if (is_arith) {
1432: gen_exts(ot, cpu_T[0]);
1.1.1.16 root 1433: tcg_gen_mov_tl(t0, cpu_T[0]);
1434: tcg_gen_sar_tl(cpu_T[0], cpu_T[0], t2);
1.1.1.7 root 1435: } else {
1436: gen_extu(ot, cpu_T[0]);
1.1.1.16 root 1437: tcg_gen_mov_tl(t0, cpu_T[0]);
1438: tcg_gen_shr_tl(cpu_T[0], cpu_T[0], t2);
1.1.1.7 root 1439: }
1440: } else {
1.1.1.16 root 1441: tcg_gen_mov_tl(t0, cpu_T[0]);
1442: tcg_gen_shl_tl(cpu_T[0], cpu_T[0], t2);
1.1.1.7 root 1443: }
1444:
1445: /* store */
1.1.1.16 root 1446: if (op1 == OR_TMP0) {
1.1.1.7 root 1447: gen_op_st_T0_A0(ot + s->mem_index);
1.1.1.16 root 1448: } else {
1.1.1.7 root 1449: gen_op_mov_reg_T0(ot, op1);
1.1.1.16 root 1450: }
1451:
1.1.1.7 root 1452: /* update eflags if non zero shift */
1.1.1.16 root 1453: if (s->cc_op != CC_OP_DYNAMIC) {
1.1.1.7 root 1454: gen_op_set_cc_op(s->cc_op);
1.1.1.16 root 1455: }
1.1.1.7 root 1456:
1.1.1.16 root 1457: tcg_gen_mov_tl(t1, cpu_T[0]);
1.1.1.7 root 1458:
1459: shift_label = gen_new_label();
1.1.1.16 root 1460: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, shift_label);
1.1.1.7 root 1461:
1.1.1.16 root 1462: tcg_gen_addi_tl(t2, t2, -1);
1463: tcg_gen_mov_tl(cpu_cc_dst, t1);
1464:
1465: if (is_right) {
1466: if (is_arith) {
1467: tcg_gen_sar_tl(cpu_cc_src, t0, t2);
1468: } else {
1469: tcg_gen_shr_tl(cpu_cc_src, t0, t2);
1470: }
1471: } else {
1472: tcg_gen_shl_tl(cpu_cc_src, t0, t2);
1473: }
1474:
1475: if (is_right) {
1.1.1.7 root 1476: tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot);
1.1.1.16 root 1477: } else {
1.1.1.7 root 1478: tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot);
1.1.1.16 root 1479: }
1480:
1.1.1.7 root 1481: gen_set_label(shift_label);
1482: s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1483:
1484: tcg_temp_free(t0);
1485: tcg_temp_free(t1);
1.1.1.16 root 1486: tcg_temp_free(t2);
1.1.1.7 root 1487: }
1488:
1489: static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
1490: int is_right, int is_arith)
1491: {
1492: int mask;
1493:
1494: if (ot == OT_QUAD)
1495: mask = 0x3f;
1496: else
1497: mask = 0x1f;
1498:
1499: /* load */
1500: if (op1 == OR_TMP0)
1501: gen_op_ld_T0_A0(ot + s->mem_index);
1502: else
1503: gen_op_mov_TN_reg(ot, 0, op1);
1504:
1505: op2 &= mask;
1506: if (op2 != 0) {
1507: if (is_right) {
1508: if (is_arith) {
1509: gen_exts(ot, cpu_T[0]);
1510: tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1511: tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
1512: } else {
1513: gen_extu(ot, cpu_T[0]);
1514: tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1515: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
1516: }
1517: } else {
1518: tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
1519: tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
1520: }
1521: }
1522:
1523: /* store */
1524: if (op1 == OR_TMP0)
1525: gen_op_st_T0_A0(ot + s->mem_index);
1526: else
1527: gen_op_mov_reg_T0(ot, op1);
1528:
1529: /* update eflags if non zero shift */
1530: if (op2 != 0) {
1531: tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
1532: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
1533: if (is_right)
1534: s->cc_op = CC_OP_SARB + ot;
1535: else
1536: s->cc_op = CC_OP_SHLB + ot;
1537: }
1538: }
1539:
1540: static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2)
1541: {
1542: if (arg2 >= 0)
1543: tcg_gen_shli_tl(ret, arg1, arg2);
1544: else
1545: tcg_gen_shri_tl(ret, arg1, -arg2);
1546: }
1547:
1548: static void gen_rot_rm_T1(DisasContext *s, int ot, int op1,
1549: int is_right)
1550: {
1551: target_ulong mask;
1552: int label1, label2, data_bits;
1553: TCGv t0, t1, t2, a0;
1554:
1555: /* XXX: inefficient, but we must use local temps */
1556: t0 = tcg_temp_local_new();
1557: t1 = tcg_temp_local_new();
1558: t2 = tcg_temp_local_new();
1559: a0 = tcg_temp_local_new();
1560:
1561: if (ot == OT_QUAD)
1562: mask = 0x3f;
1563: else
1564: mask = 0x1f;
1565:
1566: /* load */
1567: if (op1 == OR_TMP0) {
1568: tcg_gen_mov_tl(a0, cpu_A0);
1569: gen_op_ld_v(ot + s->mem_index, t0, a0);
1570: } else {
1571: gen_op_mov_v_reg(ot, t0, op1);
1572: }
1573:
1574: tcg_gen_mov_tl(t1, cpu_T[1]);
1575:
1576: tcg_gen_andi_tl(t1, t1, mask);
1577:
1578: /* Must test zero case to avoid using undefined behaviour in TCG
1579: shifts. */
1580: label1 = gen_new_label();
1581: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label1);
1582:
1583: if (ot <= OT_WORD)
1584: tcg_gen_andi_tl(cpu_tmp0, t1, (1 << (3 + ot)) - 1);
1585: else
1586: tcg_gen_mov_tl(cpu_tmp0, t1);
1587:
1588: gen_extu(ot, t0);
1589: tcg_gen_mov_tl(t2, t0);
1590:
1591: data_bits = 8 << ot;
1592: /* XXX: rely on behaviour of shifts when operand 2 overflows (XXX:
1593: fix TCG definition) */
1594: if (is_right) {
1595: tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp0);
1.1.1.9 root 1596: tcg_gen_subfi_tl(cpu_tmp0, data_bits, cpu_tmp0);
1.1.1.7 root 1597: tcg_gen_shl_tl(t0, t0, cpu_tmp0);
1598: } else {
1599: tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp0);
1.1.1.9 root 1600: tcg_gen_subfi_tl(cpu_tmp0, data_bits, cpu_tmp0);
1.1.1.7 root 1601: tcg_gen_shr_tl(t0, t0, cpu_tmp0);
1602: }
1603: tcg_gen_or_tl(t0, t0, cpu_tmp4);
1604:
1605: gen_set_label(label1);
1606: /* store */
1607: if (op1 == OR_TMP0) {
1608: gen_op_st_v(ot + s->mem_index, t0, a0);
1609: } else {
1610: gen_op_mov_reg_v(ot, op1, t0);
1.1 root 1611: }
1.1.1.7 root 1612:
1613: /* update eflags */
1614: if (s->cc_op != CC_OP_DYNAMIC)
1615: gen_op_set_cc_op(s->cc_op);
1.1 root 1616:
1.1.1.7 root 1617: label2 = gen_new_label();
1618: tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label2);
1619:
1620: gen_compute_eflags(cpu_cc_src);
1621: tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C));
1622: tcg_gen_xor_tl(cpu_tmp0, t2, t0);
1623: tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1));
1624: tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O);
1625: tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);
1626: if (is_right) {
1627: tcg_gen_shri_tl(t0, t0, data_bits - 1);
1628: }
1629: tcg_gen_andi_tl(t0, t0, CC_C);
1630: tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
1631:
1632: tcg_gen_discard_tl(cpu_cc_dst);
1633: tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS);
1634:
1635: gen_set_label(label2);
1636: s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1637:
1638: tcg_temp_free(t0);
1639: tcg_temp_free(t1);
1640: tcg_temp_free(t2);
1641: tcg_temp_free(a0);
1642: }
1643:
1.1.1.8 root 1644: static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
1645: int is_right)
1646: {
1647: int mask;
1648: int data_bits;
1649: TCGv t0, t1, a0;
1650:
1651: /* XXX: inefficient, but we must use local temps */
1652: t0 = tcg_temp_local_new();
1653: t1 = tcg_temp_local_new();
1654: a0 = tcg_temp_local_new();
1655:
1656: if (ot == OT_QUAD)
1657: mask = 0x3f;
1658: else
1659: mask = 0x1f;
1660:
1661: /* load */
1662: if (op1 == OR_TMP0) {
1663: tcg_gen_mov_tl(a0, cpu_A0);
1664: gen_op_ld_v(ot + s->mem_index, t0, a0);
1665: } else {
1666: gen_op_mov_v_reg(ot, t0, op1);
1667: }
1668:
1669: gen_extu(ot, t0);
1670: tcg_gen_mov_tl(t1, t0);
1671:
1672: op2 &= mask;
1673: data_bits = 8 << ot;
1674: if (op2 != 0) {
1675: int shift = op2 & ((1 << (3 + ot)) - 1);
1676: if (is_right) {
1677: tcg_gen_shri_tl(cpu_tmp4, t0, shift);
1678: tcg_gen_shli_tl(t0, t0, data_bits - shift);
1679: }
1680: else {
1681: tcg_gen_shli_tl(cpu_tmp4, t0, shift);
1682: tcg_gen_shri_tl(t0, t0, data_bits - shift);
1683: }
1684: tcg_gen_or_tl(t0, t0, cpu_tmp4);
1685: }
1686:
1687: /* store */
1688: if (op1 == OR_TMP0) {
1689: gen_op_st_v(ot + s->mem_index, t0, a0);
1690: } else {
1691: gen_op_mov_reg_v(ot, op1, t0);
1692: }
1693:
1694: if (op2 != 0) {
1695: /* update eflags */
1696: if (s->cc_op != CC_OP_DYNAMIC)
1697: gen_op_set_cc_op(s->cc_op);
1698:
1699: gen_compute_eflags(cpu_cc_src);
1700: tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C));
1701: tcg_gen_xor_tl(cpu_tmp0, t1, t0);
1702: tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1));
1703: tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O);
1704: tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);
1705: if (is_right) {
1706: tcg_gen_shri_tl(t0, t0, data_bits - 1);
1707: }
1708: tcg_gen_andi_tl(t0, t0, CC_C);
1709: tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
1710:
1711: tcg_gen_discard_tl(cpu_cc_dst);
1712: tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS);
1713: s->cc_op = CC_OP_EFLAGS;
1714: }
1715:
1716: tcg_temp_free(t0);
1717: tcg_temp_free(t1);
1718: tcg_temp_free(a0);
1719: }
1720:
1.1.1.7 root 1721: /* XXX: add faster immediate = 1 case */
1722: static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
1723: int is_right)
1.1 root 1724: {
1.1.1.7 root 1725: int label1;
1726:
1727: if (s->cc_op != CC_OP_DYNAMIC)
1728: gen_op_set_cc_op(s->cc_op);
1729:
1730: /* load */
1731: if (op1 == OR_TMP0)
1732: gen_op_ld_T0_A0(ot + s->mem_index);
1.1 root 1733: else
1.1.1.7 root 1734: gen_op_mov_TN_reg(ot, 0, op1);
1735:
1736: if (is_right) {
1737: switch (ot) {
1738: case 0: gen_helper_rcrb(cpu_T[0], cpu_T[0], cpu_T[1]); break;
1739: case 1: gen_helper_rcrw(cpu_T[0], cpu_T[0], cpu_T[1]); break;
1740: case 2: gen_helper_rcrl(cpu_T[0], cpu_T[0], cpu_T[1]); break;
1741: #ifdef TARGET_X86_64
1742: case 3: gen_helper_rcrq(cpu_T[0], cpu_T[0], cpu_T[1]); break;
1743: #endif
1744: }
1.1 root 1745: } else {
1.1.1.7 root 1746: switch (ot) {
1747: case 0: gen_helper_rclb(cpu_T[0], cpu_T[0], cpu_T[1]); break;
1748: case 1: gen_helper_rclw(cpu_T[0], cpu_T[0], cpu_T[1]); break;
1749: case 2: gen_helper_rcll(cpu_T[0], cpu_T[0], cpu_T[1]); break;
1750: #ifdef TARGET_X86_64
1751: case 3: gen_helper_rclq(cpu_T[0], cpu_T[0], cpu_T[1]); break;
1752: #endif
1753: }
1.1 root 1754: }
1.1.1.7 root 1755: /* store */
1756: if (op1 == OR_TMP0)
1757: gen_op_st_T0_A0(ot + s->mem_index);
1758: else
1759: gen_op_mov_reg_T0(ot, op1);
1760:
1761: /* update eflags */
1762: label1 = gen_new_label();
1763: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cc_tmp, -1, label1);
1764:
1765: tcg_gen_mov_tl(cpu_cc_src, cpu_cc_tmp);
1766: tcg_gen_discard_tl(cpu_cc_dst);
1767: tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS);
1768:
1769: gen_set_label(label1);
1770: s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1771: }
1772:
1773: /* XXX: add faster immediate case */
1774: static void gen_shiftd_rm_T1_T3(DisasContext *s, int ot, int op1,
1775: int is_right)
1776: {
1777: int label1, label2, data_bits;
1778: target_ulong mask;
1779: TCGv t0, t1, t2, a0;
1780:
1781: t0 = tcg_temp_local_new();
1782: t1 = tcg_temp_local_new();
1783: t2 = tcg_temp_local_new();
1784: a0 = tcg_temp_local_new();
1785:
1786: if (ot == OT_QUAD)
1787: mask = 0x3f;
1.1 root 1788: else
1.1.1.7 root 1789: mask = 0x1f;
1790:
1791: /* load */
1792: if (op1 == OR_TMP0) {
1793: tcg_gen_mov_tl(a0, cpu_A0);
1794: gen_op_ld_v(ot + s->mem_index, t0, a0);
1795: } else {
1796: gen_op_mov_v_reg(ot, t0, op1);
1797: }
1798:
1799: tcg_gen_andi_tl(cpu_T3, cpu_T3, mask);
1800:
1801: tcg_gen_mov_tl(t1, cpu_T[1]);
1802: tcg_gen_mov_tl(t2, cpu_T3);
1803:
1804: /* Must test zero case to avoid using undefined behaviour in TCG
1805: shifts. */
1806: label1 = gen_new_label();
1807: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
1808:
1809: tcg_gen_addi_tl(cpu_tmp5, t2, -1);
1810: if (ot == OT_WORD) {
1811: /* Note: we implement the Intel behaviour for shift count > 16 */
1812: if (is_right) {
1813: tcg_gen_andi_tl(t0, t0, 0xffff);
1814: tcg_gen_shli_tl(cpu_tmp0, t1, 16);
1815: tcg_gen_or_tl(t0, t0, cpu_tmp0);
1816: tcg_gen_ext32u_tl(t0, t0);
1817:
1818: tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5);
1819:
1820: /* only needed if count > 16, but a test would complicate */
1.1.1.9 root 1821: tcg_gen_subfi_tl(cpu_tmp5, 32, t2);
1.1.1.7 root 1822: tcg_gen_shl_tl(cpu_tmp0, t0, cpu_tmp5);
1823:
1824: tcg_gen_shr_tl(t0, t0, t2);
1825:
1826: tcg_gen_or_tl(t0, t0, cpu_tmp0);
1827: } else {
1828: /* XXX: not optimal */
1829: tcg_gen_andi_tl(t0, t0, 0xffff);
1830: tcg_gen_shli_tl(t1, t1, 16);
1831: tcg_gen_or_tl(t1, t1, t0);
1832: tcg_gen_ext32u_tl(t1, t1);
1833:
1834: tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5);
1.1.1.9 root 1835: tcg_gen_subfi_tl(cpu_tmp0, 32, cpu_tmp5);
1836: tcg_gen_shr_tl(cpu_tmp5, t1, cpu_tmp0);
1837: tcg_gen_or_tl(cpu_tmp4, cpu_tmp4, cpu_tmp5);
1.1.1.7 root 1838:
1839: tcg_gen_shl_tl(t0, t0, t2);
1.1.1.9 root 1840: tcg_gen_subfi_tl(cpu_tmp5, 32, t2);
1.1.1.7 root 1841: tcg_gen_shr_tl(t1, t1, cpu_tmp5);
1842: tcg_gen_or_tl(t0, t0, t1);
1843: }
1844: } else {
1845: data_bits = 8 << ot;
1846: if (is_right) {
1847: if (ot == OT_LONG)
1848: tcg_gen_ext32u_tl(t0, t0);
1849:
1850: tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5);
1851:
1852: tcg_gen_shr_tl(t0, t0, t2);
1.1.1.9 root 1853: tcg_gen_subfi_tl(cpu_tmp5, data_bits, t2);
1.1.1.7 root 1854: tcg_gen_shl_tl(t1, t1, cpu_tmp5);
1855: tcg_gen_or_tl(t0, t0, t1);
1856:
1857: } else {
1858: if (ot == OT_LONG)
1859: tcg_gen_ext32u_tl(t1, t1);
1860:
1861: tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5);
1862:
1863: tcg_gen_shl_tl(t0, t0, t2);
1.1.1.9 root 1864: tcg_gen_subfi_tl(cpu_tmp5, data_bits, t2);
1.1.1.7 root 1865: tcg_gen_shr_tl(t1, t1, cpu_tmp5);
1866: tcg_gen_or_tl(t0, t0, t1);
1867: }
1868: }
1869: tcg_gen_mov_tl(t1, cpu_tmp4);
1870:
1871: gen_set_label(label1);
1872: /* store */
1873: if (op1 == OR_TMP0) {
1874: gen_op_st_v(ot + s->mem_index, t0, a0);
1875: } else {
1876: gen_op_mov_reg_v(ot, op1, t0);
1877: }
1878:
1879: /* update eflags */
1880: if (s->cc_op != CC_OP_DYNAMIC)
1881: gen_op_set_cc_op(s->cc_op);
1882:
1883: label2 = gen_new_label();
1884: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label2);
1885:
1886: tcg_gen_mov_tl(cpu_cc_src, t1);
1887: tcg_gen_mov_tl(cpu_cc_dst, t0);
1888: if (is_right) {
1889: tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot);
1890: } else {
1891: tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot);
1892: }
1893: gen_set_label(label2);
1894: s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1895:
1896: tcg_temp_free(t0);
1897: tcg_temp_free(t1);
1898: tcg_temp_free(t2);
1899: tcg_temp_free(a0);
1.1 root 1900: }
1901:
1902: static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1903: {
1904: if (s != OR_TMP1)
1.1.1.7 root 1905: gen_op_mov_TN_reg(ot, 1, s);
1906: switch(op) {
1907: case OP_ROL:
1908: gen_rot_rm_T1(s1, ot, d, 0);
1909: break;
1910: case OP_ROR:
1911: gen_rot_rm_T1(s1, ot, d, 1);
1912: break;
1913: case OP_SHL:
1914: case OP_SHL1:
1915: gen_shift_rm_T1(s1, ot, d, 0, 0);
1916: break;
1917: case OP_SHR:
1918: gen_shift_rm_T1(s1, ot, d, 1, 0);
1919: break;
1920: case OP_SAR:
1921: gen_shift_rm_T1(s1, ot, d, 1, 1);
1922: break;
1923: case OP_RCL:
1924: gen_rotc_rm_T1(s1, ot, d, 0);
1925: break;
1926: case OP_RCR:
1927: gen_rotc_rm_T1(s1, ot, d, 1);
1928: break;
1929: }
1.1 root 1930: }
1931:
1932: static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1933: {
1.1.1.7 root 1934: switch(op) {
1.1.1.8 root 1935: case OP_ROL:
1936: gen_rot_rm_im(s1, ot, d, c, 0);
1937: break;
1938: case OP_ROR:
1939: gen_rot_rm_im(s1, ot, d, c, 1);
1940: break;
1.1.1.7 root 1941: case OP_SHL:
1942: case OP_SHL1:
1943: gen_shift_rm_im(s1, ot, d, c, 0, 0);
1944: break;
1945: case OP_SHR:
1946: gen_shift_rm_im(s1, ot, d, c, 1, 0);
1947: break;
1948: case OP_SAR:
1949: gen_shift_rm_im(s1, ot, d, c, 1, 1);
1950: break;
1951: default:
1952: /* currently not optimized */
1953: gen_op_movl_T1_im(c);
1954: gen_shift(s1, op, ot, d, OR_TMP1);
1955: break;
1956: }
1.1 root 1957: }
1958:
1959: static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1960: {
1961: target_long disp;
1962: int havesib;
1963: int base;
1964: int index;
1965: int scale;
1966: int opreg;
1967: int mod, rm, code, override, must_add_seg;
1968:
1969: override = s->override;
1970: must_add_seg = s->addseg;
1971: if (override >= 0)
1972: must_add_seg = 1;
1973: mod = (modrm >> 6) & 3;
1974: rm = modrm & 7;
1975:
1976: if (s->aflag) {
1977:
1978: havesib = 0;
1979: base = rm;
1980: index = 0;
1981: scale = 0;
1.1.1.6 root 1982:
1.1 root 1983: if (base == 4) {
1984: havesib = 1;
1985: code = ldub_code(s->pc++);
1986: scale = (code >> 6) & 3;
1987: index = ((code >> 3) & 7) | REX_X(s);
1988: base = (code & 7);
1989: }
1990: base |= REX_B(s);
1991:
1992: switch (mod) {
1993: case 0:
1994: if ((base & 7) == 5) {
1995: base = -1;
1996: disp = (int32_t)ldl_code(s->pc);
1997: s->pc += 4;
1998: if (CODE64(s) && !havesib) {
1999: disp += s->pc + s->rip_offset;
2000: }
2001: } else {
2002: disp = 0;
2003: }
2004: break;
2005: case 1:
2006: disp = (int8_t)ldub_code(s->pc++);
2007: break;
2008: default:
2009: case 2:
1.1.1.13 root 2010: disp = (int32_t)ldl_code(s->pc);
1.1 root 2011: s->pc += 4;
2012: break;
2013: }
1.1.1.6 root 2014:
1.1 root 2015: if (base >= 0) {
2016: /* for correct popl handling with esp */
2017: if (base == 4 && s->popl_esp_hack)
2018: disp += s->popl_esp_hack;
2019: #ifdef TARGET_X86_64
2020: if (s->aflag == 2) {
1.1.1.7 root 2021: gen_op_movq_A0_reg(base);
1.1 root 2022: if (disp != 0) {
1.1.1.7 root 2023: gen_op_addq_A0_im(disp);
1.1 root 2024: }
1.1.1.6 root 2025: } else
1.1 root 2026: #endif
2027: {
1.1.1.7 root 2028: gen_op_movl_A0_reg(base);
1.1 root 2029: if (disp != 0)
2030: gen_op_addl_A0_im(disp);
2031: }
2032: } else {
2033: #ifdef TARGET_X86_64
2034: if (s->aflag == 2) {
1.1.1.7 root 2035: gen_op_movq_A0_im(disp);
1.1.1.6 root 2036: } else
1.1 root 2037: #endif
2038: {
2039: gen_op_movl_A0_im(disp);
2040: }
2041: }
1.1.1.11 root 2042: /* index == 4 means no index */
2043: if (havesib && (index != 4)) {
1.1 root 2044: #ifdef TARGET_X86_64
2045: if (s->aflag == 2) {
1.1.1.7 root 2046: gen_op_addq_A0_reg_sN(scale, index);
1.1.1.6 root 2047: } else
1.1 root 2048: #endif
2049: {
1.1.1.7 root 2050: gen_op_addl_A0_reg_sN(scale, index);
1.1 root 2051: }
2052: }
2053: if (must_add_seg) {
2054: if (override < 0) {
2055: if (base == R_EBP || base == R_ESP)
2056: override = R_SS;
2057: else
2058: override = R_DS;
2059: }
2060: #ifdef TARGET_X86_64
2061: if (s->aflag == 2) {
1.1.1.7 root 2062: gen_op_addq_A0_seg(override);
1.1.1.6 root 2063: } else
1.1 root 2064: #endif
2065: {
1.1.1.7 root 2066: gen_op_addl_A0_seg(override);
1.1 root 2067: }
2068: }
2069: } else {
2070: switch (mod) {
2071: case 0:
2072: if (rm == 6) {
2073: disp = lduw_code(s->pc);
2074: s->pc += 2;
2075: gen_op_movl_A0_im(disp);
2076: rm = 0; /* avoid SS override */
2077: goto no_rm;
2078: } else {
2079: disp = 0;
2080: }
2081: break;
2082: case 1:
2083: disp = (int8_t)ldub_code(s->pc++);
2084: break;
2085: default:
2086: case 2:
2087: disp = lduw_code(s->pc);
2088: s->pc += 2;
2089: break;
2090: }
2091: switch(rm) {
2092: case 0:
1.1.1.7 root 2093: gen_op_movl_A0_reg(R_EBX);
2094: gen_op_addl_A0_reg_sN(0, R_ESI);
1.1 root 2095: break;
2096: case 1:
1.1.1.7 root 2097: gen_op_movl_A0_reg(R_EBX);
2098: gen_op_addl_A0_reg_sN(0, R_EDI);
1.1 root 2099: break;
2100: case 2:
1.1.1.7 root 2101: gen_op_movl_A0_reg(R_EBP);
2102: gen_op_addl_A0_reg_sN(0, R_ESI);
1.1 root 2103: break;
2104: case 3:
1.1.1.7 root 2105: gen_op_movl_A0_reg(R_EBP);
2106: gen_op_addl_A0_reg_sN(0, R_EDI);
1.1 root 2107: break;
2108: case 4:
1.1.1.7 root 2109: gen_op_movl_A0_reg(R_ESI);
1.1 root 2110: break;
2111: case 5:
1.1.1.7 root 2112: gen_op_movl_A0_reg(R_EDI);
1.1 root 2113: break;
2114: case 6:
1.1.1.7 root 2115: gen_op_movl_A0_reg(R_EBP);
1.1 root 2116: break;
2117: default:
2118: case 7:
1.1.1.7 root 2119: gen_op_movl_A0_reg(R_EBX);
1.1 root 2120: break;
2121: }
2122: if (disp != 0)
2123: gen_op_addl_A0_im(disp);
2124: gen_op_andl_A0_ffff();
2125: no_rm:
2126: if (must_add_seg) {
2127: if (override < 0) {
2128: if (rm == 2 || rm == 3 || rm == 6)
2129: override = R_SS;
2130: else
2131: override = R_DS;
2132: }
1.1.1.7 root 2133: gen_op_addl_A0_seg(override);
1.1 root 2134: }
2135: }
2136:
2137: opreg = OR_A0;
2138: disp = 0;
2139: *reg_ptr = opreg;
2140: *offset_ptr = disp;
2141: }
2142:
1.1.1.5 root 2143: static void gen_nop_modrm(DisasContext *s, int modrm)
2144: {
2145: int mod, rm, base, code;
2146:
2147: mod = (modrm >> 6) & 3;
2148: if (mod == 3)
2149: return;
2150: rm = modrm & 7;
2151:
2152: if (s->aflag) {
2153:
2154: base = rm;
1.1.1.6 root 2155:
1.1.1.5 root 2156: if (base == 4) {
2157: code = ldub_code(s->pc++);
2158: base = (code & 7);
2159: }
1.1.1.6 root 2160:
1.1.1.5 root 2161: switch (mod) {
2162: case 0:
2163: if (base == 5) {
2164: s->pc += 4;
2165: }
2166: break;
2167: case 1:
2168: s->pc++;
2169: break;
2170: default:
2171: case 2:
2172: s->pc += 4;
2173: break;
2174: }
2175: } else {
2176: switch (mod) {
2177: case 0:
2178: if (rm == 6) {
2179: s->pc += 2;
2180: }
2181: break;
2182: case 1:
2183: s->pc++;
2184: break;
2185: default:
2186: case 2:
2187: s->pc += 2;
2188: break;
2189: }
2190: }
2191: }
2192:
1.1 root 2193: /* used for LEA and MOV AX, mem */
2194: static void gen_add_A0_ds_seg(DisasContext *s)
2195: {
2196: int override, must_add_seg;
2197: must_add_seg = s->addseg;
2198: override = R_DS;
2199: if (s->override >= 0) {
2200: override = s->override;
2201: must_add_seg = 1;
2202: }
2203: if (must_add_seg) {
2204: #ifdef TARGET_X86_64
2205: if (CODE64(s)) {
1.1.1.7 root 2206: gen_op_addq_A0_seg(override);
1.1.1.6 root 2207: } else
1.1 root 2208: #endif
2209: {
1.1.1.7 root 2210: gen_op_addl_A0_seg(override);
1.1 root 2211: }
2212: }
2213: }
2214:
1.1.1.7 root 2215: /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
1.1 root 2216: OR_TMP0 */
2217: static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
2218: {
2219: int mod, rm, opreg, disp;
2220:
2221: mod = (modrm >> 6) & 3;
2222: rm = (modrm & 7) | REX_B(s);
2223: if (mod == 3) {
2224: if (is_store) {
2225: if (reg != OR_TMP0)
1.1.1.7 root 2226: gen_op_mov_TN_reg(ot, 0, reg);
2227: gen_op_mov_reg_T0(ot, rm);
1.1 root 2228: } else {
1.1.1.7 root 2229: gen_op_mov_TN_reg(ot, 0, rm);
1.1 root 2230: if (reg != OR_TMP0)
1.1.1.7 root 2231: gen_op_mov_reg_T0(ot, reg);
1.1 root 2232: }
2233: } else {
2234: gen_lea_modrm(s, modrm, &opreg, &disp);
2235: if (is_store) {
2236: if (reg != OR_TMP0)
1.1.1.7 root 2237: gen_op_mov_TN_reg(ot, 0, reg);
2238: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 2239: } else {
1.1.1.7 root 2240: gen_op_ld_T0_A0(ot + s->mem_index);
1.1 root 2241: if (reg != OR_TMP0)
1.1.1.7 root 2242: gen_op_mov_reg_T0(ot, reg);
1.1 root 2243: }
2244: }
2245: }
2246:
2247: static inline uint32_t insn_get(DisasContext *s, int ot)
2248: {
2249: uint32_t ret;
2250:
2251: switch(ot) {
2252: case OT_BYTE:
2253: ret = ldub_code(s->pc);
2254: s->pc++;
2255: break;
2256: case OT_WORD:
2257: ret = lduw_code(s->pc);
2258: s->pc += 2;
2259: break;
2260: default:
2261: case OT_LONG:
2262: ret = ldl_code(s->pc);
2263: s->pc += 4;
2264: break;
2265: }
2266: return ret;
2267: }
2268:
2269: static inline int insn_const_size(unsigned int ot)
2270: {
2271: if (ot <= OT_LONG)
2272: return 1 << ot;
2273: else
2274: return 4;
2275: }
2276:
1.1.1.2 root 2277: static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2278: {
2279: TranslationBlock *tb;
2280: target_ulong pc;
2281:
2282: pc = s->cs_base + eip;
2283: tb = s->tb;
2284: /* NOTE: we handle the case where the TB spans two pages here */
2285: if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2286: (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2287: /* jump to same page: we can use a direct jump */
1.1.1.7 root 2288: tcg_gen_goto_tb(tb_num);
1.1.1.2 root 2289: gen_jmp_im(eip);
1.1.1.15 root 2290: tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
1.1.1.2 root 2291: } else {
2292: /* jump to another page: currently not optimized */
2293: gen_jmp_im(eip);
2294: gen_eob(s);
2295: }
2296: }
2297:
1.1.1.6 root 2298: static inline void gen_jcc(DisasContext *s, int b,
1.1 root 2299: target_ulong val, target_ulong next_eip)
2300: {
1.1.1.7 root 2301: int l1, l2, cc_op;
1.1.1.6 root 2302:
1.1.1.7 root 2303: cc_op = s->cc_op;
1.1.1.13 root 2304: gen_update_cc_op(s);
1.1 root 2305: if (s->jmp_opt) {
2306: l1 = gen_new_label();
1.1.1.7 root 2307: gen_jcc1(s, cc_op, b, l1);
2308:
1.1.1.2 root 2309: gen_goto_tb(s, 0, next_eip);
1.1 root 2310:
2311: gen_set_label(l1);
1.1.1.2 root 2312: gen_goto_tb(s, 1, val);
1.1.1.13 root 2313: s->is_jmp = DISAS_TB_JUMP;
1.1 root 2314: } else {
2315:
2316: l1 = gen_new_label();
2317: l2 = gen_new_label();
1.1.1.7 root 2318: gen_jcc1(s, cc_op, b, l1);
2319:
1.1 root 2320: gen_jmp_im(next_eip);
1.1.1.7 root 2321: tcg_gen_br(l2);
2322:
1.1 root 2323: gen_set_label(l1);
2324: gen_jmp_im(val);
2325: gen_set_label(l2);
2326: gen_eob(s);
2327: }
2328: }
2329:
2330: static void gen_setcc(DisasContext *s, int b)
2331: {
1.1.1.7 root 2332: int inv, jcc_op, l1;
2333: TCGv t0;
1.1.1.6 root 2334:
1.1.1.7 root 2335: if (is_fast_jcc_case(s, b)) {
2336: /* nominal case: we use a jump */
2337: /* XXX: make it faster by adding new instructions in TCG */
2338: t0 = tcg_temp_local_new();
2339: tcg_gen_movi_tl(t0, 0);
2340: l1 = gen_new_label();
2341: gen_jcc1(s, s->cc_op, b ^ 1, l1);
2342: tcg_gen_movi_tl(t0, 1);
2343: gen_set_label(l1);
2344: tcg_gen_mov_tl(cpu_T[0], t0);
2345: tcg_temp_free(t0);
2346: } else {
2347: /* slow case: it is more efficient not to generate a jump,
2348: although it is questionnable whether this optimization is
2349: worth to */
2350: inv = b & 1;
2351: jcc_op = (b >> 1) & 7;
2352: gen_setcc_slow_T0(s, jcc_op);
2353: if (inv) {
2354: tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1);
1.1 root 2355: }
2356: }
2357: }
2358:
1.1.1.7 root 2359: static inline void gen_op_movl_T0_seg(int seg_reg)
2360: {
2361: tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
2362: offsetof(CPUX86State,segs[seg_reg].selector));
2363: }
2364:
2365: static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2366: {
2367: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
2368: tcg_gen_st32_tl(cpu_T[0], cpu_env,
2369: offsetof(CPUX86State,segs[seg_reg].selector));
2370: tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
2371: tcg_gen_st_tl(cpu_T[0], cpu_env,
2372: offsetof(CPUX86State,segs[seg_reg].base));
2373: }
2374:
1.1 root 2375: /* move T0 to seg_reg and compute if the CPU state may change. Never
2376: call this function with seg_reg == R_CS */
2377: static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2378: {
2379: if (s->pe && !s->vm86) {
2380: /* XXX: optimize by finding processor state dynamically */
2381: if (s->cc_op != CC_OP_DYNAMIC)
2382: gen_op_set_cc_op(s->cc_op);
2383: gen_jmp_im(cur_eip);
1.1.1.7 root 2384: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2385: gen_helper_load_seg(tcg_const_i32(seg_reg), cpu_tmp2_i32);
1.1 root 2386: /* abort translation because the addseg value may change or
2387: because ss32 may change. For R_SS, translation must always
2388: stop as a special handling must be done to disable hardware
2389: interrupts for the next instruction */
2390: if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1.1.1.13 root 2391: s->is_jmp = DISAS_TB_JUMP;
1.1 root 2392: } else {
1.1.1.7 root 2393: gen_op_movl_seg_T0_vm(seg_reg);
1.1 root 2394: if (seg_reg == R_SS)
1.1.1.13 root 2395: s->is_jmp = DISAS_TB_JUMP;
1.1 root 2396: }
2397: }
2398:
1.1.1.6 root 2399: static inline int svm_is_rep(int prefixes)
2400: {
2401: return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2402: }
2403:
1.1.1.7 root 2404: static inline void
1.1.1.6 root 2405: gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
1.1.1.7 root 2406: uint32_t type, uint64_t param)
1.1.1.6 root 2407: {
1.1.1.7 root 2408: /* no SVM activated; fast case */
2409: if (likely(!(s->flags & HF_SVMI_MASK)))
2410: return;
2411: if (s->cc_op != CC_OP_DYNAMIC)
2412: gen_op_set_cc_op(s->cc_op);
2413: gen_jmp_im(pc_start - s->cs_base);
2414: gen_helper_svm_check_intercept_param(tcg_const_i32(type),
2415: tcg_const_i64(param));
1.1.1.6 root 2416: }
2417:
1.1.1.7 root 2418: static inline void
1.1.1.6 root 2419: gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2420: {
1.1.1.7 root 2421: gen_svm_check_intercept_param(s, pc_start, type, 0);
1.1.1.6 root 2422: }
2423:
1.1 root 2424: static inline void gen_stack_update(DisasContext *s, int addend)
2425: {
2426: #ifdef TARGET_X86_64
2427: if (CODE64(s)) {
1.1.1.7 root 2428: gen_op_add_reg_im(2, R_ESP, addend);
1.1 root 2429: } else
2430: #endif
2431: if (s->ss32) {
1.1.1.7 root 2432: gen_op_add_reg_im(1, R_ESP, addend);
1.1 root 2433: } else {
1.1.1.7 root 2434: gen_op_add_reg_im(0, R_ESP, addend);
1.1 root 2435: }
2436: }
2437:
2438: /* generate a push. It depends on ss32, addseg and dflag */
2439: static void gen_push_T0(DisasContext *s)
2440: {
2441: #ifdef TARGET_X86_64
2442: if (CODE64(s)) {
1.1.1.7 root 2443: gen_op_movq_A0_reg(R_ESP);
1.1 root 2444: if (s->dflag) {
1.1.1.7 root 2445: gen_op_addq_A0_im(-8);
2446: gen_op_st_T0_A0(OT_QUAD + s->mem_index);
1.1 root 2447: } else {
1.1.1.7 root 2448: gen_op_addq_A0_im(-2);
2449: gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1 root 2450: }
1.1.1.7 root 2451: gen_op_mov_reg_A0(2, R_ESP);
1.1.1.6 root 2452: } else
1.1 root 2453: #endif
2454: {
1.1.1.7 root 2455: gen_op_movl_A0_reg(R_ESP);
1.1 root 2456: if (!s->dflag)
1.1.1.7 root 2457: gen_op_addl_A0_im(-2);
1.1 root 2458: else
1.1.1.7 root 2459: gen_op_addl_A0_im(-4);
1.1 root 2460: if (s->ss32) {
2461: if (s->addseg) {
1.1.1.7 root 2462: tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2463: gen_op_addl_A0_seg(R_SS);
1.1 root 2464: }
2465: } else {
2466: gen_op_andl_A0_ffff();
1.1.1.7 root 2467: tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2468: gen_op_addl_A0_seg(R_SS);
1.1 root 2469: }
1.1.1.7 root 2470: gen_op_st_T0_A0(s->dflag + 1 + s->mem_index);
1.1 root 2471: if (s->ss32 && !s->addseg)
1.1.1.7 root 2472: gen_op_mov_reg_A0(1, R_ESP);
1.1 root 2473: else
1.1.1.7 root 2474: gen_op_mov_reg_T1(s->ss32 + 1, R_ESP);
1.1 root 2475: }
2476: }
2477:
2478: /* generate a push. It depends on ss32, addseg and dflag */
2479: /* slower version for T1, only used for call Ev */
2480: static void gen_push_T1(DisasContext *s)
2481: {
2482: #ifdef TARGET_X86_64
2483: if (CODE64(s)) {
1.1.1.7 root 2484: gen_op_movq_A0_reg(R_ESP);
1.1 root 2485: if (s->dflag) {
1.1.1.7 root 2486: gen_op_addq_A0_im(-8);
2487: gen_op_st_T1_A0(OT_QUAD + s->mem_index);
1.1 root 2488: } else {
1.1.1.7 root 2489: gen_op_addq_A0_im(-2);
2490: gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1 root 2491: }
1.1.1.7 root 2492: gen_op_mov_reg_A0(2, R_ESP);
1.1.1.6 root 2493: } else
1.1 root 2494: #endif
2495: {
1.1.1.7 root 2496: gen_op_movl_A0_reg(R_ESP);
1.1 root 2497: if (!s->dflag)
1.1.1.7 root 2498: gen_op_addl_A0_im(-2);
1.1 root 2499: else
1.1.1.7 root 2500: gen_op_addl_A0_im(-4);
1.1 root 2501: if (s->ss32) {
2502: if (s->addseg) {
1.1.1.7 root 2503: gen_op_addl_A0_seg(R_SS);
1.1 root 2504: }
2505: } else {
2506: gen_op_andl_A0_ffff();
1.1.1.7 root 2507: gen_op_addl_A0_seg(R_SS);
1.1 root 2508: }
1.1.1.7 root 2509: gen_op_st_T1_A0(s->dflag + 1 + s->mem_index);
1.1.1.6 root 2510:
1.1 root 2511: if (s->ss32 && !s->addseg)
1.1.1.7 root 2512: gen_op_mov_reg_A0(1, R_ESP);
1.1 root 2513: else
2514: gen_stack_update(s, (-2) << s->dflag);
2515: }
2516: }
2517:
2518: /* two step pop is necessary for precise exceptions */
2519: static void gen_pop_T0(DisasContext *s)
2520: {
2521: #ifdef TARGET_X86_64
2522: if (CODE64(s)) {
1.1.1.7 root 2523: gen_op_movq_A0_reg(R_ESP);
2524: gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index);
1.1.1.6 root 2525: } else
1.1 root 2526: #endif
2527: {
1.1.1.7 root 2528: gen_op_movl_A0_reg(R_ESP);
1.1 root 2529: if (s->ss32) {
2530: if (s->addseg)
1.1.1.7 root 2531: gen_op_addl_A0_seg(R_SS);
1.1 root 2532: } else {
2533: gen_op_andl_A0_ffff();
1.1.1.7 root 2534: gen_op_addl_A0_seg(R_SS);
1.1 root 2535: }
1.1.1.7 root 2536: gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index);
1.1 root 2537: }
2538: }
2539:
2540: static void gen_pop_update(DisasContext *s)
2541: {
2542: #ifdef TARGET_X86_64
2543: if (CODE64(s) && s->dflag) {
2544: gen_stack_update(s, 8);
2545: } else
2546: #endif
2547: {
2548: gen_stack_update(s, 2 << s->dflag);
2549: }
2550: }
2551:
2552: static void gen_stack_A0(DisasContext *s)
2553: {
1.1.1.7 root 2554: gen_op_movl_A0_reg(R_ESP);
1.1 root 2555: if (!s->ss32)
2556: gen_op_andl_A0_ffff();
1.1.1.7 root 2557: tcg_gen_mov_tl(cpu_T[1], cpu_A0);
1.1 root 2558: if (s->addseg)
1.1.1.7 root 2559: gen_op_addl_A0_seg(R_SS);
1.1 root 2560: }
2561:
2562: /* NOTE: wrap around in 16 bit not fully handled */
2563: static void gen_pusha(DisasContext *s)
2564: {
2565: int i;
1.1.1.7 root 2566: gen_op_movl_A0_reg(R_ESP);
1.1 root 2567: gen_op_addl_A0_im(-16 << s->dflag);
2568: if (!s->ss32)
2569: gen_op_andl_A0_ffff();
1.1.1.7 root 2570: tcg_gen_mov_tl(cpu_T[1], cpu_A0);
1.1 root 2571: if (s->addseg)
1.1.1.7 root 2572: gen_op_addl_A0_seg(R_SS);
1.1 root 2573: for(i = 0;i < 8; i++) {
1.1.1.7 root 2574: gen_op_mov_TN_reg(OT_LONG, 0, 7 - i);
2575: gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index);
1.1 root 2576: gen_op_addl_A0_im(2 << s->dflag);
2577: }
1.1.1.7 root 2578: gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
1.1 root 2579: }
2580:
2581: /* NOTE: wrap around in 16 bit not fully handled */
2582: static void gen_popa(DisasContext *s)
2583: {
2584: int i;
1.1.1.7 root 2585: gen_op_movl_A0_reg(R_ESP);
1.1 root 2586: if (!s->ss32)
2587: gen_op_andl_A0_ffff();
1.1.1.7 root 2588: tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2589: tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 << s->dflag);
1.1 root 2590: if (s->addseg)
1.1.1.7 root 2591: gen_op_addl_A0_seg(R_SS);
1.1 root 2592: for(i = 0;i < 8; i++) {
2593: /* ESP is not reloaded */
2594: if (i != 3) {
1.1.1.7 root 2595: gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index);
2596: gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i);
1.1 root 2597: }
2598: gen_op_addl_A0_im(2 << s->dflag);
2599: }
1.1.1.7 root 2600: gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
1.1 root 2601: }
2602:
2603: static void gen_enter(DisasContext *s, int esp_addend, int level)
2604: {
2605: int ot, opsize;
2606:
2607: level &= 0x1f;
2608: #ifdef TARGET_X86_64
2609: if (CODE64(s)) {
2610: ot = s->dflag ? OT_QUAD : OT_WORD;
2611: opsize = 1 << ot;
1.1.1.6 root 2612:
1.1.1.7 root 2613: gen_op_movl_A0_reg(R_ESP);
1.1 root 2614: gen_op_addq_A0_im(-opsize);
1.1.1.7 root 2615: tcg_gen_mov_tl(cpu_T[1], cpu_A0);
1.1 root 2616:
2617: /* push bp */
1.1.1.7 root 2618: gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2619: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 2620: if (level) {
1.1.1.7 root 2621: /* XXX: must save state */
2622: gen_helper_enter64_level(tcg_const_i32(level),
2623: tcg_const_i32((ot == OT_QUAD)),
2624: cpu_T[1]);
2625: }
2626: gen_op_mov_reg_T1(ot, R_EBP);
2627: tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2628: gen_op_mov_reg_T1(OT_QUAD, R_ESP);
1.1.1.6 root 2629: } else
1.1 root 2630: #endif
2631: {
2632: ot = s->dflag + OT_WORD;
2633: opsize = 2 << s->dflag;
1.1.1.6 root 2634:
1.1.1.7 root 2635: gen_op_movl_A0_reg(R_ESP);
1.1 root 2636: gen_op_addl_A0_im(-opsize);
2637: if (!s->ss32)
2638: gen_op_andl_A0_ffff();
1.1.1.7 root 2639: tcg_gen_mov_tl(cpu_T[1], cpu_A0);
1.1 root 2640: if (s->addseg)
1.1.1.7 root 2641: gen_op_addl_A0_seg(R_SS);
1.1 root 2642: /* push bp */
1.1.1.7 root 2643: gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
2644: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 2645: if (level) {
1.1.1.7 root 2646: /* XXX: must save state */
2647: gen_helper_enter_level(tcg_const_i32(level),
2648: tcg_const_i32(s->dflag),
2649: cpu_T[1]);
2650: }
2651: gen_op_mov_reg_T1(ot, R_EBP);
2652: tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
2653: gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
1.1 root 2654: }
2655: }
2656:
2657: static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2658: {
2659: if (s->cc_op != CC_OP_DYNAMIC)
2660: gen_op_set_cc_op(s->cc_op);
2661: gen_jmp_im(cur_eip);
1.1.1.7 root 2662: gen_helper_raise_exception(tcg_const_i32(trapno));
1.1.1.13 root 2663: s->is_jmp = DISAS_TB_JUMP;
1.1 root 2664: }
2665:
2666: /* an interrupt is different from an exception because of the
1.1.1.6 root 2667: privilege checks */
2668: static void gen_interrupt(DisasContext *s, int intno,
1.1 root 2669: target_ulong cur_eip, target_ulong next_eip)
2670: {
2671: if (s->cc_op != CC_OP_DYNAMIC)
2672: gen_op_set_cc_op(s->cc_op);
2673: gen_jmp_im(cur_eip);
1.1.1.7 root 2674: gen_helper_raise_interrupt(tcg_const_i32(intno),
2675: tcg_const_i32(next_eip - cur_eip));
1.1.1.13 root 2676: s->is_jmp = DISAS_TB_JUMP;
1.1 root 2677: }
2678:
2679: static void gen_debug(DisasContext *s, target_ulong cur_eip)
2680: {
2681: if (s->cc_op != CC_OP_DYNAMIC)
2682: gen_op_set_cc_op(s->cc_op);
2683: gen_jmp_im(cur_eip);
1.1.1.7 root 2684: gen_helper_debug();
1.1.1.13 root 2685: s->is_jmp = DISAS_TB_JUMP;
1.1 root 2686: }
2687:
2688: /* generate a generic end of block. Trace exception is also generated
2689: if needed */
2690: static void gen_eob(DisasContext *s)
2691: {
2692: if (s->cc_op != CC_OP_DYNAMIC)
2693: gen_op_set_cc_op(s->cc_op);
2694: if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
1.1.1.7 root 2695: gen_helper_reset_inhibit_irq();
1.1 root 2696: }
1.1.1.8 root 2697: if (s->tb->flags & HF_RF_MASK) {
2698: gen_helper_reset_rf();
2699: }
1.1 root 2700: if (s->singlestep_enabled) {
1.1.1.7 root 2701: gen_helper_debug();
1.1 root 2702: } else if (s->tf) {
1.1.1.7 root 2703: gen_helper_single_step();
1.1 root 2704: } else {
1.1.1.7 root 2705: tcg_gen_exit_tb(0);
1.1 root 2706: }
1.1.1.13 root 2707: s->is_jmp = DISAS_TB_JUMP;
1.1 root 2708: }
2709:
2710: /* generate a jump to eip. No segment change must happen before as a
2711: direct call to the next block may occur */
2712: static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2713: {
2714: if (s->jmp_opt) {
1.1.1.13 root 2715: gen_update_cc_op(s);
1.1.1.2 root 2716: gen_goto_tb(s, tb_num, eip);
1.1.1.13 root 2717: s->is_jmp = DISAS_TB_JUMP;
1.1 root 2718: } else {
2719: gen_jmp_im(eip);
2720: gen_eob(s);
2721: }
2722: }
2723:
2724: static void gen_jmp(DisasContext *s, target_ulong eip)
2725: {
2726: gen_jmp_tb(s, eip, 0);
2727: }
2728:
1.1.1.7 root 2729: static inline void gen_ldq_env_A0(int idx, int offset)
1.1 root 2730: {
1.1.1.7 root 2731: int mem_index = (idx >> 2) - 1;
2732: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
2733: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
1.1 root 2734: }
2735:
1.1.1.7 root 2736: static inline void gen_stq_env_A0(int idx, int offset)
1.1 root 2737: {
1.1.1.7 root 2738: int mem_index = (idx >> 2) - 1;
2739: tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
2740: tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
1.1 root 2741: }
2742:
1.1.1.7 root 2743: static inline void gen_ldo_env_A0(int idx, int offset)
1.1 root 2744: {
1.1.1.7 root 2745: int mem_index = (idx >> 2) - 1;
2746: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index);
2747: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2748: tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2749: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_tmp0, mem_index);
2750: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
1.1 root 2751: }
2752:
1.1.1.7 root 2753: static inline void gen_sto_env_A0(int idx, int offset)
2754: {
2755: int mem_index = (idx >> 2) - 1;
2756: tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
2757: tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index);
2758: tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
2759: tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
2760: tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_tmp0, mem_index);
2761: }
1.1 root 2762:
1.1.1.7 root 2763: static inline void gen_op_movo(int d_offset, int s_offset)
2764: {
2765: tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2766: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2767: tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8);
2768: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8);
2769: }
1.1 root 2770:
1.1.1.7 root 2771: static inline void gen_op_movq(int d_offset, int s_offset)
2772: {
2773: tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2774: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2775: }
1.1 root 2776:
1.1.1.7 root 2777: static inline void gen_op_movl(int d_offset, int s_offset)
2778: {
2779: tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2780: tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
2781: }
2782:
2783: static inline void gen_op_movq_env_0(int d_offset)
2784: {
2785: tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2786: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2787: }
1.1 root 2788:
1.1.1.7 root 2789: #define SSE_SPECIAL ((void *)1)
2790: #define SSE_DUMMY ((void *)2)
1.1 root 2791:
1.1.1.7 root 2792: #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2793: #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2794: gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
1.1 root 2795:
1.1.1.7 root 2796: static void *sse_op_table1[256][4] = {
2797: /* 3DNow! extensions */
2798: [0x0e] = { SSE_DUMMY }, /* femms */
2799: [0x0f] = { SSE_DUMMY }, /* pf... */
1.1 root 2800: /* pure SSE operations */
2801: [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2802: [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
1.1.1.3 root 2803: [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
1.1 root 2804: [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
1.1.1.7 root 2805: [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2806: [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
1.1 root 2807: [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2808: [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2809:
2810: [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2811: [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2812: [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
1.1.1.9 root 2813: [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
1.1 root 2814: [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2815: [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
1.1.1.7 root 2816: [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2817: [0x2f] = { gen_helper_comiss, gen_helper_comisd },
1.1 root 2818: [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2819: [0x51] = SSE_FOP(sqrt),
1.1.1.7 root 2820: [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2821: [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2822: [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2823: [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2824: [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2825: [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
1.1 root 2826: [0x58] = SSE_FOP(add),
2827: [0x59] = SSE_FOP(mul),
1.1.1.7 root 2828: [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2829: gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2830: [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
1.1 root 2831: [0x5c] = SSE_FOP(sub),
2832: [0x5d] = SSE_FOP(min),
2833: [0x5e] = SSE_FOP(div),
2834: [0x5f] = SSE_FOP(max),
2835:
2836: [0xc2] = SSE_FOP(cmpeq),
1.1.1.7 root 2837: [0xc6] = { gen_helper_shufps, gen_helper_shufpd },
2838:
2839: [0x38] = { SSE_SPECIAL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* SSSE3/SSE4 */
2840: [0x3a] = { SSE_SPECIAL, SSE_SPECIAL }, /* SSSE3/SSE4 */
1.1 root 2841:
2842: /* MMX ops and their SSE extensions */
2843: [0x60] = MMX_OP2(punpcklbw),
2844: [0x61] = MMX_OP2(punpcklwd),
2845: [0x62] = MMX_OP2(punpckldq),
2846: [0x63] = MMX_OP2(packsswb),
2847: [0x64] = MMX_OP2(pcmpgtb),
2848: [0x65] = MMX_OP2(pcmpgtw),
2849: [0x66] = MMX_OP2(pcmpgtl),
2850: [0x67] = MMX_OP2(packuswb),
2851: [0x68] = MMX_OP2(punpckhbw),
2852: [0x69] = MMX_OP2(punpckhwd),
2853: [0x6a] = MMX_OP2(punpckhdq),
2854: [0x6b] = MMX_OP2(packssdw),
1.1.1.7 root 2855: [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2856: [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
1.1 root 2857: [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2858: [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
1.1.1.7 root 2859: [0x70] = { gen_helper_pshufw_mmx,
2860: gen_helper_pshufd_xmm,
2861: gen_helper_pshufhw_xmm,
2862: gen_helper_pshuflw_xmm },
1.1 root 2863: [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2864: [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2865: [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2866: [0x74] = MMX_OP2(pcmpeqb),
2867: [0x75] = MMX_OP2(pcmpeqw),
2868: [0x76] = MMX_OP2(pcmpeql),
1.1.1.7 root 2869: [0x77] = { SSE_DUMMY }, /* emms */
1.1.1.9 root 2870: [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2871: [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
1.1.1.7 root 2872: [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2873: [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
1.1 root 2874: [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2875: [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2876: [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2877: [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
1.1.1.7 root 2878: [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
1.1 root 2879: [0xd1] = MMX_OP2(psrlw),
2880: [0xd2] = MMX_OP2(psrld),
2881: [0xd3] = MMX_OP2(psrlq),
2882: [0xd4] = MMX_OP2(paddq),
2883: [0xd5] = MMX_OP2(pmullw),
2884: [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2885: [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2886: [0xd8] = MMX_OP2(psubusb),
2887: [0xd9] = MMX_OP2(psubusw),
2888: [0xda] = MMX_OP2(pminub),
2889: [0xdb] = MMX_OP2(pand),
2890: [0xdc] = MMX_OP2(paddusb),
2891: [0xdd] = MMX_OP2(paddusw),
2892: [0xde] = MMX_OP2(pmaxub),
2893: [0xdf] = MMX_OP2(pandn),
2894: [0xe0] = MMX_OP2(pavgb),
2895: [0xe1] = MMX_OP2(psraw),
2896: [0xe2] = MMX_OP2(psrad),
2897: [0xe3] = MMX_OP2(pavgw),
2898: [0xe4] = MMX_OP2(pmulhuw),
2899: [0xe5] = MMX_OP2(pmulhw),
1.1.1.7 root 2900: [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
1.1 root 2901: [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2902: [0xe8] = MMX_OP2(psubsb),
2903: [0xe9] = MMX_OP2(psubsw),
2904: [0xea] = MMX_OP2(pminsw),
2905: [0xeb] = MMX_OP2(por),
2906: [0xec] = MMX_OP2(paddsb),
2907: [0xed] = MMX_OP2(paddsw),
2908: [0xee] = MMX_OP2(pmaxsw),
2909: [0xef] = MMX_OP2(pxor),
1.1.1.3 root 2910: [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
1.1 root 2911: [0xf1] = MMX_OP2(psllw),
2912: [0xf2] = MMX_OP2(pslld),
2913: [0xf3] = MMX_OP2(psllq),
2914: [0xf4] = MMX_OP2(pmuludq),
2915: [0xf5] = MMX_OP2(pmaddwd),
2916: [0xf6] = MMX_OP2(psadbw),
2917: [0xf7] = MMX_OP2(maskmov),
2918: [0xf8] = MMX_OP2(psubb),
2919: [0xf9] = MMX_OP2(psubw),
2920: [0xfa] = MMX_OP2(psubl),
2921: [0xfb] = MMX_OP2(psubq),
2922: [0xfc] = MMX_OP2(paddb),
2923: [0xfd] = MMX_OP2(paddw),
2924: [0xfe] = MMX_OP2(paddl),
2925: };
2926:
1.1.1.7 root 2927: static void *sse_op_table2[3 * 8][2] = {
1.1 root 2928: [0 + 2] = MMX_OP2(psrlw),
2929: [0 + 4] = MMX_OP2(psraw),
2930: [0 + 6] = MMX_OP2(psllw),
2931: [8 + 2] = MMX_OP2(psrld),
2932: [8 + 4] = MMX_OP2(psrad),
2933: [8 + 6] = MMX_OP2(pslld),
2934: [16 + 2] = MMX_OP2(psrlq),
1.1.1.7 root 2935: [16 + 3] = { NULL, gen_helper_psrldq_xmm },
1.1 root 2936: [16 + 6] = MMX_OP2(psllq),
1.1.1.7 root 2937: [16 + 7] = { NULL, gen_helper_pslldq_xmm },
1.1 root 2938: };
2939:
1.1.1.7 root 2940: static void *sse_op_table3[4 * 3] = {
2941: gen_helper_cvtsi2ss,
2942: gen_helper_cvtsi2sd,
2943: X86_64_ONLY(gen_helper_cvtsq2ss),
2944: X86_64_ONLY(gen_helper_cvtsq2sd),
2945:
2946: gen_helper_cvttss2si,
2947: gen_helper_cvttsd2si,
2948: X86_64_ONLY(gen_helper_cvttss2sq),
2949: X86_64_ONLY(gen_helper_cvttsd2sq),
2950:
2951: gen_helper_cvtss2si,
2952: gen_helper_cvtsd2si,
2953: X86_64_ONLY(gen_helper_cvtss2sq),
2954: X86_64_ONLY(gen_helper_cvtsd2sq),
1.1 root 2955: };
1.1.1.6 root 2956:
1.1.1.7 root 2957: static void *sse_op_table4[8][4] = {
1.1 root 2958: SSE_FOP(cmpeq),
2959: SSE_FOP(cmplt),
2960: SSE_FOP(cmple),
2961: SSE_FOP(cmpunord),
2962: SSE_FOP(cmpneq),
2963: SSE_FOP(cmpnlt),
2964: SSE_FOP(cmpnle),
2965: SSE_FOP(cmpord),
2966: };
1.1.1.6 root 2967:
1.1.1.7 root 2968: static void *sse_op_table5[256] = {
2969: [0x0c] = gen_helper_pi2fw,
2970: [0x0d] = gen_helper_pi2fd,
2971: [0x1c] = gen_helper_pf2iw,
2972: [0x1d] = gen_helper_pf2id,
2973: [0x8a] = gen_helper_pfnacc,
2974: [0x8e] = gen_helper_pfpnacc,
2975: [0x90] = gen_helper_pfcmpge,
2976: [0x94] = gen_helper_pfmin,
2977: [0x96] = gen_helper_pfrcp,
2978: [0x97] = gen_helper_pfrsqrt,
2979: [0x9a] = gen_helper_pfsub,
2980: [0x9e] = gen_helper_pfadd,
2981: [0xa0] = gen_helper_pfcmpgt,
2982: [0xa4] = gen_helper_pfmax,
2983: [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2984: [0xa7] = gen_helper_movq, /* pfrsqit1 */
2985: [0xaa] = gen_helper_pfsubr,
2986: [0xae] = gen_helper_pfacc,
2987: [0xb0] = gen_helper_pfcmpeq,
2988: [0xb4] = gen_helper_pfmul,
2989: [0xb6] = gen_helper_movq, /* pfrcpit2 */
2990: [0xb7] = gen_helper_pmulhrw_mmx,
2991: [0xbb] = gen_helper_pswapd,
2992: [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
2993: };
2994:
2995: struct sse_op_helper_s {
2996: void *op[2]; uint32_t ext_mask;
2997: };
2998: #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
2999: #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
3000: #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
3001: #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
3002: static struct sse_op_helper_s sse_op_table6[256] = {
3003: [0x00] = SSSE3_OP(pshufb),
3004: [0x01] = SSSE3_OP(phaddw),
3005: [0x02] = SSSE3_OP(phaddd),
3006: [0x03] = SSSE3_OP(phaddsw),
3007: [0x04] = SSSE3_OP(pmaddubsw),
3008: [0x05] = SSSE3_OP(phsubw),
3009: [0x06] = SSSE3_OP(phsubd),
3010: [0x07] = SSSE3_OP(phsubsw),
3011: [0x08] = SSSE3_OP(psignb),
3012: [0x09] = SSSE3_OP(psignw),
3013: [0x0a] = SSSE3_OP(psignd),
3014: [0x0b] = SSSE3_OP(pmulhrsw),
3015: [0x10] = SSE41_OP(pblendvb),
3016: [0x14] = SSE41_OP(blendvps),
3017: [0x15] = SSE41_OP(blendvpd),
3018: [0x17] = SSE41_OP(ptest),
3019: [0x1c] = SSSE3_OP(pabsb),
3020: [0x1d] = SSSE3_OP(pabsw),
3021: [0x1e] = SSSE3_OP(pabsd),
3022: [0x20] = SSE41_OP(pmovsxbw),
3023: [0x21] = SSE41_OP(pmovsxbd),
3024: [0x22] = SSE41_OP(pmovsxbq),
3025: [0x23] = SSE41_OP(pmovsxwd),
3026: [0x24] = SSE41_OP(pmovsxwq),
3027: [0x25] = SSE41_OP(pmovsxdq),
3028: [0x28] = SSE41_OP(pmuldq),
3029: [0x29] = SSE41_OP(pcmpeqq),
3030: [0x2a] = SSE41_SPECIAL, /* movntqda */
3031: [0x2b] = SSE41_OP(packusdw),
3032: [0x30] = SSE41_OP(pmovzxbw),
3033: [0x31] = SSE41_OP(pmovzxbd),
3034: [0x32] = SSE41_OP(pmovzxbq),
3035: [0x33] = SSE41_OP(pmovzxwd),
3036: [0x34] = SSE41_OP(pmovzxwq),
3037: [0x35] = SSE41_OP(pmovzxdq),
3038: [0x37] = SSE42_OP(pcmpgtq),
3039: [0x38] = SSE41_OP(pminsb),
3040: [0x39] = SSE41_OP(pminsd),
3041: [0x3a] = SSE41_OP(pminuw),
3042: [0x3b] = SSE41_OP(pminud),
3043: [0x3c] = SSE41_OP(pmaxsb),
3044: [0x3d] = SSE41_OP(pmaxsd),
3045: [0x3e] = SSE41_OP(pmaxuw),
3046: [0x3f] = SSE41_OP(pmaxud),
3047: [0x40] = SSE41_OP(pmulld),
3048: [0x41] = SSE41_OP(phminposuw),
3049: };
3050:
3051: static struct sse_op_helper_s sse_op_table7[256] = {
3052: [0x08] = SSE41_OP(roundps),
3053: [0x09] = SSE41_OP(roundpd),
3054: [0x0a] = SSE41_OP(roundss),
3055: [0x0b] = SSE41_OP(roundsd),
3056: [0x0c] = SSE41_OP(blendps),
3057: [0x0d] = SSE41_OP(blendpd),
3058: [0x0e] = SSE41_OP(pblendw),
3059: [0x0f] = SSSE3_OP(palignr),
3060: [0x14] = SSE41_SPECIAL, /* pextrb */
3061: [0x15] = SSE41_SPECIAL, /* pextrw */
3062: [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3063: [0x17] = SSE41_SPECIAL, /* extractps */
3064: [0x20] = SSE41_SPECIAL, /* pinsrb */
3065: [0x21] = SSE41_SPECIAL, /* insertps */
3066: [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3067: [0x40] = SSE41_OP(dpps),
3068: [0x41] = SSE41_OP(dppd),
3069: [0x42] = SSE41_OP(mpsadbw),
3070: [0x60] = SSE42_OP(pcmpestrm),
3071: [0x61] = SSE42_OP(pcmpestri),
3072: [0x62] = SSE42_OP(pcmpistrm),
3073: [0x63] = SSE42_OP(pcmpistri),
3074: };
3075:
1.1 root 3076: static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
3077: {
3078: int b1, op1_offset, op2_offset, is_xmm, val, ot;
3079: int modrm, mod, rm, reg, reg_addr, offset_addr;
1.1.1.7 root 3080: void *sse_op2;
1.1 root 3081:
3082: b &= 0xff;
1.1.1.6 root 3083: if (s->prefix & PREFIX_DATA)
1.1 root 3084: b1 = 1;
1.1.1.6 root 3085: else if (s->prefix & PREFIX_REPZ)
1.1 root 3086: b1 = 2;
1.1.1.6 root 3087: else if (s->prefix & PREFIX_REPNZ)
1.1 root 3088: b1 = 3;
3089: else
3090: b1 = 0;
3091: sse_op2 = sse_op_table1[b][b1];
1.1.1.6 root 3092: if (!sse_op2)
1.1 root 3093: goto illegal_op;
1.1.1.7 root 3094: if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
1.1 root 3095: is_xmm = 1;
3096: } else {
3097: if (b1 == 0) {
3098: /* MMX case */
3099: is_xmm = 0;
3100: } else {
3101: is_xmm = 1;
3102: }
3103: }
3104: /* simple MMX/SSE operation */
3105: if (s->flags & HF_TS_MASK) {
3106: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3107: return;
3108: }
3109: if (s->flags & HF_EM_MASK) {
3110: illegal_op:
3111: gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
3112: return;
3113: }
3114: if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
1.1.1.7 root 3115: if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
3116: goto illegal_op;
3117: if (b == 0x0e) {
3118: if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3119: goto illegal_op;
3120: /* femms */
3121: gen_helper_emms();
3122: return;
3123: }
1.1 root 3124: if (b == 0x77) {
3125: /* emms */
1.1.1.7 root 3126: gen_helper_emms();
1.1 root 3127: return;
3128: }
3129: /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3130: the static cpu state) */
3131: if (!is_xmm) {
1.1.1.7 root 3132: gen_helper_enter_mmx();
1.1 root 3133: }
3134:
3135: modrm = ldub_code(s->pc++);
3136: reg = ((modrm >> 3) & 7);
3137: if (is_xmm)
3138: reg |= rex_r;
3139: mod = (modrm >> 6) & 3;
3140: if (sse_op2 == SSE_SPECIAL) {
3141: b |= (b1 << 8);
3142: switch(b) {
3143: case 0x0e7: /* movntq */
1.1.1.6 root 3144: if (mod == 3)
1.1 root 3145: goto illegal_op;
3146: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3147: gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
1.1 root 3148: break;
3149: case 0x1e7: /* movntdq */
3150: case 0x02b: /* movntps */
3151: case 0x12b: /* movntps */
1.1.1.3 root 3152: if (mod == 3)
1.1 root 3153: goto illegal_op;
3154: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3155: gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1 root 3156: break;
1.1.1.11 root 3157: case 0x3f0: /* lddqu */
3158: if (mod == 3)
3159: goto illegal_op;
3160: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3161: gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
3162: break;
1.1.1.9 root 3163: case 0x22b: /* movntss */
3164: case 0x32b: /* movntsd */
3165: if (mod == 3)
3166: goto illegal_op;
3167: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3168: if (b1 & 1) {
3169: gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,
3170: xmm_regs[reg]));
3171: } else {
3172: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3173: xmm_regs[reg].XMM_L(0)));
3174: gen_op_st_T0_A0(OT_LONG + s->mem_index);
3175: }
3176: break;
1.1 root 3177: case 0x6e: /* movd mm, ea */
1.1.1.5 root 3178: #ifdef TARGET_X86_64
3179: if (s->dflag == 2) {
3180: gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
1.1.1.7 root 3181: tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
1.1.1.6 root 3182: } else
1.1.1.5 root 3183: #endif
3184: {
3185: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
1.1.1.7 root 3186: tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3187: offsetof(CPUX86State,fpregs[reg].mmx));
3188: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3189: gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
1.1.1.5 root 3190: }
1.1 root 3191: break;
3192: case 0x16e: /* movd xmm, ea */
1.1.1.5 root 3193: #ifdef TARGET_X86_64
3194: if (s->dflag == 2) {
3195: gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
1.1.1.7 root 3196: tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3197: offsetof(CPUX86State,xmm_regs[reg]));
3198: gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
1.1.1.6 root 3199: } else
1.1.1.5 root 3200: #endif
3201: {
3202: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
1.1.1.7 root 3203: tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3204: offsetof(CPUX86State,xmm_regs[reg]));
3205: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3206: gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
1.1.1.5 root 3207: }
1.1 root 3208: break;
3209: case 0x6f: /* movq mm, ea */
3210: if (mod != 3) {
3211: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3212: gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
1.1 root 3213: } else {
3214: rm = (modrm & 7);
1.1.1.7 root 3215: tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3216: offsetof(CPUX86State,fpregs[rm].mmx));
3217: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3218: offsetof(CPUX86State,fpregs[reg].mmx));
1.1 root 3219: }
3220: break;
3221: case 0x010: /* movups */
3222: case 0x110: /* movupd */
3223: case 0x028: /* movaps */
3224: case 0x128: /* movapd */
3225: case 0x16f: /* movdqa xmm, ea */
3226: case 0x26f: /* movdqu xmm, ea */
3227: if (mod != 3) {
3228: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3229: gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1 root 3230: } else {
3231: rm = (modrm & 7) | REX_B(s);
3232: gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3233: offsetof(CPUX86State,xmm_regs[rm]));
3234: }
3235: break;
3236: case 0x210: /* movss xmm, ea */
3237: if (mod != 3) {
3238: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3239: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3240: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
1.1 root 3241: gen_op_movl_T0_0();
1.1.1.7 root 3242: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3243: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3244: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
1.1 root 3245: } else {
3246: rm = (modrm & 7) | REX_B(s);
3247: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3248: offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3249: }
3250: break;
3251: case 0x310: /* movsd xmm, ea */
3252: if (mod != 3) {
3253: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3254: gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1 root 3255: gen_op_movl_T0_0();
1.1.1.7 root 3256: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3257: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
1.1 root 3258: } else {
3259: rm = (modrm & 7) | REX_B(s);
3260: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3261: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3262: }
3263: break;
3264: case 0x012: /* movlps */
3265: case 0x112: /* movlpd */
3266: if (mod != 3) {
3267: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3268: gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1 root 3269: } else {
3270: /* movhlps */
3271: rm = (modrm & 7) | REX_B(s);
3272: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3273: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3274: }
3275: break;
1.1.1.3 root 3276: case 0x212: /* movsldup */
3277: if (mod != 3) {
3278: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3279: gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1.1.3 root 3280: } else {
3281: rm = (modrm & 7) | REX_B(s);
3282: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3283: offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3284: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3285: offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3286: }
3287: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3288: offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3289: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3290: offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3291: break;
3292: case 0x312: /* movddup */
3293: if (mod != 3) {
3294: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3295: gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1.1.3 root 3296: } else {
3297: rm = (modrm & 7) | REX_B(s);
3298: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3299: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3300: }
3301: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3302: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3303: break;
1.1 root 3304: case 0x016: /* movhps */
3305: case 0x116: /* movhpd */
3306: if (mod != 3) {
3307: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3308: gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
1.1 root 3309: } else {
3310: /* movlhps */
3311: rm = (modrm & 7) | REX_B(s);
3312: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3313: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3314: }
3315: break;
3316: case 0x216: /* movshdup */
3317: if (mod != 3) {
3318: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3319: gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1 root 3320: } else {
3321: rm = (modrm & 7) | REX_B(s);
3322: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3323: offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3324: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3325: offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3326: }
3327: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3328: offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3329: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3330: offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3331: break;
1.1.1.9 root 3332: case 0x178:
3333: case 0x378:
3334: {
3335: int bit_index, field_length;
3336:
3337: if (b1 == 1 && reg != 0)
3338: goto illegal_op;
3339: field_length = ldub_code(s->pc++) & 0x3F;
3340: bit_index = ldub_code(s->pc++) & 0x3F;
3341: tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3342: offsetof(CPUX86State,xmm_regs[reg]));
3343: if (b1 == 1)
3344: gen_helper_extrq_i(cpu_ptr0, tcg_const_i32(bit_index),
3345: tcg_const_i32(field_length));
3346: else
3347: gen_helper_insertq_i(cpu_ptr0, tcg_const_i32(bit_index),
3348: tcg_const_i32(field_length));
3349: }
3350: break;
1.1 root 3351: case 0x7e: /* movd ea, mm */
1.1.1.5 root 3352: #ifdef TARGET_X86_64
3353: if (s->dflag == 2) {
1.1.1.7 root 3354: tcg_gen_ld_i64(cpu_T[0], cpu_env,
3355: offsetof(CPUX86State,fpregs[reg].mmx));
1.1.1.5 root 3356: gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
1.1.1.6 root 3357: } else
1.1.1.5 root 3358: #endif
3359: {
1.1.1.7 root 3360: tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3361: offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
1.1.1.5 root 3362: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
3363: }
1.1 root 3364: break;
3365: case 0x17e: /* movd ea, xmm */
1.1.1.5 root 3366: #ifdef TARGET_X86_64
3367: if (s->dflag == 2) {
1.1.1.7 root 3368: tcg_gen_ld_i64(cpu_T[0], cpu_env,
3369: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1.1.5 root 3370: gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
1.1.1.6 root 3371: } else
1.1.1.5 root 3372: #endif
3373: {
1.1.1.7 root 3374: tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3375: offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
1.1.1.5 root 3376: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
3377: }
1.1 root 3378: break;
3379: case 0x27e: /* movq xmm, ea */
3380: if (mod != 3) {
3381: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3382: gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1 root 3383: } else {
3384: rm = (modrm & 7) | REX_B(s);
3385: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3386: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3387: }
3388: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3389: break;
3390: case 0x7f: /* movq ea, mm */
3391: if (mod != 3) {
3392: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3393: gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
1.1 root 3394: } else {
3395: rm = (modrm & 7);
3396: gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3397: offsetof(CPUX86State,fpregs[reg].mmx));
3398: }
3399: break;
3400: case 0x011: /* movups */
3401: case 0x111: /* movupd */
3402: case 0x029: /* movaps */
3403: case 0x129: /* movapd */
3404: case 0x17f: /* movdqa ea, xmm */
3405: case 0x27f: /* movdqu ea, xmm */
3406: if (mod != 3) {
3407: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3408: gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
1.1 root 3409: } else {
3410: rm = (modrm & 7) | REX_B(s);
3411: gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3412: offsetof(CPUX86State,xmm_regs[reg]));
3413: }
3414: break;
3415: case 0x211: /* movss ea, xmm */
3416: if (mod != 3) {
3417: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3418: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3419: gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1 root 3420: } else {
3421: rm = (modrm & 7) | REX_B(s);
3422: gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3423: offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3424: }
3425: break;
3426: case 0x311: /* movsd ea, xmm */
3427: if (mod != 3) {
3428: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3429: gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1 root 3430: } else {
3431: rm = (modrm & 7) | REX_B(s);
3432: gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3433: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3434: }
3435: break;
3436: case 0x013: /* movlps */
3437: case 0x113: /* movlpd */
3438: if (mod != 3) {
3439: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3440: gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1 root 3441: } else {
3442: goto illegal_op;
3443: }
3444: break;
3445: case 0x017: /* movhps */
3446: case 0x117: /* movhpd */
3447: if (mod != 3) {
3448: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3449: gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
1.1 root 3450: } else {
3451: goto illegal_op;
3452: }
3453: break;
3454: case 0x71: /* shift mm, im */
3455: case 0x72:
3456: case 0x73:
3457: case 0x171: /* shift xmm, im */
3458: case 0x172:
3459: case 0x173:
1.1.1.13 root 3460: if (b1 >= 2) {
3461: goto illegal_op;
3462: }
1.1 root 3463: val = ldub_code(s->pc++);
3464: if (is_xmm) {
3465: gen_op_movl_T0_im(val);
1.1.1.7 root 3466: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
1.1 root 3467: gen_op_movl_T0_0();
1.1.1.7 root 3468: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
1.1 root 3469: op1_offset = offsetof(CPUX86State,xmm_t0);
3470: } else {
3471: gen_op_movl_T0_im(val);
1.1.1.7 root 3472: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
1.1 root 3473: gen_op_movl_T0_0();
1.1.1.7 root 3474: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
1.1 root 3475: op1_offset = offsetof(CPUX86State,mmx_t0);
3476: }
3477: sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
3478: if (!sse_op2)
3479: goto illegal_op;
3480: if (is_xmm) {
3481: rm = (modrm & 7) | REX_B(s);
3482: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3483: } else {
3484: rm = (modrm & 7);
3485: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3486: }
1.1.1.7 root 3487: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3488: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
3489: ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
1.1 root 3490: break;
3491: case 0x050: /* movmskps */
3492: rm = (modrm & 7) | REX_B(s);
1.1.1.7 root 3493: tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3494: offsetof(CPUX86State,xmm_regs[rm]));
3495: gen_helper_movmskps(cpu_tmp2_i32, cpu_ptr0);
3496: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3497: gen_op_mov_reg_T0(OT_LONG, reg);
1.1 root 3498: break;
3499: case 0x150: /* movmskpd */
3500: rm = (modrm & 7) | REX_B(s);
1.1.1.7 root 3501: tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3502: offsetof(CPUX86State,xmm_regs[rm]));
3503: gen_helper_movmskpd(cpu_tmp2_i32, cpu_ptr0);
3504: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3505: gen_op_mov_reg_T0(OT_LONG, reg);
1.1 root 3506: break;
3507: case 0x02a: /* cvtpi2ps */
3508: case 0x12a: /* cvtpi2pd */
1.1.1.7 root 3509: gen_helper_enter_mmx();
1.1 root 3510: if (mod != 3) {
3511: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3512: op2_offset = offsetof(CPUX86State,mmx_t0);
1.1.1.7 root 3513: gen_ldq_env_A0(s->mem_index, op2_offset);
1.1 root 3514: } else {
3515: rm = (modrm & 7);
3516: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3517: }
3518: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
1.1.1.7 root 3519: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3520: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
1.1 root 3521: switch(b >> 8) {
3522: case 0x0:
1.1.1.7 root 3523: gen_helper_cvtpi2ps(cpu_ptr0, cpu_ptr1);
1.1 root 3524: break;
3525: default:
3526: case 0x1:
1.1.1.7 root 3527: gen_helper_cvtpi2pd(cpu_ptr0, cpu_ptr1);
1.1 root 3528: break;
3529: }
3530: break;
3531: case 0x22a: /* cvtsi2ss */
3532: case 0x32a: /* cvtsi2sd */
3533: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3534: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3535: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
1.1.1.7 root 3536: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3537: sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)];
3538: if (ot == OT_LONG) {
3539: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3540: ((void (*)(TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_tmp2_i32);
3541: } else {
3542: ((void (*)(TCGv_ptr, TCGv))sse_op2)(cpu_ptr0, cpu_T[0]);
3543: }
1.1 root 3544: break;
3545: case 0x02c: /* cvttps2pi */
3546: case 0x12c: /* cvttpd2pi */
3547: case 0x02d: /* cvtps2pi */
3548: case 0x12d: /* cvtpd2pi */
1.1.1.7 root 3549: gen_helper_enter_mmx();
1.1 root 3550: if (mod != 3) {
3551: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3552: op2_offset = offsetof(CPUX86State,xmm_t0);
1.1.1.7 root 3553: gen_ldo_env_A0(s->mem_index, op2_offset);
1.1 root 3554: } else {
3555: rm = (modrm & 7) | REX_B(s);
3556: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3557: }
3558: op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
1.1.1.7 root 3559: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3560: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
1.1 root 3561: switch(b) {
3562: case 0x02c:
1.1.1.7 root 3563: gen_helper_cvttps2pi(cpu_ptr0, cpu_ptr1);
1.1 root 3564: break;
3565: case 0x12c:
1.1.1.7 root 3566: gen_helper_cvttpd2pi(cpu_ptr0, cpu_ptr1);
1.1 root 3567: break;
3568: case 0x02d:
1.1.1.7 root 3569: gen_helper_cvtps2pi(cpu_ptr0, cpu_ptr1);
1.1 root 3570: break;
3571: case 0x12d:
1.1.1.7 root 3572: gen_helper_cvtpd2pi(cpu_ptr0, cpu_ptr1);
1.1 root 3573: break;
3574: }
3575: break;
3576: case 0x22c: /* cvttss2si */
3577: case 0x32c: /* cvttsd2si */
3578: case 0x22d: /* cvtss2si */
3579: case 0x32d: /* cvtsd2si */
3580: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3581: if (mod != 3) {
3582: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3583: if ((b >> 8) & 1) {
1.1.1.7 root 3584: gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
1.1 root 3585: } else {
1.1.1.7 root 3586: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3587: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
1.1 root 3588: }
3589: op2_offset = offsetof(CPUX86State,xmm_t0);
3590: } else {
3591: rm = (modrm & 7) | REX_B(s);
3592: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3593: }
1.1.1.7 root 3594: sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
3595: (b & 1) * 4];
3596: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3597: if (ot == OT_LONG) {
3598: ((void (*)(TCGv_i32, TCGv_ptr))sse_op2)(cpu_tmp2_i32, cpu_ptr0);
3599: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3600: } else {
3601: ((void (*)(TCGv, TCGv_ptr))sse_op2)(cpu_T[0], cpu_ptr0);
3602: }
3603: gen_op_mov_reg_T0(ot, reg);
1.1 root 3604: break;
3605: case 0xc4: /* pinsrw */
1.1.1.6 root 3606: case 0x1c4:
1.1.1.4 root 3607: s->rip_offset = 1;
1.1 root 3608: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3609: val = ldub_code(s->pc++);
3610: if (b1) {
3611: val &= 7;
1.1.1.7 root 3612: tcg_gen_st16_tl(cpu_T[0], cpu_env,
3613: offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
1.1 root 3614: } else {
3615: val &= 3;
1.1.1.7 root 3616: tcg_gen_st16_tl(cpu_T[0], cpu_env,
3617: offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
1.1 root 3618: }
3619: break;
3620: case 0xc5: /* pextrw */
1.1.1.6 root 3621: case 0x1c5:
1.1 root 3622: if (mod != 3)
3623: goto illegal_op;
1.1.1.7 root 3624: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
1.1 root 3625: val = ldub_code(s->pc++);
3626: if (b1) {
3627: val &= 7;
3628: rm = (modrm & 7) | REX_B(s);
1.1.1.7 root 3629: tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3630: offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
1.1 root 3631: } else {
3632: val &= 3;
3633: rm = (modrm & 7);
1.1.1.7 root 3634: tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3635: offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
1.1 root 3636: }
3637: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.7 root 3638: gen_op_mov_reg_T0(ot, reg);
1.1 root 3639: break;
3640: case 0x1d6: /* movq ea, xmm */
3641: if (mod != 3) {
3642: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 3643: gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
1.1 root 3644: } else {
3645: rm = (modrm & 7) | REX_B(s);
3646: gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3647: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3648: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3649: }
3650: break;
3651: case 0x2d6: /* movq2dq */
1.1.1.7 root 3652: gen_helper_enter_mmx();
1.1.1.4 root 3653: rm = (modrm & 7);
3654: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3655: offsetof(CPUX86State,fpregs[rm].mmx));
3656: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
1.1 root 3657: break;
3658: case 0x3d6: /* movdq2q */
1.1.1.7 root 3659: gen_helper_enter_mmx();
1.1.1.4 root 3660: rm = (modrm & 7) | REX_B(s);
3661: gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3662: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
1.1 root 3663: break;
3664: case 0xd7: /* pmovmskb */
3665: case 0x1d7:
3666: if (mod != 3)
3667: goto illegal_op;
3668: if (b1) {
3669: rm = (modrm & 7) | REX_B(s);
1.1.1.7 root 3670: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
3671: gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_ptr0);
1.1 root 3672: } else {
3673: rm = (modrm & 7);
1.1.1.7 root 3674: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
3675: gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_ptr0);
3676: }
3677: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3678: reg = ((modrm >> 3) & 7) | rex_r;
3679: gen_op_mov_reg_T0(OT_LONG, reg);
3680: break;
3681: case 0x138:
3682: if (s->prefix & PREFIX_REPNZ)
3683: goto crc32;
3684: case 0x038:
3685: b = modrm;
3686: modrm = ldub_code(s->pc++);
3687: rm = modrm & 7;
3688: reg = ((modrm >> 3) & 7) | rex_r;
3689: mod = (modrm >> 6) & 3;
1.1.1.13 root 3690: if (b1 >= 2) {
3691: goto illegal_op;
3692: }
1.1.1.7 root 3693:
3694: sse_op2 = sse_op_table6[b].op[b1];
3695: if (!sse_op2)
3696: goto illegal_op;
3697: if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3698: goto illegal_op;
3699:
3700: if (b1) {
3701: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3702: if (mod == 3) {
3703: op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3704: } else {
3705: op2_offset = offsetof(CPUX86State,xmm_t0);
3706: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3707: switch (b) {
3708: case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3709: case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3710: case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
3711: gen_ldq_env_A0(s->mem_index, op2_offset +
3712: offsetof(XMMReg, XMM_Q(0)));
3713: break;
3714: case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3715: case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3716: tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
3717: (s->mem_index >> 2) - 1);
3718: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
3719: tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3720: offsetof(XMMReg, XMM_L(0)));
3721: break;
3722: case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3723: tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0,
3724: (s->mem_index >> 2) - 1);
3725: tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3726: offsetof(XMMReg, XMM_W(0)));
3727: break;
3728: case 0x2a: /* movntqda */
3729: gen_ldo_env_A0(s->mem_index, op1_offset);
3730: return;
3731: default:
3732: gen_ldo_env_A0(s->mem_index, op2_offset);
3733: }
3734: }
3735: } else {
3736: op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3737: if (mod == 3) {
3738: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3739: } else {
3740: op2_offset = offsetof(CPUX86State,mmx_t0);
3741: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3742: gen_ldq_env_A0(s->mem_index, op2_offset);
3743: }
1.1 root 3744: }
1.1.1.7 root 3745: if (sse_op2 == SSE_SPECIAL)
3746: goto illegal_op;
3747:
3748: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3749: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3750: ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
3751:
3752: if (b == 0x17)
3753: s->cc_op = CC_OP_EFLAGS;
3754: break;
3755: case 0x338: /* crc32 */
3756: crc32:
3757: b = modrm;
3758: modrm = ldub_code(s->pc++);
3759: reg = ((modrm >> 3) & 7) | rex_r;
3760:
3761: if (b != 0xf0 && b != 0xf1)
3762: goto illegal_op;
3763: if (!(s->cpuid_ext_features & CPUID_EXT_SSE42))
3764: goto illegal_op;
3765:
3766: if (b == 0xf0)
3767: ot = OT_BYTE;
3768: else if (b == 0xf1 && s->dflag != 2)
3769: if (s->prefix & PREFIX_DATA)
3770: ot = OT_WORD;
3771: else
3772: ot = OT_LONG;
3773: else
3774: ot = OT_QUAD;
3775:
3776: gen_op_mov_TN_reg(OT_LONG, 0, reg);
3777: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3778: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3779: gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
3780: cpu_T[0], tcg_const_i32(8 << ot));
3781:
3782: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3783: gen_op_mov_reg_T0(ot, reg);
3784: break;
3785: case 0x03a:
3786: case 0x13a:
3787: b = modrm;
3788: modrm = ldub_code(s->pc++);
3789: rm = modrm & 7;
1.1 root 3790: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.7 root 3791: mod = (modrm >> 6) & 3;
1.1.1.13 root 3792: if (b1 >= 2) {
3793: goto illegal_op;
3794: }
1.1.1.7 root 3795:
3796: sse_op2 = sse_op_table7[b].op[b1];
3797: if (!sse_op2)
3798: goto illegal_op;
3799: if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
3800: goto illegal_op;
3801:
3802: if (sse_op2 == SSE_SPECIAL) {
3803: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3804: rm = (modrm & 7) | REX_B(s);
3805: if (mod != 3)
3806: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3807: reg = ((modrm >> 3) & 7) | rex_r;
3808: val = ldub_code(s->pc++);
3809: switch (b) {
3810: case 0x14: /* pextrb */
3811: tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3812: xmm_regs[reg].XMM_B(val & 15)));
3813: if (mod == 3)
3814: gen_op_mov_reg_T0(ot, rm);
3815: else
3816: tcg_gen_qemu_st8(cpu_T[0], cpu_A0,
3817: (s->mem_index >> 2) - 1);
3818: break;
3819: case 0x15: /* pextrw */
3820: tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3821: xmm_regs[reg].XMM_W(val & 7)));
3822: if (mod == 3)
3823: gen_op_mov_reg_T0(ot, rm);
3824: else
3825: tcg_gen_qemu_st16(cpu_T[0], cpu_A0,
3826: (s->mem_index >> 2) - 1);
3827: break;
3828: case 0x16:
3829: if (ot == OT_LONG) { /* pextrd */
3830: tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
3831: offsetof(CPUX86State,
3832: xmm_regs[reg].XMM_L(val & 3)));
3833: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
3834: if (mod == 3)
3835: gen_op_mov_reg_v(ot, rm, cpu_T[0]);
3836: else
3837: tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
3838: (s->mem_index >> 2) - 1);
3839: } else { /* pextrq */
3840: #ifdef TARGET_X86_64
3841: tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
3842: offsetof(CPUX86State,
3843: xmm_regs[reg].XMM_Q(val & 1)));
3844: if (mod == 3)
3845: gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
3846: else
3847: tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
3848: (s->mem_index >> 2) - 1);
3849: #else
3850: goto illegal_op;
3851: #endif
3852: }
3853: break;
3854: case 0x17: /* extractps */
3855: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3856: xmm_regs[reg].XMM_L(val & 3)));
3857: if (mod == 3)
3858: gen_op_mov_reg_T0(ot, rm);
3859: else
3860: tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
3861: (s->mem_index >> 2) - 1);
3862: break;
3863: case 0x20: /* pinsrb */
3864: if (mod == 3)
3865: gen_op_mov_TN_reg(OT_LONG, 0, rm);
3866: else
3867: tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0,
3868: (s->mem_index >> 2) - 1);
3869: tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State,
3870: xmm_regs[reg].XMM_B(val & 15)));
3871: break;
3872: case 0x21: /* insertps */
3873: if (mod == 3) {
3874: tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
3875: offsetof(CPUX86State,xmm_regs[rm]
3876: .XMM_L((val >> 6) & 3)));
3877: } else {
3878: tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
3879: (s->mem_index >> 2) - 1);
3880: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
3881: }
3882: tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
3883: offsetof(CPUX86State,xmm_regs[reg]
3884: .XMM_L((val >> 4) & 3)));
3885: if ((val >> 0) & 1)
3886: tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
3887: cpu_env, offsetof(CPUX86State,
3888: xmm_regs[reg].XMM_L(0)));
3889: if ((val >> 1) & 1)
3890: tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
3891: cpu_env, offsetof(CPUX86State,
3892: xmm_regs[reg].XMM_L(1)));
3893: if ((val >> 2) & 1)
3894: tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
3895: cpu_env, offsetof(CPUX86State,
3896: xmm_regs[reg].XMM_L(2)));
3897: if ((val >> 3) & 1)
3898: tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
3899: cpu_env, offsetof(CPUX86State,
3900: xmm_regs[reg].XMM_L(3)));
3901: break;
3902: case 0x22:
3903: if (ot == OT_LONG) { /* pinsrd */
3904: if (mod == 3)
3905: gen_op_mov_v_reg(ot, cpu_tmp0, rm);
3906: else
3907: tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
3908: (s->mem_index >> 2) - 1);
3909: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
3910: tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
3911: offsetof(CPUX86State,
3912: xmm_regs[reg].XMM_L(val & 3)));
3913: } else { /* pinsrq */
3914: #ifdef TARGET_X86_64
3915: if (mod == 3)
3916: gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
3917: else
3918: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
3919: (s->mem_index >> 2) - 1);
3920: tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
3921: offsetof(CPUX86State,
3922: xmm_regs[reg].XMM_Q(val & 1)));
3923: #else
3924: goto illegal_op;
3925: #endif
3926: }
3927: break;
3928: }
3929: return;
3930: }
3931:
3932: if (b1) {
3933: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3934: if (mod == 3) {
3935: op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3936: } else {
3937: op2_offset = offsetof(CPUX86State,xmm_t0);
3938: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3939: gen_ldo_env_A0(s->mem_index, op2_offset);
3940: }
3941: } else {
3942: op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3943: if (mod == 3) {
3944: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3945: } else {
3946: op2_offset = offsetof(CPUX86State,mmx_t0);
3947: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3948: gen_ldq_env_A0(s->mem_index, op2_offset);
3949: }
3950: }
3951: val = ldub_code(s->pc++);
3952:
3953: if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
3954: s->cc_op = CC_OP_EFLAGS;
3955:
3956: if (s->dflag == 2)
3957: /* The helper must use entire 64-bit gp registers */
3958: val |= 1 << 8;
3959: }
3960:
3961: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3962: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
3963: ((void (*)(TCGv_ptr, TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
1.1 root 3964: break;
3965: default:
3966: goto illegal_op;
3967: }
3968: } else {
3969: /* generic MMX or SSE operation */
1.1.1.4 root 3970: switch(b) {
3971: case 0x70: /* pshufx insn */
3972: case 0xc6: /* pshufx insn */
3973: case 0xc2: /* compare insns */
3974: s->rip_offset = 1;
3975: break;
3976: default:
3977: break;
1.1 root 3978: }
3979: if (is_xmm) {
3980: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3981: if (mod != 3) {
3982: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3983: op2_offset = offsetof(CPUX86State,xmm_t0);
1.1.1.4 root 3984: if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
1.1 root 3985: b == 0xc2)) {
3986: /* specific case for SSE single instructions */
3987: if (b1 == 2) {
3988: /* 32 bit access */
1.1.1.7 root 3989: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
3990: tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
1.1 root 3991: } else {
3992: /* 64 bit access */
1.1.1.7 root 3993: gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
1.1 root 3994: }
3995: } else {
1.1.1.7 root 3996: gen_ldo_env_A0(s->mem_index, op2_offset);
1.1 root 3997: }
3998: } else {
3999: rm = (modrm & 7) | REX_B(s);
4000: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4001: }
4002: } else {
4003: op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4004: if (mod != 3) {
4005: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4006: op2_offset = offsetof(CPUX86State,mmx_t0);
1.1.1.7 root 4007: gen_ldq_env_A0(s->mem_index, op2_offset);
1.1 root 4008: } else {
4009: rm = (modrm & 7);
4010: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4011: }
4012: }
4013: switch(b) {
1.1.1.7 root 4014: case 0x0f: /* 3DNow! data insns */
4015: if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4016: goto illegal_op;
4017: val = ldub_code(s->pc++);
4018: sse_op2 = sse_op_table5[val];
4019: if (!sse_op2)
4020: goto illegal_op;
4021: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4022: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4023: ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
4024: break;
1.1 root 4025: case 0x70: /* pshufx insn */
4026: case 0xc6: /* pshufx insn */
4027: val = ldub_code(s->pc++);
1.1.1.7 root 4028: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4029: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4030: ((void (*)(TCGv_ptr, TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
1.1 root 4031: break;
4032: case 0xc2:
4033: /* compare insns */
4034: val = ldub_code(s->pc++);
4035: if (val >= 8)
4036: goto illegal_op;
4037: sse_op2 = sse_op_table4[val][b1];
1.1.1.7 root 4038: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4039: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4040: ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
4041: break;
4042: case 0xf7:
4043: /* maskmov : we must prepare A0 */
4044: if (mod != 3)
4045: goto illegal_op;
4046: #ifdef TARGET_X86_64
4047: if (s->aflag == 2) {
4048: gen_op_movq_A0_reg(R_EDI);
4049: } else
4050: #endif
4051: {
4052: gen_op_movl_A0_reg(R_EDI);
4053: if (s->aflag == 0)
4054: gen_op_andl_A0_ffff();
4055: }
4056: gen_add_A0_ds_seg(s);
4057:
4058: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4059: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4060: ((void (*)(TCGv_ptr, TCGv_ptr, TCGv))sse_op2)(cpu_ptr0, cpu_ptr1, cpu_A0);
1.1 root 4061: break;
4062: default:
1.1.1.7 root 4063: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4064: tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
4065: ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1);
1.1 root 4066: break;
4067: }
4068: if (b == 0x2e || b == 0x2f) {
4069: s->cc_op = CC_OP_EFLAGS;
4070: }
4071: }
4072: }
4073:
4074: /* convert one instruction. s->is_jmp is set if the translation must
4075: be stopped. Return the next pc value */
4076: static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
4077: {
4078: int b, prefixes, aflag, dflag;
4079: int shift, ot;
4080: int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
4081: target_ulong next_eip, tval;
4082: int rex_w, rex_r;
4083:
1.1.1.7 root 4084: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
4085: tcg_gen_debug_insn_start(pc_start);
1.1 root 4086: s->pc = pc_start;
4087: prefixes = 0;
4088: aflag = s->code32;
4089: dflag = s->code32;
4090: s->override = -1;
4091: rex_w = -1;
4092: rex_r = 0;
4093: #ifdef TARGET_X86_64
4094: s->rex_x = 0;
4095: s->rex_b = 0;
1.1.1.6 root 4096: x86_64_hregs = 0;
1.1 root 4097: #endif
4098: s->rip_offset = 0; /* for relative ip address */
4099: next_byte:
4100: b = ldub_code(s->pc);
4101: s->pc++;
4102: /* check prefixes */
4103: #ifdef TARGET_X86_64
4104: if (CODE64(s)) {
4105: switch (b) {
4106: case 0xf3:
4107: prefixes |= PREFIX_REPZ;
4108: goto next_byte;
4109: case 0xf2:
4110: prefixes |= PREFIX_REPNZ;
4111: goto next_byte;
4112: case 0xf0:
4113: prefixes |= PREFIX_LOCK;
4114: goto next_byte;
4115: case 0x2e:
4116: s->override = R_CS;
4117: goto next_byte;
4118: case 0x36:
4119: s->override = R_SS;
4120: goto next_byte;
4121: case 0x3e:
4122: s->override = R_DS;
4123: goto next_byte;
4124: case 0x26:
4125: s->override = R_ES;
4126: goto next_byte;
4127: case 0x64:
4128: s->override = R_FS;
4129: goto next_byte;
4130: case 0x65:
4131: s->override = R_GS;
4132: goto next_byte;
4133: case 0x66:
4134: prefixes |= PREFIX_DATA;
4135: goto next_byte;
4136: case 0x67:
4137: prefixes |= PREFIX_ADR;
4138: goto next_byte;
4139: case 0x40 ... 0x4f:
4140: /* REX prefix */
4141: rex_w = (b >> 3) & 1;
4142: rex_r = (b & 0x4) << 1;
4143: s->rex_x = (b & 0x2) << 2;
4144: REX_B(s) = (b & 0x1) << 3;
4145: x86_64_hregs = 1; /* select uniform byte register addressing */
4146: goto next_byte;
4147: }
4148: if (rex_w == 1) {
4149: /* 0x66 is ignored if rex.w is set */
4150: dflag = 2;
4151: } else {
4152: if (prefixes & PREFIX_DATA)
4153: dflag ^= 1;
4154: }
4155: if (!(prefixes & PREFIX_ADR))
4156: aflag = 2;
1.1.1.6 root 4157: } else
1.1 root 4158: #endif
4159: {
4160: switch (b) {
4161: case 0xf3:
4162: prefixes |= PREFIX_REPZ;
4163: goto next_byte;
4164: case 0xf2:
4165: prefixes |= PREFIX_REPNZ;
4166: goto next_byte;
4167: case 0xf0:
4168: prefixes |= PREFIX_LOCK;
4169: goto next_byte;
4170: case 0x2e:
4171: s->override = R_CS;
4172: goto next_byte;
4173: case 0x36:
4174: s->override = R_SS;
4175: goto next_byte;
4176: case 0x3e:
4177: s->override = R_DS;
4178: goto next_byte;
4179: case 0x26:
4180: s->override = R_ES;
4181: goto next_byte;
4182: case 0x64:
4183: s->override = R_FS;
4184: goto next_byte;
4185: case 0x65:
4186: s->override = R_GS;
4187: goto next_byte;
4188: case 0x66:
4189: prefixes |= PREFIX_DATA;
4190: goto next_byte;
4191: case 0x67:
4192: prefixes |= PREFIX_ADR;
4193: goto next_byte;
4194: }
4195: if (prefixes & PREFIX_DATA)
4196: dflag ^= 1;
4197: if (prefixes & PREFIX_ADR)
4198: aflag ^= 1;
4199: }
4200:
4201: s->prefix = prefixes;
4202: s->aflag = aflag;
4203: s->dflag = dflag;
4204:
4205: /* lock generation */
4206: if (prefixes & PREFIX_LOCK)
1.1.1.7 root 4207: gen_helper_lock();
1.1 root 4208:
4209: /* now check op code */
4210: reswitch:
4211: switch(b) {
4212: case 0x0f:
4213: /**************************/
4214: /* extended op code */
4215: b = ldub_code(s->pc++) | 0x100;
4216: goto reswitch;
1.1.1.6 root 4217:
1.1 root 4218: /**************************/
4219: /* arith & logic */
4220: case 0x00 ... 0x05:
4221: case 0x08 ... 0x0d:
4222: case 0x10 ... 0x15:
4223: case 0x18 ... 0x1d:
4224: case 0x20 ... 0x25:
4225: case 0x28 ... 0x2d:
4226: case 0x30 ... 0x35:
4227: case 0x38 ... 0x3d:
4228: {
4229: int op, f, val;
4230: op = (b >> 3) & 7;
4231: f = (b >> 1) & 3;
4232:
4233: if ((b & 1) == 0)
4234: ot = OT_BYTE;
4235: else
4236: ot = dflag + OT_WORD;
1.1.1.6 root 4237:
1.1 root 4238: switch(f) {
4239: case 0: /* OP Ev, Gv */
4240: modrm = ldub_code(s->pc++);
4241: reg = ((modrm >> 3) & 7) | rex_r;
4242: mod = (modrm >> 6) & 3;
4243: rm = (modrm & 7) | REX_B(s);
4244: if (mod != 3) {
4245: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4246: opreg = OR_TMP0;
4247: } else if (op == OP_XORL && rm == reg) {
4248: xor_zero:
4249: /* xor reg, reg optimisation */
4250: gen_op_movl_T0_0();
4251: s->cc_op = CC_OP_LOGICB + ot;
1.1.1.7 root 4252: gen_op_mov_reg_T0(ot, reg);
1.1 root 4253: gen_op_update1_cc();
4254: break;
4255: } else {
4256: opreg = rm;
4257: }
1.1.1.7 root 4258: gen_op_mov_TN_reg(ot, 1, reg);
1.1 root 4259: gen_op(s, op, ot, opreg);
4260: break;
4261: case 1: /* OP Gv, Ev */
4262: modrm = ldub_code(s->pc++);
4263: mod = (modrm >> 6) & 3;
4264: reg = ((modrm >> 3) & 7) | rex_r;
4265: rm = (modrm & 7) | REX_B(s);
4266: if (mod != 3) {
4267: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 4268: gen_op_ld_T1_A0(ot + s->mem_index);
1.1 root 4269: } else if (op == OP_XORL && rm == reg) {
4270: goto xor_zero;
4271: } else {
1.1.1.7 root 4272: gen_op_mov_TN_reg(ot, 1, rm);
1.1 root 4273: }
4274: gen_op(s, op, ot, reg);
4275: break;
4276: case 2: /* OP A, Iv */
4277: val = insn_get(s, ot);
4278: gen_op_movl_T1_im(val);
4279: gen_op(s, op, ot, OR_EAX);
4280: break;
4281: }
4282: }
4283: break;
4284:
1.1.1.7 root 4285: case 0x82:
4286: if (CODE64(s))
4287: goto illegal_op;
1.1 root 4288: case 0x80: /* GRP1 */
4289: case 0x81:
4290: case 0x83:
4291: {
4292: int val;
4293:
4294: if ((b & 1) == 0)
4295: ot = OT_BYTE;
4296: else
4297: ot = dflag + OT_WORD;
1.1.1.6 root 4298:
1.1 root 4299: modrm = ldub_code(s->pc++);
4300: mod = (modrm >> 6) & 3;
4301: rm = (modrm & 7) | REX_B(s);
4302: op = (modrm >> 3) & 7;
1.1.1.6 root 4303:
1.1 root 4304: if (mod != 3) {
4305: if (b == 0x83)
4306: s->rip_offset = 1;
4307: else
4308: s->rip_offset = insn_const_size(ot);
4309: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4310: opreg = OR_TMP0;
4311: } else {
4312: opreg = rm;
4313: }
4314:
4315: switch(b) {
4316: default:
4317: case 0x80:
4318: case 0x81:
4319: case 0x82:
4320: val = insn_get(s, ot);
4321: break;
4322: case 0x83:
4323: val = (int8_t)insn_get(s, OT_BYTE);
4324: break;
4325: }
4326: gen_op_movl_T1_im(val);
4327: gen_op(s, op, ot, opreg);
4328: }
4329: break;
4330:
4331: /**************************/
4332: /* inc, dec, and other misc arith */
4333: case 0x40 ... 0x47: /* inc Gv */
4334: ot = dflag ? OT_LONG : OT_WORD;
4335: gen_inc(s, ot, OR_EAX + (b & 7), 1);
4336: break;
4337: case 0x48 ... 0x4f: /* dec Gv */
4338: ot = dflag ? OT_LONG : OT_WORD;
4339: gen_inc(s, ot, OR_EAX + (b & 7), -1);
4340: break;
4341: case 0xf6: /* GRP3 */
4342: case 0xf7:
4343: if ((b & 1) == 0)
4344: ot = OT_BYTE;
4345: else
4346: ot = dflag + OT_WORD;
4347:
4348: modrm = ldub_code(s->pc++);
4349: mod = (modrm >> 6) & 3;
4350: rm = (modrm & 7) | REX_B(s);
4351: op = (modrm >> 3) & 7;
4352: if (mod != 3) {
4353: if (op == 0)
4354: s->rip_offset = insn_const_size(ot);
4355: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 4356: gen_op_ld_T0_A0(ot + s->mem_index);
1.1 root 4357: } else {
1.1.1.7 root 4358: gen_op_mov_TN_reg(ot, 0, rm);
1.1 root 4359: }
4360:
4361: switch(op) {
4362: case 0: /* test */
4363: val = insn_get(s, ot);
4364: gen_op_movl_T1_im(val);
4365: gen_op_testl_T0_T1_cc();
4366: s->cc_op = CC_OP_LOGICB + ot;
4367: break;
4368: case 2: /* not */
1.1.1.7 root 4369: tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
1.1 root 4370: if (mod != 3) {
1.1.1.7 root 4371: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 4372: } else {
1.1.1.7 root 4373: gen_op_mov_reg_T0(ot, rm);
1.1 root 4374: }
4375: break;
4376: case 3: /* neg */
1.1.1.7 root 4377: tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
1.1 root 4378: if (mod != 3) {
1.1.1.7 root 4379: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 4380: } else {
1.1.1.7 root 4381: gen_op_mov_reg_T0(ot, rm);
1.1 root 4382: }
4383: gen_op_update_neg_cc();
4384: s->cc_op = CC_OP_SUBB + ot;
4385: break;
4386: case 4: /* mul */
4387: switch(ot) {
4388: case OT_BYTE:
1.1.1.7 root 4389: gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
4390: tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4391: tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4392: /* XXX: use 32 bit mul which could be faster */
4393: tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4394: gen_op_mov_reg_T0(OT_WORD, R_EAX);
4395: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4396: tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
1.1 root 4397: s->cc_op = CC_OP_MULB;
4398: break;
4399: case OT_WORD:
1.1.1.7 root 4400: gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
4401: tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4402: tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4403: /* XXX: use 32 bit mul which could be faster */
4404: tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4405: gen_op_mov_reg_T0(OT_WORD, R_EAX);
4406: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4407: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4408: gen_op_mov_reg_T0(OT_WORD, R_EDX);
4409: tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
1.1 root 4410: s->cc_op = CC_OP_MULW;
4411: break;
4412: default:
4413: case OT_LONG:
1.1.1.7 root 4414: #ifdef TARGET_X86_64
4415: gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4416: tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
4417: tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
4418: tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4419: gen_op_mov_reg_T0(OT_LONG, R_EAX);
4420: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4421: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
4422: gen_op_mov_reg_T0(OT_LONG, R_EDX);
4423: tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4424: #else
4425: {
4426: TCGv_i64 t0, t1;
4427: t0 = tcg_temp_new_i64();
4428: t1 = tcg_temp_new_i64();
4429: gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4430: tcg_gen_extu_i32_i64(t0, cpu_T[0]);
4431: tcg_gen_extu_i32_i64(t1, cpu_T[1]);
4432: tcg_gen_mul_i64(t0, t0, t1);
4433: tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4434: gen_op_mov_reg_T0(OT_LONG, R_EAX);
4435: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4436: tcg_gen_shri_i64(t0, t0, 32);
4437: tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4438: gen_op_mov_reg_T0(OT_LONG, R_EDX);
4439: tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4440: }
4441: #endif
1.1 root 4442: s->cc_op = CC_OP_MULL;
4443: break;
4444: #ifdef TARGET_X86_64
4445: case OT_QUAD:
1.1.1.7 root 4446: gen_helper_mulq_EAX_T0(cpu_T[0]);
1.1 root 4447: s->cc_op = CC_OP_MULQ;
4448: break;
4449: #endif
4450: }
4451: break;
4452: case 5: /* imul */
4453: switch(ot) {
4454: case OT_BYTE:
1.1.1.7 root 4455: gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
4456: tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4457: tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
4458: /* XXX: use 32 bit mul which could be faster */
4459: tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4460: gen_op_mov_reg_T0(OT_WORD, R_EAX);
4461: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4462: tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
4463: tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
1.1 root 4464: s->cc_op = CC_OP_MULB;
4465: break;
4466: case OT_WORD:
1.1.1.7 root 4467: gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
4468: tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4469: tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4470: /* XXX: use 32 bit mul which could be faster */
4471: tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4472: gen_op_mov_reg_T0(OT_WORD, R_EAX);
4473: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4474: tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4475: tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4476: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4477: gen_op_mov_reg_T0(OT_WORD, R_EDX);
1.1 root 4478: s->cc_op = CC_OP_MULW;
4479: break;
4480: default:
4481: case OT_LONG:
1.1.1.7 root 4482: #ifdef TARGET_X86_64
4483: gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4484: tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4485: tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
4486: tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4487: gen_op_mov_reg_T0(OT_LONG, R_EAX);
4488: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4489: tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
4490: tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4491: tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
4492: gen_op_mov_reg_T0(OT_LONG, R_EDX);
4493: #else
4494: {
4495: TCGv_i64 t0, t1;
4496: t0 = tcg_temp_new_i64();
4497: t1 = tcg_temp_new_i64();
4498: gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4499: tcg_gen_ext_i32_i64(t0, cpu_T[0]);
4500: tcg_gen_ext_i32_i64(t1, cpu_T[1]);
4501: tcg_gen_mul_i64(t0, t0, t1);
4502: tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4503: gen_op_mov_reg_T0(OT_LONG, R_EAX);
4504: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4505: tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
4506: tcg_gen_shri_i64(t0, t0, 32);
4507: tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4508: gen_op_mov_reg_T0(OT_LONG, R_EDX);
4509: tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4510: }
4511: #endif
1.1 root 4512: s->cc_op = CC_OP_MULL;
4513: break;
4514: #ifdef TARGET_X86_64
4515: case OT_QUAD:
1.1.1.7 root 4516: gen_helper_imulq_EAX_T0(cpu_T[0]);
1.1 root 4517: s->cc_op = CC_OP_MULQ;
4518: break;
4519: #endif
4520: }
4521: break;
4522: case 6: /* div */
4523: switch(ot) {
4524: case OT_BYTE:
4525: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4526: gen_helper_divb_AL(cpu_T[0]);
1.1 root 4527: break;
4528: case OT_WORD:
4529: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4530: gen_helper_divw_AX(cpu_T[0]);
1.1 root 4531: break;
4532: default:
4533: case OT_LONG:
4534: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4535: gen_helper_divl_EAX(cpu_T[0]);
1.1 root 4536: break;
4537: #ifdef TARGET_X86_64
4538: case OT_QUAD:
4539: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4540: gen_helper_divq_EAX(cpu_T[0]);
1.1 root 4541: break;
4542: #endif
4543: }
4544: break;
4545: case 7: /* idiv */
4546: switch(ot) {
4547: case OT_BYTE:
4548: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4549: gen_helper_idivb_AL(cpu_T[0]);
1.1 root 4550: break;
4551: case OT_WORD:
4552: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4553: gen_helper_idivw_AX(cpu_T[0]);
1.1 root 4554: break;
4555: default:
4556: case OT_LONG:
4557: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4558: gen_helper_idivl_EAX(cpu_T[0]);
1.1 root 4559: break;
4560: #ifdef TARGET_X86_64
4561: case OT_QUAD:
4562: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4563: gen_helper_idivq_EAX(cpu_T[0]);
1.1 root 4564: break;
4565: #endif
4566: }
4567: break;
4568: default:
4569: goto illegal_op;
4570: }
4571: break;
4572:
4573: case 0xfe: /* GRP4 */
4574: case 0xff: /* GRP5 */
4575: if ((b & 1) == 0)
4576: ot = OT_BYTE;
4577: else
4578: ot = dflag + OT_WORD;
4579:
4580: modrm = ldub_code(s->pc++);
4581: mod = (modrm >> 6) & 3;
4582: rm = (modrm & 7) | REX_B(s);
4583: op = (modrm >> 3) & 7;
4584: if (op >= 2 && b == 0xfe) {
4585: goto illegal_op;
4586: }
4587: if (CODE64(s)) {
4588: if (op == 2 || op == 4) {
4589: /* operand size for jumps is 64 bit */
4590: ot = OT_QUAD;
4591: } else if (op == 3 || op == 5) {
1.1.1.11 root 4592: ot = dflag ? OT_LONG + (rex_w == 1) : OT_WORD;
1.1 root 4593: } else if (op == 6) {
4594: /* default push size is 64 bit */
4595: ot = dflag ? OT_QUAD : OT_WORD;
4596: }
4597: }
4598: if (mod != 3) {
4599: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4600: if (op >= 2 && op != 3 && op != 5)
1.1.1.7 root 4601: gen_op_ld_T0_A0(ot + s->mem_index);
1.1 root 4602: } else {
1.1.1.7 root 4603: gen_op_mov_TN_reg(ot, 0, rm);
1.1 root 4604: }
4605:
4606: switch(op) {
4607: case 0: /* inc Ev */
4608: if (mod != 3)
4609: opreg = OR_TMP0;
4610: else
4611: opreg = rm;
4612: gen_inc(s, ot, opreg, 1);
4613: break;
4614: case 1: /* dec Ev */
4615: if (mod != 3)
4616: opreg = OR_TMP0;
4617: else
4618: opreg = rm;
4619: gen_inc(s, ot, opreg, -1);
4620: break;
4621: case 2: /* call Ev */
4622: /* XXX: optimize if memory (no 'and' is necessary) */
4623: if (s->dflag == 0)
4624: gen_op_andl_T0_ffff();
4625: next_eip = s->pc - s->cs_base;
4626: gen_movtl_T1_im(next_eip);
4627: gen_push_T1(s);
4628: gen_op_jmp_T0();
4629: gen_eob(s);
4630: break;
4631: case 3: /* lcall Ev */
1.1.1.7 root 4632: gen_op_ld_T1_A0(ot + s->mem_index);
1.1 root 4633: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
1.1.1.7 root 4634: gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
1.1 root 4635: do_lcall:
4636: if (s->pe && !s->vm86) {
4637: if (s->cc_op != CC_OP_DYNAMIC)
4638: gen_op_set_cc_op(s->cc_op);
4639: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4640: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4641: gen_helper_lcall_protected(cpu_tmp2_i32, cpu_T[1],
4642: tcg_const_i32(dflag),
4643: tcg_const_i32(s->pc - pc_start));
4644: } else {
4645: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4646: gen_helper_lcall_real(cpu_tmp2_i32, cpu_T[1],
4647: tcg_const_i32(dflag),
4648: tcg_const_i32(s->pc - s->cs_base));
1.1 root 4649: }
4650: gen_eob(s);
4651: break;
4652: case 4: /* jmp Ev */
4653: if (s->dflag == 0)
4654: gen_op_andl_T0_ffff();
4655: gen_op_jmp_T0();
4656: gen_eob(s);
4657: break;
4658: case 5: /* ljmp Ev */
1.1.1.7 root 4659: gen_op_ld_T1_A0(ot + s->mem_index);
1.1 root 4660: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
1.1.1.7 root 4661: gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
1.1 root 4662: do_ljmp:
4663: if (s->pe && !s->vm86) {
4664: if (s->cc_op != CC_OP_DYNAMIC)
4665: gen_op_set_cc_op(s->cc_op);
4666: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 4667: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4668: gen_helper_ljmp_protected(cpu_tmp2_i32, cpu_T[1],
4669: tcg_const_i32(s->pc - pc_start));
1.1 root 4670: } else {
1.1.1.7 root 4671: gen_op_movl_seg_T0_vm(R_CS);
1.1 root 4672: gen_op_movl_T0_T1();
4673: gen_op_jmp_T0();
4674: }
4675: gen_eob(s);
4676: break;
4677: case 6: /* push Ev */
4678: gen_push_T0(s);
4679: break;
4680: default:
4681: goto illegal_op;
4682: }
4683: break;
4684:
4685: case 0x84: /* test Ev, Gv */
1.1.1.6 root 4686: case 0x85:
1.1 root 4687: if ((b & 1) == 0)
4688: ot = OT_BYTE;
4689: else
4690: ot = dflag + OT_WORD;
4691:
4692: modrm = ldub_code(s->pc++);
4693: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6 root 4694:
1.1 root 4695: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1.1.1.7 root 4696: gen_op_mov_TN_reg(ot, 1, reg);
1.1 root 4697: gen_op_testl_T0_T1_cc();
4698: s->cc_op = CC_OP_LOGICB + ot;
4699: break;
1.1.1.6 root 4700:
1.1 root 4701: case 0xa8: /* test eAX, Iv */
4702: case 0xa9:
4703: if ((b & 1) == 0)
4704: ot = OT_BYTE;
4705: else
4706: ot = dflag + OT_WORD;
4707: val = insn_get(s, ot);
4708:
1.1.1.7 root 4709: gen_op_mov_TN_reg(ot, 0, OR_EAX);
1.1 root 4710: gen_op_movl_T1_im(val);
4711: gen_op_testl_T0_T1_cc();
4712: s->cc_op = CC_OP_LOGICB + ot;
4713: break;
1.1.1.6 root 4714:
1.1 root 4715: case 0x98: /* CWDE/CBW */
4716: #ifdef TARGET_X86_64
4717: if (dflag == 2) {
1.1.1.7 root 4718: gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
4719: tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4720: gen_op_mov_reg_T0(OT_QUAD, R_EAX);
1.1 root 4721: } else
4722: #endif
1.1.1.7 root 4723: if (dflag == 1) {
4724: gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
4725: tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4726: gen_op_mov_reg_T0(OT_LONG, R_EAX);
4727: } else {
4728: gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX);
4729: tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4730: gen_op_mov_reg_T0(OT_WORD, R_EAX);
4731: }
1.1 root 4732: break;
4733: case 0x99: /* CDQ/CWD */
4734: #ifdef TARGET_X86_64
4735: if (dflag == 2) {
1.1.1.7 root 4736: gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
4737: tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
4738: gen_op_mov_reg_T0(OT_QUAD, R_EDX);
1.1 root 4739: } else
4740: #endif
1.1.1.7 root 4741: if (dflag == 1) {
4742: gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
4743: tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4744: tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
4745: gen_op_mov_reg_T0(OT_LONG, R_EDX);
4746: } else {
4747: gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
4748: tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4749: tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
4750: gen_op_mov_reg_T0(OT_WORD, R_EDX);
4751: }
1.1 root 4752: break;
4753: case 0x1af: /* imul Gv, Ev */
4754: case 0x69: /* imul Gv, Ev, I */
4755: case 0x6b:
4756: ot = dflag + OT_WORD;
4757: modrm = ldub_code(s->pc++);
4758: reg = ((modrm >> 3) & 7) | rex_r;
4759: if (b == 0x69)
4760: s->rip_offset = insn_const_size(ot);
4761: else if (b == 0x6b)
4762: s->rip_offset = 1;
4763: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4764: if (b == 0x69) {
4765: val = insn_get(s, ot);
4766: gen_op_movl_T1_im(val);
4767: } else if (b == 0x6b) {
4768: val = (int8_t)insn_get(s, OT_BYTE);
4769: gen_op_movl_T1_im(val);
4770: } else {
1.1.1.7 root 4771: gen_op_mov_TN_reg(ot, 1, reg);
1.1 root 4772: }
4773:
4774: #ifdef TARGET_X86_64
4775: if (ot == OT_QUAD) {
1.1.1.7 root 4776: gen_helper_imulq_T0_T1(cpu_T[0], cpu_T[0], cpu_T[1]);
1.1 root 4777: } else
4778: #endif
4779: if (ot == OT_LONG) {
1.1.1.7 root 4780: #ifdef TARGET_X86_64
4781: tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4782: tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
4783: tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4784: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4785: tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
4786: tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4787: #else
4788: {
4789: TCGv_i64 t0, t1;
4790: t0 = tcg_temp_new_i64();
4791: t1 = tcg_temp_new_i64();
4792: tcg_gen_ext_i32_i64(t0, cpu_T[0]);
4793: tcg_gen_ext_i32_i64(t1, cpu_T[1]);
4794: tcg_gen_mul_i64(t0, t0, t1);
4795: tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4796: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4797: tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
4798: tcg_gen_shri_i64(t0, t0, 32);
4799: tcg_gen_trunc_i64_i32(cpu_T[1], t0);
4800: tcg_gen_sub_tl(cpu_cc_src, cpu_T[1], cpu_tmp0);
4801: }
4802: #endif
1.1 root 4803: } else {
1.1.1.7 root 4804: tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4805: tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4806: /* XXX: use 32 bit mul which could be faster */
4807: tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4808: tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4809: tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4810: tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
1.1 root 4811: }
1.1.1.7 root 4812: gen_op_mov_reg_T0(ot, reg);
1.1 root 4813: s->cc_op = CC_OP_MULB + ot;
4814: break;
4815: case 0x1c0:
4816: case 0x1c1: /* xadd Ev, Gv */
4817: if ((b & 1) == 0)
4818: ot = OT_BYTE;
4819: else
4820: ot = dflag + OT_WORD;
4821: modrm = ldub_code(s->pc++);
4822: reg = ((modrm >> 3) & 7) | rex_r;
4823: mod = (modrm >> 6) & 3;
4824: if (mod == 3) {
4825: rm = (modrm & 7) | REX_B(s);
1.1.1.7 root 4826: gen_op_mov_TN_reg(ot, 0, reg);
4827: gen_op_mov_TN_reg(ot, 1, rm);
1.1 root 4828: gen_op_addl_T0_T1();
1.1.1.7 root 4829: gen_op_mov_reg_T1(ot, reg);
4830: gen_op_mov_reg_T0(ot, rm);
1.1 root 4831: } else {
4832: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 4833: gen_op_mov_TN_reg(ot, 0, reg);
4834: gen_op_ld_T1_A0(ot + s->mem_index);
1.1 root 4835: gen_op_addl_T0_T1();
1.1.1.7 root 4836: gen_op_st_T0_A0(ot + s->mem_index);
4837: gen_op_mov_reg_T1(ot, reg);
1.1 root 4838: }
4839: gen_op_update2_cc();
4840: s->cc_op = CC_OP_ADDB + ot;
4841: break;
4842: case 0x1b0:
4843: case 0x1b1: /* cmpxchg Ev, Gv */
1.1.1.7 root 4844: {
4845: int label1, label2;
4846: TCGv t0, t1, t2, a0;
4847:
4848: if ((b & 1) == 0)
4849: ot = OT_BYTE;
4850: else
4851: ot = dflag + OT_WORD;
4852: modrm = ldub_code(s->pc++);
4853: reg = ((modrm >> 3) & 7) | rex_r;
4854: mod = (modrm >> 6) & 3;
4855: t0 = tcg_temp_local_new();
4856: t1 = tcg_temp_local_new();
4857: t2 = tcg_temp_local_new();
4858: a0 = tcg_temp_local_new();
4859: gen_op_mov_v_reg(ot, t1, reg);
4860: if (mod == 3) {
4861: rm = (modrm & 7) | REX_B(s);
4862: gen_op_mov_v_reg(ot, t0, rm);
4863: } else {
4864: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4865: tcg_gen_mov_tl(a0, cpu_A0);
4866: gen_op_ld_v(ot + s->mem_index, t0, a0);
4867: rm = 0; /* avoid warning */
4868: }
4869: label1 = gen_new_label();
1.1.1.9 root 4870: tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0);
1.1.1.7 root 4871: gen_extu(ot, t2);
4872: tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
1.1.1.16 root 4873: label2 = gen_new_label();
1.1.1.7 root 4874: if (mod == 3) {
4875: gen_op_mov_reg_v(ot, R_EAX, t0);
4876: tcg_gen_br(label2);
4877: gen_set_label(label1);
4878: gen_op_mov_reg_v(ot, rm, t1);
4879: } else {
1.1.1.16 root 4880: /* perform no-op store cycle like physical cpu; must be
4881: before changing accumulator to ensure idempotency if
4882: the store faults and the instruction is restarted */
4883: gen_op_st_v(ot + s->mem_index, t0, a0);
1.1.1.7 root 4884: gen_op_mov_reg_v(ot, R_EAX, t0);
1.1.1.16 root 4885: tcg_gen_br(label2);
1.1.1.7 root 4886: gen_set_label(label1);
4887: gen_op_st_v(ot + s->mem_index, t1, a0);
4888: }
1.1.1.16 root 4889: gen_set_label(label2);
1.1.1.7 root 4890: tcg_gen_mov_tl(cpu_cc_src, t0);
4891: tcg_gen_mov_tl(cpu_cc_dst, t2);
4892: s->cc_op = CC_OP_SUBB + ot;
4893: tcg_temp_free(t0);
4894: tcg_temp_free(t1);
4895: tcg_temp_free(t2);
4896: tcg_temp_free(a0);
1.1 root 4897: }
4898: break;
4899: case 0x1c7: /* cmpxchg8b */
4900: modrm = ldub_code(s->pc++);
4901: mod = (modrm >> 6) & 3;
1.1.1.6 root 4902: if ((mod == 3) || ((modrm & 0x38) != 0x8))
1.1 root 4903: goto illegal_op;
1.1.1.7 root 4904: #ifdef TARGET_X86_64
4905: if (dflag == 2) {
4906: if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
4907: goto illegal_op;
4908: gen_jmp_im(pc_start - s->cs_base);
4909: if (s->cc_op != CC_OP_DYNAMIC)
4910: gen_op_set_cc_op(s->cc_op);
4911: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4912: gen_helper_cmpxchg16b(cpu_A0);
4913: } else
4914: #endif
4915: {
4916: if (!(s->cpuid_features & CPUID_CX8))
4917: goto illegal_op;
4918: gen_jmp_im(pc_start - s->cs_base);
4919: if (s->cc_op != CC_OP_DYNAMIC)
4920: gen_op_set_cc_op(s->cc_op);
4921: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4922: gen_helper_cmpxchg8b(cpu_A0);
4923: }
1.1 root 4924: s->cc_op = CC_OP_EFLAGS;
4925: break;
1.1.1.6 root 4926:
1.1 root 4927: /**************************/
4928: /* push/pop */
4929: case 0x50 ... 0x57: /* push */
1.1.1.7 root 4930: gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
1.1 root 4931: gen_push_T0(s);
4932: break;
4933: case 0x58 ... 0x5f: /* pop */
4934: if (CODE64(s)) {
4935: ot = dflag ? OT_QUAD : OT_WORD;
4936: } else {
4937: ot = dflag + OT_WORD;
4938: }
4939: gen_pop_T0(s);
4940: /* NOTE: order is important for pop %sp */
4941: gen_pop_update(s);
1.1.1.7 root 4942: gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
1.1 root 4943: break;
4944: case 0x60: /* pusha */
4945: if (CODE64(s))
4946: goto illegal_op;
4947: gen_pusha(s);
4948: break;
4949: case 0x61: /* popa */
4950: if (CODE64(s))
4951: goto illegal_op;
4952: gen_popa(s);
4953: break;
4954: case 0x68: /* push Iv */
4955: case 0x6a:
4956: if (CODE64(s)) {
4957: ot = dflag ? OT_QUAD : OT_WORD;
4958: } else {
4959: ot = dflag + OT_WORD;
4960: }
4961: if (b == 0x68)
4962: val = insn_get(s, ot);
4963: else
4964: val = (int8_t)insn_get(s, OT_BYTE);
4965: gen_op_movl_T0_im(val);
4966: gen_push_T0(s);
4967: break;
4968: case 0x8f: /* pop Ev */
4969: if (CODE64(s)) {
4970: ot = dflag ? OT_QUAD : OT_WORD;
4971: } else {
4972: ot = dflag + OT_WORD;
4973: }
4974: modrm = ldub_code(s->pc++);
4975: mod = (modrm >> 6) & 3;
4976: gen_pop_T0(s);
4977: if (mod == 3) {
4978: /* NOTE: order is important for pop %sp */
4979: gen_pop_update(s);
4980: rm = (modrm & 7) | REX_B(s);
1.1.1.7 root 4981: gen_op_mov_reg_T0(ot, rm);
1.1 root 4982: } else {
4983: /* NOTE: order is important too for MMU exceptions */
4984: s->popl_esp_hack = 1 << ot;
4985: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4986: s->popl_esp_hack = 0;
4987: gen_pop_update(s);
4988: }
4989: break;
4990: case 0xc8: /* enter */
4991: {
4992: int level;
4993: val = lduw_code(s->pc);
4994: s->pc += 2;
4995: level = ldub_code(s->pc++);
4996: gen_enter(s, val, level);
4997: }
4998: break;
4999: case 0xc9: /* leave */
5000: /* XXX: exception not precise (ESP is updated before potential exception) */
5001: if (CODE64(s)) {
1.1.1.7 root 5002: gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
5003: gen_op_mov_reg_T0(OT_QUAD, R_ESP);
1.1 root 5004: } else if (s->ss32) {
1.1.1.7 root 5005: gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
5006: gen_op_mov_reg_T0(OT_LONG, R_ESP);
1.1 root 5007: } else {
1.1.1.7 root 5008: gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
5009: gen_op_mov_reg_T0(OT_WORD, R_ESP);
1.1 root 5010: }
5011: gen_pop_T0(s);
5012: if (CODE64(s)) {
5013: ot = dflag ? OT_QUAD : OT_WORD;
5014: } else {
5015: ot = dflag + OT_WORD;
5016: }
1.1.1.7 root 5017: gen_op_mov_reg_T0(ot, R_EBP);
1.1 root 5018: gen_pop_update(s);
5019: break;
5020: case 0x06: /* push es */
5021: case 0x0e: /* push cs */
5022: case 0x16: /* push ss */
5023: case 0x1e: /* push ds */
5024: if (CODE64(s))
5025: goto illegal_op;
5026: gen_op_movl_T0_seg(b >> 3);
5027: gen_push_T0(s);
5028: break;
5029: case 0x1a0: /* push fs */
5030: case 0x1a8: /* push gs */
5031: gen_op_movl_T0_seg((b >> 3) & 7);
5032: gen_push_T0(s);
5033: break;
5034: case 0x07: /* pop es */
5035: case 0x17: /* pop ss */
5036: case 0x1f: /* pop ds */
5037: if (CODE64(s))
5038: goto illegal_op;
5039: reg = b >> 3;
5040: gen_pop_T0(s);
5041: gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5042: gen_pop_update(s);
5043: if (reg == R_SS) {
5044: /* if reg == SS, inhibit interrupts/trace. */
5045: /* If several instructions disable interrupts, only the
5046: _first_ does it */
5047: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
1.1.1.7 root 5048: gen_helper_set_inhibit_irq();
1.1 root 5049: s->tf = 0;
5050: }
5051: if (s->is_jmp) {
5052: gen_jmp_im(s->pc - s->cs_base);
5053: gen_eob(s);
5054: }
5055: break;
5056: case 0x1a1: /* pop fs */
5057: case 0x1a9: /* pop gs */
5058: gen_pop_T0(s);
5059: gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
5060: gen_pop_update(s);
5061: if (s->is_jmp) {
5062: gen_jmp_im(s->pc - s->cs_base);
5063: gen_eob(s);
5064: }
5065: break;
5066:
5067: /**************************/
5068: /* mov */
5069: case 0x88:
5070: case 0x89: /* mov Gv, Ev */
5071: if ((b & 1) == 0)
5072: ot = OT_BYTE;
5073: else
5074: ot = dflag + OT_WORD;
5075: modrm = ldub_code(s->pc++);
5076: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6 root 5077:
1.1 root 5078: /* generate a generic store */
5079: gen_ldst_modrm(s, modrm, ot, reg, 1);
5080: break;
5081: case 0xc6:
5082: case 0xc7: /* mov Ev, Iv */
5083: if ((b & 1) == 0)
5084: ot = OT_BYTE;
5085: else
5086: ot = dflag + OT_WORD;
5087: modrm = ldub_code(s->pc++);
5088: mod = (modrm >> 6) & 3;
5089: if (mod != 3) {
5090: s->rip_offset = insn_const_size(ot);
5091: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5092: }
5093: val = insn_get(s, ot);
5094: gen_op_movl_T0_im(val);
5095: if (mod != 3)
1.1.1.7 root 5096: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 5097: else
1.1.1.7 root 5098: gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
1.1 root 5099: break;
5100: case 0x8a:
5101: case 0x8b: /* mov Ev, Gv */
5102: if ((b & 1) == 0)
5103: ot = OT_BYTE;
5104: else
5105: ot = OT_WORD + dflag;
5106: modrm = ldub_code(s->pc++);
5107: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6 root 5108:
1.1 root 5109: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1.1.1.7 root 5110: gen_op_mov_reg_T0(ot, reg);
1.1 root 5111: break;
5112: case 0x8e: /* mov seg, Gv */
5113: modrm = ldub_code(s->pc++);
5114: reg = (modrm >> 3) & 7;
5115: if (reg >= 6 || reg == R_CS)
5116: goto illegal_op;
5117: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5118: gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5119: if (reg == R_SS) {
5120: /* if reg == SS, inhibit interrupts/trace */
5121: /* If several instructions disable interrupts, only the
5122: _first_ does it */
5123: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
1.1.1.7 root 5124: gen_helper_set_inhibit_irq();
1.1 root 5125: s->tf = 0;
5126: }
5127: if (s->is_jmp) {
5128: gen_jmp_im(s->pc - s->cs_base);
5129: gen_eob(s);
5130: }
5131: break;
5132: case 0x8c: /* mov Gv, seg */
5133: modrm = ldub_code(s->pc++);
5134: reg = (modrm >> 3) & 7;
5135: mod = (modrm >> 6) & 3;
5136: if (reg >= 6)
5137: goto illegal_op;
5138: gen_op_movl_T0_seg(reg);
5139: if (mod == 3)
5140: ot = OT_WORD + dflag;
5141: else
5142: ot = OT_WORD;
5143: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5144: break;
5145:
5146: case 0x1b6: /* movzbS Gv, Eb */
5147: case 0x1b7: /* movzwS Gv, Eb */
5148: case 0x1be: /* movsbS Gv, Eb */
5149: case 0x1bf: /* movswS Gv, Eb */
5150: {
5151: int d_ot;
5152: /* d_ot is the size of destination */
5153: d_ot = dflag + OT_WORD;
5154: /* ot is the size of source */
5155: ot = (b & 1) + OT_BYTE;
5156: modrm = ldub_code(s->pc++);
5157: reg = ((modrm >> 3) & 7) | rex_r;
5158: mod = (modrm >> 6) & 3;
5159: rm = (modrm & 7) | REX_B(s);
1.1.1.6 root 5160:
1.1 root 5161: if (mod == 3) {
1.1.1.7 root 5162: gen_op_mov_TN_reg(ot, 0, rm);
1.1 root 5163: switch(ot | (b & 8)) {
5164: case OT_BYTE:
1.1.1.7 root 5165: tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
1.1 root 5166: break;
5167: case OT_BYTE | 8:
1.1.1.7 root 5168: tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
1.1 root 5169: break;
5170: case OT_WORD:
1.1.1.7 root 5171: tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
1.1 root 5172: break;
5173: default:
5174: case OT_WORD | 8:
1.1.1.7 root 5175: tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
1.1 root 5176: break;
5177: }
1.1.1.7 root 5178: gen_op_mov_reg_T0(d_ot, reg);
1.1 root 5179: } else {
5180: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5181: if (b & 8) {
1.1.1.7 root 5182: gen_op_lds_T0_A0(ot + s->mem_index);
1.1 root 5183: } else {
1.1.1.7 root 5184: gen_op_ldu_T0_A0(ot + s->mem_index);
1.1 root 5185: }
1.1.1.7 root 5186: gen_op_mov_reg_T0(d_ot, reg);
1.1 root 5187: }
5188: }
5189: break;
5190:
5191: case 0x8d: /* lea */
5192: ot = dflag + OT_WORD;
5193: modrm = ldub_code(s->pc++);
5194: mod = (modrm >> 6) & 3;
5195: if (mod == 3)
5196: goto illegal_op;
5197: reg = ((modrm >> 3) & 7) | rex_r;
5198: /* we must ensure that no segment is added */
5199: s->override = -1;
5200: val = s->addseg;
5201: s->addseg = 0;
5202: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5203: s->addseg = val;
1.1.1.7 root 5204: gen_op_mov_reg_A0(ot - OT_WORD, reg);
1.1 root 5205: break;
1.1.1.6 root 5206:
1.1 root 5207: case 0xa0: /* mov EAX, Ov */
5208: case 0xa1:
5209: case 0xa2: /* mov Ov, EAX */
5210: case 0xa3:
5211: {
5212: target_ulong offset_addr;
5213:
5214: if ((b & 1) == 0)
5215: ot = OT_BYTE;
5216: else
5217: ot = dflag + OT_WORD;
5218: #ifdef TARGET_X86_64
5219: if (s->aflag == 2) {
5220: offset_addr = ldq_code(s->pc);
5221: s->pc += 8;
1.1.1.7 root 5222: gen_op_movq_A0_im(offset_addr);
1.1.1.6 root 5223: } else
1.1 root 5224: #endif
5225: {
5226: if (s->aflag) {
5227: offset_addr = insn_get(s, OT_LONG);
5228: } else {
5229: offset_addr = insn_get(s, OT_WORD);
5230: }
5231: gen_op_movl_A0_im(offset_addr);
5232: }
5233: gen_add_A0_ds_seg(s);
5234: if ((b & 2) == 0) {
1.1.1.7 root 5235: gen_op_ld_T0_A0(ot + s->mem_index);
5236: gen_op_mov_reg_T0(ot, R_EAX);
1.1 root 5237: } else {
1.1.1.7 root 5238: gen_op_mov_TN_reg(ot, 0, R_EAX);
5239: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 5240: }
5241: }
5242: break;
5243: case 0xd7: /* xlat */
5244: #ifdef TARGET_X86_64
5245: if (s->aflag == 2) {
1.1.1.7 root 5246: gen_op_movq_A0_reg(R_EBX);
5247: gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5248: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5249: tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
1.1.1.6 root 5250: } else
1.1 root 5251: #endif
5252: {
1.1.1.7 root 5253: gen_op_movl_A0_reg(R_EBX);
5254: gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5255: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5256: tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
1.1 root 5257: if (s->aflag == 0)
5258: gen_op_andl_A0_ffff();
1.1.1.7 root 5259: else
5260: tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
1.1 root 5261: }
5262: gen_add_A0_ds_seg(s);
1.1.1.7 root 5263: gen_op_ldu_T0_A0(OT_BYTE + s->mem_index);
5264: gen_op_mov_reg_T0(OT_BYTE, R_EAX);
1.1 root 5265: break;
5266: case 0xb0 ... 0xb7: /* mov R, Ib */
5267: val = insn_get(s, OT_BYTE);
5268: gen_op_movl_T0_im(val);
1.1.1.7 root 5269: gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
1.1 root 5270: break;
5271: case 0xb8 ... 0xbf: /* mov R, Iv */
5272: #ifdef TARGET_X86_64
5273: if (dflag == 2) {
5274: uint64_t tmp;
5275: /* 64 bit case */
5276: tmp = ldq_code(s->pc);
5277: s->pc += 8;
5278: reg = (b & 7) | REX_B(s);
5279: gen_movtl_T0_im(tmp);
1.1.1.7 root 5280: gen_op_mov_reg_T0(OT_QUAD, reg);
1.1.1.6 root 5281: } else
1.1 root 5282: #endif
5283: {
5284: ot = dflag ? OT_LONG : OT_WORD;
5285: val = insn_get(s, ot);
5286: reg = (b & 7) | REX_B(s);
5287: gen_op_movl_T0_im(val);
1.1.1.7 root 5288: gen_op_mov_reg_T0(ot, reg);
1.1 root 5289: }
5290: break;
5291:
5292: case 0x91 ... 0x97: /* xchg R, EAX */
1.1.1.12 root 5293: do_xchg_reg_eax:
1.1 root 5294: ot = dflag + OT_WORD;
5295: reg = (b & 7) | REX_B(s);
5296: rm = R_EAX;
5297: goto do_xchg_reg;
5298: case 0x86:
5299: case 0x87: /* xchg Ev, Gv */
5300: if ((b & 1) == 0)
5301: ot = OT_BYTE;
5302: else
5303: ot = dflag + OT_WORD;
5304: modrm = ldub_code(s->pc++);
5305: reg = ((modrm >> 3) & 7) | rex_r;
5306: mod = (modrm >> 6) & 3;
5307: if (mod == 3) {
5308: rm = (modrm & 7) | REX_B(s);
5309: do_xchg_reg:
1.1.1.7 root 5310: gen_op_mov_TN_reg(ot, 0, reg);
5311: gen_op_mov_TN_reg(ot, 1, rm);
5312: gen_op_mov_reg_T0(ot, rm);
5313: gen_op_mov_reg_T1(ot, reg);
1.1 root 5314: } else {
5315: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 5316: gen_op_mov_TN_reg(ot, 0, reg);
1.1 root 5317: /* for xchg, lock is implicit */
5318: if (!(prefixes & PREFIX_LOCK))
1.1.1.7 root 5319: gen_helper_lock();
5320: gen_op_ld_T1_A0(ot + s->mem_index);
5321: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 5322: if (!(prefixes & PREFIX_LOCK))
1.1.1.7 root 5323: gen_helper_unlock();
5324: gen_op_mov_reg_T1(ot, reg);
1.1 root 5325: }
5326: break;
5327: case 0xc4: /* les Gv */
5328: if (CODE64(s))
5329: goto illegal_op;
5330: op = R_ES;
5331: goto do_lxx;
5332: case 0xc5: /* lds Gv */
5333: if (CODE64(s))
5334: goto illegal_op;
5335: op = R_DS;
5336: goto do_lxx;
5337: case 0x1b2: /* lss Gv */
5338: op = R_SS;
5339: goto do_lxx;
5340: case 0x1b4: /* lfs Gv */
5341: op = R_FS;
5342: goto do_lxx;
5343: case 0x1b5: /* lgs Gv */
5344: op = R_GS;
5345: do_lxx:
5346: ot = dflag ? OT_LONG : OT_WORD;
5347: modrm = ldub_code(s->pc++);
5348: reg = ((modrm >> 3) & 7) | rex_r;
5349: mod = (modrm >> 6) & 3;
5350: if (mod == 3)
5351: goto illegal_op;
5352: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 5353: gen_op_ld_T1_A0(ot + s->mem_index);
1.1 root 5354: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
5355: /* load the segment first to handle exceptions properly */
1.1.1.7 root 5356: gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
1.1 root 5357: gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5358: /* then put the data */
1.1.1.7 root 5359: gen_op_mov_reg_T1(ot, reg);
1.1 root 5360: if (s->is_jmp) {
5361: gen_jmp_im(s->pc - s->cs_base);
5362: gen_eob(s);
5363: }
5364: break;
1.1.1.6 root 5365:
1.1 root 5366: /************************/
5367: /* shifts */
5368: case 0xc0:
5369: case 0xc1:
5370: /* shift Ev,Ib */
5371: shift = 2;
5372: grp2:
5373: {
5374: if ((b & 1) == 0)
5375: ot = OT_BYTE;
5376: else
5377: ot = dflag + OT_WORD;
1.1.1.6 root 5378:
1.1 root 5379: modrm = ldub_code(s->pc++);
5380: mod = (modrm >> 6) & 3;
5381: op = (modrm >> 3) & 7;
1.1.1.6 root 5382:
1.1 root 5383: if (mod != 3) {
5384: if (shift == 2) {
5385: s->rip_offset = 1;
5386: }
5387: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5388: opreg = OR_TMP0;
5389: } else {
5390: opreg = (modrm & 7) | REX_B(s);
5391: }
5392:
5393: /* simpler op */
5394: if (shift == 0) {
5395: gen_shift(s, op, ot, opreg, OR_ECX);
5396: } else {
5397: if (shift == 2) {
5398: shift = ldub_code(s->pc++);
5399: }
5400: gen_shifti(s, op, ot, opreg, shift);
5401: }
5402: }
5403: break;
5404: case 0xd0:
5405: case 0xd1:
5406: /* shift Ev,1 */
5407: shift = 1;
5408: goto grp2;
5409: case 0xd2:
5410: case 0xd3:
5411: /* shift Ev,cl */
5412: shift = 0;
5413: goto grp2;
5414:
5415: case 0x1a4: /* shld imm */
5416: op = 0;
5417: shift = 1;
5418: goto do_shiftd;
5419: case 0x1a5: /* shld cl */
5420: op = 0;
5421: shift = 0;
5422: goto do_shiftd;
5423: case 0x1ac: /* shrd imm */
5424: op = 1;
5425: shift = 1;
5426: goto do_shiftd;
5427: case 0x1ad: /* shrd cl */
5428: op = 1;
5429: shift = 0;
5430: do_shiftd:
5431: ot = dflag + OT_WORD;
5432: modrm = ldub_code(s->pc++);
5433: mod = (modrm >> 6) & 3;
5434: rm = (modrm & 7) | REX_B(s);
5435: reg = ((modrm >> 3) & 7) | rex_r;
5436: if (mod != 3) {
5437: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 5438: opreg = OR_TMP0;
1.1 root 5439: } else {
1.1.1.7 root 5440: opreg = rm;
1.1 root 5441: }
1.1.1.7 root 5442: gen_op_mov_TN_reg(ot, 1, reg);
1.1.1.6 root 5443:
1.1 root 5444: if (shift) {
5445: val = ldub_code(s->pc++);
1.1.1.7 root 5446: tcg_gen_movi_tl(cpu_T3, val);
1.1 root 5447: } else {
1.1.1.9 root 5448: tcg_gen_mov_tl(cpu_T3, cpu_regs[R_ECX]);
1.1 root 5449: }
1.1.1.7 root 5450: gen_shiftd_rm_T1_T3(s, ot, opreg, op);
1.1 root 5451: break;
5452:
5453: /************************/
5454: /* floats */
1.1.1.6 root 5455: case 0xd8 ... 0xdf:
1.1 root 5456: if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5457: /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5458: /* XXX: what to do if illegal op ? */
5459: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5460: break;
5461: }
5462: modrm = ldub_code(s->pc++);
5463: mod = (modrm >> 6) & 3;
5464: rm = modrm & 7;
5465: op = ((b & 7) << 3) | ((modrm >> 3) & 7);
5466: if (mod != 3) {
5467: /* memory op */
5468: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5469: switch(op) {
5470: case 0x00 ... 0x07: /* fxxxs */
5471: case 0x10 ... 0x17: /* fixxxl */
5472: case 0x20 ... 0x27: /* fxxxl */
5473: case 0x30 ... 0x37: /* fixxx */
5474: {
5475: int op1;
5476: op1 = op & 7;
5477:
5478: switch(op >> 4) {
5479: case 0:
1.1.1.7 root 5480: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5481: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5482: gen_helper_flds_FT0(cpu_tmp2_i32);
1.1 root 5483: break;
5484: case 1:
1.1.1.7 root 5485: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5486: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5487: gen_helper_fildl_FT0(cpu_tmp2_i32);
1.1 root 5488: break;
5489: case 2:
1.1.1.7 root 5490: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
5491: (s->mem_index >> 2) - 1);
5492: gen_helper_fldl_FT0(cpu_tmp1_i64);
1.1 root 5493: break;
5494: case 3:
5495: default:
1.1.1.7 root 5496: gen_op_lds_T0_A0(OT_WORD + s->mem_index);
5497: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5498: gen_helper_fildl_FT0(cpu_tmp2_i32);
1.1 root 5499: break;
5500: }
1.1.1.6 root 5501:
1.1.1.7 root 5502: gen_helper_fp_arith_ST0_FT0(op1);
1.1 root 5503: if (op1 == 3) {
5504: /* fcomp needs pop */
1.1.1.7 root 5505: gen_helper_fpop();
1.1 root 5506: }
5507: }
5508: break;
5509: case 0x08: /* flds */
5510: case 0x0a: /* fsts */
5511: case 0x0b: /* fstps */
1.1.1.3 root 5512: case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5513: case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5514: case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
1.1 root 5515: switch(op & 7) {
5516: case 0:
5517: switch(op >> 4) {
5518: case 0:
1.1.1.7 root 5519: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5520: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5521: gen_helper_flds_ST0(cpu_tmp2_i32);
1.1 root 5522: break;
5523: case 1:
1.1.1.7 root 5524: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
5525: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5526: gen_helper_fildl_ST0(cpu_tmp2_i32);
1.1 root 5527: break;
5528: case 2:
1.1.1.7 root 5529: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
5530: (s->mem_index >> 2) - 1);
5531: gen_helper_fldl_ST0(cpu_tmp1_i64);
1.1 root 5532: break;
5533: case 3:
5534: default:
1.1.1.7 root 5535: gen_op_lds_T0_A0(OT_WORD + s->mem_index);
5536: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5537: gen_helper_fildl_ST0(cpu_tmp2_i32);
1.1 root 5538: break;
5539: }
5540: break;
1.1.1.3 root 5541: case 1:
1.1.1.7 root 5542: /* XXX: the corresponding CPUID bit must be tested ! */
1.1.1.3 root 5543: switch(op >> 4) {
5544: case 1:
1.1.1.7 root 5545: gen_helper_fisttl_ST0(cpu_tmp2_i32);
5546: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5547: gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1.1.3 root 5548: break;
5549: case 2:
1.1.1.7 root 5550: gen_helper_fisttll_ST0(cpu_tmp1_i64);
5551: tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
5552: (s->mem_index >> 2) - 1);
1.1.1.3 root 5553: break;
5554: case 3:
5555: default:
1.1.1.7 root 5556: gen_helper_fistt_ST0(cpu_tmp2_i32);
5557: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5558: gen_op_st_T0_A0(OT_WORD + s->mem_index);
5559: break;
1.1.1.3 root 5560: }
1.1.1.7 root 5561: gen_helper_fpop();
1.1.1.3 root 5562: break;
1.1 root 5563: default:
5564: switch(op >> 4) {
5565: case 0:
1.1.1.7 root 5566: gen_helper_fsts_ST0(cpu_tmp2_i32);
5567: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5568: gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1 root 5569: break;
5570: case 1:
1.1.1.7 root 5571: gen_helper_fistl_ST0(cpu_tmp2_i32);
5572: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5573: gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1 root 5574: break;
5575: case 2:
1.1.1.7 root 5576: gen_helper_fstl_ST0(cpu_tmp1_i64);
5577: tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
5578: (s->mem_index >> 2) - 1);
1.1 root 5579: break;
5580: case 3:
5581: default:
1.1.1.7 root 5582: gen_helper_fist_ST0(cpu_tmp2_i32);
5583: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5584: gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1 root 5585: break;
5586: }
5587: if ((op & 7) == 3)
1.1.1.7 root 5588: gen_helper_fpop();
1.1 root 5589: break;
5590: }
5591: break;
5592: case 0x0c: /* fldenv mem */
1.1.1.7 root 5593: if (s->cc_op != CC_OP_DYNAMIC)
5594: gen_op_set_cc_op(s->cc_op);
5595: gen_jmp_im(pc_start - s->cs_base);
5596: gen_helper_fldenv(
5597: cpu_A0, tcg_const_i32(s->dflag));
1.1 root 5598: break;
5599: case 0x0d: /* fldcw mem */
1.1.1.7 root 5600: gen_op_ld_T0_A0(OT_WORD + s->mem_index);
5601: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5602: gen_helper_fldcw(cpu_tmp2_i32);
1.1 root 5603: break;
5604: case 0x0e: /* fnstenv mem */
1.1.1.7 root 5605: if (s->cc_op != CC_OP_DYNAMIC)
5606: gen_op_set_cc_op(s->cc_op);
5607: gen_jmp_im(pc_start - s->cs_base);
5608: gen_helper_fstenv(cpu_A0, tcg_const_i32(s->dflag));
1.1 root 5609: break;
5610: case 0x0f: /* fnstcw mem */
1.1.1.7 root 5611: gen_helper_fnstcw(cpu_tmp2_i32);
5612: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5613: gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1 root 5614: break;
5615: case 0x1d: /* fldt mem */
1.1.1.7 root 5616: if (s->cc_op != CC_OP_DYNAMIC)
5617: gen_op_set_cc_op(s->cc_op);
5618: gen_jmp_im(pc_start - s->cs_base);
5619: gen_helper_fldt_ST0(cpu_A0);
1.1 root 5620: break;
5621: case 0x1f: /* fstpt mem */
1.1.1.7 root 5622: if (s->cc_op != CC_OP_DYNAMIC)
5623: gen_op_set_cc_op(s->cc_op);
5624: gen_jmp_im(pc_start - s->cs_base);
5625: gen_helper_fstt_ST0(cpu_A0);
5626: gen_helper_fpop();
1.1 root 5627: break;
5628: case 0x2c: /* frstor mem */
1.1.1.7 root 5629: if (s->cc_op != CC_OP_DYNAMIC)
5630: gen_op_set_cc_op(s->cc_op);
5631: gen_jmp_im(pc_start - s->cs_base);
5632: gen_helper_frstor(cpu_A0, tcg_const_i32(s->dflag));
1.1 root 5633: break;
5634: case 0x2e: /* fnsave mem */
1.1.1.7 root 5635: if (s->cc_op != CC_OP_DYNAMIC)
5636: gen_op_set_cc_op(s->cc_op);
5637: gen_jmp_im(pc_start - s->cs_base);
5638: gen_helper_fsave(cpu_A0, tcg_const_i32(s->dflag));
1.1 root 5639: break;
5640: case 0x2f: /* fnstsw mem */
1.1.1.7 root 5641: gen_helper_fnstsw(cpu_tmp2_i32);
5642: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5643: gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1 root 5644: break;
5645: case 0x3c: /* fbld */
1.1.1.7 root 5646: if (s->cc_op != CC_OP_DYNAMIC)
5647: gen_op_set_cc_op(s->cc_op);
5648: gen_jmp_im(pc_start - s->cs_base);
5649: gen_helper_fbld_ST0(cpu_A0);
1.1 root 5650: break;
5651: case 0x3e: /* fbstp */
1.1.1.7 root 5652: if (s->cc_op != CC_OP_DYNAMIC)
5653: gen_op_set_cc_op(s->cc_op);
5654: gen_jmp_im(pc_start - s->cs_base);
5655: gen_helper_fbst_ST0(cpu_A0);
5656: gen_helper_fpop();
1.1 root 5657: break;
5658: case 0x3d: /* fildll */
1.1.1.7 root 5659: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
5660: (s->mem_index >> 2) - 1);
5661: gen_helper_fildll_ST0(cpu_tmp1_i64);
1.1 root 5662: break;
5663: case 0x3f: /* fistpll */
1.1.1.7 root 5664: gen_helper_fistll_ST0(cpu_tmp1_i64);
5665: tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
5666: (s->mem_index >> 2) - 1);
5667: gen_helper_fpop();
1.1 root 5668: break;
5669: default:
5670: goto illegal_op;
5671: }
5672: } else {
5673: /* register float ops */
5674: opreg = rm;
5675:
5676: switch(op) {
5677: case 0x08: /* fld sti */
1.1.1.7 root 5678: gen_helper_fpush();
5679: gen_helper_fmov_ST0_STN(tcg_const_i32((opreg + 1) & 7));
1.1 root 5680: break;
5681: case 0x09: /* fxchg sti */
5682: case 0x29: /* fxchg4 sti, undocumented op */
5683: case 0x39: /* fxchg7 sti, undocumented op */
1.1.1.7 root 5684: gen_helper_fxchg_ST0_STN(tcg_const_i32(opreg));
1.1 root 5685: break;
5686: case 0x0a: /* grp d9/2 */
5687: switch(rm) {
5688: case 0: /* fnop */
5689: /* check exceptions (FreeBSD FPU probe) */
5690: if (s->cc_op != CC_OP_DYNAMIC)
5691: gen_op_set_cc_op(s->cc_op);
5692: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 5693: gen_helper_fwait();
1.1 root 5694: break;
5695: default:
5696: goto illegal_op;
5697: }
5698: break;
5699: case 0x0c: /* grp d9/4 */
5700: switch(rm) {
5701: case 0: /* fchs */
1.1.1.7 root 5702: gen_helper_fchs_ST0();
1.1 root 5703: break;
5704: case 1: /* fabs */
1.1.1.7 root 5705: gen_helper_fabs_ST0();
1.1 root 5706: break;
5707: case 4: /* ftst */
1.1.1.7 root 5708: gen_helper_fldz_FT0();
5709: gen_helper_fcom_ST0_FT0();
1.1 root 5710: break;
5711: case 5: /* fxam */
1.1.1.7 root 5712: gen_helper_fxam_ST0();
1.1 root 5713: break;
5714: default:
5715: goto illegal_op;
5716: }
5717: break;
5718: case 0x0d: /* grp d9/5 */
5719: {
5720: switch(rm) {
5721: case 0:
1.1.1.7 root 5722: gen_helper_fpush();
5723: gen_helper_fld1_ST0();
1.1 root 5724: break;
5725: case 1:
1.1.1.7 root 5726: gen_helper_fpush();
5727: gen_helper_fldl2t_ST0();
1.1 root 5728: break;
5729: case 2:
1.1.1.7 root 5730: gen_helper_fpush();
5731: gen_helper_fldl2e_ST0();
1.1 root 5732: break;
5733: case 3:
1.1.1.7 root 5734: gen_helper_fpush();
5735: gen_helper_fldpi_ST0();
1.1 root 5736: break;
5737: case 4:
1.1.1.7 root 5738: gen_helper_fpush();
5739: gen_helper_fldlg2_ST0();
1.1 root 5740: break;
5741: case 5:
1.1.1.7 root 5742: gen_helper_fpush();
5743: gen_helper_fldln2_ST0();
1.1 root 5744: break;
5745: case 6:
1.1.1.7 root 5746: gen_helper_fpush();
5747: gen_helper_fldz_ST0();
1.1 root 5748: break;
5749: default:
5750: goto illegal_op;
5751: }
5752: }
5753: break;
5754: case 0x0e: /* grp d9/6 */
5755: switch(rm) {
5756: case 0: /* f2xm1 */
1.1.1.7 root 5757: gen_helper_f2xm1();
1.1 root 5758: break;
5759: case 1: /* fyl2x */
1.1.1.7 root 5760: gen_helper_fyl2x();
1.1 root 5761: break;
5762: case 2: /* fptan */
1.1.1.7 root 5763: gen_helper_fptan();
1.1 root 5764: break;
5765: case 3: /* fpatan */
1.1.1.7 root 5766: gen_helper_fpatan();
1.1 root 5767: break;
5768: case 4: /* fxtract */
1.1.1.7 root 5769: gen_helper_fxtract();
1.1 root 5770: break;
5771: case 5: /* fprem1 */
1.1.1.7 root 5772: gen_helper_fprem1();
1.1 root 5773: break;
5774: case 6: /* fdecstp */
1.1.1.7 root 5775: gen_helper_fdecstp();
1.1 root 5776: break;
5777: default:
5778: case 7: /* fincstp */
1.1.1.7 root 5779: gen_helper_fincstp();
1.1 root 5780: break;
5781: }
5782: break;
5783: case 0x0f: /* grp d9/7 */
5784: switch(rm) {
5785: case 0: /* fprem */
1.1.1.7 root 5786: gen_helper_fprem();
1.1 root 5787: break;
5788: case 1: /* fyl2xp1 */
1.1.1.7 root 5789: gen_helper_fyl2xp1();
1.1 root 5790: break;
5791: case 2: /* fsqrt */
1.1.1.7 root 5792: gen_helper_fsqrt();
1.1 root 5793: break;
5794: case 3: /* fsincos */
1.1.1.7 root 5795: gen_helper_fsincos();
1.1 root 5796: break;
5797: case 5: /* fscale */
1.1.1.7 root 5798: gen_helper_fscale();
1.1 root 5799: break;
5800: case 4: /* frndint */
1.1.1.7 root 5801: gen_helper_frndint();
1.1 root 5802: break;
5803: case 6: /* fsin */
1.1.1.7 root 5804: gen_helper_fsin();
1.1 root 5805: break;
5806: default:
5807: case 7: /* fcos */
1.1.1.7 root 5808: gen_helper_fcos();
1.1 root 5809: break;
5810: }
5811: break;
5812: case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
5813: case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
5814: case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
5815: {
5816: int op1;
1.1.1.6 root 5817:
1.1 root 5818: op1 = op & 7;
5819: if (op >= 0x20) {
1.1.1.7 root 5820: gen_helper_fp_arith_STN_ST0(op1, opreg);
1.1 root 5821: if (op >= 0x30)
1.1.1.7 root 5822: gen_helper_fpop();
1.1 root 5823: } else {
1.1.1.7 root 5824: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5825: gen_helper_fp_arith_ST0_FT0(op1);
1.1 root 5826: }
5827: }
5828: break;
5829: case 0x02: /* fcom */
5830: case 0x22: /* fcom2, undocumented op */
1.1.1.7 root 5831: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5832: gen_helper_fcom_ST0_FT0();
1.1 root 5833: break;
5834: case 0x03: /* fcomp */
5835: case 0x23: /* fcomp3, undocumented op */
5836: case 0x32: /* fcomp5, undocumented op */
1.1.1.7 root 5837: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5838: gen_helper_fcom_ST0_FT0();
5839: gen_helper_fpop();
1.1 root 5840: break;
5841: case 0x15: /* da/5 */
5842: switch(rm) {
5843: case 1: /* fucompp */
1.1.1.7 root 5844: gen_helper_fmov_FT0_STN(tcg_const_i32(1));
5845: gen_helper_fucom_ST0_FT0();
5846: gen_helper_fpop();
5847: gen_helper_fpop();
1.1 root 5848: break;
5849: default:
5850: goto illegal_op;
5851: }
5852: break;
5853: case 0x1c:
5854: switch(rm) {
5855: case 0: /* feni (287 only, just do nop here) */
5856: break;
5857: case 1: /* fdisi (287 only, just do nop here) */
5858: break;
5859: case 2: /* fclex */
1.1.1.7 root 5860: gen_helper_fclex();
1.1 root 5861: break;
5862: case 3: /* fninit */
1.1.1.7 root 5863: gen_helper_fninit();
1.1 root 5864: break;
5865: case 4: /* fsetpm (287 only, just do nop here) */
5866: break;
5867: default:
5868: goto illegal_op;
5869: }
5870: break;
5871: case 0x1d: /* fucomi */
5872: if (s->cc_op != CC_OP_DYNAMIC)
5873: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 5874: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5875: gen_helper_fucomi_ST0_FT0();
1.1 root 5876: s->cc_op = CC_OP_EFLAGS;
5877: break;
5878: case 0x1e: /* fcomi */
5879: if (s->cc_op != CC_OP_DYNAMIC)
5880: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 5881: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5882: gen_helper_fcomi_ST0_FT0();
1.1 root 5883: s->cc_op = CC_OP_EFLAGS;
5884: break;
5885: case 0x28: /* ffree sti */
1.1.1.7 root 5886: gen_helper_ffree_STN(tcg_const_i32(opreg));
1.1.1.6 root 5887: break;
1.1 root 5888: case 0x2a: /* fst sti */
1.1.1.7 root 5889: gen_helper_fmov_STN_ST0(tcg_const_i32(opreg));
1.1 root 5890: break;
5891: case 0x2b: /* fstp sti */
5892: case 0x0b: /* fstp1 sti, undocumented op */
5893: case 0x3a: /* fstp8 sti, undocumented op */
5894: case 0x3b: /* fstp9 sti, undocumented op */
1.1.1.7 root 5895: gen_helper_fmov_STN_ST0(tcg_const_i32(opreg));
5896: gen_helper_fpop();
1.1 root 5897: break;
5898: case 0x2c: /* fucom st(i) */
1.1.1.7 root 5899: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5900: gen_helper_fucom_ST0_FT0();
1.1 root 5901: break;
5902: case 0x2d: /* fucomp st(i) */
1.1.1.7 root 5903: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5904: gen_helper_fucom_ST0_FT0();
5905: gen_helper_fpop();
1.1 root 5906: break;
5907: case 0x33: /* de/3 */
5908: switch(rm) {
5909: case 1: /* fcompp */
1.1.1.7 root 5910: gen_helper_fmov_FT0_STN(tcg_const_i32(1));
5911: gen_helper_fcom_ST0_FT0();
5912: gen_helper_fpop();
5913: gen_helper_fpop();
1.1 root 5914: break;
5915: default:
5916: goto illegal_op;
5917: }
5918: break;
5919: case 0x38: /* ffreep sti, undocumented op */
1.1.1.7 root 5920: gen_helper_ffree_STN(tcg_const_i32(opreg));
5921: gen_helper_fpop();
1.1 root 5922: break;
5923: case 0x3c: /* df/4 */
5924: switch(rm) {
5925: case 0:
1.1.1.7 root 5926: gen_helper_fnstsw(cpu_tmp2_i32);
5927: tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5928: gen_op_mov_reg_T0(OT_WORD, R_EAX);
1.1 root 5929: break;
5930: default:
5931: goto illegal_op;
5932: }
5933: break;
5934: case 0x3d: /* fucomip */
5935: if (s->cc_op != CC_OP_DYNAMIC)
5936: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 5937: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5938: gen_helper_fucomi_ST0_FT0();
5939: gen_helper_fpop();
1.1 root 5940: s->cc_op = CC_OP_EFLAGS;
5941: break;
5942: case 0x3e: /* fcomip */
5943: if (s->cc_op != CC_OP_DYNAMIC)
5944: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 5945: gen_helper_fmov_FT0_STN(tcg_const_i32(opreg));
5946: gen_helper_fcomi_ST0_FT0();
5947: gen_helper_fpop();
1.1 root 5948: s->cc_op = CC_OP_EFLAGS;
5949: break;
5950: case 0x10 ... 0x13: /* fcmovxx */
5951: case 0x18 ... 0x1b:
5952: {
1.1.1.7 root 5953: int op1, l1;
5954: static const uint8_t fcmov_cc[8] = {
1.1 root 5955: (JCC_B << 1),
5956: (JCC_Z << 1),
5957: (JCC_BE << 1),
5958: (JCC_P << 1),
5959: };
1.1.1.7 root 5960: op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
5961: l1 = gen_new_label();
5962: gen_jcc1(s, s->cc_op, op1, l1);
5963: gen_helper_fmov_ST0_STN(tcg_const_i32(opreg));
5964: gen_set_label(l1);
1.1 root 5965: }
5966: break;
5967: default:
5968: goto illegal_op;
5969: }
5970: }
5971: break;
5972: /************************/
5973: /* string ops */
5974:
5975: case 0xa4: /* movsS */
5976: case 0xa5:
5977: if ((b & 1) == 0)
5978: ot = OT_BYTE;
5979: else
5980: ot = dflag + OT_WORD;
5981:
5982: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5983: gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
5984: } else {
5985: gen_movs(s, ot);
5986: }
5987: break;
1.1.1.6 root 5988:
1.1 root 5989: case 0xaa: /* stosS */
5990: case 0xab:
5991: if ((b & 1) == 0)
5992: ot = OT_BYTE;
5993: else
5994: ot = dflag + OT_WORD;
5995:
5996: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
5997: gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
5998: } else {
5999: gen_stos(s, ot);
6000: }
6001: break;
6002: case 0xac: /* lodsS */
6003: case 0xad:
6004: if ((b & 1) == 0)
6005: ot = OT_BYTE;
6006: else
6007: ot = dflag + OT_WORD;
6008: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6009: gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6010: } else {
6011: gen_lods(s, ot);
6012: }
6013: break;
6014: case 0xae: /* scasS */
6015: case 0xaf:
6016: if ((b & 1) == 0)
6017: ot = OT_BYTE;
6018: else
6019: ot = dflag + OT_WORD;
6020: if (prefixes & PREFIX_REPNZ) {
6021: gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6022: } else if (prefixes & PREFIX_REPZ) {
6023: gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6024: } else {
6025: gen_scas(s, ot);
6026: s->cc_op = CC_OP_SUBB + ot;
6027: }
6028: break;
6029:
6030: case 0xa6: /* cmpsS */
6031: case 0xa7:
6032: if ((b & 1) == 0)
6033: ot = OT_BYTE;
6034: else
6035: ot = dflag + OT_WORD;
6036: if (prefixes & PREFIX_REPNZ) {
6037: gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6038: } else if (prefixes & PREFIX_REPZ) {
6039: gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6040: } else {
6041: gen_cmps(s, ot);
6042: s->cc_op = CC_OP_SUBB + ot;
6043: }
6044: break;
6045: case 0x6c: /* insS */
6046: case 0x6d:
6047: if ((b & 1) == 0)
6048: ot = OT_BYTE;
6049: else
6050: ot = dflag ? OT_LONG : OT_WORD;
1.1.1.7 root 6051: gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
1.1.1.6 root 6052: gen_op_andl_T0_ffff();
1.1.1.7 root 6053: gen_check_io(s, ot, pc_start - s->cs_base,
6054: SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
1.1 root 6055: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6056: gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6057: } else {
6058: gen_ins(s, ot);
1.1.1.7 root 6059: if (use_icount) {
6060: gen_jmp(s, s->pc - s->cs_base);
6061: }
1.1 root 6062: }
6063: break;
6064: case 0x6e: /* outsS */
6065: case 0x6f:
6066: if ((b & 1) == 0)
6067: ot = OT_BYTE;
6068: else
6069: ot = dflag ? OT_LONG : OT_WORD;
1.1.1.7 root 6070: gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
1.1.1.6 root 6071: gen_op_andl_T0_ffff();
1.1.1.7 root 6072: gen_check_io(s, ot, pc_start - s->cs_base,
6073: svm_is_rep(prefixes) | 4);
1.1 root 6074: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6075: gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6076: } else {
6077: gen_outs(s, ot);
1.1.1.7 root 6078: if (use_icount) {
6079: gen_jmp(s, s->pc - s->cs_base);
6080: }
1.1 root 6081: }
6082: break;
6083:
6084: /************************/
6085: /* port I/O */
1.1.1.6 root 6086:
1.1 root 6087: case 0xe4:
6088: case 0xe5:
6089: if ((b & 1) == 0)
6090: ot = OT_BYTE;
6091: else
6092: ot = dflag ? OT_LONG : OT_WORD;
6093: val = ldub_code(s->pc++);
6094: gen_op_movl_T0_im(val);
1.1.1.7 root 6095: gen_check_io(s, ot, pc_start - s->cs_base,
6096: SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6097: if (use_icount)
6098: gen_io_start();
6099: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6100: gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6101: gen_op_mov_reg_T1(ot, R_EAX);
6102: if (use_icount) {
6103: gen_io_end();
6104: gen_jmp(s, s->pc - s->cs_base);
6105: }
1.1 root 6106: break;
6107: case 0xe6:
6108: case 0xe7:
6109: if ((b & 1) == 0)
6110: ot = OT_BYTE;
6111: else
6112: ot = dflag ? OT_LONG : OT_WORD;
6113: val = ldub_code(s->pc++);
6114: gen_op_movl_T0_im(val);
1.1.1.7 root 6115: gen_check_io(s, ot, pc_start - s->cs_base,
6116: svm_is_rep(prefixes));
6117: gen_op_mov_TN_reg(ot, 1, R_EAX);
6118:
6119: if (use_icount)
6120: gen_io_start();
6121: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6122: tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6123: gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6124: if (use_icount) {
6125: gen_io_end();
6126: gen_jmp(s, s->pc - s->cs_base);
6127: }
1.1 root 6128: break;
6129: case 0xec:
6130: case 0xed:
6131: if ((b & 1) == 0)
6132: ot = OT_BYTE;
6133: else
6134: ot = dflag ? OT_LONG : OT_WORD;
1.1.1.7 root 6135: gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
1.1 root 6136: gen_op_andl_T0_ffff();
1.1.1.7 root 6137: gen_check_io(s, ot, pc_start - s->cs_base,
6138: SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
6139: if (use_icount)
6140: gen_io_start();
6141: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6142: gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
6143: gen_op_mov_reg_T1(ot, R_EAX);
6144: if (use_icount) {
6145: gen_io_end();
6146: gen_jmp(s, s->pc - s->cs_base);
6147: }
1.1 root 6148: break;
6149: case 0xee:
6150: case 0xef:
6151: if ((b & 1) == 0)
6152: ot = OT_BYTE;
6153: else
6154: ot = dflag ? OT_LONG : OT_WORD;
1.1.1.7 root 6155: gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
1.1 root 6156: gen_op_andl_T0_ffff();
1.1.1.7 root 6157: gen_check_io(s, ot, pc_start - s->cs_base,
6158: svm_is_rep(prefixes));
6159: gen_op_mov_TN_reg(ot, 1, R_EAX);
6160:
6161: if (use_icount)
6162: gen_io_start();
6163: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6164: tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
6165: gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
6166: if (use_icount) {
6167: gen_io_end();
6168: gen_jmp(s, s->pc - s->cs_base);
6169: }
1.1 root 6170: break;
6171:
6172: /************************/
6173: /* control */
6174: case 0xc2: /* ret im */
6175: val = ldsw_code(s->pc);
6176: s->pc += 2;
6177: gen_pop_T0(s);
6178: if (CODE64(s) && s->dflag)
6179: s->dflag = 2;
6180: gen_stack_update(s, val + (2 << s->dflag));
6181: if (s->dflag == 0)
6182: gen_op_andl_T0_ffff();
6183: gen_op_jmp_T0();
6184: gen_eob(s);
6185: break;
6186: case 0xc3: /* ret */
6187: gen_pop_T0(s);
6188: gen_pop_update(s);
6189: if (s->dflag == 0)
6190: gen_op_andl_T0_ffff();
6191: gen_op_jmp_T0();
6192: gen_eob(s);
6193: break;
6194: case 0xca: /* lret im */
6195: val = ldsw_code(s->pc);
6196: s->pc += 2;
6197: do_lret:
6198: if (s->pe && !s->vm86) {
6199: if (s->cc_op != CC_OP_DYNAMIC)
6200: gen_op_set_cc_op(s->cc_op);
6201: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6202: gen_helper_lret_protected(tcg_const_i32(s->dflag),
6203: tcg_const_i32(val));
1.1 root 6204: } else {
6205: gen_stack_A0(s);
6206: /* pop offset */
1.1.1.7 root 6207: gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
1.1 root 6208: if (s->dflag == 0)
6209: gen_op_andl_T0_ffff();
6210: /* NOTE: keeping EIP updated is not a problem in case of
6211: exception */
6212: gen_op_jmp_T0();
6213: /* pop selector */
6214: gen_op_addl_A0_im(2 << s->dflag);
1.1.1.7 root 6215: gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
6216: gen_op_movl_seg_T0_vm(R_CS);
1.1 root 6217: /* add stack offset */
6218: gen_stack_update(s, val + (4 << s->dflag));
6219: }
6220: gen_eob(s);
6221: break;
6222: case 0xcb: /* lret */
6223: val = 0;
6224: goto do_lret;
6225: case 0xcf: /* iret */
1.1.1.7 root 6226: gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
1.1 root 6227: if (!s->pe) {
6228: /* real mode */
1.1.1.7 root 6229: gen_helper_iret_real(tcg_const_i32(s->dflag));
1.1 root 6230: s->cc_op = CC_OP_EFLAGS;
6231: } else if (s->vm86) {
6232: if (s->iopl != 3) {
6233: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6234: } else {
1.1.1.7 root 6235: gen_helper_iret_real(tcg_const_i32(s->dflag));
1.1 root 6236: s->cc_op = CC_OP_EFLAGS;
6237: }
6238: } else {
6239: if (s->cc_op != CC_OP_DYNAMIC)
6240: gen_op_set_cc_op(s->cc_op);
6241: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6242: gen_helper_iret_protected(tcg_const_i32(s->dflag),
6243: tcg_const_i32(s->pc - s->cs_base));
1.1 root 6244: s->cc_op = CC_OP_EFLAGS;
6245: }
6246: gen_eob(s);
6247: break;
6248: case 0xe8: /* call im */
6249: {
6250: if (dflag)
6251: tval = (int32_t)insn_get(s, OT_LONG);
6252: else
6253: tval = (int16_t)insn_get(s, OT_WORD);
6254: next_eip = s->pc - s->cs_base;
6255: tval += next_eip;
6256: if (s->dflag == 0)
6257: tval &= 0xffff;
1.1.1.10 root 6258: else if(!CODE64(s))
6259: tval &= 0xffffffff;
1.1 root 6260: gen_movtl_T0_im(next_eip);
6261: gen_push_T0(s);
6262: gen_jmp(s, tval);
6263: }
6264: break;
6265: case 0x9a: /* lcall im */
6266: {
6267: unsigned int selector, offset;
1.1.1.6 root 6268:
1.1 root 6269: if (CODE64(s))
6270: goto illegal_op;
6271: ot = dflag ? OT_LONG : OT_WORD;
6272: offset = insn_get(s, ot);
6273: selector = insn_get(s, OT_WORD);
1.1.1.6 root 6274:
1.1 root 6275: gen_op_movl_T0_im(selector);
6276: gen_op_movl_T1_imu(offset);
6277: }
6278: goto do_lcall;
6279: case 0xe9: /* jmp im */
6280: if (dflag)
6281: tval = (int32_t)insn_get(s, OT_LONG);
6282: else
6283: tval = (int16_t)insn_get(s, OT_WORD);
6284: tval += s->pc - s->cs_base;
6285: if (s->dflag == 0)
6286: tval &= 0xffff;
1.1.1.7 root 6287: else if(!CODE64(s))
6288: tval &= 0xffffffff;
1.1 root 6289: gen_jmp(s, tval);
6290: break;
6291: case 0xea: /* ljmp im */
6292: {
6293: unsigned int selector, offset;
6294:
6295: if (CODE64(s))
6296: goto illegal_op;
6297: ot = dflag ? OT_LONG : OT_WORD;
6298: offset = insn_get(s, ot);
6299: selector = insn_get(s, OT_WORD);
1.1.1.6 root 6300:
1.1 root 6301: gen_op_movl_T0_im(selector);
6302: gen_op_movl_T1_imu(offset);
6303: }
6304: goto do_ljmp;
6305: case 0xeb: /* jmp Jb */
6306: tval = (int8_t)insn_get(s, OT_BYTE);
6307: tval += s->pc - s->cs_base;
6308: if (s->dflag == 0)
6309: tval &= 0xffff;
6310: gen_jmp(s, tval);
6311: break;
6312: case 0x70 ... 0x7f: /* jcc Jb */
6313: tval = (int8_t)insn_get(s, OT_BYTE);
6314: goto do_jcc;
6315: case 0x180 ... 0x18f: /* jcc Jv */
6316: if (dflag) {
6317: tval = (int32_t)insn_get(s, OT_LONG);
6318: } else {
1.1.1.6 root 6319: tval = (int16_t)insn_get(s, OT_WORD);
1.1 root 6320: }
6321: do_jcc:
6322: next_eip = s->pc - s->cs_base;
6323: tval += next_eip;
6324: if (s->dflag == 0)
6325: tval &= 0xffff;
6326: gen_jcc(s, b, tval, next_eip);
6327: break;
6328:
6329: case 0x190 ... 0x19f: /* setcc Gv */
6330: modrm = ldub_code(s->pc++);
6331: gen_setcc(s, b);
6332: gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
6333: break;
6334: case 0x140 ... 0x14f: /* cmov Gv, Ev */
1.1.1.7 root 6335: {
6336: int l1;
6337: TCGv t0;
6338:
6339: ot = dflag + OT_WORD;
6340: modrm = ldub_code(s->pc++);
6341: reg = ((modrm >> 3) & 7) | rex_r;
6342: mod = (modrm >> 6) & 3;
6343: t0 = tcg_temp_local_new();
6344: if (mod != 3) {
6345: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6346: gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
6347: } else {
6348: rm = (modrm & 7) | REX_B(s);
6349: gen_op_mov_v_reg(ot, t0, rm);
6350: }
6351: #ifdef TARGET_X86_64
6352: if (ot == OT_LONG) {
6353: /* XXX: specific Intel behaviour ? */
6354: l1 = gen_new_label();
6355: gen_jcc1(s, s->cc_op, b ^ 1, l1);
1.1.1.9 root 6356: tcg_gen_mov_tl(cpu_regs[reg], t0);
1.1.1.7 root 6357: gen_set_label(l1);
1.1.1.9 root 6358: tcg_gen_ext32u_tl(cpu_regs[reg], cpu_regs[reg]);
1.1.1.7 root 6359: } else
6360: #endif
6361: {
6362: l1 = gen_new_label();
6363: gen_jcc1(s, s->cc_op, b ^ 1, l1);
6364: gen_op_mov_reg_v(ot, reg, t0);
6365: gen_set_label(l1);
6366: }
6367: tcg_temp_free(t0);
1.1 root 6368: }
6369: break;
1.1.1.6 root 6370:
1.1 root 6371: /************************/
6372: /* flags */
6373: case 0x9c: /* pushf */
1.1.1.7 root 6374: gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
1.1 root 6375: if (s->vm86 && s->iopl != 3) {
6376: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6377: } else {
6378: if (s->cc_op != CC_OP_DYNAMIC)
6379: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6380: gen_helper_read_eflags(cpu_T[0]);
1.1 root 6381: gen_push_T0(s);
6382: }
6383: break;
6384: case 0x9d: /* popf */
1.1.1.7 root 6385: gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
1.1 root 6386: if (s->vm86 && s->iopl != 3) {
6387: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6388: } else {
6389: gen_pop_T0(s);
6390: if (s->cpl == 0) {
6391: if (s->dflag) {
1.1.1.7 root 6392: gen_helper_write_eflags(cpu_T[0],
6393: tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)));
1.1 root 6394: } else {
1.1.1.7 root 6395: gen_helper_write_eflags(cpu_T[0],
6396: tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff));
1.1 root 6397: }
6398: } else {
6399: if (s->cpl <= s->iopl) {
6400: if (s->dflag) {
1.1.1.7 root 6401: gen_helper_write_eflags(cpu_T[0],
6402: tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)));
1.1 root 6403: } else {
1.1.1.7 root 6404: gen_helper_write_eflags(cpu_T[0],
6405: tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff));
1.1 root 6406: }
6407: } else {
6408: if (s->dflag) {
1.1.1.7 root 6409: gen_helper_write_eflags(cpu_T[0],
6410: tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK)));
1.1 root 6411: } else {
1.1.1.7 root 6412: gen_helper_write_eflags(cpu_T[0],
6413: tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff));
1.1 root 6414: }
6415: }
6416: }
6417: gen_pop_update(s);
6418: s->cc_op = CC_OP_EFLAGS;
6419: /* abort translation because TF flag may change */
6420: gen_jmp_im(s->pc - s->cs_base);
6421: gen_eob(s);
6422: }
6423: break;
6424: case 0x9e: /* sahf */
1.1.1.7 root 6425: if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
1.1 root 6426: goto illegal_op;
1.1.1.7 root 6427: gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
1.1 root 6428: if (s->cc_op != CC_OP_DYNAMIC)
6429: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6430: gen_compute_eflags(cpu_cc_src);
6431: tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6432: tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6433: tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
1.1 root 6434: s->cc_op = CC_OP_EFLAGS;
6435: break;
6436: case 0x9f: /* lahf */
1.1.1.7 root 6437: if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
1.1 root 6438: goto illegal_op;
6439: if (s->cc_op != CC_OP_DYNAMIC)
6440: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6441: gen_compute_eflags(cpu_T[0]);
6442: /* Note: gen_compute_eflags() only gives the condition codes */
6443: tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 0x02);
6444: gen_op_mov_reg_T0(OT_BYTE, R_AH);
1.1 root 6445: break;
6446: case 0xf5: /* cmc */
6447: if (s->cc_op != CC_OP_DYNAMIC)
6448: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6449: gen_compute_eflags(cpu_cc_src);
6450: tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
1.1 root 6451: s->cc_op = CC_OP_EFLAGS;
6452: break;
6453: case 0xf8: /* clc */
6454: if (s->cc_op != CC_OP_DYNAMIC)
6455: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6456: gen_compute_eflags(cpu_cc_src);
6457: tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
1.1 root 6458: s->cc_op = CC_OP_EFLAGS;
6459: break;
6460: case 0xf9: /* stc */
6461: if (s->cc_op != CC_OP_DYNAMIC)
6462: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6463: gen_compute_eflags(cpu_cc_src);
6464: tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
1.1 root 6465: s->cc_op = CC_OP_EFLAGS;
6466: break;
6467: case 0xfc: /* cld */
1.1.1.7 root 6468: tcg_gen_movi_i32(cpu_tmp2_i32, 1);
1.1.1.17! root 6469: tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
1.1 root 6470: break;
6471: case 0xfd: /* std */
1.1.1.7 root 6472: tcg_gen_movi_i32(cpu_tmp2_i32, -1);
1.1.1.17! root 6473: tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
1.1 root 6474: break;
6475:
6476: /************************/
6477: /* bit operations */
6478: case 0x1ba: /* bt/bts/btr/btc Gv, im */
6479: ot = dflag + OT_WORD;
6480: modrm = ldub_code(s->pc++);
1.1.1.3 root 6481: op = (modrm >> 3) & 7;
1.1 root 6482: mod = (modrm >> 6) & 3;
6483: rm = (modrm & 7) | REX_B(s);
6484: if (mod != 3) {
6485: s->rip_offset = 1;
6486: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 6487: gen_op_ld_T0_A0(ot + s->mem_index);
1.1 root 6488: } else {
1.1.1.7 root 6489: gen_op_mov_TN_reg(ot, 0, rm);
1.1 root 6490: }
6491: /* load shift */
6492: val = ldub_code(s->pc++);
6493: gen_op_movl_T1_im(val);
6494: if (op < 4)
6495: goto illegal_op;
6496: op -= 4;
1.1.1.7 root 6497: goto bt_op;
1.1 root 6498: case 0x1a3: /* bt Gv, Ev */
6499: op = 0;
6500: goto do_btx;
6501: case 0x1ab: /* bts */
6502: op = 1;
6503: goto do_btx;
6504: case 0x1b3: /* btr */
6505: op = 2;
6506: goto do_btx;
6507: case 0x1bb: /* btc */
6508: op = 3;
6509: do_btx:
6510: ot = dflag + OT_WORD;
6511: modrm = ldub_code(s->pc++);
6512: reg = ((modrm >> 3) & 7) | rex_r;
6513: mod = (modrm >> 6) & 3;
6514: rm = (modrm & 7) | REX_B(s);
1.1.1.7 root 6515: gen_op_mov_TN_reg(OT_LONG, 1, reg);
1.1 root 6516: if (mod != 3) {
6517: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6518: /* specific case: we need to add a displacement */
1.1.1.7 root 6519: gen_exts(ot, cpu_T[1]);
6520: tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
6521: tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6522: tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
6523: gen_op_ld_T0_A0(ot + s->mem_index);
1.1 root 6524: } else {
1.1.1.7 root 6525: gen_op_mov_TN_reg(ot, 0, rm);
6526: }
6527: bt_op:
6528: tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
6529: switch(op) {
6530: case 0:
6531: tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
6532: tcg_gen_movi_tl(cpu_cc_dst, 0);
6533: break;
6534: case 1:
6535: tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6536: tcg_gen_movi_tl(cpu_tmp0, 1);
6537: tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6538: tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6539: break;
6540: case 2:
6541: tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6542: tcg_gen_movi_tl(cpu_tmp0, 1);
6543: tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6544: tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
6545: tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6546: break;
6547: default:
6548: case 3:
6549: tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6550: tcg_gen_movi_tl(cpu_tmp0, 1);
6551: tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6552: tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6553: break;
1.1 root 6554: }
6555: s->cc_op = CC_OP_SARB + ot;
6556: if (op != 0) {
6557: if (mod != 3)
1.1.1.7 root 6558: gen_op_st_T0_A0(ot + s->mem_index);
1.1 root 6559: else
1.1.1.7 root 6560: gen_op_mov_reg_T0(ot, rm);
6561: tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6562: tcg_gen_movi_tl(cpu_cc_dst, 0);
1.1 root 6563: }
6564: break;
6565: case 0x1bc: /* bsf */
6566: case 0x1bd: /* bsr */
1.1.1.7 root 6567: {
6568: int label1;
6569: TCGv t0;
6570:
6571: ot = dflag + OT_WORD;
6572: modrm = ldub_code(s->pc++);
6573: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.9 root 6574: gen_ldst_modrm(s,modrm, ot, OR_TMP0, 0);
1.1.1.7 root 6575: gen_extu(ot, cpu_T[0]);
6576: t0 = tcg_temp_local_new();
6577: tcg_gen_mov_tl(t0, cpu_T[0]);
1.1.1.9 root 6578: if ((b & 1) && (prefixes & PREFIX_REPZ) &&
6579: (s->cpuid_ext3_features & CPUID_EXT3_ABM)) {
6580: switch(ot) {
6581: case OT_WORD: gen_helper_lzcnt(cpu_T[0], t0,
6582: tcg_const_i32(16)); break;
6583: case OT_LONG: gen_helper_lzcnt(cpu_T[0], t0,
6584: tcg_const_i32(32)); break;
6585: case OT_QUAD: gen_helper_lzcnt(cpu_T[0], t0,
6586: tcg_const_i32(64)); break;
6587: }
6588: gen_op_mov_reg_T0(ot, reg);
1.1.1.7 root 6589: } else {
1.1.1.9 root 6590: label1 = gen_new_label();
6591: tcg_gen_movi_tl(cpu_cc_dst, 0);
6592: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1);
6593: if (b & 1) {
6594: gen_helper_bsr(cpu_T[0], t0);
6595: } else {
6596: gen_helper_bsf(cpu_T[0], t0);
6597: }
6598: gen_op_mov_reg_T0(ot, reg);
6599: tcg_gen_movi_tl(cpu_cc_dst, 1);
6600: gen_set_label(label1);
6601: tcg_gen_discard_tl(cpu_cc_src);
6602: s->cc_op = CC_OP_LOGICB + ot;
1.1.1.7 root 6603: }
6604: tcg_temp_free(t0);
6605: }
1.1 root 6606: break;
6607: /************************/
6608: /* bcd */
6609: case 0x27: /* daa */
6610: if (CODE64(s))
6611: goto illegal_op;
6612: if (s->cc_op != CC_OP_DYNAMIC)
6613: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6614: gen_helper_daa();
1.1 root 6615: s->cc_op = CC_OP_EFLAGS;
6616: break;
6617: case 0x2f: /* das */
6618: if (CODE64(s))
6619: goto illegal_op;
6620: if (s->cc_op != CC_OP_DYNAMIC)
6621: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6622: gen_helper_das();
1.1 root 6623: s->cc_op = CC_OP_EFLAGS;
6624: break;
6625: case 0x37: /* aaa */
6626: if (CODE64(s))
6627: goto illegal_op;
6628: if (s->cc_op != CC_OP_DYNAMIC)
6629: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6630: gen_helper_aaa();
1.1 root 6631: s->cc_op = CC_OP_EFLAGS;
6632: break;
6633: case 0x3f: /* aas */
6634: if (CODE64(s))
6635: goto illegal_op;
6636: if (s->cc_op != CC_OP_DYNAMIC)
6637: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6638: gen_helper_aas();
1.1 root 6639: s->cc_op = CC_OP_EFLAGS;
6640: break;
6641: case 0xd4: /* aam */
6642: if (CODE64(s))
6643: goto illegal_op;
6644: val = ldub_code(s->pc++);
1.1.1.6 root 6645: if (val == 0) {
6646: gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6647: } else {
1.1.1.7 root 6648: gen_helper_aam(tcg_const_i32(val));
1.1.1.6 root 6649: s->cc_op = CC_OP_LOGICB;
6650: }
1.1 root 6651: break;
6652: case 0xd5: /* aad */
6653: if (CODE64(s))
6654: goto illegal_op;
6655: val = ldub_code(s->pc++);
1.1.1.7 root 6656: gen_helper_aad(tcg_const_i32(val));
1.1 root 6657: s->cc_op = CC_OP_LOGICB;
6658: break;
6659: /************************/
6660: /* misc */
6661: case 0x90: /* nop */
6662: /* XXX: correct lock test for all insn */
1.1.1.12 root 6663: if (prefixes & PREFIX_LOCK) {
1.1 root 6664: goto illegal_op;
1.1.1.12 root 6665: }
6666: /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6667: if (REX_B(s)) {
6668: goto do_xchg_reg_eax;
6669: }
1.1.1.6 root 6670: if (prefixes & PREFIX_REPZ) {
6671: gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
6672: }
1.1 root 6673: break;
6674: case 0x9b: /* fwait */
1.1.1.6 root 6675: if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
1.1 root 6676: (HF_MP_MASK | HF_TS_MASK)) {
6677: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6678: } else {
6679: if (s->cc_op != CC_OP_DYNAMIC)
6680: gen_op_set_cc_op(s->cc_op);
6681: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6682: gen_helper_fwait();
1.1 root 6683: }
6684: break;
6685: case 0xcc: /* int3 */
6686: gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6687: break;
6688: case 0xcd: /* int N */
6689: val = ldub_code(s->pc++);
6690: if (s->vm86 && s->iopl != 3) {
1.1.1.6 root 6691: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
1.1 root 6692: } else {
6693: gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6694: }
6695: break;
6696: case 0xce: /* into */
6697: if (CODE64(s))
6698: goto illegal_op;
6699: if (s->cc_op != CC_OP_DYNAMIC)
6700: gen_op_set_cc_op(s->cc_op);
6701: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6702: gen_helper_into(tcg_const_i32(s->pc - pc_start));
1.1 root 6703: break;
1.1.1.7 root 6704: #ifdef WANT_ICEBP
1.1 root 6705: case 0xf1: /* icebp (undocumented, exits to external debugger) */
1.1.1.7 root 6706: gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
1.1 root 6707: #if 1
6708: gen_debug(s, pc_start - s->cs_base);
6709: #else
6710: /* start debug */
6711: tb_flush(cpu_single_env);
6712: cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
6713: #endif
6714: break;
1.1.1.7 root 6715: #endif
1.1 root 6716: case 0xfa: /* cli */
6717: if (!s->vm86) {
6718: if (s->cpl <= s->iopl) {
1.1.1.7 root 6719: gen_helper_cli();
1.1 root 6720: } else {
6721: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6722: }
6723: } else {
6724: if (s->iopl == 3) {
1.1.1.7 root 6725: gen_helper_cli();
1.1 root 6726: } else {
6727: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6728: }
6729: }
6730: break;
6731: case 0xfb: /* sti */
6732: if (!s->vm86) {
6733: if (s->cpl <= s->iopl) {
6734: gen_sti:
1.1.1.7 root 6735: gen_helper_sti();
1.1 root 6736: /* interruptions are enabled only the first insn after sti */
6737: /* If several instructions disable interrupts, only the
6738: _first_ does it */
6739: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
1.1.1.7 root 6740: gen_helper_set_inhibit_irq();
1.1 root 6741: /* give a chance to handle pending irqs */
6742: gen_jmp_im(s->pc - s->cs_base);
6743: gen_eob(s);
6744: } else {
6745: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6746: }
6747: } else {
6748: if (s->iopl == 3) {
6749: goto gen_sti;
6750: } else {
6751: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6752: }
6753: }
6754: break;
6755: case 0x62: /* bound */
6756: if (CODE64(s))
6757: goto illegal_op;
6758: ot = dflag ? OT_LONG : OT_WORD;
6759: modrm = ldub_code(s->pc++);
6760: reg = (modrm >> 3) & 7;
6761: mod = (modrm >> 6) & 3;
6762: if (mod == 3)
6763: goto illegal_op;
1.1.1.7 root 6764: gen_op_mov_TN_reg(ot, 0, reg);
1.1 root 6765: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6766: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6767: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1.1 root 6768: if (ot == OT_WORD)
1.1.1.7 root 6769: gen_helper_boundw(cpu_A0, cpu_tmp2_i32);
1.1 root 6770: else
1.1.1.7 root 6771: gen_helper_boundl(cpu_A0, cpu_tmp2_i32);
1.1 root 6772: break;
6773: case 0x1c8 ... 0x1cf: /* bswap reg */
6774: reg = (b & 7) | REX_B(s);
6775: #ifdef TARGET_X86_64
6776: if (dflag == 2) {
1.1.1.7 root 6777: gen_op_mov_TN_reg(OT_QUAD, 0, reg);
1.1.1.8 root 6778: tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
1.1.1.7 root 6779: gen_op_mov_reg_T0(OT_QUAD, reg);
1.1.1.6 root 6780: } else
1.1.1.8 root 6781: #endif
1.1.1.7 root 6782: {
6783: gen_op_mov_TN_reg(OT_LONG, 0, reg);
1.1.1.8 root 6784: tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
6785: tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
1.1.1.7 root 6786: gen_op_mov_reg_T0(OT_LONG, reg);
1.1 root 6787: }
6788: break;
6789: case 0xd6: /* salc */
6790: if (CODE64(s))
6791: goto illegal_op;
6792: if (s->cc_op != CC_OP_DYNAMIC)
6793: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6794: gen_compute_eflags_c(cpu_T[0]);
6795: tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
6796: gen_op_mov_reg_T0(OT_BYTE, R_EAX);
1.1 root 6797: break;
6798: case 0xe0: /* loopnz */
6799: case 0xe1: /* loopz */
6800: case 0xe2: /* loop */
6801: case 0xe3: /* jecxz */
6802: {
1.1.1.7 root 6803: int l1, l2, l3;
1.1 root 6804:
6805: tval = (int8_t)insn_get(s, OT_BYTE);
6806: next_eip = s->pc - s->cs_base;
6807: tval += next_eip;
6808: if (s->dflag == 0)
6809: tval &= 0xffff;
1.1.1.6 root 6810:
1.1 root 6811: l1 = gen_new_label();
6812: l2 = gen_new_label();
1.1.1.7 root 6813: l3 = gen_new_label();
1.1 root 6814: b &= 3;
1.1.1.7 root 6815: switch(b) {
6816: case 0: /* loopnz */
6817: case 1: /* loopz */
6818: if (s->cc_op != CC_OP_DYNAMIC)
6819: gen_op_set_cc_op(s->cc_op);
6820: gen_op_add_reg_im(s->aflag, R_ECX, -1);
6821: gen_op_jz_ecx(s->aflag, l3);
6822: gen_compute_eflags(cpu_tmp0);
6823: tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_Z);
6824: if (b == 0) {
6825: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
6826: } else {
6827: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, l1);
6828: }
6829: break;
6830: case 2: /* loop */
6831: gen_op_add_reg_im(s->aflag, R_ECX, -1);
6832: gen_op_jnz_ecx(s->aflag, l1);
6833: break;
6834: default:
6835: case 3: /* jcxz */
6836: gen_op_jz_ecx(s->aflag, l1);
6837: break;
1.1 root 6838: }
6839:
1.1.1.7 root 6840: gen_set_label(l3);
1.1 root 6841: gen_jmp_im(next_eip);
1.1.1.7 root 6842: tcg_gen_br(l2);
6843:
1.1 root 6844: gen_set_label(l1);
6845: gen_jmp_im(tval);
6846: gen_set_label(l2);
6847: gen_eob(s);
6848: }
6849: break;
6850: case 0x130: /* wrmsr */
6851: case 0x132: /* rdmsr */
6852: if (s->cpl != 0) {
6853: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6854: } else {
1.1.1.7 root 6855: if (s->cc_op != CC_OP_DYNAMIC)
6856: gen_op_set_cc_op(s->cc_op);
6857: gen_jmp_im(pc_start - s->cs_base);
1.1.1.6 root 6858: if (b & 2) {
1.1.1.7 root 6859: gen_helper_rdmsr();
1.1.1.6 root 6860: } else {
1.1.1.7 root 6861: gen_helper_wrmsr();
1.1.1.6 root 6862: }
1.1 root 6863: }
6864: break;
6865: case 0x131: /* rdtsc */
1.1.1.7 root 6866: if (s->cc_op != CC_OP_DYNAMIC)
6867: gen_op_set_cc_op(s->cc_op);
1.1 root 6868: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6869: if (use_icount)
6870: gen_io_start();
6871: gen_helper_rdtsc();
6872: if (use_icount) {
6873: gen_io_end();
6874: gen_jmp(s, s->pc - s->cs_base);
6875: }
1.1 root 6876: break;
1.1.1.6 root 6877: case 0x133: /* rdpmc */
1.1.1.7 root 6878: if (s->cc_op != CC_OP_DYNAMIC)
6879: gen_op_set_cc_op(s->cc_op);
1.1.1.6 root 6880: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6881: gen_helper_rdpmc();
1.1.1.6 root 6882: break;
1.1 root 6883: case 0x134: /* sysenter */
1.1.1.7 root 6884: /* For Intel SYSENTER is valid on 64-bit */
6885: if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
1.1 root 6886: goto illegal_op;
6887: if (!s->pe) {
6888: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6889: } else {
1.1.1.13 root 6890: gen_update_cc_op(s);
1.1 root 6891: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6892: gen_helper_sysenter();
1.1 root 6893: gen_eob(s);
6894: }
6895: break;
6896: case 0x135: /* sysexit */
1.1.1.7 root 6897: /* For Intel SYSEXIT is valid on 64-bit */
6898: if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
1.1 root 6899: goto illegal_op;
6900: if (!s->pe) {
6901: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6902: } else {
1.1.1.13 root 6903: gen_update_cc_op(s);
1.1 root 6904: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6905: gen_helper_sysexit(tcg_const_i32(dflag));
1.1 root 6906: gen_eob(s);
6907: }
6908: break;
6909: #ifdef TARGET_X86_64
6910: case 0x105: /* syscall */
6911: /* XXX: is it usable in real mode ? */
1.1.1.13 root 6912: gen_update_cc_op(s);
1.1 root 6913: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6914: gen_helper_syscall(tcg_const_i32(s->pc - pc_start));
1.1 root 6915: gen_eob(s);
6916: break;
6917: case 0x107: /* sysret */
6918: if (!s->pe) {
6919: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6920: } else {
1.1.1.13 root 6921: gen_update_cc_op(s);
1.1 root 6922: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6923: gen_helper_sysret(tcg_const_i32(s->dflag));
1.1 root 6924: /* condition codes are modified only in long mode */
6925: if (s->lma)
6926: s->cc_op = CC_OP_EFLAGS;
6927: gen_eob(s);
6928: }
6929: break;
6930: #endif
6931: case 0x1a2: /* cpuid */
1.1.1.7 root 6932: if (s->cc_op != CC_OP_DYNAMIC)
6933: gen_op_set_cc_op(s->cc_op);
6934: gen_jmp_im(pc_start - s->cs_base);
6935: gen_helper_cpuid();
1.1 root 6936: break;
6937: case 0xf4: /* hlt */
6938: if (s->cpl != 0) {
6939: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6940: } else {
6941: if (s->cc_op != CC_OP_DYNAMIC)
6942: gen_op_set_cc_op(s->cc_op);
1.1.1.7 root 6943: gen_jmp_im(pc_start - s->cs_base);
6944: gen_helper_hlt(tcg_const_i32(s->pc - pc_start));
1.1.1.13 root 6945: s->is_jmp = DISAS_TB_JUMP;
1.1 root 6946: }
6947: break;
6948: case 0x100:
6949: modrm = ldub_code(s->pc++);
6950: mod = (modrm >> 6) & 3;
6951: op = (modrm >> 3) & 7;
6952: switch(op) {
6953: case 0: /* sldt */
6954: if (!s->pe || s->vm86)
6955: goto illegal_op;
1.1.1.7 root 6956: gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
6957: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
1.1 root 6958: ot = OT_WORD;
6959: if (mod == 3)
6960: ot += s->dflag;
6961: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
6962: break;
6963: case 2: /* lldt */
6964: if (!s->pe || s->vm86)
6965: goto illegal_op;
6966: if (s->cpl != 0) {
6967: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6968: } else {
1.1.1.7 root 6969: gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
1.1 root 6970: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
6971: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6972: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6973: gen_helper_lldt(cpu_tmp2_i32);
1.1 root 6974: }
6975: break;
6976: case 1: /* str */
6977: if (!s->pe || s->vm86)
6978: goto illegal_op;
1.1.1.7 root 6979: gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
6980: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
1.1 root 6981: ot = OT_WORD;
6982: if (mod == 3)
6983: ot += s->dflag;
6984: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
6985: break;
6986: case 3: /* ltr */
6987: if (!s->pe || s->vm86)
6988: goto illegal_op;
6989: if (s->cpl != 0) {
6990: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6991: } else {
1.1.1.7 root 6992: gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
1.1 root 6993: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
6994: gen_jmp_im(pc_start - s->cs_base);
1.1.1.7 root 6995: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
6996: gen_helper_ltr(cpu_tmp2_i32);
1.1 root 6997: }
6998: break;
6999: case 4: /* verr */
7000: case 5: /* verw */
7001: if (!s->pe || s->vm86)
7002: goto illegal_op;
7003: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
7004: if (s->cc_op != CC_OP_DYNAMIC)
7005: gen_op_set_cc_op(s->cc_op);
7006: if (op == 4)
1.1.1.7 root 7007: gen_helper_verr(cpu_T[0]);
1.1 root 7008: else
1.1.1.7 root 7009: gen_helper_verw(cpu_T[0]);
1.1 root 7010: s->cc_op = CC_OP_EFLAGS;
7011: break;
7012: default:
7013: goto illegal_op;
7014: }
7015: break;
7016: case 0x101:
7017: modrm = ldub_code(s->pc++);
7018: mod = (modrm >> 6) & 3;
7019: op = (modrm >> 3) & 7;
1.1.1.4 root 7020: rm = modrm & 7;
1.1 root 7021: switch(op) {
7022: case 0: /* sgdt */
7023: if (mod == 3)
7024: goto illegal_op;
1.1.1.7 root 7025: gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
1.1 root 7026: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 7027: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
7028: gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1 root 7029: gen_add_A0_im(s, 2);
1.1.1.7 root 7030: tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
1.1 root 7031: if (!s->dflag)
7032: gen_op_andl_T0_im(0xffffff);
1.1.1.7 root 7033: gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
1.1 root 7034: break;
1.1.1.4 root 7035: case 1:
7036: if (mod == 3) {
7037: switch (rm) {
7038: case 0: /* monitor */
7039: if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7040: s->cpl != 0)
7041: goto illegal_op;
1.1.1.7 root 7042: if (s->cc_op != CC_OP_DYNAMIC)
7043: gen_op_set_cc_op(s->cc_op);
1.1.1.4 root 7044: gen_jmp_im(pc_start - s->cs_base);
7045: #ifdef TARGET_X86_64
7046: if (s->aflag == 2) {
1.1.1.7 root 7047: gen_op_movq_A0_reg(R_EAX);
1.1.1.6 root 7048: } else
1.1.1.4 root 7049: #endif
7050: {
1.1.1.7 root 7051: gen_op_movl_A0_reg(R_EAX);
1.1.1.4 root 7052: if (s->aflag == 0)
7053: gen_op_andl_A0_ffff();
7054: }
7055: gen_add_A0_ds_seg(s);
1.1.1.7 root 7056: gen_helper_monitor(cpu_A0);
1.1.1.4 root 7057: break;
7058: case 1: /* mwait */
7059: if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7060: s->cpl != 0)
7061: goto illegal_op;
1.1.1.13 root 7062: gen_update_cc_op(s);
1.1.1.7 root 7063: gen_jmp_im(pc_start - s->cs_base);
7064: gen_helper_mwait(tcg_const_i32(s->pc - pc_start));
1.1.1.4 root 7065: gen_eob(s);
7066: break;
7067: default:
7068: goto illegal_op;
7069: }
7070: } else { /* sidt */
1.1.1.7 root 7071: gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
1.1.1.4 root 7072: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 7073: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
7074: gen_op_st_T0_A0(OT_WORD + s->mem_index);
1.1.1.4 root 7075: gen_add_A0_im(s, 2);
1.1.1.7 root 7076: tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
1.1.1.4 root 7077: if (!s->dflag)
7078: gen_op_andl_T0_im(0xffffff);
1.1.1.7 root 7079: gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
1.1.1.4 root 7080: }
7081: break;
1.1 root 7082: case 2: /* lgdt */
7083: case 3: /* lidt */
1.1.1.6 root 7084: if (mod == 3) {
1.1.1.7 root 7085: if (s->cc_op != CC_OP_DYNAMIC)
7086: gen_op_set_cc_op(s->cc_op);
7087: gen_jmp_im(pc_start - s->cs_base);
1.1.1.6 root 7088: switch(rm) {
7089: case 0: /* VMRUN */
1.1.1.7 root 7090: if (!(s->flags & HF_SVME_MASK) || !s->pe)
7091: goto illegal_op;
7092: if (s->cpl != 0) {
7093: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
1.1.1.6 root 7094: break;
1.1.1.7 root 7095: } else {
7096: gen_helper_vmrun(tcg_const_i32(s->aflag),
7097: tcg_const_i32(s->pc - pc_start));
7098: tcg_gen_exit_tb(0);
1.1.1.13 root 7099: s->is_jmp = DISAS_TB_JUMP;
1.1.1.7 root 7100: }
1.1.1.6 root 7101: break;
7102: case 1: /* VMMCALL */
1.1.1.7 root 7103: if (!(s->flags & HF_SVME_MASK))
7104: goto illegal_op;
7105: gen_helper_vmmcall();
1.1.1.6 root 7106: break;
7107: case 2: /* VMLOAD */
1.1.1.7 root 7108: if (!(s->flags & HF_SVME_MASK) || !s->pe)
7109: goto illegal_op;
7110: if (s->cpl != 0) {
7111: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7112: break;
7113: } else {
7114: gen_helper_vmload(tcg_const_i32(s->aflag));
7115: }
1.1.1.6 root 7116: break;
7117: case 3: /* VMSAVE */
1.1.1.7 root 7118: if (!(s->flags & HF_SVME_MASK) || !s->pe)
7119: goto illegal_op;
7120: if (s->cpl != 0) {
7121: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7122: break;
7123: } else {
7124: gen_helper_vmsave(tcg_const_i32(s->aflag));
7125: }
1.1.1.6 root 7126: break;
7127: case 4: /* STGI */
1.1.1.7 root 7128: if ((!(s->flags & HF_SVME_MASK) &&
7129: !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7130: !s->pe)
7131: goto illegal_op;
7132: if (s->cpl != 0) {
7133: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7134: break;
7135: } else {
7136: gen_helper_stgi();
7137: }
1.1.1.6 root 7138: break;
7139: case 5: /* CLGI */
1.1.1.7 root 7140: if (!(s->flags & HF_SVME_MASK) || !s->pe)
7141: goto illegal_op;
7142: if (s->cpl != 0) {
7143: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7144: break;
7145: } else {
7146: gen_helper_clgi();
7147: }
1.1.1.6 root 7148: break;
7149: case 6: /* SKINIT */
1.1.1.7 root 7150: if ((!(s->flags & HF_SVME_MASK) &&
7151: !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7152: !s->pe)
7153: goto illegal_op;
7154: gen_helper_skinit();
1.1.1.6 root 7155: break;
7156: case 7: /* INVLPGA */
1.1.1.7 root 7157: if (!(s->flags & HF_SVME_MASK) || !s->pe)
7158: goto illegal_op;
7159: if (s->cpl != 0) {
7160: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7161: break;
7162: } else {
7163: gen_helper_invlpga(tcg_const_i32(s->aflag));
7164: }
1.1.1.6 root 7165: break;
7166: default:
7167: goto illegal_op;
7168: }
7169: } else if (s->cpl != 0) {
1.1 root 7170: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7171: } else {
1.1.1.7 root 7172: gen_svm_check_intercept(s, pc_start,
7173: op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
1.1 root 7174: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 7175: gen_op_ld_T1_A0(OT_WORD + s->mem_index);
1.1 root 7176: gen_add_A0_im(s, 2);
1.1.1.7 root 7177: gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
1.1 root 7178: if (!s->dflag)
7179: gen_op_andl_T0_im(0xffffff);
7180: if (op == 2) {
1.1.1.7 root 7181: tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7182: tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
1.1 root 7183: } else {
1.1.1.7 root 7184: tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7185: tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
1.1 root 7186: }
7187: }
7188: break;
7189: case 4: /* smsw */
1.1.1.7 root 7190: gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
1.1.1.9 root 7191: #if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
1.1.1.7 root 7192: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7193: #else
7194: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
7195: #endif
1.1 root 7196: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
7197: break;
7198: case 6: /* lmsw */
7199: if (s->cpl != 0) {
7200: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7201: } else {
1.1.1.7 root 7202: gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
1.1 root 7203: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
1.1.1.7 root 7204: gen_helper_lmsw(cpu_T[0]);
1.1 root 7205: gen_jmp_im(s->pc - s->cs_base);
7206: gen_eob(s);
7207: }
7208: break;
1.1.1.9 root 7209: case 7:
7210: if (mod != 3) { /* invlpg */
7211: if (s->cpl != 0) {
7212: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7213: } else {
7214: if (s->cc_op != CC_OP_DYNAMIC)
7215: gen_op_set_cc_op(s->cc_op);
7216: gen_jmp_im(pc_start - s->cs_base);
7217: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
7218: gen_helper_invlpg(cpu_A0);
7219: gen_jmp_im(s->pc - s->cs_base);
7220: gen_eob(s);
7221: }
1.1 root 7222: } else {
1.1.1.9 root 7223: switch (rm) {
7224: case 0: /* swapgs */
1.1 root 7225: #ifdef TARGET_X86_64
1.1.1.9 root 7226: if (CODE64(s)) {
7227: if (s->cpl != 0) {
7228: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7229: } else {
7230: tcg_gen_ld_tl(cpu_T[0], cpu_env,
7231: offsetof(CPUX86State,segs[R_GS].base));
7232: tcg_gen_ld_tl(cpu_T[1], cpu_env,
7233: offsetof(CPUX86State,kernelgsbase));
7234: tcg_gen_st_tl(cpu_T[1], cpu_env,
7235: offsetof(CPUX86State,segs[R_GS].base));
7236: tcg_gen_st_tl(cpu_T[0], cpu_env,
7237: offsetof(CPUX86State,kernelgsbase));
7238: }
1.1.1.6 root 7239: } else
1.1 root 7240: #endif
7241: {
7242: goto illegal_op;
7243: }
1.1.1.9 root 7244: break;
7245: case 1: /* rdtscp */
7246: if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7247: goto illegal_op;
1.1.1.7 root 7248: if (s->cc_op != CC_OP_DYNAMIC)
7249: gen_op_set_cc_op(s->cc_op);
7250: gen_jmp_im(pc_start - s->cs_base);
1.1.1.9 root 7251: if (use_icount)
7252: gen_io_start();
7253: gen_helper_rdtscp();
7254: if (use_icount) {
7255: gen_io_end();
7256: gen_jmp(s, s->pc - s->cs_base);
7257: }
7258: break;
7259: default:
7260: goto illegal_op;
1.1 root 7261: }
7262: }
7263: break;
7264: default:
7265: goto illegal_op;
7266: }
7267: break;
7268: case 0x108: /* invd */
7269: case 0x109: /* wbinvd */
7270: if (s->cpl != 0) {
7271: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7272: } else {
1.1.1.7 root 7273: gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
1.1 root 7274: /* nothing to do */
7275: }
7276: break;
7277: case 0x63: /* arpl or movslS (x86_64) */
7278: #ifdef TARGET_X86_64
7279: if (CODE64(s)) {
7280: int d_ot;
7281: /* d_ot is the size of destination */
7282: d_ot = dflag + OT_WORD;
7283:
7284: modrm = ldub_code(s->pc++);
7285: reg = ((modrm >> 3) & 7) | rex_r;
7286: mod = (modrm >> 6) & 3;
7287: rm = (modrm & 7) | REX_B(s);
1.1.1.6 root 7288:
1.1 root 7289: if (mod == 3) {
1.1.1.7 root 7290: gen_op_mov_TN_reg(OT_LONG, 0, rm);
1.1 root 7291: /* sign extend */
7292: if (d_ot == OT_QUAD)
1.1.1.7 root 7293: tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
7294: gen_op_mov_reg_T0(d_ot, reg);
1.1 root 7295: } else {
7296: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
7297: if (d_ot == OT_QUAD) {
1.1.1.7 root 7298: gen_op_lds_T0_A0(OT_LONG + s->mem_index);
1.1 root 7299: } else {
1.1.1.7 root 7300: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
1.1 root 7301: }
1.1.1.7 root 7302: gen_op_mov_reg_T0(d_ot, reg);
1.1 root 7303: }
1.1.1.6 root 7304: } else
1.1 root 7305: #endif
7306: {
1.1.1.7 root 7307: int label1;
1.1.1.9 root 7308: TCGv t0, t1, t2, a0;
1.1.1.7 root 7309:
1.1 root 7310: if (!s->pe || s->vm86)
7311: goto illegal_op;
1.1.1.7 root 7312: t0 = tcg_temp_local_new();
7313: t1 = tcg_temp_local_new();
7314: t2 = tcg_temp_local_new();
7315: ot = OT_WORD;
1.1 root 7316: modrm = ldub_code(s->pc++);
7317: reg = (modrm >> 3) & 7;
7318: mod = (modrm >> 6) & 3;
7319: rm = modrm & 7;
7320: if (mod != 3) {
7321: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 7322: gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
1.1.1.9 root 7323: a0 = tcg_temp_local_new();
7324: tcg_gen_mov_tl(a0, cpu_A0);
1.1 root 7325: } else {
1.1.1.7 root 7326: gen_op_mov_v_reg(ot, t0, rm);
1.1.1.9 root 7327: TCGV_UNUSED(a0);
1.1 root 7328: }
1.1.1.7 root 7329: gen_op_mov_v_reg(ot, t1, reg);
7330: tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7331: tcg_gen_andi_tl(t1, t1, 3);
7332: tcg_gen_movi_tl(t2, 0);
7333: label1 = gen_new_label();
7334: tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7335: tcg_gen_andi_tl(t0, t0, ~3);
7336: tcg_gen_or_tl(t0, t0, t1);
7337: tcg_gen_movi_tl(t2, CC_Z);
7338: gen_set_label(label1);
1.1 root 7339: if (mod != 3) {
1.1.1.9 root 7340: gen_op_st_v(ot + s->mem_index, t0, a0);
7341: tcg_temp_free(a0);
7342: } else {
1.1.1.7 root 7343: gen_op_mov_reg_v(ot, rm, t0);
1.1 root 7344: }
1.1.1.7 root 7345: if (s->cc_op != CC_OP_DYNAMIC)
7346: gen_op_set_cc_op(s->cc_op);
7347: gen_compute_eflags(cpu_cc_src);
7348: tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
7349: tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
7350: s->cc_op = CC_OP_EFLAGS;
7351: tcg_temp_free(t0);
7352: tcg_temp_free(t1);
7353: tcg_temp_free(t2);
1.1 root 7354: }
7355: break;
7356: case 0x102: /* lar */
7357: case 0x103: /* lsl */
1.1.1.7 root 7358: {
7359: int label1;
7360: TCGv t0;
7361: if (!s->pe || s->vm86)
7362: goto illegal_op;
7363: ot = dflag ? OT_LONG : OT_WORD;
7364: modrm = ldub_code(s->pc++);
7365: reg = ((modrm >> 3) & 7) | rex_r;
7366: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
7367: t0 = tcg_temp_local_new();
7368: if (s->cc_op != CC_OP_DYNAMIC)
7369: gen_op_set_cc_op(s->cc_op);
7370: if (b == 0x102)
7371: gen_helper_lar(t0, cpu_T[0]);
7372: else
7373: gen_helper_lsl(t0, cpu_T[0]);
7374: tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7375: label1 = gen_new_label();
7376: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
7377: gen_op_mov_reg_v(ot, reg, t0);
7378: gen_set_label(label1);
7379: s->cc_op = CC_OP_EFLAGS;
7380: tcg_temp_free(t0);
7381: }
1.1 root 7382: break;
7383: case 0x118:
7384: modrm = ldub_code(s->pc++);
7385: mod = (modrm >> 6) & 3;
7386: op = (modrm >> 3) & 7;
7387: switch(op) {
7388: case 0: /* prefetchnta */
7389: case 1: /* prefetchnt0 */
7390: case 2: /* prefetchnt0 */
7391: case 3: /* prefetchnt0 */
7392: if (mod == 3)
7393: goto illegal_op;
7394: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
7395: /* nothing more to do */
7396: break;
1.1.1.5 root 7397: default: /* nop (multi byte) */
7398: gen_nop_modrm(s, modrm);
7399: break;
1.1 root 7400: }
7401: break;
1.1.1.5 root 7402: case 0x119 ... 0x11f: /* nop (multi byte) */
7403: modrm = ldub_code(s->pc++);
7404: gen_nop_modrm(s, modrm);
7405: break;
1.1 root 7406: case 0x120: /* mov reg, crN */
7407: case 0x122: /* mov crN, reg */
7408: if (s->cpl != 0) {
7409: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7410: } else {
7411: modrm = ldub_code(s->pc++);
7412: if ((modrm & 0xc0) != 0xc0)
7413: goto illegal_op;
7414: rm = (modrm & 7) | REX_B(s);
7415: reg = ((modrm >> 3) & 7) | rex_r;
7416: if (CODE64(s))
7417: ot = OT_QUAD;
7418: else
7419: ot = OT_LONG;
1.1.1.9 root 7420: if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7421: (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7422: reg = 8;
7423: }
1.1 root 7424: switch(reg) {
7425: case 0:
7426: case 2:
7427: case 3:
7428: case 4:
7429: case 8:
1.1.1.7 root 7430: if (s->cc_op != CC_OP_DYNAMIC)
7431: gen_op_set_cc_op(s->cc_op);
7432: gen_jmp_im(pc_start - s->cs_base);
1.1 root 7433: if (b & 2) {
1.1.1.7 root 7434: gen_op_mov_TN_reg(ot, 0, rm);
7435: gen_helper_write_crN(tcg_const_i32(reg), cpu_T[0]);
1.1 root 7436: gen_jmp_im(s->pc - s->cs_base);
7437: gen_eob(s);
7438: } else {
1.1.1.7 root 7439: gen_helper_read_crN(cpu_T[0], tcg_const_i32(reg));
7440: gen_op_mov_reg_T0(ot, rm);
1.1 root 7441: }
7442: break;
7443: default:
7444: goto illegal_op;
7445: }
7446: }
7447: break;
7448: case 0x121: /* mov reg, drN */
7449: case 0x123: /* mov drN, reg */
7450: if (s->cpl != 0) {
7451: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7452: } else {
7453: modrm = ldub_code(s->pc++);
7454: if ((modrm & 0xc0) != 0xc0)
7455: goto illegal_op;
7456: rm = (modrm & 7) | REX_B(s);
7457: reg = ((modrm >> 3) & 7) | rex_r;
7458: if (CODE64(s))
7459: ot = OT_QUAD;
7460: else
7461: ot = OT_LONG;
7462: /* XXX: do it dynamically with CR4.DE bit */
7463: if (reg == 4 || reg == 5 || reg >= 8)
7464: goto illegal_op;
7465: if (b & 2) {
1.1.1.6 root 7466: gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
1.1.1.7 root 7467: gen_op_mov_TN_reg(ot, 0, rm);
7468: gen_helper_movl_drN_T0(tcg_const_i32(reg), cpu_T[0]);
1.1 root 7469: gen_jmp_im(s->pc - s->cs_base);
7470: gen_eob(s);
7471: } else {
1.1.1.6 root 7472: gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
1.1.1.7 root 7473: tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
7474: gen_op_mov_reg_T0(ot, rm);
1.1 root 7475: }
7476: }
7477: break;
7478: case 0x106: /* clts */
7479: if (s->cpl != 0) {
7480: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7481: } else {
1.1.1.6 root 7482: gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
1.1.1.7 root 7483: gen_helper_clts();
1.1 root 7484: /* abort block because static cpu state changed */
7485: gen_jmp_im(s->pc - s->cs_base);
7486: gen_eob(s);
7487: }
7488: break;
1.1.1.7 root 7489: /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
1.1 root 7490: case 0x1c3: /* MOVNTI reg, mem */
7491: if (!(s->cpuid_features & CPUID_SSE2))
7492: goto illegal_op;
7493: ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
7494: modrm = ldub_code(s->pc++);
7495: mod = (modrm >> 6) & 3;
7496: if (mod == 3)
7497: goto illegal_op;
7498: reg = ((modrm >> 3) & 7) | rex_r;
7499: /* generate a generic store */
7500: gen_ldst_modrm(s, modrm, ot, reg, 1);
7501: break;
7502: case 0x1ae:
7503: modrm = ldub_code(s->pc++);
7504: mod = (modrm >> 6) & 3;
7505: op = (modrm >> 3) & 7;
7506: switch(op) {
7507: case 0: /* fxsave */
1.1.1.6 root 7508: if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
1.1.1.9 root 7509: (s->prefix & PREFIX_LOCK))
1.1 root 7510: goto illegal_op;
1.1.1.9 root 7511: if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
1.1.1.3 root 7512: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7513: break;
7514: }
1.1 root 7515: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 7516: if (s->cc_op != CC_OP_DYNAMIC)
7517: gen_op_set_cc_op(s->cc_op);
7518: gen_jmp_im(pc_start - s->cs_base);
7519: gen_helper_fxsave(cpu_A0, tcg_const_i32((s->dflag == 2)));
1.1 root 7520: break;
7521: case 1: /* fxrstor */
1.1.1.6 root 7522: if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
1.1.1.9 root 7523: (s->prefix & PREFIX_LOCK))
1.1 root 7524: goto illegal_op;
1.1.1.9 root 7525: if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
1.1.1.3 root 7526: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7527: break;
7528: }
1.1 root 7529: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.7 root 7530: if (s->cc_op != CC_OP_DYNAMIC)
7531: gen_op_set_cc_op(s->cc_op);
7532: gen_jmp_im(pc_start - s->cs_base);
7533: gen_helper_fxrstor(cpu_A0, tcg_const_i32((s->dflag == 2)));
1.1 root 7534: break;
7535: case 2: /* ldmxcsr */
7536: case 3: /* stmxcsr */
7537: if (s->flags & HF_TS_MASK) {
7538: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7539: break;
7540: }
7541: if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7542: mod == 3)
7543: goto illegal_op;
7544: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
7545: if (op == 2) {
1.1.1.7 root 7546: gen_op_ld_T0_A0(OT_LONG + s->mem_index);
1.1.1.17! root 7547: tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
! 7548: gen_helper_ldmxcsr(cpu_tmp2_i32);
1.1 root 7549: } else {
1.1.1.7 root 7550: tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
7551: gen_op_st_T0_A0(OT_LONG + s->mem_index);
1.1 root 7552: }
7553: break;
7554: case 5: /* lfence */
7555: case 6: /* mfence */
1.1.1.15 root 7556: if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
1.1 root 7557: goto illegal_op;
7558: break;
7559: case 7: /* sfence / clflush */
7560: if ((modrm & 0xc7) == 0xc0) {
7561: /* sfence */
1.1.1.7 root 7562: /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
1.1 root 7563: if (!(s->cpuid_features & CPUID_SSE))
7564: goto illegal_op;
7565: } else {
7566: /* clflush */
7567: if (!(s->cpuid_features & CPUID_CLFLUSH))
7568: goto illegal_op;
7569: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
7570: }
7571: break;
7572: default:
7573: goto illegal_op;
7574: }
7575: break;
1.1.1.7 root 7576: case 0x10d: /* 3DNow! prefetch(w) */
1.1 root 7577: modrm = ldub_code(s->pc++);
1.1.1.7 root 7578: mod = (modrm >> 6) & 3;
7579: if (mod == 3)
7580: goto illegal_op;
1.1 root 7581: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
7582: /* ignore for now */
7583: break;
1.1.1.5 root 7584: case 0x1aa: /* rsm */
1.1.1.7 root 7585: gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
1.1.1.5 root 7586: if (!(s->flags & HF_SMM_MASK))
7587: goto illegal_op;
1.1.1.13 root 7588: gen_update_cc_op(s);
1.1.1.5 root 7589: gen_jmp_im(s->pc - s->cs_base);
1.1.1.7 root 7590: gen_helper_rsm();
1.1.1.5 root 7591: gen_eob(s);
7592: break;
1.1.1.7 root 7593: case 0x1b8: /* SSE4.2 popcnt */
7594: if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
7595: PREFIX_REPZ)
7596: goto illegal_op;
7597: if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
7598: goto illegal_op;
7599:
7600: modrm = ldub_code(s->pc++);
7601: reg = ((modrm >> 3) & 7);
7602:
7603: if (s->prefix & PREFIX_DATA)
7604: ot = OT_WORD;
7605: else if (s->dflag != 2)
7606: ot = OT_LONG;
7607: else
7608: ot = OT_QUAD;
7609:
7610: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
7611: gen_helper_popcnt(cpu_T[0], cpu_T[0], tcg_const_i32(ot));
7612: gen_op_mov_reg_T0(ot, reg);
7613:
7614: s->cc_op = CC_OP_EFLAGS;
7615: break;
7616: case 0x10e ... 0x10f:
7617: /* 3DNow! instructions, ignore prefixes */
7618: s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
1.1 root 7619: case 0x110 ... 0x117:
7620: case 0x128 ... 0x12f:
1.1.1.7 root 7621: case 0x138 ... 0x13a:
1.1.1.9 root 7622: case 0x150 ... 0x179:
1.1 root 7623: case 0x17c ... 0x17f:
7624: case 0x1c2:
7625: case 0x1c4 ... 0x1c6:
7626: case 0x1d0 ... 0x1fe:
7627: gen_sse(s, b, pc_start, rex_r);
7628: break;
7629: default:
7630: goto illegal_op;
7631: }
7632: /* lock generation */
7633: if (s->prefix & PREFIX_LOCK)
1.1.1.7 root 7634: gen_helper_unlock();
1.1 root 7635: return s->pc;
7636: illegal_op:
7637: if (s->prefix & PREFIX_LOCK)
1.1.1.7 root 7638: gen_helper_unlock();
1.1 root 7639: /* XXX: ensure that no lock was generated */
7640: gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7641: return s->pc;
7642: }
7643:
7644: void optimize_flags_init(void)
7645: {
1.1.1.7 root 7646: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7647: cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7648: offsetof(CPUX86State, cc_op), "cc_op");
! 7649: cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
1.1.1.7 root 7650: "cc_src");
1.1.1.17! root 7651: cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
1.1.1.7 root 7652: "cc_dst");
1.1.1.17! root 7653: cpu_cc_tmp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_tmp),
1.1.1.7 root 7654: "cc_tmp");
7655:
1.1.1.9 root 7656: #ifdef TARGET_X86_64
7657: cpu_regs[R_EAX] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7658: offsetof(CPUX86State, regs[R_EAX]), "rax");
1.1.1.9 root 7659: cpu_regs[R_ECX] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7660: offsetof(CPUX86State, regs[R_ECX]), "rcx");
1.1.1.9 root 7661: cpu_regs[R_EDX] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7662: offsetof(CPUX86State, regs[R_EDX]), "rdx");
1.1.1.9 root 7663: cpu_regs[R_EBX] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7664: offsetof(CPUX86State, regs[R_EBX]), "rbx");
1.1.1.9 root 7665: cpu_regs[R_ESP] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7666: offsetof(CPUX86State, regs[R_ESP]), "rsp");
1.1.1.9 root 7667: cpu_regs[R_EBP] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7668: offsetof(CPUX86State, regs[R_EBP]), "rbp");
1.1.1.9 root 7669: cpu_regs[R_ESI] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7670: offsetof(CPUX86State, regs[R_ESI]), "rsi");
1.1.1.9 root 7671: cpu_regs[R_EDI] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7672: offsetof(CPUX86State, regs[R_EDI]), "rdi");
1.1.1.9 root 7673: cpu_regs[8] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7674: offsetof(CPUX86State, regs[8]), "r8");
1.1.1.9 root 7675: cpu_regs[9] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7676: offsetof(CPUX86State, regs[9]), "r9");
1.1.1.9 root 7677: cpu_regs[10] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7678: offsetof(CPUX86State, regs[10]), "r10");
1.1.1.9 root 7679: cpu_regs[11] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7680: offsetof(CPUX86State, regs[11]), "r11");
1.1.1.9 root 7681: cpu_regs[12] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7682: offsetof(CPUX86State, regs[12]), "r12");
1.1.1.9 root 7683: cpu_regs[13] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7684: offsetof(CPUX86State, regs[13]), "r13");
1.1.1.9 root 7685: cpu_regs[14] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7686: offsetof(CPUX86State, regs[14]), "r14");
1.1.1.9 root 7687: cpu_regs[15] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.17! root 7688: offsetof(CPUX86State, regs[15]), "r15");
1.1.1.9 root 7689: #else
7690: cpu_regs[R_EAX] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7691: offsetof(CPUX86State, regs[R_EAX]), "eax");
1.1.1.9 root 7692: cpu_regs[R_ECX] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7693: offsetof(CPUX86State, regs[R_ECX]), "ecx");
1.1.1.9 root 7694: cpu_regs[R_EDX] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7695: offsetof(CPUX86State, regs[R_EDX]), "edx");
1.1.1.9 root 7696: cpu_regs[R_EBX] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7697: offsetof(CPUX86State, regs[R_EBX]), "ebx");
1.1.1.9 root 7698: cpu_regs[R_ESP] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7699: offsetof(CPUX86State, regs[R_ESP]), "esp");
1.1.1.9 root 7700: cpu_regs[R_EBP] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7701: offsetof(CPUX86State, regs[R_EBP]), "ebp");
1.1.1.9 root 7702: cpu_regs[R_ESI] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7703: offsetof(CPUX86State, regs[R_ESI]), "esi");
1.1.1.9 root 7704: cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.17! root 7705: offsetof(CPUX86State, regs[R_EDI]), "edi");
1.1.1.9 root 7706: #endif
7707:
1.1.1.7 root 7708: /* register helpers */
7709: #define GEN_HELPER 2
7710: #include "helper.h"
1.1 root 7711: }
7712:
7713: /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7714: basic block 'tb'. If search_pc is TRUE, also generate PC
7715: information for each intermediate instruction. */
1.1.1.17! root 7716: static inline void gen_intermediate_code_internal(CPUX86State *env,
1.1.1.7 root 7717: TranslationBlock *tb,
7718: int search_pc)
1.1 root 7719: {
7720: DisasContext dc1, *dc = &dc1;
7721: target_ulong pc_ptr;
7722: uint16_t *gen_opc_end;
1.1.1.7 root 7723: CPUBreakpoint *bp;
1.1.1.13 root 7724: int j, lj;
1.1.1.6 root 7725: uint64_t flags;
1.1 root 7726: target_ulong pc_start;
7727: target_ulong cs_base;
1.1.1.7 root 7728: int num_insns;
7729: int max_insns;
1.1.1.6 root 7730:
1.1 root 7731: /* generate intermediate code */
7732: pc_start = tb->pc;
7733: cs_base = tb->cs_base;
7734: flags = tb->flags;
7735:
7736: dc->pe = (flags >> HF_PE_SHIFT) & 1;
7737: dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7738: dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7739: dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7740: dc->f_st = 0;
7741: dc->vm86 = (flags >> VM_SHIFT) & 1;
7742: dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7743: dc->iopl = (flags >> IOPL_SHIFT) & 3;
7744: dc->tf = (flags >> TF_SHIFT) & 1;
7745: dc->singlestep_enabled = env->singlestep_enabled;
7746: dc->cc_op = CC_OP_DYNAMIC;
7747: dc->cs_base = cs_base;
7748: dc->tb = tb;
7749: dc->popl_esp_hack = 0;
7750: /* select memory access functions */
7751: dc->mem_index = 0;
7752: if (flags & HF_SOFTMMU_MASK) {
7753: if (dc->cpl == 3)
7754: dc->mem_index = 2 * 4;
7755: else
7756: dc->mem_index = 1 * 4;
7757: }
7758: dc->cpuid_features = env->cpuid_features;
1.1.1.4 root 7759: dc->cpuid_ext_features = env->cpuid_ext_features;
1.1.1.7 root 7760: dc->cpuid_ext2_features = env->cpuid_ext2_features;
7761: dc->cpuid_ext3_features = env->cpuid_ext3_features;
1.1 root 7762: #ifdef TARGET_X86_64
7763: dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7764: dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7765: #endif
7766: dc->flags = flags;
7767: dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
7768: (flags & HF_INHIBIT_IRQ_MASK)
7769: #ifndef CONFIG_SOFTMMU
7770: || (flags & HF_SOFTMMU_MASK)
7771: #endif
7772: );
7773: #if 0
7774: /* check addseg logic */
7775: if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
7776: printf("ERROR addseg\n");
7777: #endif
7778:
1.1.1.7 root 7779: cpu_T[0] = tcg_temp_new();
7780: cpu_T[1] = tcg_temp_new();
7781: cpu_A0 = tcg_temp_new();
7782: cpu_T3 = tcg_temp_new();
7783:
7784: cpu_tmp0 = tcg_temp_new();
7785: cpu_tmp1_i64 = tcg_temp_new_i64();
7786: cpu_tmp2_i32 = tcg_temp_new_i32();
7787: cpu_tmp3_i32 = tcg_temp_new_i32();
7788: cpu_tmp4 = tcg_temp_new();
7789: cpu_tmp5 = tcg_temp_new();
7790: cpu_ptr0 = tcg_temp_new_ptr();
7791: cpu_ptr1 = tcg_temp_new_ptr();
7792:
1.1 root 7793: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7794:
7795: dc->is_jmp = DISAS_NEXT;
7796: pc_ptr = pc_start;
7797: lj = -1;
1.1.1.7 root 7798: num_insns = 0;
7799: max_insns = tb->cflags & CF_COUNT_MASK;
7800: if (max_insns == 0)
7801: max_insns = CF_COUNT_MASK;
1.1 root 7802:
1.1.1.7 root 7803: gen_icount_start();
1.1 root 7804: for(;;) {
1.1.1.9 root 7805: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
7806: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.8 root 7807: if (bp->pc == pc_ptr &&
7808: !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
1.1 root 7809: gen_debug(dc, pc_ptr - dc->cs_base);
7810: break;
7811: }
7812: }
7813: }
7814: if (search_pc) {
7815: j = gen_opc_ptr - gen_opc_buf;
7816: if (lj < j) {
7817: lj++;
7818: while (lj < j)
7819: gen_opc_instr_start[lj++] = 0;
7820: }
7821: gen_opc_pc[lj] = pc_ptr;
7822: gen_opc_cc_op[lj] = dc->cc_op;
7823: gen_opc_instr_start[lj] = 1;
1.1.1.7 root 7824: gen_opc_icount[lj] = num_insns;
1.1 root 7825: }
1.1.1.7 root 7826: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
7827: gen_io_start();
7828:
1.1 root 7829: pc_ptr = disas_insn(dc, pc_ptr);
1.1.1.7 root 7830: num_insns++;
1.1 root 7831: /* stop translation if indicated */
7832: if (dc->is_jmp)
7833: break;
7834: /* if single step mode, we generate only one instruction and
7835: generate an exception */
7836: /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
7837: the flag and abort the translation to give the irqs a
7838: change to be happen */
1.1.1.6 root 7839: if (dc->tf || dc->singlestep_enabled ||
1.1.1.7 root 7840: (flags & HF_INHIBIT_IRQ_MASK)) {
1.1 root 7841: gen_jmp_im(pc_ptr - dc->cs_base);
7842: gen_eob(dc);
7843: break;
7844: }
7845: /* if too long translation, stop generation too */
7846: if (gen_opc_ptr >= gen_opc_end ||
1.1.1.7 root 7847: (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
7848: num_insns >= max_insns) {
1.1 root 7849: gen_jmp_im(pc_ptr - dc->cs_base);
7850: gen_eob(dc);
7851: break;
7852: }
1.1.1.8 root 7853: if (singlestep) {
7854: gen_jmp_im(pc_ptr - dc->cs_base);
7855: gen_eob(dc);
7856: break;
7857: }
1.1 root 7858: }
1.1.1.7 root 7859: if (tb->cflags & CF_LAST_IO)
7860: gen_io_end();
7861: gen_icount_end(tb, num_insns);
1.1 root 7862: *gen_opc_ptr = INDEX_op_end;
7863: /* we don't forget to fill the last values */
7864: if (search_pc) {
7865: j = gen_opc_ptr - gen_opc_buf;
7866: lj++;
7867: while (lj <= j)
7868: gen_opc_instr_start[lj++] = 0;
7869: }
1.1.1.6 root 7870:
1.1 root 7871: #ifdef DEBUG_DISAS
1.1.1.7 root 7872: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1.1 root 7873: int disas_flags;
1.1.1.7 root 7874: qemu_log("----------------\n");
7875: qemu_log("IN: %s\n", lookup_symbol(pc_start));
1.1 root 7876: #ifdef TARGET_X86_64
7877: if (dc->code64)
7878: disas_flags = 2;
7879: else
7880: #endif
7881: disas_flags = !dc->code32;
1.1.1.7 root 7882: log_target_disas(pc_start, pc_ptr - pc_start, disas_flags);
7883: qemu_log("\n");
1.1 root 7884: }
7885: #endif
7886:
1.1.1.7 root 7887: if (!search_pc) {
1.1 root 7888: tb->size = pc_ptr - pc_start;
1.1.1.7 root 7889: tb->icount = num_insns;
7890: }
1.1 root 7891: }
7892:
1.1.1.17! root 7893: void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
1.1 root 7894: {
1.1.1.7 root 7895: gen_intermediate_code_internal(env, tb, 0);
1.1 root 7896: }
7897:
1.1.1.17! root 7898: void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
1.1 root 7899: {
1.1.1.7 root 7900: gen_intermediate_code_internal(env, tb, 1);
1.1 root 7901: }
7902:
1.1.1.17! root 7903: void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
1.1.1.7 root 7904: {
7905: int cc_op;
7906: #ifdef DEBUG_DISAS
7907: if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
7908: int i;
7909: qemu_log("RESTORE:\n");
7910: for(i = 0;i <= pc_pos; i++) {
7911: if (gen_opc_instr_start[i]) {
7912: qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
7913: }
7914: }
1.1.1.15 root 7915: qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
7916: pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
1.1.1.7 root 7917: (uint32_t)tb->cs_base);
7918: }
7919: #endif
7920: env->eip = gen_opc_pc[pc_pos] - tb->cs_base;
7921: cc_op = gen_opc_cc_op[pc_pos];
7922: if (cc_op != CC_OP_DYNAMIC)
7923: env->cc_op = cc_op;
7924: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.