|
|
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
17: * License along with this library; if not, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19: */
20: #include <stdarg.h>
21: #include <stdlib.h>
22: #include <stdio.h>
23: #include <string.h>
24: #include <inttypes.h>
25: #include <signal.h>
26: #include <assert.h>
27:
28: #include "cpu.h"
29: #include "exec-all.h"
30: #include "disas.h"
31:
32: /* XXX: move that elsewhere */
33: static uint16_t *gen_opc_ptr;
34: static uint32_t *gen_opparam_ptr;
35:
36: #define PREFIX_REPZ 0x01
37: #define PREFIX_REPNZ 0x02
38: #define PREFIX_LOCK 0x04
39: #define PREFIX_DATA 0x08
40: #define PREFIX_ADR 0x10
41:
42: #ifdef TARGET_X86_64
43: #define X86_64_ONLY(x) x
44: #define X86_64_DEF(x...) x
45: #define CODE64(s) ((s)->code64)
46: #define REX_X(s) ((s)->rex_x)
47: #define REX_B(s) ((s)->rex_b)
48: /* XXX: gcc generates push/pop in some opcodes, so we cannot use them */
49: #if 1
50: #define BUGGY_64(x) NULL
51: #endif
52: #else
53: #define X86_64_ONLY(x) NULL
54: #define X86_64_DEF(x...)
55: #define CODE64(s) 0
56: #define REX_X(s) 0
57: #define REX_B(s) 0
58: #endif
59:
60: #ifdef TARGET_X86_64
61: static int x86_64_hregs;
62: #endif
63:
64: #ifdef USE_DIRECT_JUMP
65: #define TBPARAM(x)
66: #else
67: #define TBPARAM(x) (long)(x)
68: #endif
69:
70: typedef struct DisasContext {
71: /* current insn context */
72: int override; /* -1 if no override */
73: int prefix;
74: int aflag, dflag;
75: target_ulong pc; /* pc = eip + cs_base */
76: int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
77: static state change (stop translation) */
78: /* current block context */
79: target_ulong cs_base; /* base of CS segment */
80: int pe; /* protected mode */
81: int code32; /* 32 bit code segment */
82: #ifdef TARGET_X86_64
83: int lma; /* long mode active */
84: int code64; /* 64 bit code segment */
85: int rex_x, rex_b;
86: #endif
87: int ss32; /* 32 bit stack segment */
88: int cc_op; /* current CC operation */
89: int addseg; /* non zero if either DS/ES/SS have a non zero base */
90: int f_st; /* currently unused */
91: int vm86; /* vm86 mode */
92: int cpl;
93: int iopl;
94: int tf; /* TF cpu flag */
95: int singlestep_enabled; /* "hardware" single step enabled */
96: int jmp_opt; /* use direct block chaining for direct jumps */
97: int mem_index; /* select memory access functions */
1.1.1.6 ! root 98: uint64_t flags; /* all execution flags */
1.1 root 99: struct TranslationBlock *tb;
100: int popl_esp_hack; /* for correct popl with esp base handling */
101: int rip_offset; /* only used in x86_64, but left for simplicity */
102: int cpuid_features;
1.1.1.4 root 103: int cpuid_ext_features;
1.1 root 104: } DisasContext;
105:
106: static void gen_eob(DisasContext *s);
107: static void gen_jmp(DisasContext *s, target_ulong eip);
108: static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
109:
110: /* i386 arith/logic operations */
111: enum {
1.1.1.6 ! root 112: OP_ADDL,
! 113: OP_ORL,
! 114: OP_ADCL,
1.1 root 115: OP_SBBL,
1.1.1.6 ! root 116: OP_ANDL,
! 117: OP_SUBL,
! 118: OP_XORL,
1.1 root 119: OP_CMPL,
120: };
121:
122: /* i386 shift ops */
123: enum {
1.1.1.6 ! root 124: OP_ROL,
! 125: OP_ROR,
! 126: OP_RCL,
! 127: OP_RCR,
! 128: OP_SHL,
! 129: OP_SHR,
1.1 root 130: OP_SHL1, /* undocumented */
131: OP_SAR = 7,
132: };
133:
134: enum {
135: #define DEF(s, n, copy_size) INDEX_op_ ## s,
136: #include "opc.h"
137: #undef DEF
138: NB_OPS,
139: };
140:
141: #include "gen-op.h"
142:
143: /* operand size */
144: enum {
145: OT_BYTE = 0,
146: OT_WORD,
1.1.1.6 ! root 147: OT_LONG,
1.1 root 148: OT_QUAD,
149: };
150:
151: enum {
152: /* I386 int registers */
153: OR_EAX, /* MUST be even numbered */
154: OR_ECX,
155: OR_EDX,
156: OR_EBX,
157: OR_ESP,
158: OR_EBP,
159: OR_ESI,
160: OR_EDI,
161:
162: OR_TMP0 = 16, /* temporary operand register */
163: OR_TMP1,
164: OR_A0, /* temporary register used when doing address evaluation */
165: };
166:
167: #ifdef TARGET_X86_64
168:
169: #define NB_OP_SIZES 4
170:
171: #define DEF_REGS(prefix, suffix) \
172: prefix ## EAX ## suffix,\
173: prefix ## ECX ## suffix,\
174: prefix ## EDX ## suffix,\
175: prefix ## EBX ## suffix,\
176: prefix ## ESP ## suffix,\
177: prefix ## EBP ## suffix,\
178: prefix ## ESI ## suffix,\
179: prefix ## EDI ## suffix,\
180: prefix ## R8 ## suffix,\
181: prefix ## R9 ## suffix,\
182: prefix ## R10 ## suffix,\
183: prefix ## R11 ## suffix,\
184: prefix ## R12 ## suffix,\
185: prefix ## R13 ## suffix,\
186: prefix ## R14 ## suffix,\
187: prefix ## R15 ## suffix,
188:
189: #define DEF_BREGS(prefixb, prefixh, suffix) \
190: \
191: static void prefixb ## ESP ## suffix ## _wrapper(void) \
192: { \
193: if (x86_64_hregs) \
194: prefixb ## ESP ## suffix (); \
195: else \
196: prefixh ## EAX ## suffix (); \
197: } \
198: \
199: static void prefixb ## EBP ## suffix ## _wrapper(void) \
200: { \
201: if (x86_64_hregs) \
202: prefixb ## EBP ## suffix (); \
203: else \
204: prefixh ## ECX ## suffix (); \
205: } \
206: \
207: static void prefixb ## ESI ## suffix ## _wrapper(void) \
208: { \
209: if (x86_64_hregs) \
210: prefixb ## ESI ## suffix (); \
211: else \
212: prefixh ## EDX ## suffix (); \
213: } \
214: \
215: static void prefixb ## EDI ## suffix ## _wrapper(void) \
216: { \
217: if (x86_64_hregs) \
218: prefixb ## EDI ## suffix (); \
219: else \
220: prefixh ## EBX ## suffix (); \
221: }
222:
223: DEF_BREGS(gen_op_movb_, gen_op_movh_, _T0)
224: DEF_BREGS(gen_op_movb_, gen_op_movh_, _T1)
225: DEF_BREGS(gen_op_movl_T0_, gen_op_movh_T0_, )
226: DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, )
227:
228: #else /* !TARGET_X86_64 */
229:
230: #define NB_OP_SIZES 3
231:
232: #define DEF_REGS(prefix, suffix) \
233: prefix ## EAX ## suffix,\
234: prefix ## ECX ## suffix,\
235: prefix ## EDX ## suffix,\
236: prefix ## EBX ## suffix,\
237: prefix ## ESP ## suffix,\
238: prefix ## EBP ## suffix,\
239: prefix ## ESI ## suffix,\
240: prefix ## EDI ## suffix,
241:
242: #endif /* !TARGET_X86_64 */
243:
244: static GenOpFunc *gen_op_mov_reg_T0[NB_OP_SIZES][CPU_NB_REGS] = {
245: [OT_BYTE] = {
246: gen_op_movb_EAX_T0,
247: gen_op_movb_ECX_T0,
248: gen_op_movb_EDX_T0,
249: gen_op_movb_EBX_T0,
250: #ifdef TARGET_X86_64
251: gen_op_movb_ESP_T0_wrapper,
252: gen_op_movb_EBP_T0_wrapper,
253: gen_op_movb_ESI_T0_wrapper,
254: gen_op_movb_EDI_T0_wrapper,
255: gen_op_movb_R8_T0,
256: gen_op_movb_R9_T0,
257: gen_op_movb_R10_T0,
258: gen_op_movb_R11_T0,
259: gen_op_movb_R12_T0,
260: gen_op_movb_R13_T0,
261: gen_op_movb_R14_T0,
262: gen_op_movb_R15_T0,
263: #else
264: gen_op_movh_EAX_T0,
265: gen_op_movh_ECX_T0,
266: gen_op_movh_EDX_T0,
267: gen_op_movh_EBX_T0,
268: #endif
269: },
270: [OT_WORD] = {
271: DEF_REGS(gen_op_movw_, _T0)
272: },
273: [OT_LONG] = {
274: DEF_REGS(gen_op_movl_, _T0)
275: },
276: #ifdef TARGET_X86_64
277: [OT_QUAD] = {
278: DEF_REGS(gen_op_movq_, _T0)
279: },
280: #endif
281: };
282:
283: static GenOpFunc *gen_op_mov_reg_T1[NB_OP_SIZES][CPU_NB_REGS] = {
284: [OT_BYTE] = {
285: gen_op_movb_EAX_T1,
286: gen_op_movb_ECX_T1,
287: gen_op_movb_EDX_T1,
288: gen_op_movb_EBX_T1,
289: #ifdef TARGET_X86_64
290: gen_op_movb_ESP_T1_wrapper,
291: gen_op_movb_EBP_T1_wrapper,
292: gen_op_movb_ESI_T1_wrapper,
293: gen_op_movb_EDI_T1_wrapper,
294: gen_op_movb_R8_T1,
295: gen_op_movb_R9_T1,
296: gen_op_movb_R10_T1,
297: gen_op_movb_R11_T1,
298: gen_op_movb_R12_T1,
299: gen_op_movb_R13_T1,
300: gen_op_movb_R14_T1,
301: gen_op_movb_R15_T1,
302: #else
303: gen_op_movh_EAX_T1,
304: gen_op_movh_ECX_T1,
305: gen_op_movh_EDX_T1,
306: gen_op_movh_EBX_T1,
307: #endif
308: },
309: [OT_WORD] = {
310: DEF_REGS(gen_op_movw_, _T1)
311: },
312: [OT_LONG] = {
313: DEF_REGS(gen_op_movl_, _T1)
314: },
315: #ifdef TARGET_X86_64
316: [OT_QUAD] = {
317: DEF_REGS(gen_op_movq_, _T1)
318: },
319: #endif
320: };
321:
322: static GenOpFunc *gen_op_mov_reg_A0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
323: [0] = {
324: DEF_REGS(gen_op_movw_, _A0)
325: },
326: [1] = {
327: DEF_REGS(gen_op_movl_, _A0)
328: },
329: #ifdef TARGET_X86_64
330: [2] = {
331: DEF_REGS(gen_op_movq_, _A0)
332: },
333: #endif
334: };
335:
1.1.1.6 ! root 336: static GenOpFunc *gen_op_mov_TN_reg[NB_OP_SIZES][2][CPU_NB_REGS] =
1.1 root 337: {
338: [OT_BYTE] = {
339: {
340: gen_op_movl_T0_EAX,
341: gen_op_movl_T0_ECX,
342: gen_op_movl_T0_EDX,
343: gen_op_movl_T0_EBX,
344: #ifdef TARGET_X86_64
345: gen_op_movl_T0_ESP_wrapper,
346: gen_op_movl_T0_EBP_wrapper,
347: gen_op_movl_T0_ESI_wrapper,
348: gen_op_movl_T0_EDI_wrapper,
349: gen_op_movl_T0_R8,
350: gen_op_movl_T0_R9,
351: gen_op_movl_T0_R10,
352: gen_op_movl_T0_R11,
353: gen_op_movl_T0_R12,
354: gen_op_movl_T0_R13,
355: gen_op_movl_T0_R14,
356: gen_op_movl_T0_R15,
357: #else
358: gen_op_movh_T0_EAX,
359: gen_op_movh_T0_ECX,
360: gen_op_movh_T0_EDX,
361: gen_op_movh_T0_EBX,
362: #endif
363: },
364: {
365: gen_op_movl_T1_EAX,
366: gen_op_movl_T1_ECX,
367: gen_op_movl_T1_EDX,
368: gen_op_movl_T1_EBX,
369: #ifdef TARGET_X86_64
370: gen_op_movl_T1_ESP_wrapper,
371: gen_op_movl_T1_EBP_wrapper,
372: gen_op_movl_T1_ESI_wrapper,
373: gen_op_movl_T1_EDI_wrapper,
374: gen_op_movl_T1_R8,
375: gen_op_movl_T1_R9,
376: gen_op_movl_T1_R10,
377: gen_op_movl_T1_R11,
378: gen_op_movl_T1_R12,
379: gen_op_movl_T1_R13,
380: gen_op_movl_T1_R14,
381: gen_op_movl_T1_R15,
382: #else
383: gen_op_movh_T1_EAX,
384: gen_op_movh_T1_ECX,
385: gen_op_movh_T1_EDX,
386: gen_op_movh_T1_EBX,
387: #endif
388: },
389: },
390: [OT_WORD] = {
391: {
392: DEF_REGS(gen_op_movl_T0_, )
393: },
394: {
395: DEF_REGS(gen_op_movl_T1_, )
396: },
397: },
398: [OT_LONG] = {
399: {
400: DEF_REGS(gen_op_movl_T0_, )
401: },
402: {
403: DEF_REGS(gen_op_movl_T1_, )
404: },
405: },
406: #ifdef TARGET_X86_64
407: [OT_QUAD] = {
408: {
409: DEF_REGS(gen_op_movl_T0_, )
410: },
411: {
412: DEF_REGS(gen_op_movl_T1_, )
413: },
414: },
415: #endif
416: };
417:
418: static GenOpFunc *gen_op_movl_A0_reg[CPU_NB_REGS] = {
419: DEF_REGS(gen_op_movl_A0_, )
420: };
421:
422: static GenOpFunc *gen_op_addl_A0_reg_sN[4][CPU_NB_REGS] = {
423: [0] = {
424: DEF_REGS(gen_op_addl_A0_, )
425: },
426: [1] = {
427: DEF_REGS(gen_op_addl_A0_, _s1)
428: },
429: [2] = {
430: DEF_REGS(gen_op_addl_A0_, _s2)
431: },
432: [3] = {
433: DEF_REGS(gen_op_addl_A0_, _s3)
434: },
435: };
436:
437: #ifdef TARGET_X86_64
438: static GenOpFunc *gen_op_movq_A0_reg[CPU_NB_REGS] = {
439: DEF_REGS(gen_op_movq_A0_, )
440: };
441:
442: static GenOpFunc *gen_op_addq_A0_reg_sN[4][CPU_NB_REGS] = {
443: [0] = {
444: DEF_REGS(gen_op_addq_A0_, )
445: },
446: [1] = {
447: DEF_REGS(gen_op_addq_A0_, _s1)
448: },
449: [2] = {
450: DEF_REGS(gen_op_addq_A0_, _s2)
451: },
452: [3] = {
453: DEF_REGS(gen_op_addq_A0_, _s3)
454: },
455: };
456: #endif
457:
458: static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
459: [0] = {
460: DEF_REGS(gen_op_cmovw_, _T1_T0)
461: },
462: [1] = {
463: DEF_REGS(gen_op_cmovl_, _T1_T0)
464: },
465: #ifdef TARGET_X86_64
466: [2] = {
467: DEF_REGS(gen_op_cmovq_, _T1_T0)
468: },
469: #endif
470: };
471:
472: static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
473: NULL,
474: gen_op_orl_T0_T1,
475: NULL,
476: NULL,
477: gen_op_andl_T0_T1,
478: NULL,
479: gen_op_xorl_T0_T1,
480: NULL,
481: };
482:
483: #define DEF_ARITHC(SUFFIX)\
484: {\
485: gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
486: gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
487: },\
488: {\
489: gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
490: gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
491: },\
492: {\
493: gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
494: gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
495: },\
496: {\
497: X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\
498: X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\
499: },
500:
501: static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = {
502: DEF_ARITHC( )
503: };
504:
505: static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = {
506: DEF_ARITHC(_raw)
507: #ifndef CONFIG_USER_ONLY
508: DEF_ARITHC(_kernel)
509: DEF_ARITHC(_user)
510: #endif
511: };
512:
513: static const int cc_op_arithb[8] = {
514: CC_OP_ADDB,
515: CC_OP_LOGICB,
516: CC_OP_ADDB,
517: CC_OP_SUBB,
518: CC_OP_LOGICB,
519: CC_OP_SUBB,
520: CC_OP_LOGICB,
521: CC_OP_SUBB,
522: };
523:
524: #define DEF_CMPXCHG(SUFFIX)\
525: gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
526: gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
527: gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\
528: X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc),
529:
530: static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = {
531: DEF_CMPXCHG( )
532: };
533:
534: static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = {
535: DEF_CMPXCHG(_raw)
536: #ifndef CONFIG_USER_ONLY
537: DEF_CMPXCHG(_kernel)
538: DEF_CMPXCHG(_user)
539: #endif
540: };
541:
542: #define DEF_SHIFT(SUFFIX)\
543: {\
544: gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
545: gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
546: gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
547: gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
548: gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
549: gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
550: gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
551: gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
552: },\
553: {\
554: gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
555: gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
556: gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
557: gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
558: gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
559: gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
560: gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
561: gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
562: },\
563: {\
564: gen_op_roll ## SUFFIX ## _T0_T1_cc,\
565: gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
566: gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
567: gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
568: gen_op_shll ## SUFFIX ## _T0_T1_cc,\
569: gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
570: gen_op_shll ## SUFFIX ## _T0_T1_cc,\
571: gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
572: },\
573: {\
574: X86_64_ONLY(gen_op_rolq ## SUFFIX ## _T0_T1_cc),\
575: X86_64_ONLY(gen_op_rorq ## SUFFIX ## _T0_T1_cc),\
576: X86_64_ONLY(gen_op_rclq ## SUFFIX ## _T0_T1_cc),\
577: X86_64_ONLY(gen_op_rcrq ## SUFFIX ## _T0_T1_cc),\
578: X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
579: X86_64_ONLY(gen_op_shrq ## SUFFIX ## _T0_T1_cc),\
580: X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
581: X86_64_ONLY(gen_op_sarq ## SUFFIX ## _T0_T1_cc),\
582: },
583:
584: static GenOpFunc *gen_op_shift_T0_T1_cc[4][8] = {
585: DEF_SHIFT( )
586: };
587:
588: static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3 * 4][8] = {
589: DEF_SHIFT(_raw)
590: #ifndef CONFIG_USER_ONLY
591: DEF_SHIFT(_kernel)
592: DEF_SHIFT(_user)
593: #endif
594: };
595:
596: #define DEF_SHIFTD(SUFFIX, op)\
597: {\
598: NULL,\
599: NULL,\
600: },\
601: {\
602: gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
603: gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
604: },\
605: {\
606: gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
607: gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
608: },\
609: {\
610: X86_64_DEF(gen_op_shldq ## SUFFIX ## _T0_T1_ ## op ## _cc,\
611: gen_op_shrdq ## SUFFIX ## _T0_T1_ ## op ## _cc,)\
612: },
613:
614: static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[4][2] = {
615: DEF_SHIFTD(, im)
616: };
617:
618: static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[4][2] = {
619: DEF_SHIFTD(, ECX)
620: };
621:
622: static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[3 * 4][2] = {
623: DEF_SHIFTD(_raw, im)
624: #ifndef CONFIG_USER_ONLY
625: DEF_SHIFTD(_kernel, im)
626: DEF_SHIFTD(_user, im)
627: #endif
628: };
629:
630: static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[3 * 4][2] = {
631: DEF_SHIFTD(_raw, ECX)
632: #ifndef CONFIG_USER_ONLY
633: DEF_SHIFTD(_kernel, ECX)
634: DEF_SHIFTD(_user, ECX)
635: #endif
636: };
637:
638: static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = {
639: [0] = {
640: gen_op_btw_T0_T1_cc,
641: gen_op_btsw_T0_T1_cc,
642: gen_op_btrw_T0_T1_cc,
643: gen_op_btcw_T0_T1_cc,
644: },
645: [1] = {
646: gen_op_btl_T0_T1_cc,
647: gen_op_btsl_T0_T1_cc,
648: gen_op_btrl_T0_T1_cc,
649: gen_op_btcl_T0_T1_cc,
650: },
651: #ifdef TARGET_X86_64
652: [2] = {
653: gen_op_btq_T0_T1_cc,
654: gen_op_btsq_T0_T1_cc,
655: gen_op_btrq_T0_T1_cc,
656: gen_op_btcq_T0_T1_cc,
657: },
658: #endif
659: };
660:
661: static GenOpFunc *gen_op_add_bit_A0_T1[3] = {
662: gen_op_add_bitw_A0_T1,
663: gen_op_add_bitl_A0_T1,
664: X86_64_ONLY(gen_op_add_bitq_A0_T1),
665: };
666:
667: static GenOpFunc *gen_op_bsx_T0_cc[3][2] = {
668: [0] = {
669: gen_op_bsfw_T0_cc,
670: gen_op_bsrw_T0_cc,
671: },
672: [1] = {
673: gen_op_bsfl_T0_cc,
674: gen_op_bsrl_T0_cc,
675: },
676: #ifdef TARGET_X86_64
677: [2] = {
678: gen_op_bsfq_T0_cc,
679: gen_op_bsrq_T0_cc,
680: },
681: #endif
682: };
683:
684: static GenOpFunc *gen_op_lds_T0_A0[3 * 4] = {
685: gen_op_ldsb_raw_T0_A0,
686: gen_op_ldsw_raw_T0_A0,
687: X86_64_ONLY(gen_op_ldsl_raw_T0_A0),
688: NULL,
689: #ifndef CONFIG_USER_ONLY
690: gen_op_ldsb_kernel_T0_A0,
691: gen_op_ldsw_kernel_T0_A0,
692: X86_64_ONLY(gen_op_ldsl_kernel_T0_A0),
693: NULL,
694:
695: gen_op_ldsb_user_T0_A0,
696: gen_op_ldsw_user_T0_A0,
697: X86_64_ONLY(gen_op_ldsl_user_T0_A0),
698: NULL,
699: #endif
700: };
701:
702: static GenOpFunc *gen_op_ldu_T0_A0[3 * 4] = {
703: gen_op_ldub_raw_T0_A0,
704: gen_op_lduw_raw_T0_A0,
705: NULL,
706: NULL,
707:
708: #ifndef CONFIG_USER_ONLY
709: gen_op_ldub_kernel_T0_A0,
710: gen_op_lduw_kernel_T0_A0,
711: NULL,
712: NULL,
713:
714: gen_op_ldub_user_T0_A0,
715: gen_op_lduw_user_T0_A0,
716: NULL,
717: NULL,
718: #endif
719: };
720:
721: /* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
722: static GenOpFunc *gen_op_ld_T0_A0[3 * 4] = {
723: gen_op_ldub_raw_T0_A0,
724: gen_op_lduw_raw_T0_A0,
725: gen_op_ldl_raw_T0_A0,
726: X86_64_ONLY(gen_op_ldq_raw_T0_A0),
727:
728: #ifndef CONFIG_USER_ONLY
729: gen_op_ldub_kernel_T0_A0,
730: gen_op_lduw_kernel_T0_A0,
731: gen_op_ldl_kernel_T0_A0,
732: X86_64_ONLY(gen_op_ldq_kernel_T0_A0),
733:
734: gen_op_ldub_user_T0_A0,
735: gen_op_lduw_user_T0_A0,
736: gen_op_ldl_user_T0_A0,
737: X86_64_ONLY(gen_op_ldq_user_T0_A0),
738: #endif
739: };
740:
741: static GenOpFunc *gen_op_ld_T1_A0[3 * 4] = {
742: gen_op_ldub_raw_T1_A0,
743: gen_op_lduw_raw_T1_A0,
744: gen_op_ldl_raw_T1_A0,
745: X86_64_ONLY(gen_op_ldq_raw_T1_A0),
746:
747: #ifndef CONFIG_USER_ONLY
748: gen_op_ldub_kernel_T1_A0,
749: gen_op_lduw_kernel_T1_A0,
750: gen_op_ldl_kernel_T1_A0,
751: X86_64_ONLY(gen_op_ldq_kernel_T1_A0),
752:
753: gen_op_ldub_user_T1_A0,
754: gen_op_lduw_user_T1_A0,
755: gen_op_ldl_user_T1_A0,
756: X86_64_ONLY(gen_op_ldq_user_T1_A0),
757: #endif
758: };
759:
760: static GenOpFunc *gen_op_st_T0_A0[3 * 4] = {
761: gen_op_stb_raw_T0_A0,
762: gen_op_stw_raw_T0_A0,
763: gen_op_stl_raw_T0_A0,
764: X86_64_ONLY(gen_op_stq_raw_T0_A0),
765:
766: #ifndef CONFIG_USER_ONLY
767: gen_op_stb_kernel_T0_A0,
768: gen_op_stw_kernel_T0_A0,
769: gen_op_stl_kernel_T0_A0,
770: X86_64_ONLY(gen_op_stq_kernel_T0_A0),
771:
772: gen_op_stb_user_T0_A0,
773: gen_op_stw_user_T0_A0,
774: gen_op_stl_user_T0_A0,
775: X86_64_ONLY(gen_op_stq_user_T0_A0),
776: #endif
777: };
778:
779: static GenOpFunc *gen_op_st_T1_A0[3 * 4] = {
780: NULL,
781: gen_op_stw_raw_T1_A0,
782: gen_op_stl_raw_T1_A0,
783: X86_64_ONLY(gen_op_stq_raw_T1_A0),
784:
785: #ifndef CONFIG_USER_ONLY
786: NULL,
787: gen_op_stw_kernel_T1_A0,
788: gen_op_stl_kernel_T1_A0,
789: X86_64_ONLY(gen_op_stq_kernel_T1_A0),
790:
791: NULL,
792: gen_op_stw_user_T1_A0,
793: gen_op_stl_user_T1_A0,
794: X86_64_ONLY(gen_op_stq_user_T1_A0),
795: #endif
796: };
797:
798: static inline void gen_jmp_im(target_ulong pc)
799: {
800: #ifdef TARGET_X86_64
801: if (pc == (uint32_t)pc) {
802: gen_op_movl_eip_im(pc);
803: } else if (pc == (int32_t)pc) {
804: gen_op_movq_eip_im(pc);
805: } else {
806: gen_op_movq_eip_im64(pc >> 32, pc);
807: }
808: #else
809: gen_op_movl_eip_im(pc);
810: #endif
811: }
812:
813: static inline void gen_string_movl_A0_ESI(DisasContext *s)
814: {
815: int override;
816:
817: override = s->override;
818: #ifdef TARGET_X86_64
819: if (s->aflag == 2) {
820: if (override >= 0) {
821: gen_op_movq_A0_seg(offsetof(CPUX86State,segs[override].base));
822: gen_op_addq_A0_reg_sN[0][R_ESI]();
823: } else {
824: gen_op_movq_A0_reg[R_ESI]();
825: }
826: } else
827: #endif
828: if (s->aflag) {
829: /* 32 bit address */
830: if (s->addseg && override < 0)
831: override = R_DS;
832: if (override >= 0) {
833: gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
834: gen_op_addl_A0_reg_sN[0][R_ESI]();
835: } else {
836: gen_op_movl_A0_reg[R_ESI]();
837: }
838: } else {
839: /* 16 address, always override */
840: if (override < 0)
841: override = R_DS;
842: gen_op_movl_A0_reg[R_ESI]();
843: gen_op_andl_A0_ffff();
844: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
845: }
846: }
847:
848: static inline void gen_string_movl_A0_EDI(DisasContext *s)
849: {
850: #ifdef TARGET_X86_64
851: if (s->aflag == 2) {
852: gen_op_movq_A0_reg[R_EDI]();
853: } else
854: #endif
855: if (s->aflag) {
856: if (s->addseg) {
857: gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
858: gen_op_addl_A0_reg_sN[0][R_EDI]();
859: } else {
860: gen_op_movl_A0_reg[R_EDI]();
861: }
862: } else {
863: gen_op_movl_A0_reg[R_EDI]();
864: gen_op_andl_A0_ffff();
865: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
866: }
867: }
868:
869: static GenOpFunc *gen_op_movl_T0_Dshift[4] = {
870: gen_op_movl_T0_Dshiftb,
871: gen_op_movl_T0_Dshiftw,
872: gen_op_movl_T0_Dshiftl,
873: X86_64_ONLY(gen_op_movl_T0_Dshiftq),
874: };
875:
876: static GenOpFunc1 *gen_op_jnz_ecx[3] = {
877: gen_op_jnz_ecxw,
878: gen_op_jnz_ecxl,
879: X86_64_ONLY(gen_op_jnz_ecxq),
880: };
1.1.1.6 ! root 881:
1.1 root 882: static GenOpFunc1 *gen_op_jz_ecx[3] = {
883: gen_op_jz_ecxw,
884: gen_op_jz_ecxl,
885: X86_64_ONLY(gen_op_jz_ecxq),
886: };
887:
888: static GenOpFunc *gen_op_dec_ECX[3] = {
889: gen_op_decw_ECX,
890: gen_op_decl_ECX,
891: X86_64_ONLY(gen_op_decq_ECX),
892: };
893:
894: static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = {
895: {
896: gen_op_jnz_subb,
897: gen_op_jnz_subw,
898: gen_op_jnz_subl,
899: X86_64_ONLY(gen_op_jnz_subq),
900: },
901: {
902: gen_op_jz_subb,
903: gen_op_jz_subw,
904: gen_op_jz_subl,
905: X86_64_ONLY(gen_op_jz_subq),
906: },
907: };
908:
909: static GenOpFunc *gen_op_in_DX_T0[3] = {
910: gen_op_inb_DX_T0,
911: gen_op_inw_DX_T0,
912: gen_op_inl_DX_T0,
913: };
914:
915: static GenOpFunc *gen_op_out_DX_T0[3] = {
916: gen_op_outb_DX_T0,
917: gen_op_outw_DX_T0,
918: gen_op_outl_DX_T0,
919: };
920:
921: static GenOpFunc *gen_op_in[3] = {
922: gen_op_inb_T0_T1,
923: gen_op_inw_T0_T1,
924: gen_op_inl_T0_T1,
925: };
926:
927: static GenOpFunc *gen_op_out[3] = {
928: gen_op_outb_T0_T1,
929: gen_op_outw_T0_T1,
930: gen_op_outl_T0_T1,
931: };
932:
933: static GenOpFunc *gen_check_io_T0[3] = {
934: gen_op_check_iob_T0,
935: gen_op_check_iow_T0,
936: gen_op_check_iol_T0,
937: };
938:
939: static GenOpFunc *gen_check_io_DX[3] = {
940: gen_op_check_iob_DX,
941: gen_op_check_iow_DX,
942: gen_op_check_iol_DX,
943: };
944:
945: static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip)
946: {
947: if (s->pe && (s->cpl > s->iopl || s->vm86)) {
948: if (s->cc_op != CC_OP_DYNAMIC)
949: gen_op_set_cc_op(s->cc_op);
950: gen_jmp_im(cur_eip);
951: if (use_dx)
952: gen_check_io_DX[ot]();
953: else
954: gen_check_io_T0[ot]();
955: }
956: }
957:
958: static inline void gen_movs(DisasContext *s, int ot)
959: {
960: gen_string_movl_A0_ESI(s);
961: gen_op_ld_T0_A0[ot + s->mem_index]();
962: gen_string_movl_A0_EDI(s);
963: gen_op_st_T0_A0[ot + s->mem_index]();
964: gen_op_movl_T0_Dshift[ot]();
965: #ifdef TARGET_X86_64
966: if (s->aflag == 2) {
967: gen_op_addq_ESI_T0();
968: gen_op_addq_EDI_T0();
1.1.1.6 ! root 969: } else
1.1 root 970: #endif
971: if (s->aflag) {
972: gen_op_addl_ESI_T0();
973: gen_op_addl_EDI_T0();
974: } else {
975: gen_op_addw_ESI_T0();
976: gen_op_addw_EDI_T0();
977: }
978: }
979:
980: static inline void gen_update_cc_op(DisasContext *s)
981: {
982: if (s->cc_op != CC_OP_DYNAMIC) {
983: gen_op_set_cc_op(s->cc_op);
984: s->cc_op = CC_OP_DYNAMIC;
985: }
986: }
987:
988: /* XXX: does not work with gdbstub "ice" single step - not a
989: serious problem */
990: static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
991: {
992: int l1, l2;
993:
994: l1 = gen_new_label();
995: l2 = gen_new_label();
996: gen_op_jnz_ecx[s->aflag](l1);
997: gen_set_label(l2);
998: gen_jmp_tb(s, next_eip, 1);
999: gen_set_label(l1);
1000: return l2;
1001: }
1002:
1003: static inline void gen_stos(DisasContext *s, int ot)
1004: {
1005: gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1006: gen_string_movl_A0_EDI(s);
1007: gen_op_st_T0_A0[ot + s->mem_index]();
1008: gen_op_movl_T0_Dshift[ot]();
1009: #ifdef TARGET_X86_64
1010: if (s->aflag == 2) {
1011: gen_op_addq_EDI_T0();
1.1.1.6 ! root 1012: } else
1.1 root 1013: #endif
1014: if (s->aflag) {
1015: gen_op_addl_EDI_T0();
1016: } else {
1017: gen_op_addw_EDI_T0();
1018: }
1019: }
1020:
1021: static inline void gen_lods(DisasContext *s, int ot)
1022: {
1023: gen_string_movl_A0_ESI(s);
1024: gen_op_ld_T0_A0[ot + s->mem_index]();
1025: gen_op_mov_reg_T0[ot][R_EAX]();
1026: gen_op_movl_T0_Dshift[ot]();
1027: #ifdef TARGET_X86_64
1028: if (s->aflag == 2) {
1029: gen_op_addq_ESI_T0();
1.1.1.6 ! root 1030: } else
1.1 root 1031: #endif
1032: if (s->aflag) {
1033: gen_op_addl_ESI_T0();
1034: } else {
1035: gen_op_addw_ESI_T0();
1036: }
1037: }
1038:
1039: static inline void gen_scas(DisasContext *s, int ot)
1040: {
1041: gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1042: gen_string_movl_A0_EDI(s);
1043: gen_op_ld_T1_A0[ot + s->mem_index]();
1044: gen_op_cmpl_T0_T1_cc();
1045: gen_op_movl_T0_Dshift[ot]();
1046: #ifdef TARGET_X86_64
1047: if (s->aflag == 2) {
1048: gen_op_addq_EDI_T0();
1.1.1.6 ! root 1049: } else
1.1 root 1050: #endif
1051: if (s->aflag) {
1052: gen_op_addl_EDI_T0();
1053: } else {
1054: gen_op_addw_EDI_T0();
1055: }
1056: }
1057:
1058: static inline void gen_cmps(DisasContext *s, int ot)
1059: {
1060: gen_string_movl_A0_ESI(s);
1061: gen_op_ld_T0_A0[ot + s->mem_index]();
1062: gen_string_movl_A0_EDI(s);
1063: gen_op_ld_T1_A0[ot + s->mem_index]();
1064: gen_op_cmpl_T0_T1_cc();
1065: gen_op_movl_T0_Dshift[ot]();
1066: #ifdef TARGET_X86_64
1067: if (s->aflag == 2) {
1068: gen_op_addq_ESI_T0();
1069: gen_op_addq_EDI_T0();
1.1.1.6 ! root 1070: } else
1.1 root 1071: #endif
1072: if (s->aflag) {
1073: gen_op_addl_ESI_T0();
1074: gen_op_addl_EDI_T0();
1075: } else {
1076: gen_op_addw_ESI_T0();
1077: gen_op_addw_EDI_T0();
1078: }
1079: }
1080:
1081: static inline void gen_ins(DisasContext *s, int ot)
1082: {
1083: gen_string_movl_A0_EDI(s);
1084: gen_op_movl_T0_0();
1085: gen_op_st_T0_A0[ot + s->mem_index]();
1086: gen_op_in_DX_T0[ot]();
1087: gen_op_st_T0_A0[ot + s->mem_index]();
1088: gen_op_movl_T0_Dshift[ot]();
1089: #ifdef TARGET_X86_64
1090: if (s->aflag == 2) {
1091: gen_op_addq_EDI_T0();
1.1.1.6 ! root 1092: } else
1.1 root 1093: #endif
1094: if (s->aflag) {
1095: gen_op_addl_EDI_T0();
1096: } else {
1097: gen_op_addw_EDI_T0();
1098: }
1099: }
1100:
1101: static inline void gen_outs(DisasContext *s, int ot)
1102: {
1103: gen_string_movl_A0_ESI(s);
1104: gen_op_ld_T0_A0[ot + s->mem_index]();
1105: gen_op_out_DX_T0[ot]();
1106: gen_op_movl_T0_Dshift[ot]();
1107: #ifdef TARGET_X86_64
1108: if (s->aflag == 2) {
1109: gen_op_addq_ESI_T0();
1.1.1.6 ! root 1110: } else
1.1 root 1111: #endif
1112: if (s->aflag) {
1113: gen_op_addl_ESI_T0();
1114: } else {
1115: gen_op_addw_ESI_T0();
1116: }
1117: }
1118:
1119: /* same method as Valgrind : we generate jumps to current or next
1120: instruction */
1121: #define GEN_REPZ(op) \
1122: static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1123: target_ulong cur_eip, target_ulong next_eip) \
1124: { \
1125: int l2;\
1126: gen_update_cc_op(s); \
1127: l2 = gen_jz_ecx_string(s, next_eip); \
1128: gen_ ## op(s, ot); \
1129: gen_op_dec_ECX[s->aflag](); \
1130: /* a loop would cause two single step exceptions if ECX = 1 \
1131: before rep string_insn */ \
1132: if (!s->jmp_opt) \
1133: gen_op_jz_ecx[s->aflag](l2); \
1134: gen_jmp(s, cur_eip); \
1135: }
1136:
1137: #define GEN_REPZ2(op) \
1138: static inline void gen_repz_ ## op(DisasContext *s, int ot, \
1139: target_ulong cur_eip, \
1140: target_ulong next_eip, \
1141: int nz) \
1142: { \
1143: int l2;\
1144: gen_update_cc_op(s); \
1145: l2 = gen_jz_ecx_string(s, next_eip); \
1146: gen_ ## op(s, ot); \
1147: gen_op_dec_ECX[s->aflag](); \
1148: gen_op_set_cc_op(CC_OP_SUBB + ot); \
1149: gen_op_string_jnz_sub[nz][ot](l2);\
1150: if (!s->jmp_opt) \
1151: gen_op_jz_ecx[s->aflag](l2); \
1152: gen_jmp(s, cur_eip); \
1153: }
1154:
1155: GEN_REPZ(movs)
1156: GEN_REPZ(stos)
1157: GEN_REPZ(lods)
1158: GEN_REPZ(ins)
1159: GEN_REPZ(outs)
1160: GEN_REPZ2(scas)
1161: GEN_REPZ2(cmps)
1162:
1163: enum {
1164: JCC_O,
1165: JCC_B,
1166: JCC_Z,
1167: JCC_BE,
1168: JCC_S,
1169: JCC_P,
1170: JCC_L,
1171: JCC_LE,
1172: };
1173:
1174: static GenOpFunc1 *gen_jcc_sub[4][8] = {
1175: [OT_BYTE] = {
1176: NULL,
1177: gen_op_jb_subb,
1178: gen_op_jz_subb,
1179: gen_op_jbe_subb,
1180: gen_op_js_subb,
1181: NULL,
1182: gen_op_jl_subb,
1183: gen_op_jle_subb,
1184: },
1185: [OT_WORD] = {
1186: NULL,
1187: gen_op_jb_subw,
1188: gen_op_jz_subw,
1189: gen_op_jbe_subw,
1190: gen_op_js_subw,
1191: NULL,
1192: gen_op_jl_subw,
1193: gen_op_jle_subw,
1194: },
1195: [OT_LONG] = {
1196: NULL,
1197: gen_op_jb_subl,
1198: gen_op_jz_subl,
1199: gen_op_jbe_subl,
1200: gen_op_js_subl,
1201: NULL,
1202: gen_op_jl_subl,
1203: gen_op_jle_subl,
1204: },
1205: #ifdef TARGET_X86_64
1206: [OT_QUAD] = {
1207: NULL,
1208: BUGGY_64(gen_op_jb_subq),
1209: gen_op_jz_subq,
1210: BUGGY_64(gen_op_jbe_subq),
1211: gen_op_js_subq,
1212: NULL,
1213: BUGGY_64(gen_op_jl_subq),
1214: BUGGY_64(gen_op_jle_subq),
1215: },
1216: #endif
1217: };
1218: static GenOpFunc1 *gen_op_loop[3][4] = {
1219: [0] = {
1220: gen_op_loopnzw,
1221: gen_op_loopzw,
1222: gen_op_jnz_ecxw,
1223: },
1224: [1] = {
1225: gen_op_loopnzl,
1226: gen_op_loopzl,
1227: gen_op_jnz_ecxl,
1228: },
1229: #ifdef TARGET_X86_64
1230: [2] = {
1231: gen_op_loopnzq,
1232: gen_op_loopzq,
1233: gen_op_jnz_ecxq,
1234: },
1235: #endif
1236: };
1237:
1238: static GenOpFunc *gen_setcc_slow[8] = {
1239: gen_op_seto_T0_cc,
1240: gen_op_setb_T0_cc,
1241: gen_op_setz_T0_cc,
1242: gen_op_setbe_T0_cc,
1243: gen_op_sets_T0_cc,
1244: gen_op_setp_T0_cc,
1245: gen_op_setl_T0_cc,
1246: gen_op_setle_T0_cc,
1247: };
1248:
1249: static GenOpFunc *gen_setcc_sub[4][8] = {
1250: [OT_BYTE] = {
1251: NULL,
1252: gen_op_setb_T0_subb,
1253: gen_op_setz_T0_subb,
1254: gen_op_setbe_T0_subb,
1255: gen_op_sets_T0_subb,
1256: NULL,
1257: gen_op_setl_T0_subb,
1258: gen_op_setle_T0_subb,
1259: },
1260: [OT_WORD] = {
1261: NULL,
1262: gen_op_setb_T0_subw,
1263: gen_op_setz_T0_subw,
1264: gen_op_setbe_T0_subw,
1265: gen_op_sets_T0_subw,
1266: NULL,
1267: gen_op_setl_T0_subw,
1268: gen_op_setle_T0_subw,
1269: },
1270: [OT_LONG] = {
1271: NULL,
1272: gen_op_setb_T0_subl,
1273: gen_op_setz_T0_subl,
1274: gen_op_setbe_T0_subl,
1275: gen_op_sets_T0_subl,
1276: NULL,
1277: gen_op_setl_T0_subl,
1278: gen_op_setle_T0_subl,
1279: },
1280: #ifdef TARGET_X86_64
1281: [OT_QUAD] = {
1282: NULL,
1283: gen_op_setb_T0_subq,
1284: gen_op_setz_T0_subq,
1285: gen_op_setbe_T0_subq,
1286: gen_op_sets_T0_subq,
1287: NULL,
1288: gen_op_setl_T0_subq,
1289: gen_op_setle_T0_subq,
1290: },
1291: #endif
1292: };
1293:
1294: static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1295: gen_op_fadd_ST0_FT0,
1296: gen_op_fmul_ST0_FT0,
1297: gen_op_fcom_ST0_FT0,
1298: gen_op_fcom_ST0_FT0,
1299: gen_op_fsub_ST0_FT0,
1300: gen_op_fsubr_ST0_FT0,
1301: gen_op_fdiv_ST0_FT0,
1302: gen_op_fdivr_ST0_FT0,
1303: };
1304:
1305: /* NOTE the exception in "r" op ordering */
1306: static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1307: gen_op_fadd_STN_ST0,
1308: gen_op_fmul_STN_ST0,
1309: NULL,
1310: NULL,
1311: gen_op_fsubr_STN_ST0,
1312: gen_op_fsub_STN_ST0,
1313: gen_op_fdivr_STN_ST0,
1314: gen_op_fdiv_STN_ST0,
1315: };
1316:
1317: /* if d == OR_TMP0, it means memory operand (address in A0) */
1318: static void gen_op(DisasContext *s1, int op, int ot, int d)
1319: {
1320: GenOpFunc *gen_update_cc;
1.1.1.6 ! root 1321:
1.1 root 1322: if (d != OR_TMP0) {
1323: gen_op_mov_TN_reg[ot][0][d]();
1324: } else {
1325: gen_op_ld_T0_A0[ot + s1->mem_index]();
1326: }
1327: switch(op) {
1328: case OP_ADCL:
1329: case OP_SBBL:
1330: if (s1->cc_op != CC_OP_DYNAMIC)
1331: gen_op_set_cc_op(s1->cc_op);
1332: if (d != OR_TMP0) {
1333: gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1334: gen_op_mov_reg_T0[ot][d]();
1335: } else {
1336: gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
1337: }
1338: s1->cc_op = CC_OP_DYNAMIC;
1339: goto the_end;
1340: case OP_ADDL:
1341: gen_op_addl_T0_T1();
1342: s1->cc_op = CC_OP_ADDB + ot;
1343: gen_update_cc = gen_op_update2_cc;
1344: break;
1345: case OP_SUBL:
1346: gen_op_subl_T0_T1();
1347: s1->cc_op = CC_OP_SUBB + ot;
1348: gen_update_cc = gen_op_update2_cc;
1349: break;
1350: default:
1351: case OP_ANDL:
1352: case OP_ORL:
1353: case OP_XORL:
1354: gen_op_arith_T0_T1_cc[op]();
1355: s1->cc_op = CC_OP_LOGICB + ot;
1356: gen_update_cc = gen_op_update1_cc;
1357: break;
1358: case OP_CMPL:
1359: gen_op_cmpl_T0_T1_cc();
1360: s1->cc_op = CC_OP_SUBB + ot;
1361: gen_update_cc = NULL;
1362: break;
1363: }
1364: if (op != OP_CMPL) {
1365: if (d != OR_TMP0)
1366: gen_op_mov_reg_T0[ot][d]();
1367: else
1368: gen_op_st_T0_A0[ot + s1->mem_index]();
1369: }
1370: /* the flags update must happen after the memory write (precise
1371: exception support) */
1372: if (gen_update_cc)
1373: gen_update_cc();
1374: the_end: ;
1375: }
1376:
1377: /* if d == OR_TMP0, it means memory operand (address in A0) */
1378: static void gen_inc(DisasContext *s1, int ot, int d, int c)
1379: {
1380: if (d != OR_TMP0)
1381: gen_op_mov_TN_reg[ot][0][d]();
1382: else
1383: gen_op_ld_T0_A0[ot + s1->mem_index]();
1384: if (s1->cc_op != CC_OP_DYNAMIC)
1385: gen_op_set_cc_op(s1->cc_op);
1386: if (c > 0) {
1387: gen_op_incl_T0();
1388: s1->cc_op = CC_OP_INCB + ot;
1389: } else {
1390: gen_op_decl_T0();
1391: s1->cc_op = CC_OP_DECB + ot;
1392: }
1393: if (d != OR_TMP0)
1394: gen_op_mov_reg_T0[ot][d]();
1395: else
1396: gen_op_st_T0_A0[ot + s1->mem_index]();
1397: gen_op_update_inc_cc();
1398: }
1399:
1400: static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1401: {
1402: if (d != OR_TMP0)
1403: gen_op_mov_TN_reg[ot][0][d]();
1404: else
1405: gen_op_ld_T0_A0[ot + s1->mem_index]();
1406: if (s != OR_TMP1)
1407: gen_op_mov_TN_reg[ot][1][s]();
1408: /* for zero counts, flags are not updated, so must do it dynamically */
1409: if (s1->cc_op != CC_OP_DYNAMIC)
1410: gen_op_set_cc_op(s1->cc_op);
1.1.1.6 ! root 1411:
1.1 root 1412: if (d != OR_TMP0)
1413: gen_op_shift_T0_T1_cc[ot][op]();
1414: else
1415: gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
1416: if (d != OR_TMP0)
1417: gen_op_mov_reg_T0[ot][d]();
1418: s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1419: }
1420:
1421: static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1422: {
1423: /* currently not optimized */
1424: gen_op_movl_T1_im(c);
1425: gen_shift(s1, op, ot, d, OR_TMP1);
1426: }
1427:
1428: static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1429: {
1430: target_long disp;
1431: int havesib;
1432: int base;
1433: int index;
1434: int scale;
1435: int opreg;
1436: int mod, rm, code, override, must_add_seg;
1437:
1438: override = s->override;
1439: must_add_seg = s->addseg;
1440: if (override >= 0)
1441: must_add_seg = 1;
1442: mod = (modrm >> 6) & 3;
1443: rm = modrm & 7;
1444:
1445: if (s->aflag) {
1446:
1447: havesib = 0;
1448: base = rm;
1449: index = 0;
1450: scale = 0;
1.1.1.6 ! root 1451:
1.1 root 1452: if (base == 4) {
1453: havesib = 1;
1454: code = ldub_code(s->pc++);
1455: scale = (code >> 6) & 3;
1456: index = ((code >> 3) & 7) | REX_X(s);
1457: base = (code & 7);
1458: }
1459: base |= REX_B(s);
1460:
1461: switch (mod) {
1462: case 0:
1463: if ((base & 7) == 5) {
1464: base = -1;
1465: disp = (int32_t)ldl_code(s->pc);
1466: s->pc += 4;
1467: if (CODE64(s) && !havesib) {
1468: disp += s->pc + s->rip_offset;
1469: }
1470: } else {
1471: disp = 0;
1472: }
1473: break;
1474: case 1:
1475: disp = (int8_t)ldub_code(s->pc++);
1476: break;
1477: default:
1478: case 2:
1479: disp = ldl_code(s->pc);
1480: s->pc += 4;
1481: break;
1482: }
1.1.1.6 ! root 1483:
1.1 root 1484: if (base >= 0) {
1485: /* for correct popl handling with esp */
1486: if (base == 4 && s->popl_esp_hack)
1487: disp += s->popl_esp_hack;
1488: #ifdef TARGET_X86_64
1489: if (s->aflag == 2) {
1490: gen_op_movq_A0_reg[base]();
1491: if (disp != 0) {
1492: if ((int32_t)disp == disp)
1493: gen_op_addq_A0_im(disp);
1494: else
1495: gen_op_addq_A0_im64(disp >> 32, disp);
1496: }
1.1.1.6 ! root 1497: } else
1.1 root 1498: #endif
1499: {
1500: gen_op_movl_A0_reg[base]();
1501: if (disp != 0)
1502: gen_op_addl_A0_im(disp);
1503: }
1504: } else {
1505: #ifdef TARGET_X86_64
1506: if (s->aflag == 2) {
1507: if ((int32_t)disp == disp)
1508: gen_op_movq_A0_im(disp);
1509: else
1510: gen_op_movq_A0_im64(disp >> 32, disp);
1.1.1.6 ! root 1511: } else
1.1 root 1512: #endif
1513: {
1514: gen_op_movl_A0_im(disp);
1515: }
1516: }
1517: /* XXX: index == 4 is always invalid */
1518: if (havesib && (index != 4 || scale != 0)) {
1519: #ifdef TARGET_X86_64
1520: if (s->aflag == 2) {
1521: gen_op_addq_A0_reg_sN[scale][index]();
1.1.1.6 ! root 1522: } else
1.1 root 1523: #endif
1524: {
1525: gen_op_addl_A0_reg_sN[scale][index]();
1526: }
1527: }
1528: if (must_add_seg) {
1529: if (override < 0) {
1530: if (base == R_EBP || base == R_ESP)
1531: override = R_SS;
1532: else
1533: override = R_DS;
1534: }
1535: #ifdef TARGET_X86_64
1536: if (s->aflag == 2) {
1537: gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
1.1.1.6 ! root 1538: } else
1.1 root 1539: #endif
1540: {
1541: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1542: }
1543: }
1544: } else {
1545: switch (mod) {
1546: case 0:
1547: if (rm == 6) {
1548: disp = lduw_code(s->pc);
1549: s->pc += 2;
1550: gen_op_movl_A0_im(disp);
1551: rm = 0; /* avoid SS override */
1552: goto no_rm;
1553: } else {
1554: disp = 0;
1555: }
1556: break;
1557: case 1:
1558: disp = (int8_t)ldub_code(s->pc++);
1559: break;
1560: default:
1561: case 2:
1562: disp = lduw_code(s->pc);
1563: s->pc += 2;
1564: break;
1565: }
1566: switch(rm) {
1567: case 0:
1568: gen_op_movl_A0_reg[R_EBX]();
1569: gen_op_addl_A0_reg_sN[0][R_ESI]();
1570: break;
1571: case 1:
1572: gen_op_movl_A0_reg[R_EBX]();
1573: gen_op_addl_A0_reg_sN[0][R_EDI]();
1574: break;
1575: case 2:
1576: gen_op_movl_A0_reg[R_EBP]();
1577: gen_op_addl_A0_reg_sN[0][R_ESI]();
1578: break;
1579: case 3:
1580: gen_op_movl_A0_reg[R_EBP]();
1581: gen_op_addl_A0_reg_sN[0][R_EDI]();
1582: break;
1583: case 4:
1584: gen_op_movl_A0_reg[R_ESI]();
1585: break;
1586: case 5:
1587: gen_op_movl_A0_reg[R_EDI]();
1588: break;
1589: case 6:
1590: gen_op_movl_A0_reg[R_EBP]();
1591: break;
1592: default:
1593: case 7:
1594: gen_op_movl_A0_reg[R_EBX]();
1595: break;
1596: }
1597: if (disp != 0)
1598: gen_op_addl_A0_im(disp);
1599: gen_op_andl_A0_ffff();
1600: no_rm:
1601: if (must_add_seg) {
1602: if (override < 0) {
1603: if (rm == 2 || rm == 3 || rm == 6)
1604: override = R_SS;
1605: else
1606: override = R_DS;
1607: }
1608: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1609: }
1610: }
1611:
1612: opreg = OR_A0;
1613: disp = 0;
1614: *reg_ptr = opreg;
1615: *offset_ptr = disp;
1616: }
1617:
1.1.1.5 root 1618: static void gen_nop_modrm(DisasContext *s, int modrm)
1619: {
1620: int mod, rm, base, code;
1621:
1622: mod = (modrm >> 6) & 3;
1623: if (mod == 3)
1624: return;
1625: rm = modrm & 7;
1626:
1627: if (s->aflag) {
1628:
1629: base = rm;
1.1.1.6 ! root 1630:
1.1.1.5 root 1631: if (base == 4) {
1632: code = ldub_code(s->pc++);
1633: base = (code & 7);
1634: }
1.1.1.6 ! root 1635:
1.1.1.5 root 1636: switch (mod) {
1637: case 0:
1638: if (base == 5) {
1639: s->pc += 4;
1640: }
1641: break;
1642: case 1:
1643: s->pc++;
1644: break;
1645: default:
1646: case 2:
1647: s->pc += 4;
1648: break;
1649: }
1650: } else {
1651: switch (mod) {
1652: case 0:
1653: if (rm == 6) {
1654: s->pc += 2;
1655: }
1656: break;
1657: case 1:
1658: s->pc++;
1659: break;
1660: default:
1661: case 2:
1662: s->pc += 2;
1663: break;
1664: }
1665: }
1666: }
1667:
1.1 root 1668: /* used for LEA and MOV AX, mem */
1669: static void gen_add_A0_ds_seg(DisasContext *s)
1670: {
1671: int override, must_add_seg;
1672: must_add_seg = s->addseg;
1673: override = R_DS;
1674: if (s->override >= 0) {
1675: override = s->override;
1676: must_add_seg = 1;
1677: } else {
1678: override = R_DS;
1679: }
1680: if (must_add_seg) {
1681: #ifdef TARGET_X86_64
1682: if (CODE64(s)) {
1683: gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
1.1.1.6 ! root 1684: } else
1.1 root 1685: #endif
1686: {
1687: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1688: }
1689: }
1690: }
1691:
1692: /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1693: OR_TMP0 */
1694: static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1695: {
1696: int mod, rm, opreg, disp;
1697:
1698: mod = (modrm >> 6) & 3;
1699: rm = (modrm & 7) | REX_B(s);
1700: if (mod == 3) {
1701: if (is_store) {
1702: if (reg != OR_TMP0)
1703: gen_op_mov_TN_reg[ot][0][reg]();
1704: gen_op_mov_reg_T0[ot][rm]();
1705: } else {
1706: gen_op_mov_TN_reg[ot][0][rm]();
1707: if (reg != OR_TMP0)
1708: gen_op_mov_reg_T0[ot][reg]();
1709: }
1710: } else {
1711: gen_lea_modrm(s, modrm, &opreg, &disp);
1712: if (is_store) {
1713: if (reg != OR_TMP0)
1714: gen_op_mov_TN_reg[ot][0][reg]();
1715: gen_op_st_T0_A0[ot + s->mem_index]();
1716: } else {
1717: gen_op_ld_T0_A0[ot + s->mem_index]();
1718: if (reg != OR_TMP0)
1719: gen_op_mov_reg_T0[ot][reg]();
1720: }
1721: }
1722: }
1723:
1724: static inline uint32_t insn_get(DisasContext *s, int ot)
1725: {
1726: uint32_t ret;
1727:
1728: switch(ot) {
1729: case OT_BYTE:
1730: ret = ldub_code(s->pc);
1731: s->pc++;
1732: break;
1733: case OT_WORD:
1734: ret = lduw_code(s->pc);
1735: s->pc += 2;
1736: break;
1737: default:
1738: case OT_LONG:
1739: ret = ldl_code(s->pc);
1740: s->pc += 4;
1741: break;
1742: }
1743: return ret;
1744: }
1745:
1746: static inline int insn_const_size(unsigned int ot)
1747: {
1748: if (ot <= OT_LONG)
1749: return 1 << ot;
1750: else
1751: return 4;
1752: }
1753:
1.1.1.2 root 1754: static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
1755: {
1756: TranslationBlock *tb;
1757: target_ulong pc;
1758:
1759: pc = s->cs_base + eip;
1760: tb = s->tb;
1761: /* NOTE: we handle the case where the TB spans two pages here */
1762: if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
1763: (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
1764: /* jump to same page: we can use a direct jump */
1765: if (tb_num == 0)
1766: gen_op_goto_tb0(TBPARAM(tb));
1767: else
1768: gen_op_goto_tb1(TBPARAM(tb));
1769: gen_jmp_im(eip);
1770: gen_op_movl_T0_im((long)tb + tb_num);
1771: gen_op_exit_tb();
1772: } else {
1773: /* jump to another page: currently not optimized */
1774: gen_jmp_im(eip);
1775: gen_eob(s);
1776: }
1777: }
1778:
1.1.1.6 ! root 1779: static inline void gen_jcc(DisasContext *s, int b,
1.1 root 1780: target_ulong val, target_ulong next_eip)
1781: {
1782: TranslationBlock *tb;
1783: int inv, jcc_op;
1784: GenOpFunc1 *func;
1785: target_ulong tmp;
1786: int l1, l2;
1787:
1788: inv = b & 1;
1789: jcc_op = (b >> 1) & 7;
1.1.1.6 ! root 1790:
1.1 root 1791: if (s->jmp_opt) {
1792: switch(s->cc_op) {
1793: /* we optimize the cmp/jcc case */
1794: case CC_OP_SUBB:
1795: case CC_OP_SUBW:
1796: case CC_OP_SUBL:
1797: case CC_OP_SUBQ:
1798: func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1799: break;
1.1.1.6 ! root 1800:
1.1 root 1801: /* some jumps are easy to compute */
1802: case CC_OP_ADDB:
1803: case CC_OP_ADDW:
1804: case CC_OP_ADDL:
1805: case CC_OP_ADDQ:
1806:
1807: case CC_OP_ADCB:
1808: case CC_OP_ADCW:
1809: case CC_OP_ADCL:
1810: case CC_OP_ADCQ:
1811:
1812: case CC_OP_SBBB:
1813: case CC_OP_SBBW:
1814: case CC_OP_SBBL:
1815: case CC_OP_SBBQ:
1816:
1817: case CC_OP_LOGICB:
1818: case CC_OP_LOGICW:
1819: case CC_OP_LOGICL:
1820: case CC_OP_LOGICQ:
1821:
1822: case CC_OP_INCB:
1823: case CC_OP_INCW:
1824: case CC_OP_INCL:
1825: case CC_OP_INCQ:
1826:
1827: case CC_OP_DECB:
1828: case CC_OP_DECW:
1829: case CC_OP_DECL:
1830: case CC_OP_DECQ:
1831:
1832: case CC_OP_SHLB:
1833: case CC_OP_SHLW:
1834: case CC_OP_SHLL:
1835: case CC_OP_SHLQ:
1836:
1837: case CC_OP_SARB:
1838: case CC_OP_SARW:
1839: case CC_OP_SARL:
1840: case CC_OP_SARQ:
1841: switch(jcc_op) {
1842: case JCC_Z:
1843: func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1844: break;
1845: case JCC_S:
1846: func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1847: break;
1848: default:
1849: func = NULL;
1850: break;
1851: }
1852: break;
1853: default:
1854: func = NULL;
1855: break;
1856: }
1857:
1.1.1.2 root 1858: if (s->cc_op != CC_OP_DYNAMIC) {
1.1 root 1859: gen_op_set_cc_op(s->cc_op);
1.1.1.2 root 1860: s->cc_op = CC_OP_DYNAMIC;
1861: }
1.1 root 1862:
1863: if (!func) {
1864: gen_setcc_slow[jcc_op]();
1865: func = gen_op_jnz_T0_label;
1866: }
1.1.1.6 ! root 1867:
1.1 root 1868: if (inv) {
1869: tmp = val;
1870: val = next_eip;
1871: next_eip = tmp;
1872: }
1873: tb = s->tb;
1874:
1875: l1 = gen_new_label();
1876: func(l1);
1877:
1.1.1.2 root 1878: gen_goto_tb(s, 0, next_eip);
1.1 root 1879:
1880: gen_set_label(l1);
1.1.1.2 root 1881: gen_goto_tb(s, 1, val);
1.1 root 1882:
1883: s->is_jmp = 3;
1884: } else {
1885:
1886: if (s->cc_op != CC_OP_DYNAMIC) {
1887: gen_op_set_cc_op(s->cc_op);
1888: s->cc_op = CC_OP_DYNAMIC;
1889: }
1890: gen_setcc_slow[jcc_op]();
1891: if (inv) {
1892: tmp = val;
1893: val = next_eip;
1894: next_eip = tmp;
1895: }
1896: l1 = gen_new_label();
1897: l2 = gen_new_label();
1898: gen_op_jnz_T0_label(l1);
1899: gen_jmp_im(next_eip);
1900: gen_op_jmp_label(l2);
1901: gen_set_label(l1);
1902: gen_jmp_im(val);
1903: gen_set_label(l2);
1904: gen_eob(s);
1905: }
1906: }
1907:
1908: static void gen_setcc(DisasContext *s, int b)
1909: {
1910: int inv, jcc_op;
1911: GenOpFunc *func;
1912:
1913: inv = b & 1;
1914: jcc_op = (b >> 1) & 7;
1915: switch(s->cc_op) {
1916: /* we optimize the cmp/jcc case */
1917: case CC_OP_SUBB:
1918: case CC_OP_SUBW:
1919: case CC_OP_SUBL:
1920: case CC_OP_SUBQ:
1921: func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1922: if (!func)
1923: goto slow_jcc;
1924: break;
1.1.1.6 ! root 1925:
1.1 root 1926: /* some jumps are easy to compute */
1927: case CC_OP_ADDB:
1928: case CC_OP_ADDW:
1929: case CC_OP_ADDL:
1930: case CC_OP_ADDQ:
1931:
1932: case CC_OP_LOGICB:
1933: case CC_OP_LOGICW:
1934: case CC_OP_LOGICL:
1935: case CC_OP_LOGICQ:
1936:
1937: case CC_OP_INCB:
1938: case CC_OP_INCW:
1939: case CC_OP_INCL:
1940: case CC_OP_INCQ:
1941:
1942: case CC_OP_DECB:
1943: case CC_OP_DECW:
1944: case CC_OP_DECL:
1945: case CC_OP_DECQ:
1946:
1947: case CC_OP_SHLB:
1948: case CC_OP_SHLW:
1949: case CC_OP_SHLL:
1950: case CC_OP_SHLQ:
1951: switch(jcc_op) {
1952: case JCC_Z:
1953: func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1954: break;
1955: case JCC_S:
1956: func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1957: break;
1958: default:
1959: goto slow_jcc;
1960: }
1961: break;
1962: default:
1963: slow_jcc:
1964: if (s->cc_op != CC_OP_DYNAMIC)
1965: gen_op_set_cc_op(s->cc_op);
1966: func = gen_setcc_slow[jcc_op];
1967: break;
1968: }
1969: func();
1970: if (inv) {
1971: gen_op_xor_T0_1();
1972: }
1973: }
1974:
1975: /* move T0 to seg_reg and compute if the CPU state may change. Never
1976: call this function with seg_reg == R_CS */
1977: static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
1978: {
1979: if (s->pe && !s->vm86) {
1980: /* XXX: optimize by finding processor state dynamically */
1981: if (s->cc_op != CC_OP_DYNAMIC)
1982: gen_op_set_cc_op(s->cc_op);
1983: gen_jmp_im(cur_eip);
1984: gen_op_movl_seg_T0(seg_reg);
1985: /* abort translation because the addseg value may change or
1986: because ss32 may change. For R_SS, translation must always
1987: stop as a special handling must be done to disable hardware
1988: interrupts for the next instruction */
1989: if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1990: s->is_jmp = 3;
1991: } else {
1992: gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1993: if (seg_reg == R_SS)
1994: s->is_jmp = 3;
1995: }
1996: }
1997:
1.1.1.6 ! root 1998: #ifdef TARGET_X86_64
! 1999: #define SVM_movq_T1_im(x) gen_op_movq_T1_im64((x) >> 32, x)
! 2000: #else
! 2001: #define SVM_movq_T1_im(x) gen_op_movl_T1_im(x)
! 2002: #endif
! 2003:
! 2004: static inline int
! 2005: gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type)
! 2006: {
! 2007: #if !defined(CONFIG_USER_ONLY)
! 2008: if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) {
! 2009: if (s->cc_op != CC_OP_DYNAMIC)
! 2010: gen_op_set_cc_op(s->cc_op);
! 2011: SVM_movq_T1_im(s->pc - s->cs_base);
! 2012: gen_jmp_im(pc_start - s->cs_base);
! 2013: gen_op_geneflags();
! 2014: gen_op_svm_check_intercept_io((uint32_t)(type >> 32), (uint32_t)type);
! 2015: s->cc_op = CC_OP_DYNAMIC;
! 2016: /* FIXME: maybe we could move the io intercept vector to the TB as well
! 2017: so we know if this is an EOB or not ... let's assume it's not
! 2018: for now. */
! 2019: }
! 2020: #endif
! 2021: return 0;
! 2022: }
! 2023:
! 2024: static inline int svm_is_rep(int prefixes)
! 2025: {
! 2026: return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
! 2027: }
! 2028:
! 2029: static inline int
! 2030: gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
! 2031: uint64_t type, uint64_t param)
! 2032: {
! 2033: if(!(s->flags & (INTERCEPT_SVM_MASK)))
! 2034: /* no SVM activated */
! 2035: return 0;
! 2036: switch(type) {
! 2037: /* CRx and DRx reads/writes */
! 2038: case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1:
! 2039: if (s->cc_op != CC_OP_DYNAMIC) {
! 2040: gen_op_set_cc_op(s->cc_op);
! 2041: s->cc_op = CC_OP_DYNAMIC;
! 2042: }
! 2043: gen_jmp_im(pc_start - s->cs_base);
! 2044: SVM_movq_T1_im(param);
! 2045: gen_op_geneflags();
! 2046: gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
! 2047: /* this is a special case as we do not know if the interception occurs
! 2048: so we assume there was none */
! 2049: return 0;
! 2050: case SVM_EXIT_MSR:
! 2051: if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) {
! 2052: if (s->cc_op != CC_OP_DYNAMIC) {
! 2053: gen_op_set_cc_op(s->cc_op);
! 2054: s->cc_op = CC_OP_DYNAMIC;
! 2055: }
! 2056: gen_jmp_im(pc_start - s->cs_base);
! 2057: SVM_movq_T1_im(param);
! 2058: gen_op_geneflags();
! 2059: gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
! 2060: /* this is a special case as we do not know if the interception occurs
! 2061: so we assume there was none */
! 2062: return 0;
! 2063: }
! 2064: break;
! 2065: default:
! 2066: if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) {
! 2067: if (s->cc_op != CC_OP_DYNAMIC) {
! 2068: gen_op_set_cc_op(s->cc_op);
! 2069: s->cc_op = CC_OP_EFLAGS;
! 2070: }
! 2071: gen_jmp_im(pc_start - s->cs_base);
! 2072: SVM_movq_T1_im(param);
! 2073: gen_op_geneflags();
! 2074: gen_op_svm_vmexit(type >> 32, type);
! 2075: /* we can optimize this one so TBs don't get longer
! 2076: than up to vmexit */
! 2077: gen_eob(s);
! 2078: return 1;
! 2079: }
! 2080: }
! 2081: return 0;
! 2082: }
! 2083:
! 2084: static inline int
! 2085: gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
! 2086: {
! 2087: return gen_svm_check_intercept_param(s, pc_start, type, 0);
! 2088: }
! 2089:
1.1 root 2090: static inline void gen_stack_update(DisasContext *s, int addend)
2091: {
2092: #ifdef TARGET_X86_64
2093: if (CODE64(s)) {
2094: if (addend == 8)
2095: gen_op_addq_ESP_8();
1.1.1.6 ! root 2096: else
1.1 root 2097: gen_op_addq_ESP_im(addend);
2098: } else
2099: #endif
2100: if (s->ss32) {
2101: if (addend == 2)
2102: gen_op_addl_ESP_2();
2103: else if (addend == 4)
2104: gen_op_addl_ESP_4();
1.1.1.6 ! root 2105: else
1.1 root 2106: gen_op_addl_ESP_im(addend);
2107: } else {
2108: if (addend == 2)
2109: gen_op_addw_ESP_2();
2110: else if (addend == 4)
2111: gen_op_addw_ESP_4();
2112: else
2113: gen_op_addw_ESP_im(addend);
2114: }
2115: }
2116:
2117: /* generate a push. It depends on ss32, addseg and dflag */
2118: static void gen_push_T0(DisasContext *s)
2119: {
2120: #ifdef TARGET_X86_64
2121: if (CODE64(s)) {
2122: gen_op_movq_A0_reg[R_ESP]();
2123: if (s->dflag) {
2124: gen_op_subq_A0_8();
2125: gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
2126: } else {
2127: gen_op_subq_A0_2();
2128: gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2129: }
2130: gen_op_movq_ESP_A0();
1.1.1.6 ! root 2131: } else
1.1 root 2132: #endif
2133: {
2134: gen_op_movl_A0_reg[R_ESP]();
2135: if (!s->dflag)
2136: gen_op_subl_A0_2();
2137: else
2138: gen_op_subl_A0_4();
2139: if (s->ss32) {
2140: if (s->addseg) {
2141: gen_op_movl_T1_A0();
2142: gen_op_addl_A0_SS();
2143: }
2144: } else {
2145: gen_op_andl_A0_ffff();
2146: gen_op_movl_T1_A0();
2147: gen_op_addl_A0_SS();
2148: }
2149: gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
2150: if (s->ss32 && !s->addseg)
2151: gen_op_movl_ESP_A0();
2152: else
2153: gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
2154: }
2155: }
2156:
2157: /* generate a push. It depends on ss32, addseg and dflag */
2158: /* slower version for T1, only used for call Ev */
2159: static void gen_push_T1(DisasContext *s)
2160: {
2161: #ifdef TARGET_X86_64
2162: if (CODE64(s)) {
2163: gen_op_movq_A0_reg[R_ESP]();
2164: if (s->dflag) {
2165: gen_op_subq_A0_8();
2166: gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
2167: } else {
2168: gen_op_subq_A0_2();
2169: gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2170: }
2171: gen_op_movq_ESP_A0();
1.1.1.6 ! root 2172: } else
1.1 root 2173: #endif
2174: {
2175: gen_op_movl_A0_reg[R_ESP]();
2176: if (!s->dflag)
2177: gen_op_subl_A0_2();
2178: else
2179: gen_op_subl_A0_4();
2180: if (s->ss32) {
2181: if (s->addseg) {
2182: gen_op_addl_A0_SS();
2183: }
2184: } else {
2185: gen_op_andl_A0_ffff();
2186: gen_op_addl_A0_SS();
2187: }
2188: gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
1.1.1.6 ! root 2189:
1.1 root 2190: if (s->ss32 && !s->addseg)
2191: gen_op_movl_ESP_A0();
2192: else
2193: gen_stack_update(s, (-2) << s->dflag);
2194: }
2195: }
2196:
2197: /* two step pop is necessary for precise exceptions */
2198: static void gen_pop_T0(DisasContext *s)
2199: {
2200: #ifdef TARGET_X86_64
2201: if (CODE64(s)) {
2202: gen_op_movq_A0_reg[R_ESP]();
2203: gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index]();
1.1.1.6 ! root 2204: } else
1.1 root 2205: #endif
2206: {
2207: gen_op_movl_A0_reg[R_ESP]();
2208: if (s->ss32) {
2209: if (s->addseg)
2210: gen_op_addl_A0_SS();
2211: } else {
2212: gen_op_andl_A0_ffff();
2213: gen_op_addl_A0_SS();
2214: }
2215: gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2216: }
2217: }
2218:
2219: static void gen_pop_update(DisasContext *s)
2220: {
2221: #ifdef TARGET_X86_64
2222: if (CODE64(s) && s->dflag) {
2223: gen_stack_update(s, 8);
2224: } else
2225: #endif
2226: {
2227: gen_stack_update(s, 2 << s->dflag);
2228: }
2229: }
2230:
2231: static void gen_stack_A0(DisasContext *s)
2232: {
2233: gen_op_movl_A0_ESP();
2234: if (!s->ss32)
2235: gen_op_andl_A0_ffff();
2236: gen_op_movl_T1_A0();
2237: if (s->addseg)
2238: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2239: }
2240:
2241: /* NOTE: wrap around in 16 bit not fully handled */
2242: static void gen_pusha(DisasContext *s)
2243: {
2244: int i;
2245: gen_op_movl_A0_ESP();
2246: gen_op_addl_A0_im(-16 << s->dflag);
2247: if (!s->ss32)
2248: gen_op_andl_A0_ffff();
2249: gen_op_movl_T1_A0();
2250: if (s->addseg)
2251: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2252: for(i = 0;i < 8; i++) {
2253: gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
2254: gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2255: gen_op_addl_A0_im(2 << s->dflag);
2256: }
2257: gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2258: }
2259:
2260: /* NOTE: wrap around in 16 bit not fully handled */
2261: static void gen_popa(DisasContext *s)
2262: {
2263: int i;
2264: gen_op_movl_A0_ESP();
2265: if (!s->ss32)
2266: gen_op_andl_A0_ffff();
2267: gen_op_movl_T1_A0();
2268: gen_op_addl_T1_im(16 << s->dflag);
2269: if (s->addseg)
2270: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2271: for(i = 0;i < 8; i++) {
2272: /* ESP is not reloaded */
2273: if (i != 3) {
2274: gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2275: gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
2276: }
2277: gen_op_addl_A0_im(2 << s->dflag);
2278: }
2279: gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2280: }
2281:
2282: static void gen_enter(DisasContext *s, int esp_addend, int level)
2283: {
2284: int ot, opsize;
2285:
2286: level &= 0x1f;
2287: #ifdef TARGET_X86_64
2288: if (CODE64(s)) {
2289: ot = s->dflag ? OT_QUAD : OT_WORD;
2290: opsize = 1 << ot;
1.1.1.6 ! root 2291:
1.1 root 2292: gen_op_movl_A0_ESP();
2293: gen_op_addq_A0_im(-opsize);
2294: gen_op_movl_T1_A0();
2295:
2296: /* push bp */
2297: gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2298: gen_op_st_T0_A0[ot + s->mem_index]();
2299: if (level) {
2300: gen_op_enter64_level(level, (ot == OT_QUAD));
2301: }
2302: gen_op_mov_reg_T1[ot][R_EBP]();
2303: gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2304: gen_op_mov_reg_T1[OT_QUAD][R_ESP]();
1.1.1.6 ! root 2305: } else
1.1 root 2306: #endif
2307: {
2308: ot = s->dflag + OT_WORD;
2309: opsize = 2 << s->dflag;
1.1.1.6 ! root 2310:
1.1 root 2311: gen_op_movl_A0_ESP();
2312: gen_op_addl_A0_im(-opsize);
2313: if (!s->ss32)
2314: gen_op_andl_A0_ffff();
2315: gen_op_movl_T1_A0();
2316: if (s->addseg)
2317: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2318: /* push bp */
2319: gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2320: gen_op_st_T0_A0[ot + s->mem_index]();
2321: if (level) {
2322: gen_op_enter_level(level, s->dflag);
2323: }
2324: gen_op_mov_reg_T1[ot][R_EBP]();
2325: gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2326: gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2327: }
2328: }
2329:
2330: static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2331: {
2332: if (s->cc_op != CC_OP_DYNAMIC)
2333: gen_op_set_cc_op(s->cc_op);
2334: gen_jmp_im(cur_eip);
2335: gen_op_raise_exception(trapno);
2336: s->is_jmp = 3;
2337: }
2338:
2339: /* an interrupt is different from an exception because of the
1.1.1.6 ! root 2340: privilege checks */
! 2341: static void gen_interrupt(DisasContext *s, int intno,
1.1 root 2342: target_ulong cur_eip, target_ulong next_eip)
2343: {
2344: if (s->cc_op != CC_OP_DYNAMIC)
2345: gen_op_set_cc_op(s->cc_op);
2346: gen_jmp_im(cur_eip);
2347: gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
2348: s->is_jmp = 3;
2349: }
2350:
2351: static void gen_debug(DisasContext *s, target_ulong cur_eip)
2352: {
2353: if (s->cc_op != CC_OP_DYNAMIC)
2354: gen_op_set_cc_op(s->cc_op);
2355: gen_jmp_im(cur_eip);
2356: gen_op_debug();
2357: s->is_jmp = 3;
2358: }
2359:
2360: /* generate a generic end of block. Trace exception is also generated
2361: if needed */
2362: static void gen_eob(DisasContext *s)
2363: {
2364: if (s->cc_op != CC_OP_DYNAMIC)
2365: gen_op_set_cc_op(s->cc_op);
2366: if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2367: gen_op_reset_inhibit_irq();
2368: }
2369: if (s->singlestep_enabled) {
2370: gen_op_debug();
2371: } else if (s->tf) {
1.1.1.6 ! root 2372: gen_op_single_step();
1.1 root 2373: } else {
2374: gen_op_movl_T0_0();
2375: gen_op_exit_tb();
2376: }
2377: s->is_jmp = 3;
2378: }
2379:
2380: /* generate a jump to eip. No segment change must happen before as a
2381: direct call to the next block may occur */
2382: static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2383: {
2384: if (s->jmp_opt) {
1.1.1.2 root 2385: if (s->cc_op != CC_OP_DYNAMIC) {
1.1 root 2386: gen_op_set_cc_op(s->cc_op);
1.1.1.2 root 2387: s->cc_op = CC_OP_DYNAMIC;
2388: }
2389: gen_goto_tb(s, tb_num, eip);
1.1 root 2390: s->is_jmp = 3;
2391: } else {
2392: gen_jmp_im(eip);
2393: gen_eob(s);
2394: }
2395: }
2396:
2397: static void gen_jmp(DisasContext *s, target_ulong eip)
2398: {
2399: gen_jmp_tb(s, eip, 0);
2400: }
2401:
2402: static void gen_movtl_T0_im(target_ulong val)
2403: {
1.1.1.6 ! root 2404: #ifdef TARGET_X86_64
1.1 root 2405: if ((int32_t)val == val) {
2406: gen_op_movl_T0_im(val);
2407: } else {
2408: gen_op_movq_T0_im64(val >> 32, val);
2409: }
2410: #else
2411: gen_op_movl_T0_im(val);
2412: #endif
2413: }
2414:
2415: static void gen_movtl_T1_im(target_ulong val)
2416: {
1.1.1.6 ! root 2417: #ifdef TARGET_X86_64
1.1 root 2418: if ((int32_t)val == val) {
2419: gen_op_movl_T1_im(val);
2420: } else {
2421: gen_op_movq_T1_im64(val >> 32, val);
2422: }
2423: #else
2424: gen_op_movl_T1_im(val);
2425: #endif
2426: }
2427:
2428: static void gen_add_A0_im(DisasContext *s, int val)
2429: {
2430: #ifdef TARGET_X86_64
2431: if (CODE64(s))
2432: gen_op_addq_A0_im(val);
2433: else
2434: #endif
2435: gen_op_addl_A0_im(val);
2436: }
2437:
2438: static GenOpFunc1 *gen_ldq_env_A0[3] = {
2439: gen_op_ldq_raw_env_A0,
2440: #ifndef CONFIG_USER_ONLY
2441: gen_op_ldq_kernel_env_A0,
2442: gen_op_ldq_user_env_A0,
2443: #endif
2444: };
2445:
2446: static GenOpFunc1 *gen_stq_env_A0[3] = {
2447: gen_op_stq_raw_env_A0,
2448: #ifndef CONFIG_USER_ONLY
2449: gen_op_stq_kernel_env_A0,
2450: gen_op_stq_user_env_A0,
2451: #endif
2452: };
2453:
2454: static GenOpFunc1 *gen_ldo_env_A0[3] = {
2455: gen_op_ldo_raw_env_A0,
2456: #ifndef CONFIG_USER_ONLY
2457: gen_op_ldo_kernel_env_A0,
2458: gen_op_ldo_user_env_A0,
2459: #endif
2460: };
2461:
2462: static GenOpFunc1 *gen_sto_env_A0[3] = {
2463: gen_op_sto_raw_env_A0,
2464: #ifndef CONFIG_USER_ONLY
2465: gen_op_sto_kernel_env_A0,
2466: gen_op_sto_user_env_A0,
2467: #endif
2468: };
2469:
2470: #define SSE_SPECIAL ((GenOpFunc2 *)1)
2471:
2472: #define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm }
2473: #define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \
2474: gen_op_ ## x ## ss, gen_op_ ## x ## sd, }
2475:
2476: static GenOpFunc2 *sse_op_table1[256][4] = {
2477: /* pure SSE operations */
2478: [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2479: [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
1.1.1.3 root 2480: [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
1.1 root 2481: [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2482: [0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm },
2483: [0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm },
2484: [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2485: [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2486:
2487: [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2488: [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2489: [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2490: [0x2b] = { SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd */
2491: [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2492: [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2493: [0x2e] = { gen_op_ucomiss, gen_op_ucomisd },
2494: [0x2f] = { gen_op_comiss, gen_op_comisd },
2495: [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2496: [0x51] = SSE_FOP(sqrt),
2497: [0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL },
2498: [0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL },
2499: [0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */
2500: [0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */
2501: [0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */
2502: [0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */
2503: [0x58] = SSE_FOP(add),
2504: [0x59] = SSE_FOP(mul),
1.1.1.6 ! root 2505: [0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps,
1.1 root 2506: gen_op_cvtss2sd, gen_op_cvtsd2ss },
2507: [0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq },
2508: [0x5c] = SSE_FOP(sub),
2509: [0x5d] = SSE_FOP(min),
2510: [0x5e] = SSE_FOP(div),
2511: [0x5f] = SSE_FOP(max),
2512:
2513: [0xc2] = SSE_FOP(cmpeq),
2514: [0xc6] = { (GenOpFunc2 *)gen_op_shufps, (GenOpFunc2 *)gen_op_shufpd },
2515:
2516: /* MMX ops and their SSE extensions */
2517: [0x60] = MMX_OP2(punpcklbw),
2518: [0x61] = MMX_OP2(punpcklwd),
2519: [0x62] = MMX_OP2(punpckldq),
2520: [0x63] = MMX_OP2(packsswb),
2521: [0x64] = MMX_OP2(pcmpgtb),
2522: [0x65] = MMX_OP2(pcmpgtw),
2523: [0x66] = MMX_OP2(pcmpgtl),
2524: [0x67] = MMX_OP2(packuswb),
2525: [0x68] = MMX_OP2(punpckhbw),
2526: [0x69] = MMX_OP2(punpckhwd),
2527: [0x6a] = MMX_OP2(punpckhdq),
2528: [0x6b] = MMX_OP2(packssdw),
2529: [0x6c] = { NULL, gen_op_punpcklqdq_xmm },
2530: [0x6d] = { NULL, gen_op_punpckhqdq_xmm },
2531: [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2532: [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
1.1.1.6 ! root 2533: [0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx,
! 2534: (GenOpFunc2 *)gen_op_pshufd_xmm,
! 2535: (GenOpFunc2 *)gen_op_pshufhw_xmm,
1.1 root 2536: (GenOpFunc2 *)gen_op_pshuflw_xmm },
2537: [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2538: [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2539: [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2540: [0x74] = MMX_OP2(pcmpeqb),
2541: [0x75] = MMX_OP2(pcmpeqw),
2542: [0x76] = MMX_OP2(pcmpeql),
2543: [0x77] = { SSE_SPECIAL }, /* emms */
2544: [0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps },
2545: [0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps },
2546: [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2547: [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2548: [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2549: [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2550: [0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps },
2551: [0xd1] = MMX_OP2(psrlw),
2552: [0xd2] = MMX_OP2(psrld),
2553: [0xd3] = MMX_OP2(psrlq),
2554: [0xd4] = MMX_OP2(paddq),
2555: [0xd5] = MMX_OP2(pmullw),
2556: [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2557: [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2558: [0xd8] = MMX_OP2(psubusb),
2559: [0xd9] = MMX_OP2(psubusw),
2560: [0xda] = MMX_OP2(pminub),
2561: [0xdb] = MMX_OP2(pand),
2562: [0xdc] = MMX_OP2(paddusb),
2563: [0xdd] = MMX_OP2(paddusw),
2564: [0xde] = MMX_OP2(pmaxub),
2565: [0xdf] = MMX_OP2(pandn),
2566: [0xe0] = MMX_OP2(pavgb),
2567: [0xe1] = MMX_OP2(psraw),
2568: [0xe2] = MMX_OP2(psrad),
2569: [0xe3] = MMX_OP2(pavgw),
2570: [0xe4] = MMX_OP2(pmulhuw),
2571: [0xe5] = MMX_OP2(pmulhw),
2572: [0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq },
2573: [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2574: [0xe8] = MMX_OP2(psubsb),
2575: [0xe9] = MMX_OP2(psubsw),
2576: [0xea] = MMX_OP2(pminsw),
2577: [0xeb] = MMX_OP2(por),
2578: [0xec] = MMX_OP2(paddsb),
2579: [0xed] = MMX_OP2(paddsw),
2580: [0xee] = MMX_OP2(pmaxsw),
2581: [0xef] = MMX_OP2(pxor),
1.1.1.3 root 2582: [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
1.1 root 2583: [0xf1] = MMX_OP2(psllw),
2584: [0xf2] = MMX_OP2(pslld),
2585: [0xf3] = MMX_OP2(psllq),
2586: [0xf4] = MMX_OP2(pmuludq),
2587: [0xf5] = MMX_OP2(pmaddwd),
2588: [0xf6] = MMX_OP2(psadbw),
2589: [0xf7] = MMX_OP2(maskmov),
2590: [0xf8] = MMX_OP2(psubb),
2591: [0xf9] = MMX_OP2(psubw),
2592: [0xfa] = MMX_OP2(psubl),
2593: [0xfb] = MMX_OP2(psubq),
2594: [0xfc] = MMX_OP2(paddb),
2595: [0xfd] = MMX_OP2(paddw),
2596: [0xfe] = MMX_OP2(paddl),
2597: };
2598:
2599: static GenOpFunc2 *sse_op_table2[3 * 8][2] = {
2600: [0 + 2] = MMX_OP2(psrlw),
2601: [0 + 4] = MMX_OP2(psraw),
2602: [0 + 6] = MMX_OP2(psllw),
2603: [8 + 2] = MMX_OP2(psrld),
2604: [8 + 4] = MMX_OP2(psrad),
2605: [8 + 6] = MMX_OP2(pslld),
2606: [16 + 2] = MMX_OP2(psrlq),
2607: [16 + 3] = { NULL, gen_op_psrldq_xmm },
2608: [16 + 6] = MMX_OP2(psllq),
2609: [16 + 7] = { NULL, gen_op_pslldq_xmm },
2610: };
2611:
2612: static GenOpFunc1 *sse_op_table3[4 * 3] = {
2613: gen_op_cvtsi2ss,
2614: gen_op_cvtsi2sd,
2615: X86_64_ONLY(gen_op_cvtsq2ss),
2616: X86_64_ONLY(gen_op_cvtsq2sd),
1.1.1.6 ! root 2617:
1.1 root 2618: gen_op_cvttss2si,
2619: gen_op_cvttsd2si,
2620: X86_64_ONLY(gen_op_cvttss2sq),
2621: X86_64_ONLY(gen_op_cvttsd2sq),
2622:
2623: gen_op_cvtss2si,
2624: gen_op_cvtsd2si,
2625: X86_64_ONLY(gen_op_cvtss2sq),
2626: X86_64_ONLY(gen_op_cvtsd2sq),
2627: };
1.1.1.6 ! root 2628:
1.1 root 2629: static GenOpFunc2 *sse_op_table4[8][4] = {
2630: SSE_FOP(cmpeq),
2631: SSE_FOP(cmplt),
2632: SSE_FOP(cmple),
2633: SSE_FOP(cmpunord),
2634: SSE_FOP(cmpneq),
2635: SSE_FOP(cmpnlt),
2636: SSE_FOP(cmpnle),
2637: SSE_FOP(cmpord),
2638: };
1.1.1.6 ! root 2639:
1.1 root 2640: static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2641: {
2642: int b1, op1_offset, op2_offset, is_xmm, val, ot;
2643: int modrm, mod, rm, reg, reg_addr, offset_addr;
2644: GenOpFunc2 *sse_op2;
2645: GenOpFunc3 *sse_op3;
2646:
2647: b &= 0xff;
1.1.1.6 ! root 2648: if (s->prefix & PREFIX_DATA)
1.1 root 2649: b1 = 1;
1.1.1.6 ! root 2650: else if (s->prefix & PREFIX_REPZ)
1.1 root 2651: b1 = 2;
1.1.1.6 ! root 2652: else if (s->prefix & PREFIX_REPNZ)
1.1 root 2653: b1 = 3;
2654: else
2655: b1 = 0;
2656: sse_op2 = sse_op_table1[b][b1];
1.1.1.6 ! root 2657: if (!sse_op2)
1.1 root 2658: goto illegal_op;
2659: if (b <= 0x5f || b == 0xc6 || b == 0xc2) {
2660: is_xmm = 1;
2661: } else {
2662: if (b1 == 0) {
2663: /* MMX case */
2664: is_xmm = 0;
2665: } else {
2666: is_xmm = 1;
2667: }
2668: }
2669: /* simple MMX/SSE operation */
2670: if (s->flags & HF_TS_MASK) {
2671: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2672: return;
2673: }
2674: if (s->flags & HF_EM_MASK) {
2675: illegal_op:
2676: gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2677: return;
2678: }
2679: if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2680: goto illegal_op;
2681: if (b == 0x77) {
2682: /* emms */
2683: gen_op_emms();
2684: return;
2685: }
2686: /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2687: the static cpu state) */
2688: if (!is_xmm) {
2689: gen_op_enter_mmx();
2690: }
2691:
2692: modrm = ldub_code(s->pc++);
2693: reg = ((modrm >> 3) & 7);
2694: if (is_xmm)
2695: reg |= rex_r;
2696: mod = (modrm >> 6) & 3;
2697: if (sse_op2 == SSE_SPECIAL) {
2698: b |= (b1 << 8);
2699: switch(b) {
2700: case 0x0e7: /* movntq */
1.1.1.6 ! root 2701: if (mod == 3)
1.1 root 2702: goto illegal_op;
2703: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2704: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2705: break;
2706: case 0x1e7: /* movntdq */
2707: case 0x02b: /* movntps */
2708: case 0x12b: /* movntps */
1.1.1.3 root 2709: case 0x3f0: /* lddqu */
2710: if (mod == 3)
1.1 root 2711: goto illegal_op;
2712: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2713: gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2714: break;
2715: case 0x6e: /* movd mm, ea */
1.1.1.5 root 2716: #ifdef TARGET_X86_64
2717: if (s->dflag == 2) {
2718: gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2719: gen_op_movq_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
1.1.1.6 ! root 2720: } else
1.1.1.5 root 2721: #endif
2722: {
2723: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2724: gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2725: }
1.1 root 2726: break;
2727: case 0x16e: /* movd xmm, ea */
1.1.1.5 root 2728: #ifdef TARGET_X86_64
2729: if (s->dflag == 2) {
2730: gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2731: gen_op_movq_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
1.1.1.6 ! root 2732: } else
1.1.1.5 root 2733: #endif
2734: {
2735: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2736: gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2737: }
1.1 root 2738: break;
2739: case 0x6f: /* movq mm, ea */
2740: if (mod != 3) {
2741: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2742: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2743: } else {
2744: rm = (modrm & 7);
2745: gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx),
2746: offsetof(CPUX86State,fpregs[rm].mmx));
2747: }
2748: break;
2749: case 0x010: /* movups */
2750: case 0x110: /* movupd */
2751: case 0x028: /* movaps */
2752: case 0x128: /* movapd */
2753: case 0x16f: /* movdqa xmm, ea */
2754: case 0x26f: /* movdqu xmm, ea */
2755: if (mod != 3) {
2756: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2757: gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2758: } else {
2759: rm = (modrm & 7) | REX_B(s);
2760: gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2761: offsetof(CPUX86State,xmm_regs[rm]));
2762: }
2763: break;
2764: case 0x210: /* movss xmm, ea */
2765: if (mod != 3) {
2766: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2767: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2768: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2769: gen_op_movl_T0_0();
2770: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2771: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2772: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2773: } else {
2774: rm = (modrm & 7) | REX_B(s);
2775: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2776: offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2777: }
2778: break;
2779: case 0x310: /* movsd xmm, ea */
2780: if (mod != 3) {
2781: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2782: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2783: gen_op_movl_T0_0();
2784: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2785: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2786: } else {
2787: rm = (modrm & 7) | REX_B(s);
2788: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2789: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2790: }
2791: break;
2792: case 0x012: /* movlps */
2793: case 0x112: /* movlpd */
2794: if (mod != 3) {
2795: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2796: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2797: } else {
2798: /* movhlps */
2799: rm = (modrm & 7) | REX_B(s);
2800: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2801: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2802: }
2803: break;
1.1.1.3 root 2804: case 0x212: /* movsldup */
2805: if (mod != 3) {
2806: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2807: gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2808: } else {
2809: rm = (modrm & 7) | REX_B(s);
2810: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2811: offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2812: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2813: offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
2814: }
2815: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2816: offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2817: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2818: offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2819: break;
2820: case 0x312: /* movddup */
2821: if (mod != 3) {
2822: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2823: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2824: } else {
2825: rm = (modrm & 7) | REX_B(s);
2826: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2827: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2828: }
2829: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2830: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2831: break;
1.1 root 2832: case 0x016: /* movhps */
2833: case 0x116: /* movhpd */
2834: if (mod != 3) {
2835: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2836: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2837: } else {
2838: /* movlhps */
2839: rm = (modrm & 7) | REX_B(s);
2840: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2841: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2842: }
2843: break;
2844: case 0x216: /* movshdup */
2845: if (mod != 3) {
2846: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2847: gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2848: } else {
2849: rm = (modrm & 7) | REX_B(s);
2850: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2851: offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
2852: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2853: offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
2854: }
2855: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2856: offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2857: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2858: offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2859: break;
2860: case 0x7e: /* movd ea, mm */
1.1.1.5 root 2861: #ifdef TARGET_X86_64
2862: if (s->dflag == 2) {
2863: gen_op_movq_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2864: gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
1.1.1.6 ! root 2865: } else
1.1.1.5 root 2866: #endif
2867: {
2868: gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2869: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2870: }
1.1 root 2871: break;
2872: case 0x17e: /* movd ea, xmm */
1.1.1.5 root 2873: #ifdef TARGET_X86_64
2874: if (s->dflag == 2) {
2875: gen_op_movq_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2876: gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
1.1.1.6 ! root 2877: } else
1.1.1.5 root 2878: #endif
2879: {
2880: gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2881: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2882: }
1.1 root 2883: break;
2884: case 0x27e: /* movq xmm, ea */
2885: if (mod != 3) {
2886: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2887: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2888: } else {
2889: rm = (modrm & 7) | REX_B(s);
2890: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2891: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2892: }
2893: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2894: break;
2895: case 0x7f: /* movq ea, mm */
2896: if (mod != 3) {
2897: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2898: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2899: } else {
2900: rm = (modrm & 7);
2901: gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2902: offsetof(CPUX86State,fpregs[reg].mmx));
2903: }
2904: break;
2905: case 0x011: /* movups */
2906: case 0x111: /* movupd */
2907: case 0x029: /* movaps */
2908: case 0x129: /* movapd */
2909: case 0x17f: /* movdqa ea, xmm */
2910: case 0x27f: /* movdqu ea, xmm */
2911: if (mod != 3) {
2912: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2913: gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2914: } else {
2915: rm = (modrm & 7) | REX_B(s);
2916: gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
2917: offsetof(CPUX86State,xmm_regs[reg]));
2918: }
2919: break;
2920: case 0x211: /* movss ea, xmm */
2921: if (mod != 3) {
2922: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2923: gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2924: gen_op_st_T0_A0[OT_LONG + s->mem_index]();
2925: } else {
2926: rm = (modrm & 7) | REX_B(s);
2927: gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
2928: offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2929: }
2930: break;
2931: case 0x311: /* movsd ea, xmm */
2932: if (mod != 3) {
2933: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2934: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2935: } else {
2936: rm = (modrm & 7) | REX_B(s);
2937: gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2938: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2939: }
2940: break;
2941: case 0x013: /* movlps */
2942: case 0x113: /* movlpd */
2943: if (mod != 3) {
2944: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2945: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2946: } else {
2947: goto illegal_op;
2948: }
2949: break;
2950: case 0x017: /* movhps */
2951: case 0x117: /* movhpd */
2952: if (mod != 3) {
2953: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2954: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2955: } else {
2956: goto illegal_op;
2957: }
2958: break;
2959: case 0x71: /* shift mm, im */
2960: case 0x72:
2961: case 0x73:
2962: case 0x171: /* shift xmm, im */
2963: case 0x172:
2964: case 0x173:
2965: val = ldub_code(s->pc++);
2966: if (is_xmm) {
2967: gen_op_movl_T0_im(val);
2968: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2969: gen_op_movl_T0_0();
2970: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1)));
2971: op1_offset = offsetof(CPUX86State,xmm_t0);
2972: } else {
2973: gen_op_movl_T0_im(val);
2974: gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0)));
2975: gen_op_movl_T0_0();
2976: gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1)));
2977: op1_offset = offsetof(CPUX86State,mmx_t0);
2978: }
2979: sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
2980: if (!sse_op2)
2981: goto illegal_op;
2982: if (is_xmm) {
2983: rm = (modrm & 7) | REX_B(s);
2984: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2985: } else {
2986: rm = (modrm & 7);
2987: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2988: }
2989: sse_op2(op2_offset, op1_offset);
2990: break;
2991: case 0x050: /* movmskps */
2992: rm = (modrm & 7) | REX_B(s);
2993: gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm]));
2994: gen_op_mov_reg_T0[OT_LONG][reg]();
2995: break;
2996: case 0x150: /* movmskpd */
2997: rm = (modrm & 7) | REX_B(s);
2998: gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm]));
2999: gen_op_mov_reg_T0[OT_LONG][reg]();
3000: break;
3001: case 0x02a: /* cvtpi2ps */
3002: case 0x12a: /* cvtpi2pd */
3003: gen_op_enter_mmx();
3004: if (mod != 3) {
3005: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3006: op2_offset = offsetof(CPUX86State,mmx_t0);
3007: gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3008: } else {
3009: rm = (modrm & 7);
3010: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3011: }
3012: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3013: switch(b >> 8) {
3014: case 0x0:
3015: gen_op_cvtpi2ps(op1_offset, op2_offset);
3016: break;
3017: default:
3018: case 0x1:
3019: gen_op_cvtpi2pd(op1_offset, op2_offset);
3020: break;
3021: }
3022: break;
3023: case 0x22a: /* cvtsi2ss */
3024: case 0x32a: /* cvtsi2sd */
3025: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3026: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3027: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3028: sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset);
3029: break;
3030: case 0x02c: /* cvttps2pi */
3031: case 0x12c: /* cvttpd2pi */
3032: case 0x02d: /* cvtps2pi */
3033: case 0x12d: /* cvtpd2pi */
3034: gen_op_enter_mmx();
3035: if (mod != 3) {
3036: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3037: op2_offset = offsetof(CPUX86State,xmm_t0);
3038: gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3039: } else {
3040: rm = (modrm & 7) | REX_B(s);
3041: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3042: }
3043: op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3044: switch(b) {
3045: case 0x02c:
3046: gen_op_cvttps2pi(op1_offset, op2_offset);
3047: break;
3048: case 0x12c:
3049: gen_op_cvttpd2pi(op1_offset, op2_offset);
3050: break;
3051: case 0x02d:
3052: gen_op_cvtps2pi(op1_offset, op2_offset);
3053: break;
3054: case 0x12d:
3055: gen_op_cvtpd2pi(op1_offset, op2_offset);
3056: break;
3057: }
3058: break;
3059: case 0x22c: /* cvttss2si */
3060: case 0x32c: /* cvttsd2si */
3061: case 0x22d: /* cvtss2si */
3062: case 0x32d: /* cvtsd2si */
3063: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3064: if (mod != 3) {
3065: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3066: if ((b >> 8) & 1) {
3067: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
3068: } else {
3069: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3070: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3071: }
3072: op2_offset = offsetof(CPUX86State,xmm_t0);
3073: } else {
3074: rm = (modrm & 7) | REX_B(s);
3075: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3076: }
1.1.1.6 ! root 3077: sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
1.1 root 3078: (b & 1) * 4](op2_offset);
3079: gen_op_mov_reg_T0[ot][reg]();
3080: break;
3081: case 0xc4: /* pinsrw */
1.1.1.6 ! root 3082: case 0x1c4:
1.1.1.4 root 3083: s->rip_offset = 1;
1.1 root 3084: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3085: val = ldub_code(s->pc++);
3086: if (b1) {
3087: val &= 7;
3088: gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val);
3089: } else {
3090: val &= 3;
3091: gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val);
3092: }
3093: break;
3094: case 0xc5: /* pextrw */
1.1.1.6 ! root 3095: case 0x1c5:
1.1 root 3096: if (mod != 3)
3097: goto illegal_op;
3098: val = ldub_code(s->pc++);
3099: if (b1) {
3100: val &= 7;
3101: rm = (modrm & 7) | REX_B(s);
3102: gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val);
3103: } else {
3104: val &= 3;
3105: rm = (modrm & 7);
3106: gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val);
3107: }
3108: reg = ((modrm >> 3) & 7) | rex_r;
3109: gen_op_mov_reg_T0[OT_LONG][reg]();
3110: break;
3111: case 0x1d6: /* movq ea, xmm */
3112: if (mod != 3) {
3113: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3114: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3115: } else {
3116: rm = (modrm & 7) | REX_B(s);
3117: gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3118: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3119: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3120: }
3121: break;
3122: case 0x2d6: /* movq2dq */
3123: gen_op_enter_mmx();
1.1.1.4 root 3124: rm = (modrm & 7);
3125: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3126: offsetof(CPUX86State,fpregs[rm].mmx));
3127: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
1.1 root 3128: break;
3129: case 0x3d6: /* movdq2q */
3130: gen_op_enter_mmx();
1.1.1.4 root 3131: rm = (modrm & 7) | REX_B(s);
3132: gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3133: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
1.1 root 3134: break;
3135: case 0xd7: /* pmovmskb */
3136: case 0x1d7:
3137: if (mod != 3)
3138: goto illegal_op;
3139: if (b1) {
3140: rm = (modrm & 7) | REX_B(s);
3141: gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm]));
3142: } else {
3143: rm = (modrm & 7);
3144: gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx));
3145: }
3146: reg = ((modrm >> 3) & 7) | rex_r;
3147: gen_op_mov_reg_T0[OT_LONG][reg]();
3148: break;
3149: default:
3150: goto illegal_op;
3151: }
3152: } else {
3153: /* generic MMX or SSE operation */
1.1.1.4 root 3154: switch(b) {
3155: case 0xf7:
1.1 root 3156: /* maskmov : we must prepare A0 */
1.1.1.6 ! root 3157: if (mod != 3)
1.1 root 3158: goto illegal_op;
3159: #ifdef TARGET_X86_64
3160: if (s->aflag == 2) {
3161: gen_op_movq_A0_reg[R_EDI]();
1.1.1.6 ! root 3162: } else
1.1 root 3163: #endif
3164: {
3165: gen_op_movl_A0_reg[R_EDI]();
3166: if (s->aflag == 0)
3167: gen_op_andl_A0_ffff();
3168: }
3169: gen_add_A0_ds_seg(s);
1.1.1.4 root 3170: break;
3171: case 0x70: /* pshufx insn */
3172: case 0xc6: /* pshufx insn */
3173: case 0xc2: /* compare insns */
3174: s->rip_offset = 1;
3175: break;
3176: default:
3177: break;
1.1 root 3178: }
3179: if (is_xmm) {
3180: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3181: if (mod != 3) {
3182: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3183: op2_offset = offsetof(CPUX86State,xmm_t0);
1.1.1.4 root 3184: if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
1.1 root 3185: b == 0xc2)) {
3186: /* specific case for SSE single instructions */
3187: if (b1 == 2) {
3188: /* 32 bit access */
3189: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3190: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3191: } else {
3192: /* 64 bit access */
3193: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_D(0)));
3194: }
3195: } else {
3196: gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3197: }
3198: } else {
3199: rm = (modrm & 7) | REX_B(s);
3200: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3201: }
3202: } else {
3203: op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3204: if (mod != 3) {
3205: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3206: op2_offset = offsetof(CPUX86State,mmx_t0);
3207: gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3208: } else {
3209: rm = (modrm & 7);
3210: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3211: }
3212: }
3213: switch(b) {
3214: case 0x70: /* pshufx insn */
3215: case 0xc6: /* pshufx insn */
3216: val = ldub_code(s->pc++);
3217: sse_op3 = (GenOpFunc3 *)sse_op2;
3218: sse_op3(op1_offset, op2_offset, val);
3219: break;
3220: case 0xc2:
3221: /* compare insns */
3222: val = ldub_code(s->pc++);
3223: if (val >= 8)
3224: goto illegal_op;
3225: sse_op2 = sse_op_table4[val][b1];
3226: sse_op2(op1_offset, op2_offset);
3227: break;
3228: default:
3229: sse_op2(op1_offset, op2_offset);
3230: break;
3231: }
3232: if (b == 0x2e || b == 0x2f) {
3233: s->cc_op = CC_OP_EFLAGS;
3234: }
3235: }
3236: }
3237:
3238:
3239: /* convert one instruction. s->is_jmp is set if the translation must
3240: be stopped. Return the next pc value */
3241: static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
3242: {
3243: int b, prefixes, aflag, dflag;
3244: int shift, ot;
3245: int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
3246: target_ulong next_eip, tval;
3247: int rex_w, rex_r;
3248:
3249: s->pc = pc_start;
3250: prefixes = 0;
3251: aflag = s->code32;
3252: dflag = s->code32;
3253: s->override = -1;
3254: rex_w = -1;
3255: rex_r = 0;
3256: #ifdef TARGET_X86_64
3257: s->rex_x = 0;
3258: s->rex_b = 0;
1.1.1.6 ! root 3259: x86_64_hregs = 0;
1.1 root 3260: #endif
3261: s->rip_offset = 0; /* for relative ip address */
3262: next_byte:
3263: b = ldub_code(s->pc);
3264: s->pc++;
3265: /* check prefixes */
3266: #ifdef TARGET_X86_64
3267: if (CODE64(s)) {
3268: switch (b) {
3269: case 0xf3:
3270: prefixes |= PREFIX_REPZ;
3271: goto next_byte;
3272: case 0xf2:
3273: prefixes |= PREFIX_REPNZ;
3274: goto next_byte;
3275: case 0xf0:
3276: prefixes |= PREFIX_LOCK;
3277: goto next_byte;
3278: case 0x2e:
3279: s->override = R_CS;
3280: goto next_byte;
3281: case 0x36:
3282: s->override = R_SS;
3283: goto next_byte;
3284: case 0x3e:
3285: s->override = R_DS;
3286: goto next_byte;
3287: case 0x26:
3288: s->override = R_ES;
3289: goto next_byte;
3290: case 0x64:
3291: s->override = R_FS;
3292: goto next_byte;
3293: case 0x65:
3294: s->override = R_GS;
3295: goto next_byte;
3296: case 0x66:
3297: prefixes |= PREFIX_DATA;
3298: goto next_byte;
3299: case 0x67:
3300: prefixes |= PREFIX_ADR;
3301: goto next_byte;
3302: case 0x40 ... 0x4f:
3303: /* REX prefix */
3304: rex_w = (b >> 3) & 1;
3305: rex_r = (b & 0x4) << 1;
3306: s->rex_x = (b & 0x2) << 2;
3307: REX_B(s) = (b & 0x1) << 3;
3308: x86_64_hregs = 1; /* select uniform byte register addressing */
3309: goto next_byte;
3310: }
3311: if (rex_w == 1) {
3312: /* 0x66 is ignored if rex.w is set */
3313: dflag = 2;
3314: } else {
3315: if (prefixes & PREFIX_DATA)
3316: dflag ^= 1;
3317: }
3318: if (!(prefixes & PREFIX_ADR))
3319: aflag = 2;
1.1.1.6 ! root 3320: } else
1.1 root 3321: #endif
3322: {
3323: switch (b) {
3324: case 0xf3:
3325: prefixes |= PREFIX_REPZ;
3326: goto next_byte;
3327: case 0xf2:
3328: prefixes |= PREFIX_REPNZ;
3329: goto next_byte;
3330: case 0xf0:
3331: prefixes |= PREFIX_LOCK;
3332: goto next_byte;
3333: case 0x2e:
3334: s->override = R_CS;
3335: goto next_byte;
3336: case 0x36:
3337: s->override = R_SS;
3338: goto next_byte;
3339: case 0x3e:
3340: s->override = R_DS;
3341: goto next_byte;
3342: case 0x26:
3343: s->override = R_ES;
3344: goto next_byte;
3345: case 0x64:
3346: s->override = R_FS;
3347: goto next_byte;
3348: case 0x65:
3349: s->override = R_GS;
3350: goto next_byte;
3351: case 0x66:
3352: prefixes |= PREFIX_DATA;
3353: goto next_byte;
3354: case 0x67:
3355: prefixes |= PREFIX_ADR;
3356: goto next_byte;
3357: }
3358: if (prefixes & PREFIX_DATA)
3359: dflag ^= 1;
3360: if (prefixes & PREFIX_ADR)
3361: aflag ^= 1;
3362: }
3363:
3364: s->prefix = prefixes;
3365: s->aflag = aflag;
3366: s->dflag = dflag;
3367:
3368: /* lock generation */
3369: if (prefixes & PREFIX_LOCK)
3370: gen_op_lock();
3371:
3372: /* now check op code */
3373: reswitch:
3374: switch(b) {
3375: case 0x0f:
3376: /**************************/
3377: /* extended op code */
3378: b = ldub_code(s->pc++) | 0x100;
3379: goto reswitch;
1.1.1.6 ! root 3380:
1.1 root 3381: /**************************/
3382: /* arith & logic */
3383: case 0x00 ... 0x05:
3384: case 0x08 ... 0x0d:
3385: case 0x10 ... 0x15:
3386: case 0x18 ... 0x1d:
3387: case 0x20 ... 0x25:
3388: case 0x28 ... 0x2d:
3389: case 0x30 ... 0x35:
3390: case 0x38 ... 0x3d:
3391: {
3392: int op, f, val;
3393: op = (b >> 3) & 7;
3394: f = (b >> 1) & 3;
3395:
3396: if ((b & 1) == 0)
3397: ot = OT_BYTE;
3398: else
3399: ot = dflag + OT_WORD;
1.1.1.6 ! root 3400:
1.1 root 3401: switch(f) {
3402: case 0: /* OP Ev, Gv */
3403: modrm = ldub_code(s->pc++);
3404: reg = ((modrm >> 3) & 7) | rex_r;
3405: mod = (modrm >> 6) & 3;
3406: rm = (modrm & 7) | REX_B(s);
3407: if (mod != 3) {
3408: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3409: opreg = OR_TMP0;
3410: } else if (op == OP_XORL && rm == reg) {
3411: xor_zero:
3412: /* xor reg, reg optimisation */
3413: gen_op_movl_T0_0();
3414: s->cc_op = CC_OP_LOGICB + ot;
3415: gen_op_mov_reg_T0[ot][reg]();
3416: gen_op_update1_cc();
3417: break;
3418: } else {
3419: opreg = rm;
3420: }
3421: gen_op_mov_TN_reg[ot][1][reg]();
3422: gen_op(s, op, ot, opreg);
3423: break;
3424: case 1: /* OP Gv, Ev */
3425: modrm = ldub_code(s->pc++);
3426: mod = (modrm >> 6) & 3;
3427: reg = ((modrm >> 3) & 7) | rex_r;
3428: rm = (modrm & 7) | REX_B(s);
3429: if (mod != 3) {
3430: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3431: gen_op_ld_T1_A0[ot + s->mem_index]();
3432: } else if (op == OP_XORL && rm == reg) {
3433: goto xor_zero;
3434: } else {
3435: gen_op_mov_TN_reg[ot][1][rm]();
3436: }
3437: gen_op(s, op, ot, reg);
3438: break;
3439: case 2: /* OP A, Iv */
3440: val = insn_get(s, ot);
3441: gen_op_movl_T1_im(val);
3442: gen_op(s, op, ot, OR_EAX);
3443: break;
3444: }
3445: }
3446: break;
3447:
3448: case 0x80: /* GRP1 */
3449: case 0x81:
3450: case 0x82:
3451: case 0x83:
3452: {
3453: int val;
3454:
3455: if ((b & 1) == 0)
3456: ot = OT_BYTE;
3457: else
3458: ot = dflag + OT_WORD;
1.1.1.6 ! root 3459:
1.1 root 3460: modrm = ldub_code(s->pc++);
3461: mod = (modrm >> 6) & 3;
3462: rm = (modrm & 7) | REX_B(s);
3463: op = (modrm >> 3) & 7;
1.1.1.6 ! root 3464:
1.1 root 3465: if (mod != 3) {
3466: if (b == 0x83)
3467: s->rip_offset = 1;
3468: else
3469: s->rip_offset = insn_const_size(ot);
3470: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3471: opreg = OR_TMP0;
3472: } else {
3473: opreg = rm;
3474: }
3475:
3476: switch(b) {
3477: default:
3478: case 0x80:
3479: case 0x81:
3480: case 0x82:
3481: val = insn_get(s, ot);
3482: break;
3483: case 0x83:
3484: val = (int8_t)insn_get(s, OT_BYTE);
3485: break;
3486: }
3487: gen_op_movl_T1_im(val);
3488: gen_op(s, op, ot, opreg);
3489: }
3490: break;
3491:
3492: /**************************/
3493: /* inc, dec, and other misc arith */
3494: case 0x40 ... 0x47: /* inc Gv */
3495: ot = dflag ? OT_LONG : OT_WORD;
3496: gen_inc(s, ot, OR_EAX + (b & 7), 1);
3497: break;
3498: case 0x48 ... 0x4f: /* dec Gv */
3499: ot = dflag ? OT_LONG : OT_WORD;
3500: gen_inc(s, ot, OR_EAX + (b & 7), -1);
3501: break;
3502: case 0xf6: /* GRP3 */
3503: case 0xf7:
3504: if ((b & 1) == 0)
3505: ot = OT_BYTE;
3506: else
3507: ot = dflag + OT_WORD;
3508:
3509: modrm = ldub_code(s->pc++);
3510: mod = (modrm >> 6) & 3;
3511: rm = (modrm & 7) | REX_B(s);
3512: op = (modrm >> 3) & 7;
3513: if (mod != 3) {
3514: if (op == 0)
3515: s->rip_offset = insn_const_size(ot);
3516: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3517: gen_op_ld_T0_A0[ot + s->mem_index]();
3518: } else {
3519: gen_op_mov_TN_reg[ot][0][rm]();
3520: }
3521:
3522: switch(op) {
3523: case 0: /* test */
3524: val = insn_get(s, ot);
3525: gen_op_movl_T1_im(val);
3526: gen_op_testl_T0_T1_cc();
3527: s->cc_op = CC_OP_LOGICB + ot;
3528: break;
3529: case 2: /* not */
3530: gen_op_notl_T0();
3531: if (mod != 3) {
3532: gen_op_st_T0_A0[ot + s->mem_index]();
3533: } else {
3534: gen_op_mov_reg_T0[ot][rm]();
3535: }
3536: break;
3537: case 3: /* neg */
3538: gen_op_negl_T0();
3539: if (mod != 3) {
3540: gen_op_st_T0_A0[ot + s->mem_index]();
3541: } else {
3542: gen_op_mov_reg_T0[ot][rm]();
3543: }
3544: gen_op_update_neg_cc();
3545: s->cc_op = CC_OP_SUBB + ot;
3546: break;
3547: case 4: /* mul */
3548: switch(ot) {
3549: case OT_BYTE:
3550: gen_op_mulb_AL_T0();
3551: s->cc_op = CC_OP_MULB;
3552: break;
3553: case OT_WORD:
3554: gen_op_mulw_AX_T0();
3555: s->cc_op = CC_OP_MULW;
3556: break;
3557: default:
3558: case OT_LONG:
3559: gen_op_mull_EAX_T0();
3560: s->cc_op = CC_OP_MULL;
3561: break;
3562: #ifdef TARGET_X86_64
3563: case OT_QUAD:
3564: gen_op_mulq_EAX_T0();
3565: s->cc_op = CC_OP_MULQ;
3566: break;
3567: #endif
3568: }
3569: break;
3570: case 5: /* imul */
3571: switch(ot) {
3572: case OT_BYTE:
3573: gen_op_imulb_AL_T0();
3574: s->cc_op = CC_OP_MULB;
3575: break;
3576: case OT_WORD:
3577: gen_op_imulw_AX_T0();
3578: s->cc_op = CC_OP_MULW;
3579: break;
3580: default:
3581: case OT_LONG:
3582: gen_op_imull_EAX_T0();
3583: s->cc_op = CC_OP_MULL;
3584: break;
3585: #ifdef TARGET_X86_64
3586: case OT_QUAD:
3587: gen_op_imulq_EAX_T0();
3588: s->cc_op = CC_OP_MULQ;
3589: break;
3590: #endif
3591: }
3592: break;
3593: case 6: /* div */
3594: switch(ot) {
3595: case OT_BYTE:
3596: gen_jmp_im(pc_start - s->cs_base);
3597: gen_op_divb_AL_T0();
3598: break;
3599: case OT_WORD:
3600: gen_jmp_im(pc_start - s->cs_base);
3601: gen_op_divw_AX_T0();
3602: break;
3603: default:
3604: case OT_LONG:
3605: gen_jmp_im(pc_start - s->cs_base);
3606: gen_op_divl_EAX_T0();
3607: break;
3608: #ifdef TARGET_X86_64
3609: case OT_QUAD:
3610: gen_jmp_im(pc_start - s->cs_base);
3611: gen_op_divq_EAX_T0();
3612: break;
3613: #endif
3614: }
3615: break;
3616: case 7: /* idiv */
3617: switch(ot) {
3618: case OT_BYTE:
3619: gen_jmp_im(pc_start - s->cs_base);
3620: gen_op_idivb_AL_T0();
3621: break;
3622: case OT_WORD:
3623: gen_jmp_im(pc_start - s->cs_base);
3624: gen_op_idivw_AX_T0();
3625: break;
3626: default:
3627: case OT_LONG:
3628: gen_jmp_im(pc_start - s->cs_base);
3629: gen_op_idivl_EAX_T0();
3630: break;
3631: #ifdef TARGET_X86_64
3632: case OT_QUAD:
3633: gen_jmp_im(pc_start - s->cs_base);
3634: gen_op_idivq_EAX_T0();
3635: break;
3636: #endif
3637: }
3638: break;
3639: default:
3640: goto illegal_op;
3641: }
3642: break;
3643:
3644: case 0xfe: /* GRP4 */
3645: case 0xff: /* GRP5 */
3646: if ((b & 1) == 0)
3647: ot = OT_BYTE;
3648: else
3649: ot = dflag + OT_WORD;
3650:
3651: modrm = ldub_code(s->pc++);
3652: mod = (modrm >> 6) & 3;
3653: rm = (modrm & 7) | REX_B(s);
3654: op = (modrm >> 3) & 7;
3655: if (op >= 2 && b == 0xfe) {
3656: goto illegal_op;
3657: }
3658: if (CODE64(s)) {
3659: if (op == 2 || op == 4) {
3660: /* operand size for jumps is 64 bit */
3661: ot = OT_QUAD;
3662: } else if (op == 3 || op == 5) {
3663: /* for call calls, the operand is 16 or 32 bit, even
3664: in long mode */
3665: ot = dflag ? OT_LONG : OT_WORD;
3666: } else if (op == 6) {
3667: /* default push size is 64 bit */
3668: ot = dflag ? OT_QUAD : OT_WORD;
3669: }
3670: }
3671: if (mod != 3) {
3672: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3673: if (op >= 2 && op != 3 && op != 5)
3674: gen_op_ld_T0_A0[ot + s->mem_index]();
3675: } else {
3676: gen_op_mov_TN_reg[ot][0][rm]();
3677: }
3678:
3679: switch(op) {
3680: case 0: /* inc Ev */
3681: if (mod != 3)
3682: opreg = OR_TMP0;
3683: else
3684: opreg = rm;
3685: gen_inc(s, ot, opreg, 1);
3686: break;
3687: case 1: /* dec Ev */
3688: if (mod != 3)
3689: opreg = OR_TMP0;
3690: else
3691: opreg = rm;
3692: gen_inc(s, ot, opreg, -1);
3693: break;
3694: case 2: /* call Ev */
3695: /* XXX: optimize if memory (no 'and' is necessary) */
3696: if (s->dflag == 0)
3697: gen_op_andl_T0_ffff();
3698: next_eip = s->pc - s->cs_base;
3699: gen_movtl_T1_im(next_eip);
3700: gen_push_T1(s);
3701: gen_op_jmp_T0();
3702: gen_eob(s);
3703: break;
3704: case 3: /* lcall Ev */
3705: gen_op_ld_T1_A0[ot + s->mem_index]();
3706: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3707: gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3708: do_lcall:
3709: if (s->pe && !s->vm86) {
3710: if (s->cc_op != CC_OP_DYNAMIC)
3711: gen_op_set_cc_op(s->cc_op);
3712: gen_jmp_im(pc_start - s->cs_base);
3713: gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
3714: } else {
3715: gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
3716: }
3717: gen_eob(s);
3718: break;
3719: case 4: /* jmp Ev */
3720: if (s->dflag == 0)
3721: gen_op_andl_T0_ffff();
3722: gen_op_jmp_T0();
3723: gen_eob(s);
3724: break;
3725: case 5: /* ljmp Ev */
3726: gen_op_ld_T1_A0[ot + s->mem_index]();
3727: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3728: gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3729: do_ljmp:
3730: if (s->pe && !s->vm86) {
3731: if (s->cc_op != CC_OP_DYNAMIC)
3732: gen_op_set_cc_op(s->cc_op);
3733: gen_jmp_im(pc_start - s->cs_base);
3734: gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
3735: } else {
3736: gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3737: gen_op_movl_T0_T1();
3738: gen_op_jmp_T0();
3739: }
3740: gen_eob(s);
3741: break;
3742: case 6: /* push Ev */
3743: gen_push_T0(s);
3744: break;
3745: default:
3746: goto illegal_op;
3747: }
3748: break;
3749:
3750: case 0x84: /* test Ev, Gv */
1.1.1.6 ! root 3751: case 0x85:
1.1 root 3752: if ((b & 1) == 0)
3753: ot = OT_BYTE;
3754: else
3755: ot = dflag + OT_WORD;
3756:
3757: modrm = ldub_code(s->pc++);
3758: mod = (modrm >> 6) & 3;
3759: rm = (modrm & 7) | REX_B(s);
3760: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6 ! root 3761:
1.1 root 3762: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3763: gen_op_mov_TN_reg[ot][1][reg]();
3764: gen_op_testl_T0_T1_cc();
3765: s->cc_op = CC_OP_LOGICB + ot;
3766: break;
1.1.1.6 ! root 3767:
1.1 root 3768: case 0xa8: /* test eAX, Iv */
3769: case 0xa9:
3770: if ((b & 1) == 0)
3771: ot = OT_BYTE;
3772: else
3773: ot = dflag + OT_WORD;
3774: val = insn_get(s, ot);
3775:
3776: gen_op_mov_TN_reg[ot][0][OR_EAX]();
3777: gen_op_movl_T1_im(val);
3778: gen_op_testl_T0_T1_cc();
3779: s->cc_op = CC_OP_LOGICB + ot;
3780: break;
1.1.1.6 ! root 3781:
1.1 root 3782: case 0x98: /* CWDE/CBW */
3783: #ifdef TARGET_X86_64
3784: if (dflag == 2) {
3785: gen_op_movslq_RAX_EAX();
3786: } else
3787: #endif
3788: if (dflag == 1)
3789: gen_op_movswl_EAX_AX();
3790: else
3791: gen_op_movsbw_AX_AL();
3792: break;
3793: case 0x99: /* CDQ/CWD */
3794: #ifdef TARGET_X86_64
3795: if (dflag == 2) {
3796: gen_op_movsqo_RDX_RAX();
3797: } else
3798: #endif
3799: if (dflag == 1)
3800: gen_op_movslq_EDX_EAX();
3801: else
3802: gen_op_movswl_DX_AX();
3803: break;
3804: case 0x1af: /* imul Gv, Ev */
3805: case 0x69: /* imul Gv, Ev, I */
3806: case 0x6b:
3807: ot = dflag + OT_WORD;
3808: modrm = ldub_code(s->pc++);
3809: reg = ((modrm >> 3) & 7) | rex_r;
3810: if (b == 0x69)
3811: s->rip_offset = insn_const_size(ot);
3812: else if (b == 0x6b)
3813: s->rip_offset = 1;
3814: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3815: if (b == 0x69) {
3816: val = insn_get(s, ot);
3817: gen_op_movl_T1_im(val);
3818: } else if (b == 0x6b) {
3819: val = (int8_t)insn_get(s, OT_BYTE);
3820: gen_op_movl_T1_im(val);
3821: } else {
3822: gen_op_mov_TN_reg[ot][1][reg]();
3823: }
3824:
3825: #ifdef TARGET_X86_64
3826: if (ot == OT_QUAD) {
3827: gen_op_imulq_T0_T1();
3828: } else
3829: #endif
3830: if (ot == OT_LONG) {
3831: gen_op_imull_T0_T1();
3832: } else {
3833: gen_op_imulw_T0_T1();
3834: }
3835: gen_op_mov_reg_T0[ot][reg]();
3836: s->cc_op = CC_OP_MULB + ot;
3837: break;
3838: case 0x1c0:
3839: case 0x1c1: /* xadd Ev, Gv */
3840: if ((b & 1) == 0)
3841: ot = OT_BYTE;
3842: else
3843: ot = dflag + OT_WORD;
3844: modrm = ldub_code(s->pc++);
3845: reg = ((modrm >> 3) & 7) | rex_r;
3846: mod = (modrm >> 6) & 3;
3847: if (mod == 3) {
3848: rm = (modrm & 7) | REX_B(s);
3849: gen_op_mov_TN_reg[ot][0][reg]();
3850: gen_op_mov_TN_reg[ot][1][rm]();
3851: gen_op_addl_T0_T1();
3852: gen_op_mov_reg_T1[ot][reg]();
3853: gen_op_mov_reg_T0[ot][rm]();
3854: } else {
3855: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3856: gen_op_mov_TN_reg[ot][0][reg]();
3857: gen_op_ld_T1_A0[ot + s->mem_index]();
3858: gen_op_addl_T0_T1();
3859: gen_op_st_T0_A0[ot + s->mem_index]();
3860: gen_op_mov_reg_T1[ot][reg]();
3861: }
3862: gen_op_update2_cc();
3863: s->cc_op = CC_OP_ADDB + ot;
3864: break;
3865: case 0x1b0:
3866: case 0x1b1: /* cmpxchg Ev, Gv */
3867: if ((b & 1) == 0)
3868: ot = OT_BYTE;
3869: else
3870: ot = dflag + OT_WORD;
3871: modrm = ldub_code(s->pc++);
3872: reg = ((modrm >> 3) & 7) | rex_r;
3873: mod = (modrm >> 6) & 3;
3874: gen_op_mov_TN_reg[ot][1][reg]();
3875: if (mod == 3) {
3876: rm = (modrm & 7) | REX_B(s);
3877: gen_op_mov_TN_reg[ot][0][rm]();
3878: gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
3879: gen_op_mov_reg_T0[ot][rm]();
3880: } else {
3881: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3882: gen_op_ld_T0_A0[ot + s->mem_index]();
3883: gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
3884: }
3885: s->cc_op = CC_OP_SUBB + ot;
3886: break;
3887: case 0x1c7: /* cmpxchg8b */
3888: modrm = ldub_code(s->pc++);
3889: mod = (modrm >> 6) & 3;
1.1.1.6 ! root 3890: if ((mod == 3) || ((modrm & 0x38) != 0x8))
1.1 root 3891: goto illegal_op;
1.1.1.6 ! root 3892: gen_jmp_im(pc_start - s->cs_base);
1.1 root 3893: if (s->cc_op != CC_OP_DYNAMIC)
3894: gen_op_set_cc_op(s->cc_op);
3895: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3896: gen_op_cmpxchg8b();
3897: s->cc_op = CC_OP_EFLAGS;
3898: break;
1.1.1.6 ! root 3899:
1.1 root 3900: /**************************/
3901: /* push/pop */
3902: case 0x50 ... 0x57: /* push */
3903: gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
3904: gen_push_T0(s);
3905: break;
3906: case 0x58 ... 0x5f: /* pop */
3907: if (CODE64(s)) {
3908: ot = dflag ? OT_QUAD : OT_WORD;
3909: } else {
3910: ot = dflag + OT_WORD;
3911: }
3912: gen_pop_T0(s);
3913: /* NOTE: order is important for pop %sp */
3914: gen_pop_update(s);
3915: gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)]();
3916: break;
3917: case 0x60: /* pusha */
3918: if (CODE64(s))
3919: goto illegal_op;
3920: gen_pusha(s);
3921: break;
3922: case 0x61: /* popa */
3923: if (CODE64(s))
3924: goto illegal_op;
3925: gen_popa(s);
3926: break;
3927: case 0x68: /* push Iv */
3928: case 0x6a:
3929: if (CODE64(s)) {
3930: ot = dflag ? OT_QUAD : OT_WORD;
3931: } else {
3932: ot = dflag + OT_WORD;
3933: }
3934: if (b == 0x68)
3935: val = insn_get(s, ot);
3936: else
3937: val = (int8_t)insn_get(s, OT_BYTE);
3938: gen_op_movl_T0_im(val);
3939: gen_push_T0(s);
3940: break;
3941: case 0x8f: /* pop Ev */
3942: if (CODE64(s)) {
3943: ot = dflag ? OT_QUAD : OT_WORD;
3944: } else {
3945: ot = dflag + OT_WORD;
3946: }
3947: modrm = ldub_code(s->pc++);
3948: mod = (modrm >> 6) & 3;
3949: gen_pop_T0(s);
3950: if (mod == 3) {
3951: /* NOTE: order is important for pop %sp */
3952: gen_pop_update(s);
3953: rm = (modrm & 7) | REX_B(s);
3954: gen_op_mov_reg_T0[ot][rm]();
3955: } else {
3956: /* NOTE: order is important too for MMU exceptions */
3957: s->popl_esp_hack = 1 << ot;
3958: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3959: s->popl_esp_hack = 0;
3960: gen_pop_update(s);
3961: }
3962: break;
3963: case 0xc8: /* enter */
3964: {
3965: int level;
3966: val = lduw_code(s->pc);
3967: s->pc += 2;
3968: level = ldub_code(s->pc++);
3969: gen_enter(s, val, level);
3970: }
3971: break;
3972: case 0xc9: /* leave */
3973: /* XXX: exception not precise (ESP is updated before potential exception) */
3974: if (CODE64(s)) {
3975: gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
3976: gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
3977: } else if (s->ss32) {
3978: gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
3979: gen_op_mov_reg_T0[OT_LONG][R_ESP]();
3980: } else {
3981: gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
3982: gen_op_mov_reg_T0[OT_WORD][R_ESP]();
3983: }
3984: gen_pop_T0(s);
3985: if (CODE64(s)) {
3986: ot = dflag ? OT_QUAD : OT_WORD;
3987: } else {
3988: ot = dflag + OT_WORD;
3989: }
3990: gen_op_mov_reg_T0[ot][R_EBP]();
3991: gen_pop_update(s);
3992: break;
3993: case 0x06: /* push es */
3994: case 0x0e: /* push cs */
3995: case 0x16: /* push ss */
3996: case 0x1e: /* push ds */
3997: if (CODE64(s))
3998: goto illegal_op;
3999: gen_op_movl_T0_seg(b >> 3);
4000: gen_push_T0(s);
4001: break;
4002: case 0x1a0: /* push fs */
4003: case 0x1a8: /* push gs */
4004: gen_op_movl_T0_seg((b >> 3) & 7);
4005: gen_push_T0(s);
4006: break;
4007: case 0x07: /* pop es */
4008: case 0x17: /* pop ss */
4009: case 0x1f: /* pop ds */
4010: if (CODE64(s))
4011: goto illegal_op;
4012: reg = b >> 3;
4013: gen_pop_T0(s);
4014: gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4015: gen_pop_update(s);
4016: if (reg == R_SS) {
4017: /* if reg == SS, inhibit interrupts/trace. */
4018: /* If several instructions disable interrupts, only the
4019: _first_ does it */
4020: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4021: gen_op_set_inhibit_irq();
4022: s->tf = 0;
4023: }
4024: if (s->is_jmp) {
4025: gen_jmp_im(s->pc - s->cs_base);
4026: gen_eob(s);
4027: }
4028: break;
4029: case 0x1a1: /* pop fs */
4030: case 0x1a9: /* pop gs */
4031: gen_pop_T0(s);
4032: gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
4033: gen_pop_update(s);
4034: if (s->is_jmp) {
4035: gen_jmp_im(s->pc - s->cs_base);
4036: gen_eob(s);
4037: }
4038: break;
4039:
4040: /**************************/
4041: /* mov */
4042: case 0x88:
4043: case 0x89: /* mov Gv, Ev */
4044: if ((b & 1) == 0)
4045: ot = OT_BYTE;
4046: else
4047: ot = dflag + OT_WORD;
4048: modrm = ldub_code(s->pc++);
4049: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6 ! root 4050:
1.1 root 4051: /* generate a generic store */
4052: gen_ldst_modrm(s, modrm, ot, reg, 1);
4053: break;
4054: case 0xc6:
4055: case 0xc7: /* mov Ev, Iv */
4056: if ((b & 1) == 0)
4057: ot = OT_BYTE;
4058: else
4059: ot = dflag + OT_WORD;
4060: modrm = ldub_code(s->pc++);
4061: mod = (modrm >> 6) & 3;
4062: if (mod != 3) {
4063: s->rip_offset = insn_const_size(ot);
4064: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4065: }
4066: val = insn_get(s, ot);
4067: gen_op_movl_T0_im(val);
4068: if (mod != 3)
4069: gen_op_st_T0_A0[ot + s->mem_index]();
4070: else
4071: gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)]();
4072: break;
4073: case 0x8a:
4074: case 0x8b: /* mov Ev, Gv */
4075: if ((b & 1) == 0)
4076: ot = OT_BYTE;
4077: else
4078: ot = OT_WORD + dflag;
4079: modrm = ldub_code(s->pc++);
4080: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6 ! root 4081:
1.1 root 4082: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4083: gen_op_mov_reg_T0[ot][reg]();
4084: break;
4085: case 0x8e: /* mov seg, Gv */
4086: modrm = ldub_code(s->pc++);
4087: reg = (modrm >> 3) & 7;
4088: if (reg >= 6 || reg == R_CS)
4089: goto illegal_op;
4090: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4091: gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4092: if (reg == R_SS) {
4093: /* if reg == SS, inhibit interrupts/trace */
4094: /* If several instructions disable interrupts, only the
4095: _first_ does it */
4096: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4097: gen_op_set_inhibit_irq();
4098: s->tf = 0;
4099: }
4100: if (s->is_jmp) {
4101: gen_jmp_im(s->pc - s->cs_base);
4102: gen_eob(s);
4103: }
4104: break;
4105: case 0x8c: /* mov Gv, seg */
4106: modrm = ldub_code(s->pc++);
4107: reg = (modrm >> 3) & 7;
4108: mod = (modrm >> 6) & 3;
4109: if (reg >= 6)
4110: goto illegal_op;
4111: gen_op_movl_T0_seg(reg);
4112: if (mod == 3)
4113: ot = OT_WORD + dflag;
4114: else
4115: ot = OT_WORD;
4116: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4117: break;
4118:
4119: case 0x1b6: /* movzbS Gv, Eb */
4120: case 0x1b7: /* movzwS Gv, Eb */
4121: case 0x1be: /* movsbS Gv, Eb */
4122: case 0x1bf: /* movswS Gv, Eb */
4123: {
4124: int d_ot;
4125: /* d_ot is the size of destination */
4126: d_ot = dflag + OT_WORD;
4127: /* ot is the size of source */
4128: ot = (b & 1) + OT_BYTE;
4129: modrm = ldub_code(s->pc++);
4130: reg = ((modrm >> 3) & 7) | rex_r;
4131: mod = (modrm >> 6) & 3;
4132: rm = (modrm & 7) | REX_B(s);
1.1.1.6 ! root 4133:
1.1 root 4134: if (mod == 3) {
4135: gen_op_mov_TN_reg[ot][0][rm]();
4136: switch(ot | (b & 8)) {
4137: case OT_BYTE:
4138: gen_op_movzbl_T0_T0();
4139: break;
4140: case OT_BYTE | 8:
4141: gen_op_movsbl_T0_T0();
4142: break;
4143: case OT_WORD:
4144: gen_op_movzwl_T0_T0();
4145: break;
4146: default:
4147: case OT_WORD | 8:
4148: gen_op_movswl_T0_T0();
4149: break;
4150: }
4151: gen_op_mov_reg_T0[d_ot][reg]();
4152: } else {
4153: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4154: if (b & 8) {
4155: gen_op_lds_T0_A0[ot + s->mem_index]();
4156: } else {
4157: gen_op_ldu_T0_A0[ot + s->mem_index]();
4158: }
4159: gen_op_mov_reg_T0[d_ot][reg]();
4160: }
4161: }
4162: break;
4163:
4164: case 0x8d: /* lea */
4165: ot = dflag + OT_WORD;
4166: modrm = ldub_code(s->pc++);
4167: mod = (modrm >> 6) & 3;
4168: if (mod == 3)
4169: goto illegal_op;
4170: reg = ((modrm >> 3) & 7) | rex_r;
4171: /* we must ensure that no segment is added */
4172: s->override = -1;
4173: val = s->addseg;
4174: s->addseg = 0;
4175: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4176: s->addseg = val;
4177: gen_op_mov_reg_A0[ot - OT_WORD][reg]();
4178: break;
1.1.1.6 ! root 4179:
1.1 root 4180: case 0xa0: /* mov EAX, Ov */
4181: case 0xa1:
4182: case 0xa2: /* mov Ov, EAX */
4183: case 0xa3:
4184: {
4185: target_ulong offset_addr;
4186:
4187: if ((b & 1) == 0)
4188: ot = OT_BYTE;
4189: else
4190: ot = dflag + OT_WORD;
4191: #ifdef TARGET_X86_64
4192: if (s->aflag == 2) {
4193: offset_addr = ldq_code(s->pc);
4194: s->pc += 8;
4195: if (offset_addr == (int32_t)offset_addr)
4196: gen_op_movq_A0_im(offset_addr);
4197: else
4198: gen_op_movq_A0_im64(offset_addr >> 32, offset_addr);
1.1.1.6 ! root 4199: } else
1.1 root 4200: #endif
4201: {
4202: if (s->aflag) {
4203: offset_addr = insn_get(s, OT_LONG);
4204: } else {
4205: offset_addr = insn_get(s, OT_WORD);
4206: }
4207: gen_op_movl_A0_im(offset_addr);
4208: }
4209: gen_add_A0_ds_seg(s);
4210: if ((b & 2) == 0) {
4211: gen_op_ld_T0_A0[ot + s->mem_index]();
4212: gen_op_mov_reg_T0[ot][R_EAX]();
4213: } else {
4214: gen_op_mov_TN_reg[ot][0][R_EAX]();
4215: gen_op_st_T0_A0[ot + s->mem_index]();
4216: }
4217: }
4218: break;
4219: case 0xd7: /* xlat */
4220: #ifdef TARGET_X86_64
4221: if (s->aflag == 2) {
4222: gen_op_movq_A0_reg[R_EBX]();
4223: gen_op_addq_A0_AL();
1.1.1.6 ! root 4224: } else
1.1 root 4225: #endif
4226: {
4227: gen_op_movl_A0_reg[R_EBX]();
4228: gen_op_addl_A0_AL();
4229: if (s->aflag == 0)
4230: gen_op_andl_A0_ffff();
4231: }
4232: gen_add_A0_ds_seg(s);
4233: gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
4234: gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
4235: break;
4236: case 0xb0 ... 0xb7: /* mov R, Ib */
4237: val = insn_get(s, OT_BYTE);
4238: gen_op_movl_T0_im(val);
4239: gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)]();
4240: break;
4241: case 0xb8 ... 0xbf: /* mov R, Iv */
4242: #ifdef TARGET_X86_64
4243: if (dflag == 2) {
4244: uint64_t tmp;
4245: /* 64 bit case */
4246: tmp = ldq_code(s->pc);
4247: s->pc += 8;
4248: reg = (b & 7) | REX_B(s);
4249: gen_movtl_T0_im(tmp);
4250: gen_op_mov_reg_T0[OT_QUAD][reg]();
1.1.1.6 ! root 4251: } else
1.1 root 4252: #endif
4253: {
4254: ot = dflag ? OT_LONG : OT_WORD;
4255: val = insn_get(s, ot);
4256: reg = (b & 7) | REX_B(s);
4257: gen_op_movl_T0_im(val);
4258: gen_op_mov_reg_T0[ot][reg]();
4259: }
4260: break;
4261:
4262: case 0x91 ... 0x97: /* xchg R, EAX */
4263: ot = dflag + OT_WORD;
4264: reg = (b & 7) | REX_B(s);
4265: rm = R_EAX;
4266: goto do_xchg_reg;
4267: case 0x86:
4268: case 0x87: /* xchg Ev, Gv */
4269: if ((b & 1) == 0)
4270: ot = OT_BYTE;
4271: else
4272: ot = dflag + OT_WORD;
4273: modrm = ldub_code(s->pc++);
4274: reg = ((modrm >> 3) & 7) | rex_r;
4275: mod = (modrm >> 6) & 3;
4276: if (mod == 3) {
4277: rm = (modrm & 7) | REX_B(s);
4278: do_xchg_reg:
4279: gen_op_mov_TN_reg[ot][0][reg]();
4280: gen_op_mov_TN_reg[ot][1][rm]();
4281: gen_op_mov_reg_T0[ot][rm]();
4282: gen_op_mov_reg_T1[ot][reg]();
4283: } else {
4284: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4285: gen_op_mov_TN_reg[ot][0][reg]();
4286: /* for xchg, lock is implicit */
4287: if (!(prefixes & PREFIX_LOCK))
4288: gen_op_lock();
4289: gen_op_ld_T1_A0[ot + s->mem_index]();
4290: gen_op_st_T0_A0[ot + s->mem_index]();
4291: if (!(prefixes & PREFIX_LOCK))
4292: gen_op_unlock();
4293: gen_op_mov_reg_T1[ot][reg]();
4294: }
4295: break;
4296: case 0xc4: /* les Gv */
4297: if (CODE64(s))
4298: goto illegal_op;
4299: op = R_ES;
4300: goto do_lxx;
4301: case 0xc5: /* lds Gv */
4302: if (CODE64(s))
4303: goto illegal_op;
4304: op = R_DS;
4305: goto do_lxx;
4306: case 0x1b2: /* lss Gv */
4307: op = R_SS;
4308: goto do_lxx;
4309: case 0x1b4: /* lfs Gv */
4310: op = R_FS;
4311: goto do_lxx;
4312: case 0x1b5: /* lgs Gv */
4313: op = R_GS;
4314: do_lxx:
4315: ot = dflag ? OT_LONG : OT_WORD;
4316: modrm = ldub_code(s->pc++);
4317: reg = ((modrm >> 3) & 7) | rex_r;
4318: mod = (modrm >> 6) & 3;
4319: if (mod == 3)
4320: goto illegal_op;
4321: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4322: gen_op_ld_T1_A0[ot + s->mem_index]();
4323: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4324: /* load the segment first to handle exceptions properly */
4325: gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
4326: gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4327: /* then put the data */
4328: gen_op_mov_reg_T1[ot][reg]();
4329: if (s->is_jmp) {
4330: gen_jmp_im(s->pc - s->cs_base);
4331: gen_eob(s);
4332: }
4333: break;
1.1.1.6 ! root 4334:
1.1 root 4335: /************************/
4336: /* shifts */
4337: case 0xc0:
4338: case 0xc1:
4339: /* shift Ev,Ib */
4340: shift = 2;
4341: grp2:
4342: {
4343: if ((b & 1) == 0)
4344: ot = OT_BYTE;
4345: else
4346: ot = dflag + OT_WORD;
1.1.1.6 ! root 4347:
1.1 root 4348: modrm = ldub_code(s->pc++);
4349: mod = (modrm >> 6) & 3;
4350: op = (modrm >> 3) & 7;
1.1.1.6 ! root 4351:
1.1 root 4352: if (mod != 3) {
4353: if (shift == 2) {
4354: s->rip_offset = 1;
4355: }
4356: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4357: opreg = OR_TMP0;
4358: } else {
4359: opreg = (modrm & 7) | REX_B(s);
4360: }
4361:
4362: /* simpler op */
4363: if (shift == 0) {
4364: gen_shift(s, op, ot, opreg, OR_ECX);
4365: } else {
4366: if (shift == 2) {
4367: shift = ldub_code(s->pc++);
4368: }
4369: gen_shifti(s, op, ot, opreg, shift);
4370: }
4371: }
4372: break;
4373: case 0xd0:
4374: case 0xd1:
4375: /* shift Ev,1 */
4376: shift = 1;
4377: goto grp2;
4378: case 0xd2:
4379: case 0xd3:
4380: /* shift Ev,cl */
4381: shift = 0;
4382: goto grp2;
4383:
4384: case 0x1a4: /* shld imm */
4385: op = 0;
4386: shift = 1;
4387: goto do_shiftd;
4388: case 0x1a5: /* shld cl */
4389: op = 0;
4390: shift = 0;
4391: goto do_shiftd;
4392: case 0x1ac: /* shrd imm */
4393: op = 1;
4394: shift = 1;
4395: goto do_shiftd;
4396: case 0x1ad: /* shrd cl */
4397: op = 1;
4398: shift = 0;
4399: do_shiftd:
4400: ot = dflag + OT_WORD;
4401: modrm = ldub_code(s->pc++);
4402: mod = (modrm >> 6) & 3;
4403: rm = (modrm & 7) | REX_B(s);
4404: reg = ((modrm >> 3) & 7) | rex_r;
1.1.1.6 ! root 4405:
1.1 root 4406: if (mod != 3) {
4407: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4408: gen_op_ld_T0_A0[ot + s->mem_index]();
4409: } else {
4410: gen_op_mov_TN_reg[ot][0][rm]();
4411: }
4412: gen_op_mov_TN_reg[ot][1][reg]();
1.1.1.6 ! root 4413:
1.1 root 4414: if (shift) {
4415: val = ldub_code(s->pc++);
4416: if (ot == OT_QUAD)
4417: val &= 0x3f;
4418: else
4419: val &= 0x1f;
4420: if (val) {
4421: if (mod == 3)
4422: gen_op_shiftd_T0_T1_im_cc[ot][op](val);
4423: else
4424: gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
4425: if (op == 0 && ot != OT_WORD)
4426: s->cc_op = CC_OP_SHLB + ot;
4427: else
4428: s->cc_op = CC_OP_SARB + ot;
4429: }
4430: } else {
4431: if (s->cc_op != CC_OP_DYNAMIC)
4432: gen_op_set_cc_op(s->cc_op);
4433: if (mod == 3)
4434: gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
4435: else
4436: gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
4437: s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
4438: }
4439: if (mod == 3) {
4440: gen_op_mov_reg_T0[ot][rm]();
4441: }
4442: break;
4443:
4444: /************************/
4445: /* floats */
1.1.1.6 ! root 4446: case 0xd8 ... 0xdf:
1.1 root 4447: if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4448: /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4449: /* XXX: what to do if illegal op ? */
4450: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4451: break;
4452: }
4453: modrm = ldub_code(s->pc++);
4454: mod = (modrm >> 6) & 3;
4455: rm = modrm & 7;
4456: op = ((b & 7) << 3) | ((modrm >> 3) & 7);
4457: if (mod != 3) {
4458: /* memory op */
4459: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4460: switch(op) {
4461: case 0x00 ... 0x07: /* fxxxs */
4462: case 0x10 ... 0x17: /* fixxxl */
4463: case 0x20 ... 0x27: /* fxxxl */
4464: case 0x30 ... 0x37: /* fixxx */
4465: {
4466: int op1;
4467: op1 = op & 7;
4468:
4469: switch(op >> 4) {
4470: case 0:
4471: gen_op_flds_FT0_A0();
4472: break;
4473: case 1:
4474: gen_op_fildl_FT0_A0();
4475: break;
4476: case 2:
4477: gen_op_fldl_FT0_A0();
4478: break;
4479: case 3:
4480: default:
4481: gen_op_fild_FT0_A0();
4482: break;
4483: }
1.1.1.6 ! root 4484:
1.1 root 4485: gen_op_fp_arith_ST0_FT0[op1]();
4486: if (op1 == 3) {
4487: /* fcomp needs pop */
4488: gen_op_fpop();
4489: }
4490: }
4491: break;
4492: case 0x08: /* flds */
4493: case 0x0a: /* fsts */
4494: case 0x0b: /* fstps */
1.1.1.3 root 4495: case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
4496: case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
4497: case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
1.1 root 4498: switch(op & 7) {
4499: case 0:
4500: switch(op >> 4) {
4501: case 0:
4502: gen_op_flds_ST0_A0();
4503: break;
4504: case 1:
4505: gen_op_fildl_ST0_A0();
4506: break;
4507: case 2:
4508: gen_op_fldl_ST0_A0();
4509: break;
4510: case 3:
4511: default:
4512: gen_op_fild_ST0_A0();
4513: break;
4514: }
4515: break;
1.1.1.3 root 4516: case 1:
4517: switch(op >> 4) {
4518: case 1:
4519: gen_op_fisttl_ST0_A0();
4520: break;
4521: case 2:
4522: gen_op_fisttll_ST0_A0();
4523: break;
4524: case 3:
4525: default:
4526: gen_op_fistt_ST0_A0();
4527: }
4528: gen_op_fpop();
4529: break;
1.1 root 4530: default:
4531: switch(op >> 4) {
4532: case 0:
4533: gen_op_fsts_ST0_A0();
4534: break;
4535: case 1:
4536: gen_op_fistl_ST0_A0();
4537: break;
4538: case 2:
4539: gen_op_fstl_ST0_A0();
4540: break;
4541: case 3:
4542: default:
4543: gen_op_fist_ST0_A0();
4544: break;
4545: }
4546: if ((op & 7) == 3)
4547: gen_op_fpop();
4548: break;
4549: }
4550: break;
4551: case 0x0c: /* fldenv mem */
4552: gen_op_fldenv_A0(s->dflag);
4553: break;
4554: case 0x0d: /* fldcw mem */
4555: gen_op_fldcw_A0();
4556: break;
4557: case 0x0e: /* fnstenv mem */
4558: gen_op_fnstenv_A0(s->dflag);
4559: break;
4560: case 0x0f: /* fnstcw mem */
4561: gen_op_fnstcw_A0();
4562: break;
4563: case 0x1d: /* fldt mem */
4564: gen_op_fldt_ST0_A0();
4565: break;
4566: case 0x1f: /* fstpt mem */
4567: gen_op_fstt_ST0_A0();
4568: gen_op_fpop();
4569: break;
4570: case 0x2c: /* frstor mem */
4571: gen_op_frstor_A0(s->dflag);
4572: break;
4573: case 0x2e: /* fnsave mem */
4574: gen_op_fnsave_A0(s->dflag);
4575: break;
4576: case 0x2f: /* fnstsw mem */
4577: gen_op_fnstsw_A0();
4578: break;
4579: case 0x3c: /* fbld */
4580: gen_op_fbld_ST0_A0();
4581: break;
4582: case 0x3e: /* fbstp */
4583: gen_op_fbst_ST0_A0();
4584: gen_op_fpop();
4585: break;
4586: case 0x3d: /* fildll */
4587: gen_op_fildll_ST0_A0();
4588: break;
4589: case 0x3f: /* fistpll */
4590: gen_op_fistll_ST0_A0();
4591: gen_op_fpop();
4592: break;
4593: default:
4594: goto illegal_op;
4595: }
4596: } else {
4597: /* register float ops */
4598: opreg = rm;
4599:
4600: switch(op) {
4601: case 0x08: /* fld sti */
4602: gen_op_fpush();
4603: gen_op_fmov_ST0_STN((opreg + 1) & 7);
4604: break;
4605: case 0x09: /* fxchg sti */
4606: case 0x29: /* fxchg4 sti, undocumented op */
4607: case 0x39: /* fxchg7 sti, undocumented op */
4608: gen_op_fxchg_ST0_STN(opreg);
4609: break;
4610: case 0x0a: /* grp d9/2 */
4611: switch(rm) {
4612: case 0: /* fnop */
4613: /* check exceptions (FreeBSD FPU probe) */
4614: if (s->cc_op != CC_OP_DYNAMIC)
4615: gen_op_set_cc_op(s->cc_op);
4616: gen_jmp_im(pc_start - s->cs_base);
4617: gen_op_fwait();
4618: break;
4619: default:
4620: goto illegal_op;
4621: }
4622: break;
4623: case 0x0c: /* grp d9/4 */
4624: switch(rm) {
4625: case 0: /* fchs */
4626: gen_op_fchs_ST0();
4627: break;
4628: case 1: /* fabs */
4629: gen_op_fabs_ST0();
4630: break;
4631: case 4: /* ftst */
4632: gen_op_fldz_FT0();
4633: gen_op_fcom_ST0_FT0();
4634: break;
4635: case 5: /* fxam */
4636: gen_op_fxam_ST0();
4637: break;
4638: default:
4639: goto illegal_op;
4640: }
4641: break;
4642: case 0x0d: /* grp d9/5 */
4643: {
4644: switch(rm) {
4645: case 0:
4646: gen_op_fpush();
4647: gen_op_fld1_ST0();
4648: break;
4649: case 1:
4650: gen_op_fpush();
4651: gen_op_fldl2t_ST0();
4652: break;
4653: case 2:
4654: gen_op_fpush();
4655: gen_op_fldl2e_ST0();
4656: break;
4657: case 3:
4658: gen_op_fpush();
4659: gen_op_fldpi_ST0();
4660: break;
4661: case 4:
4662: gen_op_fpush();
4663: gen_op_fldlg2_ST0();
4664: break;
4665: case 5:
4666: gen_op_fpush();
4667: gen_op_fldln2_ST0();
4668: break;
4669: case 6:
4670: gen_op_fpush();
4671: gen_op_fldz_ST0();
4672: break;
4673: default:
4674: goto illegal_op;
4675: }
4676: }
4677: break;
4678: case 0x0e: /* grp d9/6 */
4679: switch(rm) {
4680: case 0: /* f2xm1 */
4681: gen_op_f2xm1();
4682: break;
4683: case 1: /* fyl2x */
4684: gen_op_fyl2x();
4685: break;
4686: case 2: /* fptan */
4687: gen_op_fptan();
4688: break;
4689: case 3: /* fpatan */
4690: gen_op_fpatan();
4691: break;
4692: case 4: /* fxtract */
4693: gen_op_fxtract();
4694: break;
4695: case 5: /* fprem1 */
4696: gen_op_fprem1();
4697: break;
4698: case 6: /* fdecstp */
4699: gen_op_fdecstp();
4700: break;
4701: default:
4702: case 7: /* fincstp */
4703: gen_op_fincstp();
4704: break;
4705: }
4706: break;
4707: case 0x0f: /* grp d9/7 */
4708: switch(rm) {
4709: case 0: /* fprem */
4710: gen_op_fprem();
4711: break;
4712: case 1: /* fyl2xp1 */
4713: gen_op_fyl2xp1();
4714: break;
4715: case 2: /* fsqrt */
4716: gen_op_fsqrt();
4717: break;
4718: case 3: /* fsincos */
4719: gen_op_fsincos();
4720: break;
4721: case 5: /* fscale */
4722: gen_op_fscale();
4723: break;
4724: case 4: /* frndint */
4725: gen_op_frndint();
4726: break;
4727: case 6: /* fsin */
4728: gen_op_fsin();
4729: break;
4730: default:
4731: case 7: /* fcos */
4732: gen_op_fcos();
4733: break;
4734: }
4735: break;
4736: case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4737: case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4738: case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4739: {
4740: int op1;
1.1.1.6 ! root 4741:
1.1 root 4742: op1 = op & 7;
4743: if (op >= 0x20) {
4744: gen_op_fp_arith_STN_ST0[op1](opreg);
4745: if (op >= 0x30)
4746: gen_op_fpop();
4747: } else {
4748: gen_op_fmov_FT0_STN(opreg);
4749: gen_op_fp_arith_ST0_FT0[op1]();
4750: }
4751: }
4752: break;
4753: case 0x02: /* fcom */
4754: case 0x22: /* fcom2, undocumented op */
4755: gen_op_fmov_FT0_STN(opreg);
4756: gen_op_fcom_ST0_FT0();
4757: break;
4758: case 0x03: /* fcomp */
4759: case 0x23: /* fcomp3, undocumented op */
4760: case 0x32: /* fcomp5, undocumented op */
4761: gen_op_fmov_FT0_STN(opreg);
4762: gen_op_fcom_ST0_FT0();
4763: gen_op_fpop();
4764: break;
4765: case 0x15: /* da/5 */
4766: switch(rm) {
4767: case 1: /* fucompp */
4768: gen_op_fmov_FT0_STN(1);
4769: gen_op_fucom_ST0_FT0();
4770: gen_op_fpop();
4771: gen_op_fpop();
4772: break;
4773: default:
4774: goto illegal_op;
4775: }
4776: break;
4777: case 0x1c:
4778: switch(rm) {
4779: case 0: /* feni (287 only, just do nop here) */
4780: break;
4781: case 1: /* fdisi (287 only, just do nop here) */
4782: break;
4783: case 2: /* fclex */
4784: gen_op_fclex();
4785: break;
4786: case 3: /* fninit */
4787: gen_op_fninit();
4788: break;
4789: case 4: /* fsetpm (287 only, just do nop here) */
4790: break;
4791: default:
4792: goto illegal_op;
4793: }
4794: break;
4795: case 0x1d: /* fucomi */
4796: if (s->cc_op != CC_OP_DYNAMIC)
4797: gen_op_set_cc_op(s->cc_op);
4798: gen_op_fmov_FT0_STN(opreg);
4799: gen_op_fucomi_ST0_FT0();
4800: s->cc_op = CC_OP_EFLAGS;
4801: break;
4802: case 0x1e: /* fcomi */
4803: if (s->cc_op != CC_OP_DYNAMIC)
4804: gen_op_set_cc_op(s->cc_op);
4805: gen_op_fmov_FT0_STN(opreg);
4806: gen_op_fcomi_ST0_FT0();
4807: s->cc_op = CC_OP_EFLAGS;
4808: break;
4809: case 0x28: /* ffree sti */
4810: gen_op_ffree_STN(opreg);
1.1.1.6 ! root 4811: break;
1.1 root 4812: case 0x2a: /* fst sti */
4813: gen_op_fmov_STN_ST0(opreg);
4814: break;
4815: case 0x2b: /* fstp sti */
4816: case 0x0b: /* fstp1 sti, undocumented op */
4817: case 0x3a: /* fstp8 sti, undocumented op */
4818: case 0x3b: /* fstp9 sti, undocumented op */
4819: gen_op_fmov_STN_ST0(opreg);
4820: gen_op_fpop();
4821: break;
4822: case 0x2c: /* fucom st(i) */
4823: gen_op_fmov_FT0_STN(opreg);
4824: gen_op_fucom_ST0_FT0();
4825: break;
4826: case 0x2d: /* fucomp st(i) */
4827: gen_op_fmov_FT0_STN(opreg);
4828: gen_op_fucom_ST0_FT0();
4829: gen_op_fpop();
4830: break;
4831: case 0x33: /* de/3 */
4832: switch(rm) {
4833: case 1: /* fcompp */
4834: gen_op_fmov_FT0_STN(1);
4835: gen_op_fcom_ST0_FT0();
4836: gen_op_fpop();
4837: gen_op_fpop();
4838: break;
4839: default:
4840: goto illegal_op;
4841: }
4842: break;
4843: case 0x38: /* ffreep sti, undocumented op */
4844: gen_op_ffree_STN(opreg);
4845: gen_op_fpop();
4846: break;
4847: case 0x3c: /* df/4 */
4848: switch(rm) {
4849: case 0:
4850: gen_op_fnstsw_EAX();
4851: break;
4852: default:
4853: goto illegal_op;
4854: }
4855: break;
4856: case 0x3d: /* fucomip */
4857: if (s->cc_op != CC_OP_DYNAMIC)
4858: gen_op_set_cc_op(s->cc_op);
4859: gen_op_fmov_FT0_STN(opreg);
4860: gen_op_fucomi_ST0_FT0();
4861: gen_op_fpop();
4862: s->cc_op = CC_OP_EFLAGS;
4863: break;
4864: case 0x3e: /* fcomip */
4865: if (s->cc_op != CC_OP_DYNAMIC)
4866: gen_op_set_cc_op(s->cc_op);
4867: gen_op_fmov_FT0_STN(opreg);
4868: gen_op_fcomi_ST0_FT0();
4869: gen_op_fpop();
4870: s->cc_op = CC_OP_EFLAGS;
4871: break;
4872: case 0x10 ... 0x13: /* fcmovxx */
4873: case 0x18 ... 0x1b:
4874: {
4875: int op1;
4876: const static uint8_t fcmov_cc[8] = {
4877: (JCC_B << 1),
4878: (JCC_Z << 1),
4879: (JCC_BE << 1),
4880: (JCC_P << 1),
4881: };
4882: op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
4883: gen_setcc(s, op1);
4884: gen_op_fcmov_ST0_STN_T0(opreg);
4885: }
4886: break;
4887: default:
4888: goto illegal_op;
4889: }
4890: }
4891: break;
4892: /************************/
4893: /* string ops */
4894:
4895: case 0xa4: /* movsS */
4896: case 0xa5:
4897: if ((b & 1) == 0)
4898: ot = OT_BYTE;
4899: else
4900: ot = dflag + OT_WORD;
4901:
4902: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4903: gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4904: } else {
4905: gen_movs(s, ot);
4906: }
4907: break;
1.1.1.6 ! root 4908:
1.1 root 4909: case 0xaa: /* stosS */
4910: case 0xab:
4911: if ((b & 1) == 0)
4912: ot = OT_BYTE;
4913: else
4914: ot = dflag + OT_WORD;
4915:
4916: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4917: gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4918: } else {
4919: gen_stos(s, ot);
4920: }
4921: break;
4922: case 0xac: /* lodsS */
4923: case 0xad:
4924: if ((b & 1) == 0)
4925: ot = OT_BYTE;
4926: else
4927: ot = dflag + OT_WORD;
4928: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4929: gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4930: } else {
4931: gen_lods(s, ot);
4932: }
4933: break;
4934: case 0xae: /* scasS */
4935: case 0xaf:
4936: if ((b & 1) == 0)
4937: ot = OT_BYTE;
4938: else
4939: ot = dflag + OT_WORD;
4940: if (prefixes & PREFIX_REPNZ) {
4941: gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4942: } else if (prefixes & PREFIX_REPZ) {
4943: gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4944: } else {
4945: gen_scas(s, ot);
4946: s->cc_op = CC_OP_SUBB + ot;
4947: }
4948: break;
4949:
4950: case 0xa6: /* cmpsS */
4951: case 0xa7:
4952: if ((b & 1) == 0)
4953: ot = OT_BYTE;
4954: else
4955: ot = dflag + OT_WORD;
4956: if (prefixes & PREFIX_REPNZ) {
4957: gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4958: } else if (prefixes & PREFIX_REPZ) {
4959: gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4960: } else {
4961: gen_cmps(s, ot);
4962: s->cc_op = CC_OP_SUBB + ot;
4963: }
4964: break;
4965: case 0x6c: /* insS */
4966: case 0x6d:
4967: if ((b & 1) == 0)
4968: ot = OT_BYTE;
4969: else
4970: ot = dflag ? OT_LONG : OT_WORD;
4971: gen_check_io(s, ot, 1, pc_start - s->cs_base);
1.1.1.6 ! root 4972: gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
! 4973: gen_op_andl_T0_ffff();
! 4974: if (gen_svm_check_io(s, pc_start,
! 4975: SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
! 4976: svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
! 4977: break;
1.1 root 4978: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4979: gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4980: } else {
4981: gen_ins(s, ot);
4982: }
4983: break;
4984: case 0x6e: /* outsS */
4985: case 0x6f:
4986: if ((b & 1) == 0)
4987: ot = OT_BYTE;
4988: else
4989: ot = dflag ? OT_LONG : OT_WORD;
4990: gen_check_io(s, ot, 1, pc_start - s->cs_base);
1.1.1.6 ! root 4991: gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
! 4992: gen_op_andl_T0_ffff();
! 4993: if (gen_svm_check_io(s, pc_start,
! 4994: (1 << (4+ot)) | svm_is_rep(prefixes) |
! 4995: 4 | (1 << (7+s->aflag))))
! 4996: break;
1.1 root 4997: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4998: gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4999: } else {
5000: gen_outs(s, ot);
5001: }
5002: break;
5003:
5004: /************************/
5005: /* port I/O */
1.1.1.6 ! root 5006:
1.1 root 5007: case 0xe4:
5008: case 0xe5:
5009: if ((b & 1) == 0)
5010: ot = OT_BYTE;
5011: else
5012: ot = dflag ? OT_LONG : OT_WORD;
5013: val = ldub_code(s->pc++);
5014: gen_op_movl_T0_im(val);
5015: gen_check_io(s, ot, 0, pc_start - s->cs_base);
1.1.1.6 ! root 5016: if (gen_svm_check_io(s, pc_start,
! 5017: SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
! 5018: (1 << (4+ot))))
! 5019: break;
1.1 root 5020: gen_op_in[ot]();
5021: gen_op_mov_reg_T1[ot][R_EAX]();
5022: break;
5023: case 0xe6:
5024: case 0xe7:
5025: if ((b & 1) == 0)
5026: ot = OT_BYTE;
5027: else
5028: ot = dflag ? OT_LONG : OT_WORD;
5029: val = ldub_code(s->pc++);
5030: gen_op_movl_T0_im(val);
5031: gen_check_io(s, ot, 0, pc_start - s->cs_base);
1.1.1.6 ! root 5032: if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) |
! 5033: (1 << (4+ot))))
! 5034: break;
1.1 root 5035: gen_op_mov_TN_reg[ot][1][R_EAX]();
5036: gen_op_out[ot]();
5037: break;
5038: case 0xec:
5039: case 0xed:
5040: if ((b & 1) == 0)
5041: ot = OT_BYTE;
5042: else
5043: ot = dflag ? OT_LONG : OT_WORD;
5044: gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
5045: gen_op_andl_T0_ffff();
5046: gen_check_io(s, ot, 0, pc_start - s->cs_base);
1.1.1.6 ! root 5047: if (gen_svm_check_io(s, pc_start,
! 5048: SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
! 5049: (1 << (4+ot))))
! 5050: break;
1.1 root 5051: gen_op_in[ot]();
5052: gen_op_mov_reg_T1[ot][R_EAX]();
5053: break;
5054: case 0xee:
5055: case 0xef:
5056: if ((b & 1) == 0)
5057: ot = OT_BYTE;
5058: else
5059: ot = dflag ? OT_LONG : OT_WORD;
5060: gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
5061: gen_op_andl_T0_ffff();
5062: gen_check_io(s, ot, 0, pc_start - s->cs_base);
1.1.1.6 ! root 5063: if (gen_svm_check_io(s, pc_start,
! 5064: svm_is_rep(prefixes) | (1 << (4+ot))))
! 5065: break;
1.1 root 5066: gen_op_mov_TN_reg[ot][1][R_EAX]();
5067: gen_op_out[ot]();
5068: break;
5069:
5070: /************************/
5071: /* control */
5072: case 0xc2: /* ret im */
5073: val = ldsw_code(s->pc);
5074: s->pc += 2;
5075: gen_pop_T0(s);
5076: if (CODE64(s) && s->dflag)
5077: s->dflag = 2;
5078: gen_stack_update(s, val + (2 << s->dflag));
5079: if (s->dflag == 0)
5080: gen_op_andl_T0_ffff();
5081: gen_op_jmp_T0();
5082: gen_eob(s);
5083: break;
5084: case 0xc3: /* ret */
5085: gen_pop_T0(s);
5086: gen_pop_update(s);
5087: if (s->dflag == 0)
5088: gen_op_andl_T0_ffff();
5089: gen_op_jmp_T0();
5090: gen_eob(s);
5091: break;
5092: case 0xca: /* lret im */
5093: val = ldsw_code(s->pc);
5094: s->pc += 2;
5095: do_lret:
5096: if (s->pe && !s->vm86) {
5097: if (s->cc_op != CC_OP_DYNAMIC)
5098: gen_op_set_cc_op(s->cc_op);
5099: gen_jmp_im(pc_start - s->cs_base);
5100: gen_op_lret_protected(s->dflag, val);
5101: } else {
5102: gen_stack_A0(s);
5103: /* pop offset */
5104: gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5105: if (s->dflag == 0)
5106: gen_op_andl_T0_ffff();
5107: /* NOTE: keeping EIP updated is not a problem in case of
5108: exception */
5109: gen_op_jmp_T0();
5110: /* pop selector */
5111: gen_op_addl_A0_im(2 << s->dflag);
5112: gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
5113: gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
5114: /* add stack offset */
5115: gen_stack_update(s, val + (4 << s->dflag));
5116: }
5117: gen_eob(s);
5118: break;
5119: case 0xcb: /* lret */
5120: val = 0;
5121: goto do_lret;
5122: case 0xcf: /* iret */
1.1.1.6 ! root 5123: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET))
! 5124: break;
1.1 root 5125: if (!s->pe) {
5126: /* real mode */
5127: gen_op_iret_real(s->dflag);
5128: s->cc_op = CC_OP_EFLAGS;
5129: } else if (s->vm86) {
5130: if (s->iopl != 3) {
5131: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5132: } else {
5133: gen_op_iret_real(s->dflag);
5134: s->cc_op = CC_OP_EFLAGS;
5135: }
5136: } else {
5137: if (s->cc_op != CC_OP_DYNAMIC)
5138: gen_op_set_cc_op(s->cc_op);
5139: gen_jmp_im(pc_start - s->cs_base);
5140: gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
5141: s->cc_op = CC_OP_EFLAGS;
5142: }
5143: gen_eob(s);
5144: break;
5145: case 0xe8: /* call im */
5146: {
5147: if (dflag)
5148: tval = (int32_t)insn_get(s, OT_LONG);
5149: else
5150: tval = (int16_t)insn_get(s, OT_WORD);
5151: next_eip = s->pc - s->cs_base;
5152: tval += next_eip;
5153: if (s->dflag == 0)
5154: tval &= 0xffff;
5155: gen_movtl_T0_im(next_eip);
5156: gen_push_T0(s);
5157: gen_jmp(s, tval);
5158: }
5159: break;
5160: case 0x9a: /* lcall im */
5161: {
5162: unsigned int selector, offset;
1.1.1.6 ! root 5163:
1.1 root 5164: if (CODE64(s))
5165: goto illegal_op;
5166: ot = dflag ? OT_LONG : OT_WORD;
5167: offset = insn_get(s, ot);
5168: selector = insn_get(s, OT_WORD);
1.1.1.6 ! root 5169:
1.1 root 5170: gen_op_movl_T0_im(selector);
5171: gen_op_movl_T1_imu(offset);
5172: }
5173: goto do_lcall;
5174: case 0xe9: /* jmp im */
5175: if (dflag)
5176: tval = (int32_t)insn_get(s, OT_LONG);
5177: else
5178: tval = (int16_t)insn_get(s, OT_WORD);
5179: tval += s->pc - s->cs_base;
5180: if (s->dflag == 0)
5181: tval &= 0xffff;
5182: gen_jmp(s, tval);
5183: break;
5184: case 0xea: /* ljmp im */
5185: {
5186: unsigned int selector, offset;
5187:
5188: if (CODE64(s))
5189: goto illegal_op;
5190: ot = dflag ? OT_LONG : OT_WORD;
5191: offset = insn_get(s, ot);
5192: selector = insn_get(s, OT_WORD);
1.1.1.6 ! root 5193:
1.1 root 5194: gen_op_movl_T0_im(selector);
5195: gen_op_movl_T1_imu(offset);
5196: }
5197: goto do_ljmp;
5198: case 0xeb: /* jmp Jb */
5199: tval = (int8_t)insn_get(s, OT_BYTE);
5200: tval += s->pc - s->cs_base;
5201: if (s->dflag == 0)
5202: tval &= 0xffff;
5203: gen_jmp(s, tval);
5204: break;
5205: case 0x70 ... 0x7f: /* jcc Jb */
5206: tval = (int8_t)insn_get(s, OT_BYTE);
5207: goto do_jcc;
5208: case 0x180 ... 0x18f: /* jcc Jv */
5209: if (dflag) {
5210: tval = (int32_t)insn_get(s, OT_LONG);
5211: } else {
1.1.1.6 ! root 5212: tval = (int16_t)insn_get(s, OT_WORD);
1.1 root 5213: }
5214: do_jcc:
5215: next_eip = s->pc - s->cs_base;
5216: tval += next_eip;
5217: if (s->dflag == 0)
5218: tval &= 0xffff;
5219: gen_jcc(s, b, tval, next_eip);
5220: break;
5221:
5222: case 0x190 ... 0x19f: /* setcc Gv */
5223: modrm = ldub_code(s->pc++);
5224: gen_setcc(s, b);
5225: gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
5226: break;
5227: case 0x140 ... 0x14f: /* cmov Gv, Ev */
5228: ot = dflag + OT_WORD;
5229: modrm = ldub_code(s->pc++);
5230: reg = ((modrm >> 3) & 7) | rex_r;
5231: mod = (modrm >> 6) & 3;
5232: gen_setcc(s, b);
5233: if (mod != 3) {
5234: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5235: gen_op_ld_T1_A0[ot + s->mem_index]();
5236: } else {
5237: rm = (modrm & 7) | REX_B(s);
5238: gen_op_mov_TN_reg[ot][1][rm]();
5239: }
5240: gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
5241: break;
1.1.1.6 ! root 5242:
1.1 root 5243: /************************/
5244: /* flags */
5245: case 0x9c: /* pushf */
1.1.1.6 ! root 5246: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF))
! 5247: break;
1.1 root 5248: if (s->vm86 && s->iopl != 3) {
5249: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5250: } else {
5251: if (s->cc_op != CC_OP_DYNAMIC)
5252: gen_op_set_cc_op(s->cc_op);
5253: gen_op_movl_T0_eflags();
5254: gen_push_T0(s);
5255: }
5256: break;
5257: case 0x9d: /* popf */
1.1.1.6 ! root 5258: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF))
! 5259: break;
1.1 root 5260: if (s->vm86 && s->iopl != 3) {
5261: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5262: } else {
5263: gen_pop_T0(s);
5264: if (s->cpl == 0) {
5265: if (s->dflag) {
5266: gen_op_movl_eflags_T0_cpl0();
5267: } else {
5268: gen_op_movw_eflags_T0_cpl0();
5269: }
5270: } else {
5271: if (s->cpl <= s->iopl) {
5272: if (s->dflag) {
5273: gen_op_movl_eflags_T0_io();
5274: } else {
5275: gen_op_movw_eflags_T0_io();
5276: }
5277: } else {
5278: if (s->dflag) {
5279: gen_op_movl_eflags_T0();
5280: } else {
5281: gen_op_movw_eflags_T0();
5282: }
5283: }
5284: }
5285: gen_pop_update(s);
5286: s->cc_op = CC_OP_EFLAGS;
5287: /* abort translation because TF flag may change */
5288: gen_jmp_im(s->pc - s->cs_base);
5289: gen_eob(s);
5290: }
5291: break;
5292: case 0x9e: /* sahf */
5293: if (CODE64(s))
5294: goto illegal_op;
5295: gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
5296: if (s->cc_op != CC_OP_DYNAMIC)
5297: gen_op_set_cc_op(s->cc_op);
5298: gen_op_movb_eflags_T0();
5299: s->cc_op = CC_OP_EFLAGS;
5300: break;
5301: case 0x9f: /* lahf */
5302: if (CODE64(s))
5303: goto illegal_op;
5304: if (s->cc_op != CC_OP_DYNAMIC)
5305: gen_op_set_cc_op(s->cc_op);
5306: gen_op_movl_T0_eflags();
5307: gen_op_mov_reg_T0[OT_BYTE][R_AH]();
5308: break;
5309: case 0xf5: /* cmc */
5310: if (s->cc_op != CC_OP_DYNAMIC)
5311: gen_op_set_cc_op(s->cc_op);
5312: gen_op_cmc();
5313: s->cc_op = CC_OP_EFLAGS;
5314: break;
5315: case 0xf8: /* clc */
5316: if (s->cc_op != CC_OP_DYNAMIC)
5317: gen_op_set_cc_op(s->cc_op);
5318: gen_op_clc();
5319: s->cc_op = CC_OP_EFLAGS;
5320: break;
5321: case 0xf9: /* stc */
5322: if (s->cc_op != CC_OP_DYNAMIC)
5323: gen_op_set_cc_op(s->cc_op);
5324: gen_op_stc();
5325: s->cc_op = CC_OP_EFLAGS;
5326: break;
5327: case 0xfc: /* cld */
5328: gen_op_cld();
5329: break;
5330: case 0xfd: /* std */
5331: gen_op_std();
5332: break;
5333:
5334: /************************/
5335: /* bit operations */
5336: case 0x1ba: /* bt/bts/btr/btc Gv, im */
5337: ot = dflag + OT_WORD;
5338: modrm = ldub_code(s->pc++);
1.1.1.3 root 5339: op = (modrm >> 3) & 7;
1.1 root 5340: mod = (modrm >> 6) & 3;
5341: rm = (modrm & 7) | REX_B(s);
5342: if (mod != 3) {
5343: s->rip_offset = 1;
5344: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5345: gen_op_ld_T0_A0[ot + s->mem_index]();
5346: } else {
5347: gen_op_mov_TN_reg[ot][0][rm]();
5348: }
5349: /* load shift */
5350: val = ldub_code(s->pc++);
5351: gen_op_movl_T1_im(val);
5352: if (op < 4)
5353: goto illegal_op;
5354: op -= 4;
5355: gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5356: s->cc_op = CC_OP_SARB + ot;
5357: if (op != 0) {
5358: if (mod != 3)
5359: gen_op_st_T0_A0[ot + s->mem_index]();
5360: else
5361: gen_op_mov_reg_T0[ot][rm]();
5362: gen_op_update_bt_cc();
5363: }
5364: break;
5365: case 0x1a3: /* bt Gv, Ev */
5366: op = 0;
5367: goto do_btx;
5368: case 0x1ab: /* bts */
5369: op = 1;
5370: goto do_btx;
5371: case 0x1b3: /* btr */
5372: op = 2;
5373: goto do_btx;
5374: case 0x1bb: /* btc */
5375: op = 3;
5376: do_btx:
5377: ot = dflag + OT_WORD;
5378: modrm = ldub_code(s->pc++);
5379: reg = ((modrm >> 3) & 7) | rex_r;
5380: mod = (modrm >> 6) & 3;
5381: rm = (modrm & 7) | REX_B(s);
5382: gen_op_mov_TN_reg[OT_LONG][1][reg]();
5383: if (mod != 3) {
5384: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5385: /* specific case: we need to add a displacement */
5386: gen_op_add_bit_A0_T1[ot - OT_WORD]();
5387: gen_op_ld_T0_A0[ot + s->mem_index]();
5388: } else {
5389: gen_op_mov_TN_reg[ot][0][rm]();
5390: }
5391: gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5392: s->cc_op = CC_OP_SARB + ot;
5393: if (op != 0) {
5394: if (mod != 3)
5395: gen_op_st_T0_A0[ot + s->mem_index]();
5396: else
5397: gen_op_mov_reg_T0[ot][rm]();
5398: gen_op_update_bt_cc();
5399: }
5400: break;
5401: case 0x1bc: /* bsf */
5402: case 0x1bd: /* bsr */
5403: ot = dflag + OT_WORD;
5404: modrm = ldub_code(s->pc++);
5405: reg = ((modrm >> 3) & 7) | rex_r;
5406: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5407: /* NOTE: in order to handle the 0 case, we must load the
5408: result. It could be optimized with a generated jump */
5409: gen_op_mov_TN_reg[ot][1][reg]();
5410: gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
5411: gen_op_mov_reg_T1[ot][reg]();
5412: s->cc_op = CC_OP_LOGICB + ot;
5413: break;
5414: /************************/
5415: /* bcd */
5416: case 0x27: /* daa */
5417: if (CODE64(s))
5418: goto illegal_op;
5419: if (s->cc_op != CC_OP_DYNAMIC)
5420: gen_op_set_cc_op(s->cc_op);
5421: gen_op_daa();
5422: s->cc_op = CC_OP_EFLAGS;
5423: break;
5424: case 0x2f: /* das */
5425: if (CODE64(s))
5426: goto illegal_op;
5427: if (s->cc_op != CC_OP_DYNAMIC)
5428: gen_op_set_cc_op(s->cc_op);
5429: gen_op_das();
5430: s->cc_op = CC_OP_EFLAGS;
5431: break;
5432: case 0x37: /* aaa */
5433: if (CODE64(s))
5434: goto illegal_op;
5435: if (s->cc_op != CC_OP_DYNAMIC)
5436: gen_op_set_cc_op(s->cc_op);
5437: gen_op_aaa();
5438: s->cc_op = CC_OP_EFLAGS;
5439: break;
5440: case 0x3f: /* aas */
5441: if (CODE64(s))
5442: goto illegal_op;
5443: if (s->cc_op != CC_OP_DYNAMIC)
5444: gen_op_set_cc_op(s->cc_op);
5445: gen_op_aas();
5446: s->cc_op = CC_OP_EFLAGS;
5447: break;
5448: case 0xd4: /* aam */
5449: if (CODE64(s))
5450: goto illegal_op;
5451: val = ldub_code(s->pc++);
1.1.1.6 ! root 5452: if (val == 0) {
! 5453: gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
! 5454: } else {
! 5455: gen_op_aam(val);
! 5456: s->cc_op = CC_OP_LOGICB;
! 5457: }
1.1 root 5458: break;
5459: case 0xd5: /* aad */
5460: if (CODE64(s))
5461: goto illegal_op;
5462: val = ldub_code(s->pc++);
5463: gen_op_aad(val);
5464: s->cc_op = CC_OP_LOGICB;
5465: break;
5466: /************************/
5467: /* misc */
5468: case 0x90: /* nop */
5469: /* XXX: xchg + rex handling */
5470: /* XXX: correct lock test for all insn */
5471: if (prefixes & PREFIX_LOCK)
5472: goto illegal_op;
1.1.1.6 ! root 5473: if (prefixes & PREFIX_REPZ) {
! 5474: gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
! 5475: }
1.1 root 5476: break;
5477: case 0x9b: /* fwait */
1.1.1.6 ! root 5478: if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
1.1 root 5479: (HF_MP_MASK | HF_TS_MASK)) {
5480: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5481: } else {
5482: if (s->cc_op != CC_OP_DYNAMIC)
5483: gen_op_set_cc_op(s->cc_op);
5484: gen_jmp_im(pc_start - s->cs_base);
5485: gen_op_fwait();
5486: }
5487: break;
5488: case 0xcc: /* int3 */
1.1.1.6 ! root 5489: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
! 5490: break;
1.1 root 5491: gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5492: break;
5493: case 0xcd: /* int N */
5494: val = ldub_code(s->pc++);
1.1.1.6 ! root 5495: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
! 5496: break;
1.1 root 5497: if (s->vm86 && s->iopl != 3) {
1.1.1.6 ! root 5498: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
1.1 root 5499: } else {
5500: gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5501: }
5502: break;
5503: case 0xce: /* into */
5504: if (CODE64(s))
5505: goto illegal_op;
1.1.1.6 ! root 5506: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
! 5507: break;
1.1 root 5508: if (s->cc_op != CC_OP_DYNAMIC)
5509: gen_op_set_cc_op(s->cc_op);
5510: gen_jmp_im(pc_start - s->cs_base);
5511: gen_op_into(s->pc - pc_start);
5512: break;
5513: case 0xf1: /* icebp (undocumented, exits to external debugger) */
1.1.1.6 ! root 5514: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP))
! 5515: break;
1.1 root 5516: #if 1
5517: gen_debug(s, pc_start - s->cs_base);
5518: #else
5519: /* start debug */
5520: tb_flush(cpu_single_env);
5521: cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5522: #endif
5523: break;
5524: case 0xfa: /* cli */
5525: if (!s->vm86) {
5526: if (s->cpl <= s->iopl) {
5527: gen_op_cli();
5528: } else {
5529: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5530: }
5531: } else {
5532: if (s->iopl == 3) {
5533: gen_op_cli();
5534: } else {
5535: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5536: }
5537: }
5538: break;
5539: case 0xfb: /* sti */
5540: if (!s->vm86) {
5541: if (s->cpl <= s->iopl) {
5542: gen_sti:
5543: gen_op_sti();
5544: /* interruptions are enabled only the first insn after sti */
5545: /* If several instructions disable interrupts, only the
5546: _first_ does it */
5547: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5548: gen_op_set_inhibit_irq();
5549: /* give a chance to handle pending irqs */
5550: gen_jmp_im(s->pc - s->cs_base);
5551: gen_eob(s);
5552: } else {
5553: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5554: }
5555: } else {
5556: if (s->iopl == 3) {
5557: goto gen_sti;
5558: } else {
5559: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5560: }
5561: }
5562: break;
5563: case 0x62: /* bound */
5564: if (CODE64(s))
5565: goto illegal_op;
5566: ot = dflag ? OT_LONG : OT_WORD;
5567: modrm = ldub_code(s->pc++);
5568: reg = (modrm >> 3) & 7;
5569: mod = (modrm >> 6) & 3;
5570: if (mod == 3)
5571: goto illegal_op;
5572: gen_op_mov_TN_reg[ot][0][reg]();
5573: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5574: gen_jmp_im(pc_start - s->cs_base);
5575: if (ot == OT_WORD)
5576: gen_op_boundw();
5577: else
5578: gen_op_boundl();
5579: break;
5580: case 0x1c8 ... 0x1cf: /* bswap reg */
5581: reg = (b & 7) | REX_B(s);
5582: #ifdef TARGET_X86_64
5583: if (dflag == 2) {
5584: gen_op_mov_TN_reg[OT_QUAD][0][reg]();
5585: gen_op_bswapq_T0();
5586: gen_op_mov_reg_T0[OT_QUAD][reg]();
1.1.1.6 ! root 5587: } else
1.1 root 5588: #endif
5589: {
5590: gen_op_mov_TN_reg[OT_LONG][0][reg]();
5591: gen_op_bswapl_T0();
5592: gen_op_mov_reg_T0[OT_LONG][reg]();
5593: }
5594: break;
5595: case 0xd6: /* salc */
5596: if (CODE64(s))
5597: goto illegal_op;
5598: if (s->cc_op != CC_OP_DYNAMIC)
5599: gen_op_set_cc_op(s->cc_op);
5600: gen_op_salc();
5601: break;
5602: case 0xe0: /* loopnz */
5603: case 0xe1: /* loopz */
5604: if (s->cc_op != CC_OP_DYNAMIC)
5605: gen_op_set_cc_op(s->cc_op);
5606: /* FALL THRU */
5607: case 0xe2: /* loop */
5608: case 0xe3: /* jecxz */
5609: {
5610: int l1, l2;
5611:
5612: tval = (int8_t)insn_get(s, OT_BYTE);
5613: next_eip = s->pc - s->cs_base;
5614: tval += next_eip;
5615: if (s->dflag == 0)
5616: tval &= 0xffff;
1.1.1.6 ! root 5617:
1.1 root 5618: l1 = gen_new_label();
5619: l2 = gen_new_label();
5620: b &= 3;
5621: if (b == 3) {
5622: gen_op_jz_ecx[s->aflag](l1);
5623: } else {
5624: gen_op_dec_ECX[s->aflag]();
5625: if (b <= 1)
5626: gen_op_mov_T0_cc();
5627: gen_op_loop[s->aflag][b](l1);
5628: }
5629:
5630: gen_jmp_im(next_eip);
5631: gen_op_jmp_label(l2);
5632: gen_set_label(l1);
5633: gen_jmp_im(tval);
5634: gen_set_label(l2);
5635: gen_eob(s);
5636: }
5637: break;
5638: case 0x130: /* wrmsr */
5639: case 0x132: /* rdmsr */
5640: if (s->cpl != 0) {
5641: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5642: } else {
1.1.1.6 ! root 5643: int retval = 0;
! 5644: if (b & 2) {
! 5645: retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0);
1.1 root 5646: gen_op_rdmsr();
1.1.1.6 ! root 5647: } else {
! 5648: retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1);
1.1 root 5649: gen_op_wrmsr();
1.1.1.6 ! root 5650: }
! 5651: if(retval)
! 5652: gen_eob(s);
1.1 root 5653: }
5654: break;
5655: case 0x131: /* rdtsc */
1.1.1.6 ! root 5656: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC))
! 5657: break;
1.1 root 5658: gen_jmp_im(pc_start - s->cs_base);
5659: gen_op_rdtsc();
5660: break;
1.1.1.6 ! root 5661: case 0x133: /* rdpmc */
! 5662: gen_jmp_im(pc_start - s->cs_base);
! 5663: gen_op_rdpmc();
! 5664: break;
1.1 root 5665: case 0x134: /* sysenter */
5666: if (CODE64(s))
5667: goto illegal_op;
5668: if (!s->pe) {
5669: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5670: } else {
5671: if (s->cc_op != CC_OP_DYNAMIC) {
5672: gen_op_set_cc_op(s->cc_op);
5673: s->cc_op = CC_OP_DYNAMIC;
5674: }
5675: gen_jmp_im(pc_start - s->cs_base);
5676: gen_op_sysenter();
5677: gen_eob(s);
5678: }
5679: break;
5680: case 0x135: /* sysexit */
5681: if (CODE64(s))
5682: goto illegal_op;
5683: if (!s->pe) {
5684: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5685: } else {
5686: if (s->cc_op != CC_OP_DYNAMIC) {
5687: gen_op_set_cc_op(s->cc_op);
5688: s->cc_op = CC_OP_DYNAMIC;
5689: }
5690: gen_jmp_im(pc_start - s->cs_base);
5691: gen_op_sysexit();
5692: gen_eob(s);
5693: }
5694: break;
5695: #ifdef TARGET_X86_64
5696: case 0x105: /* syscall */
5697: /* XXX: is it usable in real mode ? */
5698: if (s->cc_op != CC_OP_DYNAMIC) {
5699: gen_op_set_cc_op(s->cc_op);
5700: s->cc_op = CC_OP_DYNAMIC;
5701: }
5702: gen_jmp_im(pc_start - s->cs_base);
5703: gen_op_syscall(s->pc - pc_start);
5704: gen_eob(s);
5705: break;
5706: case 0x107: /* sysret */
5707: if (!s->pe) {
5708: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5709: } else {
5710: if (s->cc_op != CC_OP_DYNAMIC) {
5711: gen_op_set_cc_op(s->cc_op);
5712: s->cc_op = CC_OP_DYNAMIC;
5713: }
5714: gen_jmp_im(pc_start - s->cs_base);
5715: gen_op_sysret(s->dflag);
5716: /* condition codes are modified only in long mode */
5717: if (s->lma)
5718: s->cc_op = CC_OP_EFLAGS;
5719: gen_eob(s);
5720: }
5721: break;
5722: #endif
5723: case 0x1a2: /* cpuid */
1.1.1.6 ! root 5724: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID))
! 5725: break;
1.1 root 5726: gen_op_cpuid();
5727: break;
5728: case 0xf4: /* hlt */
5729: if (s->cpl != 0) {
5730: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5731: } else {
1.1.1.6 ! root 5732: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT))
! 5733: break;
1.1 root 5734: if (s->cc_op != CC_OP_DYNAMIC)
5735: gen_op_set_cc_op(s->cc_op);
5736: gen_jmp_im(s->pc - s->cs_base);
5737: gen_op_hlt();
5738: s->is_jmp = 3;
5739: }
5740: break;
5741: case 0x100:
5742: modrm = ldub_code(s->pc++);
5743: mod = (modrm >> 6) & 3;
5744: op = (modrm >> 3) & 7;
5745: switch(op) {
5746: case 0: /* sldt */
5747: if (!s->pe || s->vm86)
5748: goto illegal_op;
1.1.1.6 ! root 5749: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ))
! 5750: break;
1.1 root 5751: gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5752: ot = OT_WORD;
5753: if (mod == 3)
5754: ot += s->dflag;
5755: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5756: break;
5757: case 2: /* lldt */
5758: if (!s->pe || s->vm86)
5759: goto illegal_op;
5760: if (s->cpl != 0) {
5761: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5762: } else {
1.1.1.6 ! root 5763: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE))
! 5764: break;
1.1 root 5765: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5766: gen_jmp_im(pc_start - s->cs_base);
5767: gen_op_lldt_T0();
5768: }
5769: break;
5770: case 1: /* str */
5771: if (!s->pe || s->vm86)
5772: goto illegal_op;
1.1.1.6 ! root 5773: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ))
! 5774: break;
1.1 root 5775: gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5776: ot = OT_WORD;
5777: if (mod == 3)
5778: ot += s->dflag;
5779: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5780: break;
5781: case 3: /* ltr */
5782: if (!s->pe || s->vm86)
5783: goto illegal_op;
5784: if (s->cpl != 0) {
5785: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5786: } else {
1.1.1.6 ! root 5787: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE))
! 5788: break;
1.1 root 5789: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5790: gen_jmp_im(pc_start - s->cs_base);
5791: gen_op_ltr_T0();
5792: }
5793: break;
5794: case 4: /* verr */
5795: case 5: /* verw */
5796: if (!s->pe || s->vm86)
5797: goto illegal_op;
5798: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5799: if (s->cc_op != CC_OP_DYNAMIC)
5800: gen_op_set_cc_op(s->cc_op);
5801: if (op == 4)
5802: gen_op_verr();
5803: else
5804: gen_op_verw();
5805: s->cc_op = CC_OP_EFLAGS;
5806: break;
5807: default:
5808: goto illegal_op;
5809: }
5810: break;
5811: case 0x101:
5812: modrm = ldub_code(s->pc++);
5813: mod = (modrm >> 6) & 3;
5814: op = (modrm >> 3) & 7;
1.1.1.4 root 5815: rm = modrm & 7;
1.1 root 5816: switch(op) {
5817: case 0: /* sgdt */
5818: if (mod == 3)
5819: goto illegal_op;
1.1.1.6 ! root 5820: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ))
! 5821: break;
1.1 root 5822: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1.1.1.4 root 5823: gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
1.1 root 5824: gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5825: gen_add_A0_im(s, 2);
1.1.1.4 root 5826: gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base));
1.1 root 5827: if (!s->dflag)
5828: gen_op_andl_T0_im(0xffffff);
5829: gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5830: break;
1.1.1.4 root 5831: case 1:
5832: if (mod == 3) {
5833: switch (rm) {
5834: case 0: /* monitor */
5835: if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5836: s->cpl != 0)
5837: goto illegal_op;
1.1.1.6 ! root 5838: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR))
! 5839: break;
1.1.1.4 root 5840: gen_jmp_im(pc_start - s->cs_base);
5841: #ifdef TARGET_X86_64
5842: if (s->aflag == 2) {
5843: gen_op_movq_A0_reg[R_EBX]();
5844: gen_op_addq_A0_AL();
1.1.1.6 ! root 5845: } else
1.1.1.4 root 5846: #endif
5847: {
5848: gen_op_movl_A0_reg[R_EBX]();
5849: gen_op_addl_A0_AL();
5850: if (s->aflag == 0)
5851: gen_op_andl_A0_ffff();
5852: }
5853: gen_add_A0_ds_seg(s);
5854: gen_op_monitor();
5855: break;
5856: case 1: /* mwait */
5857: if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
5858: s->cpl != 0)
5859: goto illegal_op;
5860: if (s->cc_op != CC_OP_DYNAMIC) {
5861: gen_op_set_cc_op(s->cc_op);
5862: s->cc_op = CC_OP_DYNAMIC;
5863: }
1.1.1.6 ! root 5864: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT))
! 5865: break;
1.1.1.4 root 5866: gen_jmp_im(s->pc - s->cs_base);
5867: gen_op_mwait();
5868: gen_eob(s);
5869: break;
5870: default:
5871: goto illegal_op;
5872: }
5873: } else { /* sidt */
1.1.1.6 ! root 5874: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ))
! 5875: break;
1.1.1.4 root 5876: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5877: gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
5878: gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5879: gen_add_A0_im(s, 2);
5880: gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base));
5881: if (!s->dflag)
5882: gen_op_andl_T0_im(0xffffff);
5883: gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5884: }
5885: break;
1.1 root 5886: case 2: /* lgdt */
5887: case 3: /* lidt */
1.1.1.6 ! root 5888: if (mod == 3) {
! 5889: switch(rm) {
! 5890: case 0: /* VMRUN */
! 5891: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN))
! 5892: break;
! 5893: if (s->cc_op != CC_OP_DYNAMIC)
! 5894: gen_op_set_cc_op(s->cc_op);
! 5895: gen_jmp_im(s->pc - s->cs_base);
! 5896: gen_op_vmrun();
! 5897: s->cc_op = CC_OP_EFLAGS;
! 5898: gen_eob(s);
! 5899: break;
! 5900: case 1: /* VMMCALL */
! 5901: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL))
! 5902: break;
! 5903: /* FIXME: cause #UD if hflags & SVM */
! 5904: gen_op_vmmcall();
! 5905: break;
! 5906: case 2: /* VMLOAD */
! 5907: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD))
! 5908: break;
! 5909: gen_op_vmload();
! 5910: break;
! 5911: case 3: /* VMSAVE */
! 5912: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE))
! 5913: break;
! 5914: gen_op_vmsave();
! 5915: break;
! 5916: case 4: /* STGI */
! 5917: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI))
! 5918: break;
! 5919: gen_op_stgi();
! 5920: break;
! 5921: case 5: /* CLGI */
! 5922: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI))
! 5923: break;
! 5924: gen_op_clgi();
! 5925: break;
! 5926: case 6: /* SKINIT */
! 5927: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT))
! 5928: break;
! 5929: gen_op_skinit();
! 5930: break;
! 5931: case 7: /* INVLPGA */
! 5932: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA))
! 5933: break;
! 5934: gen_op_invlpga();
! 5935: break;
! 5936: default:
! 5937: goto illegal_op;
! 5938: }
! 5939: } else if (s->cpl != 0) {
1.1 root 5940: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5941: } else {
1.1.1.6 ! root 5942: if (gen_svm_check_intercept(s, pc_start,
! 5943: op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE))
! 5944: break;
1.1 root 5945: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5946: gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
5947: gen_add_A0_im(s, 2);
5948: gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5949: if (!s->dflag)
5950: gen_op_andl_T0_im(0xffffff);
5951: if (op == 2) {
5952: gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
5953: gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5954: } else {
5955: gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
5956: gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5957: }
5958: }
5959: break;
5960: case 4: /* smsw */
1.1.1.6 ! root 5961: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0))
! 5962: break;
1.1 root 5963: gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5964: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5965: break;
5966: case 6: /* lmsw */
5967: if (s->cpl != 0) {
5968: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5969: } else {
1.1.1.6 ! root 5970: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0))
! 5971: break;
1.1 root 5972: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5973: gen_op_lmsw_T0();
5974: gen_jmp_im(s->pc - s->cs_base);
5975: gen_eob(s);
5976: }
5977: break;
5978: case 7: /* invlpg */
5979: if (s->cpl != 0) {
5980: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5981: } else {
5982: if (mod == 3) {
5983: #ifdef TARGET_X86_64
1.1.1.4 root 5984: if (CODE64(s) && rm == 0) {
1.1 root 5985: /* swapgs */
5986: gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5987: gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5988: gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5989: gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
1.1.1.6 ! root 5990: } else
1.1 root 5991: #endif
5992: {
5993: goto illegal_op;
5994: }
5995: } else {
1.1.1.6 ! root 5996: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG))
! 5997: break;
1.1 root 5998: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5999: gen_op_invlpg_A0();
6000: gen_jmp_im(s->pc - s->cs_base);
6001: gen_eob(s);
6002: }
6003: }
6004: break;
6005: default:
6006: goto illegal_op;
6007: }
6008: break;
6009: case 0x108: /* invd */
6010: case 0x109: /* wbinvd */
6011: if (s->cpl != 0) {
6012: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6013: } else {
1.1.1.6 ! root 6014: if (gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD))
! 6015: break;
1.1 root 6016: /* nothing to do */
6017: }
6018: break;
6019: case 0x63: /* arpl or movslS (x86_64) */
6020: #ifdef TARGET_X86_64
6021: if (CODE64(s)) {
6022: int d_ot;
6023: /* d_ot is the size of destination */
6024: d_ot = dflag + OT_WORD;
6025:
6026: modrm = ldub_code(s->pc++);
6027: reg = ((modrm >> 3) & 7) | rex_r;
6028: mod = (modrm >> 6) & 3;
6029: rm = (modrm & 7) | REX_B(s);
1.1.1.6 ! root 6030:
1.1 root 6031: if (mod == 3) {
6032: gen_op_mov_TN_reg[OT_LONG][0][rm]();
6033: /* sign extend */
6034: if (d_ot == OT_QUAD)
6035: gen_op_movslq_T0_T0();
6036: gen_op_mov_reg_T0[d_ot][reg]();
6037: } else {
6038: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6039: if (d_ot == OT_QUAD) {
6040: gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
6041: } else {
6042: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6043: }
6044: gen_op_mov_reg_T0[d_ot][reg]();
6045: }
1.1.1.6 ! root 6046: } else
1.1 root 6047: #endif
6048: {
6049: if (!s->pe || s->vm86)
6050: goto illegal_op;
6051: ot = dflag ? OT_LONG : OT_WORD;
6052: modrm = ldub_code(s->pc++);
6053: reg = (modrm >> 3) & 7;
6054: mod = (modrm >> 6) & 3;
6055: rm = modrm & 7;
6056: if (mod != 3) {
6057: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6058: gen_op_ld_T0_A0[ot + s->mem_index]();
6059: } else {
6060: gen_op_mov_TN_reg[ot][0][rm]();
6061: }
6062: if (s->cc_op != CC_OP_DYNAMIC)
6063: gen_op_set_cc_op(s->cc_op);
6064: gen_op_arpl();
6065: s->cc_op = CC_OP_EFLAGS;
6066: if (mod != 3) {
6067: gen_op_st_T0_A0[ot + s->mem_index]();
6068: } else {
6069: gen_op_mov_reg_T0[ot][rm]();
6070: }
6071: gen_op_arpl_update();
6072: }
6073: break;
6074: case 0x102: /* lar */
6075: case 0x103: /* lsl */
6076: if (!s->pe || s->vm86)
6077: goto illegal_op;
6078: ot = dflag ? OT_LONG : OT_WORD;
6079: modrm = ldub_code(s->pc++);
6080: reg = ((modrm >> 3) & 7) | rex_r;
6081: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
6082: gen_op_mov_TN_reg[ot][1][reg]();
6083: if (s->cc_op != CC_OP_DYNAMIC)
6084: gen_op_set_cc_op(s->cc_op);
6085: if (b == 0x102)
6086: gen_op_lar();
6087: else
6088: gen_op_lsl();
6089: s->cc_op = CC_OP_EFLAGS;
6090: gen_op_mov_reg_T1[ot][reg]();
6091: break;
6092: case 0x118:
6093: modrm = ldub_code(s->pc++);
6094: mod = (modrm >> 6) & 3;
6095: op = (modrm >> 3) & 7;
6096: switch(op) {
6097: case 0: /* prefetchnta */
6098: case 1: /* prefetchnt0 */
6099: case 2: /* prefetchnt0 */
6100: case 3: /* prefetchnt0 */
6101: if (mod == 3)
6102: goto illegal_op;
6103: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6104: /* nothing more to do */
6105: break;
1.1.1.5 root 6106: default: /* nop (multi byte) */
6107: gen_nop_modrm(s, modrm);
6108: break;
1.1 root 6109: }
6110: break;
1.1.1.5 root 6111: case 0x119 ... 0x11f: /* nop (multi byte) */
6112: modrm = ldub_code(s->pc++);
6113: gen_nop_modrm(s, modrm);
6114: break;
1.1 root 6115: case 0x120: /* mov reg, crN */
6116: case 0x122: /* mov crN, reg */
6117: if (s->cpl != 0) {
6118: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6119: } else {
6120: modrm = ldub_code(s->pc++);
6121: if ((modrm & 0xc0) != 0xc0)
6122: goto illegal_op;
6123: rm = (modrm & 7) | REX_B(s);
6124: reg = ((modrm >> 3) & 7) | rex_r;
6125: if (CODE64(s))
6126: ot = OT_QUAD;
6127: else
6128: ot = OT_LONG;
6129: switch(reg) {
6130: case 0:
6131: case 2:
6132: case 3:
6133: case 4:
6134: case 8:
6135: if (b & 2) {
1.1.1.6 ! root 6136: gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg);
1.1 root 6137: gen_op_mov_TN_reg[ot][0][rm]();
6138: gen_op_movl_crN_T0(reg);
6139: gen_jmp_im(s->pc - s->cs_base);
6140: gen_eob(s);
6141: } else {
1.1.1.6 ! root 6142: gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg);
! 6143: #if !defined(CONFIG_USER_ONLY)
1.1 root 6144: if (reg == 8)
6145: gen_op_movtl_T0_cr8();
6146: else
6147: #endif
6148: gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
6149: gen_op_mov_reg_T0[ot][rm]();
6150: }
6151: break;
6152: default:
6153: goto illegal_op;
6154: }
6155: }
6156: break;
6157: case 0x121: /* mov reg, drN */
6158: case 0x123: /* mov drN, reg */
6159: if (s->cpl != 0) {
6160: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6161: } else {
6162: modrm = ldub_code(s->pc++);
6163: if ((modrm & 0xc0) != 0xc0)
6164: goto illegal_op;
6165: rm = (modrm & 7) | REX_B(s);
6166: reg = ((modrm >> 3) & 7) | rex_r;
6167: if (CODE64(s))
6168: ot = OT_QUAD;
6169: else
6170: ot = OT_LONG;
6171: /* XXX: do it dynamically with CR4.DE bit */
6172: if (reg == 4 || reg == 5 || reg >= 8)
6173: goto illegal_op;
6174: if (b & 2) {
1.1.1.6 ! root 6175: gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
1.1 root 6176: gen_op_mov_TN_reg[ot][0][rm]();
6177: gen_op_movl_drN_T0(reg);
6178: gen_jmp_im(s->pc - s->cs_base);
6179: gen_eob(s);
6180: } else {
1.1.1.6 ! root 6181: gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
1.1 root 6182: gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
6183: gen_op_mov_reg_T0[ot][rm]();
6184: }
6185: }
6186: break;
6187: case 0x106: /* clts */
6188: if (s->cpl != 0) {
6189: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6190: } else {
1.1.1.6 ! root 6191: gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
1.1 root 6192: gen_op_clts();
6193: /* abort block because static cpu state changed */
6194: gen_jmp_im(s->pc - s->cs_base);
6195: gen_eob(s);
6196: }
6197: break;
6198: /* MMX/SSE/SSE2/PNI support */
6199: case 0x1c3: /* MOVNTI reg, mem */
6200: if (!(s->cpuid_features & CPUID_SSE2))
6201: goto illegal_op;
6202: ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
6203: modrm = ldub_code(s->pc++);
6204: mod = (modrm >> 6) & 3;
6205: if (mod == 3)
6206: goto illegal_op;
6207: reg = ((modrm >> 3) & 7) | rex_r;
6208: /* generate a generic store */
6209: gen_ldst_modrm(s, modrm, ot, reg, 1);
6210: break;
6211: case 0x1ae:
6212: modrm = ldub_code(s->pc++);
6213: mod = (modrm >> 6) & 3;
6214: op = (modrm >> 3) & 7;
6215: switch(op) {
6216: case 0: /* fxsave */
1.1.1.6 ! root 6217: if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
1.1.1.3 root 6218: (s->flags & HF_EM_MASK))
1.1 root 6219: goto illegal_op;
1.1.1.3 root 6220: if (s->flags & HF_TS_MASK) {
6221: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6222: break;
6223: }
1.1 root 6224: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6225: gen_op_fxsave_A0((s->dflag == 2));
6226: break;
6227: case 1: /* fxrstor */
1.1.1.6 ! root 6228: if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
1.1.1.3 root 6229: (s->flags & HF_EM_MASK))
1.1 root 6230: goto illegal_op;
1.1.1.3 root 6231: if (s->flags & HF_TS_MASK) {
6232: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6233: break;
6234: }
1.1 root 6235: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6236: gen_op_fxrstor_A0((s->dflag == 2));
6237: break;
6238: case 2: /* ldmxcsr */
6239: case 3: /* stmxcsr */
6240: if (s->flags & HF_TS_MASK) {
6241: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
6242: break;
6243: }
6244: if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
6245: mod == 3)
6246: goto illegal_op;
6247: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6248: if (op == 2) {
6249: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
6250: gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
6251: } else {
6252: gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
6253: gen_op_st_T0_A0[OT_LONG + s->mem_index]();
6254: }
6255: break;
6256: case 5: /* lfence */
6257: case 6: /* mfence */
6258: if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
6259: goto illegal_op;
6260: break;
6261: case 7: /* sfence / clflush */
6262: if ((modrm & 0xc7) == 0xc0) {
6263: /* sfence */
6264: if (!(s->cpuid_features & CPUID_SSE))
6265: goto illegal_op;
6266: } else {
6267: /* clflush */
6268: if (!(s->cpuid_features & CPUID_CLFLUSH))
6269: goto illegal_op;
6270: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6271: }
6272: break;
6273: default:
6274: goto illegal_op;
6275: }
6276: break;
6277: case 0x10d: /* prefetch */
6278: modrm = ldub_code(s->pc++);
6279: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
6280: /* ignore for now */
6281: break;
1.1.1.5 root 6282: case 0x1aa: /* rsm */
1.1.1.6 ! root 6283: if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM))
! 6284: break;
1.1.1.5 root 6285: if (!(s->flags & HF_SMM_MASK))
6286: goto illegal_op;
6287: if (s->cc_op != CC_OP_DYNAMIC) {
6288: gen_op_set_cc_op(s->cc_op);
6289: s->cc_op = CC_OP_DYNAMIC;
6290: }
6291: gen_jmp_im(s->pc - s->cs_base);
6292: gen_op_rsm();
6293: gen_eob(s);
6294: break;
1.1 root 6295: case 0x110 ... 0x117:
6296: case 0x128 ... 0x12f:
6297: case 0x150 ... 0x177:
6298: case 0x17c ... 0x17f:
6299: case 0x1c2:
6300: case 0x1c4 ... 0x1c6:
6301: case 0x1d0 ... 0x1fe:
6302: gen_sse(s, b, pc_start, rex_r);
6303: break;
6304: default:
6305: goto illegal_op;
6306: }
6307: /* lock generation */
6308: if (s->prefix & PREFIX_LOCK)
6309: gen_op_unlock();
6310: return s->pc;
6311: illegal_op:
6312: if (s->prefix & PREFIX_LOCK)
6313: gen_op_unlock();
6314: /* XXX: ensure that no lock was generated */
6315: gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
6316: return s->pc;
6317: }
6318:
6319: #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
6320: #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
6321:
6322: /* flags read by an operation */
1.1.1.6 ! root 6323: static uint16_t opc_read_flags[NB_OPS] = {
1.1 root 6324: [INDEX_op_aas] = CC_A,
6325: [INDEX_op_aaa] = CC_A,
6326: [INDEX_op_das] = CC_A | CC_C,
6327: [INDEX_op_daa] = CC_A | CC_C,
6328:
6329: /* subtle: due to the incl/decl implementation, C is used */
1.1.1.6 ! root 6330: [INDEX_op_update_inc_cc] = CC_C,
1.1 root 6331:
6332: [INDEX_op_into] = CC_O,
6333:
6334: [INDEX_op_jb_subb] = CC_C,
6335: [INDEX_op_jb_subw] = CC_C,
6336: [INDEX_op_jb_subl] = CC_C,
6337:
6338: [INDEX_op_jz_subb] = CC_Z,
6339: [INDEX_op_jz_subw] = CC_Z,
6340: [INDEX_op_jz_subl] = CC_Z,
6341:
6342: [INDEX_op_jbe_subb] = CC_Z | CC_C,
6343: [INDEX_op_jbe_subw] = CC_Z | CC_C,
6344: [INDEX_op_jbe_subl] = CC_Z | CC_C,
6345:
6346: [INDEX_op_js_subb] = CC_S,
6347: [INDEX_op_js_subw] = CC_S,
6348: [INDEX_op_js_subl] = CC_S,
6349:
6350: [INDEX_op_jl_subb] = CC_O | CC_S,
6351: [INDEX_op_jl_subw] = CC_O | CC_S,
6352: [INDEX_op_jl_subl] = CC_O | CC_S,
6353:
6354: [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
6355: [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
6356: [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
6357:
6358: [INDEX_op_loopnzw] = CC_Z,
6359: [INDEX_op_loopnzl] = CC_Z,
6360: [INDEX_op_loopzw] = CC_Z,
6361: [INDEX_op_loopzl] = CC_Z,
6362:
6363: [INDEX_op_seto_T0_cc] = CC_O,
6364: [INDEX_op_setb_T0_cc] = CC_C,
6365: [INDEX_op_setz_T0_cc] = CC_Z,
6366: [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
6367: [INDEX_op_sets_T0_cc] = CC_S,
6368: [INDEX_op_setp_T0_cc] = CC_P,
6369: [INDEX_op_setl_T0_cc] = CC_O | CC_S,
6370: [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
6371:
6372: [INDEX_op_setb_T0_subb] = CC_C,
6373: [INDEX_op_setb_T0_subw] = CC_C,
6374: [INDEX_op_setb_T0_subl] = CC_C,
6375:
6376: [INDEX_op_setz_T0_subb] = CC_Z,
6377: [INDEX_op_setz_T0_subw] = CC_Z,
6378: [INDEX_op_setz_T0_subl] = CC_Z,
6379:
6380: [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
6381: [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
6382: [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
6383:
6384: [INDEX_op_sets_T0_subb] = CC_S,
6385: [INDEX_op_sets_T0_subw] = CC_S,
6386: [INDEX_op_sets_T0_subl] = CC_S,
6387:
6388: [INDEX_op_setl_T0_subb] = CC_O | CC_S,
6389: [INDEX_op_setl_T0_subw] = CC_O | CC_S,
6390: [INDEX_op_setl_T0_subl] = CC_O | CC_S,
6391:
6392: [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
6393: [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
6394: [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
6395:
6396: [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
6397: [INDEX_op_cmc] = CC_C,
6398: [INDEX_op_salc] = CC_C,
6399:
6400: /* needed for correct flag optimisation before string ops */
6401: [INDEX_op_jnz_ecxw] = CC_OSZAPC,
6402: [INDEX_op_jnz_ecxl] = CC_OSZAPC,
6403: [INDEX_op_jz_ecxw] = CC_OSZAPC,
6404: [INDEX_op_jz_ecxl] = CC_OSZAPC,
6405:
6406: #ifdef TARGET_X86_64
6407: [INDEX_op_jb_subq] = CC_C,
6408: [INDEX_op_jz_subq] = CC_Z,
6409: [INDEX_op_jbe_subq] = CC_Z | CC_C,
6410: [INDEX_op_js_subq] = CC_S,
6411: [INDEX_op_jl_subq] = CC_O | CC_S,
6412: [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
6413:
6414: [INDEX_op_loopnzq] = CC_Z,
6415: [INDEX_op_loopzq] = CC_Z,
6416:
6417: [INDEX_op_setb_T0_subq] = CC_C,
6418: [INDEX_op_setz_T0_subq] = CC_Z,
6419: [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
6420: [INDEX_op_sets_T0_subq] = CC_S,
6421: [INDEX_op_setl_T0_subq] = CC_O | CC_S,
6422: [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
6423:
6424: [INDEX_op_jnz_ecxq] = CC_OSZAPC,
6425: [INDEX_op_jz_ecxq] = CC_OSZAPC,
6426: #endif
6427:
6428: #define DEF_READF(SUFFIX)\
6429: [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6430: [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6431: [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6432: X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6433: [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6434: [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6435: [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6436: X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6437: \
6438: [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6439: [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6440: [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
6441: X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6442: [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6443: [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6444: [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6445: X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
6446:
6447: DEF_READF( )
6448: DEF_READF(_raw)
6449: #ifndef CONFIG_USER_ONLY
6450: DEF_READF(_kernel)
6451: DEF_READF(_user)
6452: #endif
6453: };
6454:
6455: /* flags written by an operation */
1.1.1.6 ! root 6456: static uint16_t opc_write_flags[NB_OPS] = {
1.1 root 6457: [INDEX_op_update2_cc] = CC_OSZAPC,
6458: [INDEX_op_update1_cc] = CC_OSZAPC,
6459: [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6460: [INDEX_op_update_neg_cc] = CC_OSZAPC,
6461: /* subtle: due to the incl/decl implementation, C is used */
1.1.1.6 ! root 6462: [INDEX_op_update_inc_cc] = CC_OSZAPC,
1.1 root 6463: [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6464:
6465: [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
6466: [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
6467: [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
6468: X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6469: [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6470: [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
6471: [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
6472: X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
6473: [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6474: [INDEX_op_imull_T0_T1] = CC_OSZAPC,
6475: X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6476:
6477: /* sse */
6478: [INDEX_op_ucomiss] = CC_OSZAPC,
6479: [INDEX_op_ucomisd] = CC_OSZAPC,
6480: [INDEX_op_comiss] = CC_OSZAPC,
6481: [INDEX_op_comisd] = CC_OSZAPC,
6482:
6483: /* bcd */
6484: [INDEX_op_aam] = CC_OSZAPC,
6485: [INDEX_op_aad] = CC_OSZAPC,
6486: [INDEX_op_aas] = CC_OSZAPC,
6487: [INDEX_op_aaa] = CC_OSZAPC,
6488: [INDEX_op_das] = CC_OSZAPC,
6489: [INDEX_op_daa] = CC_OSZAPC,
6490:
6491: [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6492: [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6493: [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
6494: [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6495: [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6496: [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6497: [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
6498: [INDEX_op_clc] = CC_C,
6499: [INDEX_op_stc] = CC_C,
6500: [INDEX_op_cmc] = CC_C,
6501:
6502: [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6503: [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
6504: X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
6505: [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6506: [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
6507: X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
6508: [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6509: [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
6510: X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
6511: [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6512: [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
6513: X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
6514:
6515: [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6516: [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
6517: X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
6518: [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6519: [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
6520: X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
6521:
6522: [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6523: [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6524: [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
6525: X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
6526:
6527: [INDEX_op_cmpxchg8b] = CC_Z,
6528: [INDEX_op_lar] = CC_Z,
6529: [INDEX_op_lsl] = CC_Z,
6530: [INDEX_op_verr] = CC_Z,
6531: [INDEX_op_verw] = CC_Z,
6532: [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6533: [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6534:
6535: #define DEF_WRITEF(SUFFIX)\
6536: [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6537: [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6538: [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6539: X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6540: [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6541: [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6542: [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6543: X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6544: \
6545: [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6546: [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6547: [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6548: X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6549: [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6550: [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6551: [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6552: X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6553: \
6554: [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6555: [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6556: [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6557: X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6558: [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6559: [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6560: [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6561: X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6562: \
6563: [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6564: [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6565: [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6566: X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6567: \
6568: [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6569: [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6570: [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6571: X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6572: \
6573: [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6574: [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6575: [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6576: X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6577: \
6578: [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6579: [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6580: X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6581: [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6582: [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6583: X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6584: \
6585: [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6586: [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6587: X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6588: [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6589: [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6590: X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6591: \
6592: [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6593: [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6594: [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6595: X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
6596:
6597:
6598: DEF_WRITEF( )
6599: DEF_WRITEF(_raw)
6600: #ifndef CONFIG_USER_ONLY
6601: DEF_WRITEF(_kernel)
6602: DEF_WRITEF(_user)
6603: #endif
6604: };
6605:
6606: /* simpler form of an operation if no flags need to be generated */
1.1.1.6 ! root 6607: static uint16_t opc_simpler[NB_OPS] = {
1.1 root 6608: [INDEX_op_update2_cc] = INDEX_op_nop,
6609: [INDEX_op_update1_cc] = INDEX_op_nop,
6610: [INDEX_op_update_neg_cc] = INDEX_op_nop,
6611: #if 0
6612: /* broken: CC_OP logic must be rewritten */
6613: [INDEX_op_update_inc_cc] = INDEX_op_nop,
6614: #endif
6615:
6616: [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6617: [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6618: [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
6619: X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
6620:
6621: [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6622: [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6623: [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
6624: X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
6625:
6626: [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6627: [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6628: [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
6629: X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
6630:
6631: #define DEF_SIMPLER(SUFFIX)\
6632: [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6633: [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6634: [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
6635: X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
6636: \
6637: [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6638: [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
6639: [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6640: X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
6641:
6642: DEF_SIMPLER( )
6643: DEF_SIMPLER(_raw)
6644: #ifndef CONFIG_USER_ONLY
6645: DEF_SIMPLER(_kernel)
6646: DEF_SIMPLER(_user)
6647: #endif
6648: };
6649:
6650: void optimize_flags_init(void)
6651: {
6652: int i;
6653: /* put default values in arrays */
6654: for(i = 0; i < NB_OPS; i++) {
6655: if (opc_simpler[i] == 0)
6656: opc_simpler[i] = i;
6657: }
6658: }
6659:
6660: /* CPU flags computation optimization: we move backward thru the
6661: generated code to see which flags are needed. The operation is
6662: modified if suitable */
6663: static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6664: {
6665: uint16_t *opc_ptr;
6666: int live_flags, write_flags, op;
6667:
6668: opc_ptr = opc_buf + opc_buf_len;
6669: /* live_flags contains the flags needed by the next instructions
1.1.1.6 ! root 6670: in the code. At the end of the block, we consider that all the
1.1 root 6671: flags are live. */
6672: live_flags = CC_OSZAPC;
6673: while (opc_ptr > opc_buf) {
6674: op = *--opc_ptr;
6675: /* if none of the flags written by the instruction is used,
6676: then we can try to find a simpler instruction */
6677: write_flags = opc_write_flags[op];
6678: if ((live_flags & write_flags) == 0) {
6679: *opc_ptr = opc_simpler[op];
6680: }
6681: /* compute the live flags before the instruction */
6682: live_flags &= ~write_flags;
6683: live_flags |= opc_read_flags[op];
6684: }
6685: }
6686:
6687: /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6688: basic block 'tb'. If search_pc is TRUE, also generate PC
6689: information for each intermediate instruction. */
6690: static inline int gen_intermediate_code_internal(CPUState *env,
1.1.1.6 ! root 6691: TranslationBlock *tb,
1.1 root 6692: int search_pc)
6693: {
6694: DisasContext dc1, *dc = &dc1;
6695: target_ulong pc_ptr;
6696: uint16_t *gen_opc_end;
1.1.1.6 ! root 6697: int j, lj, cflags;
! 6698: uint64_t flags;
1.1 root 6699: target_ulong pc_start;
6700: target_ulong cs_base;
1.1.1.6 ! root 6701:
1.1 root 6702: /* generate intermediate code */
6703: pc_start = tb->pc;
6704: cs_base = tb->cs_base;
6705: flags = tb->flags;
6706: cflags = tb->cflags;
6707:
6708: dc->pe = (flags >> HF_PE_SHIFT) & 1;
6709: dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6710: dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6711: dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6712: dc->f_st = 0;
6713: dc->vm86 = (flags >> VM_SHIFT) & 1;
6714: dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6715: dc->iopl = (flags >> IOPL_SHIFT) & 3;
6716: dc->tf = (flags >> TF_SHIFT) & 1;
6717: dc->singlestep_enabled = env->singlestep_enabled;
6718: dc->cc_op = CC_OP_DYNAMIC;
6719: dc->cs_base = cs_base;
6720: dc->tb = tb;
6721: dc->popl_esp_hack = 0;
6722: /* select memory access functions */
6723: dc->mem_index = 0;
6724: if (flags & HF_SOFTMMU_MASK) {
6725: if (dc->cpl == 3)
6726: dc->mem_index = 2 * 4;
6727: else
6728: dc->mem_index = 1 * 4;
6729: }
6730: dc->cpuid_features = env->cpuid_features;
1.1.1.4 root 6731: dc->cpuid_ext_features = env->cpuid_ext_features;
1.1 root 6732: #ifdef TARGET_X86_64
6733: dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6734: dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6735: #endif
6736: dc->flags = flags;
6737: dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6738: (flags & HF_INHIBIT_IRQ_MASK)
6739: #ifndef CONFIG_SOFTMMU
6740: || (flags & HF_SOFTMMU_MASK)
6741: #endif
6742: );
6743: #if 0
6744: /* check addseg logic */
6745: if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
6746: printf("ERROR addseg\n");
6747: #endif
6748:
6749: gen_opc_ptr = gen_opc_buf;
6750: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6751: gen_opparam_ptr = gen_opparam_buf;
6752: nb_gen_labels = 0;
6753:
6754: dc->is_jmp = DISAS_NEXT;
6755: pc_ptr = pc_start;
6756: lj = -1;
6757:
6758: for(;;) {
6759: if (env->nb_breakpoints > 0) {
6760: for(j = 0; j < env->nb_breakpoints; j++) {
6761: if (env->breakpoints[j] == pc_ptr) {
6762: gen_debug(dc, pc_ptr - dc->cs_base);
6763: break;
6764: }
6765: }
6766: }
6767: if (search_pc) {
6768: j = gen_opc_ptr - gen_opc_buf;
6769: if (lj < j) {
6770: lj++;
6771: while (lj < j)
6772: gen_opc_instr_start[lj++] = 0;
6773: }
6774: gen_opc_pc[lj] = pc_ptr;
6775: gen_opc_cc_op[lj] = dc->cc_op;
6776: gen_opc_instr_start[lj] = 1;
6777: }
6778: pc_ptr = disas_insn(dc, pc_ptr);
6779: /* stop translation if indicated */
6780: if (dc->is_jmp)
6781: break;
6782: /* if single step mode, we generate only one instruction and
6783: generate an exception */
6784: /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6785: the flag and abort the translation to give the irqs a
6786: change to be happen */
1.1.1.6 ! root 6787: if (dc->tf || dc->singlestep_enabled ||
1.1 root 6788: (flags & HF_INHIBIT_IRQ_MASK) ||
6789: (cflags & CF_SINGLE_INSN)) {
6790: gen_jmp_im(pc_ptr - dc->cs_base);
6791: gen_eob(dc);
6792: break;
6793: }
6794: /* if too long translation, stop generation too */
6795: if (gen_opc_ptr >= gen_opc_end ||
6796: (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
6797: gen_jmp_im(pc_ptr - dc->cs_base);
6798: gen_eob(dc);
6799: break;
6800: }
6801: }
6802: *gen_opc_ptr = INDEX_op_end;
6803: /* we don't forget to fill the last values */
6804: if (search_pc) {
6805: j = gen_opc_ptr - gen_opc_buf;
6806: lj++;
6807: while (lj <= j)
6808: gen_opc_instr_start[lj++] = 0;
6809: }
1.1.1.6 ! root 6810:
1.1 root 6811: #ifdef DEBUG_DISAS
6812: if (loglevel & CPU_LOG_TB_CPU) {
6813: cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
6814: }
6815: if (loglevel & CPU_LOG_TB_IN_ASM) {
6816: int disas_flags;
6817: fprintf(logfile, "----------------\n");
6818: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6819: #ifdef TARGET_X86_64
6820: if (dc->code64)
6821: disas_flags = 2;
6822: else
6823: #endif
6824: disas_flags = !dc->code32;
6825: target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
6826: fprintf(logfile, "\n");
6827: if (loglevel & CPU_LOG_TB_OP) {
6828: fprintf(logfile, "OP:\n");
6829: dump_ops(gen_opc_buf, gen_opparam_buf);
6830: fprintf(logfile, "\n");
6831: }
6832: }
6833: #endif
6834:
6835: /* optimize flag computations */
6836: optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6837:
6838: #ifdef DEBUG_DISAS
6839: if (loglevel & CPU_LOG_TB_OP_OPT) {
6840: fprintf(logfile, "AFTER FLAGS OPT:\n");
6841: dump_ops(gen_opc_buf, gen_opparam_buf);
6842: fprintf(logfile, "\n");
6843: }
6844: #endif
6845: if (!search_pc)
6846: tb->size = pc_ptr - pc_start;
6847: return 0;
6848: }
6849:
6850: int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6851: {
6852: return gen_intermediate_code_internal(env, tb, 0);
6853: }
6854:
6855: int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6856: {
6857: return gen_intermediate_code_internal(env, tb, 1);
6858: }
6859:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.