|
|
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:
1703: static inline void gen_jcc(DisasContext *s, int b,
1704: target_ulong val, target_ulong next_eip)
1705: {
1706: TranslationBlock *tb;
1707: int inv, jcc_op;
1708: GenOpFunc1 *func;
1709: target_ulong tmp;
1710: int l1, l2;
1711:
1712: inv = b & 1;
1713: jcc_op = (b >> 1) & 7;
1714:
1715: if (s->jmp_opt) {
1716: switch(s->cc_op) {
1717: /* we optimize the cmp/jcc case */
1718: case CC_OP_SUBB:
1719: case CC_OP_SUBW:
1720: case CC_OP_SUBL:
1721: case CC_OP_SUBQ:
1722: func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1723: break;
1724:
1725: /* some jumps are easy to compute */
1726: case CC_OP_ADDB:
1727: case CC_OP_ADDW:
1728: case CC_OP_ADDL:
1729: case CC_OP_ADDQ:
1730:
1731: case CC_OP_ADCB:
1732: case CC_OP_ADCW:
1733: case CC_OP_ADCL:
1734: case CC_OP_ADCQ:
1735:
1736: case CC_OP_SBBB:
1737: case CC_OP_SBBW:
1738: case CC_OP_SBBL:
1739: case CC_OP_SBBQ:
1740:
1741: case CC_OP_LOGICB:
1742: case CC_OP_LOGICW:
1743: case CC_OP_LOGICL:
1744: case CC_OP_LOGICQ:
1745:
1746: case CC_OP_INCB:
1747: case CC_OP_INCW:
1748: case CC_OP_INCL:
1749: case CC_OP_INCQ:
1750:
1751: case CC_OP_DECB:
1752: case CC_OP_DECW:
1753: case CC_OP_DECL:
1754: case CC_OP_DECQ:
1755:
1756: case CC_OP_SHLB:
1757: case CC_OP_SHLW:
1758: case CC_OP_SHLL:
1759: case CC_OP_SHLQ:
1760:
1761: case CC_OP_SARB:
1762: case CC_OP_SARW:
1763: case CC_OP_SARL:
1764: case CC_OP_SARQ:
1765: switch(jcc_op) {
1766: case JCC_Z:
1767: func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1768: break;
1769: case JCC_S:
1770: func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1771: break;
1772: default:
1773: func = NULL;
1774: break;
1775: }
1776: break;
1777: default:
1778: func = NULL;
1779: break;
1780: }
1781:
1782: if (s->cc_op != CC_OP_DYNAMIC)
1783: gen_op_set_cc_op(s->cc_op);
1784:
1785: if (!func) {
1786: gen_setcc_slow[jcc_op]();
1787: func = gen_op_jnz_T0_label;
1788: }
1789:
1790: if (inv) {
1791: tmp = val;
1792: val = next_eip;
1793: next_eip = tmp;
1794: }
1795: tb = s->tb;
1796:
1797: l1 = gen_new_label();
1798: func(l1);
1799:
1800: gen_op_goto_tb0(TBPARAM(tb));
1801: gen_jmp_im(next_eip);
1802: gen_op_movl_T0_im((long)tb + 0);
1803: gen_op_exit_tb();
1804:
1805: gen_set_label(l1);
1806: gen_op_goto_tb1(TBPARAM(tb));
1807: gen_jmp_im(val);
1808: gen_op_movl_T0_im((long)tb + 1);
1809: gen_op_exit_tb();
1810:
1811: s->is_jmp = 3;
1812: } else {
1813:
1814: if (s->cc_op != CC_OP_DYNAMIC) {
1815: gen_op_set_cc_op(s->cc_op);
1816: s->cc_op = CC_OP_DYNAMIC;
1817: }
1818: gen_setcc_slow[jcc_op]();
1819: if (inv) {
1820: tmp = val;
1821: val = next_eip;
1822: next_eip = tmp;
1823: }
1824: l1 = gen_new_label();
1825: l2 = gen_new_label();
1826: gen_op_jnz_T0_label(l1);
1827: gen_jmp_im(next_eip);
1828: gen_op_jmp_label(l2);
1829: gen_set_label(l1);
1830: gen_jmp_im(val);
1831: gen_set_label(l2);
1832: gen_eob(s);
1833: }
1834: }
1835:
1836: static void gen_setcc(DisasContext *s, int b)
1837: {
1838: int inv, jcc_op;
1839: GenOpFunc *func;
1840:
1841: inv = b & 1;
1842: jcc_op = (b >> 1) & 7;
1843: switch(s->cc_op) {
1844: /* we optimize the cmp/jcc case */
1845: case CC_OP_SUBB:
1846: case CC_OP_SUBW:
1847: case CC_OP_SUBL:
1848: case CC_OP_SUBQ:
1849: func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1850: if (!func)
1851: goto slow_jcc;
1852: break;
1853:
1854: /* some jumps are easy to compute */
1855: case CC_OP_ADDB:
1856: case CC_OP_ADDW:
1857: case CC_OP_ADDL:
1858: case CC_OP_ADDQ:
1859:
1860: case CC_OP_LOGICB:
1861: case CC_OP_LOGICW:
1862: case CC_OP_LOGICL:
1863: case CC_OP_LOGICQ:
1864:
1865: case CC_OP_INCB:
1866: case CC_OP_INCW:
1867: case CC_OP_INCL:
1868: case CC_OP_INCQ:
1869:
1870: case CC_OP_DECB:
1871: case CC_OP_DECW:
1872: case CC_OP_DECL:
1873: case CC_OP_DECQ:
1874:
1875: case CC_OP_SHLB:
1876: case CC_OP_SHLW:
1877: case CC_OP_SHLL:
1878: case CC_OP_SHLQ:
1879: switch(jcc_op) {
1880: case JCC_Z:
1881: func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1882: break;
1883: case JCC_S:
1884: func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1885: break;
1886: default:
1887: goto slow_jcc;
1888: }
1889: break;
1890: default:
1891: slow_jcc:
1892: if (s->cc_op != CC_OP_DYNAMIC)
1893: gen_op_set_cc_op(s->cc_op);
1894: func = gen_setcc_slow[jcc_op];
1895: break;
1896: }
1897: func();
1898: if (inv) {
1899: gen_op_xor_T0_1();
1900: }
1901: }
1902:
1903: /* move T0 to seg_reg and compute if the CPU state may change. Never
1904: call this function with seg_reg == R_CS */
1905: static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
1906: {
1907: if (s->pe && !s->vm86) {
1908: /* XXX: optimize by finding processor state dynamically */
1909: if (s->cc_op != CC_OP_DYNAMIC)
1910: gen_op_set_cc_op(s->cc_op);
1911: gen_jmp_im(cur_eip);
1912: gen_op_movl_seg_T0(seg_reg);
1913: /* abort translation because the addseg value may change or
1914: because ss32 may change. For R_SS, translation must always
1915: stop as a special handling must be done to disable hardware
1916: interrupts for the next instruction */
1917: if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1918: s->is_jmp = 3;
1919: } else {
1920: gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1921: if (seg_reg == R_SS)
1922: s->is_jmp = 3;
1923: }
1924: }
1925:
1926: static inline void gen_stack_update(DisasContext *s, int addend)
1927: {
1928: #ifdef TARGET_X86_64
1929: if (CODE64(s)) {
1930: if (addend == 8)
1931: gen_op_addq_ESP_8();
1932: else
1933: gen_op_addq_ESP_im(addend);
1934: } else
1935: #endif
1936: if (s->ss32) {
1937: if (addend == 2)
1938: gen_op_addl_ESP_2();
1939: else if (addend == 4)
1940: gen_op_addl_ESP_4();
1941: else
1942: gen_op_addl_ESP_im(addend);
1943: } else {
1944: if (addend == 2)
1945: gen_op_addw_ESP_2();
1946: else if (addend == 4)
1947: gen_op_addw_ESP_4();
1948: else
1949: gen_op_addw_ESP_im(addend);
1950: }
1951: }
1952:
1953: /* generate a push. It depends on ss32, addseg and dflag */
1954: static void gen_push_T0(DisasContext *s)
1955: {
1956: #ifdef TARGET_X86_64
1957: if (CODE64(s)) {
1958: gen_op_movq_A0_reg[R_ESP]();
1959: if (s->dflag) {
1960: gen_op_subq_A0_8();
1961: gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
1962: } else {
1963: gen_op_subq_A0_2();
1964: gen_op_st_T0_A0[OT_WORD + s->mem_index]();
1965: }
1966: gen_op_movq_ESP_A0();
1967: } else
1968: #endif
1969: {
1970: gen_op_movl_A0_reg[R_ESP]();
1971: if (!s->dflag)
1972: gen_op_subl_A0_2();
1973: else
1974: gen_op_subl_A0_4();
1975: if (s->ss32) {
1976: if (s->addseg) {
1977: gen_op_movl_T1_A0();
1978: gen_op_addl_A0_SS();
1979: }
1980: } else {
1981: gen_op_andl_A0_ffff();
1982: gen_op_movl_T1_A0();
1983: gen_op_addl_A0_SS();
1984: }
1985: gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
1986: if (s->ss32 && !s->addseg)
1987: gen_op_movl_ESP_A0();
1988: else
1989: gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
1990: }
1991: }
1992:
1993: /* generate a push. It depends on ss32, addseg and dflag */
1994: /* slower version for T1, only used for call Ev */
1995: static void gen_push_T1(DisasContext *s)
1996: {
1997: #ifdef TARGET_X86_64
1998: if (CODE64(s)) {
1999: gen_op_movq_A0_reg[R_ESP]();
2000: if (s->dflag) {
2001: gen_op_subq_A0_8();
2002: gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
2003: } else {
2004: gen_op_subq_A0_2();
2005: gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2006: }
2007: gen_op_movq_ESP_A0();
2008: } else
2009: #endif
2010: {
2011: gen_op_movl_A0_reg[R_ESP]();
2012: if (!s->dflag)
2013: gen_op_subl_A0_2();
2014: else
2015: gen_op_subl_A0_4();
2016: if (s->ss32) {
2017: if (s->addseg) {
2018: gen_op_addl_A0_SS();
2019: }
2020: } else {
2021: gen_op_andl_A0_ffff();
2022: gen_op_addl_A0_SS();
2023: }
2024: gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
2025:
2026: if (s->ss32 && !s->addseg)
2027: gen_op_movl_ESP_A0();
2028: else
2029: gen_stack_update(s, (-2) << s->dflag);
2030: }
2031: }
2032:
2033: /* two step pop is necessary for precise exceptions */
2034: static void gen_pop_T0(DisasContext *s)
2035: {
2036: #ifdef TARGET_X86_64
2037: if (CODE64(s)) {
2038: gen_op_movq_A0_reg[R_ESP]();
2039: gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index]();
2040: } else
2041: #endif
2042: {
2043: gen_op_movl_A0_reg[R_ESP]();
2044: if (s->ss32) {
2045: if (s->addseg)
2046: gen_op_addl_A0_SS();
2047: } else {
2048: gen_op_andl_A0_ffff();
2049: gen_op_addl_A0_SS();
2050: }
2051: gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2052: }
2053: }
2054:
2055: static void gen_pop_update(DisasContext *s)
2056: {
2057: #ifdef TARGET_X86_64
2058: if (CODE64(s) && s->dflag) {
2059: gen_stack_update(s, 8);
2060: } else
2061: #endif
2062: {
2063: gen_stack_update(s, 2 << s->dflag);
2064: }
2065: }
2066:
2067: static void gen_stack_A0(DisasContext *s)
2068: {
2069: gen_op_movl_A0_ESP();
2070: if (!s->ss32)
2071: gen_op_andl_A0_ffff();
2072: gen_op_movl_T1_A0();
2073: if (s->addseg)
2074: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2075: }
2076:
2077: /* NOTE: wrap around in 16 bit not fully handled */
2078: static void gen_pusha(DisasContext *s)
2079: {
2080: int i;
2081: gen_op_movl_A0_ESP();
2082: gen_op_addl_A0_im(-16 << s->dflag);
2083: if (!s->ss32)
2084: gen_op_andl_A0_ffff();
2085: gen_op_movl_T1_A0();
2086: if (s->addseg)
2087: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2088: for(i = 0;i < 8; i++) {
2089: gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
2090: gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2091: gen_op_addl_A0_im(2 << s->dflag);
2092: }
2093: gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2094: }
2095:
2096: /* NOTE: wrap around in 16 bit not fully handled */
2097: static void gen_popa(DisasContext *s)
2098: {
2099: int i;
2100: gen_op_movl_A0_ESP();
2101: if (!s->ss32)
2102: gen_op_andl_A0_ffff();
2103: gen_op_movl_T1_A0();
2104: gen_op_addl_T1_im(16 << s->dflag);
2105: if (s->addseg)
2106: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2107: for(i = 0;i < 8; i++) {
2108: /* ESP is not reloaded */
2109: if (i != 3) {
2110: gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2111: gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
2112: }
2113: gen_op_addl_A0_im(2 << s->dflag);
2114: }
2115: gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2116: }
2117:
2118: static void gen_enter(DisasContext *s, int esp_addend, int level)
2119: {
2120: int ot, opsize;
2121:
2122: level &= 0x1f;
2123: #ifdef TARGET_X86_64
2124: if (CODE64(s)) {
2125: ot = s->dflag ? OT_QUAD : OT_WORD;
2126: opsize = 1 << ot;
2127:
2128: gen_op_movl_A0_ESP();
2129: gen_op_addq_A0_im(-opsize);
2130: gen_op_movl_T1_A0();
2131:
2132: /* push bp */
2133: gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2134: gen_op_st_T0_A0[ot + s->mem_index]();
2135: if (level) {
2136: gen_op_enter64_level(level, (ot == OT_QUAD));
2137: }
2138: gen_op_mov_reg_T1[ot][R_EBP]();
2139: gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2140: gen_op_mov_reg_T1[OT_QUAD][R_ESP]();
2141: } else
2142: #endif
2143: {
2144: ot = s->dflag + OT_WORD;
2145: opsize = 2 << s->dflag;
2146:
2147: gen_op_movl_A0_ESP();
2148: gen_op_addl_A0_im(-opsize);
2149: if (!s->ss32)
2150: gen_op_andl_A0_ffff();
2151: gen_op_movl_T1_A0();
2152: if (s->addseg)
2153: gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2154: /* push bp */
2155: gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2156: gen_op_st_T0_A0[ot + s->mem_index]();
2157: if (level) {
2158: gen_op_enter_level(level, s->dflag);
2159: }
2160: gen_op_mov_reg_T1[ot][R_EBP]();
2161: gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2162: gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2163: }
2164: }
2165:
2166: static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2167: {
2168: if (s->cc_op != CC_OP_DYNAMIC)
2169: gen_op_set_cc_op(s->cc_op);
2170: gen_jmp_im(cur_eip);
2171: gen_op_raise_exception(trapno);
2172: s->is_jmp = 3;
2173: }
2174:
2175: /* an interrupt is different from an exception because of the
2176: priviledge checks */
2177: static void gen_interrupt(DisasContext *s, int intno,
2178: target_ulong cur_eip, target_ulong next_eip)
2179: {
2180: if (s->cc_op != CC_OP_DYNAMIC)
2181: gen_op_set_cc_op(s->cc_op);
2182: gen_jmp_im(cur_eip);
2183: gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
2184: s->is_jmp = 3;
2185: }
2186:
2187: static void gen_debug(DisasContext *s, 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_debug();
2193: s->is_jmp = 3;
2194: }
2195:
2196: /* generate a generic end of block. Trace exception is also generated
2197: if needed */
2198: static void gen_eob(DisasContext *s)
2199: {
2200: if (s->cc_op != CC_OP_DYNAMIC)
2201: gen_op_set_cc_op(s->cc_op);
2202: if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2203: gen_op_reset_inhibit_irq();
2204: }
2205: if (s->singlestep_enabled) {
2206: gen_op_debug();
2207: } else if (s->tf) {
2208: gen_op_raise_exception(EXCP01_SSTP);
2209: } else {
2210: gen_op_movl_T0_0();
2211: gen_op_exit_tb();
2212: }
2213: s->is_jmp = 3;
2214: }
2215:
2216: /* generate a jump to eip. No segment change must happen before as a
2217: direct call to the next block may occur */
2218: static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2219: {
2220: TranslationBlock *tb = s->tb;
2221:
2222: if (s->jmp_opt) {
2223: if (s->cc_op != CC_OP_DYNAMIC)
2224: gen_op_set_cc_op(s->cc_op);
2225: if (tb_num)
2226: gen_op_goto_tb1(TBPARAM(tb));
2227: else
2228: gen_op_goto_tb0(TBPARAM(tb));
2229: gen_jmp_im(eip);
2230: gen_op_movl_T0_im((long)tb + tb_num);
2231: gen_op_exit_tb();
2232: s->is_jmp = 3;
2233: } else {
2234: gen_jmp_im(eip);
2235: gen_eob(s);
2236: }
2237: }
2238:
2239: static void gen_jmp(DisasContext *s, target_ulong eip)
2240: {
2241: gen_jmp_tb(s, eip, 0);
2242: }
2243:
2244: static void gen_movtl_T0_im(target_ulong val)
2245: {
2246: #ifdef TARGET_X86_64
2247: if ((int32_t)val == val) {
2248: gen_op_movl_T0_im(val);
2249: } else {
2250: gen_op_movq_T0_im64(val >> 32, val);
2251: }
2252: #else
2253: gen_op_movl_T0_im(val);
2254: #endif
2255: }
2256:
2257: static void gen_movtl_T1_im(target_ulong val)
2258: {
2259: #ifdef TARGET_X86_64
2260: if ((int32_t)val == val) {
2261: gen_op_movl_T1_im(val);
2262: } else {
2263: gen_op_movq_T1_im64(val >> 32, val);
2264: }
2265: #else
2266: gen_op_movl_T1_im(val);
2267: #endif
2268: }
2269:
2270: static void gen_add_A0_im(DisasContext *s, int val)
2271: {
2272: #ifdef TARGET_X86_64
2273: if (CODE64(s))
2274: gen_op_addq_A0_im(val);
2275: else
2276: #endif
2277: gen_op_addl_A0_im(val);
2278: }
2279:
2280: static GenOpFunc1 *gen_ldq_env_A0[3] = {
2281: gen_op_ldq_raw_env_A0,
2282: #ifndef CONFIG_USER_ONLY
2283: gen_op_ldq_kernel_env_A0,
2284: gen_op_ldq_user_env_A0,
2285: #endif
2286: };
2287:
2288: static GenOpFunc1 *gen_stq_env_A0[3] = {
2289: gen_op_stq_raw_env_A0,
2290: #ifndef CONFIG_USER_ONLY
2291: gen_op_stq_kernel_env_A0,
2292: gen_op_stq_user_env_A0,
2293: #endif
2294: };
2295:
2296: static GenOpFunc1 *gen_ldo_env_A0[3] = {
2297: gen_op_ldo_raw_env_A0,
2298: #ifndef CONFIG_USER_ONLY
2299: gen_op_ldo_kernel_env_A0,
2300: gen_op_ldo_user_env_A0,
2301: #endif
2302: };
2303:
2304: static GenOpFunc1 *gen_sto_env_A0[3] = {
2305: gen_op_sto_raw_env_A0,
2306: #ifndef CONFIG_USER_ONLY
2307: gen_op_sto_kernel_env_A0,
2308: gen_op_sto_user_env_A0,
2309: #endif
2310: };
2311:
2312: #define SSE_SPECIAL ((GenOpFunc2 *)1)
2313:
2314: #define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm }
2315: #define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \
2316: gen_op_ ## x ## ss, gen_op_ ## x ## sd, }
2317:
2318: static GenOpFunc2 *sse_op_table1[256][4] = {
2319: /* pure SSE operations */
2320: [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2321: [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2322: [0x12] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2323: [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
2324: [0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm },
2325: [0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm },
2326: [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2327: [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2328:
2329: [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2330: [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2331: [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2332: [0x2b] = { SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd */
2333: [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2334: [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2335: [0x2e] = { gen_op_ucomiss, gen_op_ucomisd },
2336: [0x2f] = { gen_op_comiss, gen_op_comisd },
2337: [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2338: [0x51] = SSE_FOP(sqrt),
2339: [0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL },
2340: [0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL },
2341: [0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */
2342: [0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */
2343: [0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */
2344: [0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */
2345: [0x58] = SSE_FOP(add),
2346: [0x59] = SSE_FOP(mul),
2347: [0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps,
2348: gen_op_cvtss2sd, gen_op_cvtsd2ss },
2349: [0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq },
2350: [0x5c] = SSE_FOP(sub),
2351: [0x5d] = SSE_FOP(min),
2352: [0x5e] = SSE_FOP(div),
2353: [0x5f] = SSE_FOP(max),
2354:
2355: [0xc2] = SSE_FOP(cmpeq),
2356: [0xc6] = { (GenOpFunc2 *)gen_op_shufps, (GenOpFunc2 *)gen_op_shufpd },
2357:
2358: /* MMX ops and their SSE extensions */
2359: [0x60] = MMX_OP2(punpcklbw),
2360: [0x61] = MMX_OP2(punpcklwd),
2361: [0x62] = MMX_OP2(punpckldq),
2362: [0x63] = MMX_OP2(packsswb),
2363: [0x64] = MMX_OP2(pcmpgtb),
2364: [0x65] = MMX_OP2(pcmpgtw),
2365: [0x66] = MMX_OP2(pcmpgtl),
2366: [0x67] = MMX_OP2(packuswb),
2367: [0x68] = MMX_OP2(punpckhbw),
2368: [0x69] = MMX_OP2(punpckhwd),
2369: [0x6a] = MMX_OP2(punpckhdq),
2370: [0x6b] = MMX_OP2(packssdw),
2371: [0x6c] = { NULL, gen_op_punpcklqdq_xmm },
2372: [0x6d] = { NULL, gen_op_punpckhqdq_xmm },
2373: [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2374: [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2375: [0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx,
2376: (GenOpFunc2 *)gen_op_pshufd_xmm,
2377: (GenOpFunc2 *)gen_op_pshufhw_xmm,
2378: (GenOpFunc2 *)gen_op_pshuflw_xmm },
2379: [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2380: [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2381: [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2382: [0x74] = MMX_OP2(pcmpeqb),
2383: [0x75] = MMX_OP2(pcmpeqw),
2384: [0x76] = MMX_OP2(pcmpeql),
2385: [0x77] = { SSE_SPECIAL }, /* emms */
2386: [0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps },
2387: [0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps },
2388: [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2389: [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2390: [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2391: [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2392: [0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps },
2393: [0xd1] = MMX_OP2(psrlw),
2394: [0xd2] = MMX_OP2(psrld),
2395: [0xd3] = MMX_OP2(psrlq),
2396: [0xd4] = MMX_OP2(paddq),
2397: [0xd5] = MMX_OP2(pmullw),
2398: [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2399: [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2400: [0xd8] = MMX_OP2(psubusb),
2401: [0xd9] = MMX_OP2(psubusw),
2402: [0xda] = MMX_OP2(pminub),
2403: [0xdb] = MMX_OP2(pand),
2404: [0xdc] = MMX_OP2(paddusb),
2405: [0xdd] = MMX_OP2(paddusw),
2406: [0xde] = MMX_OP2(pmaxub),
2407: [0xdf] = MMX_OP2(pandn),
2408: [0xe0] = MMX_OP2(pavgb),
2409: [0xe1] = MMX_OP2(psraw),
2410: [0xe2] = MMX_OP2(psrad),
2411: [0xe3] = MMX_OP2(pavgw),
2412: [0xe4] = MMX_OP2(pmulhuw),
2413: [0xe5] = MMX_OP2(pmulhw),
2414: [0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq },
2415: [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2416: [0xe8] = MMX_OP2(psubsb),
2417: [0xe9] = MMX_OP2(psubsw),
2418: [0xea] = MMX_OP2(pminsw),
2419: [0xeb] = MMX_OP2(por),
2420: [0xec] = MMX_OP2(paddsb),
2421: [0xed] = MMX_OP2(paddsw),
2422: [0xee] = MMX_OP2(pmaxsw),
2423: [0xef] = MMX_OP2(pxor),
2424: [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu (PNI) */
2425: [0xf1] = MMX_OP2(psllw),
2426: [0xf2] = MMX_OP2(pslld),
2427: [0xf3] = MMX_OP2(psllq),
2428: [0xf4] = MMX_OP2(pmuludq),
2429: [0xf5] = MMX_OP2(pmaddwd),
2430: [0xf6] = MMX_OP2(psadbw),
2431: [0xf7] = MMX_OP2(maskmov),
2432: [0xf8] = MMX_OP2(psubb),
2433: [0xf9] = MMX_OP2(psubw),
2434: [0xfa] = MMX_OP2(psubl),
2435: [0xfb] = MMX_OP2(psubq),
2436: [0xfc] = MMX_OP2(paddb),
2437: [0xfd] = MMX_OP2(paddw),
2438: [0xfe] = MMX_OP2(paddl),
2439: };
2440:
2441: static GenOpFunc2 *sse_op_table2[3 * 8][2] = {
2442: [0 + 2] = MMX_OP2(psrlw),
2443: [0 + 4] = MMX_OP2(psraw),
2444: [0 + 6] = MMX_OP2(psllw),
2445: [8 + 2] = MMX_OP2(psrld),
2446: [8 + 4] = MMX_OP2(psrad),
2447: [8 + 6] = MMX_OP2(pslld),
2448: [16 + 2] = MMX_OP2(psrlq),
2449: [16 + 3] = { NULL, gen_op_psrldq_xmm },
2450: [16 + 6] = MMX_OP2(psllq),
2451: [16 + 7] = { NULL, gen_op_pslldq_xmm },
2452: };
2453:
2454: static GenOpFunc1 *sse_op_table3[4 * 3] = {
2455: gen_op_cvtsi2ss,
2456: gen_op_cvtsi2sd,
2457: X86_64_ONLY(gen_op_cvtsq2ss),
2458: X86_64_ONLY(gen_op_cvtsq2sd),
2459:
2460: gen_op_cvttss2si,
2461: gen_op_cvttsd2si,
2462: X86_64_ONLY(gen_op_cvttss2sq),
2463: X86_64_ONLY(gen_op_cvttsd2sq),
2464:
2465: gen_op_cvtss2si,
2466: gen_op_cvtsd2si,
2467: X86_64_ONLY(gen_op_cvtss2sq),
2468: X86_64_ONLY(gen_op_cvtsd2sq),
2469: };
2470:
2471: static GenOpFunc2 *sse_op_table4[8][4] = {
2472: SSE_FOP(cmpeq),
2473: SSE_FOP(cmplt),
2474: SSE_FOP(cmple),
2475: SSE_FOP(cmpunord),
2476: SSE_FOP(cmpneq),
2477: SSE_FOP(cmpnlt),
2478: SSE_FOP(cmpnle),
2479: SSE_FOP(cmpord),
2480: };
2481:
2482: static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2483: {
2484: int b1, op1_offset, op2_offset, is_xmm, val, ot;
2485: int modrm, mod, rm, reg, reg_addr, offset_addr;
2486: GenOpFunc2 *sse_op2;
2487: GenOpFunc3 *sse_op3;
2488:
2489: b &= 0xff;
2490: if (s->prefix & PREFIX_DATA)
2491: b1 = 1;
2492: else if (s->prefix & PREFIX_REPZ)
2493: b1 = 2;
2494: else if (s->prefix & PREFIX_REPNZ)
2495: b1 = 3;
2496: else
2497: b1 = 0;
2498: sse_op2 = sse_op_table1[b][b1];
2499: if (!sse_op2)
2500: goto illegal_op;
2501: if (b <= 0x5f || b == 0xc6 || b == 0xc2) {
2502: is_xmm = 1;
2503: } else {
2504: if (b1 == 0) {
2505: /* MMX case */
2506: is_xmm = 0;
2507: } else {
2508: is_xmm = 1;
2509: }
2510: }
2511: /* simple MMX/SSE operation */
2512: if (s->flags & HF_TS_MASK) {
2513: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2514: return;
2515: }
2516: if (s->flags & HF_EM_MASK) {
2517: illegal_op:
2518: gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2519: return;
2520: }
2521: if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2522: goto illegal_op;
2523: if (b == 0x77) {
2524: /* emms */
2525: gen_op_emms();
2526: return;
2527: }
2528: /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2529: the static cpu state) */
2530: if (!is_xmm) {
2531: gen_op_enter_mmx();
2532: }
2533:
2534: modrm = ldub_code(s->pc++);
2535: reg = ((modrm >> 3) & 7);
2536: if (is_xmm)
2537: reg |= rex_r;
2538: mod = (modrm >> 6) & 3;
2539: if (sse_op2 == SSE_SPECIAL) {
2540: b |= (b1 << 8);
2541: switch(b) {
2542: case 0x0e7: /* movntq */
2543: if (mod == 3)
2544: goto illegal_op;
2545: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2546: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2547: break;
2548: case 0x1e7: /* movntdq */
2549: case 0x02b: /* movntps */
2550: case 0x12b: /* movntps */
2551: case 0x2f0: /* lddqu */
2552: if (mod == 3)
2553: goto illegal_op;
2554: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2555: gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2556: break;
2557: case 0x6e: /* movd mm, ea */
2558: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2559: gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2560: break;
2561: case 0x16e: /* movd xmm, ea */
2562: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2563: gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2564: break;
2565: case 0x6f: /* movq mm, ea */
2566: if (mod != 3) {
2567: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2568: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2569: } else {
2570: rm = (modrm & 7);
2571: gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx),
2572: offsetof(CPUX86State,fpregs[rm].mmx));
2573: }
2574: break;
2575: case 0x010: /* movups */
2576: case 0x110: /* movupd */
2577: case 0x028: /* movaps */
2578: case 0x128: /* movapd */
2579: case 0x16f: /* movdqa xmm, ea */
2580: case 0x26f: /* movdqu xmm, ea */
2581: if (mod != 3) {
2582: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2583: gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2584: } else {
2585: rm = (modrm & 7) | REX_B(s);
2586: gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2587: offsetof(CPUX86State,xmm_regs[rm]));
2588: }
2589: break;
2590: case 0x210: /* movss xmm, ea */
2591: if (mod != 3) {
2592: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2593: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2594: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2595: gen_op_movl_T0_0();
2596: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2597: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2598: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2599: } else {
2600: rm = (modrm & 7) | REX_B(s);
2601: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2602: offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2603: }
2604: break;
2605: case 0x310: /* movsd xmm, ea */
2606: if (mod != 3) {
2607: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2608: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2609: gen_op_movl_T0_0();
2610: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2611: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2612: } else {
2613: rm = (modrm & 7) | REX_B(s);
2614: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2615: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2616: }
2617: break;
2618: case 0x012: /* movlps */
2619: case 0x112: /* movlpd */
2620: if (mod != 3) {
2621: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2622: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2623: } else {
2624: /* movhlps */
2625: rm = (modrm & 7) | REX_B(s);
2626: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2627: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2628: }
2629: break;
2630: case 0x016: /* movhps */
2631: case 0x116: /* movhpd */
2632: if (mod != 3) {
2633: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2634: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2635: } else {
2636: /* movlhps */
2637: rm = (modrm & 7) | REX_B(s);
2638: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2639: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2640: }
2641: break;
2642: case 0x216: /* movshdup */
2643: if (mod != 3) {
2644: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2645: gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2646: } else {
2647: rm = (modrm & 7) | REX_B(s);
2648: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2649: offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
2650: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2651: offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
2652: }
2653: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2654: offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2655: gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2656: offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2657: break;
2658: case 0x7e: /* movd ea, mm */
2659: gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2660: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2661: break;
2662: case 0x17e: /* movd ea, xmm */
2663: gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2664: gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2665: break;
2666: case 0x27e: /* movq xmm, ea */
2667: if (mod != 3) {
2668: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2669: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2670: } else {
2671: rm = (modrm & 7) | REX_B(s);
2672: gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2673: offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2674: }
2675: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2676: break;
2677: case 0x7f: /* movq ea, mm */
2678: if (mod != 3) {
2679: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2680: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2681: } else {
2682: rm = (modrm & 7);
2683: gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2684: offsetof(CPUX86State,fpregs[reg].mmx));
2685: }
2686: break;
2687: case 0x011: /* movups */
2688: case 0x111: /* movupd */
2689: case 0x029: /* movaps */
2690: case 0x129: /* movapd */
2691: case 0x17f: /* movdqa ea, xmm */
2692: case 0x27f: /* movdqu ea, xmm */
2693: if (mod != 3) {
2694: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2695: gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2696: } else {
2697: rm = (modrm & 7) | REX_B(s);
2698: gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
2699: offsetof(CPUX86State,xmm_regs[reg]));
2700: }
2701: break;
2702: case 0x211: /* movss ea, xmm */
2703: if (mod != 3) {
2704: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2705: gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2706: gen_op_st_T0_A0[OT_LONG + s->mem_index]();
2707: } else {
2708: rm = (modrm & 7) | REX_B(s);
2709: gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
2710: offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2711: }
2712: break;
2713: case 0x311: /* movsd ea, xmm */
2714: if (mod != 3) {
2715: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2716: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2717: } else {
2718: rm = (modrm & 7) | REX_B(s);
2719: gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2720: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2721: }
2722: break;
2723: case 0x013: /* movlps */
2724: case 0x113: /* movlpd */
2725: if (mod != 3) {
2726: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2727: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2728: } else {
2729: goto illegal_op;
2730: }
2731: break;
2732: case 0x017: /* movhps */
2733: case 0x117: /* movhpd */
2734: if (mod != 3) {
2735: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2736: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2737: } else {
2738: goto illegal_op;
2739: }
2740: break;
2741: case 0x71: /* shift mm, im */
2742: case 0x72:
2743: case 0x73:
2744: case 0x171: /* shift xmm, im */
2745: case 0x172:
2746: case 0x173:
2747: val = ldub_code(s->pc++);
2748: if (is_xmm) {
2749: gen_op_movl_T0_im(val);
2750: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2751: gen_op_movl_T0_0();
2752: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1)));
2753: op1_offset = offsetof(CPUX86State,xmm_t0);
2754: } else {
2755: gen_op_movl_T0_im(val);
2756: gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0)));
2757: gen_op_movl_T0_0();
2758: gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1)));
2759: op1_offset = offsetof(CPUX86State,mmx_t0);
2760: }
2761: sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
2762: if (!sse_op2)
2763: goto illegal_op;
2764: if (is_xmm) {
2765: rm = (modrm & 7) | REX_B(s);
2766: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2767: } else {
2768: rm = (modrm & 7);
2769: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2770: }
2771: sse_op2(op2_offset, op1_offset);
2772: break;
2773: case 0x050: /* movmskps */
2774: rm = (modrm & 7) | REX_B(s);
2775: gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm]));
2776: gen_op_mov_reg_T0[OT_LONG][reg]();
2777: break;
2778: case 0x150: /* movmskpd */
2779: rm = (modrm & 7) | REX_B(s);
2780: gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm]));
2781: gen_op_mov_reg_T0[OT_LONG][reg]();
2782: break;
2783: case 0x02a: /* cvtpi2ps */
2784: case 0x12a: /* cvtpi2pd */
2785: gen_op_enter_mmx();
2786: if (mod != 3) {
2787: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2788: op2_offset = offsetof(CPUX86State,mmx_t0);
2789: gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
2790: } else {
2791: rm = (modrm & 7);
2792: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2793: }
2794: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2795: switch(b >> 8) {
2796: case 0x0:
2797: gen_op_cvtpi2ps(op1_offset, op2_offset);
2798: break;
2799: default:
2800: case 0x1:
2801: gen_op_cvtpi2pd(op1_offset, op2_offset);
2802: break;
2803: }
2804: break;
2805: case 0x22a: /* cvtsi2ss */
2806: case 0x32a: /* cvtsi2sd */
2807: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
2808: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2809: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2810: sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset);
2811: break;
2812: case 0x02c: /* cvttps2pi */
2813: case 0x12c: /* cvttpd2pi */
2814: case 0x02d: /* cvtps2pi */
2815: case 0x12d: /* cvtpd2pi */
2816: gen_op_enter_mmx();
2817: if (mod != 3) {
2818: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2819: op2_offset = offsetof(CPUX86State,xmm_t0);
2820: gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
2821: } else {
2822: rm = (modrm & 7) | REX_B(s);
2823: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2824: }
2825: op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
2826: switch(b) {
2827: case 0x02c:
2828: gen_op_cvttps2pi(op1_offset, op2_offset);
2829: break;
2830: case 0x12c:
2831: gen_op_cvttpd2pi(op1_offset, op2_offset);
2832: break;
2833: case 0x02d:
2834: gen_op_cvtps2pi(op1_offset, op2_offset);
2835: break;
2836: case 0x12d:
2837: gen_op_cvtpd2pi(op1_offset, op2_offset);
2838: break;
2839: }
2840: break;
2841: case 0x22c: /* cvttss2si */
2842: case 0x32c: /* cvttsd2si */
2843: case 0x22d: /* cvtss2si */
2844: case 0x32d: /* cvtsd2si */
2845: ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
2846: if (mod != 3) {
2847: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2848: if ((b >> 8) & 1) {
2849: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
2850: } else {
2851: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2852: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2853: }
2854: op2_offset = offsetof(CPUX86State,xmm_t0);
2855: } else {
2856: rm = (modrm & 7) | REX_B(s);
2857: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2858: }
2859: sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
2860: (b & 1) * 4](op2_offset);
2861: gen_op_mov_reg_T0[ot][reg]();
2862: break;
2863: case 0xc4: /* pinsrw */
2864: case 0x1c4:
2865: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2866: val = ldub_code(s->pc++);
2867: if (b1) {
2868: val &= 7;
2869: gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val);
2870: } else {
2871: val &= 3;
2872: gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val);
2873: }
2874: break;
2875: case 0xc5: /* pextrw */
2876: case 0x1c5:
2877: if (mod != 3)
2878: goto illegal_op;
2879: val = ldub_code(s->pc++);
2880: if (b1) {
2881: val &= 7;
2882: rm = (modrm & 7) | REX_B(s);
2883: gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val);
2884: } else {
2885: val &= 3;
2886: rm = (modrm & 7);
2887: gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val);
2888: }
2889: reg = ((modrm >> 3) & 7) | rex_r;
2890: gen_op_mov_reg_T0[OT_LONG][reg]();
2891: break;
2892: case 0x1d6: /* movq ea, xmm */
2893: if (mod != 3) {
2894: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2895: gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2896: } else {
2897: rm = (modrm & 7) | REX_B(s);
2898: gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2899: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2900: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2901: }
2902: break;
2903: case 0x2d6: /* movq2dq */
2904: gen_op_enter_mmx();
2905: rm = (modrm & 7) | REX_B(s);
2906: gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2907: offsetof(CPUX86State,fpregs[reg & 7].mmx));
2908: gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2909: break;
2910: case 0x3d6: /* movdq2q */
2911: gen_op_enter_mmx();
2912: rm = (modrm & 7);
2913: gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2914: offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2915: break;
2916: case 0xd7: /* pmovmskb */
2917: case 0x1d7:
2918: if (mod != 3)
2919: goto illegal_op;
2920: if (b1) {
2921: rm = (modrm & 7) | REX_B(s);
2922: gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm]));
2923: } else {
2924: rm = (modrm & 7);
2925: gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx));
2926: }
2927: reg = ((modrm >> 3) & 7) | rex_r;
2928: gen_op_mov_reg_T0[OT_LONG][reg]();
2929: break;
2930: default:
2931: goto illegal_op;
2932: }
2933: } else {
2934: /* generic MMX or SSE operation */
2935: if (b == 0xf7) {
2936: /* maskmov : we must prepare A0 */
2937: if (mod != 3)
2938: goto illegal_op;
2939: #ifdef TARGET_X86_64
2940: if (s->aflag == 2) {
2941: gen_op_movq_A0_reg[R_EDI]();
2942: } else
2943: #endif
2944: {
2945: gen_op_movl_A0_reg[R_EDI]();
2946: if (s->aflag == 0)
2947: gen_op_andl_A0_ffff();
2948: }
2949: gen_add_A0_ds_seg(s);
2950: }
2951: if (is_xmm) {
2952: op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2953: if (mod != 3) {
2954: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2955: op2_offset = offsetof(CPUX86State,xmm_t0);
2956: if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f) ||
2957: b == 0xc2)) {
2958: /* specific case for SSE single instructions */
2959: if (b1 == 2) {
2960: /* 32 bit access */
2961: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2962: gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2963: } else {
2964: /* 64 bit access */
2965: gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_D(0)));
2966: }
2967: } else {
2968: gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
2969: }
2970: } else {
2971: rm = (modrm & 7) | REX_B(s);
2972: op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2973: }
2974: } else {
2975: op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
2976: if (mod != 3) {
2977: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2978: op2_offset = offsetof(CPUX86State,mmx_t0);
2979: gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
2980: } else {
2981: rm = (modrm & 7);
2982: op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2983: }
2984: }
2985: switch(b) {
2986: case 0x70: /* pshufx insn */
2987: case 0xc6: /* pshufx insn */
2988: val = ldub_code(s->pc++);
2989: sse_op3 = (GenOpFunc3 *)sse_op2;
2990: sse_op3(op1_offset, op2_offset, val);
2991: break;
2992: case 0xc2:
2993: /* compare insns */
2994: val = ldub_code(s->pc++);
2995: if (val >= 8)
2996: goto illegal_op;
2997: sse_op2 = sse_op_table4[val][b1];
2998: sse_op2(op1_offset, op2_offset);
2999: break;
3000: default:
3001: sse_op2(op1_offset, op2_offset);
3002: break;
3003: }
3004: if (b == 0x2e || b == 0x2f) {
3005: s->cc_op = CC_OP_EFLAGS;
3006: }
3007: }
3008: }
3009:
3010:
3011: /* convert one instruction. s->is_jmp is set if the translation must
3012: be stopped. Return the next pc value */
3013: static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
3014: {
3015: int b, prefixes, aflag, dflag;
3016: int shift, ot;
3017: int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
3018: target_ulong next_eip, tval;
3019: int rex_w, rex_r;
3020:
3021: s->pc = pc_start;
3022: prefixes = 0;
3023: aflag = s->code32;
3024: dflag = s->code32;
3025: s->override = -1;
3026: rex_w = -1;
3027: rex_r = 0;
3028: #ifdef TARGET_X86_64
3029: s->rex_x = 0;
3030: s->rex_b = 0;
3031: x86_64_hregs = 0;
3032: #endif
3033: s->rip_offset = 0; /* for relative ip address */
3034: next_byte:
3035: b = ldub_code(s->pc);
3036: s->pc++;
3037: /* check prefixes */
3038: #ifdef TARGET_X86_64
3039: if (CODE64(s)) {
3040: switch (b) {
3041: case 0xf3:
3042: prefixes |= PREFIX_REPZ;
3043: goto next_byte;
3044: case 0xf2:
3045: prefixes |= PREFIX_REPNZ;
3046: goto next_byte;
3047: case 0xf0:
3048: prefixes |= PREFIX_LOCK;
3049: goto next_byte;
3050: case 0x2e:
3051: s->override = R_CS;
3052: goto next_byte;
3053: case 0x36:
3054: s->override = R_SS;
3055: goto next_byte;
3056: case 0x3e:
3057: s->override = R_DS;
3058: goto next_byte;
3059: case 0x26:
3060: s->override = R_ES;
3061: goto next_byte;
3062: case 0x64:
3063: s->override = R_FS;
3064: goto next_byte;
3065: case 0x65:
3066: s->override = R_GS;
3067: goto next_byte;
3068: case 0x66:
3069: prefixes |= PREFIX_DATA;
3070: goto next_byte;
3071: case 0x67:
3072: prefixes |= PREFIX_ADR;
3073: goto next_byte;
3074: case 0x40 ... 0x4f:
3075: /* REX prefix */
3076: rex_w = (b >> 3) & 1;
3077: rex_r = (b & 0x4) << 1;
3078: s->rex_x = (b & 0x2) << 2;
3079: REX_B(s) = (b & 0x1) << 3;
3080: x86_64_hregs = 1; /* select uniform byte register addressing */
3081: goto next_byte;
3082: }
3083: if (rex_w == 1) {
3084: /* 0x66 is ignored if rex.w is set */
3085: dflag = 2;
3086: } else {
3087: if (prefixes & PREFIX_DATA)
3088: dflag ^= 1;
3089: }
3090: if (!(prefixes & PREFIX_ADR))
3091: aflag = 2;
3092: } else
3093: #endif
3094: {
3095: switch (b) {
3096: case 0xf3:
3097: prefixes |= PREFIX_REPZ;
3098: goto next_byte;
3099: case 0xf2:
3100: prefixes |= PREFIX_REPNZ;
3101: goto next_byte;
3102: case 0xf0:
3103: prefixes |= PREFIX_LOCK;
3104: goto next_byte;
3105: case 0x2e:
3106: s->override = R_CS;
3107: goto next_byte;
3108: case 0x36:
3109: s->override = R_SS;
3110: goto next_byte;
3111: case 0x3e:
3112: s->override = R_DS;
3113: goto next_byte;
3114: case 0x26:
3115: s->override = R_ES;
3116: goto next_byte;
3117: case 0x64:
3118: s->override = R_FS;
3119: goto next_byte;
3120: case 0x65:
3121: s->override = R_GS;
3122: goto next_byte;
3123: case 0x66:
3124: prefixes |= PREFIX_DATA;
3125: goto next_byte;
3126: case 0x67:
3127: prefixes |= PREFIX_ADR;
3128: goto next_byte;
3129: }
3130: if (prefixes & PREFIX_DATA)
3131: dflag ^= 1;
3132: if (prefixes & PREFIX_ADR)
3133: aflag ^= 1;
3134: }
3135:
3136: s->prefix = prefixes;
3137: s->aflag = aflag;
3138: s->dflag = dflag;
3139:
3140: /* lock generation */
3141: if (prefixes & PREFIX_LOCK)
3142: gen_op_lock();
3143:
3144: /* now check op code */
3145: reswitch:
3146: switch(b) {
3147: case 0x0f:
3148: /**************************/
3149: /* extended op code */
3150: b = ldub_code(s->pc++) | 0x100;
3151: goto reswitch;
3152:
3153: /**************************/
3154: /* arith & logic */
3155: case 0x00 ... 0x05:
3156: case 0x08 ... 0x0d:
3157: case 0x10 ... 0x15:
3158: case 0x18 ... 0x1d:
3159: case 0x20 ... 0x25:
3160: case 0x28 ... 0x2d:
3161: case 0x30 ... 0x35:
3162: case 0x38 ... 0x3d:
3163: {
3164: int op, f, val;
3165: op = (b >> 3) & 7;
3166: f = (b >> 1) & 3;
3167:
3168: if ((b & 1) == 0)
3169: ot = OT_BYTE;
3170: else
3171: ot = dflag + OT_WORD;
3172:
3173: switch(f) {
3174: case 0: /* OP Ev, Gv */
3175: modrm = ldub_code(s->pc++);
3176: reg = ((modrm >> 3) & 7) | rex_r;
3177: mod = (modrm >> 6) & 3;
3178: rm = (modrm & 7) | REX_B(s);
3179: if (mod != 3) {
3180: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3181: opreg = OR_TMP0;
3182: } else if (op == OP_XORL && rm == reg) {
3183: xor_zero:
3184: /* xor reg, reg optimisation */
3185: gen_op_movl_T0_0();
3186: s->cc_op = CC_OP_LOGICB + ot;
3187: gen_op_mov_reg_T0[ot][reg]();
3188: gen_op_update1_cc();
3189: break;
3190: } else {
3191: opreg = rm;
3192: }
3193: gen_op_mov_TN_reg[ot][1][reg]();
3194: gen_op(s, op, ot, opreg);
3195: break;
3196: case 1: /* OP Gv, Ev */
3197: modrm = ldub_code(s->pc++);
3198: mod = (modrm >> 6) & 3;
3199: reg = ((modrm >> 3) & 7) | rex_r;
3200: rm = (modrm & 7) | REX_B(s);
3201: if (mod != 3) {
3202: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3203: gen_op_ld_T1_A0[ot + s->mem_index]();
3204: } else if (op == OP_XORL && rm == reg) {
3205: goto xor_zero;
3206: } else {
3207: gen_op_mov_TN_reg[ot][1][rm]();
3208: }
3209: gen_op(s, op, ot, reg);
3210: break;
3211: case 2: /* OP A, Iv */
3212: val = insn_get(s, ot);
3213: gen_op_movl_T1_im(val);
3214: gen_op(s, op, ot, OR_EAX);
3215: break;
3216: }
3217: }
3218: break;
3219:
3220: case 0x80: /* GRP1 */
3221: case 0x81:
3222: case 0x82:
3223: case 0x83:
3224: {
3225: int val;
3226:
3227: if ((b & 1) == 0)
3228: ot = OT_BYTE;
3229: else
3230: ot = dflag + OT_WORD;
3231:
3232: modrm = ldub_code(s->pc++);
3233: mod = (modrm >> 6) & 3;
3234: rm = (modrm & 7) | REX_B(s);
3235: op = (modrm >> 3) & 7;
3236:
3237: if (mod != 3) {
3238: if (b == 0x83)
3239: s->rip_offset = 1;
3240: else
3241: s->rip_offset = insn_const_size(ot);
3242: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3243: opreg = OR_TMP0;
3244: } else {
3245: opreg = rm;
3246: }
3247:
3248: switch(b) {
3249: default:
3250: case 0x80:
3251: case 0x81:
3252: case 0x82:
3253: val = insn_get(s, ot);
3254: break;
3255: case 0x83:
3256: val = (int8_t)insn_get(s, OT_BYTE);
3257: break;
3258: }
3259: gen_op_movl_T1_im(val);
3260: gen_op(s, op, ot, opreg);
3261: }
3262: break;
3263:
3264: /**************************/
3265: /* inc, dec, and other misc arith */
3266: case 0x40 ... 0x47: /* inc Gv */
3267: ot = dflag ? OT_LONG : OT_WORD;
3268: gen_inc(s, ot, OR_EAX + (b & 7), 1);
3269: break;
3270: case 0x48 ... 0x4f: /* dec Gv */
3271: ot = dflag ? OT_LONG : OT_WORD;
3272: gen_inc(s, ot, OR_EAX + (b & 7), -1);
3273: break;
3274: case 0xf6: /* GRP3 */
3275: case 0xf7:
3276: if ((b & 1) == 0)
3277: ot = OT_BYTE;
3278: else
3279: ot = dflag + OT_WORD;
3280:
3281: modrm = ldub_code(s->pc++);
3282: mod = (modrm >> 6) & 3;
3283: rm = (modrm & 7) | REX_B(s);
3284: op = (modrm >> 3) & 7;
3285: if (mod != 3) {
3286: if (op == 0)
3287: s->rip_offset = insn_const_size(ot);
3288: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3289: gen_op_ld_T0_A0[ot + s->mem_index]();
3290: } else {
3291: gen_op_mov_TN_reg[ot][0][rm]();
3292: }
3293:
3294: switch(op) {
3295: case 0: /* test */
3296: val = insn_get(s, ot);
3297: gen_op_movl_T1_im(val);
3298: gen_op_testl_T0_T1_cc();
3299: s->cc_op = CC_OP_LOGICB + ot;
3300: break;
3301: case 2: /* not */
3302: gen_op_notl_T0();
3303: if (mod != 3) {
3304: gen_op_st_T0_A0[ot + s->mem_index]();
3305: } else {
3306: gen_op_mov_reg_T0[ot][rm]();
3307: }
3308: break;
3309: case 3: /* neg */
3310: gen_op_negl_T0();
3311: if (mod != 3) {
3312: gen_op_st_T0_A0[ot + s->mem_index]();
3313: } else {
3314: gen_op_mov_reg_T0[ot][rm]();
3315: }
3316: gen_op_update_neg_cc();
3317: s->cc_op = CC_OP_SUBB + ot;
3318: break;
3319: case 4: /* mul */
3320: switch(ot) {
3321: case OT_BYTE:
3322: gen_op_mulb_AL_T0();
3323: s->cc_op = CC_OP_MULB;
3324: break;
3325: case OT_WORD:
3326: gen_op_mulw_AX_T0();
3327: s->cc_op = CC_OP_MULW;
3328: break;
3329: default:
3330: case OT_LONG:
3331: gen_op_mull_EAX_T0();
3332: s->cc_op = CC_OP_MULL;
3333: break;
3334: #ifdef TARGET_X86_64
3335: case OT_QUAD:
3336: gen_op_mulq_EAX_T0();
3337: s->cc_op = CC_OP_MULQ;
3338: break;
3339: #endif
3340: }
3341: break;
3342: case 5: /* imul */
3343: switch(ot) {
3344: case OT_BYTE:
3345: gen_op_imulb_AL_T0();
3346: s->cc_op = CC_OP_MULB;
3347: break;
3348: case OT_WORD:
3349: gen_op_imulw_AX_T0();
3350: s->cc_op = CC_OP_MULW;
3351: break;
3352: default:
3353: case OT_LONG:
3354: gen_op_imull_EAX_T0();
3355: s->cc_op = CC_OP_MULL;
3356: break;
3357: #ifdef TARGET_X86_64
3358: case OT_QUAD:
3359: gen_op_imulq_EAX_T0();
3360: s->cc_op = CC_OP_MULQ;
3361: break;
3362: #endif
3363: }
3364: break;
3365: case 6: /* div */
3366: switch(ot) {
3367: case OT_BYTE:
3368: gen_jmp_im(pc_start - s->cs_base);
3369: gen_op_divb_AL_T0();
3370: break;
3371: case OT_WORD:
3372: gen_jmp_im(pc_start - s->cs_base);
3373: gen_op_divw_AX_T0();
3374: break;
3375: default:
3376: case OT_LONG:
3377: gen_jmp_im(pc_start - s->cs_base);
3378: gen_op_divl_EAX_T0();
3379: break;
3380: #ifdef TARGET_X86_64
3381: case OT_QUAD:
3382: gen_jmp_im(pc_start - s->cs_base);
3383: gen_op_divq_EAX_T0();
3384: break;
3385: #endif
3386: }
3387: break;
3388: case 7: /* idiv */
3389: switch(ot) {
3390: case OT_BYTE:
3391: gen_jmp_im(pc_start - s->cs_base);
3392: gen_op_idivb_AL_T0();
3393: break;
3394: case OT_WORD:
3395: gen_jmp_im(pc_start - s->cs_base);
3396: gen_op_idivw_AX_T0();
3397: break;
3398: default:
3399: case OT_LONG:
3400: gen_jmp_im(pc_start - s->cs_base);
3401: gen_op_idivl_EAX_T0();
3402: break;
3403: #ifdef TARGET_X86_64
3404: case OT_QUAD:
3405: gen_jmp_im(pc_start - s->cs_base);
3406: gen_op_idivq_EAX_T0();
3407: break;
3408: #endif
3409: }
3410: break;
3411: default:
3412: goto illegal_op;
3413: }
3414: break;
3415:
3416: case 0xfe: /* GRP4 */
3417: case 0xff: /* GRP5 */
3418: if ((b & 1) == 0)
3419: ot = OT_BYTE;
3420: else
3421: ot = dflag + OT_WORD;
3422:
3423: modrm = ldub_code(s->pc++);
3424: mod = (modrm >> 6) & 3;
3425: rm = (modrm & 7) | REX_B(s);
3426: op = (modrm >> 3) & 7;
3427: if (op >= 2 && b == 0xfe) {
3428: goto illegal_op;
3429: }
3430: if (CODE64(s)) {
3431: if (op == 2 || op == 4) {
3432: /* operand size for jumps is 64 bit */
3433: ot = OT_QUAD;
3434: } else if (op == 3 || op == 5) {
3435: /* for call calls, the operand is 16 or 32 bit, even
3436: in long mode */
3437: ot = dflag ? OT_LONG : OT_WORD;
3438: } else if (op == 6) {
3439: /* default push size is 64 bit */
3440: ot = dflag ? OT_QUAD : OT_WORD;
3441: }
3442: }
3443: if (mod != 3) {
3444: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3445: if (op >= 2 && op != 3 && op != 5)
3446: gen_op_ld_T0_A0[ot + s->mem_index]();
3447: } else {
3448: gen_op_mov_TN_reg[ot][0][rm]();
3449: }
3450:
3451: switch(op) {
3452: case 0: /* inc Ev */
3453: if (mod != 3)
3454: opreg = OR_TMP0;
3455: else
3456: opreg = rm;
3457: gen_inc(s, ot, opreg, 1);
3458: break;
3459: case 1: /* dec Ev */
3460: if (mod != 3)
3461: opreg = OR_TMP0;
3462: else
3463: opreg = rm;
3464: gen_inc(s, ot, opreg, -1);
3465: break;
3466: case 2: /* call Ev */
3467: /* XXX: optimize if memory (no 'and' is necessary) */
3468: if (s->dflag == 0)
3469: gen_op_andl_T0_ffff();
3470: next_eip = s->pc - s->cs_base;
3471: gen_movtl_T1_im(next_eip);
3472: gen_push_T1(s);
3473: gen_op_jmp_T0();
3474: gen_eob(s);
3475: break;
3476: case 3: /* lcall Ev */
3477: gen_op_ld_T1_A0[ot + s->mem_index]();
3478: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3479: gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3480: do_lcall:
3481: if (s->pe && !s->vm86) {
3482: if (s->cc_op != CC_OP_DYNAMIC)
3483: gen_op_set_cc_op(s->cc_op);
3484: gen_jmp_im(pc_start - s->cs_base);
3485: gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
3486: } else {
3487: gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
3488: }
3489: gen_eob(s);
3490: break;
3491: case 4: /* jmp Ev */
3492: if (s->dflag == 0)
3493: gen_op_andl_T0_ffff();
3494: gen_op_jmp_T0();
3495: gen_eob(s);
3496: break;
3497: case 5: /* ljmp Ev */
3498: gen_op_ld_T1_A0[ot + s->mem_index]();
3499: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3500: gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3501: do_ljmp:
3502: if (s->pe && !s->vm86) {
3503: if (s->cc_op != CC_OP_DYNAMIC)
3504: gen_op_set_cc_op(s->cc_op);
3505: gen_jmp_im(pc_start - s->cs_base);
3506: gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
3507: } else {
3508: gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3509: gen_op_movl_T0_T1();
3510: gen_op_jmp_T0();
3511: }
3512: gen_eob(s);
3513: break;
3514: case 6: /* push Ev */
3515: gen_push_T0(s);
3516: break;
3517: default:
3518: goto illegal_op;
3519: }
3520: break;
3521:
3522: case 0x84: /* test Ev, Gv */
3523: case 0x85:
3524: if ((b & 1) == 0)
3525: ot = OT_BYTE;
3526: else
3527: ot = dflag + OT_WORD;
3528:
3529: modrm = ldub_code(s->pc++);
3530: mod = (modrm >> 6) & 3;
3531: rm = (modrm & 7) | REX_B(s);
3532: reg = ((modrm >> 3) & 7) | rex_r;
3533:
3534: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3535: gen_op_mov_TN_reg[ot][1][reg]();
3536: gen_op_testl_T0_T1_cc();
3537: s->cc_op = CC_OP_LOGICB + ot;
3538: break;
3539:
3540: case 0xa8: /* test eAX, Iv */
3541: case 0xa9:
3542: if ((b & 1) == 0)
3543: ot = OT_BYTE;
3544: else
3545: ot = dflag + OT_WORD;
3546: val = insn_get(s, ot);
3547:
3548: gen_op_mov_TN_reg[ot][0][OR_EAX]();
3549: gen_op_movl_T1_im(val);
3550: gen_op_testl_T0_T1_cc();
3551: s->cc_op = CC_OP_LOGICB + ot;
3552: break;
3553:
3554: case 0x98: /* CWDE/CBW */
3555: #ifdef TARGET_X86_64
3556: if (dflag == 2) {
3557: gen_op_movslq_RAX_EAX();
3558: } else
3559: #endif
3560: if (dflag == 1)
3561: gen_op_movswl_EAX_AX();
3562: else
3563: gen_op_movsbw_AX_AL();
3564: break;
3565: case 0x99: /* CDQ/CWD */
3566: #ifdef TARGET_X86_64
3567: if (dflag == 2) {
3568: gen_op_movsqo_RDX_RAX();
3569: } else
3570: #endif
3571: if (dflag == 1)
3572: gen_op_movslq_EDX_EAX();
3573: else
3574: gen_op_movswl_DX_AX();
3575: break;
3576: case 0x1af: /* imul Gv, Ev */
3577: case 0x69: /* imul Gv, Ev, I */
3578: case 0x6b:
3579: ot = dflag + OT_WORD;
3580: modrm = ldub_code(s->pc++);
3581: reg = ((modrm >> 3) & 7) | rex_r;
3582: if (b == 0x69)
3583: s->rip_offset = insn_const_size(ot);
3584: else if (b == 0x6b)
3585: s->rip_offset = 1;
3586: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3587: if (b == 0x69) {
3588: val = insn_get(s, ot);
3589: gen_op_movl_T1_im(val);
3590: } else if (b == 0x6b) {
3591: val = (int8_t)insn_get(s, OT_BYTE);
3592: gen_op_movl_T1_im(val);
3593: } else {
3594: gen_op_mov_TN_reg[ot][1][reg]();
3595: }
3596:
3597: #ifdef TARGET_X86_64
3598: if (ot == OT_QUAD) {
3599: gen_op_imulq_T0_T1();
3600: } else
3601: #endif
3602: if (ot == OT_LONG) {
3603: gen_op_imull_T0_T1();
3604: } else {
3605: gen_op_imulw_T0_T1();
3606: }
3607: gen_op_mov_reg_T0[ot][reg]();
3608: s->cc_op = CC_OP_MULB + ot;
3609: break;
3610: case 0x1c0:
3611: case 0x1c1: /* xadd Ev, Gv */
3612: if ((b & 1) == 0)
3613: ot = OT_BYTE;
3614: else
3615: ot = dflag + OT_WORD;
3616: modrm = ldub_code(s->pc++);
3617: reg = ((modrm >> 3) & 7) | rex_r;
3618: mod = (modrm >> 6) & 3;
3619: if (mod == 3) {
3620: rm = (modrm & 7) | REX_B(s);
3621: gen_op_mov_TN_reg[ot][0][reg]();
3622: gen_op_mov_TN_reg[ot][1][rm]();
3623: gen_op_addl_T0_T1();
3624: gen_op_mov_reg_T1[ot][reg]();
3625: gen_op_mov_reg_T0[ot][rm]();
3626: } else {
3627: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3628: gen_op_mov_TN_reg[ot][0][reg]();
3629: gen_op_ld_T1_A0[ot + s->mem_index]();
3630: gen_op_addl_T0_T1();
3631: gen_op_st_T0_A0[ot + s->mem_index]();
3632: gen_op_mov_reg_T1[ot][reg]();
3633: }
3634: gen_op_update2_cc();
3635: s->cc_op = CC_OP_ADDB + ot;
3636: break;
3637: case 0x1b0:
3638: case 0x1b1: /* cmpxchg Ev, Gv */
3639: if ((b & 1) == 0)
3640: ot = OT_BYTE;
3641: else
3642: ot = dflag + OT_WORD;
3643: modrm = ldub_code(s->pc++);
3644: reg = ((modrm >> 3) & 7) | rex_r;
3645: mod = (modrm >> 6) & 3;
3646: gen_op_mov_TN_reg[ot][1][reg]();
3647: if (mod == 3) {
3648: rm = (modrm & 7) | REX_B(s);
3649: gen_op_mov_TN_reg[ot][0][rm]();
3650: gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
3651: gen_op_mov_reg_T0[ot][rm]();
3652: } else {
3653: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3654: gen_op_ld_T0_A0[ot + s->mem_index]();
3655: gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
3656: }
3657: s->cc_op = CC_OP_SUBB + ot;
3658: break;
3659: case 0x1c7: /* cmpxchg8b */
3660: modrm = ldub_code(s->pc++);
3661: mod = (modrm >> 6) & 3;
3662: if (mod == 3)
3663: goto illegal_op;
3664: if (s->cc_op != CC_OP_DYNAMIC)
3665: gen_op_set_cc_op(s->cc_op);
3666: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3667: gen_op_cmpxchg8b();
3668: s->cc_op = CC_OP_EFLAGS;
3669: break;
3670:
3671: /**************************/
3672: /* push/pop */
3673: case 0x50 ... 0x57: /* push */
3674: gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
3675: gen_push_T0(s);
3676: break;
3677: case 0x58 ... 0x5f: /* pop */
3678: if (CODE64(s)) {
3679: ot = dflag ? OT_QUAD : OT_WORD;
3680: } else {
3681: ot = dflag + OT_WORD;
3682: }
3683: gen_pop_T0(s);
3684: /* NOTE: order is important for pop %sp */
3685: gen_pop_update(s);
3686: gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)]();
3687: break;
3688: case 0x60: /* pusha */
3689: if (CODE64(s))
3690: goto illegal_op;
3691: gen_pusha(s);
3692: break;
3693: case 0x61: /* popa */
3694: if (CODE64(s))
3695: goto illegal_op;
3696: gen_popa(s);
3697: break;
3698: case 0x68: /* push Iv */
3699: case 0x6a:
3700: if (CODE64(s)) {
3701: ot = dflag ? OT_QUAD : OT_WORD;
3702: } else {
3703: ot = dflag + OT_WORD;
3704: }
3705: if (b == 0x68)
3706: val = insn_get(s, ot);
3707: else
3708: val = (int8_t)insn_get(s, OT_BYTE);
3709: gen_op_movl_T0_im(val);
3710: gen_push_T0(s);
3711: break;
3712: case 0x8f: /* pop Ev */
3713: if (CODE64(s)) {
3714: ot = dflag ? OT_QUAD : OT_WORD;
3715: } else {
3716: ot = dflag + OT_WORD;
3717: }
3718: modrm = ldub_code(s->pc++);
3719: mod = (modrm >> 6) & 3;
3720: gen_pop_T0(s);
3721: if (mod == 3) {
3722: /* NOTE: order is important for pop %sp */
3723: gen_pop_update(s);
3724: rm = (modrm & 7) | REX_B(s);
3725: gen_op_mov_reg_T0[ot][rm]();
3726: } else {
3727: /* NOTE: order is important too for MMU exceptions */
3728: s->popl_esp_hack = 1 << ot;
3729: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3730: s->popl_esp_hack = 0;
3731: gen_pop_update(s);
3732: }
3733: break;
3734: case 0xc8: /* enter */
3735: {
3736: int level;
3737: val = lduw_code(s->pc);
3738: s->pc += 2;
3739: level = ldub_code(s->pc++);
3740: gen_enter(s, val, level);
3741: }
3742: break;
3743: case 0xc9: /* leave */
3744: /* XXX: exception not precise (ESP is updated before potential exception) */
3745: if (CODE64(s)) {
3746: gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
3747: gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
3748: } else if (s->ss32) {
3749: gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
3750: gen_op_mov_reg_T0[OT_LONG][R_ESP]();
3751: } else {
3752: gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
3753: gen_op_mov_reg_T0[OT_WORD][R_ESP]();
3754: }
3755: gen_pop_T0(s);
3756: if (CODE64(s)) {
3757: ot = dflag ? OT_QUAD : OT_WORD;
3758: } else {
3759: ot = dflag + OT_WORD;
3760: }
3761: gen_op_mov_reg_T0[ot][R_EBP]();
3762: gen_pop_update(s);
3763: break;
3764: case 0x06: /* push es */
3765: case 0x0e: /* push cs */
3766: case 0x16: /* push ss */
3767: case 0x1e: /* push ds */
3768: if (CODE64(s))
3769: goto illegal_op;
3770: gen_op_movl_T0_seg(b >> 3);
3771: gen_push_T0(s);
3772: break;
3773: case 0x1a0: /* push fs */
3774: case 0x1a8: /* push gs */
3775: gen_op_movl_T0_seg((b >> 3) & 7);
3776: gen_push_T0(s);
3777: break;
3778: case 0x07: /* pop es */
3779: case 0x17: /* pop ss */
3780: case 0x1f: /* pop ds */
3781: if (CODE64(s))
3782: goto illegal_op;
3783: reg = b >> 3;
3784: gen_pop_T0(s);
3785: gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
3786: gen_pop_update(s);
3787: if (reg == R_SS) {
3788: /* if reg == SS, inhibit interrupts/trace. */
3789: /* If several instructions disable interrupts, only the
3790: _first_ does it */
3791: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3792: gen_op_set_inhibit_irq();
3793: s->tf = 0;
3794: }
3795: if (s->is_jmp) {
3796: gen_jmp_im(s->pc - s->cs_base);
3797: gen_eob(s);
3798: }
3799: break;
3800: case 0x1a1: /* pop fs */
3801: case 0x1a9: /* pop gs */
3802: gen_pop_T0(s);
3803: gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
3804: gen_pop_update(s);
3805: if (s->is_jmp) {
3806: gen_jmp_im(s->pc - s->cs_base);
3807: gen_eob(s);
3808: }
3809: break;
3810:
3811: /**************************/
3812: /* mov */
3813: case 0x88:
3814: case 0x89: /* mov Gv, Ev */
3815: if ((b & 1) == 0)
3816: ot = OT_BYTE;
3817: else
3818: ot = dflag + OT_WORD;
3819: modrm = ldub_code(s->pc++);
3820: reg = ((modrm >> 3) & 7) | rex_r;
3821:
3822: /* generate a generic store */
3823: gen_ldst_modrm(s, modrm, ot, reg, 1);
3824: break;
3825: case 0xc6:
3826: case 0xc7: /* mov Ev, Iv */
3827: if ((b & 1) == 0)
3828: ot = OT_BYTE;
3829: else
3830: ot = dflag + OT_WORD;
3831: modrm = ldub_code(s->pc++);
3832: mod = (modrm >> 6) & 3;
3833: if (mod != 3) {
3834: s->rip_offset = insn_const_size(ot);
3835: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3836: }
3837: val = insn_get(s, ot);
3838: gen_op_movl_T0_im(val);
3839: if (mod != 3)
3840: gen_op_st_T0_A0[ot + s->mem_index]();
3841: else
3842: gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)]();
3843: break;
3844: case 0x8a:
3845: case 0x8b: /* mov Ev, Gv */
3846: if ((b & 1) == 0)
3847: ot = OT_BYTE;
3848: else
3849: ot = OT_WORD + dflag;
3850: modrm = ldub_code(s->pc++);
3851: reg = ((modrm >> 3) & 7) | rex_r;
3852:
3853: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3854: gen_op_mov_reg_T0[ot][reg]();
3855: break;
3856: case 0x8e: /* mov seg, Gv */
3857: modrm = ldub_code(s->pc++);
3858: reg = (modrm >> 3) & 7;
3859: if (reg >= 6 || reg == R_CS)
3860: goto illegal_op;
3861: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3862: gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
3863: if (reg == R_SS) {
3864: /* if reg == SS, inhibit interrupts/trace */
3865: /* If several instructions disable interrupts, only the
3866: _first_ does it */
3867: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3868: gen_op_set_inhibit_irq();
3869: s->tf = 0;
3870: }
3871: if (s->is_jmp) {
3872: gen_jmp_im(s->pc - s->cs_base);
3873: gen_eob(s);
3874: }
3875: break;
3876: case 0x8c: /* mov Gv, seg */
3877: modrm = ldub_code(s->pc++);
3878: reg = (modrm >> 3) & 7;
3879: mod = (modrm >> 6) & 3;
3880: if (reg >= 6)
3881: goto illegal_op;
3882: gen_op_movl_T0_seg(reg);
3883: if (mod == 3)
3884: ot = OT_WORD + dflag;
3885: else
3886: ot = OT_WORD;
3887: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3888: break;
3889:
3890: case 0x1b6: /* movzbS Gv, Eb */
3891: case 0x1b7: /* movzwS Gv, Eb */
3892: case 0x1be: /* movsbS Gv, Eb */
3893: case 0x1bf: /* movswS Gv, Eb */
3894: {
3895: int d_ot;
3896: /* d_ot is the size of destination */
3897: d_ot = dflag + OT_WORD;
3898: /* ot is the size of source */
3899: ot = (b & 1) + OT_BYTE;
3900: modrm = ldub_code(s->pc++);
3901: reg = ((modrm >> 3) & 7) | rex_r;
3902: mod = (modrm >> 6) & 3;
3903: rm = (modrm & 7) | REX_B(s);
3904:
3905: if (mod == 3) {
3906: gen_op_mov_TN_reg[ot][0][rm]();
3907: switch(ot | (b & 8)) {
3908: case OT_BYTE:
3909: gen_op_movzbl_T0_T0();
3910: break;
3911: case OT_BYTE | 8:
3912: gen_op_movsbl_T0_T0();
3913: break;
3914: case OT_WORD:
3915: gen_op_movzwl_T0_T0();
3916: break;
3917: default:
3918: case OT_WORD | 8:
3919: gen_op_movswl_T0_T0();
3920: break;
3921: }
3922: gen_op_mov_reg_T0[d_ot][reg]();
3923: } else {
3924: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3925: if (b & 8) {
3926: gen_op_lds_T0_A0[ot + s->mem_index]();
3927: } else {
3928: gen_op_ldu_T0_A0[ot + s->mem_index]();
3929: }
3930: gen_op_mov_reg_T0[d_ot][reg]();
3931: }
3932: }
3933: break;
3934:
3935: case 0x8d: /* lea */
3936: ot = dflag + OT_WORD;
3937: modrm = ldub_code(s->pc++);
3938: mod = (modrm >> 6) & 3;
3939: if (mod == 3)
3940: goto illegal_op;
3941: reg = ((modrm >> 3) & 7) | rex_r;
3942: /* we must ensure that no segment is added */
3943: s->override = -1;
3944: val = s->addseg;
3945: s->addseg = 0;
3946: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3947: s->addseg = val;
3948: gen_op_mov_reg_A0[ot - OT_WORD][reg]();
3949: break;
3950:
3951: case 0xa0: /* mov EAX, Ov */
3952: case 0xa1:
3953: case 0xa2: /* mov Ov, EAX */
3954: case 0xa3:
3955: {
3956: target_ulong offset_addr;
3957:
3958: if ((b & 1) == 0)
3959: ot = OT_BYTE;
3960: else
3961: ot = dflag + OT_WORD;
3962: #ifdef TARGET_X86_64
3963: if (s->aflag == 2) {
3964: offset_addr = ldq_code(s->pc);
3965: s->pc += 8;
3966: if (offset_addr == (int32_t)offset_addr)
3967: gen_op_movq_A0_im(offset_addr);
3968: else
3969: gen_op_movq_A0_im64(offset_addr >> 32, offset_addr);
3970: } else
3971: #endif
3972: {
3973: if (s->aflag) {
3974: offset_addr = insn_get(s, OT_LONG);
3975: } else {
3976: offset_addr = insn_get(s, OT_WORD);
3977: }
3978: gen_op_movl_A0_im(offset_addr);
3979: }
3980: gen_add_A0_ds_seg(s);
3981: if ((b & 2) == 0) {
3982: gen_op_ld_T0_A0[ot + s->mem_index]();
3983: gen_op_mov_reg_T0[ot][R_EAX]();
3984: } else {
3985: gen_op_mov_TN_reg[ot][0][R_EAX]();
3986: gen_op_st_T0_A0[ot + s->mem_index]();
3987: }
3988: }
3989: break;
3990: case 0xd7: /* xlat */
3991: #ifdef TARGET_X86_64
3992: if (s->aflag == 2) {
3993: gen_op_movq_A0_reg[R_EBX]();
3994: gen_op_addq_A0_AL();
3995: } else
3996: #endif
3997: {
3998: gen_op_movl_A0_reg[R_EBX]();
3999: gen_op_addl_A0_AL();
4000: if (s->aflag == 0)
4001: gen_op_andl_A0_ffff();
4002: }
4003: gen_add_A0_ds_seg(s);
4004: gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
4005: gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
4006: break;
4007: case 0xb0 ... 0xb7: /* mov R, Ib */
4008: val = insn_get(s, OT_BYTE);
4009: gen_op_movl_T0_im(val);
4010: gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)]();
4011: break;
4012: case 0xb8 ... 0xbf: /* mov R, Iv */
4013: #ifdef TARGET_X86_64
4014: if (dflag == 2) {
4015: uint64_t tmp;
4016: /* 64 bit case */
4017: tmp = ldq_code(s->pc);
4018: s->pc += 8;
4019: reg = (b & 7) | REX_B(s);
4020: gen_movtl_T0_im(tmp);
4021: gen_op_mov_reg_T0[OT_QUAD][reg]();
4022: } else
4023: #endif
4024: {
4025: ot = dflag ? OT_LONG : OT_WORD;
4026: val = insn_get(s, ot);
4027: reg = (b & 7) | REX_B(s);
4028: gen_op_movl_T0_im(val);
4029: gen_op_mov_reg_T0[ot][reg]();
4030: }
4031: break;
4032:
4033: case 0x91 ... 0x97: /* xchg R, EAX */
4034: ot = dflag + OT_WORD;
4035: reg = (b & 7) | REX_B(s);
4036: rm = R_EAX;
4037: goto do_xchg_reg;
4038: case 0x86:
4039: case 0x87: /* xchg Ev, Gv */
4040: if ((b & 1) == 0)
4041: ot = OT_BYTE;
4042: else
4043: ot = dflag + OT_WORD;
4044: modrm = ldub_code(s->pc++);
4045: reg = ((modrm >> 3) & 7) | rex_r;
4046: mod = (modrm >> 6) & 3;
4047: if (mod == 3) {
4048: rm = (modrm & 7) | REX_B(s);
4049: do_xchg_reg:
4050: gen_op_mov_TN_reg[ot][0][reg]();
4051: gen_op_mov_TN_reg[ot][1][rm]();
4052: gen_op_mov_reg_T0[ot][rm]();
4053: gen_op_mov_reg_T1[ot][reg]();
4054: } else {
4055: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4056: gen_op_mov_TN_reg[ot][0][reg]();
4057: /* for xchg, lock is implicit */
4058: if (!(prefixes & PREFIX_LOCK))
4059: gen_op_lock();
4060: gen_op_ld_T1_A0[ot + s->mem_index]();
4061: gen_op_st_T0_A0[ot + s->mem_index]();
4062: if (!(prefixes & PREFIX_LOCK))
4063: gen_op_unlock();
4064: gen_op_mov_reg_T1[ot][reg]();
4065: }
4066: break;
4067: case 0xc4: /* les Gv */
4068: if (CODE64(s))
4069: goto illegal_op;
4070: op = R_ES;
4071: goto do_lxx;
4072: case 0xc5: /* lds Gv */
4073: if (CODE64(s))
4074: goto illegal_op;
4075: op = R_DS;
4076: goto do_lxx;
4077: case 0x1b2: /* lss Gv */
4078: op = R_SS;
4079: goto do_lxx;
4080: case 0x1b4: /* lfs Gv */
4081: op = R_FS;
4082: goto do_lxx;
4083: case 0x1b5: /* lgs Gv */
4084: op = R_GS;
4085: do_lxx:
4086: ot = dflag ? OT_LONG : OT_WORD;
4087: modrm = ldub_code(s->pc++);
4088: reg = ((modrm >> 3) & 7) | rex_r;
4089: mod = (modrm >> 6) & 3;
4090: if (mod == 3)
4091: goto illegal_op;
4092: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4093: gen_op_ld_T1_A0[ot + s->mem_index]();
4094: gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4095: /* load the segment first to handle exceptions properly */
4096: gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
4097: gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4098: /* then put the data */
4099: gen_op_mov_reg_T1[ot][reg]();
4100: if (s->is_jmp) {
4101: gen_jmp_im(s->pc - s->cs_base);
4102: gen_eob(s);
4103: }
4104: break;
4105:
4106: /************************/
4107: /* shifts */
4108: case 0xc0:
4109: case 0xc1:
4110: /* shift Ev,Ib */
4111: shift = 2;
4112: grp2:
4113: {
4114: if ((b & 1) == 0)
4115: ot = OT_BYTE;
4116: else
4117: ot = dflag + OT_WORD;
4118:
4119: modrm = ldub_code(s->pc++);
4120: mod = (modrm >> 6) & 3;
4121: op = (modrm >> 3) & 7;
4122:
4123: if (mod != 3) {
4124: if (shift == 2) {
4125: s->rip_offset = 1;
4126: }
4127: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4128: opreg = OR_TMP0;
4129: } else {
4130: opreg = (modrm & 7) | REX_B(s);
4131: }
4132:
4133: /* simpler op */
4134: if (shift == 0) {
4135: gen_shift(s, op, ot, opreg, OR_ECX);
4136: } else {
4137: if (shift == 2) {
4138: shift = ldub_code(s->pc++);
4139: }
4140: gen_shifti(s, op, ot, opreg, shift);
4141: }
4142: }
4143: break;
4144: case 0xd0:
4145: case 0xd1:
4146: /* shift Ev,1 */
4147: shift = 1;
4148: goto grp2;
4149: case 0xd2:
4150: case 0xd3:
4151: /* shift Ev,cl */
4152: shift = 0;
4153: goto grp2;
4154:
4155: case 0x1a4: /* shld imm */
4156: op = 0;
4157: shift = 1;
4158: goto do_shiftd;
4159: case 0x1a5: /* shld cl */
4160: op = 0;
4161: shift = 0;
4162: goto do_shiftd;
4163: case 0x1ac: /* shrd imm */
4164: op = 1;
4165: shift = 1;
4166: goto do_shiftd;
4167: case 0x1ad: /* shrd cl */
4168: op = 1;
4169: shift = 0;
4170: do_shiftd:
4171: ot = dflag + OT_WORD;
4172: modrm = ldub_code(s->pc++);
4173: mod = (modrm >> 6) & 3;
4174: rm = (modrm & 7) | REX_B(s);
4175: reg = ((modrm >> 3) & 7) | rex_r;
4176:
4177: if (mod != 3) {
4178: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4179: gen_op_ld_T0_A0[ot + s->mem_index]();
4180: } else {
4181: gen_op_mov_TN_reg[ot][0][rm]();
4182: }
4183: gen_op_mov_TN_reg[ot][1][reg]();
4184:
4185: if (shift) {
4186: val = ldub_code(s->pc++);
4187: if (ot == OT_QUAD)
4188: val &= 0x3f;
4189: else
4190: val &= 0x1f;
4191: if (val) {
4192: if (mod == 3)
4193: gen_op_shiftd_T0_T1_im_cc[ot][op](val);
4194: else
4195: gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
4196: if (op == 0 && ot != OT_WORD)
4197: s->cc_op = CC_OP_SHLB + ot;
4198: else
4199: s->cc_op = CC_OP_SARB + ot;
4200: }
4201: } else {
4202: if (s->cc_op != CC_OP_DYNAMIC)
4203: gen_op_set_cc_op(s->cc_op);
4204: if (mod == 3)
4205: gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
4206: else
4207: gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
4208: s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
4209: }
4210: if (mod == 3) {
4211: gen_op_mov_reg_T0[ot][rm]();
4212: }
4213: break;
4214:
4215: /************************/
4216: /* floats */
4217: case 0xd8 ... 0xdf:
4218: if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4219: /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4220: /* XXX: what to do if illegal op ? */
4221: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4222: break;
4223: }
4224: modrm = ldub_code(s->pc++);
4225: mod = (modrm >> 6) & 3;
4226: rm = modrm & 7;
4227: op = ((b & 7) << 3) | ((modrm >> 3) & 7);
4228: if (mod != 3) {
4229: /* memory op */
4230: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4231: switch(op) {
4232: case 0x00 ... 0x07: /* fxxxs */
4233: case 0x10 ... 0x17: /* fixxxl */
4234: case 0x20 ... 0x27: /* fxxxl */
4235: case 0x30 ... 0x37: /* fixxx */
4236: {
4237: int op1;
4238: op1 = op & 7;
4239:
4240: switch(op >> 4) {
4241: case 0:
4242: gen_op_flds_FT0_A0();
4243: break;
4244: case 1:
4245: gen_op_fildl_FT0_A0();
4246: break;
4247: case 2:
4248: gen_op_fldl_FT0_A0();
4249: break;
4250: case 3:
4251: default:
4252: gen_op_fild_FT0_A0();
4253: break;
4254: }
4255:
4256: gen_op_fp_arith_ST0_FT0[op1]();
4257: if (op1 == 3) {
4258: /* fcomp needs pop */
4259: gen_op_fpop();
4260: }
4261: }
4262: break;
4263: case 0x08: /* flds */
4264: case 0x0a: /* fsts */
4265: case 0x0b: /* fstps */
4266: case 0x18: /* fildl */
4267: case 0x1a: /* fistl */
4268: case 0x1b: /* fistpl */
4269: case 0x28: /* fldl */
4270: case 0x2a: /* fstl */
4271: case 0x2b: /* fstpl */
4272: case 0x38: /* filds */
4273: case 0x3a: /* fists */
4274: case 0x3b: /* fistps */
4275:
4276: switch(op & 7) {
4277: case 0:
4278: switch(op >> 4) {
4279: case 0:
4280: gen_op_flds_ST0_A0();
4281: break;
4282: case 1:
4283: gen_op_fildl_ST0_A0();
4284: break;
4285: case 2:
4286: gen_op_fldl_ST0_A0();
4287: break;
4288: case 3:
4289: default:
4290: gen_op_fild_ST0_A0();
4291: break;
4292: }
4293: break;
4294: default:
4295: switch(op >> 4) {
4296: case 0:
4297: gen_op_fsts_ST0_A0();
4298: break;
4299: case 1:
4300: gen_op_fistl_ST0_A0();
4301: break;
4302: case 2:
4303: gen_op_fstl_ST0_A0();
4304: break;
4305: case 3:
4306: default:
4307: gen_op_fist_ST0_A0();
4308: break;
4309: }
4310: if ((op & 7) == 3)
4311: gen_op_fpop();
4312: break;
4313: }
4314: break;
4315: case 0x0c: /* fldenv mem */
4316: gen_op_fldenv_A0(s->dflag);
4317: break;
4318: case 0x0d: /* fldcw mem */
4319: gen_op_fldcw_A0();
4320: break;
4321: case 0x0e: /* fnstenv mem */
4322: gen_op_fnstenv_A0(s->dflag);
4323: break;
4324: case 0x0f: /* fnstcw mem */
4325: gen_op_fnstcw_A0();
4326: break;
4327: case 0x1d: /* fldt mem */
4328: gen_op_fldt_ST0_A0();
4329: break;
4330: case 0x1f: /* fstpt mem */
4331: gen_op_fstt_ST0_A0();
4332: gen_op_fpop();
4333: break;
4334: case 0x2c: /* frstor mem */
4335: gen_op_frstor_A0(s->dflag);
4336: break;
4337: case 0x2e: /* fnsave mem */
4338: gen_op_fnsave_A0(s->dflag);
4339: break;
4340: case 0x2f: /* fnstsw mem */
4341: gen_op_fnstsw_A0();
4342: break;
4343: case 0x3c: /* fbld */
4344: gen_op_fbld_ST0_A0();
4345: break;
4346: case 0x3e: /* fbstp */
4347: gen_op_fbst_ST0_A0();
4348: gen_op_fpop();
4349: break;
4350: case 0x3d: /* fildll */
4351: gen_op_fildll_ST0_A0();
4352: break;
4353: case 0x3f: /* fistpll */
4354: gen_op_fistll_ST0_A0();
4355: gen_op_fpop();
4356: break;
4357: default:
4358: goto illegal_op;
4359: }
4360: } else {
4361: /* register float ops */
4362: opreg = rm;
4363:
4364: switch(op) {
4365: case 0x08: /* fld sti */
4366: gen_op_fpush();
4367: gen_op_fmov_ST0_STN((opreg + 1) & 7);
4368: break;
4369: case 0x09: /* fxchg sti */
4370: case 0x29: /* fxchg4 sti, undocumented op */
4371: case 0x39: /* fxchg7 sti, undocumented op */
4372: gen_op_fxchg_ST0_STN(opreg);
4373: break;
4374: case 0x0a: /* grp d9/2 */
4375: switch(rm) {
4376: case 0: /* fnop */
4377: /* check exceptions (FreeBSD FPU probe) */
4378: if (s->cc_op != CC_OP_DYNAMIC)
4379: gen_op_set_cc_op(s->cc_op);
4380: gen_jmp_im(pc_start - s->cs_base);
4381: gen_op_fwait();
4382: break;
4383: default:
4384: goto illegal_op;
4385: }
4386: break;
4387: case 0x0c: /* grp d9/4 */
4388: switch(rm) {
4389: case 0: /* fchs */
4390: gen_op_fchs_ST0();
4391: break;
4392: case 1: /* fabs */
4393: gen_op_fabs_ST0();
4394: break;
4395: case 4: /* ftst */
4396: gen_op_fldz_FT0();
4397: gen_op_fcom_ST0_FT0();
4398: break;
4399: case 5: /* fxam */
4400: gen_op_fxam_ST0();
4401: break;
4402: default:
4403: goto illegal_op;
4404: }
4405: break;
4406: case 0x0d: /* grp d9/5 */
4407: {
4408: switch(rm) {
4409: case 0:
4410: gen_op_fpush();
4411: gen_op_fld1_ST0();
4412: break;
4413: case 1:
4414: gen_op_fpush();
4415: gen_op_fldl2t_ST0();
4416: break;
4417: case 2:
4418: gen_op_fpush();
4419: gen_op_fldl2e_ST0();
4420: break;
4421: case 3:
4422: gen_op_fpush();
4423: gen_op_fldpi_ST0();
4424: break;
4425: case 4:
4426: gen_op_fpush();
4427: gen_op_fldlg2_ST0();
4428: break;
4429: case 5:
4430: gen_op_fpush();
4431: gen_op_fldln2_ST0();
4432: break;
4433: case 6:
4434: gen_op_fpush();
4435: gen_op_fldz_ST0();
4436: break;
4437: default:
4438: goto illegal_op;
4439: }
4440: }
4441: break;
4442: case 0x0e: /* grp d9/6 */
4443: switch(rm) {
4444: case 0: /* f2xm1 */
4445: gen_op_f2xm1();
4446: break;
4447: case 1: /* fyl2x */
4448: gen_op_fyl2x();
4449: break;
4450: case 2: /* fptan */
4451: gen_op_fptan();
4452: break;
4453: case 3: /* fpatan */
4454: gen_op_fpatan();
4455: break;
4456: case 4: /* fxtract */
4457: gen_op_fxtract();
4458: break;
4459: case 5: /* fprem1 */
4460: gen_op_fprem1();
4461: break;
4462: case 6: /* fdecstp */
4463: gen_op_fdecstp();
4464: break;
4465: default:
4466: case 7: /* fincstp */
4467: gen_op_fincstp();
4468: break;
4469: }
4470: break;
4471: case 0x0f: /* grp d9/7 */
4472: switch(rm) {
4473: case 0: /* fprem */
4474: gen_op_fprem();
4475: break;
4476: case 1: /* fyl2xp1 */
4477: gen_op_fyl2xp1();
4478: break;
4479: case 2: /* fsqrt */
4480: gen_op_fsqrt();
4481: break;
4482: case 3: /* fsincos */
4483: gen_op_fsincos();
4484: break;
4485: case 5: /* fscale */
4486: gen_op_fscale();
4487: break;
4488: case 4: /* frndint */
4489: gen_op_frndint();
4490: break;
4491: case 6: /* fsin */
4492: gen_op_fsin();
4493: break;
4494: default:
4495: case 7: /* fcos */
4496: gen_op_fcos();
4497: break;
4498: }
4499: break;
4500: case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4501: case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4502: case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4503: {
4504: int op1;
4505:
4506: op1 = op & 7;
4507: if (op >= 0x20) {
4508: gen_op_fp_arith_STN_ST0[op1](opreg);
4509: if (op >= 0x30)
4510: gen_op_fpop();
4511: } else {
4512: gen_op_fmov_FT0_STN(opreg);
4513: gen_op_fp_arith_ST0_FT0[op1]();
4514: }
4515: }
4516: break;
4517: case 0x02: /* fcom */
4518: case 0x22: /* fcom2, undocumented op */
4519: gen_op_fmov_FT0_STN(opreg);
4520: gen_op_fcom_ST0_FT0();
4521: break;
4522: case 0x03: /* fcomp */
4523: case 0x23: /* fcomp3, undocumented op */
4524: case 0x32: /* fcomp5, undocumented op */
4525: gen_op_fmov_FT0_STN(opreg);
4526: gen_op_fcom_ST0_FT0();
4527: gen_op_fpop();
4528: break;
4529: case 0x15: /* da/5 */
4530: switch(rm) {
4531: case 1: /* fucompp */
4532: gen_op_fmov_FT0_STN(1);
4533: gen_op_fucom_ST0_FT0();
4534: gen_op_fpop();
4535: gen_op_fpop();
4536: break;
4537: default:
4538: goto illegal_op;
4539: }
4540: break;
4541: case 0x1c:
4542: switch(rm) {
4543: case 0: /* feni (287 only, just do nop here) */
4544: break;
4545: case 1: /* fdisi (287 only, just do nop here) */
4546: break;
4547: case 2: /* fclex */
4548: gen_op_fclex();
4549: break;
4550: case 3: /* fninit */
4551: gen_op_fninit();
4552: break;
4553: case 4: /* fsetpm (287 only, just do nop here) */
4554: break;
4555: default:
4556: goto illegal_op;
4557: }
4558: break;
4559: case 0x1d: /* fucomi */
4560: if (s->cc_op != CC_OP_DYNAMIC)
4561: gen_op_set_cc_op(s->cc_op);
4562: gen_op_fmov_FT0_STN(opreg);
4563: gen_op_fucomi_ST0_FT0();
4564: s->cc_op = CC_OP_EFLAGS;
4565: break;
4566: case 0x1e: /* fcomi */
4567: if (s->cc_op != CC_OP_DYNAMIC)
4568: gen_op_set_cc_op(s->cc_op);
4569: gen_op_fmov_FT0_STN(opreg);
4570: gen_op_fcomi_ST0_FT0();
4571: s->cc_op = CC_OP_EFLAGS;
4572: break;
4573: case 0x28: /* ffree sti */
4574: gen_op_ffree_STN(opreg);
4575: break;
4576: case 0x2a: /* fst sti */
4577: gen_op_fmov_STN_ST0(opreg);
4578: break;
4579: case 0x2b: /* fstp sti */
4580: case 0x0b: /* fstp1 sti, undocumented op */
4581: case 0x3a: /* fstp8 sti, undocumented op */
4582: case 0x3b: /* fstp9 sti, undocumented op */
4583: gen_op_fmov_STN_ST0(opreg);
4584: gen_op_fpop();
4585: break;
4586: case 0x2c: /* fucom st(i) */
4587: gen_op_fmov_FT0_STN(opreg);
4588: gen_op_fucom_ST0_FT0();
4589: break;
4590: case 0x2d: /* fucomp st(i) */
4591: gen_op_fmov_FT0_STN(opreg);
4592: gen_op_fucom_ST0_FT0();
4593: gen_op_fpop();
4594: break;
4595: case 0x33: /* de/3 */
4596: switch(rm) {
4597: case 1: /* fcompp */
4598: gen_op_fmov_FT0_STN(1);
4599: gen_op_fcom_ST0_FT0();
4600: gen_op_fpop();
4601: gen_op_fpop();
4602: break;
4603: default:
4604: goto illegal_op;
4605: }
4606: break;
4607: case 0x38: /* ffreep sti, undocumented op */
4608: gen_op_ffree_STN(opreg);
4609: gen_op_fpop();
4610: break;
4611: case 0x3c: /* df/4 */
4612: switch(rm) {
4613: case 0:
4614: gen_op_fnstsw_EAX();
4615: break;
4616: default:
4617: goto illegal_op;
4618: }
4619: break;
4620: case 0x3d: /* fucomip */
4621: if (s->cc_op != CC_OP_DYNAMIC)
4622: gen_op_set_cc_op(s->cc_op);
4623: gen_op_fmov_FT0_STN(opreg);
4624: gen_op_fucomi_ST0_FT0();
4625: gen_op_fpop();
4626: s->cc_op = CC_OP_EFLAGS;
4627: break;
4628: case 0x3e: /* fcomip */
4629: if (s->cc_op != CC_OP_DYNAMIC)
4630: gen_op_set_cc_op(s->cc_op);
4631: gen_op_fmov_FT0_STN(opreg);
4632: gen_op_fcomi_ST0_FT0();
4633: gen_op_fpop();
4634: s->cc_op = CC_OP_EFLAGS;
4635: break;
4636: case 0x10 ... 0x13: /* fcmovxx */
4637: case 0x18 ... 0x1b:
4638: {
4639: int op1;
4640: const static uint8_t fcmov_cc[8] = {
4641: (JCC_B << 1),
4642: (JCC_Z << 1),
4643: (JCC_BE << 1),
4644: (JCC_P << 1),
4645: };
4646: op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
4647: gen_setcc(s, op1);
4648: gen_op_fcmov_ST0_STN_T0(opreg);
4649: }
4650: break;
4651: default:
4652: goto illegal_op;
4653: }
4654: }
4655: #ifdef USE_CODE_COPY
4656: s->tb->cflags |= CF_TB_FP_USED;
4657: #endif
4658: break;
4659: /************************/
4660: /* string ops */
4661:
4662: case 0xa4: /* movsS */
4663: case 0xa5:
4664: if ((b & 1) == 0)
4665: ot = OT_BYTE;
4666: else
4667: ot = dflag + OT_WORD;
4668:
4669: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4670: gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4671: } else {
4672: gen_movs(s, ot);
4673: }
4674: break;
4675:
4676: case 0xaa: /* stosS */
4677: case 0xab:
4678: if ((b & 1) == 0)
4679: ot = OT_BYTE;
4680: else
4681: ot = dflag + OT_WORD;
4682:
4683: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4684: gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4685: } else {
4686: gen_stos(s, ot);
4687: }
4688: break;
4689: case 0xac: /* lodsS */
4690: case 0xad:
4691: if ((b & 1) == 0)
4692: ot = OT_BYTE;
4693: else
4694: ot = dflag + OT_WORD;
4695: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4696: gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4697: } else {
4698: gen_lods(s, ot);
4699: }
4700: break;
4701: case 0xae: /* scasS */
4702: case 0xaf:
4703: if ((b & 1) == 0)
4704: ot = OT_BYTE;
4705: else
4706: ot = dflag + OT_WORD;
4707: if (prefixes & PREFIX_REPNZ) {
4708: gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4709: } else if (prefixes & PREFIX_REPZ) {
4710: gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4711: } else {
4712: gen_scas(s, ot);
4713: s->cc_op = CC_OP_SUBB + ot;
4714: }
4715: break;
4716:
4717: case 0xa6: /* cmpsS */
4718: case 0xa7:
4719: if ((b & 1) == 0)
4720: ot = OT_BYTE;
4721: else
4722: ot = dflag + OT_WORD;
4723: if (prefixes & PREFIX_REPNZ) {
4724: gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4725: } else if (prefixes & PREFIX_REPZ) {
4726: gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4727: } else {
4728: gen_cmps(s, ot);
4729: s->cc_op = CC_OP_SUBB + ot;
4730: }
4731: break;
4732: case 0x6c: /* insS */
4733: case 0x6d:
4734: if ((b & 1) == 0)
4735: ot = OT_BYTE;
4736: else
4737: ot = dflag ? OT_LONG : OT_WORD;
4738: gen_check_io(s, ot, 1, pc_start - s->cs_base);
4739: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4740: gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4741: } else {
4742: gen_ins(s, ot);
4743: }
4744: break;
4745: case 0x6e: /* outsS */
4746: case 0x6f:
4747: if ((b & 1) == 0)
4748: ot = OT_BYTE;
4749: else
4750: ot = dflag ? OT_LONG : OT_WORD;
4751: gen_check_io(s, ot, 1, pc_start - s->cs_base);
4752: if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4753: gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4754: } else {
4755: gen_outs(s, ot);
4756: }
4757: break;
4758:
4759: /************************/
4760: /* port I/O */
4761: case 0xe4:
4762: case 0xe5:
4763: if ((b & 1) == 0)
4764: ot = OT_BYTE;
4765: else
4766: ot = dflag ? OT_LONG : OT_WORD;
4767: val = ldub_code(s->pc++);
4768: gen_op_movl_T0_im(val);
4769: gen_check_io(s, ot, 0, pc_start - s->cs_base);
4770: gen_op_in[ot]();
4771: gen_op_mov_reg_T1[ot][R_EAX]();
4772: break;
4773: case 0xe6:
4774: case 0xe7:
4775: if ((b & 1) == 0)
4776: ot = OT_BYTE;
4777: else
4778: ot = dflag ? OT_LONG : OT_WORD;
4779: val = ldub_code(s->pc++);
4780: gen_op_movl_T0_im(val);
4781: gen_check_io(s, ot, 0, pc_start - s->cs_base);
4782: gen_op_mov_TN_reg[ot][1][R_EAX]();
4783: gen_op_out[ot]();
4784: break;
4785: case 0xec:
4786: case 0xed:
4787: if ((b & 1) == 0)
4788: ot = OT_BYTE;
4789: else
4790: ot = dflag ? OT_LONG : OT_WORD;
4791: gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4792: gen_op_andl_T0_ffff();
4793: gen_check_io(s, ot, 0, pc_start - s->cs_base);
4794: gen_op_in[ot]();
4795: gen_op_mov_reg_T1[ot][R_EAX]();
4796: break;
4797: case 0xee:
4798: case 0xef:
4799: if ((b & 1) == 0)
4800: ot = OT_BYTE;
4801: else
4802: ot = dflag ? OT_LONG : OT_WORD;
4803: gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4804: gen_op_andl_T0_ffff();
4805: gen_check_io(s, ot, 0, pc_start - s->cs_base);
4806: gen_op_mov_TN_reg[ot][1][R_EAX]();
4807: gen_op_out[ot]();
4808: break;
4809:
4810: /************************/
4811: /* control */
4812: case 0xc2: /* ret im */
4813: val = ldsw_code(s->pc);
4814: s->pc += 2;
4815: gen_pop_T0(s);
4816: if (CODE64(s) && s->dflag)
4817: s->dflag = 2;
4818: gen_stack_update(s, val + (2 << s->dflag));
4819: if (s->dflag == 0)
4820: gen_op_andl_T0_ffff();
4821: gen_op_jmp_T0();
4822: gen_eob(s);
4823: break;
4824: case 0xc3: /* ret */
4825: gen_pop_T0(s);
4826: gen_pop_update(s);
4827: if (s->dflag == 0)
4828: gen_op_andl_T0_ffff();
4829: gen_op_jmp_T0();
4830: gen_eob(s);
4831: break;
4832: case 0xca: /* lret im */
4833: val = ldsw_code(s->pc);
4834: s->pc += 2;
4835: do_lret:
4836: if (s->pe && !s->vm86) {
4837: if (s->cc_op != CC_OP_DYNAMIC)
4838: gen_op_set_cc_op(s->cc_op);
4839: gen_jmp_im(pc_start - s->cs_base);
4840: gen_op_lret_protected(s->dflag, val);
4841: } else {
4842: gen_stack_A0(s);
4843: /* pop offset */
4844: gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
4845: if (s->dflag == 0)
4846: gen_op_andl_T0_ffff();
4847: /* NOTE: keeping EIP updated is not a problem in case of
4848: exception */
4849: gen_op_jmp_T0();
4850: /* pop selector */
4851: gen_op_addl_A0_im(2 << s->dflag);
4852: gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
4853: gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
4854: /* add stack offset */
4855: gen_stack_update(s, val + (4 << s->dflag));
4856: }
4857: gen_eob(s);
4858: break;
4859: case 0xcb: /* lret */
4860: val = 0;
4861: goto do_lret;
4862: case 0xcf: /* iret */
4863: if (!s->pe) {
4864: /* real mode */
4865: gen_op_iret_real(s->dflag);
4866: s->cc_op = CC_OP_EFLAGS;
4867: } else if (s->vm86) {
4868: if (s->iopl != 3) {
4869: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4870: } else {
4871: gen_op_iret_real(s->dflag);
4872: s->cc_op = CC_OP_EFLAGS;
4873: }
4874: } else {
4875: if (s->cc_op != CC_OP_DYNAMIC)
4876: gen_op_set_cc_op(s->cc_op);
4877: gen_jmp_im(pc_start - s->cs_base);
4878: gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
4879: s->cc_op = CC_OP_EFLAGS;
4880: }
4881: gen_eob(s);
4882: break;
4883: case 0xe8: /* call im */
4884: {
4885: if (dflag)
4886: tval = (int32_t)insn_get(s, OT_LONG);
4887: else
4888: tval = (int16_t)insn_get(s, OT_WORD);
4889: next_eip = s->pc - s->cs_base;
4890: tval += next_eip;
4891: if (s->dflag == 0)
4892: tval &= 0xffff;
4893: gen_movtl_T0_im(next_eip);
4894: gen_push_T0(s);
4895: gen_jmp(s, tval);
4896: }
4897: break;
4898: case 0x9a: /* lcall im */
4899: {
4900: unsigned int selector, offset;
4901:
4902: if (CODE64(s))
4903: goto illegal_op;
4904: ot = dflag ? OT_LONG : OT_WORD;
4905: offset = insn_get(s, ot);
4906: selector = insn_get(s, OT_WORD);
4907:
4908: gen_op_movl_T0_im(selector);
4909: gen_op_movl_T1_imu(offset);
4910: }
4911: goto do_lcall;
4912: case 0xe9: /* jmp im */
4913: if (dflag)
4914: tval = (int32_t)insn_get(s, OT_LONG);
4915: else
4916: tval = (int16_t)insn_get(s, OT_WORD);
4917: tval += s->pc - s->cs_base;
4918: if (s->dflag == 0)
4919: tval &= 0xffff;
4920: gen_jmp(s, tval);
4921: break;
4922: case 0xea: /* ljmp im */
4923: {
4924: unsigned int selector, offset;
4925:
4926: if (CODE64(s))
4927: goto illegal_op;
4928: ot = dflag ? OT_LONG : OT_WORD;
4929: offset = insn_get(s, ot);
4930: selector = insn_get(s, OT_WORD);
4931:
4932: gen_op_movl_T0_im(selector);
4933: gen_op_movl_T1_imu(offset);
4934: }
4935: goto do_ljmp;
4936: case 0xeb: /* jmp Jb */
4937: tval = (int8_t)insn_get(s, OT_BYTE);
4938: tval += s->pc - s->cs_base;
4939: if (s->dflag == 0)
4940: tval &= 0xffff;
4941: gen_jmp(s, tval);
4942: break;
4943: case 0x70 ... 0x7f: /* jcc Jb */
4944: tval = (int8_t)insn_get(s, OT_BYTE);
4945: goto do_jcc;
4946: case 0x180 ... 0x18f: /* jcc Jv */
4947: if (dflag) {
4948: tval = (int32_t)insn_get(s, OT_LONG);
4949: } else {
4950: tval = (int16_t)insn_get(s, OT_WORD);
4951: }
4952: do_jcc:
4953: next_eip = s->pc - s->cs_base;
4954: tval += next_eip;
4955: if (s->dflag == 0)
4956: tval &= 0xffff;
4957: gen_jcc(s, b, tval, next_eip);
4958: break;
4959:
4960: case 0x190 ... 0x19f: /* setcc Gv */
4961: modrm = ldub_code(s->pc++);
4962: gen_setcc(s, b);
4963: gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
4964: break;
4965: case 0x140 ... 0x14f: /* cmov Gv, Ev */
4966: ot = dflag + OT_WORD;
4967: modrm = ldub_code(s->pc++);
4968: reg = ((modrm >> 3) & 7) | rex_r;
4969: mod = (modrm >> 6) & 3;
4970: gen_setcc(s, b);
4971: if (mod != 3) {
4972: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
4973: gen_op_ld_T1_A0[ot + s->mem_index]();
4974: } else {
4975: rm = (modrm & 7) | REX_B(s);
4976: gen_op_mov_TN_reg[ot][1][rm]();
4977: }
4978: gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
4979: break;
4980:
4981: /************************/
4982: /* flags */
4983: case 0x9c: /* pushf */
4984: if (s->vm86 && s->iopl != 3) {
4985: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4986: } else {
4987: if (s->cc_op != CC_OP_DYNAMIC)
4988: gen_op_set_cc_op(s->cc_op);
4989: gen_op_movl_T0_eflags();
4990: gen_push_T0(s);
4991: }
4992: break;
4993: case 0x9d: /* popf */
4994: if (s->vm86 && s->iopl != 3) {
4995: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4996: } else {
4997: gen_pop_T0(s);
4998: if (s->cpl == 0) {
4999: if (s->dflag) {
5000: gen_op_movl_eflags_T0_cpl0();
5001: } else {
5002: gen_op_movw_eflags_T0_cpl0();
5003: }
5004: } else {
5005: if (s->cpl <= s->iopl) {
5006: if (s->dflag) {
5007: gen_op_movl_eflags_T0_io();
5008: } else {
5009: gen_op_movw_eflags_T0_io();
5010: }
5011: } else {
5012: if (s->dflag) {
5013: gen_op_movl_eflags_T0();
5014: } else {
5015: gen_op_movw_eflags_T0();
5016: }
5017: }
5018: }
5019: gen_pop_update(s);
5020: s->cc_op = CC_OP_EFLAGS;
5021: /* abort translation because TF flag may change */
5022: gen_jmp_im(s->pc - s->cs_base);
5023: gen_eob(s);
5024: }
5025: break;
5026: case 0x9e: /* sahf */
5027: if (CODE64(s))
5028: goto illegal_op;
5029: gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
5030: if (s->cc_op != CC_OP_DYNAMIC)
5031: gen_op_set_cc_op(s->cc_op);
5032: gen_op_movb_eflags_T0();
5033: s->cc_op = CC_OP_EFLAGS;
5034: break;
5035: case 0x9f: /* lahf */
5036: if (CODE64(s))
5037: goto illegal_op;
5038: if (s->cc_op != CC_OP_DYNAMIC)
5039: gen_op_set_cc_op(s->cc_op);
5040: gen_op_movl_T0_eflags();
5041: gen_op_mov_reg_T0[OT_BYTE][R_AH]();
5042: break;
5043: case 0xf5: /* cmc */
5044: if (s->cc_op != CC_OP_DYNAMIC)
5045: gen_op_set_cc_op(s->cc_op);
5046: gen_op_cmc();
5047: s->cc_op = CC_OP_EFLAGS;
5048: break;
5049: case 0xf8: /* clc */
5050: if (s->cc_op != CC_OP_DYNAMIC)
5051: gen_op_set_cc_op(s->cc_op);
5052: gen_op_clc();
5053: s->cc_op = CC_OP_EFLAGS;
5054: break;
5055: case 0xf9: /* stc */
5056: if (s->cc_op != CC_OP_DYNAMIC)
5057: gen_op_set_cc_op(s->cc_op);
5058: gen_op_stc();
5059: s->cc_op = CC_OP_EFLAGS;
5060: break;
5061: case 0xfc: /* cld */
5062: gen_op_cld();
5063: break;
5064: case 0xfd: /* std */
5065: gen_op_std();
5066: break;
5067:
5068: /************************/
5069: /* bit operations */
5070: case 0x1ba: /* bt/bts/btr/btc Gv, im */
5071: ot = dflag + OT_WORD;
5072: modrm = ldub_code(s->pc++);
5073: op = ((modrm >> 3) & 7) | rex_r;
5074: mod = (modrm >> 6) & 3;
5075: rm = (modrm & 7) | REX_B(s);
5076: if (mod != 3) {
5077: s->rip_offset = 1;
5078: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5079: gen_op_ld_T0_A0[ot + s->mem_index]();
5080: } else {
5081: gen_op_mov_TN_reg[ot][0][rm]();
5082: }
5083: /* load shift */
5084: val = ldub_code(s->pc++);
5085: gen_op_movl_T1_im(val);
5086: if (op < 4)
5087: goto illegal_op;
5088: op -= 4;
5089: gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5090: s->cc_op = CC_OP_SARB + ot;
5091: if (op != 0) {
5092: if (mod != 3)
5093: gen_op_st_T0_A0[ot + s->mem_index]();
5094: else
5095: gen_op_mov_reg_T0[ot][rm]();
5096: gen_op_update_bt_cc();
5097: }
5098: break;
5099: case 0x1a3: /* bt Gv, Ev */
5100: op = 0;
5101: goto do_btx;
5102: case 0x1ab: /* bts */
5103: op = 1;
5104: goto do_btx;
5105: case 0x1b3: /* btr */
5106: op = 2;
5107: goto do_btx;
5108: case 0x1bb: /* btc */
5109: op = 3;
5110: do_btx:
5111: ot = dflag + OT_WORD;
5112: modrm = ldub_code(s->pc++);
5113: reg = ((modrm >> 3) & 7) | rex_r;
5114: mod = (modrm >> 6) & 3;
5115: rm = (modrm & 7) | REX_B(s);
5116: gen_op_mov_TN_reg[OT_LONG][1][reg]();
5117: if (mod != 3) {
5118: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5119: /* specific case: we need to add a displacement */
5120: gen_op_add_bit_A0_T1[ot - OT_WORD]();
5121: gen_op_ld_T0_A0[ot + s->mem_index]();
5122: } else {
5123: gen_op_mov_TN_reg[ot][0][rm]();
5124: }
5125: gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5126: s->cc_op = CC_OP_SARB + ot;
5127: if (op != 0) {
5128: if (mod != 3)
5129: gen_op_st_T0_A0[ot + s->mem_index]();
5130: else
5131: gen_op_mov_reg_T0[ot][rm]();
5132: gen_op_update_bt_cc();
5133: }
5134: break;
5135: case 0x1bc: /* bsf */
5136: case 0x1bd: /* bsr */
5137: ot = dflag + OT_WORD;
5138: modrm = ldub_code(s->pc++);
5139: reg = ((modrm >> 3) & 7) | rex_r;
5140: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5141: /* NOTE: in order to handle the 0 case, we must load the
5142: result. It could be optimized with a generated jump */
5143: gen_op_mov_TN_reg[ot][1][reg]();
5144: gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
5145: gen_op_mov_reg_T1[ot][reg]();
5146: s->cc_op = CC_OP_LOGICB + ot;
5147: break;
5148: /************************/
5149: /* bcd */
5150: case 0x27: /* daa */
5151: if (CODE64(s))
5152: goto illegal_op;
5153: if (s->cc_op != CC_OP_DYNAMIC)
5154: gen_op_set_cc_op(s->cc_op);
5155: gen_op_daa();
5156: s->cc_op = CC_OP_EFLAGS;
5157: break;
5158: case 0x2f: /* das */
5159: if (CODE64(s))
5160: goto illegal_op;
5161: if (s->cc_op != CC_OP_DYNAMIC)
5162: gen_op_set_cc_op(s->cc_op);
5163: gen_op_das();
5164: s->cc_op = CC_OP_EFLAGS;
5165: break;
5166: case 0x37: /* aaa */
5167: if (CODE64(s))
5168: goto illegal_op;
5169: if (s->cc_op != CC_OP_DYNAMIC)
5170: gen_op_set_cc_op(s->cc_op);
5171: gen_op_aaa();
5172: s->cc_op = CC_OP_EFLAGS;
5173: break;
5174: case 0x3f: /* aas */
5175: if (CODE64(s))
5176: goto illegal_op;
5177: if (s->cc_op != CC_OP_DYNAMIC)
5178: gen_op_set_cc_op(s->cc_op);
5179: gen_op_aas();
5180: s->cc_op = CC_OP_EFLAGS;
5181: break;
5182: case 0xd4: /* aam */
5183: if (CODE64(s))
5184: goto illegal_op;
5185: val = ldub_code(s->pc++);
5186: gen_op_aam(val);
5187: s->cc_op = CC_OP_LOGICB;
5188: break;
5189: case 0xd5: /* aad */
5190: if (CODE64(s))
5191: goto illegal_op;
5192: val = ldub_code(s->pc++);
5193: gen_op_aad(val);
5194: s->cc_op = CC_OP_LOGICB;
5195: break;
5196: /************************/
5197: /* misc */
5198: case 0x90: /* nop */
5199: /* XXX: xchg + rex handling */
5200: /* XXX: correct lock test for all insn */
5201: if (prefixes & PREFIX_LOCK)
5202: goto illegal_op;
5203: break;
5204: case 0x9b: /* fwait */
5205: if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
5206: (HF_MP_MASK | HF_TS_MASK)) {
5207: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5208: } else {
5209: if (s->cc_op != CC_OP_DYNAMIC)
5210: gen_op_set_cc_op(s->cc_op);
5211: gen_jmp_im(pc_start - s->cs_base);
5212: gen_op_fwait();
5213: }
5214: break;
5215: case 0xcc: /* int3 */
5216: gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5217: break;
5218: case 0xcd: /* int N */
5219: val = ldub_code(s->pc++);
5220: if (s->vm86 && s->iopl != 3) {
5221: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5222: } else {
5223: gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5224: }
5225: break;
5226: case 0xce: /* into */
5227: if (CODE64(s))
5228: goto illegal_op;
5229: if (s->cc_op != CC_OP_DYNAMIC)
5230: gen_op_set_cc_op(s->cc_op);
5231: gen_jmp_im(pc_start - s->cs_base);
5232: gen_op_into(s->pc - pc_start);
5233: break;
5234: case 0xf1: /* icebp (undocumented, exits to external debugger) */
5235: #if 1
5236: gen_debug(s, pc_start - s->cs_base);
5237: #else
5238: /* start debug */
5239: tb_flush(cpu_single_env);
5240: cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5241: #endif
5242: break;
5243: case 0xfa: /* cli */
5244: if (!s->vm86) {
5245: if (s->cpl <= s->iopl) {
5246: gen_op_cli();
5247: } else {
5248: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5249: }
5250: } else {
5251: if (s->iopl == 3) {
5252: gen_op_cli();
5253: } else {
5254: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5255: }
5256: }
5257: break;
5258: case 0xfb: /* sti */
5259: if (!s->vm86) {
5260: if (s->cpl <= s->iopl) {
5261: gen_sti:
5262: gen_op_sti();
5263: /* interruptions are enabled only the first insn after sti */
5264: /* If several instructions disable interrupts, only the
5265: _first_ does it */
5266: if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5267: gen_op_set_inhibit_irq();
5268: /* give a chance to handle pending irqs */
5269: gen_jmp_im(s->pc - s->cs_base);
5270: gen_eob(s);
5271: } else {
5272: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5273: }
5274: } else {
5275: if (s->iopl == 3) {
5276: goto gen_sti;
5277: } else {
5278: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5279: }
5280: }
5281: break;
5282: case 0x62: /* bound */
5283: if (CODE64(s))
5284: goto illegal_op;
5285: ot = dflag ? OT_LONG : OT_WORD;
5286: modrm = ldub_code(s->pc++);
5287: reg = (modrm >> 3) & 7;
5288: mod = (modrm >> 6) & 3;
5289: if (mod == 3)
5290: goto illegal_op;
5291: gen_op_mov_TN_reg[ot][0][reg]();
5292: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5293: gen_jmp_im(pc_start - s->cs_base);
5294: if (ot == OT_WORD)
5295: gen_op_boundw();
5296: else
5297: gen_op_boundl();
5298: break;
5299: case 0x1c8 ... 0x1cf: /* bswap reg */
5300: reg = (b & 7) | REX_B(s);
5301: #ifdef TARGET_X86_64
5302: if (dflag == 2) {
5303: gen_op_mov_TN_reg[OT_QUAD][0][reg]();
5304: gen_op_bswapq_T0();
5305: gen_op_mov_reg_T0[OT_QUAD][reg]();
5306: } else
5307: #endif
5308: {
5309: gen_op_mov_TN_reg[OT_LONG][0][reg]();
5310: gen_op_bswapl_T0();
5311: gen_op_mov_reg_T0[OT_LONG][reg]();
5312: }
5313: break;
5314: case 0xd6: /* salc */
5315: if (CODE64(s))
5316: goto illegal_op;
5317: if (s->cc_op != CC_OP_DYNAMIC)
5318: gen_op_set_cc_op(s->cc_op);
5319: gen_op_salc();
5320: break;
5321: case 0xe0: /* loopnz */
5322: case 0xe1: /* loopz */
5323: if (s->cc_op != CC_OP_DYNAMIC)
5324: gen_op_set_cc_op(s->cc_op);
5325: /* FALL THRU */
5326: case 0xe2: /* loop */
5327: case 0xe3: /* jecxz */
5328: {
5329: int l1, l2;
5330:
5331: tval = (int8_t)insn_get(s, OT_BYTE);
5332: next_eip = s->pc - s->cs_base;
5333: tval += next_eip;
5334: if (s->dflag == 0)
5335: tval &= 0xffff;
5336:
5337: l1 = gen_new_label();
5338: l2 = gen_new_label();
5339: b &= 3;
5340: if (b == 3) {
5341: gen_op_jz_ecx[s->aflag](l1);
5342: } else {
5343: gen_op_dec_ECX[s->aflag]();
5344: if (b <= 1)
5345: gen_op_mov_T0_cc();
5346: gen_op_loop[s->aflag][b](l1);
5347: }
5348:
5349: gen_jmp_im(next_eip);
5350: gen_op_jmp_label(l2);
5351: gen_set_label(l1);
5352: gen_jmp_im(tval);
5353: gen_set_label(l2);
5354: gen_eob(s);
5355: }
5356: break;
5357: case 0x130: /* wrmsr */
5358: case 0x132: /* rdmsr */
5359: if (s->cpl != 0) {
5360: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5361: } else {
5362: if (b & 2)
5363: gen_op_rdmsr();
5364: else
5365: gen_op_wrmsr();
5366: }
5367: break;
5368: case 0x131: /* rdtsc */
5369: gen_jmp_im(pc_start - s->cs_base);
5370: gen_op_rdtsc();
5371: break;
5372: case 0x134: /* sysenter */
5373: if (CODE64(s))
5374: goto illegal_op;
5375: if (!s->pe) {
5376: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5377: } else {
5378: if (s->cc_op != CC_OP_DYNAMIC) {
5379: gen_op_set_cc_op(s->cc_op);
5380: s->cc_op = CC_OP_DYNAMIC;
5381: }
5382: gen_jmp_im(pc_start - s->cs_base);
5383: gen_op_sysenter();
5384: gen_eob(s);
5385: }
5386: break;
5387: case 0x135: /* sysexit */
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_sysexit();
5399: gen_eob(s);
5400: }
5401: break;
5402: #ifdef TARGET_X86_64
5403: case 0x105: /* syscall */
5404: /* XXX: is it usable in real mode ? */
5405: if (s->cc_op != CC_OP_DYNAMIC) {
5406: gen_op_set_cc_op(s->cc_op);
5407: s->cc_op = CC_OP_DYNAMIC;
5408: }
5409: gen_jmp_im(pc_start - s->cs_base);
5410: gen_op_syscall(s->pc - pc_start);
5411: gen_eob(s);
5412: break;
5413: case 0x107: /* sysret */
5414: if (!s->pe) {
5415: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5416: } else {
5417: if (s->cc_op != CC_OP_DYNAMIC) {
5418: gen_op_set_cc_op(s->cc_op);
5419: s->cc_op = CC_OP_DYNAMIC;
5420: }
5421: gen_jmp_im(pc_start - s->cs_base);
5422: gen_op_sysret(s->dflag);
5423: /* condition codes are modified only in long mode */
5424: if (s->lma)
5425: s->cc_op = CC_OP_EFLAGS;
5426: gen_eob(s);
5427: }
5428: break;
5429: #endif
5430: case 0x1a2: /* cpuid */
5431: gen_op_cpuid();
5432: break;
5433: case 0xf4: /* hlt */
5434: if (s->cpl != 0) {
5435: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5436: } else {
5437: if (s->cc_op != CC_OP_DYNAMIC)
5438: gen_op_set_cc_op(s->cc_op);
5439: gen_jmp_im(s->pc - s->cs_base);
5440: gen_op_hlt();
5441: s->is_jmp = 3;
5442: }
5443: break;
5444: case 0x100:
5445: modrm = ldub_code(s->pc++);
5446: mod = (modrm >> 6) & 3;
5447: op = (modrm >> 3) & 7;
5448: switch(op) {
5449: case 0: /* sldt */
5450: if (!s->pe || s->vm86)
5451: goto illegal_op;
5452: gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5453: ot = OT_WORD;
5454: if (mod == 3)
5455: ot += s->dflag;
5456: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5457: break;
5458: case 2: /* lldt */
5459: if (!s->pe || s->vm86)
5460: goto illegal_op;
5461: if (s->cpl != 0) {
5462: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5463: } else {
5464: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5465: gen_jmp_im(pc_start - s->cs_base);
5466: gen_op_lldt_T0();
5467: }
5468: break;
5469: case 1: /* str */
5470: if (!s->pe || s->vm86)
5471: goto illegal_op;
5472: gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5473: ot = OT_WORD;
5474: if (mod == 3)
5475: ot += s->dflag;
5476: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5477: break;
5478: case 3: /* ltr */
5479: if (!s->pe || s->vm86)
5480: goto illegal_op;
5481: if (s->cpl != 0) {
5482: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5483: } else {
5484: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5485: gen_jmp_im(pc_start - s->cs_base);
5486: gen_op_ltr_T0();
5487: }
5488: break;
5489: case 4: /* verr */
5490: case 5: /* verw */
5491: if (!s->pe || s->vm86)
5492: goto illegal_op;
5493: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5494: if (s->cc_op != CC_OP_DYNAMIC)
5495: gen_op_set_cc_op(s->cc_op);
5496: if (op == 4)
5497: gen_op_verr();
5498: else
5499: gen_op_verw();
5500: s->cc_op = CC_OP_EFLAGS;
5501: break;
5502: default:
5503: goto illegal_op;
5504: }
5505: break;
5506: case 0x101:
5507: modrm = ldub_code(s->pc++);
5508: mod = (modrm >> 6) & 3;
5509: op = (modrm >> 3) & 7;
5510: switch(op) {
5511: case 0: /* sgdt */
5512: case 1: /* sidt */
5513: if (mod == 3)
5514: goto illegal_op;
5515: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5516: if (op == 0)
5517: gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
5518: else
5519: gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
5520: gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5521: gen_add_A0_im(s, 2);
5522: if (op == 0)
5523: gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base));
5524: else
5525: gen_op_movtl_T0_env(offsetof(CPUX86State,idt.base));
5526: if (!s->dflag)
5527: gen_op_andl_T0_im(0xffffff);
5528: gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5529: break;
5530: case 2: /* lgdt */
5531: case 3: /* lidt */
5532: if (mod == 3)
5533: goto illegal_op;
5534: if (s->cpl != 0) {
5535: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5536: } else {
5537: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5538: gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
5539: gen_add_A0_im(s, 2);
5540: gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5541: if (!s->dflag)
5542: gen_op_andl_T0_im(0xffffff);
5543: if (op == 2) {
5544: gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
5545: gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5546: } else {
5547: gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
5548: gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5549: }
5550: }
5551: break;
5552: case 4: /* smsw */
5553: gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5554: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5555: break;
5556: case 6: /* lmsw */
5557: if (s->cpl != 0) {
5558: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5559: } else {
5560: gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5561: gen_op_lmsw_T0();
5562: gen_jmp_im(s->pc - s->cs_base);
5563: gen_eob(s);
5564: }
5565: break;
5566: case 7: /* invlpg */
5567: if (s->cpl != 0) {
5568: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5569: } else {
5570: if (mod == 3) {
5571: #ifdef TARGET_X86_64
5572: if (CODE64(s) && (modrm & 7) == 0) {
5573: /* swapgs */
5574: gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5575: gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5576: gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5577: gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
5578: } else
5579: #endif
5580: {
5581: goto illegal_op;
5582: }
5583: } else {
5584: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5585: gen_op_invlpg_A0();
5586: gen_jmp_im(s->pc - s->cs_base);
5587: gen_eob(s);
5588: }
5589: }
5590: break;
5591: default:
5592: goto illegal_op;
5593: }
5594: break;
5595: case 0x108: /* invd */
5596: case 0x109: /* wbinvd */
5597: if (s->cpl != 0) {
5598: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5599: } else {
5600: /* nothing to do */
5601: }
5602: break;
5603: case 0x63: /* arpl or movslS (x86_64) */
5604: #ifdef TARGET_X86_64
5605: if (CODE64(s)) {
5606: int d_ot;
5607: /* d_ot is the size of destination */
5608: d_ot = dflag + OT_WORD;
5609:
5610: modrm = ldub_code(s->pc++);
5611: reg = ((modrm >> 3) & 7) | rex_r;
5612: mod = (modrm >> 6) & 3;
5613: rm = (modrm & 7) | REX_B(s);
5614:
5615: if (mod == 3) {
5616: gen_op_mov_TN_reg[OT_LONG][0][rm]();
5617: /* sign extend */
5618: if (d_ot == OT_QUAD)
5619: gen_op_movslq_T0_T0();
5620: gen_op_mov_reg_T0[d_ot][reg]();
5621: } else {
5622: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5623: if (d_ot == OT_QUAD) {
5624: gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
5625: } else {
5626: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
5627: }
5628: gen_op_mov_reg_T0[d_ot][reg]();
5629: }
5630: } else
5631: #endif
5632: {
5633: if (!s->pe || s->vm86)
5634: goto illegal_op;
5635: ot = dflag ? OT_LONG : OT_WORD;
5636: modrm = ldub_code(s->pc++);
5637: reg = (modrm >> 3) & 7;
5638: mod = (modrm >> 6) & 3;
5639: rm = modrm & 7;
5640: if (mod != 3) {
5641: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5642: gen_op_ld_T0_A0[ot + s->mem_index]();
5643: } else {
5644: gen_op_mov_TN_reg[ot][0][rm]();
5645: }
5646: if (s->cc_op != CC_OP_DYNAMIC)
5647: gen_op_set_cc_op(s->cc_op);
5648: gen_op_arpl();
5649: s->cc_op = CC_OP_EFLAGS;
5650: if (mod != 3) {
5651: gen_op_st_T0_A0[ot + s->mem_index]();
5652: } else {
5653: gen_op_mov_reg_T0[ot][rm]();
5654: }
5655: gen_op_arpl_update();
5656: }
5657: break;
5658: case 0x102: /* lar */
5659: case 0x103: /* lsl */
5660: if (!s->pe || s->vm86)
5661: goto illegal_op;
5662: ot = dflag ? OT_LONG : OT_WORD;
5663: modrm = ldub_code(s->pc++);
5664: reg = ((modrm >> 3) & 7) | rex_r;
5665: gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5666: gen_op_mov_TN_reg[ot][1][reg]();
5667: if (s->cc_op != CC_OP_DYNAMIC)
5668: gen_op_set_cc_op(s->cc_op);
5669: if (b == 0x102)
5670: gen_op_lar();
5671: else
5672: gen_op_lsl();
5673: s->cc_op = CC_OP_EFLAGS;
5674: gen_op_mov_reg_T1[ot][reg]();
5675: break;
5676: case 0x118:
5677: modrm = ldub_code(s->pc++);
5678: mod = (modrm >> 6) & 3;
5679: op = (modrm >> 3) & 7;
5680: switch(op) {
5681: case 0: /* prefetchnta */
5682: case 1: /* prefetchnt0 */
5683: case 2: /* prefetchnt0 */
5684: case 3: /* prefetchnt0 */
5685: if (mod == 3)
5686: goto illegal_op;
5687: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5688: /* nothing more to do */
5689: break;
5690: default:
5691: goto illegal_op;
5692: }
5693: break;
5694: case 0x120: /* mov reg, crN */
5695: case 0x122: /* mov crN, reg */
5696: if (s->cpl != 0) {
5697: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5698: } else {
5699: modrm = ldub_code(s->pc++);
5700: if ((modrm & 0xc0) != 0xc0)
5701: goto illegal_op;
5702: rm = (modrm & 7) | REX_B(s);
5703: reg = ((modrm >> 3) & 7) | rex_r;
5704: if (CODE64(s))
5705: ot = OT_QUAD;
5706: else
5707: ot = OT_LONG;
5708: switch(reg) {
5709: case 0:
5710: case 2:
5711: case 3:
5712: case 4:
5713: case 8:
5714: if (b & 2) {
5715: gen_op_mov_TN_reg[ot][0][rm]();
5716: gen_op_movl_crN_T0(reg);
5717: gen_jmp_im(s->pc - s->cs_base);
5718: gen_eob(s);
5719: } else {
5720: #if !defined(CONFIG_USER_ONLY)
5721: if (reg == 8)
5722: gen_op_movtl_T0_cr8();
5723: else
5724: #endif
5725: gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
5726: gen_op_mov_reg_T0[ot][rm]();
5727: }
5728: break;
5729: default:
5730: goto illegal_op;
5731: }
5732: }
5733: break;
5734: case 0x121: /* mov reg, drN */
5735: case 0x123: /* mov drN, reg */
5736: if (s->cpl != 0) {
5737: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5738: } else {
5739: modrm = ldub_code(s->pc++);
5740: if ((modrm & 0xc0) != 0xc0)
5741: goto illegal_op;
5742: rm = (modrm & 7) | REX_B(s);
5743: reg = ((modrm >> 3) & 7) | rex_r;
5744: if (CODE64(s))
5745: ot = OT_QUAD;
5746: else
5747: ot = OT_LONG;
5748: /* XXX: do it dynamically with CR4.DE bit */
5749: if (reg == 4 || reg == 5 || reg >= 8)
5750: goto illegal_op;
5751: if (b & 2) {
5752: gen_op_mov_TN_reg[ot][0][rm]();
5753: gen_op_movl_drN_T0(reg);
5754: gen_jmp_im(s->pc - s->cs_base);
5755: gen_eob(s);
5756: } else {
5757: gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
5758: gen_op_mov_reg_T0[ot][rm]();
5759: }
5760: }
5761: break;
5762: case 0x106: /* clts */
5763: if (s->cpl != 0) {
5764: gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5765: } else {
5766: gen_op_clts();
5767: /* abort block because static cpu state changed */
5768: gen_jmp_im(s->pc - s->cs_base);
5769: gen_eob(s);
5770: }
5771: break;
5772: /* MMX/SSE/SSE2/PNI support */
5773: case 0x1c3: /* MOVNTI reg, mem */
5774: if (!(s->cpuid_features & CPUID_SSE2))
5775: goto illegal_op;
5776: ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
5777: modrm = ldub_code(s->pc++);
5778: mod = (modrm >> 6) & 3;
5779: if (mod == 3)
5780: goto illegal_op;
5781: reg = ((modrm >> 3) & 7) | rex_r;
5782: /* generate a generic store */
5783: gen_ldst_modrm(s, modrm, ot, reg, 1);
5784: break;
5785: case 0x1ae:
5786: modrm = ldub_code(s->pc++);
5787: mod = (modrm >> 6) & 3;
5788: op = (modrm >> 3) & 7;
5789: switch(op) {
5790: case 0: /* fxsave */
5791: if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
5792: goto illegal_op;
5793: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5794: gen_op_fxsave_A0((s->dflag == 2));
5795: break;
5796: case 1: /* fxrstor */
5797: if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
5798: goto illegal_op;
5799: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5800: gen_op_fxrstor_A0((s->dflag == 2));
5801: break;
5802: case 2: /* ldmxcsr */
5803: case 3: /* stmxcsr */
5804: if (s->flags & HF_TS_MASK) {
5805: gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5806: break;
5807: }
5808: if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
5809: mod == 3)
5810: goto illegal_op;
5811: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5812: if (op == 2) {
5813: gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
5814: gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
5815: } else {
5816: gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
5817: gen_op_st_T0_A0[OT_LONG + s->mem_index]();
5818: }
5819: break;
5820: case 5: /* lfence */
5821: case 6: /* mfence */
5822: if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
5823: goto illegal_op;
5824: break;
5825: case 7: /* sfence / clflush */
5826: if ((modrm & 0xc7) == 0xc0) {
5827: /* sfence */
5828: if (!(s->cpuid_features & CPUID_SSE))
5829: goto illegal_op;
5830: } else {
5831: /* clflush */
5832: if (!(s->cpuid_features & CPUID_CLFLUSH))
5833: goto illegal_op;
5834: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5835: }
5836: break;
5837: default:
5838: goto illegal_op;
5839: }
5840: break;
5841: case 0x10d: /* prefetch */
5842: modrm = ldub_code(s->pc++);
5843: gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
5844: /* ignore for now */
5845: break;
5846: case 0x110 ... 0x117:
5847: case 0x128 ... 0x12f:
5848: case 0x150 ... 0x177:
5849: case 0x17c ... 0x17f:
5850: case 0x1c2:
5851: case 0x1c4 ... 0x1c6:
5852: case 0x1d0 ... 0x1fe:
5853: gen_sse(s, b, pc_start, rex_r);
5854: break;
5855: default:
5856: goto illegal_op;
5857: }
5858: /* lock generation */
5859: if (s->prefix & PREFIX_LOCK)
5860: gen_op_unlock();
5861: return s->pc;
5862: illegal_op:
5863: if (s->prefix & PREFIX_LOCK)
5864: gen_op_unlock();
5865: /* XXX: ensure that no lock was generated */
5866: gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
5867: return s->pc;
5868: }
5869:
5870: #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
5871: #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
5872:
5873: /* flags read by an operation */
5874: static uint16_t opc_read_flags[NB_OPS] = {
5875: [INDEX_op_aas] = CC_A,
5876: [INDEX_op_aaa] = CC_A,
5877: [INDEX_op_das] = CC_A | CC_C,
5878: [INDEX_op_daa] = CC_A | CC_C,
5879:
5880: /* subtle: due to the incl/decl implementation, C is used */
5881: [INDEX_op_update_inc_cc] = CC_C,
5882:
5883: [INDEX_op_into] = CC_O,
5884:
5885: [INDEX_op_jb_subb] = CC_C,
5886: [INDEX_op_jb_subw] = CC_C,
5887: [INDEX_op_jb_subl] = CC_C,
5888:
5889: [INDEX_op_jz_subb] = CC_Z,
5890: [INDEX_op_jz_subw] = CC_Z,
5891: [INDEX_op_jz_subl] = CC_Z,
5892:
5893: [INDEX_op_jbe_subb] = CC_Z | CC_C,
5894: [INDEX_op_jbe_subw] = CC_Z | CC_C,
5895: [INDEX_op_jbe_subl] = CC_Z | CC_C,
5896:
5897: [INDEX_op_js_subb] = CC_S,
5898: [INDEX_op_js_subw] = CC_S,
5899: [INDEX_op_js_subl] = CC_S,
5900:
5901: [INDEX_op_jl_subb] = CC_O | CC_S,
5902: [INDEX_op_jl_subw] = CC_O | CC_S,
5903: [INDEX_op_jl_subl] = CC_O | CC_S,
5904:
5905: [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
5906: [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
5907: [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
5908:
5909: [INDEX_op_loopnzw] = CC_Z,
5910: [INDEX_op_loopnzl] = CC_Z,
5911: [INDEX_op_loopzw] = CC_Z,
5912: [INDEX_op_loopzl] = CC_Z,
5913:
5914: [INDEX_op_seto_T0_cc] = CC_O,
5915: [INDEX_op_setb_T0_cc] = CC_C,
5916: [INDEX_op_setz_T0_cc] = CC_Z,
5917: [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
5918: [INDEX_op_sets_T0_cc] = CC_S,
5919: [INDEX_op_setp_T0_cc] = CC_P,
5920: [INDEX_op_setl_T0_cc] = CC_O | CC_S,
5921: [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
5922:
5923: [INDEX_op_setb_T0_subb] = CC_C,
5924: [INDEX_op_setb_T0_subw] = CC_C,
5925: [INDEX_op_setb_T0_subl] = CC_C,
5926:
5927: [INDEX_op_setz_T0_subb] = CC_Z,
5928: [INDEX_op_setz_T0_subw] = CC_Z,
5929: [INDEX_op_setz_T0_subl] = CC_Z,
5930:
5931: [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
5932: [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
5933: [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
5934:
5935: [INDEX_op_sets_T0_subb] = CC_S,
5936: [INDEX_op_sets_T0_subw] = CC_S,
5937: [INDEX_op_sets_T0_subl] = CC_S,
5938:
5939: [INDEX_op_setl_T0_subb] = CC_O | CC_S,
5940: [INDEX_op_setl_T0_subw] = CC_O | CC_S,
5941: [INDEX_op_setl_T0_subl] = CC_O | CC_S,
5942:
5943: [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
5944: [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
5945: [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
5946:
5947: [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
5948: [INDEX_op_cmc] = CC_C,
5949: [INDEX_op_salc] = CC_C,
5950:
5951: /* needed for correct flag optimisation before string ops */
5952: [INDEX_op_jnz_ecxw] = CC_OSZAPC,
5953: [INDEX_op_jnz_ecxl] = CC_OSZAPC,
5954: [INDEX_op_jz_ecxw] = CC_OSZAPC,
5955: [INDEX_op_jz_ecxl] = CC_OSZAPC,
5956:
5957: #ifdef TARGET_X86_64
5958: [INDEX_op_jb_subq] = CC_C,
5959: [INDEX_op_jz_subq] = CC_Z,
5960: [INDEX_op_jbe_subq] = CC_Z | CC_C,
5961: [INDEX_op_js_subq] = CC_S,
5962: [INDEX_op_jl_subq] = CC_O | CC_S,
5963: [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
5964:
5965: [INDEX_op_loopnzq] = CC_Z,
5966: [INDEX_op_loopzq] = CC_Z,
5967:
5968: [INDEX_op_setb_T0_subq] = CC_C,
5969: [INDEX_op_setz_T0_subq] = CC_Z,
5970: [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
5971: [INDEX_op_sets_T0_subq] = CC_S,
5972: [INDEX_op_setl_T0_subq] = CC_O | CC_S,
5973: [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
5974:
5975: [INDEX_op_jnz_ecxq] = CC_OSZAPC,
5976: [INDEX_op_jz_ecxq] = CC_OSZAPC,
5977: #endif
5978:
5979: #define DEF_READF(SUFFIX)\
5980: [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5981: [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
5982: [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
5983: X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
5984: [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5985: [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
5986: [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
5987: X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
5988: \
5989: [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5990: [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
5991: [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
5992: X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
5993: [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5994: [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
5995: [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
5996: X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
5997:
5998: DEF_READF( )
5999: DEF_READF(_raw)
6000: #ifndef CONFIG_USER_ONLY
6001: DEF_READF(_kernel)
6002: DEF_READF(_user)
6003: #endif
6004: };
6005:
6006: /* flags written by an operation */
6007: static uint16_t opc_write_flags[NB_OPS] = {
6008: [INDEX_op_update2_cc] = CC_OSZAPC,
6009: [INDEX_op_update1_cc] = CC_OSZAPC,
6010: [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6011: [INDEX_op_update_neg_cc] = CC_OSZAPC,
6012: /* subtle: due to the incl/decl implementation, C is used */
6013: [INDEX_op_update_inc_cc] = CC_OSZAPC,
6014: [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6015:
6016: [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
6017: [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
6018: [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
6019: X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6020: [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6021: [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
6022: [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
6023: X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
6024: [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6025: [INDEX_op_imull_T0_T1] = CC_OSZAPC,
6026: X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6027:
6028: /* sse */
6029: [INDEX_op_ucomiss] = CC_OSZAPC,
6030: [INDEX_op_ucomisd] = CC_OSZAPC,
6031: [INDEX_op_comiss] = CC_OSZAPC,
6032: [INDEX_op_comisd] = CC_OSZAPC,
6033:
6034: /* bcd */
6035: [INDEX_op_aam] = CC_OSZAPC,
6036: [INDEX_op_aad] = CC_OSZAPC,
6037: [INDEX_op_aas] = CC_OSZAPC,
6038: [INDEX_op_aaa] = CC_OSZAPC,
6039: [INDEX_op_das] = CC_OSZAPC,
6040: [INDEX_op_daa] = CC_OSZAPC,
6041:
6042: [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6043: [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6044: [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
6045: [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6046: [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6047: [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6048: [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
6049: [INDEX_op_clc] = CC_C,
6050: [INDEX_op_stc] = CC_C,
6051: [INDEX_op_cmc] = CC_C,
6052:
6053: [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6054: [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
6055: X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
6056: [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6057: [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
6058: X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
6059: [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6060: [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
6061: X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
6062: [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6063: [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
6064: X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
6065:
6066: [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6067: [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
6068: X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
6069: [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6070: [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
6071: X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
6072:
6073: [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6074: [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6075: [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
6076: X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
6077:
6078: [INDEX_op_cmpxchg8b] = CC_Z,
6079: [INDEX_op_lar] = CC_Z,
6080: [INDEX_op_lsl] = CC_Z,
6081: [INDEX_op_verr] = CC_Z,
6082: [INDEX_op_verw] = CC_Z,
6083: [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6084: [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6085:
6086: #define DEF_WRITEF(SUFFIX)\
6087: [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6088: [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6089: [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6090: X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6091: [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6092: [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6093: [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6094: X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6095: \
6096: [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6097: [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6098: [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6099: X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6100: [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6101: [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6102: [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6103: X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6104: \
6105: [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6106: [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6107: [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6108: X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6109: [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6110: [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6111: [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6112: X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6113: \
6114: [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6115: [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6116: [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6117: X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6118: \
6119: [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6120: [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6121: [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6122: X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6123: \
6124: [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6125: [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6126: [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6127: X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6128: \
6129: [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6130: [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6131: X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6132: [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6133: [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6134: X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6135: \
6136: [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6137: [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6138: X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6139: [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6140: [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6141: X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6142: \
6143: [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6144: [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6145: [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6146: X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
6147:
6148:
6149: DEF_WRITEF( )
6150: DEF_WRITEF(_raw)
6151: #ifndef CONFIG_USER_ONLY
6152: DEF_WRITEF(_kernel)
6153: DEF_WRITEF(_user)
6154: #endif
6155: };
6156:
6157: /* simpler form of an operation if no flags need to be generated */
6158: static uint16_t opc_simpler[NB_OPS] = {
6159: [INDEX_op_update2_cc] = INDEX_op_nop,
6160: [INDEX_op_update1_cc] = INDEX_op_nop,
6161: [INDEX_op_update_neg_cc] = INDEX_op_nop,
6162: #if 0
6163: /* broken: CC_OP logic must be rewritten */
6164: [INDEX_op_update_inc_cc] = INDEX_op_nop,
6165: #endif
6166:
6167: [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6168: [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6169: [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
6170: X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
6171:
6172: [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6173: [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6174: [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
6175: X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
6176:
6177: [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6178: [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6179: [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
6180: X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
6181:
6182: #define DEF_SIMPLER(SUFFIX)\
6183: [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6184: [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6185: [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
6186: X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
6187: \
6188: [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6189: [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
6190: [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6191: X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
6192:
6193: DEF_SIMPLER( )
6194: DEF_SIMPLER(_raw)
6195: #ifndef CONFIG_USER_ONLY
6196: DEF_SIMPLER(_kernel)
6197: DEF_SIMPLER(_user)
6198: #endif
6199: };
6200:
6201: void optimize_flags_init(void)
6202: {
6203: int i;
6204: /* put default values in arrays */
6205: for(i = 0; i < NB_OPS; i++) {
6206: if (opc_simpler[i] == 0)
6207: opc_simpler[i] = i;
6208: }
6209: }
6210:
6211: /* CPU flags computation optimization: we move backward thru the
6212: generated code to see which flags are needed. The operation is
6213: modified if suitable */
6214: static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6215: {
6216: uint16_t *opc_ptr;
6217: int live_flags, write_flags, op;
6218:
6219: opc_ptr = opc_buf + opc_buf_len;
6220: /* live_flags contains the flags needed by the next instructions
6221: in the code. At the end of the bloc, we consider that all the
6222: flags are live. */
6223: live_flags = CC_OSZAPC;
6224: while (opc_ptr > opc_buf) {
6225: op = *--opc_ptr;
6226: /* if none of the flags written by the instruction is used,
6227: then we can try to find a simpler instruction */
6228: write_flags = opc_write_flags[op];
6229: if ((live_flags & write_flags) == 0) {
6230: *opc_ptr = opc_simpler[op];
6231: }
6232: /* compute the live flags before the instruction */
6233: live_flags &= ~write_flags;
6234: live_flags |= opc_read_flags[op];
6235: }
6236: }
6237:
6238: /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6239: basic block 'tb'. If search_pc is TRUE, also generate PC
6240: information for each intermediate instruction. */
6241: static inline int gen_intermediate_code_internal(CPUState *env,
6242: TranslationBlock *tb,
6243: int search_pc)
6244: {
6245: DisasContext dc1, *dc = &dc1;
6246: target_ulong pc_ptr;
6247: uint16_t *gen_opc_end;
6248: int flags, j, lj, cflags;
6249: target_ulong pc_start;
6250: target_ulong cs_base;
6251:
6252: /* generate intermediate code */
6253: pc_start = tb->pc;
6254: cs_base = tb->cs_base;
6255: flags = tb->flags;
6256: cflags = tb->cflags;
6257:
6258: dc->pe = (flags >> HF_PE_SHIFT) & 1;
6259: dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6260: dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6261: dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6262: dc->f_st = 0;
6263: dc->vm86 = (flags >> VM_SHIFT) & 1;
6264: dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6265: dc->iopl = (flags >> IOPL_SHIFT) & 3;
6266: dc->tf = (flags >> TF_SHIFT) & 1;
6267: dc->singlestep_enabled = env->singlestep_enabled;
6268: dc->cc_op = CC_OP_DYNAMIC;
6269: dc->cs_base = cs_base;
6270: dc->tb = tb;
6271: dc->popl_esp_hack = 0;
6272: /* select memory access functions */
6273: dc->mem_index = 0;
6274: if (flags & HF_SOFTMMU_MASK) {
6275: if (dc->cpl == 3)
6276: dc->mem_index = 2 * 4;
6277: else
6278: dc->mem_index = 1 * 4;
6279: }
6280: dc->cpuid_features = env->cpuid_features;
6281: #ifdef TARGET_X86_64
6282: dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6283: dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6284: #endif
6285: dc->flags = flags;
6286: dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6287: (flags & HF_INHIBIT_IRQ_MASK)
6288: #ifndef CONFIG_SOFTMMU
6289: || (flags & HF_SOFTMMU_MASK)
6290: #endif
6291: );
6292: #if 0
6293: /* check addseg logic */
6294: if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
6295: printf("ERROR addseg\n");
6296: #endif
6297:
6298: gen_opc_ptr = gen_opc_buf;
6299: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6300: gen_opparam_ptr = gen_opparam_buf;
6301: nb_gen_labels = 0;
6302:
6303: dc->is_jmp = DISAS_NEXT;
6304: pc_ptr = pc_start;
6305: lj = -1;
6306:
6307: for(;;) {
6308: if (env->nb_breakpoints > 0) {
6309: for(j = 0; j < env->nb_breakpoints; j++) {
6310: if (env->breakpoints[j] == pc_ptr) {
6311: gen_debug(dc, pc_ptr - dc->cs_base);
6312: break;
6313: }
6314: }
6315: }
6316: if (search_pc) {
6317: j = gen_opc_ptr - gen_opc_buf;
6318: if (lj < j) {
6319: lj++;
6320: while (lj < j)
6321: gen_opc_instr_start[lj++] = 0;
6322: }
6323: gen_opc_pc[lj] = pc_ptr;
6324: gen_opc_cc_op[lj] = dc->cc_op;
6325: gen_opc_instr_start[lj] = 1;
6326: }
6327: pc_ptr = disas_insn(dc, pc_ptr);
6328: /* stop translation if indicated */
6329: if (dc->is_jmp)
6330: break;
6331: /* if single step mode, we generate only one instruction and
6332: generate an exception */
6333: /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6334: the flag and abort the translation to give the irqs a
6335: change to be happen */
6336: if (dc->tf || dc->singlestep_enabled ||
6337: (flags & HF_INHIBIT_IRQ_MASK) ||
6338: (cflags & CF_SINGLE_INSN)) {
6339: gen_jmp_im(pc_ptr - dc->cs_base);
6340: gen_eob(dc);
6341: break;
6342: }
6343: /* if too long translation, stop generation too */
6344: if (gen_opc_ptr >= gen_opc_end ||
6345: (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
6346: gen_jmp_im(pc_ptr - dc->cs_base);
6347: gen_eob(dc);
6348: break;
6349: }
6350: }
6351: *gen_opc_ptr = INDEX_op_end;
6352: /* we don't forget to fill the last values */
6353: if (search_pc) {
6354: j = gen_opc_ptr - gen_opc_buf;
6355: lj++;
6356: while (lj <= j)
6357: gen_opc_instr_start[lj++] = 0;
6358: }
6359:
6360: #ifdef DEBUG_DISAS
6361: if (loglevel & CPU_LOG_TB_CPU) {
6362: cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
6363: }
6364: if (loglevel & CPU_LOG_TB_IN_ASM) {
6365: int disas_flags;
6366: fprintf(logfile, "----------------\n");
6367: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6368: #ifdef TARGET_X86_64
6369: if (dc->code64)
6370: disas_flags = 2;
6371: else
6372: #endif
6373: disas_flags = !dc->code32;
6374: target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
6375: fprintf(logfile, "\n");
6376: if (loglevel & CPU_LOG_TB_OP) {
6377: fprintf(logfile, "OP:\n");
6378: dump_ops(gen_opc_buf, gen_opparam_buf);
6379: fprintf(logfile, "\n");
6380: }
6381: }
6382: #endif
6383:
6384: /* optimize flag computations */
6385: optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6386:
6387: #ifdef DEBUG_DISAS
6388: if (loglevel & CPU_LOG_TB_OP_OPT) {
6389: fprintf(logfile, "AFTER FLAGS OPT:\n");
6390: dump_ops(gen_opc_buf, gen_opparam_buf);
6391: fprintf(logfile, "\n");
6392: }
6393: #endif
6394: if (!search_pc)
6395: tb->size = pc_ptr - pc_start;
6396: return 0;
6397: }
6398:
6399: int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6400: {
6401: return gen_intermediate_code_internal(env, tb, 0);
6402: }
6403:
6404: int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6405: {
6406: return gen_intermediate_code_internal(env, tb, 1);
6407: }
6408:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.