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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 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 27 #include "cpu.h" 28 #include "exec-all.h" 29 #include "disas.h" 30 #include "tcg-op.h" 31 32 #include "helper.h" 33 #define GEN_HELPER 1 34 #include "helper.h" 35 #include "hax.h" 36 37 #define PREFIX_REPZ 0x01 38 #define PREFIX_REPNZ 0x02 39 #define PREFIX_LOCK 0x04 40 #define PREFIX_DATA 0x08 41 #define PREFIX_ADR 0x10 42 43 #ifdef TARGET_X86_64 44 #define X86_64_ONLY(x) x 45 #define X86_64_DEF(...) __VA_ARGS__ 46 #define CODE64(s) ((s)->code64) 47 #define REX_X(s) ((s)->rex_x) 48 #define REX_B(s) ((s)->rex_b) 49 /* XXX: gcc generates push/pop in some opcodes, so we cannot use them */ 50 #if 1 51 #define BUGGY_64(x) NULL 52 #endif 53 #else 54 #define X86_64_ONLY(x) NULL 55 #define X86_64_DEF(...) 56 #define CODE64(s) 0 57 #define REX_X(s) 0 58 #define REX_B(s) 0 59 #endif 60 61 //#define MACRO_TEST 1 62 63 /* global register indexes */ 64 static TCGv_ptr cpu_env; 65 static TCGv cpu_A0, cpu_cc_src, cpu_cc_dst, cpu_cc_tmp; 66 static TCGv_i32 cpu_cc_op; 67 /* local temps */ 68 static TCGv cpu_T[2], cpu_T3; 69 /* local register indexes (only used inside old micro ops) */ 70 static TCGv cpu_tmp0, cpu_tmp4; 71 static TCGv_ptr cpu_ptr0, cpu_ptr1; 72 static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32; 73 static TCGv_i64 cpu_tmp1_i64; 74 static TCGv cpu_tmp5, cpu_tmp6; 75 76 #include "gen-icount.h" 77 78 #ifdef TARGET_X86_64 79 static int x86_64_hregs; 80 #endif 81 82 typedef struct DisasContext { 83 /* current insn context */ 84 int override; /* -1 if no override */ 85 int prefix; 86 int aflag, dflag; 87 target_ulong pc; /* pc = eip + cs_base */ 88 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU 89 static state change (stop translation) */ 90 /* current block context */ 91 target_ulong cs_base; /* base of CS segment */ 92 int pe; /* protected mode */ 93 int code32; /* 32 bit code segment */ 94 #ifdef TARGET_X86_64 95 int lma; /* long mode active */ 96 int code64; /* 64 bit code segment */ 97 int rex_x, rex_b; 98 #endif 99 int ss32; /* 32 bit stack segment */ 100 int cc_op; /* current CC operation */ 101 int addseg; /* non zero if either DS/ES/SS have a non zero base */ 102 int f_st; /* currently unused */ 103 int vm86; /* vm86 mode */ 104 int cpl; 105 int iopl; 106 int tf; /* TF cpu flag */ 107 int singlestep_enabled; /* "hardware" single step enabled */ 108 int jmp_opt; /* use direct block chaining for direct jumps */ 109 int mem_index; /* select memory access functions */ 110 uint64_t flags; /* all execution flags */ 111 struct TranslationBlock *tb; 112 int popl_esp_hack; /* for correct popl with esp base handling */ 113 int rip_offset; /* only used in x86_64, but left for simplicity */ 114 int cpuid_features; 115 int cpuid_ext_features; 116 int cpuid_ext2_features; 117 int cpuid_ext3_features; 118 } DisasContext; 119 120 static void gen_eob(DisasContext *s); 121 static void gen_jmp(DisasContext *s, target_ulong eip); 122 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num); 123 124 /* i386 arith/logic operations */ 125 enum { 126 OP_ADDL, 127 OP_ORL, 128 OP_ADCL, 129 OP_SBBL, 130 OP_ANDL, 131 OP_SUBL, 132 OP_XORL, 133 OP_CMPL, 134 }; 135 136 /* i386 shift ops */ 137 enum { 138 OP_ROL, 139 OP_ROR, 140 OP_RCL, 141 OP_RCR, 142 OP_SHL, 143 OP_SHR, 144 OP_SHL1, /* undocumented */ 145 OP_SAR = 7, 146 }; 147 148 enum { 149 JCC_O, 150 JCC_B, 151 JCC_Z, 152 JCC_BE, 153 JCC_S, 154 JCC_P, 155 JCC_L, 156 JCC_LE, 157 }; 158 159 /* operand size */ 160 enum { 161 OT_BYTE = 0, 162 OT_WORD, 163 OT_LONG, 164 OT_QUAD, 165 }; 166 167 enum { 168 /* I386 int registers */ 169 OR_EAX, /* MUST be even numbered */ 170 OR_ECX, 171 OR_EDX, 172 OR_EBX, 173 OR_ESP, 174 OR_EBP, 175 OR_ESI, 176 OR_EDI, 177 178 OR_TMP0 = 16, /* temporary operand register */ 179 OR_TMP1, 180 OR_A0, /* temporary register used when doing address evaluation */ 181 }; 182 183 static inline void gen_op_movl_T0_0(void) 184 { 185 tcg_gen_movi_tl(cpu_T[0], 0); 186 } 187 188 static inline void gen_op_movl_T0_im(int32_t val) 189 { 190 tcg_gen_movi_tl(cpu_T[0], val); 191 } 192 193 static inline void gen_op_movl_T0_imu(uint32_t val) 194 { 195 tcg_gen_movi_tl(cpu_T[0], val); 196 } 197 198 static inline void gen_op_movl_T1_im(int32_t val) 199 { 200 tcg_gen_movi_tl(cpu_T[1], val); 201 } 202 203 static inline void gen_op_movl_T1_imu(uint32_t val) 204 { 205 tcg_gen_movi_tl(cpu_T[1], val); 206 } 207 208 static inline void gen_op_movl_A0_im(uint32_t val) 209 { 210 tcg_gen_movi_tl(cpu_A0, val); 211 } 212 213 #ifdef TARGET_X86_64 214 static inline void gen_op_movq_A0_im(int64_t val) 215 { 216 tcg_gen_movi_tl(cpu_A0, val); 217 } 218 #endif 219 220 static inline void gen_movtl_T0_im(target_ulong val) 221 { 222 tcg_gen_movi_tl(cpu_T[0], val); 223 } 224 225 static inline void gen_movtl_T1_im(target_ulong val) 226 { 227 tcg_gen_movi_tl(cpu_T[1], val); 228 } 229 230 static inline void gen_op_andl_T0_ffff(void) 231 { 232 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff); 233 } 234 235 static inline void gen_op_andl_T0_im(uint32_t val) 236 { 237 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val); 238 } 239 240 static inline void gen_op_movl_T0_T1(void) 241 { 242 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); 243 } 244 245 static inline void gen_op_andl_A0_ffff(void) 246 { 247 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff); 248 } 249 250 #ifdef TARGET_X86_64 251 252 #define NB_OP_SIZES 4 253 254 #else /* !TARGET_X86_64 */ 255 256 #define NB_OP_SIZES 3 257 258 #endif /* !TARGET_X86_64 */ 259 260 #if defined(WORDS_BIGENDIAN) 261 #define REG_B_OFFSET (sizeof(target_ulong) - 1) 262 #define REG_H_OFFSET (sizeof(target_ulong) - 2) 263 #define REG_W_OFFSET (sizeof(target_ulong) - 2) 264 #define REG_L_OFFSET (sizeof(target_ulong) - 4) 265 #define REG_LH_OFFSET (sizeof(target_ulong) - 8) 266 #else 267 #define REG_B_OFFSET 0 268 #define REG_H_OFFSET 1 269 #define REG_W_OFFSET 0 270 #define REG_L_OFFSET 0 271 #define REG_LH_OFFSET 4 272 #endif 273 274 static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0) 275 { 276 switch(ot) { 277 case OT_BYTE: 278 if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { 279 tcg_gen_st8_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_B_OFFSET); 280 } else { 281 tcg_gen_st8_tl(t0, cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET); 282 } 283 break; 284 case OT_WORD: 285 tcg_gen_st16_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); 286 break; 287 #ifdef TARGET_X86_64 288 case OT_LONG: 289 tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); 290 /* high part of register set to zero */ 291 tcg_gen_movi_tl(cpu_tmp0, 0); 292 tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); 293 break; 294 default: 295 case OT_QUAD: 296 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, regs[reg])); 297 break; 298 #else 299 default: 300 case OT_LONG: 301 tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); 302 break; 303 #endif 304 } 305 } 306 307 static inline void gen_op_mov_reg_T0(int ot, int reg) 308 { 309 gen_op_mov_reg_v(ot, reg, cpu_T[0]); 310 } 311 312 static inline void gen_op_mov_reg_T1(int ot, int reg) 313 { 314 gen_op_mov_reg_v(ot, reg, cpu_T[1]); 315 } 316 317 static inline void gen_op_mov_reg_A0(int size, int reg) 318 { 319 switch(size) { 320 case 0: 321 tcg_gen_st16_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); 322 break; 323 #ifdef TARGET_X86_64 324 case 1: 325 tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); 326 /* high part of register set to zero */ 327 tcg_gen_movi_tl(cpu_tmp0, 0); 328 tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); 329 break; 330 default: 331 case 2: 332 tcg_gen_st_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg])); 333 break; 334 #else 335 default: 336 case 1: 337 tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); 338 break; 339 #endif 340 } 341 } 342 343 static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg) 344 { 345 switch(ot) { 346 case OT_BYTE: 347 if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { 348 goto std_case; 349 } else { 350 tcg_gen_ld8u_tl(t0, cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET); 351 } 352 break; 353 default: 354 std_case: 355 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, regs[reg])); 356 break; 357 } 358 } 359 360 static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg) 361 { 362 gen_op_mov_v_reg(ot, cpu_T[t_index], reg); 363 } 364 365 static inline void gen_op_movl_A0_reg(int reg) 366 { 367 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); 368 } 369 370 static inline void gen_op_addl_A0_im(int32_t val) 371 { 372 tcg_gen_addi_tl(cpu_A0, cpu_A0, val); 373 #ifdef TARGET_X86_64 374 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); 375 #endif 376 } 377 378 #ifdef TARGET_X86_64 379 static inline void gen_op_addq_A0_im(int64_t val) 380 { 381 tcg_gen_addi_tl(cpu_A0, cpu_A0, val); 382 } 383 #endif 384 385 static void gen_add_A0_im(DisasContext *s, int val) 386 { 387 #ifdef TARGET_X86_64 388 if (CODE64(s)) 389 gen_op_addq_A0_im(val); 390 else 391 #endif 392 gen_op_addl_A0_im(val); 393 } 394 395 static inline void gen_op_addl_T0_T1(void) 396 { 397 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 398 } 399 400 static inline void gen_op_jmp_T0(void) 401 { 402 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip)); 403 } 404 405 static inline void gen_op_add_reg_im(int size, int reg, int32_t val) 406 { 407 switch(size) { 408 case 0: 409 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 410 tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); 411 tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); 412 break; 413 case 1: 414 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 415 tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); 416 #ifdef TARGET_X86_64 417 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff); 418 #endif 419 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 420 break; 421 #ifdef TARGET_X86_64 422 case 2: 423 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 424 tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); 425 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 426 break; 427 #endif 428 } 429 } 430 431 static inline void gen_op_add_reg_T0(int size, int reg) 432 { 433 switch(size) { 434 case 0: 435 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 436 tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); 437 tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); 438 break; 439 case 1: 440 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 441 tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); 442 #ifdef TARGET_X86_64 443 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff); 444 #endif 445 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 446 break; 447 #ifdef TARGET_X86_64 448 case 2: 449 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 450 tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); 451 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 452 break; 453 #endif 454 } 455 } 456 457 static inline void gen_op_set_cc_op(int32_t val) 458 { 459 tcg_gen_movi_i32(cpu_cc_op, val); 460 } 461 462 static inline void gen_op_addl_A0_reg_sN(int shift, int reg) 463 { 464 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 465 if (shift != 0) 466 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift); 467 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); 468 #ifdef TARGET_X86_64 469 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); 470 #endif 471 } 472 473 static inline void gen_op_movl_A0_seg(int reg) 474 { 475 tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base) + REG_L_OFFSET); 476 } 477 478 static inline void gen_op_addl_A0_seg(int reg) 479 { 480 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base)); 481 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); 482 #ifdef TARGET_X86_64 483 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); 484 #endif 485 } 486 487 #ifdef TARGET_X86_64 488 static inline void gen_op_movq_A0_seg(int reg) 489 { 490 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base)); 491 } 492 493 static inline void gen_op_addq_A0_seg(int reg) 494 { 495 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base)); 496 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); 497 } 498 499 static inline void gen_op_movq_A0_reg(int reg) 500 { 501 tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg])); 502 } 503 504 static inline void gen_op_addq_A0_reg_sN(int shift, int reg) 505 { 506 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); 507 if (shift != 0) 508 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift); 509 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); 510 } 511 #endif 512 513 static inline void gen_op_lds_T0_A0(int idx) 514 { 515 int mem_index = (idx >> 2) - 1; 516 switch(idx & 3) { 517 case 0: 518 tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index); 519 break; 520 case 1: 521 tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index); 522 break; 523 default: 524 case 2: 525 tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index); 526 break; 527 } 528 } 529 530 static inline void gen_op_ld_v(int idx, TCGv t0, TCGv a0) 531 { 532 int mem_index = (idx >> 2) - 1; 533 switch(idx & 3) { 534 case 0: 535 tcg_gen_qemu_ld8u(t0, a0, mem_index); 536 break; 537 case 1: 538 tcg_gen_qemu_ld16u(t0, a0, mem_index); 539 break; 540 case 2: 541 tcg_gen_qemu_ld32u(t0, a0, mem_index); 542 break; 543 default: 544 case 3: 545 /* Should never happen on 32-bit targets. */ 546 #ifdef TARGET_X86_64 547 tcg_gen_qemu_ld64(t0, a0, mem_index); 548 #endif 549 break; 550 } 551 } 552 553 /* XXX: always use ldu or lds */ 554 static inline void gen_op_ld_T0_A0(int idx) 555 { 556 gen_op_ld_v(idx, cpu_T[0], cpu_A0); 557 } 558 559 static inline void gen_op_ldu_T0_A0(int idx) 560 { 561 gen_op_ld_v(idx, cpu_T[0], cpu_A0); 562 } 563 564 static inline void gen_op_ld_T1_A0(int idx) 565 { 566 gen_op_ld_v(idx, cpu_T[1], cpu_A0); 567 } 568 569 static inline void gen_op_st_v(int idx, TCGv t0, TCGv a0) 570 { 571 int mem_index = (idx >> 2) - 1; 572 switch(idx & 3) { 573 case 0: 574 tcg_gen_qemu_st8(t0, a0, mem_index); 575 break; 576 case 1: 577 tcg_gen_qemu_st16(t0, a0, mem_index); 578 break; 579 case 2: 580 tcg_gen_qemu_st32(t0, a0, mem_index); 581 break; 582 default: 583 case 3: 584 /* Should never happen on 32-bit targets. */ 585 #ifdef TARGET_X86_64 586 tcg_gen_qemu_st64(t0, a0, mem_index); 587 #endif 588 break; 589 } 590 } 591 592 static inline void gen_op_st_T0_A0(int idx) 593 { 594 gen_op_st_v(idx, cpu_T[0], cpu_A0); 595 } 596 597 static inline void gen_op_st_T1_A0(int idx) 598 { 599 gen_op_st_v(idx, cpu_T[1], cpu_A0); 600 } 601 602 static inline void gen_jmp_im(target_ulong pc) 603 { 604 tcg_gen_movi_tl(cpu_tmp0, pc); 605 tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, eip)); 606 } 607 608 static inline void gen_string_movl_A0_ESI(DisasContext *s) 609 { 610 int override; 611 612 override = s->override; 613 #ifdef TARGET_X86_64 614 if (s->aflag == 2) { 615 if (override >= 0) { 616 gen_op_movq_A0_seg(override); 617 gen_op_addq_A0_reg_sN(0, R_ESI); 618 } else { 619 gen_op_movq_A0_reg(R_ESI); 620 } 621 } else 622 #endif 623 if (s->aflag) { 624 /* 32 bit address */ 625 if (s->addseg && override < 0) 626 override = R_DS; 627 if (override >= 0) { 628 gen_op_movl_A0_seg(override); 629 gen_op_addl_A0_reg_sN(0, R_ESI); 630 } else { 631 gen_op_movl_A0_reg(R_ESI); 632 } 633 } else { 634 /* 16 address, always override */ 635 if (override < 0) 636 override = R_DS; 637 gen_op_movl_A0_reg(R_ESI); 638 gen_op_andl_A0_ffff(); 639 gen_op_addl_A0_seg(override); 640 } 641 } 642 643 static inline void gen_string_movl_A0_EDI(DisasContext *s) 644 { 645 #ifdef TARGET_X86_64 646 if (s->aflag == 2) { 647 gen_op_movq_A0_reg(R_EDI); 648 } else 649 #endif 650 if (s->aflag) { 651 if (s->addseg) { 652 gen_op_movl_A0_seg(R_ES); 653 gen_op_addl_A0_reg_sN(0, R_EDI); 654 } else { 655 gen_op_movl_A0_reg(R_EDI); 656 } 657 } else { 658 gen_op_movl_A0_reg(R_EDI); 659 gen_op_andl_A0_ffff(); 660 gen_op_addl_A0_seg(R_ES); 661 } 662 } 663 664 static inline void gen_op_movl_T0_Dshift(int ot) 665 { 666 tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUState, df)); 667 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot); 668 }; 669 670 static void gen_extu(int ot, TCGv reg) 671 { 672 switch(ot) { 673 case OT_BYTE: 674 tcg_gen_ext8u_tl(reg, reg); 675 break; 676 case OT_WORD: 677 tcg_gen_ext16u_tl(reg, reg); 678 break; 679 case OT_LONG: 680 tcg_gen_ext32u_tl(reg, reg); 681 break; 682 default: 683 break; 684 } 685 } 686 687 static void gen_exts(int ot, TCGv reg) 688 { 689 switch(ot) { 690 case OT_BYTE: 691 tcg_gen_ext8s_tl(reg, reg); 692 break; 693 case OT_WORD: 694 tcg_gen_ext16s_tl(reg, reg); 695 break; 696 case OT_LONG: 697 tcg_gen_ext32s_tl(reg, reg); 698 break; 699 default: 700 break; 701 } 702 } 703 704 static inline void gen_op_jnz_ecx(int size, int label1) 705 { 706 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX])); 707 gen_extu(size + 1, cpu_tmp0); 708 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1); 709 } 710 711 static inline void gen_op_jz_ecx(int size, int label1) 712 { 713 tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX])); 714 gen_extu(size + 1, cpu_tmp0); 715 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1); 716 } 717 718 static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n) 719 { 720 switch (ot) { 721 case 0: gen_helper_inb(v, n); break; 722 case 1: gen_helper_inw(v, n); break; 723 case 2: gen_helper_inl(v, n); break; 724 } 725 726 } 727 728 static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n) 729 { 730 switch (ot) { 731 case 0: gen_helper_outb(v, n); break; 732 case 1: gen_helper_outw(v, n); break; 733 case 2: gen_helper_outl(v, n); break; 734 } 735 736 } 737 738 static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, 739 uint32_t svm_flags) 740 { 741 int state_saved; 742 target_ulong next_eip; 743 744 state_saved = 0; 745 if (s->pe && (s->cpl > s->iopl || s->vm86)) { 746 if (s->cc_op != CC_OP_DYNAMIC) 747 gen_op_set_cc_op(s->cc_op); 748 gen_jmp_im(cur_eip); 749 state_saved = 1; 750 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 751 switch (ot) { 752 case 0: gen_helper_check_iob(cpu_tmp2_i32); break; 753 case 1: gen_helper_check_iow(cpu_tmp2_i32); break; 754 case 2: gen_helper_check_iol(cpu_tmp2_i32); break; 755 } 756 } 757 if(s->flags & HF_SVMI_MASK) { 758 if (!state_saved) { 759 if (s->cc_op != CC_OP_DYNAMIC) 760 gen_op_set_cc_op(s->cc_op); 761 gen_jmp_im(cur_eip); 762 state_saved = 1; 763 } 764 svm_flags |= (1 << (4 + ot)); 765 next_eip = s->pc - s->cs_base; 766 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 767 gen_helper_svm_check_io(cpu_tmp2_i32, tcg_const_i32(svm_flags), 768 tcg_const_i32(next_eip - cur_eip)); 769 } 770 } 771 772 static inline void gen_movs(DisasContext *s, int ot) 773 { 774 gen_string_movl_A0_ESI(s); 775 gen_op_ld_T0_A0(ot + s->mem_index); 776 gen_string_movl_A0_EDI(s); 777 gen_op_st_T0_A0(ot + s->mem_index); 778 gen_op_movl_T0_Dshift(ot); 779 gen_op_add_reg_T0(s->aflag, R_ESI); 780 gen_op_add_reg_T0(s->aflag, R_EDI); 781 } 782 783 static inline void gen_update_cc_op(DisasContext *s) 784 { 785 if (s->cc_op != CC_OP_DYNAMIC) { 786 gen_op_set_cc_op(s->cc_op); 787 s->cc_op = CC_OP_DYNAMIC; 788 } 789 } 790 791 static void gen_op_update1_cc(void) 792 { 793 tcg_gen_discard_tl(cpu_cc_src); 794 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 795 } 796 797 static void gen_op_update2_cc(void) 798 { 799 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); 800 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 801 } 802 803 static inline void gen_op_cmpl_T0_T1_cc(void) 804 { 805 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); 806 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]); 807 } 808 809 static inline void gen_op_testl_T0_T1_cc(void) 810 { 811 tcg_gen_discard_tl(cpu_cc_src); 812 tcg_gen_and_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]); 813 } 814 815 static void gen_op_update_neg_cc(void) 816 { 817 tcg_gen_neg_tl(cpu_cc_src, cpu_T[0]); 818 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 819 } 820 821 /* compute eflags.C to reg */ 822 static void gen_compute_eflags_c(TCGv reg) 823 { 824 gen_helper_cc_compute_c(cpu_tmp2_i32, cpu_cc_op); 825 tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); 826 } 827 828 /* compute all eflags to cc_src */ 829 static void gen_compute_eflags(TCGv reg) 830 { 831 gen_helper_cc_compute_all(cpu_tmp2_i32, cpu_cc_op); 832 tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); 833 } 834 835 static inline void gen_setcc_slow_T0(DisasContext *s, int jcc_op) 836 { 837 if (s->cc_op != CC_OP_DYNAMIC) 838 gen_op_set_cc_op(s->cc_op); 839 switch(jcc_op) { 840 case JCC_O: 841 gen_compute_eflags(cpu_T[0]); 842 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 11); 843 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); 844 break; 845 case JCC_B: 846 gen_compute_eflags_c(cpu_T[0]); 847 break; 848 case JCC_Z: 849 gen_compute_eflags(cpu_T[0]); 850 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 6); 851 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); 852 break; 853 case JCC_BE: 854 gen_compute_eflags(cpu_tmp0); 855 tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 6); 856 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0); 857 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); 858 break; 859 case JCC_S: 860 gen_compute_eflags(cpu_T[0]); 861 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 7); 862 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); 863 break; 864 case JCC_P: 865 gen_compute_eflags(cpu_T[0]); 866 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 2); 867 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); 868 break; 869 case JCC_L: 870 gen_compute_eflags(cpu_tmp0); 871 tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */ 872 tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 7); /* CC_S */ 873 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0); 874 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); 875 break; 876 default: 877 case JCC_LE: 878 gen_compute_eflags(cpu_tmp0); 879 tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */ 880 tcg_gen_shri_tl(cpu_tmp4, cpu_tmp0, 7); /* CC_S */ 881 tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 6); /* CC_Z */ 882 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp4); 883 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0); 884 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); 885 break; 886 } 887 } 888 889 /* return true if setcc_slow is not needed (WARNING: must be kept in 890 sync with gen_jcc1) */ 891 static int is_fast_jcc_case(DisasContext *s, int b) 892 { 893 int jcc_op; 894 jcc_op = (b >> 1) & 7; 895 switch(s->cc_op) { 896 /* we optimize the cmp/jcc case */ 897 case CC_OP_SUBB: 898 case CC_OP_SUBW: 899 case CC_OP_SUBL: 900 case CC_OP_SUBQ: 901 if (jcc_op == JCC_O || jcc_op == JCC_P) 902 goto slow_jcc; 903 break; 904 905 /* some jumps are easy to compute */ 906 case CC_OP_ADDB: 907 case CC_OP_ADDW: 908 case CC_OP_ADDL: 909 case CC_OP_ADDQ: 910 911 case CC_OP_LOGICB: 912 case CC_OP_LOGICW: 913 case CC_OP_LOGICL: 914 case CC_OP_LOGICQ: 915 916 case CC_OP_INCB: 917 case CC_OP_INCW: 918 case CC_OP_INCL: 919 case CC_OP_INCQ: 920 921 case CC_OP_DECB: 922 case CC_OP_DECW: 923 case CC_OP_DECL: 924 case CC_OP_DECQ: 925 926 case CC_OP_SHLB: 927 case CC_OP_SHLW: 928 case CC_OP_SHLL: 929 case CC_OP_SHLQ: 930 if (jcc_op != JCC_Z && jcc_op != JCC_S) 931 goto slow_jcc; 932 break; 933 default: 934 slow_jcc: 935 return 0; 936 } 937 return 1; 938 } 939 940 /* generate a conditional jump to label 'l1' according to jump opcode 941 value 'b'. In the fast case, T0 is guaranted not to be used. */ 942 static inline void gen_jcc1(DisasContext *s, int cc_op, int b, int l1) 943 { 944 int inv, jcc_op, size, cond; 945 TCGv t0; 946 947 inv = b & 1; 948 jcc_op = (b >> 1) & 7; 949 950 switch(cc_op) { 951 /* we optimize the cmp/jcc case */ 952 case CC_OP_SUBB: 953 case CC_OP_SUBW: 954 case CC_OP_SUBL: 955 case CC_OP_SUBQ: 956 957 size = cc_op - CC_OP_SUBB; 958 switch(jcc_op) { 959 case JCC_Z: 960 fast_jcc_z: 961 switch(size) { 962 case 0: 963 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xff); 964 t0 = cpu_tmp0; 965 break; 966 case 1: 967 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffff); 968 t0 = cpu_tmp0; 969 break; 970 #ifdef TARGET_X86_64 971 case 2: 972 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffffffff); 973 t0 = cpu_tmp0; 974 break; 975 #endif 976 default: 977 t0 = cpu_cc_dst; 978 break; 979 } 980 tcg_gen_brcondi_tl(inv ? TCG_COND_NE : TCG_COND_EQ, t0, 0, l1); 981 break; 982 case JCC_S: 983 fast_jcc_s: 984 switch(size) { 985 case 0: 986 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80); 987 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, 988 0, l1); 989 break; 990 case 1: 991 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x8000); 992 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, 993 0, l1); 994 break; 995 #ifdef TARGET_X86_64 996 case 2: 997 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80000000); 998 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, 999 0, l1); 1000 break; 1001 #endif 1002 default: 1003 tcg_gen_brcondi_tl(inv ? TCG_COND_GE : TCG_COND_LT, cpu_cc_dst, 1004 0, l1); 1005 break; 1006 } 1007 break; 1008 1009 case JCC_B: 1010 cond = inv ? TCG_COND_GEU : TCG_COND_LTU; 1011 goto fast_jcc_b; 1012 case JCC_BE: 1013 cond = inv ? TCG_COND_GTU : TCG_COND_LEU; 1014 fast_jcc_b: 1015 tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src); 1016 switch(size) { 1017 case 0: 1018 t0 = cpu_tmp0; 1019 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xff); 1020 tcg_gen_andi_tl(t0, cpu_cc_src, 0xff); 1021 break; 1022 case 1: 1023 t0 = cpu_tmp0; 1024 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffff); 1025 tcg_gen_andi_tl(t0, cpu_cc_src, 0xffff); 1026 break; 1027 #ifdef TARGET_X86_64 1028 case 2: 1029 t0 = cpu_tmp0; 1030 tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffffffff); 1031 tcg_gen_andi_tl(t0, cpu_cc_src, 0xffffffff); 1032 break; 1033 #endif 1034 default: 1035 t0 = cpu_cc_src; 1036 break; 1037 } 1038 tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1); 1039 break; 1040 1041 case JCC_L: 1042 cond = inv ? TCG_COND_GE : TCG_COND_LT; 1043 goto fast_jcc_l; 1044 case JCC_LE: 1045 cond = inv ? TCG_COND_GT : TCG_COND_LE; 1046 fast_jcc_l: 1047 tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src); 1048 switch(size) { 1049 case 0: 1050 t0 = cpu_tmp0; 1051 tcg_gen_ext8s_tl(cpu_tmp4, cpu_tmp4); 1052 tcg_gen_ext8s_tl(t0, cpu_cc_src); 1053 break; 1054 case 1: 1055 t0 = cpu_tmp0; 1056 tcg_gen_ext16s_tl(cpu_tmp4, cpu_tmp4); 1057 tcg_gen_ext16s_tl(t0, cpu_cc_src); 1058 break; 1059 #ifdef TARGET_X86_64 1060 case 2: 1061 t0 = cpu_tmp0; 1062 tcg_gen_ext32s_tl(cpu_tmp4, cpu_tmp4); 1063 tcg_gen_ext32s_tl(t0, cpu_cc_src); 1064 break; 1065 #endif 1066 default: 1067 t0 = cpu_cc_src; 1068 break; 1069 } 1070 tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1); 1071 break; 1072 1073 default: 1074 goto slow_jcc; 1075 } 1076 break; 1077 1078 /* some jumps are easy to compute */ 1079 case CC_OP_ADDB: 1080 case CC_OP_ADDW: 1081 case CC_OP_ADDL: 1082 case CC_OP_ADDQ: 1083 1084 case CC_OP_ADCB: 1085 case CC_OP_ADCW: 1086 case CC_OP_ADCL: 1087 case CC_OP_ADCQ: 1088 1089 case CC_OP_SBBB: 1090 case CC_OP_SBBW: 1091 case CC_OP_SBBL: 1092 case CC_OP_SBBQ: 1093 1094 case CC_OP_LOGICB: 1095 case CC_OP_LOGICW: 1096 case CC_OP_LOGICL: 1097 case CC_OP_LOGICQ: 1098 1099 case CC_OP_INCB: 1100 case CC_OP_INCW: 1101 case CC_OP_INCL: 1102 case CC_OP_INCQ: 1103 1104 case CC_OP_DECB: 1105 case CC_OP_DECW: 1106 case CC_OP_DECL: 1107 case CC_OP_DECQ: 1108 1109 case CC_OP_SHLB: 1110 case CC_OP_SHLW: 1111 case CC_OP_SHLL: 1112 case CC_OP_SHLQ: 1113 1114 case CC_OP_SARB: 1115 case CC_OP_SARW: 1116 case CC_OP_SARL: 1117 case CC_OP_SARQ: 1118 switch(jcc_op) { 1119 case JCC_Z: 1120 size = (cc_op - CC_OP_ADDB) & 3; 1121 goto fast_jcc_z; 1122 case JCC_S: 1123 size = (cc_op - CC_OP_ADDB) & 3; 1124 goto fast_jcc_s; 1125 default: 1126 goto slow_jcc; 1127 } 1128 break; 1129 default: 1130 slow_jcc: 1131 gen_setcc_slow_T0(s, jcc_op); 1132 tcg_gen_brcondi_tl(inv ? TCG_COND_EQ : TCG_COND_NE, 1133 cpu_T[0], 0, l1); 1134 break; 1135 } 1136 } 1137 1138 /* XXX: does not work with gdbstub "ice" single step - not a 1139 serious problem */ 1140 static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) 1141 { 1142 int l1, l2; 1143 1144 l1 = gen_new_label(); 1145 l2 = gen_new_label(); 1146 gen_op_jnz_ecx(s->aflag, l1); 1147 gen_set_label(l2); 1148 gen_jmp_tb(s, next_eip, 1); 1149 gen_set_label(l1); 1150 return l2; 1151 } 1152 1153 static inline void gen_stos(DisasContext *s, int ot) 1154 { 1155 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); 1156 gen_string_movl_A0_EDI(s); 1157 gen_op_st_T0_A0(ot + s->mem_index); 1158 gen_op_movl_T0_Dshift(ot); 1159 gen_op_add_reg_T0(s->aflag, R_EDI); 1160 } 1161 1162 static inline void gen_lods(DisasContext *s, int ot) 1163 { 1164 gen_string_movl_A0_ESI(s); 1165 gen_op_ld_T0_A0(ot + s->mem_index); 1166 gen_op_mov_reg_T0(ot, R_EAX); 1167 gen_op_movl_T0_Dshift(ot); 1168 gen_op_add_reg_T0(s->aflag, R_ESI); 1169 } 1170 1171 static inline void gen_scas(DisasContext *s, int ot) 1172 { 1173 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); 1174 gen_string_movl_A0_EDI(s); 1175 gen_op_ld_T1_A0(ot + s->mem_index); 1176 gen_op_cmpl_T0_T1_cc(); 1177 gen_op_movl_T0_Dshift(ot); 1178 gen_op_add_reg_T0(s->aflag, R_EDI); 1179 } 1180 1181 static inline void gen_cmps(DisasContext *s, int ot) 1182 { 1183 gen_string_movl_A0_ESI(s); 1184 gen_op_ld_T0_A0(ot + s->mem_index); 1185 gen_string_movl_A0_EDI(s); 1186 gen_op_ld_T1_A0(ot + s->mem_index); 1187 gen_op_cmpl_T0_T1_cc(); 1188 gen_op_movl_T0_Dshift(ot); 1189 gen_op_add_reg_T0(s->aflag, R_ESI); 1190 gen_op_add_reg_T0(s->aflag, R_EDI); 1191 } 1192 1193 static inline void gen_ins(DisasContext *s, int ot) 1194 { 1195 if (use_icount) 1196 gen_io_start(); 1197 gen_string_movl_A0_EDI(s); 1198 /* Note: we must do this dummy write first to be restartable in 1199 case of page fault. */ 1200 gen_op_movl_T0_0(); 1201 gen_op_st_T0_A0(ot + s->mem_index); 1202 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX); 1203 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]); 1204 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); 1205 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32); 1206 gen_op_st_T0_A0(ot + s->mem_index); 1207 gen_op_movl_T0_Dshift(ot); 1208 gen_op_add_reg_T0(s->aflag, R_EDI); 1209 if (use_icount) 1210 gen_io_end(); 1211 } 1212 1213 static inline void gen_outs(DisasContext *s, int ot) 1214 { 1215 if (use_icount) 1216 gen_io_start(); 1217 gen_string_movl_A0_ESI(s); 1218 gen_op_ld_T0_A0(ot + s->mem_index); 1219 1220 gen_op_mov_TN_reg(OT_WORD, 1, R_EDX); 1221 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]); 1222 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); 1223 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]); 1224 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); 1225 1226 gen_op_movl_T0_Dshift(ot); 1227 gen_op_add_reg_T0(s->aflag, R_ESI); 1228 if (use_icount) 1229 gen_io_end(); 1230 } 1231 1232 /* same method as Valgrind : we generate jumps to current or next 1233 instruction */ 1234 #define GEN_REPZ(op) \ 1235 static inline void gen_repz_ ## op(DisasContext *s, int ot, \ 1236 target_ulong cur_eip, target_ulong next_eip) \ 1237 { \ 1238 int l2;\ 1239 gen_update_cc_op(s); \ 1240 l2 = gen_jz_ecx_string(s, next_eip); \ 1241 gen_ ## op(s, ot); \ 1242 gen_op_add_reg_im(s->aflag, R_ECX, -1); \ 1243 /* a loop would cause two single step exceptions if ECX = 1 \ 1244 before rep string_insn */ \ 1245 if (!s->jmp_opt) \ 1246 gen_op_jz_ecx(s->aflag, l2); \ 1247 gen_jmp(s, cur_eip); \ 1248 } 1249 1250 #define GEN_REPZ2(op) \ 1251 static inline void gen_repz_ ## op(DisasContext *s, int ot, \ 1252 target_ulong cur_eip, \ 1253 target_ulong next_eip, \ 1254 int nz) \ 1255 { \ 1256 int l2;\ 1257 gen_update_cc_op(s); \ 1258 l2 = gen_jz_ecx_string(s, next_eip); \ 1259 gen_ ## op(s, ot); \ 1260 gen_op_add_reg_im(s->aflag, R_ECX, -1); \ 1261 gen_op_set_cc_op(CC_OP_SUBB + ot); \ 1262 gen_jcc1(s, CC_OP_SUBB + ot, (JCC_Z << 1) | (nz ^ 1), l2); \ 1263 if (!s->jmp_opt) \ 1264 gen_op_jz_ecx(s->aflag, l2); \ 1265 gen_jmp(s, cur_eip); \ 1266 } 1267 1268 GEN_REPZ(movs) 1269 GEN_REPZ(stos) 1270 GEN_REPZ(lods) 1271 GEN_REPZ(ins) 1272 GEN_REPZ(outs) 1273 GEN_REPZ2(scas) 1274 GEN_REPZ2(cmps) 1275 1276 static void gen_helper_fp_arith_ST0_FT0(int op) 1277 { 1278 switch (op) { 1279 case 0: gen_helper_fadd_ST0_FT0(); break; 1280 case 1: gen_helper_fmul_ST0_FT0(); break; 1281 case 2: gen_helper_fcom_ST0_FT0(); break; 1282 case 3: gen_helper_fcom_ST0_FT0(); break; 1283 case 4: gen_helper_fsub_ST0_FT0(); break; 1284 case 5: gen_helper_fsubr_ST0_FT0(); break; 1285 case 6: gen_helper_fdiv_ST0_FT0(); break; 1286 case 7: gen_helper_fdivr_ST0_FT0(); break; 1287 } 1288 } 1289 1290 /* NOTE the exception in "r" op ordering */ 1291 static void gen_helper_fp_arith_STN_ST0(int op, int opreg) 1292 { 1293 TCGv_i32 tmp = tcg_const_i32(opreg); 1294 switch (op) { 1295 case 0: gen_helper_fadd_STN_ST0(tmp); break; 1296 case 1: gen_helper_fmul_STN_ST0(tmp); break; 1297 case 4: gen_helper_fsubr_STN_ST0(tmp); break; 1298 case 5: gen_helper_fsub_STN_ST0(tmp); break; 1299 case 6: gen_helper_fdivr_STN_ST0(tmp); break; 1300 case 7: gen_helper_fdiv_STN_ST0(tmp); break; 1301 } 1302 } 1303 1304 /* if d == OR_TMP0, it means memory operand (address in A0) */ 1305 static void gen_op(DisasContext *s1, int op, int ot, int d) 1306 { 1307 if (d != OR_TMP0) { 1308 gen_op_mov_TN_reg(ot, 0, d); 1309 } else { 1310 gen_op_ld_T0_A0(ot + s1->mem_index); 1311 } 1312 switch(op) { 1313 case OP_ADCL: 1314 if (s1->cc_op != CC_OP_DYNAMIC) 1315 gen_op_set_cc_op(s1->cc_op); 1316 gen_compute_eflags_c(cpu_tmp4); 1317 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1318 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4); 1319 if (d != OR_TMP0) 1320 gen_op_mov_reg_T0(ot, d); 1321 else 1322 gen_op_st_T0_A0(ot + s1->mem_index); 1323 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); 1324 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 1325 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4); 1326 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2); 1327 tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_ADDB + ot); 1328 s1->cc_op = CC_OP_DYNAMIC; 1329 break; 1330 case OP_SBBL: 1331 if (s1->cc_op != CC_OP_DYNAMIC) 1332 gen_op_set_cc_op(s1->cc_op); 1333 gen_compute_eflags_c(cpu_tmp4); 1334 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1335 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4); 1336 if (d != OR_TMP0) 1337 gen_op_mov_reg_T0(ot, d); 1338 else 1339 gen_op_st_T0_A0(ot + s1->mem_index); 1340 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); 1341 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 1342 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4); 1343 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2); 1344 tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_SUBB + ot); 1345 s1->cc_op = CC_OP_DYNAMIC; 1346 break; 1347 case OP_ADDL: 1348 gen_op_addl_T0_T1(); 1349 if (d != OR_TMP0) 1350 gen_op_mov_reg_T0(ot, d); 1351 else 1352 gen_op_st_T0_A0(ot + s1->mem_index); 1353 gen_op_update2_cc(); 1354 s1->cc_op = CC_OP_ADDB + ot; 1355 break; 1356 case OP_SUBL: 1357 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1358 if (d != OR_TMP0) 1359 gen_op_mov_reg_T0(ot, d); 1360 else 1361 gen_op_st_T0_A0(ot + s1->mem_index); 1362 gen_op_update2_cc(); 1363 s1->cc_op = CC_OP_SUBB + ot; 1364 break; 1365 default: 1366 case OP_ANDL: 1367 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1368 if (d != OR_TMP0) 1369 gen_op_mov_reg_T0(ot, d); 1370 else 1371 gen_op_st_T0_A0(ot + s1->mem_index); 1372 gen_op_update1_cc(); 1373 s1->cc_op = CC_OP_LOGICB + ot; 1374 break; 1375 case OP_ORL: 1376 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1377 if (d != OR_TMP0) 1378 gen_op_mov_reg_T0(ot, d); 1379 else 1380 gen_op_st_T0_A0(ot + s1->mem_index); 1381 gen_op_update1_cc(); 1382 s1->cc_op = CC_OP_LOGICB + ot; 1383 break; 1384 case OP_XORL: 1385 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1386 if (d != OR_TMP0) 1387 gen_op_mov_reg_T0(ot, d); 1388 else 1389 gen_op_st_T0_A0(ot + s1->mem_index); 1390 gen_op_update1_cc(); 1391 s1->cc_op = CC_OP_LOGICB + ot; 1392 break; 1393 case OP_CMPL: 1394 gen_op_cmpl_T0_T1_cc(); 1395 s1->cc_op = CC_OP_SUBB + ot; 1396 break; 1397 } 1398 } 1399 1400 /* if d == OR_TMP0, it means memory operand (address in A0) */ 1401 static void gen_inc(DisasContext *s1, int ot, int d, int c) 1402 { 1403 if (d != OR_TMP0) 1404 gen_op_mov_TN_reg(ot, 0, d); 1405 else 1406 gen_op_ld_T0_A0(ot + s1->mem_index); 1407 if (s1->cc_op != CC_OP_DYNAMIC) 1408 gen_op_set_cc_op(s1->cc_op); 1409 if (c > 0) { 1410 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1); 1411 s1->cc_op = CC_OP_INCB + ot; 1412 } else { 1413 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1); 1414 s1->cc_op = CC_OP_DECB + ot; 1415 } 1416 if (d != OR_TMP0) 1417 gen_op_mov_reg_T0(ot, d); 1418 else 1419 gen_op_st_T0_A0(ot + s1->mem_index); 1420 gen_compute_eflags_c(cpu_cc_src); 1421 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 1422 } 1423 1424 static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, 1425 int is_right, int is_arith) 1426 { 1427 target_ulong mask; 1428 int shift_label; 1429 TCGv t0, t1; 1430 1431 if (ot == OT_QUAD) 1432 mask = 0x3f; 1433 else 1434 mask = 0x1f; 1435 1436 /* load */ 1437 if (op1 == OR_TMP0) 1438 gen_op_ld_T0_A0(ot + s->mem_index); 1439 else 1440 gen_op_mov_TN_reg(ot, 0, op1); 1441 1442 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask); 1443 1444 tcg_gen_addi_tl(cpu_tmp5, cpu_T[1], -1); 1445 1446 if (is_right) { 1447 if (is_arith) { 1448 gen_exts(ot, cpu_T[0]); 1449 tcg_gen_sar_tl(cpu_T3, cpu_T[0], cpu_tmp5); 1450 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1451 } else { 1452 gen_extu(ot, cpu_T[0]); 1453 tcg_gen_shr_tl(cpu_T3, cpu_T[0], cpu_tmp5); 1454 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1455 } 1456 } else { 1457 tcg_gen_shl_tl(cpu_T3, cpu_T[0], cpu_tmp5); 1458 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 1459 } 1460 1461 /* store */ 1462 if (op1 == OR_TMP0) 1463 gen_op_st_T0_A0(ot + s->mem_index); 1464 else 1465 gen_op_mov_reg_T0(ot, op1); 1466 1467 /* update eflags if non zero shift */ 1468 if (s->cc_op != CC_OP_DYNAMIC) 1469 gen_op_set_cc_op(s->cc_op); 1470 1471 /* XXX: inefficient */ 1472 t0 = tcg_temp_local_new(); 1473 t1 = tcg_temp_local_new(); 1474 1475 tcg_gen_mov_tl(t0, cpu_T[0]); 1476 tcg_gen_mov_tl(t1, cpu_T3); 1477 1478 shift_label = gen_new_label(); 1479 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, shift_label); 1480 1481 tcg_gen_mov_tl(cpu_cc_src, t1); 1482 tcg_gen_mov_tl(cpu_cc_dst, t0); 1483 if (is_right) 1484 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot); 1485 else 1486 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot); 1487 1488 gen_set_label(shift_label); 1489 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 1490 1491 tcg_temp_free(t0); 1492 tcg_temp_free(t1); 1493 } 1494 1495 static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2, 1496 int is_right, int is_arith) 1497 { 1498 int mask; 1499 1500 if (ot == OT_QUAD) 1501 mask = 0x3f; 1502 else 1503 mask = 0x1f; 1504 1505 /* load */ 1506 if (op1 == OR_TMP0) 1507 gen_op_ld_T0_A0(ot + s->mem_index); 1508 else 1509 gen_op_mov_TN_reg(ot, 0, op1); 1510 1511 op2 &= mask; 1512 if (op2 != 0) { 1513 if (is_right) { 1514 if (is_arith) { 1515 gen_exts(ot, cpu_T[0]); 1516 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1); 1517 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2); 1518 } else { 1519 gen_extu(ot, cpu_T[0]); 1520 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1); 1521 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2); 1522 } 1523 } else { 1524 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1); 1525 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2); 1526 } 1527 } 1528 1529 /* store */ 1530 if (op1 == OR_TMP0) 1531 gen_op_st_T0_A0(ot + s->mem_index); 1532 else 1533 gen_op_mov_reg_T0(ot, op1); 1534 1535 /* update eflags if non zero shift */ 1536 if (op2 != 0) { 1537 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4); 1538 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 1539 if (is_right) 1540 s->cc_op = CC_OP_SARB + ot; 1541 else 1542 s->cc_op = CC_OP_SHLB + ot; 1543 } 1544 } 1545 1546 static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2) 1547 { 1548 if (arg2 >= 0) 1549 tcg_gen_shli_tl(ret, arg1, arg2); 1550 else 1551 tcg_gen_shri_tl(ret, arg1, -arg2); 1552 } 1553 1554 static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, 1555 int is_right) 1556 { 1557 target_ulong mask; 1558 int label1, label2, data_bits; 1559 TCGv t0, t1, t2, a0; 1560 1561 /* XXX: inefficient, but we must use local temps */ 1562 t0 = tcg_temp_local_new(); 1563 t1 = tcg_temp_local_new(); 1564 t2 = tcg_temp_local_new(); 1565 a0 = tcg_temp_local_new(); 1566 1567 if (ot == OT_QUAD) 1568 mask = 0x3f; 1569 else 1570 mask = 0x1f; 1571 1572 /* load */ 1573 if (op1 == OR_TMP0) { 1574 tcg_gen_mov_tl(a0, cpu_A0); 1575 gen_op_ld_v(ot + s->mem_index, t0, a0); 1576 } else { 1577 gen_op_mov_v_reg(ot, t0, op1); 1578 } 1579 1580 tcg_gen_mov_tl(t1, cpu_T[1]); 1581 1582 tcg_gen_andi_tl(t1, t1, mask); 1583 1584 /* Must test zero case to avoid using undefined behaviour in TCG 1585 shifts. */ 1586 label1 = gen_new_label(); 1587 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label1); 1588 1589 if (ot <= OT_WORD) 1590 tcg_gen_andi_tl(cpu_tmp0, t1, (1 << (3 + ot)) - 1); 1591 else 1592 tcg_gen_mov_tl(cpu_tmp0, t1); 1593 1594 gen_extu(ot, t0); 1595 tcg_gen_mov_tl(t2, t0); 1596 1597 data_bits = 8 << ot; 1598 /* XXX: rely on behaviour of shifts when operand 2 overflows (XXX: 1599 fix TCG definition) */ 1600 if (is_right) { 1601 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp0); 1602 tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(data_bits), cpu_tmp0); 1603 tcg_gen_shl_tl(t0, t0, cpu_tmp0); 1604 } else { 1605 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp0); 1606 tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(data_bits), cpu_tmp0); 1607 tcg_gen_shr_tl(t0, t0, cpu_tmp0); 1608 } 1609 tcg_gen_or_tl(t0, t0, cpu_tmp4); 1610 1611 gen_set_label(label1); 1612 /* store */ 1613 if (op1 == OR_TMP0) { 1614 gen_op_st_v(ot + s->mem_index, t0, a0); 1615 } else { 1616 gen_op_mov_reg_v(ot, op1, t0); 1617 } 1618 1619 /* update eflags */ 1620 if (s->cc_op != CC_OP_DYNAMIC) 1621 gen_op_set_cc_op(s->cc_op); 1622 1623 label2 = gen_new_label(); 1624 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, label2); 1625 1626 gen_compute_eflags(cpu_cc_src); 1627 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C)); 1628 tcg_gen_xor_tl(cpu_tmp0, t2, t0); 1629 tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1)); 1630 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O); 1631 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0); 1632 if (is_right) { 1633 tcg_gen_shri_tl(t0, t0, data_bits - 1); 1634 } 1635 tcg_gen_andi_tl(t0, t0, CC_C); 1636 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0); 1637 1638 tcg_gen_discard_tl(cpu_cc_dst); 1639 tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS); 1640 1641 gen_set_label(label2); 1642 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 1643 1644 tcg_temp_free(t0); 1645 tcg_temp_free(t1); 1646 tcg_temp_free(t2); 1647 tcg_temp_free(a0); 1648 } 1649 1650 static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2, 1651 int is_right) 1652 { 1653 int mask; 1654 int data_bits; 1655 TCGv t0, t1, a0; 1656 1657 /* XXX: inefficient, but we must use local temps */ 1658 t0 = tcg_temp_local_new(); 1659 t1 = tcg_temp_local_new(); 1660 a0 = tcg_temp_local_new(); 1661 1662 if (ot == OT_QUAD) 1663 mask = 0x3f; 1664 else 1665 mask = 0x1f; 1666 1667 /* load */ 1668 if (op1 == OR_TMP0) { 1669 tcg_gen_mov_tl(a0, cpu_A0); 1670 gen_op_ld_v(ot + s->mem_index, t0, a0); 1671 } else { 1672 gen_op_mov_v_reg(ot, t0, op1); 1673 } 1674 1675 gen_extu(ot, t0); 1676 tcg_gen_mov_tl(t1, t0); 1677 1678 op2 &= mask; 1679 data_bits = 8 << ot; 1680 if (op2 != 0) { 1681 int shift = op2 & ((1 << (3 + ot)) - 1); 1682 if (is_right) { 1683 tcg_gen_shri_tl(cpu_tmp4, t0, shift); 1684 tcg_gen_shli_tl(t0, t0, data_bits - shift); 1685 } 1686 else { 1687 tcg_gen_shli_tl(cpu_tmp4, t0, shift); 1688 tcg_gen_shri_tl(t0, t0, data_bits - shift); 1689 } 1690 tcg_gen_or_tl(t0, t0, cpu_tmp4); 1691 } 1692 1693 /* store */ 1694 if (op1 == OR_TMP0) { 1695 gen_op_st_v(ot + s->mem_index, t0, a0); 1696 } else { 1697 gen_op_mov_reg_v(ot, op1, t0); 1698 } 1699 1700 if (op2 != 0) { 1701 /* update eflags */ 1702 if (s->cc_op != CC_OP_DYNAMIC) 1703 gen_op_set_cc_op(s->cc_op); 1704 1705 gen_compute_eflags(cpu_cc_src); 1706 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C)); 1707 tcg_gen_xor_tl(cpu_tmp0, t1, t0); 1708 tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1)); 1709 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O); 1710 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0); 1711 if (is_right) { 1712 tcg_gen_shri_tl(t0, t0, data_bits - 1); 1713 } 1714 tcg_gen_andi_tl(t0, t0, CC_C); 1715 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0); 1716 1717 tcg_gen_discard_tl(cpu_cc_dst); 1718 tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS); 1719 s->cc_op = CC_OP_EFLAGS; 1720 } 1721 1722 tcg_temp_free(t0); 1723 tcg_temp_free(t1); 1724 tcg_temp_free(a0); 1725 } 1726 1727 /* XXX: add faster immediate = 1 case */ 1728 static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1, 1729 int is_right) 1730 { 1731 int label1; 1732 1733 if (s->cc_op != CC_OP_DYNAMIC) 1734 gen_op_set_cc_op(s->cc_op); 1735 1736 /* load */ 1737 if (op1 == OR_TMP0) 1738 gen_op_ld_T0_A0(ot + s->mem_index); 1739 else 1740 gen_op_mov_TN_reg(ot, 0, op1); 1741 1742 if (is_right) { 1743 switch (ot) { 1744 case 0: gen_helper_rcrb(cpu_T[0], cpu_T[0], cpu_T[1]); break; 1745 case 1: gen_helper_rcrw(cpu_T[0], cpu_T[0], cpu_T[1]); break; 1746 case 2: gen_helper_rcrl(cpu_T[0], cpu_T[0], cpu_T[1]); break; 1747 #ifdef TARGET_X86_64 1748 case 3: gen_helper_rcrq(cpu_T[0], cpu_T[0], cpu_T[1]); break; 1749 #endif 1750 } 1751 } else { 1752 switch (ot) { 1753 case 0: gen_helper_rclb(cpu_T[0], cpu_T[0], cpu_T[1]); break; 1754 case 1: gen_helper_rclw(cpu_T[0], cpu_T[0], cpu_T[1]); break; 1755 case 2: gen_helper_rcll(cpu_T[0], cpu_T[0], cpu_T[1]); break; 1756 #ifdef TARGET_X86_64 1757 case 3: gen_helper_rclq(cpu_T[0], cpu_T[0], cpu_T[1]); break; 1758 #endif 1759 } 1760 } 1761 /* store */ 1762 if (op1 == OR_TMP0) 1763 gen_op_st_T0_A0(ot + s->mem_index); 1764 else 1765 gen_op_mov_reg_T0(ot, op1); 1766 1767 /* update eflags */ 1768 label1 = gen_new_label(); 1769 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cc_tmp, -1, label1); 1770 1771 tcg_gen_mov_tl(cpu_cc_src, cpu_cc_tmp); 1772 tcg_gen_discard_tl(cpu_cc_dst); 1773 tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS); 1774 1775 gen_set_label(label1); 1776 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 1777 } 1778 1779 /* XXX: add faster immediate case */ 1780 static void gen_shiftd_rm_T1_T3(DisasContext *s, int ot, int op1, 1781 int is_right) 1782 { 1783 int label1, label2, data_bits; 1784 target_ulong mask; 1785 TCGv t0, t1, t2, a0; 1786 1787 t0 = tcg_temp_local_new(); 1788 t1 = tcg_temp_local_new(); 1789 t2 = tcg_temp_local_new(); 1790 a0 = tcg_temp_local_new(); 1791 1792 if (ot == OT_QUAD) 1793 mask = 0x3f; 1794 else 1795 mask = 0x1f; 1796 1797 /* load */ 1798 if (op1 == OR_TMP0) { 1799 tcg_gen_mov_tl(a0, cpu_A0); 1800 gen_op_ld_v(ot + s->mem_index, t0, a0); 1801 } else { 1802 gen_op_mov_v_reg(ot, t0, op1); 1803 } 1804 1805 tcg_gen_andi_tl(cpu_T3, cpu_T3, mask); 1806 1807 tcg_gen_mov_tl(t1, cpu_T[1]); 1808 tcg_gen_mov_tl(t2, cpu_T3); 1809 1810 /* Must test zero case to avoid using undefined behaviour in TCG 1811 shifts. */ 1812 label1 = gen_new_label(); 1813 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1); 1814 1815 tcg_gen_addi_tl(cpu_tmp5, t2, -1); 1816 if (ot == OT_WORD) { 1817 /* Note: we implement the Intel behaviour for shift count > 16 */ 1818 if (is_right) { 1819 tcg_gen_andi_tl(t0, t0, 0xffff); 1820 tcg_gen_shli_tl(cpu_tmp0, t1, 16); 1821 tcg_gen_or_tl(t0, t0, cpu_tmp0); 1822 tcg_gen_ext32u_tl(t0, t0); 1823 1824 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5); 1825 1826 /* only needed if count > 16, but a test would complicate */ 1827 tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(32), t2); 1828 tcg_gen_shl_tl(cpu_tmp0, t0, cpu_tmp5); 1829 1830 tcg_gen_shr_tl(t0, t0, t2); 1831 1832 tcg_gen_or_tl(t0, t0, cpu_tmp0); 1833 } else { 1834 /* XXX: not optimal */ 1835 tcg_gen_andi_tl(t0, t0, 0xffff); 1836 tcg_gen_shli_tl(t1, t1, 16); 1837 tcg_gen_or_tl(t1, t1, t0); 1838 tcg_gen_ext32u_tl(t1, t1); 1839 1840 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5); 1841 tcg_gen_sub_tl(cpu_tmp0, tcg_const_tl(32), cpu_tmp5); 1842 tcg_gen_shr_tl(cpu_tmp6, t1, cpu_tmp0); 1843 tcg_gen_or_tl(cpu_tmp4, cpu_tmp4, cpu_tmp6); 1844 1845 tcg_gen_shl_tl(t0, t0, t2); 1846 tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(32), t2); 1847 tcg_gen_shr_tl(t1, t1, cpu_tmp5); 1848 tcg_gen_or_tl(t0, t0, t1); 1849 } 1850 } else { 1851 data_bits = 8 << ot; 1852 if (is_right) { 1853 if (ot == OT_LONG) 1854 tcg_gen_ext32u_tl(t0, t0); 1855 1856 tcg_gen_shr_tl(cpu_tmp4, t0, cpu_tmp5); 1857 1858 tcg_gen_shr_tl(t0, t0, t2); 1859 tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(data_bits), t2); 1860 tcg_gen_shl_tl(t1, t1, cpu_tmp5); 1861 tcg_gen_or_tl(t0, t0, t1); 1862 1863 } else { 1864 if (ot == OT_LONG) 1865 tcg_gen_ext32u_tl(t1, t1); 1866 1867 tcg_gen_shl_tl(cpu_tmp4, t0, cpu_tmp5); 1868 1869 tcg_gen_shl_tl(t0, t0, t2); 1870 tcg_gen_sub_tl(cpu_tmp5, tcg_const_tl(data_bits), t2); 1871 tcg_gen_shr_tl(t1, t1, cpu_tmp5); 1872 tcg_gen_or_tl(t0, t0, t1); 1873 } 1874 } 1875 tcg_gen_mov_tl(t1, cpu_tmp4); 1876 1877 gen_set_label(label1); 1878 /* store */ 1879 if (op1 == OR_TMP0) { 1880 gen_op_st_v(ot + s->mem_index, t0, a0); 1881 } else { 1882 gen_op_mov_reg_v(ot, op1, t0); 1883 } 1884 1885 /* update eflags */ 1886 if (s->cc_op != CC_OP_DYNAMIC) 1887 gen_op_set_cc_op(s->cc_op); 1888 1889 label2 = gen_new_label(); 1890 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label2); 1891 1892 tcg_gen_mov_tl(cpu_cc_src, t1); 1893 tcg_gen_mov_tl(cpu_cc_dst, t0); 1894 if (is_right) { 1895 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SARB + ot); 1896 } else { 1897 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SHLB + ot); 1898 } 1899 gen_set_label(label2); 1900 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 1901 1902 tcg_temp_free(t0); 1903 tcg_temp_free(t1); 1904 tcg_temp_free(t2); 1905 tcg_temp_free(a0); 1906 } 1907 1908 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) 1909 { 1910 if (s != OR_TMP1) 1911 gen_op_mov_TN_reg(ot, 1, s); 1912 switch(op) { 1913 case OP_ROL: 1914 gen_rot_rm_T1(s1, ot, d, 0); 1915 break; 1916 case OP_ROR: 1917 gen_rot_rm_T1(s1, ot, d, 1); 1918 break; 1919 case OP_SHL: 1920 case OP_SHL1: 1921 gen_shift_rm_T1(s1, ot, d, 0, 0); 1922 break; 1923 case OP_SHR: 1924 gen_shift_rm_T1(s1, ot, d, 1, 0); 1925 break; 1926 case OP_SAR: 1927 gen_shift_rm_T1(s1, ot, d, 1, 1); 1928 break; 1929 case OP_RCL: 1930 gen_rotc_rm_T1(s1, ot, d, 0); 1931 break; 1932 case OP_RCR: 1933 gen_rotc_rm_T1(s1, ot, d, 1); 1934 break; 1935 } 1936 } 1937 1938 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c) 1939 { 1940 switch(op) { 1941 case OP_ROL: 1942 gen_rot_rm_im(s1, ot, d, c, 0); 1943 break; 1944 case OP_ROR: 1945 gen_rot_rm_im(s1, ot, d, c, 1); 1946 break; 1947 case OP_SHL: 1948 case OP_SHL1: 1949 gen_shift_rm_im(s1, ot, d, c, 0, 0); 1950 break; 1951 case OP_SHR: 1952 gen_shift_rm_im(s1, ot, d, c, 1, 0); 1953 break; 1954 case OP_SAR: 1955 gen_shift_rm_im(s1, ot, d, c, 1, 1); 1956 break; 1957 default: 1958 /* currently not optimized */ 1959 gen_op_movl_T1_im(c); 1960 gen_shift(s1, op, ot, d, OR_TMP1); 1961 break; 1962 } 1963 } 1964 1965 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr) 1966 { 1967 target_long disp; 1968 int havesib; 1969 int base; 1970 int index; 1971 int scale; 1972 int opreg; 1973 int mod, rm, code, override, must_add_seg; 1974 1975 override = s->override; 1976 must_add_seg = s->addseg; 1977 if (override >= 0) 1978 must_add_seg = 1; 1979 mod = (modrm >> 6) & 3; 1980 rm = modrm & 7; 1981 1982 if (s->aflag) { 1983 1984 havesib = 0; 1985 base = rm; 1986 index = 0; 1987 scale = 0; 1988 1989 if (base == 4) { 1990 havesib = 1; 1991 code = ldub_code(s->pc++); 1992 scale = (code >> 6) & 3; 1993 index = ((code >> 3) & 7) | REX_X(s); 1994 base = (code & 7); 1995 } 1996 base |= REX_B(s); 1997 1998 switch (mod) { 1999 case 0: 2000 if ((base & 7) == 5) { 2001 base = -1; 2002 disp = (int32_t)ldl_code(s->pc); 2003 s->pc += 4; 2004 if (CODE64(s) && !havesib) { 2005 disp += s->pc + s->rip_offset; 2006 } 2007 } else { 2008 disp = 0; 2009 } 2010 break; 2011 case 1: 2012 disp = (int8_t)ldub_code(s->pc++); 2013 break; 2014 default: 2015 case 2: 2016 disp = ldl_code(s->pc); 2017 s->pc += 4; 2018 break; 2019 } 2020 2021 if (base >= 0) { 2022 /* for correct popl handling with esp */ 2023 if (base == 4 && s->popl_esp_hack) 2024 disp += s->popl_esp_hack; 2025 #ifdef TARGET_X86_64 2026 if (s->aflag == 2) { 2027 gen_op_movq_A0_reg(base); 2028 if (disp != 0) { 2029 gen_op_addq_A0_im(disp); 2030 } 2031 } else 2032 #endif 2033 { 2034 gen_op_movl_A0_reg(base); 2035 if (disp != 0) 2036 gen_op_addl_A0_im(disp); 2037 } 2038 } else { 2039 #ifdef TARGET_X86_64 2040 if (s->aflag == 2) { 2041 gen_op_movq_A0_im(disp); 2042 } else 2043 #endif 2044 { 2045 gen_op_movl_A0_im(disp); 2046 } 2047 } 2048 /* XXX: index == 4 is always invalid */ 2049 if (havesib && (index != 4 || scale != 0)) { 2050 #ifdef TARGET_X86_64 2051 if (s->aflag == 2) { 2052 gen_op_addq_A0_reg_sN(scale, index); 2053 } else 2054 #endif 2055 { 2056 gen_op_addl_A0_reg_sN(scale, index); 2057 } 2058 } 2059 if (must_add_seg) { 2060 if (override < 0) { 2061 if (base == R_EBP || base == R_ESP) 2062 override = R_SS; 2063 else 2064 override = R_DS; 2065 } 2066 #ifdef TARGET_X86_64 2067 if (s->aflag == 2) { 2068 gen_op_addq_A0_seg(override); 2069 } else 2070 #endif 2071 { 2072 gen_op_addl_A0_seg(override); 2073 } 2074 } 2075 } else { 2076 switch (mod) { 2077 case 0: 2078 if (rm == 6) { 2079 disp = lduw_code(s->pc); 2080 s->pc += 2; 2081 gen_op_movl_A0_im(disp); 2082 rm = 0; /* avoid SS override */ 2083 goto no_rm; 2084 } else { 2085 disp = 0; 2086 } 2087 break; 2088 case 1: 2089 disp = (int8_t)ldub_code(s->pc++); 2090 break; 2091 default: 2092 case 2: 2093 disp = lduw_code(s->pc); 2094 s->pc += 2; 2095 break; 2096 } 2097 switch(rm) { 2098 case 0: 2099 gen_op_movl_A0_reg(R_EBX); 2100 gen_op_addl_A0_reg_sN(0, R_ESI); 2101 break; 2102 case 1: 2103 gen_op_movl_A0_reg(R_EBX); 2104 gen_op_addl_A0_reg_sN(0, R_EDI); 2105 break; 2106 case 2: 2107 gen_op_movl_A0_reg(R_EBP); 2108 gen_op_addl_A0_reg_sN(0, R_ESI); 2109 break; 2110 case 3: 2111 gen_op_movl_A0_reg(R_EBP); 2112 gen_op_addl_A0_reg_sN(0, R_EDI); 2113 break; 2114 case 4: 2115 gen_op_movl_A0_reg(R_ESI); 2116 break; 2117 case 5: 2118 gen_op_movl_A0_reg(R_EDI); 2119 break; 2120 case 6: 2121 gen_op_movl_A0_reg(R_EBP); 2122 break; 2123 default: 2124 case 7: 2125 gen_op_movl_A0_reg(R_EBX); 2126 break; 2127 } 2128 if (disp != 0) 2129 gen_op_addl_A0_im(disp); 2130 gen_op_andl_A0_ffff(); 2131 no_rm: 2132 if (must_add_seg) { 2133 if (override < 0) { 2134 if (rm == 2 || rm == 3 || rm == 6) 2135 override = R_SS; 2136 else 2137 override = R_DS; 2138 } 2139 gen_op_addl_A0_seg(override); 2140 } 2141 } 2142 2143 opreg = OR_A0; 2144 disp = 0; 2145 *reg_ptr = opreg; 2146 *offset_ptr = disp; 2147 } 2148 2149 static void gen_nop_modrm(DisasContext *s, int modrm) 2150 { 2151 int mod, rm, base, code; 2152 2153 mod = (modrm >> 6) & 3; 2154 if (mod == 3) 2155 return; 2156 rm = modrm & 7; 2157 2158 if (s->aflag) { 2159 2160 base = rm; 2161 2162 if (base == 4) { 2163 code = ldub_code(s->pc++); 2164 base = (code & 7); 2165 } 2166 2167 switch (mod) { 2168 case 0: 2169 if (base == 5) { 2170 s->pc += 4; 2171 } 2172 break; 2173 case 1: 2174 s->pc++; 2175 break; 2176 default: 2177 case 2: 2178 s->pc += 4; 2179 break; 2180 } 2181 } else { 2182 switch (mod) { 2183 case 0: 2184 if (rm == 6) { 2185 s->pc += 2; 2186 } 2187 break; 2188 case 1: 2189 s->pc++; 2190 break; 2191 default: 2192 case 2: 2193 s->pc += 2; 2194 break; 2195 } 2196 } 2197 } 2198 2199 /* used for LEA and MOV AX, mem */ 2200 static void gen_add_A0_ds_seg(DisasContext *s) 2201 { 2202 int override, must_add_seg; 2203 must_add_seg = s->addseg; 2204 override = R_DS; 2205 if (s->override >= 0) { 2206 override = s->override; 2207 must_add_seg = 1; 2208 } else { 2209 override = R_DS; 2210 } 2211 if (must_add_seg) { 2212 #ifdef TARGET_X86_64 2213 if (CODE64(s)) { 2214 gen_op_addq_A0_seg(override); 2215 } else 2216 #endif 2217 { 2218 gen_op_addl_A0_seg(override); 2219 } 2220 } 2221 } 2222 2223 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg == 2224 OR_TMP0 */ 2225 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store) 2226 { 2227 int mod, rm, opreg, disp; 2228 2229 mod = (modrm >> 6) & 3; 2230 rm = (modrm & 7) | REX_B(s); 2231 if (mod == 3) { 2232 if (is_store) { 2233 if (reg != OR_TMP0) 2234 gen_op_mov_TN_reg(ot, 0, reg); 2235 gen_op_mov_reg_T0(ot, rm); 2236 } else { 2237 gen_op_mov_TN_reg(ot, 0, rm); 2238 if (reg != OR_TMP0) 2239 gen_op_mov_reg_T0(ot, reg); 2240 } 2241 } else { 2242 gen_lea_modrm(s, modrm, &opreg, &disp); 2243 if (is_store) { 2244 if (reg != OR_TMP0) 2245 gen_op_mov_TN_reg(ot, 0, reg); 2246 gen_op_st_T0_A0(ot + s->mem_index); 2247 } else { 2248 gen_op_ld_T0_A0(ot + s->mem_index); 2249 if (reg != OR_TMP0) 2250 gen_op_mov_reg_T0(ot, reg); 2251 } 2252 } 2253 } 2254 2255 static inline uint32_t insn_get(DisasContext *s, int ot) 2256 { 2257 uint32_t ret; 2258 2259 switch(ot) { 2260 case OT_BYTE: 2261 ret = ldub_code(s->pc); 2262 s->pc++; 2263 break; 2264 case OT_WORD: 2265 ret = lduw_code(s->pc); 2266 s->pc += 2; 2267 break; 2268 default: 2269 case OT_LONG: 2270 ret = ldl_code(s->pc); 2271 s->pc += 4; 2272 break; 2273 } 2274 return ret; 2275 } 2276 2277 static inline int insn_const_size(unsigned int ot) 2278 { 2279 if (ot <= OT_LONG) 2280 return 1 << ot; 2281 else 2282 return 4; 2283 } 2284 2285 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) 2286 { 2287 TranslationBlock *tb; 2288 target_ulong pc; 2289 2290 pc = s->cs_base + eip; 2291 tb = s->tb; 2292 /* NOTE: we handle the case where the TB spans two pages here */ 2293 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) || 2294 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) { 2295 /* jump to same page: we can use a direct jump */ 2296 tcg_gen_goto_tb(tb_num); 2297 gen_jmp_im(eip); 2298 tcg_gen_exit_tb((long)tb + tb_num); 2299 } else { 2300 /* jump to another page: currently not optimized */ 2301 gen_jmp_im(eip); 2302 gen_eob(s); 2303 } 2304 } 2305 2306 static inline void gen_jcc(DisasContext *s, int b, 2307 target_ulong val, target_ulong next_eip) 2308 { 2309 int l1, l2, cc_op; 2310 2311 cc_op = s->cc_op; 2312 if (s->cc_op != CC_OP_DYNAMIC) { 2313 gen_op_set_cc_op(s->cc_op); 2314 s->cc_op = CC_OP_DYNAMIC; 2315 } 2316 if (s->jmp_opt) { 2317 l1 = gen_new_label(); 2318 gen_jcc1(s, cc_op, b, l1); 2319 2320 gen_goto_tb(s, 0, next_eip); 2321 2322 gen_set_label(l1); 2323 gen_goto_tb(s, 1, val); 2324 s->is_jmp = 3; 2325 } else { 2326 2327 l1 = gen_new_label(); 2328 l2 = gen_new_label(); 2329 gen_jcc1(s, cc_op, b, l1); 2330 2331 gen_jmp_im(next_eip); 2332 tcg_gen_br(l2); 2333 2334 gen_set_label(l1); 2335 gen_jmp_im(val); 2336 gen_set_label(l2); 2337 gen_eob(s); 2338 } 2339 } 2340 2341 static void gen_setcc(DisasContext *s, int b) 2342 { 2343 int inv, jcc_op, l1; 2344 TCGv t0; 2345 2346 if (is_fast_jcc_case(s, b)) { 2347 /* nominal case: we use a jump */ 2348 /* XXX: make it faster by adding new instructions in TCG */ 2349 t0 = tcg_temp_local_new(); 2350 tcg_gen_movi_tl(t0, 0); 2351 l1 = gen_new_label(); 2352 gen_jcc1(s, s->cc_op, b ^ 1, l1); 2353 tcg_gen_movi_tl(t0, 1); 2354 gen_set_label(l1); 2355 tcg_gen_mov_tl(cpu_T[0], t0); 2356 tcg_temp_free(t0); 2357 } else { 2358 /* slow case: it is more efficient not to generate a jump, 2359 although it is questionnable whether this optimization is 2360 worth to */ 2361 inv = b & 1; 2362 jcc_op = (b >> 1) & 7; 2363 gen_setcc_slow_T0(s, jcc_op); 2364 if (inv) { 2365 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1); 2366 } 2367 } 2368 } 2369 2370 static inline void gen_op_movl_T0_seg(int seg_reg) 2371 { 2372 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 2373 offsetof(CPUX86State,segs[seg_reg].selector)); 2374 } 2375 2376 static inline void gen_op_movl_seg_T0_vm(int seg_reg) 2377 { 2378 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff); 2379 tcg_gen_st32_tl(cpu_T[0], cpu_env, 2380 offsetof(CPUX86State,segs[seg_reg].selector)); 2381 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4); 2382 tcg_gen_st_tl(cpu_T[0], cpu_env, 2383 offsetof(CPUX86State,segs[seg_reg].base)); 2384 } 2385 2386 /* move T0 to seg_reg and compute if the CPU state may change. Never 2387 call this function with seg_reg == R_CS */ 2388 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip) 2389 { 2390 if (s->pe && !s->vm86) { 2391 /* XXX: optimize by finding processor state dynamically */ 2392 if (s->cc_op != CC_OP_DYNAMIC) 2393 gen_op_set_cc_op(s->cc_op); 2394 gen_jmp_im(cur_eip); 2395 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 2396 gen_helper_load_seg(tcg_const_i32(seg_reg), cpu_tmp2_i32); 2397 /* abort translation because the addseg value may change or 2398 because ss32 may change. For R_SS, translation must always 2399 stop as a special handling must be done to disable hardware 2400 interrupts for the next instruction */ 2401 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) 2402 s->is_jmp = 3; 2403 } else { 2404 gen_op_movl_seg_T0_vm(seg_reg); 2405 if (seg_reg == R_SS) 2406 s->is_jmp = 3; 2407 } 2408 } 2409 2410 static inline int svm_is_rep(int prefixes) 2411 { 2412 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0); 2413 } 2414 2415 static inline void 2416 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, 2417 uint32_t type, uint64_t param) 2418 { 2419 /* no SVM activated; fast case */ 2420 if (likely(!(s->flags & HF_SVMI_MASK))) 2421 return; 2422 if (s->cc_op != CC_OP_DYNAMIC) 2423 gen_op_set_cc_op(s->cc_op); 2424 gen_jmp_im(pc_start - s->cs_base); 2425 gen_helper_svm_check_intercept_param(tcg_const_i32(type), 2426 tcg_const_i64(param)); 2427 } 2428 2429 static inline void 2430 gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type) 2431 { 2432 gen_svm_check_intercept_param(s, pc_start, type, 0); 2433 } 2434 2435 static inline void gen_stack_update(DisasContext *s, int addend) 2436 { 2437 #ifdef TARGET_X86_64 2438 if (CODE64(s)) { 2439 gen_op_add_reg_im(2, R_ESP, addend); 2440 } else 2441 #endif 2442 if (s->ss32) { 2443 gen_op_add_reg_im(1, R_ESP, addend); 2444 } else { 2445 gen_op_add_reg_im(0, R_ESP, addend); 2446 } 2447 } 2448 2449 /* generate a push. It depends on ss32, addseg and dflag */ 2450 static void gen_push_T0(DisasContext *s) 2451 { 2452 #ifdef TARGET_X86_64 2453 if (CODE64(s)) { 2454 gen_op_movq_A0_reg(R_ESP); 2455 if (s->dflag) { 2456 gen_op_addq_A0_im(-8); 2457 gen_op_st_T0_A0(OT_QUAD + s->mem_index); 2458 } else { 2459 gen_op_addq_A0_im(-2); 2460 gen_op_st_T0_A0(OT_WORD + s->mem_index); 2461 } 2462 gen_op_mov_reg_A0(2, R_ESP); 2463 } else 2464 #endif 2465 { 2466 gen_op_movl_A0_reg(R_ESP); 2467 if (!s->dflag) 2468 gen_op_addl_A0_im(-2); 2469 else 2470 gen_op_addl_A0_im(-4); 2471 if (s->ss32) { 2472 if (s->addseg) { 2473 tcg_gen_mov_tl(cpu_T[1], cpu_A0); 2474 gen_op_addl_A0_seg(R_SS); 2475 } 2476 } else { 2477 gen_op_andl_A0_ffff(); 2478 tcg_gen_mov_tl(cpu_T[1], cpu_A0); 2479 gen_op_addl_A0_seg(R_SS); 2480 } 2481 gen_op_st_T0_A0(s->dflag + 1 + s->mem_index); 2482 if (s->ss32 && !s->addseg) 2483 gen_op_mov_reg_A0(1, R_ESP); 2484 else 2485 gen_op_mov_reg_T1(s->ss32 + 1, R_ESP); 2486 } 2487 } 2488 2489 /* generate a push. It depends on ss32, addseg and dflag */ 2490 /* slower version for T1, only used for call Ev */ 2491 static void gen_push_T1(DisasContext *s) 2492 { 2493 #ifdef TARGET_X86_64 2494 if (CODE64(s)) { 2495 gen_op_movq_A0_reg(R_ESP); 2496 if (s->dflag) { 2497 gen_op_addq_A0_im(-8); 2498 gen_op_st_T1_A0(OT_QUAD + s->mem_index); 2499 } else { 2500 gen_op_addq_A0_im(-2); 2501 gen_op_st_T0_A0(OT_WORD + s->mem_index); 2502 } 2503 gen_op_mov_reg_A0(2, R_ESP); 2504 } else 2505 #endif 2506 { 2507 gen_op_movl_A0_reg(R_ESP); 2508 if (!s->dflag) 2509 gen_op_addl_A0_im(-2); 2510 else 2511 gen_op_addl_A0_im(-4); 2512 if (s->ss32) { 2513 if (s->addseg) { 2514 gen_op_addl_A0_seg(R_SS); 2515 } 2516 } else { 2517 gen_op_andl_A0_ffff(); 2518 gen_op_addl_A0_seg(R_SS); 2519 } 2520 gen_op_st_T1_A0(s->dflag + 1 + s->mem_index); 2521 2522 if (s->ss32 && !s->addseg) 2523 gen_op_mov_reg_A0(1, R_ESP); 2524 else 2525 gen_stack_update(s, (-2) << s->dflag); 2526 } 2527 } 2528 2529 /* two step pop is necessary for precise exceptions */ 2530 static void gen_pop_T0(DisasContext *s) 2531 { 2532 #ifdef TARGET_X86_64 2533 if (CODE64(s)) { 2534 gen_op_movq_A0_reg(R_ESP); 2535 gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index); 2536 } else 2537 #endif 2538 { 2539 gen_op_movl_A0_reg(R_ESP); 2540 if (s->ss32) { 2541 if (s->addseg) 2542 gen_op_addl_A0_seg(R_SS); 2543 } else { 2544 gen_op_andl_A0_ffff(); 2545 gen_op_addl_A0_seg(R_SS); 2546 } 2547 gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index); 2548 } 2549 } 2550 2551 static void gen_pop_update(DisasContext *s) 2552 { 2553 #ifdef TARGET_X86_64 2554 if (CODE64(s) && s->dflag) { 2555 gen_stack_update(s, 8); 2556 } else 2557 #endif 2558 { 2559 gen_stack_update(s, 2 << s->dflag); 2560 } 2561 } 2562 2563 static void gen_stack_A0(DisasContext *s) 2564 { 2565 gen_op_movl_A0_reg(R_ESP); 2566 if (!s->ss32) 2567 gen_op_andl_A0_ffff(); 2568 tcg_gen_mov_tl(cpu_T[1], cpu_A0); 2569 if (s->addseg) 2570 gen_op_addl_A0_seg(R_SS); 2571 } 2572 2573 /* NOTE: wrap around in 16 bit not fully handled */ 2574 static void gen_pusha(DisasContext *s) 2575 { 2576 int i; 2577 gen_op_movl_A0_reg(R_ESP); 2578 gen_op_addl_A0_im(-16 << s->dflag); 2579 if (!s->ss32) 2580 gen_op_andl_A0_ffff(); 2581 tcg_gen_mov_tl(cpu_T[1], cpu_A0); 2582 if (s->addseg) 2583 gen_op_addl_A0_seg(R_SS); 2584 for(i = 0;i < 8; i++) { 2585 gen_op_mov_TN_reg(OT_LONG, 0, 7 - i); 2586 gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index); 2587 gen_op_addl_A0_im(2 << s->dflag); 2588 } 2589 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); 2590 } 2591 2592 /* NOTE: wrap around in 16 bit not fully handled */ 2593 static void gen_popa(DisasContext *s) 2594 { 2595 int i; 2596 gen_op_movl_A0_reg(R_ESP); 2597 if (!s->ss32) 2598 gen_op_andl_A0_ffff(); 2599 tcg_gen_mov_tl(cpu_T[1], cpu_A0); 2600 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 << s->dflag); 2601 if (s->addseg) 2602 gen_op_addl_A0_seg(R_SS); 2603 for(i = 0;i < 8; i++) { 2604 /* ESP is not reloaded */ 2605 if (i != 3) { 2606 gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index); 2607 gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i); 2608 } 2609 gen_op_addl_A0_im(2 << s->dflag); 2610 } 2611 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); 2612 } 2613 2614 static void gen_enter(DisasContext *s, int esp_addend, int level) 2615 { 2616 int ot, opsize; 2617 2618 level &= 0x1f; 2619 #ifdef TARGET_X86_64 2620 if (CODE64(s)) { 2621 ot = s->dflag ? OT_QUAD : OT_WORD; 2622 opsize = 1 << ot; 2623 2624 gen_op_movl_A0_reg(R_ESP); 2625 gen_op_addq_A0_im(-opsize); 2626 tcg_gen_mov_tl(cpu_T[1], cpu_A0); 2627 2628 /* push bp */ 2629 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); 2630 gen_op_st_T0_A0(ot + s->mem_index); 2631 if (level) { 2632 /* XXX: must save state */ 2633 gen_helper_enter64_level(tcg_const_i32(level), 2634 tcg_const_i32((ot == OT_QUAD)), 2635 cpu_T[1]); 2636 } 2637 gen_op_mov_reg_T1(ot, R_EBP); 2638 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level)); 2639 gen_op_mov_reg_T1(OT_QUAD, R_ESP); 2640 } else 2641 #endif 2642 { 2643 ot = s->dflag + OT_WORD; 2644 opsize = 2 << s->dflag; 2645 2646 gen_op_movl_A0_reg(R_ESP); 2647 gen_op_addl_A0_im(-opsize); 2648 if (!s->ss32) 2649 gen_op_andl_A0_ffff(); 2650 tcg_gen_mov_tl(cpu_T[1], cpu_A0); 2651 if (s->addseg) 2652 gen_op_addl_A0_seg(R_SS); 2653 /* push bp */ 2654 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); 2655 gen_op_st_T0_A0(ot + s->mem_index); 2656 if (level) { 2657 /* XXX: must save state */ 2658 gen_helper_enter_level(tcg_const_i32(level), 2659 tcg_const_i32(s->dflag), 2660 cpu_T[1]); 2661 } 2662 gen_op_mov_reg_T1(ot, R_EBP); 2663 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level)); 2664 gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); 2665 } 2666 } 2667 2668 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip) 2669 { 2670 if (s->cc_op != CC_OP_DYNAMIC) 2671 gen_op_set_cc_op(s->cc_op); 2672 gen_jmp_im(cur_eip); 2673 gen_helper_raise_exception(tcg_const_i32(trapno)); 2674 s->is_jmp = 3; 2675 } 2676 2677 /* an interrupt is different from an exception because of the 2678 privilege checks */ 2679 static void gen_interrupt(DisasContext *s, int intno, 2680 target_ulong cur_eip, target_ulong next_eip) 2681 { 2682 if (s->cc_op != CC_OP_DYNAMIC) 2683 gen_op_set_cc_op(s->cc_op); 2684 gen_jmp_im(cur_eip); 2685 gen_helper_raise_interrupt(tcg_const_i32(intno), 2686 tcg_const_i32(next_eip - cur_eip)); 2687 s->is_jmp = 3; 2688 } 2689 2690 static void gen_debug(DisasContext *s, target_ulong cur_eip) 2691 { 2692 if (s->cc_op != CC_OP_DYNAMIC) 2693 gen_op_set_cc_op(s->cc_op); 2694 gen_jmp_im(cur_eip); 2695 gen_helper_debug(); 2696 s->is_jmp = 3; 2697 } 2698 2699 /* generate a generic end of block. Trace exception is also generated 2700 if needed */ 2701 static void gen_eob(DisasContext *s) 2702 { 2703 if (s->cc_op != CC_OP_DYNAMIC) 2704 gen_op_set_cc_op(s->cc_op); 2705 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) { 2706 gen_helper_reset_inhibit_irq(); 2707 } 2708 if (s->tb->flags & HF_RF_MASK) { 2709 gen_helper_reset_rf(); 2710 } 2711 if (s->singlestep_enabled) { 2712 gen_helper_debug(); 2713 } else if (s->tf) { 2714 gen_helper_single_step(); 2715 } else { 2716 tcg_gen_exit_tb(0); 2717 } 2718 s->is_jmp = 3; 2719 } 2720 2721 /* generate a jump to eip. No segment change must happen before as a 2722 direct call to the next block may occur */ 2723 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num) 2724 { 2725 if (s->jmp_opt) { 2726 if (s->cc_op != CC_OP_DYNAMIC) { 2727 gen_op_set_cc_op(s->cc_op); 2728 s->cc_op = CC_OP_DYNAMIC; 2729 } 2730 gen_goto_tb(s, tb_num, eip); 2731 s->is_jmp = 3; 2732 } else { 2733 gen_jmp_im(eip); 2734 gen_eob(s); 2735 } 2736 } 2737 2738 static void gen_jmp(DisasContext *s, target_ulong eip) 2739 { 2740 gen_jmp_tb(s, eip, 0); 2741 } 2742 2743 static inline void gen_ldq_env_A0(int idx, int offset) 2744 { 2745 int mem_index = (idx >> 2) - 1; 2746 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index); 2747 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset); 2748 } 2749 2750 static inline void gen_stq_env_A0(int idx, int offset) 2751 { 2752 int mem_index = (idx >> 2) - 1; 2753 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset); 2754 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index); 2755 } 2756 2757 static inline void gen_ldo_env_A0(int idx, int offset) 2758 { 2759 int mem_index = (idx >> 2) - 1; 2760 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, mem_index); 2761 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0))); 2762 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8); 2763 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_tmp0, mem_index); 2764 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1))); 2765 } 2766 2767 static inline void gen_sto_env_A0(int idx, int offset) 2768 { 2769 int mem_index = (idx >> 2) - 1; 2770 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0))); 2771 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, mem_index); 2772 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8); 2773 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1))); 2774 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_tmp0, mem_index); 2775 } 2776 2777 static inline void gen_op_movo(int d_offset, int s_offset) 2778 { 2779 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset); 2780 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); 2781 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8); 2782 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8); 2783 } 2784 2785 static inline void gen_op_movq(int d_offset, int s_offset) 2786 { 2787 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset); 2788 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); 2789 } 2790 2791 static inline void gen_op_movl(int d_offset, int s_offset) 2792 { 2793 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset); 2794 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset); 2795 } 2796 2797 static inline void gen_op_movq_env_0(int d_offset) 2798 { 2799 tcg_gen_movi_i64(cpu_tmp1_i64, 0); 2800 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); 2801 } 2802 2803 #define SSE_SPECIAL ((void *)1) 2804 #define SSE_DUMMY ((void *)2) 2805 2806 #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm } 2807 #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \ 2808 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, } 2809 2810 static void *sse_op_table1[256][4] = { 2811 /* 3DNow! extensions */ 2812 [0x0e] = { SSE_DUMMY }, /* femms */ 2813 [0x0f] = { SSE_DUMMY }, /* pf... */ 2814 /* pure SSE operations */ 2815 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ 2816 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ 2817 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */ 2818 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */ 2819 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm }, 2820 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm }, 2821 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */ 2822 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */ 2823 2824 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */ 2825 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */ 2826 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */ 2827 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd */ 2828 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */ 2829 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */ 2830 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd }, 2831 [0x2f] = { gen_helper_comiss, gen_helper_comisd }, 2832 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */ 2833 [0x51] = SSE_FOP(sqrt), 2834 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL }, 2835 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL }, 2836 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */ 2837 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */ 2838 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */ 2839 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */ 2840 [0x58] = SSE_FOP(add), 2841 [0x59] = SSE_FOP(mul), 2842 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps, 2843 gen_helper_cvtss2sd, gen_helper_cvtsd2ss }, 2844 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq }, 2845 [0x5c] = SSE_FOP(sub), 2846 [0x5d] = SSE_FOP(min), 2847 [0x5e] = SSE_FOP(div), 2848 [0x5f] = SSE_FOP(max), 2849 2850 [0xc2] = SSE_FOP(cmpeq), 2851 [0xc6] = { gen_helper_shufps, gen_helper_shufpd }, 2852 2853 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* SSSE3/SSE4 */ 2854 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL }, /* SSSE3/SSE4 */ 2855 2856 /* MMX ops and their SSE extensions */ 2857 [0x60] = MMX_OP2(punpcklbw), 2858 [0x61] = MMX_OP2(punpcklwd), 2859 [0x62] = MMX_OP2(punpckldq), 2860 [0x63] = MMX_OP2(packsswb), 2861 [0x64] = MMX_OP2(pcmpgtb), 2862 [0x65] = MMX_OP2(pcmpgtw), 2863 [0x66] = MMX_OP2(pcmpgtl), 2864 [0x67] = MMX_OP2(packuswb), 2865 [0x68] = MMX_OP2(punpckhbw), 2866 [0x69] = MMX_OP2(punpckhwd), 2867 [0x6a] = MMX_OP2(punpckhdq), 2868 [0x6b] = MMX_OP2(packssdw), 2869 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm }, 2870 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm }, 2871 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */ 2872 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */ 2873 [0x70] = { gen_helper_pshufw_mmx, 2874 gen_helper_pshufd_xmm, 2875 gen_helper_pshufhw_xmm, 2876 gen_helper_pshuflw_xmm }, 2877 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */ 2878 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */ 2879 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */ 2880 [0x74] = MMX_OP2(pcmpeqb), 2881 [0x75] = MMX_OP2(pcmpeqw), 2882 [0x76] = MMX_OP2(pcmpeql), 2883 [0x77] = { SSE_DUMMY }, /* emms */ 2884 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps }, 2885 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps }, 2886 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */ 2887 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */ 2888 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */ 2889 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */ 2890 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps }, 2891 [0xd1] = MMX_OP2(psrlw), 2892 [0xd2] = MMX_OP2(psrld), 2893 [0xd3] = MMX_OP2(psrlq), 2894 [0xd4] = MMX_OP2(paddq), 2895 [0xd5] = MMX_OP2(pmullw), 2896 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, 2897 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */ 2898 [0xd8] = MMX_OP2(psubusb), 2899 [0xd9] = MMX_OP2(psubusw), 2900 [0xda] = MMX_OP2(pminub), 2901 [0xdb] = MMX_OP2(pand), 2902 [0xdc] = MMX_OP2(paddusb), 2903 [0xdd] = MMX_OP2(paddusw), 2904 [0xde] = MMX_OP2(pmaxub), 2905 [0xdf] = MMX_OP2(pandn), 2906 [0xe0] = MMX_OP2(pavgb), 2907 [0xe1] = MMX_OP2(psraw), 2908 [0xe2] = MMX_OP2(psrad), 2909 [0xe3] = MMX_OP2(pavgw), 2910 [0xe4] = MMX_OP2(pmulhuw), 2911 [0xe5] = MMX_OP2(pmulhw), 2912 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq }, 2913 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */ 2914 [0xe8] = MMX_OP2(psubsb), 2915 [0xe9] = MMX_OP2(psubsw), 2916 [0xea] = MMX_OP2(pminsw), 2917 [0xeb] = MMX_OP2(por), 2918 [0xec] = MMX_OP2(paddsb), 2919 [0xed] = MMX_OP2(paddsw), 2920 [0xee] = MMX_OP2(pmaxsw), 2921 [0xef] = MMX_OP2(pxor), 2922 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */ 2923 [0xf1] = MMX_OP2(psllw), 2924 [0xf2] = MMX_OP2(pslld), 2925 [0xf3] = MMX_OP2(psllq), 2926 [0xf4] = MMX_OP2(pmuludq), 2927 [0xf5] = MMX_OP2(pmaddwd), 2928 [0xf6] = MMX_OP2(psadbw), 2929 [0xf7] = MMX_OP2(maskmov), 2930 [0xf8] = MMX_OP2(psubb), 2931 [0xf9] = MMX_OP2(psubw), 2932 [0xfa] = MMX_OP2(psubl), 2933 [0xfb] = MMX_OP2(psubq), 2934 [0xfc] = MMX_OP2(paddb), 2935 [0xfd] = MMX_OP2(paddw), 2936 [0xfe] = MMX_OP2(paddl), 2937 }; 2938 2939 static void *sse_op_table2[3 * 8][2] = { 2940 [0 + 2] = MMX_OP2(psrlw), 2941 [0 + 4] = MMX_OP2(psraw), 2942 [0 + 6] = MMX_OP2(psllw), 2943 [8 + 2] = MMX_OP2(psrld), 2944 [8 + 4] = MMX_OP2(psrad), 2945 [8 + 6] = MMX_OP2(pslld), 2946 [16 + 2] = MMX_OP2(psrlq), 2947 [16 + 3] = { NULL, gen_helper_psrldq_xmm }, 2948 [16 + 6] = MMX_OP2(psllq), 2949 [16 + 7] = { NULL, gen_helper_pslldq_xmm }, 2950 }; 2951 2952 static void *sse_op_table3[4 * 3] = { 2953 gen_helper_cvtsi2ss, 2954 gen_helper_cvtsi2sd, 2955 X86_64_ONLY(gen_helper_cvtsq2ss), 2956 X86_64_ONLY(gen_helper_cvtsq2sd), 2957 2958 gen_helper_cvttss2si, 2959 gen_helper_cvttsd2si, 2960 X86_64_ONLY(gen_helper_cvttss2sq), 2961 X86_64_ONLY(gen_helper_cvttsd2sq), 2962 2963 gen_helper_cvtss2si, 2964 gen_helper_cvtsd2si, 2965 X86_64_ONLY(gen_helper_cvtss2sq), 2966 X86_64_ONLY(gen_helper_cvtsd2sq), 2967 }; 2968 2969 static void *sse_op_table4[8][4] = { 2970 SSE_FOP(cmpeq), 2971 SSE_FOP(cmplt), 2972 SSE_FOP(cmple), 2973 SSE_FOP(cmpunord), 2974 SSE_FOP(cmpneq), 2975 SSE_FOP(cmpnlt), 2976 SSE_FOP(cmpnle), 2977 SSE_FOP(cmpord), 2978 }; 2979 2980 static void *sse_op_table5[256] = { 2981 [0x0c] = gen_helper_pi2fw, 2982 [0x0d] = gen_helper_pi2fd, 2983 [0x1c] = gen_helper_pf2iw, 2984 [0x1d] = gen_helper_pf2id, 2985 [0x8a] = gen_helper_pfnacc, 2986 [0x8e] = gen_helper_pfpnacc, 2987 [0x90] = gen_helper_pfcmpge, 2988 [0x94] = gen_helper_pfmin, 2989 [0x96] = gen_helper_pfrcp, 2990 [0x97] = gen_helper_pfrsqrt, 2991 [0x9a] = gen_helper_pfsub, 2992 [0x9e] = gen_helper_pfadd, 2993 [0xa0] = gen_helper_pfcmpgt, 2994 [0xa4] = gen_helper_pfmax, 2995 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */ 2996 [0xa7] = gen_helper_movq, /* pfrsqit1 */ 2997 [0xaa] = gen_helper_pfsubr, 2998 [0xae] = gen_helper_pfacc, 2999 [0xb0] = gen_helper_pfcmpeq, 3000 [0xb4] = gen_helper_pfmul, 3001 [0xb6] = gen_helper_movq, /* pfrcpit2 */ 3002 [0xb7] = gen_helper_pmulhrw_mmx, 3003 [0xbb] = gen_helper_pswapd, 3004 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */ 3005 }; 3006 3007 struct sse_op_helper_s { 3008 void *op[2]; uint32_t ext_mask; 3009 }; 3010 #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 } 3011 #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 } 3012 #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 } 3013 #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 } 3014 static struct sse_op_helper_s sse_op_table6[256] = { 3015 [0x00] = SSSE3_OP(pshufb), 3016 [0x01] = SSSE3_OP(phaddw), 3017 [0x02] = SSSE3_OP(phaddd), 3018 [0x03] = SSSE3_OP(phaddsw), 3019 [0x04] = SSSE3_OP(pmaddubsw), 3020 [0x05] = SSSE3_OP(phsubw), 3021 [0x06] = SSSE3_OP(phsubd), 3022 [0x07] = SSSE3_OP(phsubsw), 3023 [0x08] = SSSE3_OP(psignb), 3024 [0x09] = SSSE3_OP(psignw), 3025 [0x0a] = SSSE3_OP(psignd), 3026 [0x0b] = SSSE3_OP(pmulhrsw), 3027 [0x10] = SSE41_OP(pblendvb), 3028 [0x14] = SSE41_OP(blendvps), 3029 [0x15] = SSE41_OP(blendvpd), 3030 [0x17] = SSE41_OP(ptest), 3031 [0x1c] = SSSE3_OP(pabsb), 3032 [0x1d] = SSSE3_OP(pabsw), 3033 [0x1e] = SSSE3_OP(pabsd), 3034 [0x20] = SSE41_OP(pmovsxbw), 3035 [0x21] = SSE41_OP(pmovsxbd), 3036 [0x22] = SSE41_OP(pmovsxbq), 3037 [0x23] = SSE41_OP(pmovsxwd), 3038 [0x24] = SSE41_OP(pmovsxwq), 3039 [0x25] = SSE41_OP(pmovsxdq), 3040 [0x28] = SSE41_OP(pmuldq), 3041 [0x29] = SSE41_OP(pcmpeqq), 3042 [0x2a] = SSE41_SPECIAL, /* movntqda */ 3043 [0x2b] = SSE41_OP(packusdw), 3044 [0x30] = SSE41_OP(pmovzxbw), 3045 [0x31] = SSE41_OP(pmovzxbd), 3046 [0x32] = SSE41_OP(pmovzxbq), 3047 [0x33] = SSE41_OP(pmovzxwd), 3048 [0x34] = SSE41_OP(pmovzxwq), 3049 [0x35] = SSE41_OP(pmovzxdq), 3050 [0x37] = SSE42_OP(pcmpgtq), 3051 [0x38] = SSE41_OP(pminsb), 3052 [0x39] = SSE41_OP(pminsd), 3053 [0x3a] = SSE41_OP(pminuw), 3054 [0x3b] = SSE41_OP(pminud), 3055 [0x3c] = SSE41_OP(pmaxsb), 3056 [0x3d] = SSE41_OP(pmaxsd), 3057 [0x3e] = SSE41_OP(pmaxuw), 3058 [0x3f] = SSE41_OP(pmaxud), 3059 [0x40] = SSE41_OP(pmulld), 3060 [0x41] = SSE41_OP(phminposuw), 3061 }; 3062 3063 static struct sse_op_helper_s sse_op_table7[256] = { 3064 [0x08] = SSE41_OP(roundps), 3065 [0x09] = SSE41_OP(roundpd), 3066 [0x0a] = SSE41_OP(roundss), 3067 [0x0b] = SSE41_OP(roundsd), 3068 [0x0c] = SSE41_OP(blendps), 3069 [0x0d] = SSE41_OP(blendpd), 3070 [0x0e] = SSE41_OP(pblendw), 3071 [0x0f] = SSSE3_OP(palignr), 3072 [0x14] = SSE41_SPECIAL, /* pextrb */ 3073 [0x15] = SSE41_SPECIAL, /* pextrw */ 3074 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */ 3075 [0x17] = SSE41_SPECIAL, /* extractps */ 3076 [0x20] = SSE41_SPECIAL, /* pinsrb */ 3077 [0x21] = SSE41_SPECIAL, /* insertps */ 3078 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */ 3079 [0x40] = SSE41_OP(dpps), 3080 [0x41] = SSE41_OP(dppd), 3081 [0x42] = SSE41_OP(mpsadbw), 3082 [0x60] = SSE42_OP(pcmpestrm), 3083 [0x61] = SSE42_OP(pcmpestri), 3084 [0x62] = SSE42_OP(pcmpistrm), 3085 [0x63] = SSE42_OP(pcmpistri), 3086 }; 3087 3088 static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) 3089 { 3090 int b1, op1_offset, op2_offset, is_xmm, val, ot; 3091 int modrm, mod, rm, reg, reg_addr, offset_addr; 3092 void *sse_op2; 3093 3094 b &= 0xff; 3095 if (s->prefix & PREFIX_DATA) 3096 b1 = 1; 3097 else if (s->prefix & PREFIX_REPZ) 3098 b1 = 2; 3099 else if (s->prefix & PREFIX_REPNZ) 3100 b1 = 3; 3101 else 3102 b1 = 0; 3103 sse_op2 = sse_op_table1[b][b1]; 3104 if (!sse_op2) 3105 goto illegal_op; 3106 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) { 3107 is_xmm = 1; 3108 } else { 3109 if (b1 == 0) { 3110 /* MMX case */ 3111 is_xmm = 0; 3112 } else { 3113 is_xmm = 1; 3114 } 3115 } 3116 /* simple MMX/SSE operation */ 3117 if (s->flags & HF_TS_MASK) { 3118 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); 3119 return; 3120 } 3121 if (s->flags & HF_EM_MASK) { 3122 illegal_op: 3123 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); 3124 return; 3125 } 3126 if (is_xmm && !(s->flags & HF_OSFXSR_MASK)) 3127 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA)) 3128 goto illegal_op; 3129 if (b == 0x0e) { 3130 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) 3131 goto illegal_op; 3132 /* femms */ 3133 gen_helper_emms(); 3134 return; 3135 } 3136 if (b == 0x77) { 3137 /* emms */ 3138 gen_helper_emms(); 3139 return; 3140 } 3141 /* prepare MMX state (XXX: optimize by storing fptt and fptags in 3142 the static cpu state) */ 3143 if (!is_xmm) { 3144 gen_helper_enter_mmx(); 3145 } 3146 3147 modrm = ldub_code(s->pc++); 3148 reg = ((modrm >> 3) & 7); 3149 if (is_xmm) 3150 reg |= rex_r; 3151 mod = (modrm >> 6) & 3; 3152 if (sse_op2 == SSE_SPECIAL) { 3153 b |= (b1 << 8); 3154 switch(b) { 3155 case 0x0e7: /* movntq */ 3156 if (mod == 3) 3157 goto illegal_op; 3158 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3159 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx)); 3160 break; 3161 case 0x1e7: /* movntdq */ 3162 case 0x02b: /* movntps */ 3163 case 0x12b: /* movntps */ 3164 case 0x3f0: /* lddqu */ 3165 if (mod == 3) 3166 goto illegal_op; 3167 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3168 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); 3169 break; 3170 case 0x6e: /* movd mm, ea */ 3171 #ifdef TARGET_X86_64 3172 if (s->dflag == 2) { 3173 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0); 3174 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx)); 3175 } else 3176 #endif 3177 { 3178 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0); 3179 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 3180 offsetof(CPUX86State,fpregs[reg].mmx)); 3181 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 3182 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32); 3183 } 3184 break; 3185 case 0x16e: /* movd xmm, ea */ 3186 #ifdef TARGET_X86_64 3187 if (s->dflag == 2) { 3188 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0); 3189 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 3190 offsetof(CPUX86State,xmm_regs[reg])); 3191 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]); 3192 } else 3193 #endif 3194 { 3195 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0); 3196 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 3197 offsetof(CPUX86State,xmm_regs[reg])); 3198 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 3199 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32); 3200 } 3201 break; 3202 case 0x6f: /* movq mm, ea */ 3203 if (mod != 3) { 3204 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3205 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx)); 3206 } else { 3207 rm = (modrm & 7); 3208 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, 3209 offsetof(CPUX86State,fpregs[rm].mmx)); 3210 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, 3211 offsetof(CPUX86State,fpregs[reg].mmx)); 3212 } 3213 break; 3214 case 0x010: /* movups */ 3215 case 0x110: /* movupd */ 3216 case 0x028: /* movaps */ 3217 case 0x128: /* movapd */ 3218 case 0x16f: /* movdqa xmm, ea */ 3219 case 0x26f: /* movdqu xmm, ea */ 3220 if (mod != 3) { 3221 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3222 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); 3223 } else { 3224 rm = (modrm & 7) | REX_B(s); 3225 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]), 3226 offsetof(CPUX86State,xmm_regs[rm])); 3227 } 3228 break; 3229 case 0x210: /* movss xmm, ea */ 3230 if (mod != 3) { 3231 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3232 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 3233 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); 3234 gen_op_movl_T0_0(); 3235 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1))); 3236 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2))); 3237 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); 3238 } else { 3239 rm = (modrm & 7) | REX_B(s); 3240 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)), 3241 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0))); 3242 } 3243 break; 3244 case 0x310: /* movsd xmm, ea */ 3245 if (mod != 3) { 3246 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3247 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3248 gen_op_movl_T0_0(); 3249 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2))); 3250 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); 3251 } else { 3252 rm = (modrm & 7) | REX_B(s); 3253 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), 3254 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); 3255 } 3256 break; 3257 case 0x012: /* movlps */ 3258 case 0x112: /* movlpd */ 3259 if (mod != 3) { 3260 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3261 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3262 } else { 3263 /* movhlps */ 3264 rm = (modrm & 7) | REX_B(s); 3265 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), 3266 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1))); 3267 } 3268 break; 3269 case 0x212: /* movsldup */ 3270 if (mod != 3) { 3271 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3272 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); 3273 } else { 3274 rm = (modrm & 7) | REX_B(s); 3275 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)), 3276 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0))); 3277 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)), 3278 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2))); 3279 } 3280 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)), 3281 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); 3282 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)), 3283 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2))); 3284 break; 3285 case 0x312: /* movddup */ 3286 if (mod != 3) { 3287 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3288 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3289 } else { 3290 rm = (modrm & 7) | REX_B(s); 3291 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), 3292 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); 3293 } 3294 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)), 3295 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3296 break; 3297 case 0x016: /* movhps */ 3298 case 0x116: /* movhpd */ 3299 if (mod != 3) { 3300 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3301 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); 3302 } else { 3303 /* movlhps */ 3304 rm = (modrm & 7) | REX_B(s); 3305 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)), 3306 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); 3307 } 3308 break; 3309 case 0x216: /* movshdup */ 3310 if (mod != 3) { 3311 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3312 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); 3313 } else { 3314 rm = (modrm & 7) | REX_B(s); 3315 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)), 3316 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1))); 3317 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)), 3318 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3))); 3319 } 3320 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)), 3321 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1))); 3322 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)), 3323 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); 3324 break; 3325 case 0x7e: /* movd ea, mm */ 3326 #ifdef TARGET_X86_64 3327 if (s->dflag == 2) { 3328 tcg_gen_ld_i64(cpu_T[0], cpu_env, 3329 offsetof(CPUX86State,fpregs[reg].mmx)); 3330 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1); 3331 } else 3332 #endif 3333 { 3334 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 3335 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0))); 3336 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1); 3337 } 3338 break; 3339 case 0x17e: /* movd ea, xmm */ 3340 #ifdef TARGET_X86_64 3341 if (s->dflag == 2) { 3342 tcg_gen_ld_i64(cpu_T[0], cpu_env, 3343 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3344 gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1); 3345 } else 3346 #endif 3347 { 3348 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 3349 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); 3350 gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1); 3351 } 3352 break; 3353 case 0x27e: /* movq xmm, ea */ 3354 if (mod != 3) { 3355 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3356 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3357 } else { 3358 rm = (modrm & 7) | REX_B(s); 3359 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), 3360 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); 3361 } 3362 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); 3363 break; 3364 case 0x7f: /* movq ea, mm */ 3365 if (mod != 3) { 3366 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3367 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx)); 3368 } else { 3369 rm = (modrm & 7); 3370 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx), 3371 offsetof(CPUX86State,fpregs[reg].mmx)); 3372 } 3373 break; 3374 case 0x011: /* movups */ 3375 case 0x111: /* movupd */ 3376 case 0x029: /* movaps */ 3377 case 0x129: /* movapd */ 3378 case 0x17f: /* movdqa ea, xmm */ 3379 case 0x27f: /* movdqu ea, xmm */ 3380 if (mod != 3) { 3381 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3382 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); 3383 } else { 3384 rm = (modrm & 7) | REX_B(s); 3385 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]), 3386 offsetof(CPUX86State,xmm_regs[reg])); 3387 } 3388 break; 3389 case 0x211: /* movss ea, xmm */ 3390 if (mod != 3) { 3391 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3392 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); 3393 gen_op_st_T0_A0(OT_LONG + s->mem_index); 3394 } else { 3395 rm = (modrm & 7) | REX_B(s); 3396 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)), 3397 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); 3398 } 3399 break; 3400 case 0x311: /* movsd ea, xmm */ 3401 if (mod != 3) { 3402 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3403 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3404 } else { 3405 rm = (modrm & 7) | REX_B(s); 3406 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)), 3407 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3408 } 3409 break; 3410 case 0x013: /* movlps */ 3411 case 0x113: /* movlpd */ 3412 if (mod != 3) { 3413 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3414 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3415 } else { 3416 goto illegal_op; 3417 } 3418 break; 3419 case 0x017: /* movhps */ 3420 case 0x117: /* movhpd */ 3421 if (mod != 3) { 3422 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3423 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); 3424 } else { 3425 goto illegal_op; 3426 } 3427 break; 3428 case 0x71: /* shift mm, im */ 3429 case 0x72: 3430 case 0x73: 3431 case 0x171: /* shift xmm, im */ 3432 case 0x172: 3433 case 0x173: 3434 val = ldub_code(s->pc++); 3435 if (is_xmm) { 3436 gen_op_movl_T0_im(val); 3437 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0))); 3438 gen_op_movl_T0_0(); 3439 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1))); 3440 op1_offset = offsetof(CPUX86State,xmm_t0); 3441 } else { 3442 gen_op_movl_T0_im(val); 3443 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0))); 3444 gen_op_movl_T0_0(); 3445 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1))); 3446 op1_offset = offsetof(CPUX86State,mmx_t0); 3447 } 3448 sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1]; 3449 if (!sse_op2) 3450 goto illegal_op; 3451 if (is_xmm) { 3452 rm = (modrm & 7) | REX_B(s); 3453 op2_offset = offsetof(CPUX86State,xmm_regs[rm]); 3454 } else { 3455 rm = (modrm & 7); 3456 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); 3457 } 3458 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); 3459 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset); 3460 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); 3461 break; 3462 case 0x050: /* movmskps */ 3463 rm = (modrm & 7) | REX_B(s); 3464 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 3465 offsetof(CPUX86State,xmm_regs[rm])); 3466 gen_helper_movmskps(cpu_tmp2_i32, cpu_ptr0); 3467 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 3468 gen_op_mov_reg_T0(OT_LONG, reg); 3469 break; 3470 case 0x150: /* movmskpd */ 3471 rm = (modrm & 7) | REX_B(s); 3472 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 3473 offsetof(CPUX86State,xmm_regs[rm])); 3474 gen_helper_movmskpd(cpu_tmp2_i32, cpu_ptr0); 3475 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 3476 gen_op_mov_reg_T0(OT_LONG, reg); 3477 break; 3478 case 0x02a: /* cvtpi2ps */ 3479 case 0x12a: /* cvtpi2pd */ 3480 gen_helper_enter_mmx(); 3481 if (mod != 3) { 3482 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3483 op2_offset = offsetof(CPUX86State,mmx_t0); 3484 gen_ldq_env_A0(s->mem_index, op2_offset); 3485 } else { 3486 rm = (modrm & 7); 3487 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); 3488 } 3489 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); 3490 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 3491 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 3492 switch(b >> 8) { 3493 case 0x0: 3494 gen_helper_cvtpi2ps(cpu_ptr0, cpu_ptr1); 3495 break; 3496 default: 3497 case 0x1: 3498 gen_helper_cvtpi2pd(cpu_ptr0, cpu_ptr1); 3499 break; 3500 } 3501 break; 3502 case 0x22a: /* cvtsi2ss */ 3503 case 0x32a: /* cvtsi2sd */ 3504 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; 3505 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 3506 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); 3507 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 3508 sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)]; 3509 if (ot == OT_LONG) { 3510 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 3511 ((void (*)(TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_tmp2_i32); 3512 } else { 3513 ((void (*)(TCGv_ptr, TCGv))sse_op2)(cpu_ptr0, cpu_T[0]); 3514 } 3515 break; 3516 case 0x02c: /* cvttps2pi */ 3517 case 0x12c: /* cvttpd2pi */ 3518 case 0x02d: /* cvtps2pi */ 3519 case 0x12d: /* cvtpd2pi */ 3520 gen_helper_enter_mmx(); 3521 if (mod != 3) { 3522 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3523 op2_offset = offsetof(CPUX86State,xmm_t0); 3524 gen_ldo_env_A0(s->mem_index, op2_offset); 3525 } else { 3526 rm = (modrm & 7) | REX_B(s); 3527 op2_offset = offsetof(CPUX86State,xmm_regs[rm]); 3528 } 3529 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx); 3530 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 3531 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 3532 switch(b) { 3533 case 0x02c: 3534 gen_helper_cvttps2pi(cpu_ptr0, cpu_ptr1); 3535 break; 3536 case 0x12c: 3537 gen_helper_cvttpd2pi(cpu_ptr0, cpu_ptr1); 3538 break; 3539 case 0x02d: 3540 gen_helper_cvtps2pi(cpu_ptr0, cpu_ptr1); 3541 break; 3542 case 0x12d: 3543 gen_helper_cvtpd2pi(cpu_ptr0, cpu_ptr1); 3544 break; 3545 } 3546 break; 3547 case 0x22c: /* cvttss2si */ 3548 case 0x32c: /* cvttsd2si */ 3549 case 0x22d: /* cvtss2si */ 3550 case 0x32d: /* cvtsd2si */ 3551 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; 3552 if (mod != 3) { 3553 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3554 if ((b >> 8) & 1) { 3555 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0))); 3556 } else { 3557 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 3558 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0))); 3559 } 3560 op2_offset = offsetof(CPUX86State,xmm_t0); 3561 } else { 3562 rm = (modrm & 7) | REX_B(s); 3563 op2_offset = offsetof(CPUX86State,xmm_regs[rm]); 3564 } 3565 sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 + 3566 (b & 1) * 4]; 3567 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); 3568 if (ot == OT_LONG) { 3569 ((void (*)(TCGv_i32, TCGv_ptr))sse_op2)(cpu_tmp2_i32, cpu_ptr0); 3570 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 3571 } else { 3572 ((void (*)(TCGv, TCGv_ptr))sse_op2)(cpu_T[0], cpu_ptr0); 3573 } 3574 gen_op_mov_reg_T0(ot, reg); 3575 break; 3576 case 0xc4: /* pinsrw */ 3577 case 0x1c4: 3578 s->rip_offset = 1; 3579 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); 3580 val = ldub_code(s->pc++); 3581 if (b1) { 3582 val &= 7; 3583 tcg_gen_st16_tl(cpu_T[0], cpu_env, 3584 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val))); 3585 } else { 3586 val &= 3; 3587 tcg_gen_st16_tl(cpu_T[0], cpu_env, 3588 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val))); 3589 } 3590 break; 3591 case 0xc5: /* pextrw */ 3592 case 0x1c5: 3593 if (mod != 3) 3594 goto illegal_op; 3595 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; 3596 val = ldub_code(s->pc++); 3597 if (b1) { 3598 val &= 7; 3599 rm = (modrm & 7) | REX_B(s); 3600 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, 3601 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val))); 3602 } else { 3603 val &= 3; 3604 rm = (modrm & 7); 3605 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, 3606 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val))); 3607 } 3608 reg = ((modrm >> 3) & 7) | rex_r; 3609 gen_op_mov_reg_T0(ot, reg); 3610 break; 3611 case 0x1d6: /* movq ea, xmm */ 3612 if (mod != 3) { 3613 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3614 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3615 } else { 3616 rm = (modrm & 7) | REX_B(s); 3617 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)), 3618 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); 3619 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1))); 3620 } 3621 break; 3622 case 0x2d6: /* movq2dq */ 3623 gen_helper_enter_mmx(); 3624 rm = (modrm & 7); 3625 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), 3626 offsetof(CPUX86State,fpregs[rm].mmx)); 3627 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); 3628 break; 3629 case 0x3d6: /* movdq2q */ 3630 gen_helper_enter_mmx(); 3631 rm = (modrm & 7) | REX_B(s); 3632 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx), 3633 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); 3634 break; 3635 case 0xd7: /* pmovmskb */ 3636 case 0x1d7: 3637 if (mod != 3) 3638 goto illegal_op; 3639 if (b1) { 3640 rm = (modrm & 7) | REX_B(s); 3641 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); 3642 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_ptr0); 3643 } else { 3644 rm = (modrm & 7); 3645 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx)); 3646 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_ptr0); 3647 } 3648 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 3649 reg = ((modrm >> 3) & 7) | rex_r; 3650 gen_op_mov_reg_T0(OT_LONG, reg); 3651 break; 3652 case 0x138: 3653 if (s->prefix & PREFIX_REPNZ) 3654 goto crc32; 3655 case 0x038: 3656 b = modrm; 3657 modrm = ldub_code(s->pc++); 3658 rm = modrm & 7; 3659 reg = ((modrm >> 3) & 7) | rex_r; 3660 mod = (modrm >> 6) & 3; 3661 3662 sse_op2 = sse_op_table6[b].op[b1]; 3663 if (!sse_op2) 3664 goto illegal_op; 3665 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask)) 3666 goto illegal_op; 3667 3668 if (b1) { 3669 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); 3670 if (mod == 3) { 3671 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]); 3672 } else { 3673 op2_offset = offsetof(CPUX86State,xmm_t0); 3674 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3675 switch (b) { 3676 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */ 3677 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */ 3678 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */ 3679 gen_ldq_env_A0(s->mem_index, op2_offset + 3680 offsetof(XMMReg, XMM_Q(0))); 3681 break; 3682 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */ 3683 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */ 3684 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0, 3685 (s->mem_index >> 2) - 1); 3686 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0); 3687 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset + 3688 offsetof(XMMReg, XMM_L(0))); 3689 break; 3690 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */ 3691 tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0, 3692 (s->mem_index >> 2) - 1); 3693 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset + 3694 offsetof(XMMReg, XMM_W(0))); 3695 break; 3696 case 0x2a: /* movntqda */ 3697 gen_ldo_env_A0(s->mem_index, op1_offset); 3698 return; 3699 default: 3700 gen_ldo_env_A0(s->mem_index, op2_offset); 3701 } 3702 } 3703 } else { 3704 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); 3705 if (mod == 3) { 3706 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); 3707 } else { 3708 op2_offset = offsetof(CPUX86State,mmx_t0); 3709 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3710 gen_ldq_env_A0(s->mem_index, op2_offset); 3711 } 3712 } 3713 if (sse_op2 == SSE_SPECIAL) 3714 goto illegal_op; 3715 3716 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 3717 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 3718 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); 3719 3720 if (b == 0x17) 3721 s->cc_op = CC_OP_EFLAGS; 3722 break; 3723 case 0x338: /* crc32 */ 3724 crc32: 3725 b = modrm; 3726 modrm = ldub_code(s->pc++); 3727 reg = ((modrm >> 3) & 7) | rex_r; 3728 3729 if (b != 0xf0 && b != 0xf1) 3730 goto illegal_op; 3731 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) 3732 goto illegal_op; 3733 3734 if (b == 0xf0) 3735 ot = OT_BYTE; 3736 else if (b == 0xf1 && s->dflag != 2) 3737 if (s->prefix & PREFIX_DATA) 3738 ot = OT_WORD; 3739 else 3740 ot = OT_LONG; 3741 else 3742 ot = OT_QUAD; 3743 3744 gen_op_mov_TN_reg(OT_LONG, 0, reg); 3745 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 3746 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 3747 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32, 3748 cpu_T[0], tcg_const_i32(8 << ot)); 3749 3750 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; 3751 gen_op_mov_reg_T0(ot, reg); 3752 break; 3753 case 0x03a: 3754 case 0x13a: 3755 b = modrm; 3756 modrm = ldub_code(s->pc++); 3757 rm = modrm & 7; 3758 reg = ((modrm >> 3) & 7) | rex_r; 3759 mod = (modrm >> 6) & 3; 3760 3761 sse_op2 = sse_op_table7[b].op[b1]; 3762 if (!sse_op2) 3763 goto illegal_op; 3764 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask)) 3765 goto illegal_op; 3766 3767 if (sse_op2 == SSE_SPECIAL) { 3768 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; 3769 rm = (modrm & 7) | REX_B(s); 3770 if (mod != 3) 3771 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3772 reg = ((modrm >> 3) & 7) | rex_r; 3773 val = ldub_code(s->pc++); 3774 switch (b) { 3775 case 0x14: /* pextrb */ 3776 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, 3777 xmm_regs[reg].XMM_B(val & 15))); 3778 if (mod == 3) 3779 gen_op_mov_reg_T0(ot, rm); 3780 else 3781 tcg_gen_qemu_st8(cpu_T[0], cpu_A0, 3782 (s->mem_index >> 2) - 1); 3783 break; 3784 case 0x15: /* pextrw */ 3785 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, 3786 xmm_regs[reg].XMM_W(val & 7))); 3787 if (mod == 3) 3788 gen_op_mov_reg_T0(ot, rm); 3789 else 3790 tcg_gen_qemu_st16(cpu_T[0], cpu_A0, 3791 (s->mem_index >> 2) - 1); 3792 break; 3793 case 0x16: 3794 if (ot == OT_LONG) { /* pextrd */ 3795 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, 3796 offsetof(CPUX86State, 3797 xmm_regs[reg].XMM_L(val & 3))); 3798 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 3799 if (mod == 3) 3800 gen_op_mov_reg_v(ot, rm, cpu_T[0]); 3801 else 3802 tcg_gen_qemu_st32(cpu_T[0], cpu_A0, 3803 (s->mem_index >> 2) - 1); 3804 } else { /* pextrq */ 3805 #ifdef TARGET_X86_64 3806 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, 3807 offsetof(CPUX86State, 3808 xmm_regs[reg].XMM_Q(val & 1))); 3809 if (mod == 3) 3810 gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64); 3811 else 3812 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 3813 (s->mem_index >> 2) - 1); 3814 #else 3815 goto illegal_op; 3816 #endif 3817 } 3818 break; 3819 case 0x17: /* extractps */ 3820 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, 3821 xmm_regs[reg].XMM_L(val & 3))); 3822 if (mod == 3) 3823 gen_op_mov_reg_T0(ot, rm); 3824 else 3825 tcg_gen_qemu_st32(cpu_T[0], cpu_A0, 3826 (s->mem_index >> 2) - 1); 3827 break; 3828 case 0x20: /* pinsrb */ 3829 if (mod == 3) 3830 gen_op_mov_TN_reg(OT_LONG, 0, rm); 3831 else 3832 tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0, 3833 (s->mem_index >> 2) - 1); 3834 tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, 3835 xmm_regs[reg].XMM_B(val & 15))); 3836 break; 3837 case 0x21: /* insertps */ 3838 if (mod == 3) { 3839 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, 3840 offsetof(CPUX86State,xmm_regs[rm] 3841 .XMM_L((val >> 6) & 3))); 3842 } else { 3843 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0, 3844 (s->mem_index >> 2) - 1); 3845 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0); 3846 } 3847 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, 3848 offsetof(CPUX86State,xmm_regs[reg] 3849 .XMM_L((val >> 4) & 3))); 3850 if ((val >> 0) & 1) 3851 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/), 3852 cpu_env, offsetof(CPUX86State, 3853 xmm_regs[reg].XMM_L(0))); 3854 if ((val >> 1) & 1) 3855 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/), 3856 cpu_env, offsetof(CPUX86State, 3857 xmm_regs[reg].XMM_L(1))); 3858 if ((val >> 2) & 1) 3859 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/), 3860 cpu_env, offsetof(CPUX86State, 3861 xmm_regs[reg].XMM_L(2))); 3862 if ((val >> 3) & 1) 3863 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/), 3864 cpu_env, offsetof(CPUX86State, 3865 xmm_regs[reg].XMM_L(3))); 3866 break; 3867 case 0x22: 3868 if (ot == OT_LONG) { /* pinsrd */ 3869 if (mod == 3) 3870 gen_op_mov_v_reg(ot, cpu_tmp0, rm); 3871 else 3872 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0, 3873 (s->mem_index >> 2) - 1); 3874 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0); 3875 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, 3876 offsetof(CPUX86State, 3877 xmm_regs[reg].XMM_L(val & 3))); 3878 } else { /* pinsrq */ 3879 #ifdef TARGET_X86_64 3880 if (mod == 3) 3881 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm); 3882 else 3883 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 3884 (s->mem_index >> 2) - 1); 3885 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, 3886 offsetof(CPUX86State, 3887 xmm_regs[reg].XMM_Q(val & 1))); 3888 #else 3889 goto illegal_op; 3890 #endif 3891 } 3892 break; 3893 } 3894 return; 3895 } 3896 3897 if (b1) { 3898 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); 3899 if (mod == 3) { 3900 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]); 3901 } else { 3902 op2_offset = offsetof(CPUX86State,xmm_t0); 3903 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3904 gen_ldo_env_A0(s->mem_index, op2_offset); 3905 } 3906 } else { 3907 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); 3908 if (mod == 3) { 3909 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); 3910 } else { 3911 op2_offset = offsetof(CPUX86State,mmx_t0); 3912 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3913 gen_ldq_env_A0(s->mem_index, op2_offset); 3914 } 3915 } 3916 val = ldub_code(s->pc++); 3917 3918 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */ 3919 s->cc_op = CC_OP_EFLAGS; 3920 3921 if (s->dflag == 2) 3922 /* The helper must use entire 64-bit gp registers */ 3923 val |= 1 << 8; 3924 } 3925 3926 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 3927 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 3928 ((void (*)(TCGv_ptr, TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); 3929 break; 3930 default: 3931 goto illegal_op; 3932 } 3933 } else { 3934 /* generic MMX or SSE operation */ 3935 switch(b) { 3936 case 0x70: /* pshufx insn */ 3937 case 0xc6: /* pshufx insn */ 3938 case 0xc2: /* compare insns */ 3939 s->rip_offset = 1; 3940 break; 3941 default: 3942 break; 3943 } 3944 if (is_xmm) { 3945 op1_offset = offsetof(CPUX86State,xmm_regs[reg]); 3946 if (mod != 3) { 3947 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3948 op2_offset = offsetof(CPUX86State,xmm_t0); 3949 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) || 3950 b == 0xc2)) { 3951 /* specific case for SSE single instructions */ 3952 if (b1 == 2) { 3953 /* 32 bit access */ 3954 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 3955 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0))); 3956 } else { 3957 /* 64 bit access */ 3958 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0))); 3959 } 3960 } else { 3961 gen_ldo_env_A0(s->mem_index, op2_offset); 3962 } 3963 } else { 3964 rm = (modrm & 7) | REX_B(s); 3965 op2_offset = offsetof(CPUX86State,xmm_regs[rm]); 3966 } 3967 } else { 3968 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); 3969 if (mod != 3) { 3970 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 3971 op2_offset = offsetof(CPUX86State,mmx_t0); 3972 gen_ldq_env_A0(s->mem_index, op2_offset); 3973 } else { 3974 rm = (modrm & 7); 3975 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); 3976 } 3977 } 3978 switch(b) { 3979 case 0x0f: /* 3DNow! data insns */ 3980 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) 3981 goto illegal_op; 3982 val = ldub_code(s->pc++); 3983 sse_op2 = sse_op_table5[val]; 3984 if (!sse_op2) 3985 goto illegal_op; 3986 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 3987 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 3988 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); 3989 break; 3990 case 0x70: /* pshufx insn */ 3991 case 0xc6: /* pshufx insn */ 3992 val = ldub_code(s->pc++); 3993 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 3994 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 3995 ((void (*)(TCGv_ptr, TCGv_ptr, TCGv_i32))sse_op2)(cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); 3996 break; 3997 case 0xc2: 3998 /* compare insns */ 3999 val = ldub_code(s->pc++); 4000 if (val >= 8) 4001 goto illegal_op; 4002 sse_op2 = sse_op_table4[val][b1]; 4003 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 4004 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 4005 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); 4006 break; 4007 case 0xf7: 4008 /* maskmov : we must prepare A0 */ 4009 if (mod != 3) 4010 goto illegal_op; 4011 #ifdef TARGET_X86_64 4012 if (s->aflag == 2) { 4013 gen_op_movq_A0_reg(R_EDI); 4014 } else 4015 #endif 4016 { 4017 gen_op_movl_A0_reg(R_EDI); 4018 if (s->aflag == 0) 4019 gen_op_andl_A0_ffff(); 4020 } 4021 gen_add_A0_ds_seg(s); 4022 4023 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 4024 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 4025 ((void (*)(TCGv_ptr, TCGv_ptr, TCGv))sse_op2)(cpu_ptr0, cpu_ptr1, cpu_A0); 4026 break; 4027 default: 4028 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); 4029 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); 4030 ((void (*)(TCGv_ptr, TCGv_ptr))sse_op2)(cpu_ptr0, cpu_ptr1); 4031 break; 4032 } 4033 if (b == 0x2e || b == 0x2f) { 4034 s->cc_op = CC_OP_EFLAGS; 4035 } 4036 } 4037 } 4038 4039 /* convert one instruction. s->is_jmp is set if the translation must 4040 be stopped. Return the next pc value */ 4041 static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) 4042 { 4043 int b, prefixes, aflag, dflag; 4044 int shift, ot; 4045 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val; 4046 target_ulong next_eip, tval; 4047 int rex_w, rex_r; 4048 4049 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) 4050 tcg_gen_debug_insn_start(pc_start); 4051 s->pc = pc_start; 4052 prefixes = 0; 4053 aflag = s->code32; 4054 dflag = s->code32; 4055 s->override = -1; 4056 rex_w = -1; 4057 rex_r = 0; 4058 #ifdef TARGET_X86_64 4059 s->rex_x = 0; 4060 s->rex_b = 0; 4061 x86_64_hregs = 0; 4062 #endif 4063 s->rip_offset = 0; /* for relative ip address */ 4064 next_byte: 4065 b = ldub_code(s->pc); 4066 s->pc++; 4067 /* check prefixes */ 4068 #ifdef TARGET_X86_64 4069 if (CODE64(s)) { 4070 switch (b) { 4071 case 0xf3: 4072 prefixes |= PREFIX_REPZ; 4073 goto next_byte; 4074 case 0xf2: 4075 prefixes |= PREFIX_REPNZ; 4076 goto next_byte; 4077 case 0xf0: 4078 prefixes |= PREFIX_LOCK; 4079 goto next_byte; 4080 case 0x2e: 4081 s->override = R_CS; 4082 goto next_byte; 4083 case 0x36: 4084 s->override = R_SS; 4085 goto next_byte; 4086 case 0x3e: 4087 s->override = R_DS; 4088 goto next_byte; 4089 case 0x26: 4090 s->override = R_ES; 4091 goto next_byte; 4092 case 0x64: 4093 s->override = R_FS; 4094 goto next_byte; 4095 case 0x65: 4096 s->override = R_GS; 4097 goto next_byte; 4098 case 0x66: 4099 prefixes |= PREFIX_DATA; 4100 goto next_byte; 4101 case 0x67: 4102 prefixes |= PREFIX_ADR; 4103 goto next_byte; 4104 case 0x40 ... 0x4f: 4105 /* REX prefix */ 4106 rex_w = (b >> 3) & 1; 4107 rex_r = (b & 0x4) << 1; 4108 s->rex_x = (b & 0x2) << 2; 4109 REX_B(s) = (b & 0x1) << 3; 4110 x86_64_hregs = 1; /* select uniform byte register addressing */ 4111 goto next_byte; 4112 } 4113 if (rex_w == 1) { 4114 /* 0x66 is ignored if rex.w is set */ 4115 dflag = 2; 4116 } else { 4117 if (prefixes & PREFIX_DATA) 4118 dflag ^= 1; 4119 } 4120 if (!(prefixes & PREFIX_ADR)) 4121 aflag = 2; 4122 } else 4123 #endif 4124 { 4125 switch (b) { 4126 case 0xf3: 4127 prefixes |= PREFIX_REPZ; 4128 goto next_byte; 4129 case 0xf2: 4130 prefixes |= PREFIX_REPNZ; 4131 goto next_byte; 4132 case 0xf0: 4133 prefixes |= PREFIX_LOCK; 4134 goto next_byte; 4135 case 0x2e: 4136 s->override = R_CS; 4137 goto next_byte; 4138 case 0x36: 4139 s->override = R_SS; 4140 goto next_byte; 4141 case 0x3e: 4142 s->override = R_DS; 4143 goto next_byte; 4144 case 0x26: 4145 s->override = R_ES; 4146 goto next_byte; 4147 case 0x64: 4148 s->override = R_FS; 4149 goto next_byte; 4150 case 0x65: 4151 s->override = R_GS; 4152 goto next_byte; 4153 case 0x66: 4154 prefixes |= PREFIX_DATA; 4155 goto next_byte; 4156 case 0x67: 4157 prefixes |= PREFIX_ADR; 4158 goto next_byte; 4159 } 4160 if (prefixes & PREFIX_DATA) 4161 dflag ^= 1; 4162 if (prefixes & PREFIX_ADR) 4163 aflag ^= 1; 4164 } 4165 4166 s->prefix = prefixes; 4167 s->aflag = aflag; 4168 s->dflag = dflag; 4169 4170 /* lock generation */ 4171 if (prefixes & PREFIX_LOCK) 4172 gen_helper_lock(); 4173 4174 /* now check op code */ 4175 reswitch: 4176 switch(b) { 4177 case 0x0f: 4178 /**************************/ 4179 /* extended op code */ 4180 b = ldub_code(s->pc++) | 0x100; 4181 goto reswitch; 4182 4183 /**************************/ 4184 /* arith & logic */ 4185 case 0x00 ... 0x05: 4186 case 0x08 ... 0x0d: 4187 case 0x10 ... 0x15: 4188 case 0x18 ... 0x1d: 4189 case 0x20 ... 0x25: 4190 case 0x28 ... 0x2d: 4191 case 0x30 ... 0x35: 4192 case 0x38 ... 0x3d: 4193 { 4194 int op, f, val; 4195 op = (b >> 3) & 7; 4196 f = (b >> 1) & 3; 4197 4198 if ((b & 1) == 0) 4199 ot = OT_BYTE; 4200 else 4201 ot = dflag + OT_WORD; 4202 4203 switch(f) { 4204 case 0: /* OP Ev, Gv */ 4205 modrm = ldub_code(s->pc++); 4206 reg = ((modrm >> 3) & 7) | rex_r; 4207 mod = (modrm >> 6) & 3; 4208 rm = (modrm & 7) | REX_B(s); 4209 if (mod != 3) { 4210 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4211 opreg = OR_TMP0; 4212 } else if (op == OP_XORL && rm == reg) { 4213 xor_zero: 4214 /* xor reg, reg optimisation */ 4215 gen_op_movl_T0_0(); 4216 s->cc_op = CC_OP_LOGICB + ot; 4217 gen_op_mov_reg_T0(ot, reg); 4218 gen_op_update1_cc(); 4219 break; 4220 } else { 4221 opreg = rm; 4222 } 4223 gen_op_mov_TN_reg(ot, 1, reg); 4224 gen_op(s, op, ot, opreg); 4225 break; 4226 case 1: /* OP Gv, Ev */ 4227 modrm = ldub_code(s->pc++); 4228 mod = (modrm >> 6) & 3; 4229 reg = ((modrm >> 3) & 7) | rex_r; 4230 rm = (modrm & 7) | REX_B(s); 4231 if (mod != 3) { 4232 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4233 gen_op_ld_T1_A0(ot + s->mem_index); 4234 } else if (op == OP_XORL && rm == reg) { 4235 goto xor_zero; 4236 } else { 4237 gen_op_mov_TN_reg(ot, 1, rm); 4238 } 4239 gen_op(s, op, ot, reg); 4240 break; 4241 case 2: /* OP A, Iv */ 4242 val = insn_get(s, ot); 4243 gen_op_movl_T1_im(val); 4244 gen_op(s, op, ot, OR_EAX); 4245 break; 4246 } 4247 } 4248 break; 4249 4250 case 0x82: 4251 if (CODE64(s)) 4252 goto illegal_op; 4253 case 0x80: /* GRP1 */ 4254 case 0x81: 4255 case 0x83: 4256 { 4257 int val; 4258 4259 if ((b & 1) == 0) 4260 ot = OT_BYTE; 4261 else 4262 ot = dflag + OT_WORD; 4263 4264 modrm = ldub_code(s->pc++); 4265 mod = (modrm >> 6) & 3; 4266 rm = (modrm & 7) | REX_B(s); 4267 op = (modrm >> 3) & 7; 4268 4269 if (mod != 3) { 4270 if (b == 0x83) 4271 s->rip_offset = 1; 4272 else 4273 s->rip_offset = insn_const_size(ot); 4274 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4275 opreg = OR_TMP0; 4276 } else { 4277 opreg = rm; 4278 } 4279 4280 switch(b) { 4281 default: 4282 case 0x80: 4283 case 0x81: 4284 case 0x82: 4285 val = insn_get(s, ot); 4286 break; 4287 case 0x83: 4288 val = (int8_t)insn_get(s, OT_BYTE); 4289 break; 4290 } 4291 gen_op_movl_T1_im(val); 4292 gen_op(s, op, ot, opreg); 4293 } 4294 break; 4295 4296 /**************************/ 4297 /* inc, dec, and other misc arith */ 4298 case 0x40 ... 0x47: /* inc Gv */ 4299 ot = dflag ? OT_LONG : OT_WORD; 4300 gen_inc(s, ot, OR_EAX + (b & 7), 1); 4301 break; 4302 case 0x48 ... 0x4f: /* dec Gv */ 4303 ot = dflag ? OT_LONG : OT_WORD; 4304 gen_inc(s, ot, OR_EAX + (b & 7), -1); 4305 break; 4306 case 0xf6: /* GRP3 */ 4307 case 0xf7: 4308 if ((b & 1) == 0) 4309 ot = OT_BYTE; 4310 else 4311 ot = dflag + OT_WORD; 4312 4313 modrm = ldub_code(s->pc++); 4314 mod = (modrm >> 6) & 3; 4315 rm = (modrm & 7) | REX_B(s); 4316 op = (modrm >> 3) & 7; 4317 if (mod != 3) { 4318 if (op == 0) 4319 s->rip_offset = insn_const_size(ot); 4320 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4321 gen_op_ld_T0_A0(ot + s->mem_index); 4322 } else { 4323 gen_op_mov_TN_reg(ot, 0, rm); 4324 } 4325 4326 switch(op) { 4327 case 0: /* test */ 4328 val = insn_get(s, ot); 4329 gen_op_movl_T1_im(val); 4330 gen_op_testl_T0_T1_cc(); 4331 s->cc_op = CC_OP_LOGICB + ot; 4332 break; 4333 case 2: /* not */ 4334 tcg_gen_not_tl(cpu_T[0], cpu_T[0]); 4335 if (mod != 3) { 4336 gen_op_st_T0_A0(ot + s->mem_index); 4337 } else { 4338 gen_op_mov_reg_T0(ot, rm); 4339 } 4340 break; 4341 case 3: /* neg */ 4342 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]); 4343 if (mod != 3) { 4344 gen_op_st_T0_A0(ot + s->mem_index); 4345 } else { 4346 gen_op_mov_reg_T0(ot, rm); 4347 } 4348 gen_op_update_neg_cc(); 4349 s->cc_op = CC_OP_SUBB + ot; 4350 break; 4351 case 4: /* mul */ 4352 switch(ot) { 4353 case OT_BYTE: 4354 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX); 4355 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]); 4356 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]); 4357 /* XXX: use 32 bit mul which could be faster */ 4358 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 4359 gen_op_mov_reg_T0(OT_WORD, R_EAX); 4360 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4361 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00); 4362 s->cc_op = CC_OP_MULB; 4363 break; 4364 case OT_WORD: 4365 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX); 4366 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); 4367 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]); 4368 /* XXX: use 32 bit mul which could be faster */ 4369 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 4370 gen_op_mov_reg_T0(OT_WORD, R_EAX); 4371 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4372 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16); 4373 gen_op_mov_reg_T0(OT_WORD, R_EDX); 4374 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); 4375 s->cc_op = CC_OP_MULW; 4376 break; 4377 default: 4378 case OT_LONG: 4379 #ifdef TARGET_X86_64 4380 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); 4381 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); 4382 tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); 4383 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 4384 gen_op_mov_reg_T0(OT_LONG, R_EAX); 4385 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4386 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32); 4387 gen_op_mov_reg_T0(OT_LONG, R_EDX); 4388 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); 4389 #else 4390 { 4391 TCGv_i64 t0, t1; 4392 t0 = tcg_temp_new_i64(); 4393 t1 = tcg_temp_new_i64(); 4394 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); 4395 tcg_gen_extu_i32_i64(t0, cpu_T[0]); 4396 tcg_gen_extu_i32_i64(t1, cpu_T[1]); 4397 tcg_gen_mul_i64(t0, t0, t1); 4398 tcg_gen_trunc_i64_i32(cpu_T[0], t0); 4399 gen_op_mov_reg_T0(OT_LONG, R_EAX); 4400 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4401 tcg_gen_shri_i64(t0, t0, 32); 4402 tcg_gen_trunc_i64_i32(cpu_T[0], t0); 4403 gen_op_mov_reg_T0(OT_LONG, R_EDX); 4404 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); 4405 } 4406 #endif 4407 s->cc_op = CC_OP_MULL; 4408 break; 4409 #ifdef TARGET_X86_64 4410 case OT_QUAD: 4411 gen_helper_mulq_EAX_T0(cpu_T[0]); 4412 s->cc_op = CC_OP_MULQ; 4413 break; 4414 #endif 4415 } 4416 break; 4417 case 5: /* imul */ 4418 switch(ot) { 4419 case OT_BYTE: 4420 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX); 4421 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]); 4422 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]); 4423 /* XXX: use 32 bit mul which could be faster */ 4424 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 4425 gen_op_mov_reg_T0(OT_WORD, R_EAX); 4426 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4427 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]); 4428 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); 4429 s->cc_op = CC_OP_MULB; 4430 break; 4431 case OT_WORD: 4432 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX); 4433 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); 4434 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]); 4435 /* XXX: use 32 bit mul which could be faster */ 4436 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 4437 gen_op_mov_reg_T0(OT_WORD, R_EAX); 4438 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4439 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]); 4440 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); 4441 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16); 4442 gen_op_mov_reg_T0(OT_WORD, R_EDX); 4443 s->cc_op = CC_OP_MULW; 4444 break; 4445 default: 4446 case OT_LONG: 4447 #ifdef TARGET_X86_64 4448 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); 4449 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); 4450 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); 4451 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 4452 gen_op_mov_reg_T0(OT_LONG, R_EAX); 4453 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4454 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]); 4455 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); 4456 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32); 4457 gen_op_mov_reg_T0(OT_LONG, R_EDX); 4458 #else 4459 { 4460 TCGv_i64 t0, t1; 4461 t0 = tcg_temp_new_i64(); 4462 t1 = tcg_temp_new_i64(); 4463 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX); 4464 tcg_gen_ext_i32_i64(t0, cpu_T[0]); 4465 tcg_gen_ext_i32_i64(t1, cpu_T[1]); 4466 tcg_gen_mul_i64(t0, t0, t1); 4467 tcg_gen_trunc_i64_i32(cpu_T[0], t0); 4468 gen_op_mov_reg_T0(OT_LONG, R_EAX); 4469 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4470 tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31); 4471 tcg_gen_shri_i64(t0, t0, 32); 4472 tcg_gen_trunc_i64_i32(cpu_T[0], t0); 4473 gen_op_mov_reg_T0(OT_LONG, R_EDX); 4474 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); 4475 } 4476 #endif 4477 s->cc_op = CC_OP_MULL; 4478 break; 4479 #ifdef TARGET_X86_64 4480 case OT_QUAD: 4481 gen_helper_imulq_EAX_T0(cpu_T[0]); 4482 s->cc_op = CC_OP_MULQ; 4483 break; 4484 #endif 4485 } 4486 break; 4487 case 6: /* div */ 4488 switch(ot) { 4489 case OT_BYTE: 4490 gen_jmp_im(pc_start - s->cs_base); 4491 gen_helper_divb_AL(cpu_T[0]); 4492 break; 4493 case OT_WORD: 4494 gen_jmp_im(pc_start - s->cs_base); 4495 gen_helper_divw_AX(cpu_T[0]); 4496 break; 4497 default: 4498 case OT_LONG: 4499 gen_jmp_im(pc_start - s->cs_base); 4500 gen_helper_divl_EAX(cpu_T[0]); 4501 break; 4502 #ifdef TARGET_X86_64 4503 case OT_QUAD: 4504 gen_jmp_im(pc_start - s->cs_base); 4505 gen_helper_divq_EAX(cpu_T[0]); 4506 break; 4507 #endif 4508 } 4509 break; 4510 case 7: /* idiv */ 4511 switch(ot) { 4512 case OT_BYTE: 4513 gen_jmp_im(pc_start - s->cs_base); 4514 gen_helper_idivb_AL(cpu_T[0]); 4515 break; 4516 case OT_WORD: 4517 gen_jmp_im(pc_start - s->cs_base); 4518 gen_helper_idivw_AX(cpu_T[0]); 4519 break; 4520 default: 4521 case OT_LONG: 4522 gen_jmp_im(pc_start - s->cs_base); 4523 gen_helper_idivl_EAX(cpu_T[0]); 4524 break; 4525 #ifdef TARGET_X86_64 4526 case OT_QUAD: 4527 gen_jmp_im(pc_start - s->cs_base); 4528 gen_helper_idivq_EAX(cpu_T[0]); 4529 break; 4530 #endif 4531 } 4532 break; 4533 default: 4534 goto illegal_op; 4535 } 4536 break; 4537 4538 case 0xfe: /* GRP4 */ 4539 case 0xff: /* GRP5 */ 4540 if ((b & 1) == 0) 4541 ot = OT_BYTE; 4542 else 4543 ot = dflag + OT_WORD; 4544 4545 modrm = ldub_code(s->pc++); 4546 mod = (modrm >> 6) & 3; 4547 rm = (modrm & 7) | REX_B(s); 4548 op = (modrm >> 3) & 7; 4549 if (op >= 2 && b == 0xfe) { 4550 goto illegal_op; 4551 } 4552 if (CODE64(s)) { 4553 if (op == 2 || op == 4) { 4554 /* operand size for jumps is 64 bit */ 4555 ot = OT_QUAD; 4556 } else if (op == 3 || op == 5) { 4557 /* for call calls, the operand is 16 or 32 bit, even 4558 in long mode */ 4559 ot = dflag ? OT_LONG : OT_WORD; 4560 } else if (op == 6) { 4561 /* default push size is 64 bit */ 4562 ot = dflag ? OT_QUAD : OT_WORD; 4563 } 4564 } 4565 if (mod != 3) { 4566 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4567 if (op >= 2 && op != 3 && op != 5) 4568 gen_op_ld_T0_A0(ot + s->mem_index); 4569 } else { 4570 gen_op_mov_TN_reg(ot, 0, rm); 4571 } 4572 4573 switch(op) { 4574 case 0: /* inc Ev */ 4575 if (mod != 3) 4576 opreg = OR_TMP0; 4577 else 4578 opreg = rm; 4579 gen_inc(s, ot, opreg, 1); 4580 break; 4581 case 1: /* dec Ev */ 4582 if (mod != 3) 4583 opreg = OR_TMP0; 4584 else 4585 opreg = rm; 4586 gen_inc(s, ot, opreg, -1); 4587 break; 4588 case 2: /* call Ev */ 4589 /* XXX: optimize if memory (no 'and' is necessary) */ 4590 if (s->dflag == 0) 4591 gen_op_andl_T0_ffff(); 4592 next_eip = s->pc - s->cs_base; 4593 gen_movtl_T1_im(next_eip); 4594 gen_push_T1(s); 4595 gen_op_jmp_T0(); 4596 gen_eob(s); 4597 break; 4598 case 3: /* lcall Ev */ 4599 gen_op_ld_T1_A0(ot + s->mem_index); 4600 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); 4601 gen_op_ldu_T0_A0(OT_WORD + s->mem_index); 4602 do_lcall: 4603 if (s->pe && !s->vm86) { 4604 if (s->cc_op != CC_OP_DYNAMIC) 4605 gen_op_set_cc_op(s->cc_op); 4606 gen_jmp_im(pc_start - s->cs_base); 4607 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 4608 gen_helper_lcall_protected(cpu_tmp2_i32, cpu_T[1], 4609 tcg_const_i32(dflag), 4610 tcg_const_i32(s->pc - pc_start)); 4611 } else { 4612 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 4613 gen_helper_lcall_real(cpu_tmp2_i32, cpu_T[1], 4614 tcg_const_i32(dflag), 4615 tcg_const_i32(s->pc - s->cs_base)); 4616 } 4617 gen_eob(s); 4618 break; 4619 case 4: /* jmp Ev */ 4620 if (s->dflag == 0) 4621 gen_op_andl_T0_ffff(); 4622 gen_op_jmp_T0(); 4623 gen_eob(s); 4624 break; 4625 case 5: /* ljmp Ev */ 4626 gen_op_ld_T1_A0(ot + s->mem_index); 4627 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); 4628 gen_op_ldu_T0_A0(OT_WORD + s->mem_index); 4629 do_ljmp: 4630 if (s->pe && !s->vm86) { 4631 if (s->cc_op != CC_OP_DYNAMIC) 4632 gen_op_set_cc_op(s->cc_op); 4633 gen_jmp_im(pc_start - s->cs_base); 4634 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 4635 gen_helper_ljmp_protected(cpu_tmp2_i32, cpu_T[1], 4636 tcg_const_i32(s->pc - pc_start)); 4637 } else { 4638 gen_op_movl_seg_T0_vm(R_CS); 4639 gen_op_movl_T0_T1(); 4640 gen_op_jmp_T0(); 4641 } 4642 gen_eob(s); 4643 break; 4644 case 6: /* push Ev */ 4645 gen_push_T0(s); 4646 break; 4647 default: 4648 goto illegal_op; 4649 } 4650 break; 4651 4652 case 0x84: /* test Ev, Gv */ 4653 case 0x85: 4654 if ((b & 1) == 0) 4655 ot = OT_BYTE; 4656 else 4657 ot = dflag + OT_WORD; 4658 4659 modrm = ldub_code(s->pc++); 4660 mod = (modrm >> 6) & 3; 4661 rm = (modrm & 7) | REX_B(s); 4662 reg = ((modrm >> 3) & 7) | rex_r; 4663 4664 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 4665 gen_op_mov_TN_reg(ot, 1, reg); 4666 gen_op_testl_T0_T1_cc(); 4667 s->cc_op = CC_OP_LOGICB + ot; 4668 break; 4669 4670 case 0xa8: /* test eAX, Iv */ 4671 case 0xa9: 4672 if ((b & 1) == 0) 4673 ot = OT_BYTE; 4674 else 4675 ot = dflag + OT_WORD; 4676 val = insn_get(s, ot); 4677 4678 gen_op_mov_TN_reg(ot, 0, OR_EAX); 4679 gen_op_movl_T1_im(val); 4680 gen_op_testl_T0_T1_cc(); 4681 s->cc_op = CC_OP_LOGICB + ot; 4682 break; 4683 4684 case 0x98: /* CWDE/CBW */ 4685 #ifdef TARGET_X86_64 4686 if (dflag == 2) { 4687 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); 4688 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); 4689 gen_op_mov_reg_T0(OT_QUAD, R_EAX); 4690 } else 4691 #endif 4692 if (dflag == 1) { 4693 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX); 4694 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); 4695 gen_op_mov_reg_T0(OT_LONG, R_EAX); 4696 } else { 4697 gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX); 4698 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]); 4699 gen_op_mov_reg_T0(OT_WORD, R_EAX); 4700 } 4701 break; 4702 case 0x99: /* CDQ/CWD */ 4703 #ifdef TARGET_X86_64 4704 if (dflag == 2) { 4705 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX); 4706 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63); 4707 gen_op_mov_reg_T0(OT_QUAD, R_EDX); 4708 } else 4709 #endif 4710 if (dflag == 1) { 4711 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); 4712 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); 4713 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31); 4714 gen_op_mov_reg_T0(OT_LONG, R_EDX); 4715 } else { 4716 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX); 4717 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); 4718 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15); 4719 gen_op_mov_reg_T0(OT_WORD, R_EDX); 4720 } 4721 break; 4722 case 0x1af: /* imul Gv, Ev */ 4723 case 0x69: /* imul Gv, Ev, I */ 4724 case 0x6b: 4725 ot = dflag + OT_WORD; 4726 modrm = ldub_code(s->pc++); 4727 reg = ((modrm >> 3) & 7) | rex_r; 4728 if (b == 0x69) 4729 s->rip_offset = insn_const_size(ot); 4730 else if (b == 0x6b) 4731 s->rip_offset = 1; 4732 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 4733 if (b == 0x69) { 4734 val = insn_get(s, ot); 4735 gen_op_movl_T1_im(val); 4736 } else if (b == 0x6b) { 4737 val = (int8_t)insn_get(s, OT_BYTE); 4738 gen_op_movl_T1_im(val); 4739 } else { 4740 gen_op_mov_TN_reg(ot, 1, reg); 4741 } 4742 4743 #ifdef TARGET_X86_64 4744 if (ot == OT_QUAD) { 4745 gen_helper_imulq_T0_T1(cpu_T[0], cpu_T[0], cpu_T[1]); 4746 } else 4747 #endif 4748 if (ot == OT_LONG) { 4749 #ifdef TARGET_X86_64 4750 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); 4751 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); 4752 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 4753 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4754 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]); 4755 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); 4756 #else 4757 { 4758 TCGv_i64 t0, t1; 4759 t0 = tcg_temp_new_i64(); 4760 t1 = tcg_temp_new_i64(); 4761 tcg_gen_ext_i32_i64(t0, cpu_T[0]); 4762 tcg_gen_ext_i32_i64(t1, cpu_T[1]); 4763 tcg_gen_mul_i64(t0, t0, t1); 4764 tcg_gen_trunc_i64_i32(cpu_T[0], t0); 4765 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4766 tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31); 4767 tcg_gen_shri_i64(t0, t0, 32); 4768 tcg_gen_trunc_i64_i32(cpu_T[1], t0); 4769 tcg_gen_sub_tl(cpu_cc_src, cpu_T[1], cpu_tmp0); 4770 } 4771 #endif 4772 } else { 4773 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); 4774 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]); 4775 /* XXX: use 32 bit mul which could be faster */ 4776 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]); 4777 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); 4778 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]); 4779 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0); 4780 } 4781 gen_op_mov_reg_T0(ot, reg); 4782 s->cc_op = CC_OP_MULB + ot; 4783 break; 4784 case 0x1c0: 4785 case 0x1c1: /* xadd Ev, Gv */ 4786 if ((b & 1) == 0) 4787 ot = OT_BYTE; 4788 else 4789 ot = dflag + OT_WORD; 4790 modrm = ldub_code(s->pc++); 4791 reg = ((modrm >> 3) & 7) | rex_r; 4792 mod = (modrm >> 6) & 3; 4793 if (mod == 3) { 4794 rm = (modrm & 7) | REX_B(s); 4795 gen_op_mov_TN_reg(ot, 0, reg); 4796 gen_op_mov_TN_reg(ot, 1, rm); 4797 gen_op_addl_T0_T1(); 4798 gen_op_mov_reg_T1(ot, reg); 4799 gen_op_mov_reg_T0(ot, rm); 4800 } else { 4801 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4802 gen_op_mov_TN_reg(ot, 0, reg); 4803 gen_op_ld_T1_A0(ot + s->mem_index); 4804 gen_op_addl_T0_T1(); 4805 gen_op_st_T0_A0(ot + s->mem_index); 4806 gen_op_mov_reg_T1(ot, reg); 4807 } 4808 gen_op_update2_cc(); 4809 s->cc_op = CC_OP_ADDB + ot; 4810 break; 4811 case 0x1b0: 4812 case 0x1b1: /* cmpxchg Ev, Gv */ 4813 { 4814 int label1, label2; 4815 TCGv t0, t1, t2, a0; 4816 4817 if ((b & 1) == 0) 4818 ot = OT_BYTE; 4819 else 4820 ot = dflag + OT_WORD; 4821 modrm = ldub_code(s->pc++); 4822 reg = ((modrm >> 3) & 7) | rex_r; 4823 mod = (modrm >> 6) & 3; 4824 t0 = tcg_temp_local_new(); 4825 t1 = tcg_temp_local_new(); 4826 t2 = tcg_temp_local_new(); 4827 a0 = tcg_temp_local_new(); 4828 gen_op_mov_v_reg(ot, t1, reg); 4829 if (mod == 3) { 4830 rm = (modrm & 7) | REX_B(s); 4831 gen_op_mov_v_reg(ot, t0, rm); 4832 } else { 4833 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4834 tcg_gen_mov_tl(a0, cpu_A0); 4835 gen_op_ld_v(ot + s->mem_index, t0, a0); 4836 rm = 0; /* avoid warning */ 4837 } 4838 label1 = gen_new_label(); 4839 tcg_gen_ld_tl(t2, cpu_env, offsetof(CPUState, regs[R_EAX])); 4840 tcg_gen_sub_tl(t2, t2, t0); 4841 gen_extu(ot, t2); 4842 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1); 4843 if (mod == 3) { 4844 label2 = gen_new_label(); 4845 gen_op_mov_reg_v(ot, R_EAX, t0); 4846 tcg_gen_br(label2); 4847 gen_set_label(label1); 4848 gen_op_mov_reg_v(ot, rm, t1); 4849 gen_set_label(label2); 4850 } else { 4851 tcg_gen_mov_tl(t1, t0); 4852 gen_op_mov_reg_v(ot, R_EAX, t0); 4853 gen_set_label(label1); 4854 /* always store */ 4855 gen_op_st_v(ot + s->mem_index, t1, a0); 4856 } 4857 tcg_gen_mov_tl(cpu_cc_src, t0); 4858 tcg_gen_mov_tl(cpu_cc_dst, t2); 4859 s->cc_op = CC_OP_SUBB + ot; 4860 tcg_temp_free(t0); 4861 tcg_temp_free(t1); 4862 tcg_temp_free(t2); 4863 tcg_temp_free(a0); 4864 } 4865 break; 4866 case 0x1c7: /* cmpxchg8b */ 4867 modrm = ldub_code(s->pc++); 4868 mod = (modrm >> 6) & 3; 4869 if ((mod == 3) || ((modrm & 0x38) != 0x8)) 4870 goto illegal_op; 4871 #ifdef TARGET_X86_64 4872 if (dflag == 2) { 4873 if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) 4874 goto illegal_op; 4875 gen_jmp_im(pc_start - s->cs_base); 4876 if (s->cc_op != CC_OP_DYNAMIC) 4877 gen_op_set_cc_op(s->cc_op); 4878 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4879 gen_helper_cmpxchg16b(cpu_A0); 4880 } else 4881 #endif 4882 { 4883 if (!(s->cpuid_features & CPUID_CX8)) 4884 goto illegal_op; 4885 gen_jmp_im(pc_start - s->cs_base); 4886 if (s->cc_op != CC_OP_DYNAMIC) 4887 gen_op_set_cc_op(s->cc_op); 4888 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 4889 gen_helper_cmpxchg8b(cpu_A0); 4890 } 4891 s->cc_op = CC_OP_EFLAGS; 4892 break; 4893 4894 /**************************/ 4895 /* push/pop */ 4896 case 0x50 ... 0x57: /* push */ 4897 gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s)); 4898 gen_push_T0(s); 4899 break; 4900 case 0x58 ... 0x5f: /* pop */ 4901 if (CODE64(s)) { 4902 ot = dflag ? OT_QUAD : OT_WORD; 4903 } else { 4904 ot = dflag + OT_WORD; 4905 } 4906 gen_pop_T0(s); 4907 /* NOTE: order is important for pop %sp */ 4908 gen_pop_update(s); 4909 gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s)); 4910 break; 4911 case 0x60: /* pusha */ 4912 if (CODE64(s)) 4913 goto illegal_op; 4914 gen_pusha(s); 4915 break; 4916 case 0x61: /* popa */ 4917 if (CODE64(s)) 4918 goto illegal_op; 4919 gen_popa(s); 4920 break; 4921 case 0x68: /* push Iv */ 4922 case 0x6a: 4923 if (CODE64(s)) { 4924 ot = dflag ? OT_QUAD : OT_WORD; 4925 } else { 4926 ot = dflag + OT_WORD; 4927 } 4928 if (b == 0x68) 4929 val = insn_get(s, ot); 4930 else 4931 val = (int8_t)insn_get(s, OT_BYTE); 4932 gen_op_movl_T0_im(val); 4933 gen_push_T0(s); 4934 break; 4935 case 0x8f: /* pop Ev */ 4936 if (CODE64(s)) { 4937 ot = dflag ? OT_QUAD : OT_WORD; 4938 } else { 4939 ot = dflag + OT_WORD; 4940 } 4941 modrm = ldub_code(s->pc++); 4942 mod = (modrm >> 6) & 3; 4943 gen_pop_T0(s); 4944 if (mod == 3) { 4945 /* NOTE: order is important for pop %sp */ 4946 gen_pop_update(s); 4947 rm = (modrm & 7) | REX_B(s); 4948 gen_op_mov_reg_T0(ot, rm); 4949 } else { 4950 /* NOTE: order is important too for MMU exceptions */ 4951 s->popl_esp_hack = 1 << ot; 4952 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); 4953 s->popl_esp_hack = 0; 4954 gen_pop_update(s); 4955 } 4956 break; 4957 case 0xc8: /* enter */ 4958 { 4959 int level; 4960 val = lduw_code(s->pc); 4961 s->pc += 2; 4962 level = ldub_code(s->pc++); 4963 gen_enter(s, val, level); 4964 } 4965 break; 4966 case 0xc9: /* leave */ 4967 /* XXX: exception not precise (ESP is updated before potential exception) */ 4968 if (CODE64(s)) { 4969 gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP); 4970 gen_op_mov_reg_T0(OT_QUAD, R_ESP); 4971 } else if (s->ss32) { 4972 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); 4973 gen_op_mov_reg_T0(OT_LONG, R_ESP); 4974 } else { 4975 gen_op_mov_TN_reg(OT_WORD, 0, R_EBP); 4976 gen_op_mov_reg_T0(OT_WORD, R_ESP); 4977 } 4978 gen_pop_T0(s); 4979 if (CODE64(s)) { 4980 ot = dflag ? OT_QUAD : OT_WORD; 4981 } else { 4982 ot = dflag + OT_WORD; 4983 } 4984 gen_op_mov_reg_T0(ot, R_EBP); 4985 gen_pop_update(s); 4986 break; 4987 case 0x06: /* push es */ 4988 case 0x0e: /* push cs */ 4989 case 0x16: /* push ss */ 4990 case 0x1e: /* push ds */ 4991 if (CODE64(s)) 4992 goto illegal_op; 4993 gen_op_movl_T0_seg(b >> 3); 4994 gen_push_T0(s); 4995 break; 4996 case 0x1a0: /* push fs */ 4997 case 0x1a8: /* push gs */ 4998 gen_op_movl_T0_seg((b >> 3) & 7); 4999 gen_push_T0(s); 5000 break; 5001 case 0x07: /* pop es */ 5002 case 0x17: /* pop ss */ 5003 case 0x1f: /* pop ds */ 5004 if (CODE64(s)) 5005 goto illegal_op; 5006 reg = b >> 3; 5007 gen_pop_T0(s); 5008 gen_movl_seg_T0(s, reg, pc_start - s->cs_base); 5009 gen_pop_update(s); 5010 if (reg == R_SS) { 5011 /* if reg == SS, inhibit interrupts/trace. */ 5012 /* If several instructions disable interrupts, only the 5013 _first_ does it */ 5014 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) 5015 gen_helper_set_inhibit_irq(); 5016 s->tf = 0; 5017 } 5018 if (s->is_jmp) { 5019 gen_jmp_im(s->pc - s->cs_base); 5020 gen_eob(s); 5021 } 5022 break; 5023 case 0x1a1: /* pop fs */ 5024 case 0x1a9: /* pop gs */ 5025 gen_pop_T0(s); 5026 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base); 5027 gen_pop_update(s); 5028 if (s->is_jmp) { 5029 gen_jmp_im(s->pc - s->cs_base); 5030 gen_eob(s); 5031 } 5032 break; 5033 5034 /**************************/ 5035 /* mov */ 5036 case 0x88: 5037 case 0x89: /* mov Gv, Ev */ 5038 if ((b & 1) == 0) 5039 ot = OT_BYTE; 5040 else 5041 ot = dflag + OT_WORD; 5042 modrm = ldub_code(s->pc++); 5043 reg = ((modrm >> 3) & 7) | rex_r; 5044 5045 /* generate a generic store */ 5046 gen_ldst_modrm(s, modrm, ot, reg, 1); 5047 break; 5048 case 0xc6: 5049 case 0xc7: /* mov Ev, Iv */ 5050 if ((b & 1) == 0) 5051 ot = OT_BYTE; 5052 else 5053 ot = dflag + OT_WORD; 5054 modrm = ldub_code(s->pc++); 5055 mod = (modrm >> 6) & 3; 5056 if (mod != 3) { 5057 s->rip_offset = insn_const_size(ot); 5058 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 5059 } 5060 val = insn_get(s, ot); 5061 gen_op_movl_T0_im(val); 5062 if (mod != 3) 5063 gen_op_st_T0_A0(ot + s->mem_index); 5064 else 5065 gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s)); 5066 break; 5067 case 0x8a: 5068 case 0x8b: /* mov Ev, Gv */ 5069 if ((b & 1) == 0) 5070 ot = OT_BYTE; 5071 else 5072 ot = OT_WORD + dflag; 5073 modrm = ldub_code(s->pc++); 5074 reg = ((modrm >> 3) & 7) | rex_r; 5075 5076 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 5077 gen_op_mov_reg_T0(ot, reg); 5078 break; 5079 case 0x8e: /* mov seg, Gv */ 5080 modrm = ldub_code(s->pc++); 5081 reg = (modrm >> 3) & 7; 5082 if (reg >= 6 || reg == R_CS) 5083 goto illegal_op; 5084 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); 5085 gen_movl_seg_T0(s, reg, pc_start - s->cs_base); 5086 if (reg == R_SS) { 5087 /* if reg == SS, inhibit interrupts/trace */ 5088 /* If several instructions disable interrupts, only the 5089 _first_ does it */ 5090 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) 5091 gen_helper_set_inhibit_irq(); 5092 s->tf = 0; 5093 } 5094 if (s->is_jmp) { 5095 gen_jmp_im(s->pc - s->cs_base); 5096 gen_eob(s); 5097 } 5098 break; 5099 case 0x8c: /* mov Gv, seg */ 5100 modrm = ldub_code(s->pc++); 5101 reg = (modrm >> 3) & 7; 5102 mod = (modrm >> 6) & 3; 5103 if (reg >= 6) 5104 goto illegal_op; 5105 gen_op_movl_T0_seg(reg); 5106 if (mod == 3) 5107 ot = OT_WORD + dflag; 5108 else 5109 ot = OT_WORD; 5110 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); 5111 break; 5112 5113 case 0x1b6: /* movzbS Gv, Eb */ 5114 case 0x1b7: /* movzwS Gv, Eb */ 5115 case 0x1be: /* movsbS Gv, Eb */ 5116 case 0x1bf: /* movswS Gv, Eb */ 5117 { 5118 int d_ot; 5119 /* d_ot is the size of destination */ 5120 d_ot = dflag + OT_WORD; 5121 /* ot is the size of source */ 5122 ot = (b & 1) + OT_BYTE; 5123 modrm = ldub_code(s->pc++); 5124 reg = ((modrm >> 3) & 7) | rex_r; 5125 mod = (modrm >> 6) & 3; 5126 rm = (modrm & 7) | REX_B(s); 5127 5128 if (mod == 3) { 5129 gen_op_mov_TN_reg(ot, 0, rm); 5130 switch(ot | (b & 8)) { 5131 case OT_BYTE: 5132 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]); 5133 break; 5134 case OT_BYTE | 8: 5135 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]); 5136 break; 5137 case OT_WORD: 5138 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); 5139 break; 5140 default: 5141 case OT_WORD | 8: 5142 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]); 5143 break; 5144 } 5145 gen_op_mov_reg_T0(d_ot, reg); 5146 } else { 5147 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 5148 if (b & 8) { 5149 gen_op_lds_T0_A0(ot + s->mem_index); 5150 } else { 5151 gen_op_ldu_T0_A0(ot + s->mem_index); 5152 } 5153 gen_op_mov_reg_T0(d_ot, reg); 5154 } 5155 } 5156 break; 5157 5158 case 0x8d: /* lea */ 5159 ot = dflag + OT_WORD; 5160 modrm = ldub_code(s->pc++); 5161 mod = (modrm >> 6) & 3; 5162 if (mod == 3) 5163 goto illegal_op; 5164 reg = ((modrm >> 3) & 7) | rex_r; 5165 /* we must ensure that no segment is added */ 5166 s->override = -1; 5167 val = s->addseg; 5168 s->addseg = 0; 5169 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 5170 s->addseg = val; 5171 gen_op_mov_reg_A0(ot - OT_WORD, reg); 5172 break; 5173 5174 case 0xa0: /* mov EAX, Ov */ 5175 case 0xa1: 5176 case 0xa2: /* mov Ov, EAX */ 5177 case 0xa3: 5178 { 5179 target_ulong offset_addr; 5180 5181 if ((b & 1) == 0) 5182 ot = OT_BYTE; 5183 else 5184 ot = dflag + OT_WORD; 5185 #ifdef TARGET_X86_64 5186 if (s->aflag == 2) { 5187 offset_addr = ldq_code(s->pc); 5188 s->pc += 8; 5189 gen_op_movq_A0_im(offset_addr); 5190 } else 5191 #endif 5192 { 5193 if (s->aflag) { 5194 offset_addr = insn_get(s, OT_LONG); 5195 } else { 5196 offset_addr = insn_get(s, OT_WORD); 5197 } 5198 gen_op_movl_A0_im(offset_addr); 5199 } 5200 gen_add_A0_ds_seg(s); 5201 if ((b & 2) == 0) { 5202 gen_op_ld_T0_A0(ot + s->mem_index); 5203 gen_op_mov_reg_T0(ot, R_EAX); 5204 } else { 5205 gen_op_mov_TN_reg(ot, 0, R_EAX); 5206 gen_op_st_T0_A0(ot + s->mem_index); 5207 } 5208 } 5209 break; 5210 case 0xd7: /* xlat */ 5211 #ifdef TARGET_X86_64 5212 if (s->aflag == 2) { 5213 gen_op_movq_A0_reg(R_EBX); 5214 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX); 5215 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff); 5216 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]); 5217 } else 5218 #endif 5219 { 5220 gen_op_movl_A0_reg(R_EBX); 5221 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); 5222 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff); 5223 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]); 5224 if (s->aflag == 0) 5225 gen_op_andl_A0_ffff(); 5226 else 5227 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); 5228 } 5229 gen_add_A0_ds_seg(s); 5230 gen_op_ldu_T0_A0(OT_BYTE + s->mem_index); 5231 gen_op_mov_reg_T0(OT_BYTE, R_EAX); 5232 break; 5233 case 0xb0 ... 0xb7: /* mov R, Ib */ 5234 val = insn_get(s, OT_BYTE); 5235 gen_op_movl_T0_im(val); 5236 gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s)); 5237 break; 5238 case 0xb8 ... 0xbf: /* mov R, Iv */ 5239 #ifdef TARGET_X86_64 5240 if (dflag == 2) { 5241 uint64_t tmp; 5242 /* 64 bit case */ 5243 tmp = ldq_code(s->pc); 5244 s->pc += 8; 5245 reg = (b & 7) | REX_B(s); 5246 gen_movtl_T0_im(tmp); 5247 gen_op_mov_reg_T0(OT_QUAD, reg); 5248 } else 5249 #endif 5250 { 5251 ot = dflag ? OT_LONG : OT_WORD; 5252 val = insn_get(s, ot); 5253 reg = (b & 7) | REX_B(s); 5254 gen_op_movl_T0_im(val); 5255 gen_op_mov_reg_T0(ot, reg); 5256 } 5257 break; 5258 5259 case 0x91 ... 0x97: /* xchg R, EAX */ 5260 ot = dflag + OT_WORD; 5261 reg = (b & 7) | REX_B(s); 5262 rm = R_EAX; 5263 goto do_xchg_reg; 5264 case 0x86: 5265 case 0x87: /* xchg Ev, Gv */ 5266 if ((b & 1) == 0) 5267 ot = OT_BYTE; 5268 else 5269 ot = dflag + OT_WORD; 5270 modrm = ldub_code(s->pc++); 5271 reg = ((modrm >> 3) & 7) | rex_r; 5272 mod = (modrm >> 6) & 3; 5273 if (mod == 3) { 5274 rm = (modrm & 7) | REX_B(s); 5275 do_xchg_reg: 5276 gen_op_mov_TN_reg(ot, 0, reg); 5277 gen_op_mov_TN_reg(ot, 1, rm); 5278 gen_op_mov_reg_T0(ot, rm); 5279 gen_op_mov_reg_T1(ot, reg); 5280 } else { 5281 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 5282 gen_op_mov_TN_reg(ot, 0, reg); 5283 /* for xchg, lock is implicit */ 5284 if (!(prefixes & PREFIX_LOCK)) 5285 gen_helper_lock(); 5286 gen_op_ld_T1_A0(ot + s->mem_index); 5287 gen_op_st_T0_A0(ot + s->mem_index); 5288 if (!(prefixes & PREFIX_LOCK)) 5289 gen_helper_unlock(); 5290 gen_op_mov_reg_T1(ot, reg); 5291 } 5292 break; 5293 case 0xc4: /* les Gv */ 5294 if (CODE64(s)) 5295 goto illegal_op; 5296 op = R_ES; 5297 goto do_lxx; 5298 case 0xc5: /* lds Gv */ 5299 if (CODE64(s)) 5300 goto illegal_op; 5301 op = R_DS; 5302 goto do_lxx; 5303 case 0x1b2: /* lss Gv */ 5304 op = R_SS; 5305 goto do_lxx; 5306 case 0x1b4: /* lfs Gv */ 5307 op = R_FS; 5308 goto do_lxx; 5309 case 0x1b5: /* lgs Gv */ 5310 op = R_GS; 5311 do_lxx: 5312 ot = dflag ? OT_LONG : OT_WORD; 5313 modrm = ldub_code(s->pc++); 5314 reg = ((modrm >> 3) & 7) | rex_r; 5315 mod = (modrm >> 6) & 3; 5316 if (mod == 3) 5317 goto illegal_op; 5318 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 5319 gen_op_ld_T1_A0(ot + s->mem_index); 5320 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); 5321 /* load the segment first to handle exceptions properly */ 5322 gen_op_ldu_T0_A0(OT_WORD + s->mem_index); 5323 gen_movl_seg_T0(s, op, pc_start - s->cs_base); 5324 /* then put the data */ 5325 gen_op_mov_reg_T1(ot, reg); 5326 if (s->is_jmp) { 5327 gen_jmp_im(s->pc - s->cs_base); 5328 gen_eob(s); 5329 } 5330 break; 5331 5332 /************************/ 5333 /* shifts */ 5334 case 0xc0: 5335 case 0xc1: 5336 /* shift Ev,Ib */ 5337 shift = 2; 5338 GRP2: 5339 { 5340 if ((b & 1) == 0) 5341 ot = OT_BYTE; 5342 else 5343 ot = dflag + OT_WORD; 5344 5345 modrm = ldub_code(s->pc++); 5346 mod = (modrm >> 6) & 3; 5347 op = (modrm >> 3) & 7; 5348 5349 if (mod != 3) { 5350 if (shift == 2) { 5351 s->rip_offset = 1; 5352 } 5353 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 5354 opreg = OR_TMP0; 5355 } else { 5356 opreg = (modrm & 7) | REX_B(s); 5357 } 5358 5359 /* simpler op */ 5360 if (shift == 0) { 5361 gen_shift(s, op, ot, opreg, OR_ECX); 5362 } else { 5363 if (shift == 2) { 5364 shift = ldub_code(s->pc++); 5365 } 5366 gen_shifti(s, op, ot, opreg, shift); 5367 } 5368 } 5369 break; 5370 case 0xd0: 5371 case 0xd1: 5372 /* shift Ev,1 */ 5373 shift = 1; 5374 goto GRP2; 5375 case 0xd2: 5376 case 0xd3: 5377 /* shift Ev,cl */ 5378 shift = 0; 5379 goto GRP2; 5380 5381 case 0x1a4: /* shld imm */ 5382 op = 0; 5383 shift = 1; 5384 goto do_shiftd; 5385 case 0x1a5: /* shld cl */ 5386 op = 0; 5387 shift = 0; 5388 goto do_shiftd; 5389 case 0x1ac: /* shrd imm */ 5390 op = 1; 5391 shift = 1; 5392 goto do_shiftd; 5393 case 0x1ad: /* shrd cl */ 5394 op = 1; 5395 shift = 0; 5396 do_shiftd: 5397 ot = dflag + OT_WORD; 5398 modrm = ldub_code(s->pc++); 5399 mod = (modrm >> 6) & 3; 5400 rm = (modrm & 7) | REX_B(s); 5401 reg = ((modrm >> 3) & 7) | rex_r; 5402 if (mod != 3) { 5403 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 5404 opreg = OR_TMP0; 5405 } else { 5406 opreg = rm; 5407 } 5408 gen_op_mov_TN_reg(ot, 1, reg); 5409 5410 if (shift) { 5411 val = ldub_code(s->pc++); 5412 tcg_gen_movi_tl(cpu_T3, val); 5413 } else { 5414 tcg_gen_ld_tl(cpu_T3, cpu_env, offsetof(CPUState, regs[R_ECX])); 5415 } 5416 gen_shiftd_rm_T1_T3(s, ot, opreg, op); 5417 break; 5418 5419 /************************/ 5420 /* floats */ 5421 case 0xd8 ... 0xdf: 5422 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { 5423 /* if CR0.EM or CR0.TS are set, generate an FPU exception */ 5424 /* XXX: what to do if illegal op ? */ 5425 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); 5426 break; 5427 } 5428 modrm = ldub_code(s->pc++); 5429 mod = (modrm >> 6) & 3; 5430 rm = modrm & 7; 5431 op = ((b & 7) << 3) | ((modrm >> 3) & 7); 5432 if (mod != 3) { 5433 /* memory op */ 5434 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 5435 switch(op) { 5436 case 0x00 ... 0x07: /* fxxxs */ 5437 case 0x10 ... 0x17: /* fixxxl */ 5438 case 0x20 ... 0x27: /* fxxxl */ 5439 case 0x30 ... 0x37: /* fixxx */ 5440 { 5441 int op1; 5442 op1 = op & 7; 5443 5444 switch(op >> 4) { 5445 case 0: 5446 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 5447 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 5448 gen_helper_flds_FT0(cpu_tmp2_i32); 5449 break; 5450 case 1: 5451 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 5452 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 5453 gen_helper_fildl_FT0(cpu_tmp2_i32); 5454 break; 5455 case 2: 5456 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 5457 (s->mem_index >> 2) - 1); 5458 gen_helper_fldl_FT0(cpu_tmp1_i64); 5459 break; 5460 case 3: 5461 default: 5462 gen_op_lds_T0_A0(OT_WORD + s->mem_index); 5463 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 5464 gen_helper_fildl_FT0(cpu_tmp2_i32); 5465 break; 5466 } 5467 5468 gen_helper_fp_arith_ST0_FT0(op1); 5469 if (op1 == 3) { 5470 /* fcomp needs pop */ 5471 gen_helper_fpop(); 5472 } 5473 } 5474 break; 5475 case 0x08: /* flds */ 5476 case 0x0a: /* fsts */ 5477 case 0x0b: /* fstps */ 5478 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */ 5479 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */ 5480 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */ 5481 switch(op & 7) { 5482 case 0: 5483 switch(op >> 4) { 5484 case 0: 5485 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 5486 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 5487 gen_helper_flds_ST0(cpu_tmp2_i32); 5488 break; 5489 case 1: 5490 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 5491 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 5492 gen_helper_fildl_ST0(cpu_tmp2_i32); 5493 break; 5494 case 2: 5495 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 5496 (s->mem_index >> 2) - 1); 5497 gen_helper_fldl_ST0(cpu_tmp1_i64); 5498 break; 5499 case 3: 5500 default: 5501 gen_op_lds_T0_A0(OT_WORD + s->mem_index); 5502 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 5503 gen_helper_fildl_ST0(cpu_tmp2_i32); 5504 break; 5505 } 5506 break; 5507 case 1: 5508 /* XXX: the corresponding CPUID bit must be tested ! */ 5509 switch(op >> 4) { 5510 case 1: 5511 gen_helper_fisttl_ST0(cpu_tmp2_i32); 5512 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 5513 gen_op_st_T0_A0(OT_LONG + s->mem_index); 5514 break; 5515 case 2: 5516 gen_helper_fisttll_ST0(cpu_tmp1_i64); 5517 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 5518 (s->mem_index >> 2) - 1); 5519 break; 5520 case 3: 5521 default: 5522 gen_helper_fistt_ST0(cpu_tmp2_i32); 5523 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 5524 gen_op_st_T0_A0(OT_WORD + s->mem_index); 5525 break; 5526 } 5527 gen_helper_fpop(); 5528 break; 5529 default: 5530 switch(op >> 4) { 5531 case 0: 5532 gen_helper_fsts_ST0(cpu_tmp2_i32); 5533 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 5534 gen_op_st_T0_A0(OT_LONG + s->mem_index); 5535 break; 5536 case 1: 5537 gen_helper_fistl_ST0(cpu_tmp2_i32); 5538 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 5539 gen_op_st_T0_A0(OT_LONG + s->mem_index); 5540 break; 5541 case 2: 5542 gen_helper_fstl_ST0(cpu_tmp1_i64); 5543 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 5544 (s->mem_index >> 2) - 1); 5545 break; 5546 case 3: 5547 default: 5548 gen_helper_fist_ST0(cpu_tmp2_i32); 5549 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 5550 gen_op_st_T0_A0(OT_WORD + s->mem_index); 5551 break; 5552 } 5553 if ((op & 7) == 3) 5554 gen_helper_fpop(); 5555 break; 5556 } 5557 break; 5558 case 0x0c: /* fldenv mem */ 5559 if (s->cc_op != CC_OP_DYNAMIC) 5560 gen_op_set_cc_op(s->cc_op); 5561 gen_jmp_im(pc_start - s->cs_base); 5562 gen_helper_fldenv( 5563 cpu_A0, tcg_const_i32(s->dflag)); 5564 break; 5565 case 0x0d: /* fldcw mem */ 5566 gen_op_ld_T0_A0(OT_WORD + s->mem_index); 5567 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 5568 gen_helper_fldcw(cpu_tmp2_i32); 5569 break; 5570 case 0x0e: /* fnstenv mem */ 5571 if (s->cc_op != CC_OP_DYNAMIC) 5572 gen_op_set_cc_op(s->cc_op); 5573 gen_jmp_im(pc_start - s->cs_base); 5574 gen_helper_fstenv(cpu_A0, tcg_const_i32(s->dflag)); 5575 break; 5576 case 0x0f: /* fnstcw mem */ 5577 gen_helper_fnstcw(cpu_tmp2_i32); 5578 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 5579 gen_op_st_T0_A0(OT_WORD + s->mem_index); 5580 break; 5581 case 0x1d: /* fldt mem */ 5582 if (s->cc_op != CC_OP_DYNAMIC) 5583 gen_op_set_cc_op(s->cc_op); 5584 gen_jmp_im(pc_start - s->cs_base); 5585 gen_helper_fldt_ST0(cpu_A0); 5586 break; 5587 case 0x1f: /* fstpt mem */ 5588 if (s->cc_op != CC_OP_DYNAMIC) 5589 gen_op_set_cc_op(s->cc_op); 5590 gen_jmp_im(pc_start - s->cs_base); 5591 gen_helper_fstt_ST0(cpu_A0); 5592 gen_helper_fpop(); 5593 break; 5594 case 0x2c: /* frstor mem */ 5595 if (s->cc_op != CC_OP_DYNAMIC) 5596 gen_op_set_cc_op(s->cc_op); 5597 gen_jmp_im(pc_start - s->cs_base); 5598 gen_helper_frstor(cpu_A0, tcg_const_i32(s->dflag)); 5599 break; 5600 case 0x2e: /* fnsave mem */ 5601 if (s->cc_op != CC_OP_DYNAMIC) 5602 gen_op_set_cc_op(s->cc_op); 5603 gen_jmp_im(pc_start - s->cs_base); 5604 gen_helper_fsave(cpu_A0, tcg_const_i32(s->dflag)); 5605 break; 5606 case 0x2f: /* fnstsw mem */ 5607 gen_helper_fnstsw(cpu_tmp2_i32); 5608 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 5609 gen_op_st_T0_A0(OT_WORD + s->mem_index); 5610 break; 5611 case 0x3c: /* fbld */ 5612 if (s->cc_op != CC_OP_DYNAMIC) 5613 gen_op_set_cc_op(s->cc_op); 5614 gen_jmp_im(pc_start - s->cs_base); 5615 gen_helper_fbld_ST0(cpu_A0); 5616 break; 5617 case 0x3e: /* fbstp */ 5618 if (s->cc_op != CC_OP_DYNAMIC) 5619 gen_op_set_cc_op(s->cc_op); 5620 gen_jmp_im(pc_start - s->cs_base); 5621 gen_helper_fbst_ST0(cpu_A0); 5622 gen_helper_fpop(); 5623 break; 5624 case 0x3d: /* fildll */ 5625 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, 5626 (s->mem_index >> 2) - 1); 5627 gen_helper_fildll_ST0(cpu_tmp1_i64); 5628 break; 5629 case 0x3f: /* fistpll */ 5630 gen_helper_fistll_ST0(cpu_tmp1_i64); 5631 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, 5632 (s->mem_index >> 2) - 1); 5633 gen_helper_fpop(); 5634 break; 5635 default: 5636 goto illegal_op; 5637 } 5638 } else { 5639 /* register float ops */ 5640 opreg = rm; 5641 5642 switch(op) { 5643 case 0x08: /* fld sti */ 5644 gen_helper_fpush(); 5645 gen_helper_fmov_ST0_STN(tcg_const_i32((opreg + 1) & 7)); 5646 break; 5647 case 0x09: /* fxchg sti */ 5648 case 0x29: /* fxchg4 sti, undocumented op */ 5649 case 0x39: /* fxchg7 sti, undocumented op */ 5650 gen_helper_fxchg_ST0_STN(tcg_const_i32(opreg)); 5651 break; 5652 case 0x0a: /* grp d9/2 */ 5653 switch(rm) { 5654 case 0: /* fnop */ 5655 /* check exceptions (FreeBSD FPU probe) */ 5656 if (s->cc_op != CC_OP_DYNAMIC) 5657 gen_op_set_cc_op(s->cc_op); 5658 gen_jmp_im(pc_start - s->cs_base); 5659 gen_helper_fwait(); 5660 break; 5661 default: 5662 goto illegal_op; 5663 } 5664 break; 5665 case 0x0c: /* grp d9/4 */ 5666 switch(rm) { 5667 case 0: /* fchs */ 5668 gen_helper_fchs_ST0(); 5669 break; 5670 case 1: /* fabs */ 5671 gen_helper_fabs_ST0(); 5672 break; 5673 case 4: /* ftst */ 5674 gen_helper_fldz_FT0(); 5675 gen_helper_fcom_ST0_FT0(); 5676 break; 5677 case 5: /* fxam */ 5678 gen_helper_fxam_ST0(); 5679 break; 5680 default: 5681 goto illegal_op; 5682 } 5683 break; 5684 case 0x0d: /* grp d9/5 */ 5685 { 5686 switch(rm) { 5687 case 0: 5688 gen_helper_fpush(); 5689 gen_helper_fld1_ST0(); 5690 break; 5691 case 1: 5692 gen_helper_fpush(); 5693 gen_helper_fldl2t_ST0(); 5694 break; 5695 case 2: 5696 gen_helper_fpush(); 5697 gen_helper_fldl2e_ST0(); 5698 break; 5699 case 3: 5700 gen_helper_fpush(); 5701 gen_helper_fldpi_ST0(); 5702 break; 5703 case 4: 5704 gen_helper_fpush(); 5705 gen_helper_fldlg2_ST0(); 5706 break; 5707 case 5: 5708 gen_helper_fpush(); 5709 gen_helper_fldln2_ST0(); 5710 break; 5711 case 6: 5712 gen_helper_fpush(); 5713 gen_helper_fldz_ST0(); 5714 break; 5715 default: 5716 goto illegal_op; 5717 } 5718 } 5719 break; 5720 case 0x0e: /* grp d9/6 */ 5721 switch(rm) { 5722 case 0: /* f2xm1 */ 5723 gen_helper_f2xm1(); 5724 break; 5725 case 1: /* fyl2x */ 5726 gen_helper_fyl2x(); 5727 break; 5728 case 2: /* fptan */ 5729 gen_helper_fptan(); 5730 break; 5731 case 3: /* fpatan */ 5732 gen_helper_fpatan(); 5733 break; 5734 case 4: /* fxtract */ 5735 gen_helper_fxtract(); 5736 break; 5737 case 5: /* fprem1 */ 5738 gen_helper_fprem1(); 5739 break; 5740 case 6: /* fdecstp */ 5741 gen_helper_fdecstp(); 5742 break; 5743 default: 5744 case 7: /* fincstp */ 5745 gen_helper_fincstp(); 5746 break; 5747 } 5748 break; 5749 case 0x0f: /* grp d9/7 */ 5750 switch(rm) { 5751 case 0: /* fprem */ 5752 gen_helper_fprem(); 5753 break; 5754 case 1: /* fyl2xp1 */ 5755 gen_helper_fyl2xp1(); 5756 break; 5757 case 2: /* fsqrt */ 5758 gen_helper_fsqrt(); 5759 break; 5760 case 3: /* fsincos */ 5761 gen_helper_fsincos(); 5762 break; 5763 case 5: /* fscale */ 5764 gen_helper_fscale(); 5765 break; 5766 case 4: /* frndint */ 5767 gen_helper_frndint(); 5768 break; 5769 case 6: /* fsin */ 5770 gen_helper_fsin(); 5771 break; 5772 default: 5773 case 7: /* fcos */ 5774 gen_helper_fcos(); 5775 break; 5776 } 5777 break; 5778 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ 5779 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ 5780 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ 5781 { 5782 int op1; 5783 5784 op1 = op & 7; 5785 if (op >= 0x20) { 5786 gen_helper_fp_arith_STN_ST0(op1, opreg); 5787 if (op >= 0x30) 5788 gen_helper_fpop(); 5789 } else { 5790 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5791 gen_helper_fp_arith_ST0_FT0(op1); 5792 } 5793 } 5794 break; 5795 case 0x02: /* fcom */ 5796 case 0x22: /* fcom2, undocumented op */ 5797 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5798 gen_helper_fcom_ST0_FT0(); 5799 break; 5800 case 0x03: /* fcomp */ 5801 case 0x23: /* fcomp3, undocumented op */ 5802 case 0x32: /* fcomp5, undocumented op */ 5803 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5804 gen_helper_fcom_ST0_FT0(); 5805 gen_helper_fpop(); 5806 break; 5807 case 0x15: /* da/5 */ 5808 switch(rm) { 5809 case 1: /* fucompp */ 5810 gen_helper_fmov_FT0_STN(tcg_const_i32(1)); 5811 gen_helper_fucom_ST0_FT0(); 5812 gen_helper_fpop(); 5813 gen_helper_fpop(); 5814 break; 5815 default: 5816 goto illegal_op; 5817 } 5818 break; 5819 case 0x1c: 5820 switch(rm) { 5821 case 0: /* feni (287 only, just do nop here) */ 5822 break; 5823 case 1: /* fdisi (287 only, just do nop here) */ 5824 break; 5825 case 2: /* fclex */ 5826 gen_helper_fclex(); 5827 break; 5828 case 3: /* fninit */ 5829 gen_helper_fninit(); 5830 break; 5831 case 4: /* fsetpm (287 only, just do nop here) */ 5832 break; 5833 default: 5834 goto illegal_op; 5835 } 5836 break; 5837 case 0x1d: /* fucomi */ 5838 if (s->cc_op != CC_OP_DYNAMIC) 5839 gen_op_set_cc_op(s->cc_op); 5840 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5841 gen_helper_fucomi_ST0_FT0(); 5842 s->cc_op = CC_OP_EFLAGS; 5843 break; 5844 case 0x1e: /* fcomi */ 5845 if (s->cc_op != CC_OP_DYNAMIC) 5846 gen_op_set_cc_op(s->cc_op); 5847 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5848 gen_helper_fcomi_ST0_FT0(); 5849 s->cc_op = CC_OP_EFLAGS; 5850 break; 5851 case 0x28: /* ffree sti */ 5852 gen_helper_ffree_STN(tcg_const_i32(opreg)); 5853 break; 5854 case 0x2a: /* fst sti */ 5855 gen_helper_fmov_STN_ST0(tcg_const_i32(opreg)); 5856 break; 5857 case 0x2b: /* fstp sti */ 5858 case 0x0b: /* fstp1 sti, undocumented op */ 5859 case 0x3a: /* fstp8 sti, undocumented op */ 5860 case 0x3b: /* fstp9 sti, undocumented op */ 5861 gen_helper_fmov_STN_ST0(tcg_const_i32(opreg)); 5862 gen_helper_fpop(); 5863 break; 5864 case 0x2c: /* fucom st(i) */ 5865 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5866 gen_helper_fucom_ST0_FT0(); 5867 break; 5868 case 0x2d: /* fucomp st(i) */ 5869 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5870 gen_helper_fucom_ST0_FT0(); 5871 gen_helper_fpop(); 5872 break; 5873 case 0x33: /* de/3 */ 5874 switch(rm) { 5875 case 1: /* fcompp */ 5876 gen_helper_fmov_FT0_STN(tcg_const_i32(1)); 5877 gen_helper_fcom_ST0_FT0(); 5878 gen_helper_fpop(); 5879 gen_helper_fpop(); 5880 break; 5881 default: 5882 goto illegal_op; 5883 } 5884 break; 5885 case 0x38: /* ffreep sti, undocumented op */ 5886 gen_helper_ffree_STN(tcg_const_i32(opreg)); 5887 gen_helper_fpop(); 5888 break; 5889 case 0x3c: /* df/4 */ 5890 switch(rm) { 5891 case 0: 5892 gen_helper_fnstsw(cpu_tmp2_i32); 5893 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); 5894 gen_op_mov_reg_T0(OT_WORD, R_EAX); 5895 break; 5896 default: 5897 goto illegal_op; 5898 } 5899 break; 5900 case 0x3d: /* fucomip */ 5901 if (s->cc_op != CC_OP_DYNAMIC) 5902 gen_op_set_cc_op(s->cc_op); 5903 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5904 gen_helper_fucomi_ST0_FT0(); 5905 gen_helper_fpop(); 5906 s->cc_op = CC_OP_EFLAGS; 5907 break; 5908 case 0x3e: /* fcomip */ 5909 if (s->cc_op != CC_OP_DYNAMIC) 5910 gen_op_set_cc_op(s->cc_op); 5911 gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); 5912 gen_helper_fcomi_ST0_FT0(); 5913 gen_helper_fpop(); 5914 s->cc_op = CC_OP_EFLAGS; 5915 break; 5916 case 0x10 ... 0x13: /* fcmovxx */ 5917 case 0x18 ... 0x1b: 5918 { 5919 int op1, l1; 5920 static const uint8_t fcmov_cc[8] = { 5921 (JCC_B << 1), 5922 (JCC_Z << 1), 5923 (JCC_BE << 1), 5924 (JCC_P << 1), 5925 }; 5926 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); 5927 l1 = gen_new_label(); 5928 gen_jcc1(s, s->cc_op, op1, l1); 5929 gen_helper_fmov_ST0_STN(tcg_const_i32(opreg)); 5930 gen_set_label(l1); 5931 } 5932 break; 5933 default: 5934 goto illegal_op; 5935 } 5936 } 5937 break; 5938 /************************/ 5939 /* string ops */ 5940 5941 case 0xa4: /* movsS */ 5942 case 0xa5: 5943 if ((b & 1) == 0) 5944 ot = OT_BYTE; 5945 else 5946 ot = dflag + OT_WORD; 5947 5948 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { 5949 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); 5950 } else { 5951 gen_movs(s, ot); 5952 } 5953 break; 5954 5955 case 0xaa: /* stosS */ 5956 case 0xab: 5957 if ((b & 1) == 0) 5958 ot = OT_BYTE; 5959 else 5960 ot = dflag + OT_WORD; 5961 5962 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { 5963 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); 5964 } else { 5965 gen_stos(s, ot); 5966 } 5967 break; 5968 case 0xac: /* lodsS */ 5969 case 0xad: 5970 if ((b & 1) == 0) 5971 ot = OT_BYTE; 5972 else 5973 ot = dflag + OT_WORD; 5974 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { 5975 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); 5976 } else { 5977 gen_lods(s, ot); 5978 } 5979 break; 5980 case 0xae: /* scasS */ 5981 case 0xaf: 5982 if ((b & 1) == 0) 5983 ot = OT_BYTE; 5984 else 5985 ot = dflag + OT_WORD; 5986 if (prefixes & PREFIX_REPNZ) { 5987 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1); 5988 } else if (prefixes & PREFIX_REPZ) { 5989 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0); 5990 } else { 5991 gen_scas(s, ot); 5992 s->cc_op = CC_OP_SUBB + ot; 5993 } 5994 break; 5995 5996 case 0xa6: /* cmpsS */ 5997 case 0xa7: 5998 if ((b & 1) == 0) 5999 ot = OT_BYTE; 6000 else 6001 ot = dflag + OT_WORD; 6002 if (prefixes & PREFIX_REPNZ) { 6003 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1); 6004 } else if (prefixes & PREFIX_REPZ) { 6005 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0); 6006 } else { 6007 gen_cmps(s, ot); 6008 s->cc_op = CC_OP_SUBB + ot; 6009 } 6010 break; 6011 case 0x6c: /* insS */ 6012 case 0x6d: 6013 if ((b & 1) == 0) 6014 ot = OT_BYTE; 6015 else 6016 ot = dflag ? OT_LONG : OT_WORD; 6017 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); 6018 gen_op_andl_T0_ffff(); 6019 gen_check_io(s, ot, pc_start - s->cs_base, 6020 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4); 6021 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { 6022 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); 6023 } else { 6024 gen_ins(s, ot); 6025 if (use_icount) { 6026 gen_jmp(s, s->pc - s->cs_base); 6027 } 6028 } 6029 break; 6030 case 0x6e: /* outsS */ 6031 case 0x6f: 6032 if ((b & 1) == 0) 6033 ot = OT_BYTE; 6034 else 6035 ot = dflag ? OT_LONG : OT_WORD; 6036 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); 6037 gen_op_andl_T0_ffff(); 6038 gen_check_io(s, ot, pc_start - s->cs_base, 6039 svm_is_rep(prefixes) | 4); 6040 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { 6041 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); 6042 } else { 6043 gen_outs(s, ot); 6044 if (use_icount) { 6045 gen_jmp(s, s->pc - s->cs_base); 6046 } 6047 } 6048 break; 6049 6050 /************************/ 6051 /* port I/O */ 6052 6053 case 0xe4: 6054 case 0xe5: 6055 if ((b & 1) == 0) 6056 ot = OT_BYTE; 6057 else 6058 ot = dflag ? OT_LONG : OT_WORD; 6059 val = ldub_code(s->pc++); 6060 gen_op_movl_T0_im(val); 6061 gen_check_io(s, ot, pc_start - s->cs_base, 6062 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); 6063 if (use_icount) 6064 gen_io_start(); 6065 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 6066 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32); 6067 gen_op_mov_reg_T1(ot, R_EAX); 6068 if (use_icount) { 6069 gen_io_end(); 6070 gen_jmp(s, s->pc - s->cs_base); 6071 } 6072 break; 6073 case 0xe6: 6074 case 0xe7: 6075 if ((b & 1) == 0) 6076 ot = OT_BYTE; 6077 else 6078 ot = dflag ? OT_LONG : OT_WORD; 6079 val = ldub_code(s->pc++); 6080 gen_op_movl_T0_im(val); 6081 gen_check_io(s, ot, pc_start - s->cs_base, 6082 svm_is_rep(prefixes)); 6083 gen_op_mov_TN_reg(ot, 1, R_EAX); 6084 6085 if (use_icount) 6086 gen_io_start(); 6087 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 6088 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); 6089 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]); 6090 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); 6091 if (use_icount) { 6092 gen_io_end(); 6093 gen_jmp(s, s->pc - s->cs_base); 6094 } 6095 break; 6096 case 0xec: 6097 case 0xed: 6098 if ((b & 1) == 0) 6099 ot = OT_BYTE; 6100 else 6101 ot = dflag ? OT_LONG : OT_WORD; 6102 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); 6103 gen_op_andl_T0_ffff(); 6104 gen_check_io(s, ot, pc_start - s->cs_base, 6105 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); 6106 if (use_icount) 6107 gen_io_start(); 6108 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 6109 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32); 6110 gen_op_mov_reg_T1(ot, R_EAX); 6111 if (use_icount) { 6112 gen_io_end(); 6113 gen_jmp(s, s->pc - s->cs_base); 6114 } 6115 break; 6116 case 0xee: 6117 case 0xef: 6118 if ((b & 1) == 0) 6119 ot = OT_BYTE; 6120 else 6121 ot = dflag ? OT_LONG : OT_WORD; 6122 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); 6123 gen_op_andl_T0_ffff(); 6124 gen_check_io(s, ot, pc_start - s->cs_base, 6125 svm_is_rep(prefixes)); 6126 gen_op_mov_TN_reg(ot, 1, R_EAX); 6127 6128 if (use_icount) 6129 gen_io_start(); 6130 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 6131 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); 6132 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]); 6133 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); 6134 if (use_icount) { 6135 gen_io_end(); 6136 gen_jmp(s, s->pc - s->cs_base); 6137 } 6138 break; 6139 6140 /************************/ 6141 /* control */ 6142 case 0xc2: /* ret im */ 6143 val = ldsw_code(s->pc); 6144 s->pc += 2; 6145 gen_pop_T0(s); 6146 if (CODE64(s) && s->dflag) 6147 s->dflag = 2; 6148 gen_stack_update(s, val + (2 << s->dflag)); 6149 if (s->dflag == 0) 6150 gen_op_andl_T0_ffff(); 6151 gen_op_jmp_T0(); 6152 gen_eob(s); 6153 break; 6154 case 0xc3: /* ret */ 6155 gen_pop_T0(s); 6156 gen_pop_update(s); 6157 if (s->dflag == 0) 6158 gen_op_andl_T0_ffff(); 6159 gen_op_jmp_T0(); 6160 gen_eob(s); 6161 break; 6162 case 0xca: /* lret im */ 6163 val = ldsw_code(s->pc); 6164 s->pc += 2; 6165 do_lret: 6166 if (s->pe && !s->vm86) { 6167 if (s->cc_op != CC_OP_DYNAMIC) 6168 gen_op_set_cc_op(s->cc_op); 6169 gen_jmp_im(pc_start - s->cs_base); 6170 gen_helper_lret_protected(tcg_const_i32(s->dflag), 6171 tcg_const_i32(val)); 6172 } else { 6173 gen_stack_A0(s); 6174 /* pop offset */ 6175 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index); 6176 if (s->dflag == 0) 6177 gen_op_andl_T0_ffff(); 6178 /* NOTE: keeping EIP updated is not a problem in case of 6179 exception */ 6180 gen_op_jmp_T0(); 6181 /* pop selector */ 6182 gen_op_addl_A0_im(2 << s->dflag); 6183 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index); 6184 gen_op_movl_seg_T0_vm(R_CS); 6185 /* add stack offset */ 6186 gen_stack_update(s, val + (4 << s->dflag)); 6187 } 6188 gen_eob(s); 6189 break; 6190 case 0xcb: /* lret */ 6191 val = 0; 6192 goto do_lret; 6193 case 0xcf: /* iret */ 6194 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET); 6195 if (!s->pe) { 6196 /* real mode */ 6197 gen_helper_iret_real(tcg_const_i32(s->dflag)); 6198 s->cc_op = CC_OP_EFLAGS; 6199 } else if (s->vm86) { 6200 if (s->iopl != 3) { 6201 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6202 } else { 6203 gen_helper_iret_real(tcg_const_i32(s->dflag)); 6204 s->cc_op = CC_OP_EFLAGS; 6205 } 6206 } else { 6207 if (s->cc_op != CC_OP_DYNAMIC) 6208 gen_op_set_cc_op(s->cc_op); 6209 gen_jmp_im(pc_start - s->cs_base); 6210 gen_helper_iret_protected(tcg_const_i32(s->dflag), 6211 tcg_const_i32(s->pc - s->cs_base)); 6212 s->cc_op = CC_OP_EFLAGS; 6213 } 6214 gen_eob(s); 6215 break; 6216 case 0xe8: /* call im */ 6217 { 6218 if (dflag) 6219 tval = (int32_t)insn_get(s, OT_LONG); 6220 else 6221 tval = (int16_t)insn_get(s, OT_WORD); 6222 next_eip = s->pc - s->cs_base; 6223 tval += next_eip; 6224 if (s->dflag == 0) 6225 tval &= 0xffff; 6226 gen_movtl_T0_im(next_eip); 6227 gen_push_T0(s); 6228 gen_jmp(s, tval); 6229 } 6230 break; 6231 case 0x9a: /* lcall im */ 6232 { 6233 unsigned int selector, offset; 6234 6235 if (CODE64(s)) 6236 goto illegal_op; 6237 ot = dflag ? OT_LONG : OT_WORD; 6238 offset = insn_get(s, ot); 6239 selector = insn_get(s, OT_WORD); 6240 6241 gen_op_movl_T0_im(selector); 6242 gen_op_movl_T1_imu(offset); 6243 } 6244 goto do_lcall; 6245 case 0xe9: /* jmp im */ 6246 if (dflag) 6247 tval = (int32_t)insn_get(s, OT_LONG); 6248 else 6249 tval = (int16_t)insn_get(s, OT_WORD); 6250 tval += s->pc - s->cs_base; 6251 if (s->dflag == 0) 6252 tval &= 0xffff; 6253 else if(!CODE64(s)) 6254 tval &= 0xffffffff; 6255 gen_jmp(s, tval); 6256 break; 6257 case 0xea: /* ljmp im */ 6258 { 6259 unsigned int selector, offset; 6260 6261 if (CODE64(s)) 6262 goto illegal_op; 6263 ot = dflag ? OT_LONG : OT_WORD; 6264 offset = insn_get(s, ot); 6265 selector = insn_get(s, OT_WORD); 6266 6267 gen_op_movl_T0_im(selector); 6268 gen_op_movl_T1_imu(offset); 6269 } 6270 goto do_ljmp; 6271 case 0xeb: /* jmp Jb */ 6272 tval = (int8_t)insn_get(s, OT_BYTE); 6273 tval += s->pc - s->cs_base; 6274 if (s->dflag == 0) 6275 tval &= 0xffff; 6276 gen_jmp(s, tval); 6277 break; 6278 case 0x70 ... 0x7f: /* jcc Jb */ 6279 tval = (int8_t)insn_get(s, OT_BYTE); 6280 goto do_jcc; 6281 case 0x180 ... 0x18f: /* jcc Jv */ 6282 if (dflag) { 6283 tval = (int32_t)insn_get(s, OT_LONG); 6284 } else { 6285 tval = (int16_t)insn_get(s, OT_WORD); 6286 } 6287 do_jcc: 6288 next_eip = s->pc - s->cs_base; 6289 tval += next_eip; 6290 if (s->dflag == 0) 6291 tval &= 0xffff; 6292 gen_jcc(s, b, tval, next_eip); 6293 break; 6294 6295 case 0x190 ... 0x19f: /* setcc Gv */ 6296 modrm = ldub_code(s->pc++); 6297 gen_setcc(s, b); 6298 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); 6299 break; 6300 case 0x140 ... 0x14f: /* cmov Gv, Ev */ 6301 { 6302 int l1; 6303 TCGv t0; 6304 6305 ot = dflag + OT_WORD; 6306 modrm = ldub_code(s->pc++); 6307 reg = ((modrm >> 3) & 7) | rex_r; 6308 mod = (modrm >> 6) & 3; 6309 t0 = tcg_temp_local_new(); 6310 if (mod != 3) { 6311 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 6312 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0); 6313 } else { 6314 rm = (modrm & 7) | REX_B(s); 6315 gen_op_mov_v_reg(ot, t0, rm); 6316 } 6317 #ifdef TARGET_X86_64 6318 if (ot == OT_LONG) { 6319 /* XXX: specific Intel behaviour ? */ 6320 l1 = gen_new_label(); 6321 gen_jcc1(s, s->cc_op, b ^ 1, l1); 6322 tcg_gen_st32_tl(t0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); 6323 gen_set_label(l1); 6324 tcg_gen_movi_tl(cpu_tmp0, 0); 6325 tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); 6326 } else 6327 #endif 6328 { 6329 l1 = gen_new_label(); 6330 gen_jcc1(s, s->cc_op, b ^ 1, l1); 6331 gen_op_mov_reg_v(ot, reg, t0); 6332 gen_set_label(l1); 6333 } 6334 tcg_temp_free(t0); 6335 } 6336 break; 6337 6338 /************************/ 6339 /* flags */ 6340 case 0x9c: /* pushf */ 6341 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF); 6342 if (s->vm86 && s->iopl != 3) { 6343 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6344 } else { 6345 if (s->cc_op != CC_OP_DYNAMIC) 6346 gen_op_set_cc_op(s->cc_op); 6347 gen_helper_read_eflags(cpu_T[0]); 6348 gen_push_T0(s); 6349 } 6350 break; 6351 case 0x9d: /* popf */ 6352 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF); 6353 if (s->vm86 && s->iopl != 3) { 6354 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6355 } else { 6356 gen_pop_T0(s); 6357 if (s->cpl == 0) { 6358 if (s->dflag) { 6359 gen_helper_write_eflags(cpu_T[0], 6360 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK))); 6361 } else { 6362 gen_helper_write_eflags(cpu_T[0], 6363 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff)); 6364 } 6365 } else { 6366 if (s->cpl <= s->iopl) { 6367 if (s->dflag) { 6368 gen_helper_write_eflags(cpu_T[0], 6369 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK))); 6370 } else { 6371 gen_helper_write_eflags(cpu_T[0], 6372 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff)); 6373 } 6374 } else { 6375 if (s->dflag) { 6376 gen_helper_write_eflags(cpu_T[0], 6377 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK))); 6378 } else { 6379 gen_helper_write_eflags(cpu_T[0], 6380 tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff)); 6381 } 6382 } 6383 } 6384 gen_pop_update(s); 6385 s->cc_op = CC_OP_EFLAGS; 6386 /* abort translation because TF flag may change */ 6387 gen_jmp_im(s->pc - s->cs_base); 6388 gen_eob(s); 6389 } 6390 break; 6391 case 0x9e: /* sahf */ 6392 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) 6393 goto illegal_op; 6394 gen_op_mov_TN_reg(OT_BYTE, 0, R_AH); 6395 if (s->cc_op != CC_OP_DYNAMIC) 6396 gen_op_set_cc_op(s->cc_op); 6397 gen_compute_eflags(cpu_cc_src); 6398 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); 6399 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C); 6400 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]); 6401 s->cc_op = CC_OP_EFLAGS; 6402 break; 6403 case 0x9f: /* lahf */ 6404 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) 6405 goto illegal_op; 6406 if (s->cc_op != CC_OP_DYNAMIC) 6407 gen_op_set_cc_op(s->cc_op); 6408 gen_compute_eflags(cpu_T[0]); 6409 /* Note: gen_compute_eflags() only gives the condition codes */ 6410 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 0x02); 6411 gen_op_mov_reg_T0(OT_BYTE, R_AH); 6412 break; 6413 case 0xf5: /* cmc */ 6414 if (s->cc_op != CC_OP_DYNAMIC) 6415 gen_op_set_cc_op(s->cc_op); 6416 gen_compute_eflags(cpu_cc_src); 6417 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); 6418 s->cc_op = CC_OP_EFLAGS; 6419 break; 6420 case 0xf8: /* clc */ 6421 if (s->cc_op != CC_OP_DYNAMIC) 6422 gen_op_set_cc_op(s->cc_op); 6423 gen_compute_eflags(cpu_cc_src); 6424 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C); 6425 s->cc_op = CC_OP_EFLAGS; 6426 break; 6427 case 0xf9: /* stc */ 6428 if (s->cc_op != CC_OP_DYNAMIC) 6429 gen_op_set_cc_op(s->cc_op); 6430 gen_compute_eflags(cpu_cc_src); 6431 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); 6432 s->cc_op = CC_OP_EFLAGS; 6433 break; 6434 case 0xfc: /* cld */ 6435 tcg_gen_movi_i32(cpu_tmp2_i32, 1); 6436 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df)); 6437 break; 6438 case 0xfd: /* std */ 6439 tcg_gen_movi_i32(cpu_tmp2_i32, -1); 6440 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df)); 6441 break; 6442 6443 /************************/ 6444 /* bit operations */ 6445 case 0x1ba: /* bt/bts/btr/btc Gv, im */ 6446 ot = dflag + OT_WORD; 6447 modrm = ldub_code(s->pc++); 6448 op = (modrm >> 3) & 7; 6449 mod = (modrm >> 6) & 3; 6450 rm = (modrm & 7) | REX_B(s); 6451 if (mod != 3) { 6452 s->rip_offset = 1; 6453 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 6454 gen_op_ld_T0_A0(ot + s->mem_index); 6455 } else { 6456 gen_op_mov_TN_reg(ot, 0, rm); 6457 } 6458 /* load shift */ 6459 val = ldub_code(s->pc++); 6460 gen_op_movl_T1_im(val); 6461 if (op < 4) 6462 goto illegal_op; 6463 op -= 4; 6464 goto bt_op; 6465 case 0x1a3: /* bt Gv, Ev */ 6466 op = 0; 6467 goto do_btx; 6468 case 0x1ab: /* bts */ 6469 op = 1; 6470 goto do_btx; 6471 case 0x1b3: /* btr */ 6472 op = 2; 6473 goto do_btx; 6474 case 0x1bb: /* btc */ 6475 op = 3; 6476 do_btx: 6477 ot = dflag + OT_WORD; 6478 modrm = ldub_code(s->pc++); 6479 reg = ((modrm >> 3) & 7) | rex_r; 6480 mod = (modrm >> 6) & 3; 6481 rm = (modrm & 7) | REX_B(s); 6482 gen_op_mov_TN_reg(OT_LONG, 1, reg); 6483 if (mod != 3) { 6484 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 6485 /* specific case: we need to add a displacement */ 6486 gen_exts(ot, cpu_T[1]); 6487 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot); 6488 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot); 6489 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); 6490 gen_op_ld_T0_A0(ot + s->mem_index); 6491 } else { 6492 gen_op_mov_TN_reg(ot, 0, rm); 6493 } 6494 bt_op: 6495 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1); 6496 switch(op) { 6497 case 0: 6498 tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]); 6499 tcg_gen_movi_tl(cpu_cc_dst, 0); 6500 break; 6501 case 1: 6502 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]); 6503 tcg_gen_movi_tl(cpu_tmp0, 1); 6504 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]); 6505 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0); 6506 break; 6507 case 2: 6508 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]); 6509 tcg_gen_movi_tl(cpu_tmp0, 1); 6510 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]); 6511 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0); 6512 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0); 6513 break; 6514 default: 6515 case 3: 6516 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]); 6517 tcg_gen_movi_tl(cpu_tmp0, 1); 6518 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]); 6519 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0); 6520 break; 6521 } 6522 s->cc_op = CC_OP_SARB + ot; 6523 if (op != 0) { 6524 if (mod != 3) 6525 gen_op_st_T0_A0(ot + s->mem_index); 6526 else 6527 gen_op_mov_reg_T0(ot, rm); 6528 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4); 6529 tcg_gen_movi_tl(cpu_cc_dst, 0); 6530 } 6531 break; 6532 case 0x1bc: /* bsf */ 6533 case 0x1bd: /* bsr */ 6534 { 6535 int label1; 6536 TCGv t0; 6537 6538 ot = dflag + OT_WORD; 6539 modrm = ldub_code(s->pc++); 6540 reg = ((modrm >> 3) & 7) | rex_r; 6541 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 6542 gen_extu(ot, cpu_T[0]); 6543 label1 = gen_new_label(); 6544 tcg_gen_movi_tl(cpu_cc_dst, 0); 6545 t0 = tcg_temp_local_new(); 6546 tcg_gen_mov_tl(t0, cpu_T[0]); 6547 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1); 6548 if (b & 1) { 6549 gen_helper_bsr(cpu_T[0], t0); 6550 } else { 6551 gen_helper_bsf(cpu_T[0], t0); 6552 } 6553 gen_op_mov_reg_T0(ot, reg); 6554 tcg_gen_movi_tl(cpu_cc_dst, 1); 6555 gen_set_label(label1); 6556 tcg_gen_discard_tl(cpu_cc_src); 6557 s->cc_op = CC_OP_LOGICB + ot; 6558 tcg_temp_free(t0); 6559 } 6560 break; 6561 /************************/ 6562 /* bcd */ 6563 case 0x27: /* daa */ 6564 if (CODE64(s)) 6565 goto illegal_op; 6566 if (s->cc_op != CC_OP_DYNAMIC) 6567 gen_op_set_cc_op(s->cc_op); 6568 gen_helper_daa(); 6569 s->cc_op = CC_OP_EFLAGS; 6570 break; 6571 case 0x2f: /* das */ 6572 if (CODE64(s)) 6573 goto illegal_op; 6574 if (s->cc_op != CC_OP_DYNAMIC) 6575 gen_op_set_cc_op(s->cc_op); 6576 gen_helper_das(); 6577 s->cc_op = CC_OP_EFLAGS; 6578 break; 6579 case 0x37: /* aaa */ 6580 if (CODE64(s)) 6581 goto illegal_op; 6582 if (s->cc_op != CC_OP_DYNAMIC) 6583 gen_op_set_cc_op(s->cc_op); 6584 gen_helper_aaa(); 6585 s->cc_op = CC_OP_EFLAGS; 6586 break; 6587 case 0x3f: /* aas */ 6588 if (CODE64(s)) 6589 goto illegal_op; 6590 if (s->cc_op != CC_OP_DYNAMIC) 6591 gen_op_set_cc_op(s->cc_op); 6592 gen_helper_aas(); 6593 s->cc_op = CC_OP_EFLAGS; 6594 break; 6595 case 0xd4: /* aam */ 6596 if (CODE64(s)) 6597 goto illegal_op; 6598 val = ldub_code(s->pc++); 6599 if (val == 0) { 6600 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base); 6601 } else { 6602 gen_helper_aam(tcg_const_i32(val)); 6603 s->cc_op = CC_OP_LOGICB; 6604 } 6605 break; 6606 case 0xd5: /* aad */ 6607 if (CODE64(s)) 6608 goto illegal_op; 6609 val = ldub_code(s->pc++); 6610 gen_helper_aad(tcg_const_i32(val)); 6611 s->cc_op = CC_OP_LOGICB; 6612 break; 6613 /************************/ 6614 /* misc */ 6615 case 0x90: /* nop */ 6616 /* XXX: xchg + rex handling */ 6617 /* XXX: correct lock test for all insn */ 6618 if (prefixes & PREFIX_LOCK) 6619 goto illegal_op; 6620 if (prefixes & PREFIX_REPZ) { 6621 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE); 6622 } 6623 break; 6624 case 0x9b: /* fwait */ 6625 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == 6626 (HF_MP_MASK | HF_TS_MASK)) { 6627 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); 6628 } else { 6629 if (s->cc_op != CC_OP_DYNAMIC) 6630 gen_op_set_cc_op(s->cc_op); 6631 gen_jmp_im(pc_start - s->cs_base); 6632 gen_helper_fwait(); 6633 } 6634 break; 6635 case 0xcc: /* int3 */ 6636 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); 6637 break; 6638 case 0xcd: /* int N */ 6639 val = ldub_code(s->pc++); 6640 if (s->vm86 && s->iopl != 3) { 6641 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6642 } else { 6643 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base); 6644 } 6645 break; 6646 case 0xce: /* into */ 6647 if (CODE64(s)) 6648 goto illegal_op; 6649 if (s->cc_op != CC_OP_DYNAMIC) 6650 gen_op_set_cc_op(s->cc_op); 6651 gen_jmp_im(pc_start - s->cs_base); 6652 gen_helper_into(tcg_const_i32(s->pc - pc_start)); 6653 break; 6654 #ifdef WANT_ICEBP 6655 case 0xf1: /* icebp (undocumented, exits to external debugger) */ 6656 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP); 6657 #if 1 6658 gen_debug(s, pc_start - s->cs_base); 6659 #else 6660 /* start debug */ 6661 tb_flush(cpu_single_env); 6662 cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM); 6663 #endif 6664 break; 6665 #endif 6666 case 0xfa: /* cli */ 6667 if (!s->vm86) { 6668 if (s->cpl <= s->iopl) { 6669 gen_helper_cli(); 6670 } else { 6671 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6672 } 6673 } else { 6674 if (s->iopl == 3) { 6675 gen_helper_cli(); 6676 } else { 6677 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6678 } 6679 } 6680 break; 6681 case 0xfb: /* sti */ 6682 if (!s->vm86) { 6683 if (s->cpl <= s->iopl) { 6684 gen_sti: 6685 gen_helper_sti(); 6686 /* interruptions are enabled only the first insn after sti */ 6687 /* If several instructions disable interrupts, only the 6688 _first_ does it */ 6689 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) 6690 gen_helper_set_inhibit_irq(); 6691 /* give a chance to handle pending irqs */ 6692 gen_jmp_im(s->pc - s->cs_base); 6693 gen_eob(s); 6694 } else { 6695 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6696 } 6697 } else { 6698 if (s->iopl == 3) { 6699 goto gen_sti; 6700 } else { 6701 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6702 } 6703 } 6704 break; 6705 case 0x62: /* bound */ 6706 if (CODE64(s)) 6707 goto illegal_op; 6708 ot = dflag ? OT_LONG : OT_WORD; 6709 modrm = ldub_code(s->pc++); 6710 reg = (modrm >> 3) & 7; 6711 mod = (modrm >> 6) & 3; 6712 if (mod == 3) 6713 goto illegal_op; 6714 gen_op_mov_TN_reg(ot, 0, reg); 6715 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 6716 gen_jmp_im(pc_start - s->cs_base); 6717 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 6718 if (ot == OT_WORD) 6719 gen_helper_boundw(cpu_A0, cpu_tmp2_i32); 6720 else 6721 gen_helper_boundl(cpu_A0, cpu_tmp2_i32); 6722 break; 6723 case 0x1c8 ... 0x1cf: /* bswap reg */ 6724 reg = (b & 7) | REX_B(s); 6725 #ifdef TARGET_X86_64 6726 if (dflag == 2) { 6727 gen_op_mov_TN_reg(OT_QUAD, 0, reg); 6728 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]); 6729 gen_op_mov_reg_T0(OT_QUAD, reg); 6730 } else 6731 #endif 6732 { 6733 gen_op_mov_TN_reg(OT_LONG, 0, reg); 6734 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); 6735 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]); 6736 gen_op_mov_reg_T0(OT_LONG, reg); 6737 } 6738 break; 6739 case 0xd6: /* salc */ 6740 if (CODE64(s)) 6741 goto illegal_op; 6742 if (s->cc_op != CC_OP_DYNAMIC) 6743 gen_op_set_cc_op(s->cc_op); 6744 gen_compute_eflags_c(cpu_T[0]); 6745 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]); 6746 gen_op_mov_reg_T0(OT_BYTE, R_EAX); 6747 break; 6748 case 0xe0: /* loopnz */ 6749 case 0xe1: /* loopz */ 6750 case 0xe2: /* loop */ 6751 case 0xe3: /* jecxz */ 6752 { 6753 int l1, l2, l3; 6754 6755 tval = (int8_t)insn_get(s, OT_BYTE); 6756 next_eip = s->pc - s->cs_base; 6757 tval += next_eip; 6758 if (s->dflag == 0) 6759 tval &= 0xffff; 6760 6761 l1 = gen_new_label(); 6762 l2 = gen_new_label(); 6763 l3 = gen_new_label(); 6764 b &= 3; 6765 switch(b) { 6766 case 0: /* loopnz */ 6767 case 1: /* loopz */ 6768 if (s->cc_op != CC_OP_DYNAMIC) 6769 gen_op_set_cc_op(s->cc_op); 6770 gen_op_add_reg_im(s->aflag, R_ECX, -1); 6771 gen_op_jz_ecx(s->aflag, l3); 6772 gen_compute_eflags(cpu_tmp0); 6773 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_Z); 6774 if (b == 0) { 6775 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1); 6776 } else { 6777 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, l1); 6778 } 6779 break; 6780 case 2: /* loop */ 6781 gen_op_add_reg_im(s->aflag, R_ECX, -1); 6782 gen_op_jnz_ecx(s->aflag, l1); 6783 break; 6784 default: 6785 case 3: /* jcxz */ 6786 gen_op_jz_ecx(s->aflag, l1); 6787 break; 6788 } 6789 6790 gen_set_label(l3); 6791 gen_jmp_im(next_eip); 6792 tcg_gen_br(l2); 6793 6794 gen_set_label(l1); 6795 gen_jmp_im(tval); 6796 gen_set_label(l2); 6797 gen_eob(s); 6798 } 6799 break; 6800 case 0x130: /* wrmsr */ 6801 case 0x132: /* rdmsr */ 6802 if (s->cpl != 0) { 6803 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6804 } else { 6805 if (s->cc_op != CC_OP_DYNAMIC) 6806 gen_op_set_cc_op(s->cc_op); 6807 gen_jmp_im(pc_start - s->cs_base); 6808 if (b & 2) { 6809 gen_helper_rdmsr(); 6810 } else { 6811 gen_helper_wrmsr(); 6812 } 6813 } 6814 break; 6815 case 0x131: /* rdtsc */ 6816 if (s->cc_op != CC_OP_DYNAMIC) 6817 gen_op_set_cc_op(s->cc_op); 6818 gen_jmp_im(pc_start - s->cs_base); 6819 if (use_icount) 6820 gen_io_start(); 6821 gen_helper_rdtsc(); 6822 if (use_icount) { 6823 gen_io_end(); 6824 gen_jmp(s, s->pc - s->cs_base); 6825 } 6826 break; 6827 case 0x133: /* rdpmc */ 6828 if (s->cc_op != CC_OP_DYNAMIC) 6829 gen_op_set_cc_op(s->cc_op); 6830 gen_jmp_im(pc_start - s->cs_base); 6831 gen_helper_rdpmc(); 6832 break; 6833 case 0x134: /* sysenter */ 6834 /* For Intel SYSENTER is valid on 64-bit */ 6835 if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) 6836 goto illegal_op; 6837 if (!s->pe) { 6838 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6839 } else { 6840 if (s->cc_op != CC_OP_DYNAMIC) { 6841 gen_op_set_cc_op(s->cc_op); 6842 s->cc_op = CC_OP_DYNAMIC; 6843 } 6844 gen_jmp_im(pc_start - s->cs_base); 6845 gen_helper_sysenter(); 6846 gen_eob(s); 6847 } 6848 break; 6849 case 0x135: /* sysexit */ 6850 /* For Intel SYSEXIT is valid on 64-bit */ 6851 if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) 6852 goto illegal_op; 6853 if (!s->pe) { 6854 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6855 } else { 6856 if (s->cc_op != CC_OP_DYNAMIC) { 6857 gen_op_set_cc_op(s->cc_op); 6858 s->cc_op = CC_OP_DYNAMIC; 6859 } 6860 gen_jmp_im(pc_start - s->cs_base); 6861 gen_helper_sysexit(tcg_const_i32(dflag)); 6862 gen_eob(s); 6863 } 6864 break; 6865 #ifdef TARGET_X86_64 6866 case 0x105: /* syscall */ 6867 /* XXX: is it usable in real mode ? */ 6868 if (s->cc_op != CC_OP_DYNAMIC) { 6869 gen_op_set_cc_op(s->cc_op); 6870 s->cc_op = CC_OP_DYNAMIC; 6871 } 6872 gen_jmp_im(pc_start - s->cs_base); 6873 gen_helper_syscall(tcg_const_i32(s->pc - pc_start)); 6874 gen_eob(s); 6875 break; 6876 case 0x107: /* sysret */ 6877 if (!s->pe) { 6878 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6879 } else { 6880 if (s->cc_op != CC_OP_DYNAMIC) { 6881 gen_op_set_cc_op(s->cc_op); 6882 s->cc_op = CC_OP_DYNAMIC; 6883 } 6884 gen_jmp_im(pc_start - s->cs_base); 6885 gen_helper_sysret(tcg_const_i32(s->dflag)); 6886 /* condition codes are modified only in long mode */ 6887 if (s->lma) 6888 s->cc_op = CC_OP_EFLAGS; 6889 gen_eob(s); 6890 } 6891 break; 6892 #endif 6893 case 0x1a2: /* cpuid */ 6894 if (s->cc_op != CC_OP_DYNAMIC) 6895 gen_op_set_cc_op(s->cc_op); 6896 gen_jmp_im(pc_start - s->cs_base); 6897 gen_helper_cpuid(); 6898 break; 6899 case 0xf4: /* hlt */ 6900 if (s->cpl != 0) { 6901 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6902 } else { 6903 if (s->cc_op != CC_OP_DYNAMIC) 6904 gen_op_set_cc_op(s->cc_op); 6905 gen_jmp_im(pc_start - s->cs_base); 6906 gen_helper_hlt(tcg_const_i32(s->pc - pc_start)); 6907 s->is_jmp = 3; 6908 } 6909 break; 6910 case 0x100: 6911 modrm = ldub_code(s->pc++); 6912 mod = (modrm >> 6) & 3; 6913 op = (modrm >> 3) & 7; 6914 switch(op) { 6915 case 0: /* sldt */ 6916 if (!s->pe || s->vm86) 6917 goto illegal_op; 6918 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ); 6919 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector)); 6920 ot = OT_WORD; 6921 if (mod == 3) 6922 ot += s->dflag; 6923 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); 6924 break; 6925 case 2: /* lldt */ 6926 if (!s->pe || s->vm86) 6927 goto illegal_op; 6928 if (s->cpl != 0) { 6929 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6930 } else { 6931 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE); 6932 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); 6933 gen_jmp_im(pc_start - s->cs_base); 6934 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 6935 gen_helper_lldt(cpu_tmp2_i32); 6936 } 6937 break; 6938 case 1: /* str */ 6939 if (!s->pe || s->vm86) 6940 goto illegal_op; 6941 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ); 6942 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector)); 6943 ot = OT_WORD; 6944 if (mod == 3) 6945 ot += s->dflag; 6946 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); 6947 break; 6948 case 3: /* ltr */ 6949 if (!s->pe || s->vm86) 6950 goto illegal_op; 6951 if (s->cpl != 0) { 6952 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 6953 } else { 6954 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE); 6955 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); 6956 gen_jmp_im(pc_start - s->cs_base); 6957 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); 6958 gen_helper_ltr(cpu_tmp2_i32); 6959 } 6960 break; 6961 case 4: /* verr */ 6962 case 5: /* verw */ 6963 if (!s->pe || s->vm86) 6964 goto illegal_op; 6965 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); 6966 if (s->cc_op != CC_OP_DYNAMIC) 6967 gen_op_set_cc_op(s->cc_op); 6968 if (op == 4) 6969 gen_helper_verr(cpu_T[0]); 6970 else 6971 gen_helper_verw(cpu_T[0]); 6972 s->cc_op = CC_OP_EFLAGS; 6973 break; 6974 default: 6975 goto illegal_op; 6976 } 6977 break; 6978 case 0x101: 6979 modrm = ldub_code(s->pc++); 6980 mod = (modrm >> 6) & 3; 6981 op = (modrm >> 3) & 7; 6982 rm = modrm & 7; 6983 switch(op) { 6984 case 0: /* sgdt */ 6985 if (mod == 3) 6986 goto illegal_op; 6987 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ); 6988 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 6989 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit)); 6990 gen_op_st_T0_A0(OT_WORD + s->mem_index); 6991 gen_add_A0_im(s, 2); 6992 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base)); 6993 if (!s->dflag) 6994 gen_op_andl_T0_im(0xffffff); 6995 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index); 6996 break; 6997 case 1: 6998 if (mod == 3) { 6999 switch (rm) { 7000 case 0: /* monitor */ 7001 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || 7002 s->cpl != 0) 7003 goto illegal_op; 7004 if (s->cc_op != CC_OP_DYNAMIC) 7005 gen_op_set_cc_op(s->cc_op); 7006 gen_jmp_im(pc_start - s->cs_base); 7007 #ifdef TARGET_X86_64 7008 if (s->aflag == 2) { 7009 gen_op_movq_A0_reg(R_EAX); 7010 } else 7011 #endif 7012 { 7013 gen_op_movl_A0_reg(R_EAX); 7014 if (s->aflag == 0) 7015 gen_op_andl_A0_ffff(); 7016 } 7017 gen_add_A0_ds_seg(s); 7018 gen_helper_monitor(cpu_A0); 7019 break; 7020 case 1: /* mwait */ 7021 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || 7022 s->cpl != 0) 7023 goto illegal_op; 7024 if (s->cc_op != CC_OP_DYNAMIC) { 7025 gen_op_set_cc_op(s->cc_op); 7026 s->cc_op = CC_OP_DYNAMIC; 7027 } 7028 gen_jmp_im(pc_start - s->cs_base); 7029 gen_helper_mwait(tcg_const_i32(s->pc - pc_start)); 7030 gen_eob(s); 7031 break; 7032 default: 7033 goto illegal_op; 7034 } 7035 } else { /* sidt */ 7036 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ); 7037 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7038 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit)); 7039 gen_op_st_T0_A0(OT_WORD + s->mem_index); 7040 gen_add_A0_im(s, 2); 7041 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base)); 7042 if (!s->dflag) 7043 gen_op_andl_T0_im(0xffffff); 7044 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index); 7045 } 7046 break; 7047 case 2: /* lgdt */ 7048 case 3: /* lidt */ 7049 if (mod == 3) { 7050 if (s->cc_op != CC_OP_DYNAMIC) 7051 gen_op_set_cc_op(s->cc_op); 7052 gen_jmp_im(pc_start - s->cs_base); 7053 switch(rm) { 7054 case 0: /* VMRUN */ 7055 if (!(s->flags & HF_SVME_MASK) || !s->pe) 7056 goto illegal_op; 7057 if (s->cpl != 0) { 7058 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7059 break; 7060 } else { 7061 gen_helper_vmrun(tcg_const_i32(s->aflag), 7062 tcg_const_i32(s->pc - pc_start)); 7063 tcg_gen_exit_tb(0); 7064 s->is_jmp = 3; 7065 } 7066 break; 7067 case 1: /* VMMCALL */ 7068 if (!(s->flags & HF_SVME_MASK)) 7069 goto illegal_op; 7070 gen_helper_vmmcall(); 7071 break; 7072 case 2: /* VMLOAD */ 7073 if (!(s->flags & HF_SVME_MASK) || !s->pe) 7074 goto illegal_op; 7075 if (s->cpl != 0) { 7076 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7077 break; 7078 } else { 7079 gen_helper_vmload(tcg_const_i32(s->aflag)); 7080 } 7081 break; 7082 case 3: /* VMSAVE */ 7083 if (!(s->flags & HF_SVME_MASK) || !s->pe) 7084 goto illegal_op; 7085 if (s->cpl != 0) { 7086 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7087 break; 7088 } else { 7089 gen_helper_vmsave(tcg_const_i32(s->aflag)); 7090 } 7091 break; 7092 case 4: /* STGI */ 7093 if ((!(s->flags & HF_SVME_MASK) && 7094 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || 7095 !s->pe) 7096 goto illegal_op; 7097 if (s->cpl != 0) { 7098 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7099 break; 7100 } else { 7101 gen_helper_stgi(); 7102 } 7103 break; 7104 case 5: /* CLGI */ 7105 if (!(s->flags & HF_SVME_MASK) || !s->pe) 7106 goto illegal_op; 7107 if (s->cpl != 0) { 7108 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7109 break; 7110 } else { 7111 gen_helper_clgi(); 7112 } 7113 break; 7114 case 6: /* SKINIT */ 7115 if ((!(s->flags & HF_SVME_MASK) && 7116 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || 7117 !s->pe) 7118 goto illegal_op; 7119 gen_helper_skinit(); 7120 break; 7121 case 7: /* INVLPGA */ 7122 if (!(s->flags & HF_SVME_MASK) || !s->pe) 7123 goto illegal_op; 7124 if (s->cpl != 0) { 7125 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7126 break; 7127 } else { 7128 gen_helper_invlpga(tcg_const_i32(s->aflag)); 7129 } 7130 break; 7131 default: 7132 goto illegal_op; 7133 } 7134 } else if (s->cpl != 0) { 7135 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7136 } else { 7137 gen_svm_check_intercept(s, pc_start, 7138 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE); 7139 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7140 gen_op_ld_T1_A0(OT_WORD + s->mem_index); 7141 gen_add_A0_im(s, 2); 7142 gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index); 7143 if (!s->dflag) 7144 gen_op_andl_T0_im(0xffffff); 7145 if (op == 2) { 7146 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base)); 7147 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit)); 7148 } else { 7149 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base)); 7150 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit)); 7151 } 7152 } 7153 break; 7154 case 4: /* smsw */ 7155 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0); 7156 #if defined TARGET_X86_64 && defined WORDS_BIGENDIAN 7157 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4); 7158 #else 7159 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0])); 7160 #endif 7161 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); 7162 break; 7163 case 6: /* lmsw */ 7164 if (s->cpl != 0) { 7165 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7166 } else { 7167 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); 7168 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); 7169 gen_helper_lmsw(cpu_T[0]); 7170 gen_jmp_im(s->pc - s->cs_base); 7171 gen_eob(s); 7172 } 7173 break; 7174 case 7: /* invlpg */ 7175 if (s->cpl != 0) { 7176 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7177 } else { 7178 if (mod == 3) { 7179 #ifdef TARGET_X86_64 7180 if (CODE64(s) && rm == 0) { 7181 /* swapgs */ 7182 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,segs[R_GS].base)); 7183 tcg_gen_ld_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,kernelgsbase)); 7184 tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,segs[R_GS].base)); 7185 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,kernelgsbase)); 7186 } else 7187 #endif 7188 { 7189 goto illegal_op; 7190 } 7191 } else { 7192 if (s->cc_op != CC_OP_DYNAMIC) 7193 gen_op_set_cc_op(s->cc_op); 7194 gen_jmp_im(pc_start - s->cs_base); 7195 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7196 gen_helper_invlpg(cpu_A0); 7197 gen_jmp_im(s->pc - s->cs_base); 7198 gen_eob(s); 7199 } 7200 } 7201 break; 7202 default: 7203 goto illegal_op; 7204 } 7205 break; 7206 case 0x108: /* invd */ 7207 case 0x109: /* wbinvd */ 7208 if (s->cpl != 0) { 7209 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7210 } else { 7211 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD); 7212 /* nothing to do */ 7213 } 7214 break; 7215 case 0x63: /* arpl or movslS (x86_64) */ 7216 #ifdef TARGET_X86_64 7217 if (CODE64(s)) { 7218 int d_ot; 7219 /* d_ot is the size of destination */ 7220 d_ot = dflag + OT_WORD; 7221 7222 modrm = ldub_code(s->pc++); 7223 reg = ((modrm >> 3) & 7) | rex_r; 7224 mod = (modrm >> 6) & 3; 7225 rm = (modrm & 7) | REX_B(s); 7226 7227 if (mod == 3) { 7228 gen_op_mov_TN_reg(OT_LONG, 0, rm); 7229 /* sign extend */ 7230 if (d_ot == OT_QUAD) 7231 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); 7232 gen_op_mov_reg_T0(d_ot, reg); 7233 } else { 7234 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7235 if (d_ot == OT_QUAD) { 7236 gen_op_lds_T0_A0(OT_LONG + s->mem_index); 7237 } else { 7238 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 7239 } 7240 gen_op_mov_reg_T0(d_ot, reg); 7241 } 7242 } else 7243 #endif 7244 { 7245 int label1; 7246 TCGv t0, t1, t2; 7247 7248 if (!s->pe || s->vm86) 7249 goto illegal_op; 7250 t0 = tcg_temp_local_new(); 7251 t1 = tcg_temp_local_new(); 7252 t2 = tcg_temp_local_new(); 7253 ot = OT_WORD; 7254 modrm = ldub_code(s->pc++); 7255 reg = (modrm >> 3) & 7; 7256 mod = (modrm >> 6) & 3; 7257 rm = modrm & 7; 7258 if (mod != 3) { 7259 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7260 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0); 7261 } else { 7262 gen_op_mov_v_reg(ot, t0, rm); 7263 } 7264 gen_op_mov_v_reg(ot, t1, reg); 7265 tcg_gen_andi_tl(cpu_tmp0, t0, 3); 7266 tcg_gen_andi_tl(t1, t1, 3); 7267 tcg_gen_movi_tl(t2, 0); 7268 label1 = gen_new_label(); 7269 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1); 7270 tcg_gen_andi_tl(t0, t0, ~3); 7271 tcg_gen_or_tl(t0, t0, t1); 7272 tcg_gen_movi_tl(t2, CC_Z); 7273 gen_set_label(label1); 7274 if (mod != 3) { 7275 gen_op_st_v(ot + s->mem_index, t0, cpu_A0); 7276 } else { 7277 gen_op_mov_reg_v(ot, rm, t0); 7278 } 7279 if (s->cc_op != CC_OP_DYNAMIC) 7280 gen_op_set_cc_op(s->cc_op); 7281 gen_compute_eflags(cpu_cc_src); 7282 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z); 7283 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2); 7284 s->cc_op = CC_OP_EFLAGS; 7285 tcg_temp_free(t0); 7286 tcg_temp_free(t1); 7287 tcg_temp_free(t2); 7288 } 7289 break; 7290 case 0x102: /* lar */ 7291 case 0x103: /* lsl */ 7292 { 7293 int label1; 7294 TCGv t0; 7295 if (!s->pe || s->vm86) 7296 goto illegal_op; 7297 ot = dflag ? OT_LONG : OT_WORD; 7298 modrm = ldub_code(s->pc++); 7299 reg = ((modrm >> 3) & 7) | rex_r; 7300 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); 7301 t0 = tcg_temp_local_new(); 7302 if (s->cc_op != CC_OP_DYNAMIC) 7303 gen_op_set_cc_op(s->cc_op); 7304 if (b == 0x102) 7305 gen_helper_lar(t0, cpu_T[0]); 7306 else 7307 gen_helper_lsl(t0, cpu_T[0]); 7308 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z); 7309 label1 = gen_new_label(); 7310 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1); 7311 gen_op_mov_reg_v(ot, reg, t0); 7312 gen_set_label(label1); 7313 s->cc_op = CC_OP_EFLAGS; 7314 tcg_temp_free(t0); 7315 } 7316 break; 7317 case 0x118: 7318 modrm = ldub_code(s->pc++); 7319 mod = (modrm >> 6) & 3; 7320 op = (modrm >> 3) & 7; 7321 switch(op) { 7322 case 0: /* prefetchnta */ 7323 case 1: /* prefetchnt0 */ 7324 case 2: /* prefetchnt0 */ 7325 case 3: /* prefetchnt0 */ 7326 if (mod == 3) 7327 goto illegal_op; 7328 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7329 /* nothing more to do */ 7330 break; 7331 default: /* nop (multi byte) */ 7332 gen_nop_modrm(s, modrm); 7333 break; 7334 } 7335 break; 7336 case 0x119 ... 0x11f: /* nop (multi byte) */ 7337 modrm = ldub_code(s->pc++); 7338 gen_nop_modrm(s, modrm); 7339 break; 7340 case 0x120: /* mov reg, crN */ 7341 case 0x122: /* mov crN, reg */ 7342 if (s->cpl != 0) { 7343 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7344 } else { 7345 modrm = ldub_code(s->pc++); 7346 if ((modrm & 0xc0) != 0xc0) 7347 goto illegal_op; 7348 rm = (modrm & 7) | REX_B(s); 7349 reg = ((modrm >> 3) & 7) | rex_r; 7350 if (CODE64(s)) 7351 ot = OT_QUAD; 7352 else 7353 ot = OT_LONG; 7354 switch(reg) { 7355 case 0: 7356 case 2: 7357 case 3: 7358 case 4: 7359 case 8: 7360 if (s->cc_op != CC_OP_DYNAMIC) 7361 gen_op_set_cc_op(s->cc_op); 7362 gen_jmp_im(pc_start - s->cs_base); 7363 if (b & 2) { 7364 gen_op_mov_TN_reg(ot, 0, rm); 7365 gen_helper_write_crN(tcg_const_i32(reg), cpu_T[0]); 7366 gen_jmp_im(s->pc - s->cs_base); 7367 gen_eob(s); 7368 } else { 7369 gen_helper_read_crN(cpu_T[0], tcg_const_i32(reg)); 7370 gen_op_mov_reg_T0(ot, rm); 7371 } 7372 break; 7373 default: 7374 goto illegal_op; 7375 } 7376 } 7377 break; 7378 case 0x121: /* mov reg, drN */ 7379 case 0x123: /* mov drN, reg */ 7380 if (s->cpl != 0) { 7381 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7382 } else { 7383 modrm = ldub_code(s->pc++); 7384 if ((modrm & 0xc0) != 0xc0) 7385 goto illegal_op; 7386 rm = (modrm & 7) | REX_B(s); 7387 reg = ((modrm >> 3) & 7) | rex_r; 7388 if (CODE64(s)) 7389 ot = OT_QUAD; 7390 else 7391 ot = OT_LONG; 7392 /* XXX: do it dynamically with CR4.DE bit */ 7393 if (reg == 4 || reg == 5 || reg >= 8) 7394 goto illegal_op; 7395 if (b & 2) { 7396 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg); 7397 gen_op_mov_TN_reg(ot, 0, rm); 7398 gen_helper_movl_drN_T0(tcg_const_i32(reg), cpu_T[0]); 7399 gen_jmp_im(s->pc - s->cs_base); 7400 gen_eob(s); 7401 } else { 7402 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg); 7403 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg])); 7404 gen_op_mov_reg_T0(ot, rm); 7405 } 7406 } 7407 break; 7408 case 0x106: /* clts */ 7409 if (s->cpl != 0) { 7410 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 7411 } else { 7412 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); 7413 gen_helper_clts(); 7414 /* abort block because static cpu state changed */ 7415 gen_jmp_im(s->pc - s->cs_base); 7416 gen_eob(s); 7417 } 7418 break; 7419 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */ 7420 case 0x1c3: /* MOVNTI reg, mem */ 7421 if (!(s->cpuid_features & CPUID_SSE2)) 7422 goto illegal_op; 7423 ot = s->dflag == 2 ? OT_QUAD : OT_LONG; 7424 modrm = ldub_code(s->pc++); 7425 mod = (modrm >> 6) & 3; 7426 if (mod == 3) 7427 goto illegal_op; 7428 reg = ((modrm >> 3) & 7) | rex_r; 7429 /* generate a generic store */ 7430 gen_ldst_modrm(s, modrm, ot, reg, 1); 7431 break; 7432 case 0x1ae: 7433 modrm = ldub_code(s->pc++); 7434 mod = (modrm >> 6) & 3; 7435 op = (modrm >> 3) & 7; 7436 switch(op) { 7437 case 0: /* fxsave */ 7438 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || 7439 (s->flags & HF_EM_MASK)) 7440 goto illegal_op; 7441 if (s->flags & HF_TS_MASK) { 7442 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); 7443 break; 7444 } 7445 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7446 if (s->cc_op != CC_OP_DYNAMIC) 7447 gen_op_set_cc_op(s->cc_op); 7448 gen_jmp_im(pc_start - s->cs_base); 7449 gen_helper_fxsave(cpu_A0, tcg_const_i32((s->dflag == 2))); 7450 break; 7451 case 1: /* fxrstor */ 7452 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || 7453 (s->flags & HF_EM_MASK)) 7454 goto illegal_op; 7455 if (s->flags & HF_TS_MASK) { 7456 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); 7457 break; 7458 } 7459 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7460 if (s->cc_op != CC_OP_DYNAMIC) 7461 gen_op_set_cc_op(s->cc_op); 7462 gen_jmp_im(pc_start - s->cs_base); 7463 gen_helper_fxrstor(cpu_A0, tcg_const_i32((s->dflag == 2))); 7464 break; 7465 case 2: /* ldmxcsr */ 7466 case 3: /* stmxcsr */ 7467 if (s->flags & HF_TS_MASK) { 7468 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); 7469 break; 7470 } 7471 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) || 7472 mod == 3) 7473 goto illegal_op; 7474 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7475 if (op == 2) { 7476 gen_op_ld_T0_A0(OT_LONG + s->mem_index); 7477 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr)); 7478 } else { 7479 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr)); 7480 gen_op_st_T0_A0(OT_LONG + s->mem_index); 7481 } 7482 break; 7483 case 5: /* lfence */ 7484 case 6: /* mfence */ 7485 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) 7486 goto illegal_op; 7487 break; 7488 case 7: /* sfence / clflush */ 7489 if ((modrm & 0xc7) == 0xc0) { 7490 /* sfence */ 7491 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */ 7492 if (!(s->cpuid_features & CPUID_SSE)) 7493 goto illegal_op; 7494 } else { 7495 /* clflush */ 7496 if (!(s->cpuid_features & CPUID_CLFLUSH)) 7497 goto illegal_op; 7498 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7499 } 7500 break; 7501 default: 7502 goto illegal_op; 7503 } 7504 break; 7505 case 0x10d: /* 3DNow! prefetch(w) */ 7506 modrm = ldub_code(s->pc++); 7507 mod = (modrm >> 6) & 3; 7508 if (mod == 3) 7509 goto illegal_op; 7510 gen_lea_modrm(s, modrm, ®_addr, &offset_addr); 7511 /* ignore for now */ 7512 break; 7513 case 0x1aa: /* rsm */ 7514 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM); 7515 if (!(s->flags & HF_SMM_MASK)) 7516 goto illegal_op; 7517 if (s->cc_op != CC_OP_DYNAMIC) { 7518 gen_op_set_cc_op(s->cc_op); 7519 s->cc_op = CC_OP_DYNAMIC; 7520 } 7521 gen_jmp_im(s->pc - s->cs_base); 7522 gen_helper_rsm(); 7523 gen_eob(s); 7524 break; 7525 case 0x1b8: /* SSE4.2 popcnt */ 7526 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) != 7527 PREFIX_REPZ) 7528 goto illegal_op; 7529 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT)) 7530 goto illegal_op; 7531 7532 modrm = ldub_code(s->pc++); 7533 reg = ((modrm >> 3) & 7); 7534 7535 if (s->prefix & PREFIX_DATA) 7536 ot = OT_WORD; 7537 else if (s->dflag != 2) 7538 ot = OT_LONG; 7539 else 7540 ot = OT_QUAD; 7541 7542 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 7543 gen_helper_popcnt(cpu_T[0], cpu_T[0], tcg_const_i32(ot)); 7544 gen_op_mov_reg_T0(ot, reg); 7545 7546 s->cc_op = CC_OP_EFLAGS; 7547 break; 7548 case 0x10e ... 0x10f: 7549 /* 3DNow! instructions, ignore prefixes */ 7550 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA); 7551 case 0x110 ... 0x117: 7552 case 0x128 ... 0x12f: 7553 case 0x138 ... 0x13a: 7554 case 0x150 ... 0x177: 7555 case 0x17c ... 0x17f: 7556 case 0x1c2: 7557 case 0x1c4 ... 0x1c6: 7558 case 0x1d0 ... 0x1fe: 7559 gen_sse(s, b, pc_start, rex_r); 7560 break; 7561 default: 7562 goto illegal_op; 7563 } 7564 /* lock generation */ 7565 if (s->prefix & PREFIX_LOCK) 7566 gen_helper_unlock(); 7567 return s->pc; 7568 illegal_op: 7569 if (s->prefix & PREFIX_LOCK) 7570 gen_helper_unlock(); 7571 /* XXX: ensure that no lock was generated */ 7572 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); 7573 return s->pc; 7574 } 7575 7576 void optimize_flags_init(void) 7577 { 7578 #if TCG_TARGET_REG_BITS == 32 7579 assert(sizeof(CCTable) == (1 << 3)); 7580 #else 7581 assert(sizeof(CCTable) == (1 << 4)); 7582 #endif 7583 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); 7584 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, 7585 offsetof(CPUState, cc_op), "cc_op"); 7586 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_src), 7587 "cc_src"); 7588 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_dst), 7589 "cc_dst"); 7590 cpu_cc_tmp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_tmp), 7591 "cc_tmp"); 7592 7593 /* register helpers */ 7594 #define GEN_HELPER 2 7595 #include "helper.h" 7596 } 7597 7598 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for 7599 basic block 'tb'. If search_pc is TRUE, also generate PC 7600 information for each intermediate instruction. */ 7601 static inline void gen_intermediate_code_internal(CPUState *env, 7602 TranslationBlock *tb, 7603 int search_pc) 7604 { 7605 DisasContext dc1, *dc = &dc1; 7606 target_ulong pc_ptr; 7607 uint16_t *gen_opc_end; 7608 CPUBreakpoint *bp; 7609 int j, lj, cflags; 7610 uint64_t flags; 7611 target_ulong pc_start; 7612 target_ulong cs_base; 7613 int num_insns; 7614 int max_insns; 7615 7616 /* generate intermediate code */ 7617 pc_start = tb->pc; 7618 cs_base = tb->cs_base; 7619 flags = tb->flags; 7620 cflags = tb->cflags; 7621 7622 dc->pe = (flags >> HF_PE_SHIFT) & 1; 7623 dc->code32 = (flags >> HF_CS32_SHIFT) & 1; 7624 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1; 7625 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1; 7626 dc->f_st = 0; 7627 dc->vm86 = (flags >> VM_SHIFT) & 1; 7628 dc->cpl = (flags >> HF_CPL_SHIFT) & 3; 7629 dc->iopl = (flags >> IOPL_SHIFT) & 3; 7630 dc->tf = (flags >> TF_SHIFT) & 1; 7631 dc->singlestep_enabled = env->singlestep_enabled; 7632 dc->cc_op = CC_OP_DYNAMIC; 7633 dc->cs_base = cs_base; 7634 dc->tb = tb; 7635 dc->popl_esp_hack = 0; 7636 /* select memory access functions */ 7637 dc->mem_index = 0; 7638 if (flags & HF_SOFTMMU_MASK) { 7639 if (dc->cpl == 3) 7640 dc->mem_index = 2 * 4; 7641 else 7642 dc->mem_index = 1 * 4; 7643 } 7644 dc->cpuid_features = env->cpuid_features; 7645 dc->cpuid_ext_features = env->cpuid_ext_features; 7646 dc->cpuid_ext2_features = env->cpuid_ext2_features; 7647 dc->cpuid_ext3_features = env->cpuid_ext3_features; 7648 #ifdef TARGET_X86_64 7649 dc->lma = (flags >> HF_LMA_SHIFT) & 1; 7650 dc->code64 = (flags >> HF_CS64_SHIFT) & 1; 7651 #endif 7652 dc->flags = flags; 7653 dc->jmp_opt = !(dc->tf || env->singlestep_enabled || 7654 (flags & HF_INHIBIT_IRQ_MASK) 7655 #ifndef CONFIG_SOFTMMU 7656 || (flags & HF_SOFTMMU_MASK) 7657 #endif 7658 ); 7659 #if 0 7660 /* check addseg logic */ 7661 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32)) 7662 printf("ERROR addseg\n"); 7663 #endif 7664 7665 cpu_T[0] = tcg_temp_new(); 7666 cpu_T[1] = tcg_temp_new(); 7667 cpu_A0 = tcg_temp_new(); 7668 cpu_T3 = tcg_temp_new(); 7669 7670 cpu_tmp0 = tcg_temp_new(); 7671 cpu_tmp1_i64 = tcg_temp_new_i64(); 7672 cpu_tmp2_i32 = tcg_temp_new_i32(); 7673 cpu_tmp3_i32 = tcg_temp_new_i32(); 7674 cpu_tmp4 = tcg_temp_new(); 7675 cpu_tmp5 = tcg_temp_new(); 7676 cpu_tmp6 = tcg_temp_new(); 7677 cpu_ptr0 = tcg_temp_new_ptr(); 7678 cpu_ptr1 = tcg_temp_new_ptr(); 7679 7680 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 7681 7682 dc->is_jmp = DISAS_NEXT; 7683 pc_ptr = pc_start; 7684 lj = -1; 7685 num_insns = 0; 7686 max_insns = tb->cflags & CF_COUNT_MASK; 7687 if (max_insns == 0) 7688 max_insns = CF_COUNT_MASK; 7689 7690 gen_icount_start(); 7691 for(;;) { 7692 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) { 7693 QTAILQ_FOREACH(bp, &env->breakpoints, entry) { 7694 if (bp->pc == pc_ptr && 7695 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) { 7696 gen_debug(dc, pc_ptr - dc->cs_base); 7697 break; 7698 } 7699 } 7700 } 7701 if (search_pc) { 7702 j = gen_opc_ptr - gen_opc_buf; 7703 if (lj < j) { 7704 lj++; 7705 while (lj < j) 7706 gen_opc_instr_start[lj++] = 0; 7707 } 7708 gen_opc_pc[lj] = pc_ptr; 7709 gen_opc_cc_op[lj] = dc->cc_op; 7710 gen_opc_instr_start[lj] = 1; 7711 gen_opc_icount[lj] = num_insns; 7712 } 7713 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) 7714 gen_io_start(); 7715 7716 pc_ptr = disas_insn(dc, pc_ptr); 7717 num_insns++; 7718 #ifdef CONFIG_HAX 7719 if (hax_enabled() && hax_stop_translate(env)) 7720 { 7721 gen_jmp_im(pc_ptr - dc->cs_base); 7722 gen_eob(dc); 7723 break; 7724 } 7725 #endif 7726 /* stop translation if indicated */ 7727 if (dc->is_jmp) 7728 break; 7729 /* if single step mode, we generate only one instruction and 7730 generate an exception */ 7731 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear 7732 the flag and abort the translation to give the irqs a 7733 change to be happen */ 7734 if (dc->tf || dc->singlestep_enabled || 7735 (flags & HF_INHIBIT_IRQ_MASK)) { 7736 gen_jmp_im(pc_ptr - dc->cs_base); 7737 gen_eob(dc); 7738 break; 7739 } 7740 /* if too long translation, stop generation too */ 7741 if (gen_opc_ptr >= gen_opc_end || 7742 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) || 7743 num_insns >= max_insns) { 7744 gen_jmp_im(pc_ptr - dc->cs_base); 7745 gen_eob(dc); 7746 break; 7747 } 7748 if (singlestep) { 7749 gen_jmp_im(pc_ptr - dc->cs_base); 7750 gen_eob(dc); 7751 break; 7752 } 7753 } 7754 if (tb->cflags & CF_LAST_IO) 7755 gen_io_end(); 7756 gen_icount_end(tb, num_insns); 7757 *gen_opc_ptr = INDEX_op_end; 7758 /* we don't forget to fill the last values */ 7759 if (search_pc) { 7760 j = gen_opc_ptr - gen_opc_buf; 7761 lj++; 7762 while (lj <= j) 7763 gen_opc_instr_start[lj++] = 0; 7764 } 7765 7766 #ifdef DEBUG_DISAS 7767 log_cpu_state_mask(CPU_LOG_TB_CPU, env, X86_DUMP_CCOP); 7768 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { 7769 int disas_flags; 7770 qemu_log("----------------\n"); 7771 qemu_log("IN: %s\n", lookup_symbol(pc_start)); 7772 #ifdef TARGET_X86_64 7773 if (dc->code64) 7774 disas_flags = 2; 7775 else 7776 #endif 7777 disas_flags = !dc->code32; 7778 log_target_disas(pc_start, pc_ptr - pc_start, disas_flags); 7779 qemu_log("\n"); 7780 } 7781 #endif 7782 7783 if (!search_pc) { 7784 tb->size = pc_ptr - pc_start; 7785 tb->icount = num_insns; 7786 } 7787 } 7788 7789 void gen_intermediate_code(CPUState *env, TranslationBlock *tb) 7790 { 7791 gen_intermediate_code_internal(env, tb, 0); 7792 } 7793 7794 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) 7795 { 7796 gen_intermediate_code_internal(env, tb, 1); 7797 } 7798 7799 void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos) 7800 { 7801 int cc_op; 7802 #ifdef DEBUG_DISAS 7803 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) { 7804 int i; 7805 qemu_log("RESTORE:\n"); 7806 for(i = 0;i <= pc_pos; i++) { 7807 if (gen_opc_instr_start[i]) { 7808 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]); 7809 } 7810 } 7811 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n", 7812 pc_pos, gen_opc_pc[pc_pos] - tb->cs_base, 7813 (uint32_t)tb->cs_base); 7814 } 7815 #endif 7816 env->eip = gen_opc_pc[pc_pos] - tb->cs_base; 7817 cc_op = gen_opc_cc_op[pc_pos]; 7818 if (cc_op != CC_OP_DYNAMIC) 7819 env->cc_op = cc_op; 7820 } 7821