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