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