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