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