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