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