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