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