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