1b3e22b23SPaolo Bonzini/* 2b3e22b23SPaolo Bonzini * New-style TCG opcode generator for i386 instructions 3b3e22b23SPaolo Bonzini * 4b3e22b23SPaolo Bonzini * Copyright (c) 2022 Red Hat, Inc. 5b3e22b23SPaolo Bonzini * 6b3e22b23SPaolo Bonzini * Author: Paolo Bonzini <pbonzini@redhat.com> 7b3e22b23SPaolo Bonzini * 8b3e22b23SPaolo Bonzini * This library is free software; you can redistribute it and/or 9b3e22b23SPaolo Bonzini * modify it under the terms of the GNU Lesser General Public 10b3e22b23SPaolo Bonzini * License as published by the Free Software Foundation; either 11b3e22b23SPaolo Bonzini * version 2.1 of the License, or (at your option) any later version. 12b3e22b23SPaolo Bonzini * 13b3e22b23SPaolo Bonzini * This library is distributed in the hope that it will be useful, 14b3e22b23SPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of 15b3e22b23SPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16b3e22b23SPaolo Bonzini * Lesser General Public License for more details. 17b3e22b23SPaolo Bonzini * 18b3e22b23SPaolo Bonzini * You should have received a copy of the GNU Lesser General Public 19b3e22b23SPaolo Bonzini * License along with this library; if not, see <http://www.gnu.org/licenses/>. 20b3e22b23SPaolo Bonzini */ 21b3e22b23SPaolo Bonzini 22d7c41a60SPaolo Bonzini/* 23d7c41a60SPaolo Bonzini * Sometimes, knowing what the backend has can produce better code. 24d7c41a60SPaolo Bonzini * The exact opcode to check depends on 32- vs. 64-bit. 25d7c41a60SPaolo Bonzini */ 26d7c41a60SPaolo Bonzini#ifdef TARGET_X86_64 27d7c41a60SPaolo Bonzini#define TCG_TARGET_HAS_extract2_tl TCG_TARGET_HAS_extract2_i64 28d7c41a60SPaolo Bonzini#define TCG_TARGET_deposit_tl_valid TCG_TARGET_deposit_i64_valid 29d7c41a60SPaolo Bonzini#define TCG_TARGET_extract_tl_valid TCG_TARGET_extract_i64_valid 30d7c41a60SPaolo Bonzini#else 31d7c41a60SPaolo Bonzini#define TCG_TARGET_HAS_extract2_tl TCG_TARGET_HAS_extract2_i32 32d7c41a60SPaolo Bonzini#define TCG_TARGET_deposit_tl_valid TCG_TARGET_deposit_i32_valid 33d7c41a60SPaolo Bonzini#define TCG_TARGET_extract_tl_valid TCG_TARGET_extract_i32_valid 34d7c41a60SPaolo Bonzini#endif 35d7c41a60SPaolo Bonzini 367700d229SRichard Henderson#define MMX_OFFSET(reg) \ 377700d229SRichard Henderson ({ assert((reg) >= 0 && (reg) <= 7); \ 387700d229SRichard Henderson offsetof(CPUX86State, fpregs[reg].mmx); }) 39d7c41a60SPaolo Bonzini 407700d229SRichard Henderson#define ZMM_OFFSET(reg) \ 417700d229SRichard Henderson ({ assert((reg) >= 0 && (reg) <= 15); \ 427700d229SRichard Henderson offsetof(CPUX86State, xmm_regs[reg]); }) 43653fad24SPaolo Bonzini 44653fad24SPaolo Bonzinitypedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg); 45653fad24SPaolo Bonzinitypedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg); 4671a0891dSPaolo Bonzinitypedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b); 47653fad24SPaolo Bonzinitypedef void (*SSEFunc_0_eppp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, 48653fad24SPaolo Bonzini TCGv_ptr reg_c); 49653fad24SPaolo Bonzinitypedef void (*SSEFunc_0_epppp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, 50653fad24SPaolo Bonzini TCGv_ptr reg_c, TCGv_ptr reg_d); 51653fad24SPaolo Bonzinitypedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, 52653fad24SPaolo Bonzini TCGv_i32 val); 53653fad24SPaolo Bonzinitypedef void (*SSEFunc_0_epppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, 54653fad24SPaolo Bonzini TCGv_ptr reg_c, TCGv_i32 val); 55653fad24SPaolo Bonzinitypedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val); 56653fad24SPaolo Bonzinitypedef void (*SSEFunc_0_pppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_ptr reg_c, 57653fad24SPaolo Bonzini TCGv_i32 val); 58653fad24SPaolo Bonzinitypedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, 59653fad24SPaolo Bonzini TCGv val); 6016fc5726SPaolo Bonzinitypedef void (*SSEFunc_0_epppti)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, 6116fc5726SPaolo Bonzini TCGv_ptr reg_c, TCGv a0, TCGv_i32 scale); 622872b0f3SPaolo Bonzinitypedef void (*SSEFunc_0_eppppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, 632872b0f3SPaolo Bonzini TCGv_ptr reg_c, TCGv_ptr reg_d, TCGv_i32 flags); 642872b0f3SPaolo Bonzinitypedef void (*SSEFunc_0_eppppii)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, 652872b0f3SPaolo Bonzini TCGv_ptr reg_c, TCGv_ptr reg_d, TCGv_i32 even, 662872b0f3SPaolo Bonzini TCGv_i32 odd); 6716fc5726SPaolo Bonzini 684228eb8cSPaolo Bonzinistatic void gen_JMP_m(DisasContext *s, X86DecodedInsn *decode); 694228eb8cSPaolo Bonzinistatic void gen_JMP(DisasContext *s, X86DecodedInsn *decode); 70d7c41a60SPaolo Bonzini 71ce4fcb94SPaolo Bonzinistatic inline TCGv_i32 tcg_constant8u_i32(uint8_t val) 72ce4fcb94SPaolo Bonzini{ 73ce4fcb94SPaolo Bonzini return tcg_constant_i32(val); 74ce4fcb94SPaolo Bonzini} 75ce4fcb94SPaolo Bonzini 7620581aadSPaolo Bonzinistatic void gen_NM_exception(DisasContext *s) 7720581aadSPaolo Bonzini{ 7820581aadSPaolo Bonzini gen_exception(s, EXCP07_PREX); 7920581aadSPaolo Bonzini} 8020581aadSPaolo Bonzini 81a2e2c78dSPaolo Bonzinistatic void gen_lea_modrm(DisasContext *s, X86DecodedInsn *decode) 82b3e22b23SPaolo Bonzini{ 8310eae899SPaolo Bonzini AddressParts *mem = &decode->mem; 8410eae899SPaolo Bonzini TCGv ea; 8510eae899SPaolo Bonzini 8610eae899SPaolo Bonzini ea = gen_lea_modrm_1(s, *mem, decode->e.vex_class == 12); 8710eae899SPaolo Bonzini if (decode->e.special == X86_SPECIAL_BitTest) { 8810eae899SPaolo Bonzini MemOp ot = decode->op[1].ot; 8910eae899SPaolo Bonzini int poslen = 8 << ot; 9010eae899SPaolo Bonzini int opn = decode->op[2].n; 9110eae899SPaolo Bonzini TCGv ofs = tcg_temp_new(); 9210eae899SPaolo Bonzini 9310eae899SPaolo Bonzini /* Extract memory displacement from the second operand. */ 9410eae899SPaolo Bonzini assert(decode->op[2].unit == X86_OP_INT && decode->op[2].ot != MO_8); 9510eae899SPaolo Bonzini tcg_gen_sextract_tl(ofs, cpu_regs[opn], 3, poslen - 3); 9610eae899SPaolo Bonzini tcg_gen_andi_tl(ofs, ofs, -1 << ot); 9710eae899SPaolo Bonzini tcg_gen_add_tl(s->A0, ea, ofs); 9810eae899SPaolo Bonzini ea = s->A0; 9910eae899SPaolo Bonzini } 10010eae899SPaolo Bonzini 10156da568fSPaolo Bonzini gen_lea_v_seg(s, ea, mem->def_seg, s->override); 102b3e22b23SPaolo Bonzini} 1036ba13999SPaolo Bonzini 1046ba13999SPaolo Bonzinistatic inline int mmx_offset(MemOp ot) 1056ba13999SPaolo Bonzini{ 1066ba13999SPaolo Bonzini switch (ot) { 1076ba13999SPaolo Bonzini case MO_8: 1086ba13999SPaolo Bonzini return offsetof(MMXReg, MMX_B(0)); 1096ba13999SPaolo Bonzini case MO_16: 1106ba13999SPaolo Bonzini return offsetof(MMXReg, MMX_W(0)); 1116ba13999SPaolo Bonzini case MO_32: 1126ba13999SPaolo Bonzini return offsetof(MMXReg, MMX_L(0)); 1136ba13999SPaolo Bonzini case MO_64: 1146ba13999SPaolo Bonzini return offsetof(MMXReg, MMX_Q(0)); 1156ba13999SPaolo Bonzini default: 1166ba13999SPaolo Bonzini g_assert_not_reached(); 1176ba13999SPaolo Bonzini } 1186ba13999SPaolo Bonzini} 1196ba13999SPaolo Bonzini 1206ba13999SPaolo Bonzinistatic inline int xmm_offset(MemOp ot) 1216ba13999SPaolo Bonzini{ 1226ba13999SPaolo Bonzini switch (ot) { 1236ba13999SPaolo Bonzini case MO_8: 1246ba13999SPaolo Bonzini return offsetof(ZMMReg, ZMM_B(0)); 1256ba13999SPaolo Bonzini case MO_16: 1266ba13999SPaolo Bonzini return offsetof(ZMMReg, ZMM_W(0)); 1276ba13999SPaolo Bonzini case MO_32: 1286ba13999SPaolo Bonzini return offsetof(ZMMReg, ZMM_L(0)); 1296ba13999SPaolo Bonzini case MO_64: 1306ba13999SPaolo Bonzini return offsetof(ZMMReg, ZMM_Q(0)); 1316ba13999SPaolo Bonzini case MO_128: 1326ba13999SPaolo Bonzini return offsetof(ZMMReg, ZMM_X(0)); 1336ba13999SPaolo Bonzini case MO_256: 1346ba13999SPaolo Bonzini return offsetof(ZMMReg, ZMM_Y(0)); 1356ba13999SPaolo Bonzini default: 1366ba13999SPaolo Bonzini g_assert_not_reached(); 1376ba13999SPaolo Bonzini } 1386ba13999SPaolo Bonzini} 1396ba13999SPaolo Bonzini 14092ec056aSPaolo Bonzinistatic int vector_reg_offset(X86DecodedOp *op) 14192ec056aSPaolo Bonzini{ 14292ec056aSPaolo Bonzini assert(op->unit == X86_OP_MMX || op->unit == X86_OP_SSE); 14392ec056aSPaolo Bonzini 14492ec056aSPaolo Bonzini if (op->unit == X86_OP_MMX) { 14592ec056aSPaolo Bonzini return op->offset - mmx_offset(op->ot); 14692ec056aSPaolo Bonzini } else { 14792ec056aSPaolo Bonzini return op->offset - xmm_offset(op->ot); 14892ec056aSPaolo Bonzini } 14992ec056aSPaolo Bonzini} 15092ec056aSPaolo Bonzini 15192ec056aSPaolo Bonzinistatic int vector_elem_offset(X86DecodedOp *op, MemOp ot, int n) 15292ec056aSPaolo Bonzini{ 15392ec056aSPaolo Bonzini int base_ofs = vector_reg_offset(op); 15492ec056aSPaolo Bonzini switch(ot) { 15592ec056aSPaolo Bonzini case MO_8: 15692ec056aSPaolo Bonzini if (op->unit == X86_OP_MMX) { 15792ec056aSPaolo Bonzini return base_ofs + offsetof(MMXReg, MMX_B(n)); 15892ec056aSPaolo Bonzini } else { 15992ec056aSPaolo Bonzini return base_ofs + offsetof(ZMMReg, ZMM_B(n)); 16092ec056aSPaolo Bonzini } 16192ec056aSPaolo Bonzini case MO_16: 16292ec056aSPaolo Bonzini if (op->unit == X86_OP_MMX) { 16392ec056aSPaolo Bonzini return base_ofs + offsetof(MMXReg, MMX_W(n)); 16492ec056aSPaolo Bonzini } else { 16592ec056aSPaolo Bonzini return base_ofs + offsetof(ZMMReg, ZMM_W(n)); 16692ec056aSPaolo Bonzini } 16792ec056aSPaolo Bonzini case MO_32: 16892ec056aSPaolo Bonzini if (op->unit == X86_OP_MMX) { 16992ec056aSPaolo Bonzini return base_ofs + offsetof(MMXReg, MMX_L(n)); 17092ec056aSPaolo Bonzini } else { 17192ec056aSPaolo Bonzini return base_ofs + offsetof(ZMMReg, ZMM_L(n)); 17292ec056aSPaolo Bonzini } 17392ec056aSPaolo Bonzini case MO_64: 17492ec056aSPaolo Bonzini if (op->unit == X86_OP_MMX) { 17592ec056aSPaolo Bonzini return base_ofs; 17692ec056aSPaolo Bonzini } else { 17792ec056aSPaolo Bonzini return base_ofs + offsetof(ZMMReg, ZMM_Q(n)); 17892ec056aSPaolo Bonzini } 17992ec056aSPaolo Bonzini case MO_128: 18092ec056aSPaolo Bonzini assert(op->unit == X86_OP_SSE); 18192ec056aSPaolo Bonzini return base_ofs + offsetof(ZMMReg, ZMM_X(n)); 18292ec056aSPaolo Bonzini case MO_256: 18392ec056aSPaolo Bonzini assert(op->unit == X86_OP_SSE); 18492ec056aSPaolo Bonzini return base_ofs + offsetof(ZMMReg, ZMM_Y(n)); 18592ec056aSPaolo Bonzini default: 18692ec056aSPaolo Bonzini g_assert_not_reached(); 18792ec056aSPaolo Bonzini } 18892ec056aSPaolo Bonzini} 18992ec056aSPaolo Bonzini 1906ba13999SPaolo Bonzinistatic void compute_mmx_offset(X86DecodedOp *op) 1916ba13999SPaolo Bonzini{ 1926ba13999SPaolo Bonzini if (!op->has_ea) { 1937700d229SRichard Henderson op->offset = MMX_OFFSET(op->n) + mmx_offset(op->ot); 1946ba13999SPaolo Bonzini } else { 1956ba13999SPaolo Bonzini op->offset = offsetof(CPUX86State, mmx_t0) + mmx_offset(op->ot); 1966ba13999SPaolo Bonzini } 1976ba13999SPaolo Bonzini} 1986ba13999SPaolo Bonzini 1996ba13999SPaolo Bonzinistatic void compute_xmm_offset(X86DecodedOp *op) 2006ba13999SPaolo Bonzini{ 2016ba13999SPaolo Bonzini if (!op->has_ea) { 2026ba13999SPaolo Bonzini op->offset = ZMM_OFFSET(op->n) + xmm_offset(op->ot); 2036ba13999SPaolo Bonzini } else { 2046ba13999SPaolo Bonzini op->offset = offsetof(CPUX86State, xmm_t0) + xmm_offset(op->ot); 2056ba13999SPaolo Bonzini } 2066ba13999SPaolo Bonzini} 2076ba13999SPaolo Bonzini 2086ba13999SPaolo Bonzinistatic void gen_load_sse(DisasContext *s, TCGv temp, MemOp ot, int dest_ofs, bool aligned) 2096ba13999SPaolo Bonzini{ 2106ba13999SPaolo Bonzini switch(ot) { 2116ba13999SPaolo Bonzini case MO_8: 2126ba13999SPaolo Bonzini gen_op_ld_v(s, MO_8, temp, s->A0); 213ad75a51eSRichard Henderson tcg_gen_st8_tl(temp, tcg_env, dest_ofs); 2146ba13999SPaolo Bonzini break; 2156ba13999SPaolo Bonzini case MO_16: 2166ba13999SPaolo Bonzini gen_op_ld_v(s, MO_16, temp, s->A0); 217ad75a51eSRichard Henderson tcg_gen_st16_tl(temp, tcg_env, dest_ofs); 2186ba13999SPaolo Bonzini break; 2196ba13999SPaolo Bonzini case MO_32: 2206ba13999SPaolo Bonzini gen_op_ld_v(s, MO_32, temp, s->A0); 221ad75a51eSRichard Henderson tcg_gen_st32_tl(temp, tcg_env, dest_ofs); 2226ba13999SPaolo Bonzini break; 2236ba13999SPaolo Bonzini case MO_64: 2246ba13999SPaolo Bonzini gen_ldq_env_A0(s, dest_ofs); 2256ba13999SPaolo Bonzini break; 2266ba13999SPaolo Bonzini case MO_128: 2276ba13999SPaolo Bonzini gen_ldo_env_A0(s, dest_ofs, aligned); 2286ba13999SPaolo Bonzini break; 2296ba13999SPaolo Bonzini case MO_256: 2306ba13999SPaolo Bonzini gen_ldy_env_A0(s, dest_ofs, aligned); 2316ba13999SPaolo Bonzini break; 2326ba13999SPaolo Bonzini default: 2336ba13999SPaolo Bonzini g_assert_not_reached(); 2346ba13999SPaolo Bonzini } 2356ba13999SPaolo Bonzini} 2366ba13999SPaolo Bonzini 23720581aadSPaolo Bonzinistatic bool sse_needs_alignment(DisasContext *s, X86DecodedInsn *decode, MemOp ot) 23820581aadSPaolo Bonzini{ 23920581aadSPaolo Bonzini switch (decode->e.vex_class) { 24020581aadSPaolo Bonzini case 2: 24120581aadSPaolo Bonzini case 4: 24220581aadSPaolo Bonzini if ((s->prefix & PREFIX_VEX) || 24320581aadSPaolo Bonzini decode->e.vex_special == X86_VEX_SSEUnaligned) { 24420581aadSPaolo Bonzini /* MOST legacy SSE instructions require aligned memory operands, but not all. */ 24520581aadSPaolo Bonzini return false; 24620581aadSPaolo Bonzini } 24720581aadSPaolo Bonzini /* fall through */ 24820581aadSPaolo Bonzini case 1: 24920581aadSPaolo Bonzini return ot >= MO_128; 25020581aadSPaolo Bonzini 25120581aadSPaolo Bonzini default: 25220581aadSPaolo Bonzini return false; 25320581aadSPaolo Bonzini } 25420581aadSPaolo Bonzini} 25520581aadSPaolo Bonzini 2566ba13999SPaolo Bonzinistatic void gen_load(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv v) 2576ba13999SPaolo Bonzini{ 2586ba13999SPaolo Bonzini X86DecodedOp *op = &decode->op[opn]; 2596ba13999SPaolo Bonzini 2606ba13999SPaolo Bonzini switch (op->unit) { 2616ba13999SPaolo Bonzini case X86_OP_SKIP: 2626ba13999SPaolo Bonzini return; 2636ba13999SPaolo Bonzini case X86_OP_SEG: 264ad75a51eSRichard Henderson tcg_gen_ld32u_tl(v, tcg_env, 2656ba13999SPaolo Bonzini offsetof(CPUX86State,segs[op->n].selector)); 2666ba13999SPaolo Bonzini break; 267a1af7fbaSPaolo Bonzini#ifndef CONFIG_USER_ONLY 2686ba13999SPaolo Bonzini case X86_OP_CR: 269a1af7fbaSPaolo Bonzini if (op->n == 8) { 270a1af7fbaSPaolo Bonzini translator_io_start(&s->base); 271e0448caeSPaolo Bonzini gen_helper_read_cr8(v, tcg_env); 272a1af7fbaSPaolo Bonzini } else { 273ad75a51eSRichard Henderson tcg_gen_ld_tl(v, tcg_env, offsetof(CPUX86State, cr[op->n])); 274a1af7fbaSPaolo Bonzini } 2756ba13999SPaolo Bonzini break; 2766ba13999SPaolo Bonzini case X86_OP_DR: 277a1af7fbaSPaolo Bonzini /* CR4.DE tested in the helper. */ 278a1af7fbaSPaolo Bonzini gen_helper_get_dr(v, tcg_env, tcg_constant_i32(op->n)); 2796ba13999SPaolo Bonzini break; 280a1af7fbaSPaolo Bonzini#endif 2816ba13999SPaolo Bonzini case X86_OP_INT: 2826ba13999SPaolo Bonzini if (op->has_ea) { 2838a36bbcfSPaolo Bonzini if (v == s->T0 && decode->e.special == X86_SPECIAL_SExtT0) { 2848a36bbcfSPaolo Bonzini gen_op_ld_v(s, op->ot | MO_SIGN, v, s->A0); 2856ba13999SPaolo Bonzini } else { 2868a36bbcfSPaolo Bonzini gen_op_ld_v(s, op->ot, v, s->A0); 2878a36bbcfSPaolo Bonzini } 2888a36bbcfSPaolo Bonzini 2898a36bbcfSPaolo Bonzini } else if (op->ot == MO_8 && byte_reg_is_xH(s, op->n)) { 2908a36bbcfSPaolo Bonzini if (v == s->T0 && decode->e.special == X86_SPECIAL_SExtT0) { 2918a36bbcfSPaolo Bonzini tcg_gen_sextract_tl(v, cpu_regs[op->n - 4], 8, 8); 2928a36bbcfSPaolo Bonzini } else { 2938a36bbcfSPaolo Bonzini tcg_gen_extract_tl(v, cpu_regs[op->n - 4], 8, 8); 2948a36bbcfSPaolo Bonzini } 2958a36bbcfSPaolo Bonzini 2968a36bbcfSPaolo Bonzini } else if (op->ot < MO_TL && v == s->T0 && 2978a36bbcfSPaolo Bonzini (decode->e.special == X86_SPECIAL_SExtT0 || 2988a36bbcfSPaolo Bonzini decode->e.special == X86_SPECIAL_ZExtT0)) { 2998a36bbcfSPaolo Bonzini if (decode->e.special == X86_SPECIAL_SExtT0) { 3008a36bbcfSPaolo Bonzini tcg_gen_ext_tl(v, cpu_regs[op->n], op->ot | MO_SIGN); 3018a36bbcfSPaolo Bonzini } else { 3028a36bbcfSPaolo Bonzini tcg_gen_ext_tl(v, cpu_regs[op->n], op->ot); 3038a36bbcfSPaolo Bonzini } 3048a36bbcfSPaolo Bonzini 3058a36bbcfSPaolo Bonzini } else { 3068a36bbcfSPaolo Bonzini tcg_gen_mov_tl(v, cpu_regs[op->n]); 3076ba13999SPaolo Bonzini } 3086ba13999SPaolo Bonzini break; 3096ba13999SPaolo Bonzini case X86_OP_IMM: 3102666fbd2SPaolo Bonzini tcg_gen_movi_tl(v, op->imm); 3116ba13999SPaolo Bonzini break; 3126ba13999SPaolo Bonzini 3136ba13999SPaolo Bonzini case X86_OP_MMX: 3146ba13999SPaolo Bonzini compute_mmx_offset(op); 3156ba13999SPaolo Bonzini goto load_vector; 3166ba13999SPaolo Bonzini 3176ba13999SPaolo Bonzini case X86_OP_SSE: 3186ba13999SPaolo Bonzini compute_xmm_offset(op); 3196ba13999SPaolo Bonzini load_vector: 3206ba13999SPaolo Bonzini if (op->has_ea) { 32120581aadSPaolo Bonzini bool aligned = sse_needs_alignment(s, decode, op->ot); 32220581aadSPaolo Bonzini gen_load_sse(s, v, op->ot, op->offset, aligned); 3236ba13999SPaolo Bonzini } 3246ba13999SPaolo Bonzini break; 3256ba13999SPaolo Bonzini 3266ba13999SPaolo Bonzini default: 3276ba13999SPaolo Bonzini g_assert_not_reached(); 3286ba13999SPaolo Bonzini } 3296ba13999SPaolo Bonzini} 3306ba13999SPaolo Bonzini 33192ec056aSPaolo Bonzinistatic TCGv_ptr op_ptr(X86DecodedInsn *decode, int opn) 33292ec056aSPaolo Bonzini{ 33392ec056aSPaolo Bonzini X86DecodedOp *op = &decode->op[opn]; 3342666fbd2SPaolo Bonzini 3352666fbd2SPaolo Bonzini assert(op->unit == X86_OP_MMX || op->unit == X86_OP_SSE); 33692ec056aSPaolo Bonzini if (op->v_ptr) { 33792ec056aSPaolo Bonzini return op->v_ptr; 33892ec056aSPaolo Bonzini } 33992ec056aSPaolo Bonzini op->v_ptr = tcg_temp_new_ptr(); 34092ec056aSPaolo Bonzini 34192ec056aSPaolo Bonzini /* The temporary points to the MMXReg or ZMMReg. */ 342ad75a51eSRichard Henderson tcg_gen_addi_ptr(op->v_ptr, tcg_env, vector_reg_offset(op)); 34392ec056aSPaolo Bonzini return op->v_ptr; 34492ec056aSPaolo Bonzini} 34592ec056aSPaolo Bonzini 34692ec056aSPaolo Bonzini#define OP_PTR0 op_ptr(decode, 0) 34792ec056aSPaolo Bonzini#define OP_PTR1 op_ptr(decode, 1) 34892ec056aSPaolo Bonzini#define OP_PTR2 op_ptr(decode, 2) 34992ec056aSPaolo Bonzini 3506ba13999SPaolo Bonzinistatic void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv v) 3516ba13999SPaolo Bonzini{ 3526ba13999SPaolo Bonzini X86DecodedOp *op = &decode->op[opn]; 3536ba13999SPaolo Bonzini switch (op->unit) { 3546ba13999SPaolo Bonzini case X86_OP_SKIP: 3556ba13999SPaolo Bonzini break; 3566ba13999SPaolo Bonzini case X86_OP_SEG: 357b6031364SPaolo Bonzini /* Note that gen_movl_seg takes care of interrupt shadow and TF. */ 358b6031364SPaolo Bonzini gen_movl_seg(s, op->n, s->T0); 3596ba13999SPaolo Bonzini break; 3606ba13999SPaolo Bonzini case X86_OP_INT: 3616ba13999SPaolo Bonzini if (op->has_ea) { 3626ba13999SPaolo Bonzini gen_op_st_v(s, op->ot, v, s->A0); 3636ba13999SPaolo Bonzini } else { 3646ba13999SPaolo Bonzini gen_op_mov_reg_v(s, op->ot, op->n, v); 3656ba13999SPaolo Bonzini } 3666ba13999SPaolo Bonzini break; 3676ba13999SPaolo Bonzini case X86_OP_MMX: 36820581aadSPaolo Bonzini break; 3696ba13999SPaolo Bonzini case X86_OP_SSE: 370cf5ec664SPaolo Bonzini if (!op->has_ea && (s->prefix & PREFIX_VEX) && op->ot <= MO_128) { 37120581aadSPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, 37220581aadSPaolo Bonzini offsetof(CPUX86State, xmm_regs[op->n].ZMM_X(1)), 37320581aadSPaolo Bonzini 16, 16, 0); 37420581aadSPaolo Bonzini } 3756ba13999SPaolo Bonzini break; 376a1af7fbaSPaolo Bonzini#ifndef CONFIG_USER_ONLY 3776ba13999SPaolo Bonzini case X86_OP_CR: 378a1af7fbaSPaolo Bonzini if (op->n == 8) { 379a1af7fbaSPaolo Bonzini translator_io_start(&s->base); 380a1af7fbaSPaolo Bonzini } 381a1af7fbaSPaolo Bonzini gen_helper_write_crN(tcg_env, tcg_constant_i32(op->n), v); 382a1af7fbaSPaolo Bonzini s->base.is_jmp = DISAS_EOB_NEXT; 383a1af7fbaSPaolo Bonzini break; 3846ba13999SPaolo Bonzini case X86_OP_DR: 385a1af7fbaSPaolo Bonzini /* CR4.DE tested in the helper. */ 386a1af7fbaSPaolo Bonzini gen_helper_set_dr(tcg_env, tcg_constant_i32(op->n), v); 387a1af7fbaSPaolo Bonzini s->base.is_jmp = DISAS_EOB_NEXT; 388a1af7fbaSPaolo Bonzini break; 389a1af7fbaSPaolo Bonzini#endif 3906ba13999SPaolo Bonzini default: 3916ba13999SPaolo Bonzini g_assert_not_reached(); 3926ba13999SPaolo Bonzini } 393d7c41a60SPaolo Bonzini op->unit = X86_OP_SKIP; 3946ba13999SPaolo Bonzini} 3951d0b9261SPaolo Bonzini 39692ec056aSPaolo Bonzinistatic inline int vector_len(DisasContext *s, X86DecodedInsn *decode) 39792ec056aSPaolo Bonzini{ 39892ec056aSPaolo Bonzini if (decode->e.special == X86_SPECIAL_MMX && 39992ec056aSPaolo Bonzini !(s->prefix & (PREFIX_DATA | PREFIX_REPZ | PREFIX_REPNZ))) { 40092ec056aSPaolo Bonzini return 8; 40192ec056aSPaolo Bonzini } 40292ec056aSPaolo Bonzini return s->vex_l ? 32 : 16; 40392ec056aSPaolo Bonzini} 40492ec056aSPaolo Bonzini 405e7bbb7cbSPaolo Bonzinistatic void prepare_update1_cc(X86DecodedInsn *decode, DisasContext *s, CCOp op) 406e7bbb7cbSPaolo Bonzini{ 407e7bbb7cbSPaolo Bonzini decode->cc_dst = s->T0; 408e7bbb7cbSPaolo Bonzini decode->cc_op = op; 409e7bbb7cbSPaolo Bonzini} 410e7bbb7cbSPaolo Bonzini 411e7bbb7cbSPaolo Bonzinistatic void prepare_update2_cc(X86DecodedInsn *decode, DisasContext *s, CCOp op) 412e7bbb7cbSPaolo Bonzini{ 413e7bbb7cbSPaolo Bonzini decode->cc_src = s->T1; 414e7bbb7cbSPaolo Bonzini decode->cc_dst = s->T0; 415e7bbb7cbSPaolo Bonzini decode->cc_op = op; 416e7bbb7cbSPaolo Bonzini} 417e7bbb7cbSPaolo Bonzini 418cc1d28bdSPaolo Bonzinistatic void prepare_update_cc_incdec(X86DecodedInsn *decode, DisasContext *s, CCOp op) 419cc1d28bdSPaolo Bonzini{ 420cc1d28bdSPaolo Bonzini gen_compute_eflags_c(s, s->T1); 421cc1d28bdSPaolo Bonzini prepare_update2_cc(decode, s, op); 422cc1d28bdSPaolo Bonzini} 423cc1d28bdSPaolo Bonzini 424cc1d28bdSPaolo Bonzinistatic void prepare_update3_cc(X86DecodedInsn *decode, DisasContext *s, CCOp op, TCGv reg) 425cc1d28bdSPaolo Bonzini{ 426cc1d28bdSPaolo Bonzini decode->cc_src2 = reg; 427cc1d28bdSPaolo Bonzini decode->cc_src = s->T1; 428cc1d28bdSPaolo Bonzini decode->cc_dst = s->T0; 429cc1d28bdSPaolo Bonzini decode->cc_op = op; 430cc1d28bdSPaolo Bonzini} 431cc1d28bdSPaolo Bonzini 43210eae899SPaolo Bonzini/* Set up decode->cc_* to modify CF while keeping other flags unchanged. */ 43310eae899SPaolo Bonzinistatic void prepare_update_cf(X86DecodedInsn *decode, DisasContext *s, TCGv cf) 43410eae899SPaolo Bonzini{ 43510eae899SPaolo Bonzini switch (s->cc_op) { 43610eae899SPaolo Bonzini case CC_OP_ADOX: 43710eae899SPaolo Bonzini case CC_OP_ADCOX: 43810eae899SPaolo Bonzini decode->cc_src2 = cpu_cc_src2; 43910eae899SPaolo Bonzini decode->cc_src = cpu_cc_src; 44010eae899SPaolo Bonzini decode->cc_op = CC_OP_ADCOX; 44110eae899SPaolo Bonzini break; 44210eae899SPaolo Bonzini 44310eae899SPaolo Bonzini case CC_OP_EFLAGS: 44410eae899SPaolo Bonzini case CC_OP_ADCX: 44510eae899SPaolo Bonzini decode->cc_src = cpu_cc_src; 44610eae899SPaolo Bonzini decode->cc_op = CC_OP_ADCX; 44710eae899SPaolo Bonzini break; 44810eae899SPaolo Bonzini 44910eae899SPaolo Bonzini default: 45010eae899SPaolo Bonzini decode->cc_src = tcg_temp_new(); 45110eae899SPaolo Bonzini gen_mov_eflags(s, decode->cc_src); 45210eae899SPaolo Bonzini decode->cc_op = CC_OP_ADCX; 45310eae899SPaolo Bonzini break; 45410eae899SPaolo Bonzini } 45510eae899SPaolo Bonzini decode->cc_dst = cf; 45610eae899SPaolo Bonzini} 45710eae899SPaolo Bonzini 45892ec056aSPaolo Bonzinistatic void gen_store_sse(DisasContext *s, X86DecodedInsn *decode, int src_ofs) 45992ec056aSPaolo Bonzini{ 46092ec056aSPaolo Bonzini MemOp ot = decode->op[0].ot; 46192ec056aSPaolo Bonzini int vec_len = vector_len(s, decode); 46292ec056aSPaolo Bonzini bool aligned = sse_needs_alignment(s, decode, ot); 46392ec056aSPaolo Bonzini 46492ec056aSPaolo Bonzini if (!decode->op[0].has_ea) { 46592ec056aSPaolo Bonzini tcg_gen_gvec_mov(MO_64, decode->op[0].offset, src_ofs, vec_len, vec_len); 46692ec056aSPaolo Bonzini return; 46792ec056aSPaolo Bonzini } 46892ec056aSPaolo Bonzini 46992ec056aSPaolo Bonzini switch (ot) { 47092ec056aSPaolo Bonzini case MO_64: 47192ec056aSPaolo Bonzini gen_stq_env_A0(s, src_ofs); 47292ec056aSPaolo Bonzini break; 47392ec056aSPaolo Bonzini case MO_128: 47492ec056aSPaolo Bonzini gen_sto_env_A0(s, src_ofs, aligned); 47592ec056aSPaolo Bonzini break; 47692ec056aSPaolo Bonzini case MO_256: 47792ec056aSPaolo Bonzini gen_sty_env_A0(s, src_ofs, aligned); 47892ec056aSPaolo Bonzini break; 47992ec056aSPaolo Bonzini default: 48092ec056aSPaolo Bonzini g_assert_not_reached(); 48192ec056aSPaolo Bonzini } 48292ec056aSPaolo Bonzini} 48392ec056aSPaolo Bonzini 48471a0891dSPaolo Bonzinistatic void gen_helper_pavgusb(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b) 48571a0891dSPaolo Bonzini{ 48671a0891dSPaolo Bonzini gen_helper_pavgb_mmx(env, reg_a, reg_a, reg_b); 48771a0891dSPaolo Bonzini} 48871a0891dSPaolo Bonzini 48971a0891dSPaolo Bonzini#define FN_3DNOW_MOVE ((SSEFunc_0_epp) (uintptr_t) 1) 49071a0891dSPaolo Bonzinistatic const SSEFunc_0_epp fns_3dnow[] = { 49171a0891dSPaolo Bonzini [0x0c] = gen_helper_pi2fw, 49271a0891dSPaolo Bonzini [0x0d] = gen_helper_pi2fd, 49371a0891dSPaolo Bonzini [0x1c] = gen_helper_pf2iw, 49471a0891dSPaolo Bonzini [0x1d] = gen_helper_pf2id, 49571a0891dSPaolo Bonzini [0x8a] = gen_helper_pfnacc, 49671a0891dSPaolo Bonzini [0x8e] = gen_helper_pfpnacc, 49771a0891dSPaolo Bonzini [0x90] = gen_helper_pfcmpge, 49871a0891dSPaolo Bonzini [0x94] = gen_helper_pfmin, 49971a0891dSPaolo Bonzini [0x96] = gen_helper_pfrcp, 50071a0891dSPaolo Bonzini [0x97] = gen_helper_pfrsqrt, 50171a0891dSPaolo Bonzini [0x9a] = gen_helper_pfsub, 50271a0891dSPaolo Bonzini [0x9e] = gen_helper_pfadd, 50371a0891dSPaolo Bonzini [0xa0] = gen_helper_pfcmpgt, 50471a0891dSPaolo Bonzini [0xa4] = gen_helper_pfmax, 50571a0891dSPaolo Bonzini [0xa6] = FN_3DNOW_MOVE, /* PFRCPIT1; no need to actually increase precision */ 50671a0891dSPaolo Bonzini [0xa7] = FN_3DNOW_MOVE, /* PFRSQIT1 */ 50771a0891dSPaolo Bonzini [0xb6] = FN_3DNOW_MOVE, /* PFRCPIT2 */ 50871a0891dSPaolo Bonzini [0xaa] = gen_helper_pfsubr, 50971a0891dSPaolo Bonzini [0xae] = gen_helper_pfacc, 51071a0891dSPaolo Bonzini [0xb0] = gen_helper_pfcmpeq, 51171a0891dSPaolo Bonzini [0xb4] = gen_helper_pfmul, 51271a0891dSPaolo Bonzini [0xb7] = gen_helper_pmulhrw_mmx, 51371a0891dSPaolo Bonzini [0xbb] = gen_helper_pswapd, 51471a0891dSPaolo Bonzini [0xbf] = gen_helper_pavgusb, 51571a0891dSPaolo Bonzini}; 51671a0891dSPaolo Bonzini 5174228eb8cSPaolo Bonzinistatic void gen_3dnow(DisasContext *s, X86DecodedInsn *decode) 51871a0891dSPaolo Bonzini{ 51971a0891dSPaolo Bonzini uint8_t b = decode->immediate; 52071a0891dSPaolo Bonzini SSEFunc_0_epp fn = b < ARRAY_SIZE(fns_3dnow) ? fns_3dnow[b] : NULL; 52171a0891dSPaolo Bonzini 52271a0891dSPaolo Bonzini if (!fn) { 52371a0891dSPaolo Bonzini gen_illegal_opcode(s); 52471a0891dSPaolo Bonzini return; 52571a0891dSPaolo Bonzini } 52671a0891dSPaolo Bonzini if (s->flags & HF_TS_MASK) { 52771a0891dSPaolo Bonzini gen_NM_exception(s); 52871a0891dSPaolo Bonzini return; 52971a0891dSPaolo Bonzini } 53071a0891dSPaolo Bonzini if (s->flags & HF_EM_MASK) { 53171a0891dSPaolo Bonzini gen_illegal_opcode(s); 53271a0891dSPaolo Bonzini return; 53371a0891dSPaolo Bonzini } 53471a0891dSPaolo Bonzini 535ad75a51eSRichard Henderson gen_helper_enter_mmx(tcg_env); 53671a0891dSPaolo Bonzini if (fn == FN_3DNOW_MOVE) { 537ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[1].offset); 538ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset); 53971a0891dSPaolo Bonzini } else { 540ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR1); 54171a0891dSPaolo Bonzini } 54271a0891dSPaolo Bonzini} 54371a0891dSPaolo Bonzini 54403b45880SPaolo Bonzini/* 54503b45880SPaolo Bonzini * 00 = v*ps Vps, Hps, Wpd 54603b45880SPaolo Bonzini * 66 = v*pd Vpd, Hpd, Wps 54703b45880SPaolo Bonzini * f3 = v*ss Vss, Hss, Wps 54803b45880SPaolo Bonzini * f2 = v*sd Vsd, Hsd, Wps 54903b45880SPaolo Bonzini */ 5504228eb8cSPaolo Bonzinistatic inline void gen_unary_fp_sse(DisasContext *s, X86DecodedInsn *decode, 55103b45880SPaolo Bonzini SSEFunc_0_epp pd_xmm, SSEFunc_0_epp ps_xmm, 55203b45880SPaolo Bonzini SSEFunc_0_epp pd_ymm, SSEFunc_0_epp ps_ymm, 55303b45880SPaolo Bonzini SSEFunc_0_eppp sd, SSEFunc_0_eppp ss) 55403b45880SPaolo Bonzini{ 55503b45880SPaolo Bonzini if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) != 0) { 55603b45880SPaolo Bonzini SSEFunc_0_eppp fn = s->prefix & PREFIX_REPZ ? ss : sd; 55703b45880SPaolo Bonzini if (!fn) { 55803b45880SPaolo Bonzini gen_illegal_opcode(s); 55903b45880SPaolo Bonzini return; 56003b45880SPaolo Bonzini } 561ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 56203b45880SPaolo Bonzini } else { 56303b45880SPaolo Bonzini SSEFunc_0_epp ps, pd, fn; 56403b45880SPaolo Bonzini ps = s->vex_l ? ps_ymm : ps_xmm; 56503b45880SPaolo Bonzini pd = s->vex_l ? pd_ymm : pd_xmm; 56603b45880SPaolo Bonzini fn = s->prefix & PREFIX_DATA ? pd : ps; 56703b45880SPaolo Bonzini if (!fn) { 56803b45880SPaolo Bonzini gen_illegal_opcode(s); 56903b45880SPaolo Bonzini return; 57003b45880SPaolo Bonzini } 571ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR2); 57203b45880SPaolo Bonzini } 57303b45880SPaolo Bonzini} 57403b45880SPaolo Bonzini#define UNARY_FP_SSE(uname, lname) \ 5754228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 57603b45880SPaolo Bonzini{ \ 5774228eb8cSPaolo Bonzini gen_unary_fp_sse(s, decode, \ 57803b45880SPaolo Bonzini gen_helper_##lname##pd_xmm, \ 57903b45880SPaolo Bonzini gen_helper_##lname##ps_xmm, \ 58003b45880SPaolo Bonzini gen_helper_##lname##pd_ymm, \ 58103b45880SPaolo Bonzini gen_helper_##lname##ps_ymm, \ 58203b45880SPaolo Bonzini gen_helper_##lname##sd, \ 58303b45880SPaolo Bonzini gen_helper_##lname##ss); \ 58403b45880SPaolo Bonzini} 58503b45880SPaolo BonziniUNARY_FP_SSE(VSQRT, sqrt) 58603b45880SPaolo Bonzini 58703b45880SPaolo Bonzini/* 58803b45880SPaolo Bonzini * 00 = v*ps Vps, Hps, Wpd 58903b45880SPaolo Bonzini * 66 = v*pd Vpd, Hpd, Wps 59003b45880SPaolo Bonzini * f3 = v*ss Vss, Hss, Wps 59103b45880SPaolo Bonzini * f2 = v*sd Vsd, Hsd, Wps 59203b45880SPaolo Bonzini */ 5934228eb8cSPaolo Bonzinistatic inline void gen_fp_sse(DisasContext *s, X86DecodedInsn *decode, 59403b45880SPaolo Bonzini SSEFunc_0_eppp pd_xmm, SSEFunc_0_eppp ps_xmm, 59503b45880SPaolo Bonzini SSEFunc_0_eppp pd_ymm, SSEFunc_0_eppp ps_ymm, 59603b45880SPaolo Bonzini SSEFunc_0_eppp sd, SSEFunc_0_eppp ss) 59703b45880SPaolo Bonzini{ 59803b45880SPaolo Bonzini SSEFunc_0_eppp ps, pd, fn; 59903b45880SPaolo Bonzini if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) != 0) { 60003b45880SPaolo Bonzini fn = s->prefix & PREFIX_REPZ ? ss : sd; 60103b45880SPaolo Bonzini } else { 60203b45880SPaolo Bonzini ps = s->vex_l ? ps_ymm : ps_xmm; 60303b45880SPaolo Bonzini pd = s->vex_l ? pd_ymm : pd_xmm; 60403b45880SPaolo Bonzini fn = s->prefix & PREFIX_DATA ? pd : ps; 60503b45880SPaolo Bonzini } 60603b45880SPaolo Bonzini if (fn) { 607ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 60803b45880SPaolo Bonzini } else { 60903b45880SPaolo Bonzini gen_illegal_opcode(s); 61003b45880SPaolo Bonzini } 61103b45880SPaolo Bonzini} 6127170a17eSPaolo Bonzini 61303b45880SPaolo Bonzini#define FP_SSE(uname, lname) \ 6144228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 61503b45880SPaolo Bonzini{ \ 6164228eb8cSPaolo Bonzini gen_fp_sse(s, decode, \ 61703b45880SPaolo Bonzini gen_helper_##lname##pd_xmm, \ 61803b45880SPaolo Bonzini gen_helper_##lname##ps_xmm, \ 61903b45880SPaolo Bonzini gen_helper_##lname##pd_ymm, \ 62003b45880SPaolo Bonzini gen_helper_##lname##ps_ymm, \ 62103b45880SPaolo Bonzini gen_helper_##lname##sd, \ 62203b45880SPaolo Bonzini gen_helper_##lname##ss); \ 62303b45880SPaolo Bonzini} 62403b45880SPaolo BonziniFP_SSE(VADD, add) 62503b45880SPaolo BonziniFP_SSE(VMUL, mul) 62603b45880SPaolo BonziniFP_SSE(VSUB, sub) 62703b45880SPaolo BonziniFP_SSE(VMIN, min) 62803b45880SPaolo BonziniFP_SSE(VDIV, div) 62903b45880SPaolo BonziniFP_SSE(VMAX, max) 63003b45880SPaolo Bonzini 6312872b0f3SPaolo Bonzini#define FMA_SSE_PACKED(uname, ptr0, ptr1, ptr2, even, odd) \ 6324228eb8cSPaolo Bonzinistatic void gen_##uname##Px(DisasContext *s, X86DecodedInsn *decode) \ 6332872b0f3SPaolo Bonzini{ \ 6342872b0f3SPaolo Bonzini SSEFunc_0_eppppii xmm = s->vex_w ? gen_helper_fma4pd_xmm : gen_helper_fma4ps_xmm; \ 6352872b0f3SPaolo Bonzini SSEFunc_0_eppppii ymm = s->vex_w ? gen_helper_fma4pd_ymm : gen_helper_fma4ps_ymm; \ 6362872b0f3SPaolo Bonzini SSEFunc_0_eppppii fn = s->vex_l ? ymm : xmm; \ 6372872b0f3SPaolo Bonzini \ 638ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, ptr0, ptr1, ptr2, \ 6392872b0f3SPaolo Bonzini tcg_constant_i32(even), \ 6402872b0f3SPaolo Bonzini tcg_constant_i32((even) ^ (odd))); \ 6412872b0f3SPaolo Bonzini} 6422872b0f3SPaolo Bonzini 6432872b0f3SPaolo Bonzini#define FMA_SSE(uname, ptr0, ptr1, ptr2, flags) \ 6442872b0f3SPaolo BonziniFMA_SSE_PACKED(uname, ptr0, ptr1, ptr2, flags, flags) \ 6454228eb8cSPaolo Bonzinistatic void gen_##uname##Sx(DisasContext *s, X86DecodedInsn *decode) \ 6462872b0f3SPaolo Bonzini{ \ 6472872b0f3SPaolo Bonzini SSEFunc_0_eppppi fn = s->vex_w ? gen_helper_fma4sd : gen_helper_fma4ss; \ 6482872b0f3SPaolo Bonzini \ 649ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, ptr0, ptr1, ptr2, \ 6502872b0f3SPaolo Bonzini tcg_constant_i32(flags)); \ 6512872b0f3SPaolo Bonzini} \ 6522872b0f3SPaolo Bonzini 6532872b0f3SPaolo BonziniFMA_SSE(VFMADD231, OP_PTR1, OP_PTR2, OP_PTR0, 0) 6542872b0f3SPaolo BonziniFMA_SSE(VFMADD213, OP_PTR1, OP_PTR0, OP_PTR2, 0) 6552872b0f3SPaolo BonziniFMA_SSE(VFMADD132, OP_PTR0, OP_PTR2, OP_PTR1, 0) 6562872b0f3SPaolo Bonzini 6572872b0f3SPaolo BonziniFMA_SSE(VFNMADD231, OP_PTR1, OP_PTR2, OP_PTR0, float_muladd_negate_product) 6582872b0f3SPaolo BonziniFMA_SSE(VFNMADD213, OP_PTR1, OP_PTR0, OP_PTR2, float_muladd_negate_product) 6592872b0f3SPaolo BonziniFMA_SSE(VFNMADD132, OP_PTR0, OP_PTR2, OP_PTR1, float_muladd_negate_product) 6602872b0f3SPaolo Bonzini 6612872b0f3SPaolo BonziniFMA_SSE(VFMSUB231, OP_PTR1, OP_PTR2, OP_PTR0, float_muladd_negate_c) 6622872b0f3SPaolo BonziniFMA_SSE(VFMSUB213, OP_PTR1, OP_PTR0, OP_PTR2, float_muladd_negate_c) 6632872b0f3SPaolo BonziniFMA_SSE(VFMSUB132, OP_PTR0, OP_PTR2, OP_PTR1, float_muladd_negate_c) 6642872b0f3SPaolo Bonzini 6652872b0f3SPaolo BonziniFMA_SSE(VFNMSUB231, OP_PTR1, OP_PTR2, OP_PTR0, float_muladd_negate_c|float_muladd_negate_product) 6662872b0f3SPaolo BonziniFMA_SSE(VFNMSUB213, OP_PTR1, OP_PTR0, OP_PTR2, float_muladd_negate_c|float_muladd_negate_product) 6672872b0f3SPaolo BonziniFMA_SSE(VFNMSUB132, OP_PTR0, OP_PTR2, OP_PTR1, float_muladd_negate_c|float_muladd_negate_product) 6682872b0f3SPaolo Bonzini 6692872b0f3SPaolo BonziniFMA_SSE_PACKED(VFMADDSUB231, OP_PTR1, OP_PTR2, OP_PTR0, float_muladd_negate_c, 0) 6702872b0f3SPaolo BonziniFMA_SSE_PACKED(VFMADDSUB213, OP_PTR1, OP_PTR0, OP_PTR2, float_muladd_negate_c, 0) 6712872b0f3SPaolo BonziniFMA_SSE_PACKED(VFMADDSUB132, OP_PTR0, OP_PTR2, OP_PTR1, float_muladd_negate_c, 0) 6722872b0f3SPaolo Bonzini 6732872b0f3SPaolo BonziniFMA_SSE_PACKED(VFMSUBADD231, OP_PTR1, OP_PTR2, OP_PTR0, 0, float_muladd_negate_c) 6742872b0f3SPaolo BonziniFMA_SSE_PACKED(VFMSUBADD213, OP_PTR1, OP_PTR0, OP_PTR2, 0, float_muladd_negate_c) 6752872b0f3SPaolo BonziniFMA_SSE_PACKED(VFMSUBADD132, OP_PTR0, OP_PTR2, OP_PTR1, 0, float_muladd_negate_c) 6762872b0f3SPaolo Bonzini 6777170a17eSPaolo Bonzini#define FP_UNPACK_SSE(uname, lname) \ 6784228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 6797170a17eSPaolo Bonzini{ \ 6807170a17eSPaolo Bonzini /* PS maps to the DQ integer instruction, PD maps to QDQ. */ \ 6814228eb8cSPaolo Bonzini gen_fp_sse(s, decode, \ 6827170a17eSPaolo Bonzini gen_helper_##lname##qdq_xmm, \ 6837170a17eSPaolo Bonzini gen_helper_##lname##dq_xmm, \ 6847170a17eSPaolo Bonzini gen_helper_##lname##qdq_ymm, \ 6857170a17eSPaolo Bonzini gen_helper_##lname##dq_ymm, \ 6867170a17eSPaolo Bonzini NULL, NULL); \ 6877170a17eSPaolo Bonzini} 6887170a17eSPaolo BonziniFP_UNPACK_SSE(VUNPCKLPx, punpckl) 6897170a17eSPaolo BonziniFP_UNPACK_SSE(VUNPCKHPx, punpckh) 6907170a17eSPaolo Bonzini 69103b45880SPaolo Bonzini/* 69203b45880SPaolo Bonzini * 00 = v*ps Vps, Wpd 69303b45880SPaolo Bonzini * f3 = v*ss Vss, Wps 69403b45880SPaolo Bonzini */ 6954228eb8cSPaolo Bonzinistatic inline void gen_unary_fp32_sse(DisasContext *s, X86DecodedInsn *decode, 69603b45880SPaolo Bonzini SSEFunc_0_epp ps_xmm, 69703b45880SPaolo Bonzini SSEFunc_0_epp ps_ymm, 69803b45880SPaolo Bonzini SSEFunc_0_eppp ss) 69903b45880SPaolo Bonzini{ 70003b45880SPaolo Bonzini if ((s->prefix & (PREFIX_DATA | PREFIX_REPNZ)) != 0) { 70103b45880SPaolo Bonzini goto illegal_op; 70203b45880SPaolo Bonzini } else if (s->prefix & PREFIX_REPZ) { 70303b45880SPaolo Bonzini if (!ss) { 70403b45880SPaolo Bonzini goto illegal_op; 70503b45880SPaolo Bonzini } 706ad75a51eSRichard Henderson ss(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 70703b45880SPaolo Bonzini } else { 70803b45880SPaolo Bonzini SSEFunc_0_epp fn = s->vex_l ? ps_ymm : ps_xmm; 70903b45880SPaolo Bonzini if (!fn) { 71003b45880SPaolo Bonzini goto illegal_op; 71103b45880SPaolo Bonzini } 712ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR2); 71303b45880SPaolo Bonzini } 71403b45880SPaolo Bonzini return; 71503b45880SPaolo Bonzini 71603b45880SPaolo Bonziniillegal_op: 71703b45880SPaolo Bonzini gen_illegal_opcode(s); 71803b45880SPaolo Bonzini} 71903b45880SPaolo Bonzini#define UNARY_FP32_SSE(uname, lname) \ 7204228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 72103b45880SPaolo Bonzini{ \ 7224228eb8cSPaolo Bonzini gen_unary_fp32_sse(s, decode, \ 72303b45880SPaolo Bonzini gen_helper_##lname##ps_xmm, \ 72403b45880SPaolo Bonzini gen_helper_##lname##ps_ymm, \ 72503b45880SPaolo Bonzini gen_helper_##lname##ss); \ 72603b45880SPaolo Bonzini} 72703b45880SPaolo BonziniUNARY_FP32_SSE(VRSQRT, rsqrt) 72803b45880SPaolo BonziniUNARY_FP32_SSE(VRCP, rcp) 72903b45880SPaolo Bonzini 730d1c1a422SPaolo Bonzini/* 731d1c1a422SPaolo Bonzini * 66 = v*pd Vpd, Hpd, Wpd 732d1c1a422SPaolo Bonzini * f2 = v*ps Vps, Hps, Wps 733d1c1a422SPaolo Bonzini */ 7344228eb8cSPaolo Bonzinistatic inline void gen_horizontal_fp_sse(DisasContext *s, X86DecodedInsn *decode, 735d1c1a422SPaolo Bonzini SSEFunc_0_eppp pd_xmm, SSEFunc_0_eppp ps_xmm, 736d1c1a422SPaolo Bonzini SSEFunc_0_eppp pd_ymm, SSEFunc_0_eppp ps_ymm) 737d1c1a422SPaolo Bonzini{ 738d1c1a422SPaolo Bonzini SSEFunc_0_eppp ps, pd, fn; 739d1c1a422SPaolo Bonzini ps = s->vex_l ? ps_ymm : ps_xmm; 740d1c1a422SPaolo Bonzini pd = s->vex_l ? pd_ymm : pd_xmm; 741d1c1a422SPaolo Bonzini fn = s->prefix & PREFIX_DATA ? pd : ps; 742ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 743d1c1a422SPaolo Bonzini} 744d1c1a422SPaolo Bonzini#define HORIZONTAL_FP_SSE(uname, lname) \ 7454228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 746d1c1a422SPaolo Bonzini{ \ 7474228eb8cSPaolo Bonzini gen_horizontal_fp_sse(s, decode, \ 748d1c1a422SPaolo Bonzini gen_helper_##lname##pd_xmm, gen_helper_##lname##ps_xmm, \ 749d1c1a422SPaolo Bonzini gen_helper_##lname##pd_ymm, gen_helper_##lname##ps_ymm); \ 750d1c1a422SPaolo Bonzini} 751d1c1a422SPaolo BonziniHORIZONTAL_FP_SSE(VHADD, hadd) 752d1c1a422SPaolo BonziniHORIZONTAL_FP_SSE(VHSUB, hsub) 7536bbeb98dSPaolo BonziniHORIZONTAL_FP_SSE(VADDSUB, addsub) 754d1c1a422SPaolo Bonzini 7554228eb8cSPaolo Bonzinistatic inline void gen_ternary_sse(DisasContext *s, X86DecodedInsn *decode, 75679068477SPaolo Bonzini int op3, SSEFunc_0_epppp xmm, SSEFunc_0_epppp ymm) 75779068477SPaolo Bonzini{ 75879068477SPaolo Bonzini SSEFunc_0_epppp fn = s->vex_l ? ymm : xmm; 75979068477SPaolo Bonzini TCGv_ptr ptr3 = tcg_temp_new_ptr(); 76079068477SPaolo Bonzini 76179068477SPaolo Bonzini /* The format of the fourth input is Lx */ 762ad75a51eSRichard Henderson tcg_gen_addi_ptr(ptr3, tcg_env, ZMM_OFFSET(op3)); 763ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, ptr3); 76479068477SPaolo Bonzini} 76516fc5726SPaolo Bonzini#define TERNARY_SSE(uname, uvname, lname) \ 7664228eb8cSPaolo Bonzinistatic void gen_##uvname(DisasContext *s, X86DecodedInsn *decode) \ 76779068477SPaolo Bonzini{ \ 7684228eb8cSPaolo Bonzini gen_ternary_sse(s, decode, (uint8_t)decode->immediate >> 4, \ 76979068477SPaolo Bonzini gen_helper_##lname##_xmm, gen_helper_##lname##_ymm); \ 77016fc5726SPaolo Bonzini} \ 7714228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 77216fc5726SPaolo Bonzini{ \ 7734228eb8cSPaolo Bonzini gen_ternary_sse(s, decode, 0, \ 77416fc5726SPaolo Bonzini gen_helper_##lname##_xmm, gen_helper_##lname##_ymm); \ 77579068477SPaolo Bonzini} 77616fc5726SPaolo BonziniTERNARY_SSE(BLENDVPS, VBLENDVPS, blendvps) 77716fc5726SPaolo BonziniTERNARY_SSE(BLENDVPD, VBLENDVPD, blendvpd) 77816fc5726SPaolo BonziniTERNARY_SSE(PBLENDVB, VPBLENDVB, pblendvb) 77979068477SPaolo Bonzini 7804228eb8cSPaolo Bonzinistatic inline void gen_binary_imm_sse(DisasContext *s, X86DecodedInsn *decode, 78179068477SPaolo Bonzini SSEFunc_0_epppi xmm, SSEFunc_0_epppi ymm) 78279068477SPaolo Bonzini{ 78379068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 78479068477SPaolo Bonzini if (!s->vex_l) { 785ad75a51eSRichard Henderson xmm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm); 78679068477SPaolo Bonzini } else { 787ad75a51eSRichard Henderson ymm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm); 78879068477SPaolo Bonzini } 78979068477SPaolo Bonzini} 79079068477SPaolo Bonzini 79179068477SPaolo Bonzini#define BINARY_IMM_SSE(uname, lname) \ 7924228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 79379068477SPaolo Bonzini{ \ 7944228eb8cSPaolo Bonzini gen_binary_imm_sse(s, decode, \ 79579068477SPaolo Bonzini gen_helper_##lname##_xmm, \ 79679068477SPaolo Bonzini gen_helper_##lname##_ymm); \ 79779068477SPaolo Bonzini} 79879068477SPaolo Bonzini 79979068477SPaolo BonziniBINARY_IMM_SSE(VBLENDPD, blendpd) 80079068477SPaolo BonziniBINARY_IMM_SSE(VBLENDPS, blendps) 80179068477SPaolo BonziniBINARY_IMM_SSE(VPBLENDW, pblendw) 80279068477SPaolo BonziniBINARY_IMM_SSE(VDDPS, dpps) 80379068477SPaolo Bonzini#define gen_helper_dppd_ymm NULL 80479068477SPaolo BonziniBINARY_IMM_SSE(VDDPD, dppd) 80579068477SPaolo BonziniBINARY_IMM_SSE(VMPSADBW, mpsadbw) 80679068477SPaolo BonziniBINARY_IMM_SSE(PCLMULQDQ, pclmulqdq) 80779068477SPaolo Bonzini 80816fc5726SPaolo Bonzini 80916fc5726SPaolo Bonzini#define UNARY_INT_GVEC(uname, func, ...) \ 8104228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 81116fc5726SPaolo Bonzini{ \ 81216fc5726SPaolo Bonzini int vec_len = vector_len(s, decode); \ 81316fc5726SPaolo Bonzini \ 81416fc5726SPaolo Bonzini func(__VA_ARGS__, decode->op[0].offset, \ 81516fc5726SPaolo Bonzini decode->op[2].offset, vec_len, vec_len); \ 81616fc5726SPaolo Bonzini} 81716fc5726SPaolo BonziniUNARY_INT_GVEC(PABSB, tcg_gen_gvec_abs, MO_8) 81816fc5726SPaolo BonziniUNARY_INT_GVEC(PABSW, tcg_gen_gvec_abs, MO_16) 81916fc5726SPaolo BonziniUNARY_INT_GVEC(PABSD, tcg_gen_gvec_abs, MO_32) 82016fc5726SPaolo BonziniUNARY_INT_GVEC(VBROADCASTx128, tcg_gen_gvec_dup_mem, MO_128) 82116fc5726SPaolo BonziniUNARY_INT_GVEC(VPBROADCASTB, tcg_gen_gvec_dup_mem, MO_8) 82216fc5726SPaolo BonziniUNARY_INT_GVEC(VPBROADCASTW, tcg_gen_gvec_dup_mem, MO_16) 82316fc5726SPaolo BonziniUNARY_INT_GVEC(VPBROADCASTD, tcg_gen_gvec_dup_mem, MO_32) 82416fc5726SPaolo BonziniUNARY_INT_GVEC(VPBROADCASTQ, tcg_gen_gvec_dup_mem, MO_64) 82516fc5726SPaolo Bonzini 82616fc5726SPaolo Bonzini 82792ec056aSPaolo Bonzini#define BINARY_INT_GVEC(uname, func, ...) \ 8284228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 82992ec056aSPaolo Bonzini{ \ 83092ec056aSPaolo Bonzini int vec_len = vector_len(s, decode); \ 83192ec056aSPaolo Bonzini \ 83292ec056aSPaolo Bonzini func(__VA_ARGS__, \ 83392ec056aSPaolo Bonzini decode->op[0].offset, decode->op[1].offset, \ 83492ec056aSPaolo Bonzini decode->op[2].offset, vec_len, vec_len); \ 83592ec056aSPaolo Bonzini} 83692ec056aSPaolo Bonzini 8371d0efbdbSPaolo BonziniBINARY_INT_GVEC(PADDB, tcg_gen_gvec_add, MO_8) 8381d0efbdbSPaolo BonziniBINARY_INT_GVEC(PADDW, tcg_gen_gvec_add, MO_16) 8391d0efbdbSPaolo BonziniBINARY_INT_GVEC(PADDD, tcg_gen_gvec_add, MO_32) 8406bbeb98dSPaolo BonziniBINARY_INT_GVEC(PADDQ, tcg_gen_gvec_add, MO_64) 8411d0efbdbSPaolo BonziniBINARY_INT_GVEC(PADDSB, tcg_gen_gvec_ssadd, MO_8) 8421d0efbdbSPaolo BonziniBINARY_INT_GVEC(PADDSW, tcg_gen_gvec_ssadd, MO_16) 8431d0efbdbSPaolo BonziniBINARY_INT_GVEC(PADDUSB, tcg_gen_gvec_usadd, MO_8) 8441d0efbdbSPaolo BonziniBINARY_INT_GVEC(PADDUSW, tcg_gen_gvec_usadd, MO_16) 8451d0efbdbSPaolo BonziniBINARY_INT_GVEC(PAND, tcg_gen_gvec_and, MO_64) 846ce4fcb94SPaolo BonziniBINARY_INT_GVEC(PCMPEQB, tcg_gen_gvec_cmp, TCG_COND_EQ, MO_8) 847ce4fcb94SPaolo BonziniBINARY_INT_GVEC(PCMPEQD, tcg_gen_gvec_cmp, TCG_COND_EQ, MO_32) 848ce4fcb94SPaolo BonziniBINARY_INT_GVEC(PCMPEQW, tcg_gen_gvec_cmp, TCG_COND_EQ, MO_16) 84916fc5726SPaolo BonziniBINARY_INT_GVEC(PCMPEQQ, tcg_gen_gvec_cmp, TCG_COND_EQ, MO_64) 85092ec056aSPaolo BonziniBINARY_INT_GVEC(PCMPGTB, tcg_gen_gvec_cmp, TCG_COND_GT, MO_8) 85192ec056aSPaolo BonziniBINARY_INT_GVEC(PCMPGTW, tcg_gen_gvec_cmp, TCG_COND_GT, MO_16) 85292ec056aSPaolo BonziniBINARY_INT_GVEC(PCMPGTD, tcg_gen_gvec_cmp, TCG_COND_GT, MO_32) 85316fc5726SPaolo BonziniBINARY_INT_GVEC(PCMPGTQ, tcg_gen_gvec_cmp, TCG_COND_GT, MO_64) 85416fc5726SPaolo BonziniBINARY_INT_GVEC(PMAXSB, tcg_gen_gvec_smax, MO_8) 8551d0efbdbSPaolo BonziniBINARY_INT_GVEC(PMAXSW, tcg_gen_gvec_smax, MO_16) 85616fc5726SPaolo BonziniBINARY_INT_GVEC(PMAXSD, tcg_gen_gvec_smax, MO_32) 8571d0efbdbSPaolo BonziniBINARY_INT_GVEC(PMAXUB, tcg_gen_gvec_umax, MO_8) 85816fc5726SPaolo BonziniBINARY_INT_GVEC(PMAXUW, tcg_gen_gvec_umax, MO_16) 85916fc5726SPaolo BonziniBINARY_INT_GVEC(PMAXUD, tcg_gen_gvec_umax, MO_32) 86016fc5726SPaolo BonziniBINARY_INT_GVEC(PMINSB, tcg_gen_gvec_smin, MO_8) 8611d0efbdbSPaolo BonziniBINARY_INT_GVEC(PMINSW, tcg_gen_gvec_smin, MO_16) 86216fc5726SPaolo BonziniBINARY_INT_GVEC(PMINSD, tcg_gen_gvec_smin, MO_32) 8631d0efbdbSPaolo BonziniBINARY_INT_GVEC(PMINUB, tcg_gen_gvec_umin, MO_8) 86416fc5726SPaolo BonziniBINARY_INT_GVEC(PMINUW, tcg_gen_gvec_umin, MO_16) 86516fc5726SPaolo BonziniBINARY_INT_GVEC(PMINUD, tcg_gen_gvec_umin, MO_32) 8666bbeb98dSPaolo BonziniBINARY_INT_GVEC(PMULLW, tcg_gen_gvec_mul, MO_16) 86716fc5726SPaolo BonziniBINARY_INT_GVEC(PMULLD, tcg_gen_gvec_mul, MO_32) 8681d0efbdbSPaolo BonziniBINARY_INT_GVEC(POR, tcg_gen_gvec_or, MO_64) 8691d0efbdbSPaolo BonziniBINARY_INT_GVEC(PSUBB, tcg_gen_gvec_sub, MO_8) 8701d0efbdbSPaolo BonziniBINARY_INT_GVEC(PSUBW, tcg_gen_gvec_sub, MO_16) 8711d0efbdbSPaolo BonziniBINARY_INT_GVEC(PSUBD, tcg_gen_gvec_sub, MO_32) 8721d0efbdbSPaolo BonziniBINARY_INT_GVEC(PSUBQ, tcg_gen_gvec_sub, MO_64) 8731d0efbdbSPaolo BonziniBINARY_INT_GVEC(PSUBSB, tcg_gen_gvec_sssub, MO_8) 8741d0efbdbSPaolo BonziniBINARY_INT_GVEC(PSUBSW, tcg_gen_gvec_sssub, MO_16) 8751d0efbdbSPaolo BonziniBINARY_INT_GVEC(PSUBUSB, tcg_gen_gvec_ussub, MO_8) 8761d0efbdbSPaolo BonziniBINARY_INT_GVEC(PSUBUSW, tcg_gen_gvec_ussub, MO_16) 8771d0efbdbSPaolo BonziniBINARY_INT_GVEC(PXOR, tcg_gen_gvec_xor, MO_64) 87892ec056aSPaolo Bonzini 87992ec056aSPaolo Bonzini 88092ec056aSPaolo Bonzini/* 88192ec056aSPaolo Bonzini * 00 = p* Pq, Qq (if mmx not NULL; no VEX) 88292ec056aSPaolo Bonzini * 66 = vp* Vx, Hx, Wx 88392ec056aSPaolo Bonzini * 88492ec056aSPaolo Bonzini * These are really the same encoding, because 1) V is the same as P when VEX.V 88592ec056aSPaolo Bonzini * is not present 2) P and Q are the same as H and W apart from MM/XMM 88692ec056aSPaolo Bonzini */ 8874228eb8cSPaolo Bonzinistatic inline void gen_binary_int_sse(DisasContext *s, X86DecodedInsn *decode, 88892ec056aSPaolo Bonzini SSEFunc_0_eppp mmx, SSEFunc_0_eppp xmm, SSEFunc_0_eppp ymm) 88992ec056aSPaolo Bonzini{ 89092ec056aSPaolo Bonzini assert(!!mmx == !!(decode->e.special == X86_SPECIAL_MMX)); 89192ec056aSPaolo Bonzini 89292ec056aSPaolo Bonzini if (mmx && (s->prefix & PREFIX_VEX) && !(s->prefix & PREFIX_DATA)) { 89392ec056aSPaolo Bonzini /* VEX encoding is not applicable to MMX instructions. */ 89492ec056aSPaolo Bonzini gen_illegal_opcode(s); 89592ec056aSPaolo Bonzini return; 89692ec056aSPaolo Bonzini } 89792ec056aSPaolo Bonzini if (!(s->prefix & PREFIX_DATA)) { 898ad75a51eSRichard Henderson mmx(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 89992ec056aSPaolo Bonzini } else if (!s->vex_l) { 900ad75a51eSRichard Henderson xmm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 90192ec056aSPaolo Bonzini } else { 902ad75a51eSRichard Henderson ymm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 90392ec056aSPaolo Bonzini } 90492ec056aSPaolo Bonzini} 90592ec056aSPaolo Bonzini 90692ec056aSPaolo Bonzini 90792ec056aSPaolo Bonzini#define BINARY_INT_MMX(uname, lname) \ 9084228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 90992ec056aSPaolo Bonzini{ \ 9104228eb8cSPaolo Bonzini gen_binary_int_sse(s, decode, \ 91192ec056aSPaolo Bonzini gen_helper_##lname##_mmx, \ 91292ec056aSPaolo Bonzini gen_helper_##lname##_xmm, \ 91392ec056aSPaolo Bonzini gen_helper_##lname##_ymm); \ 91492ec056aSPaolo Bonzini} 91592ec056aSPaolo BonziniBINARY_INT_MMX(PUNPCKLBW, punpcklbw) 91692ec056aSPaolo BonziniBINARY_INT_MMX(PUNPCKLWD, punpcklwd) 91792ec056aSPaolo BonziniBINARY_INT_MMX(PUNPCKLDQ, punpckldq) 91892ec056aSPaolo BonziniBINARY_INT_MMX(PACKSSWB, packsswb) 91992ec056aSPaolo BonziniBINARY_INT_MMX(PACKUSWB, packuswb) 92092ec056aSPaolo BonziniBINARY_INT_MMX(PUNPCKHBW, punpckhbw) 92192ec056aSPaolo BonziniBINARY_INT_MMX(PUNPCKHWD, punpckhwd) 92292ec056aSPaolo BonziniBINARY_INT_MMX(PUNPCKHDQ, punpckhdq) 92392ec056aSPaolo BonziniBINARY_INT_MMX(PACKSSDW, packssdw) 92492ec056aSPaolo Bonzini 9256bbeb98dSPaolo BonziniBINARY_INT_MMX(PAVGB, pavgb) 9266bbeb98dSPaolo BonziniBINARY_INT_MMX(PAVGW, pavgw) 9276bbeb98dSPaolo BonziniBINARY_INT_MMX(PMADDWD, pmaddwd) 9286bbeb98dSPaolo BonziniBINARY_INT_MMX(PMULHUW, pmulhuw) 9296bbeb98dSPaolo BonziniBINARY_INT_MMX(PMULHW, pmulhw) 9306bbeb98dSPaolo BonziniBINARY_INT_MMX(PMULUDQ, pmuludq) 9316bbeb98dSPaolo BonziniBINARY_INT_MMX(PSADBW, psadbw) 9326bbeb98dSPaolo Bonzini 9336bbeb98dSPaolo BonziniBINARY_INT_MMX(PSLLW_r, psllw) 9346bbeb98dSPaolo BonziniBINARY_INT_MMX(PSLLD_r, pslld) 9356bbeb98dSPaolo BonziniBINARY_INT_MMX(PSLLQ_r, psllq) 9366bbeb98dSPaolo BonziniBINARY_INT_MMX(PSRLW_r, psrlw) 9376bbeb98dSPaolo BonziniBINARY_INT_MMX(PSRLD_r, psrld) 9386bbeb98dSPaolo BonziniBINARY_INT_MMX(PSRLQ_r, psrlq) 9396bbeb98dSPaolo BonziniBINARY_INT_MMX(PSRAW_r, psraw) 9406bbeb98dSPaolo BonziniBINARY_INT_MMX(PSRAD_r, psrad) 9416bbeb98dSPaolo Bonzini 94216fc5726SPaolo BonziniBINARY_INT_MMX(PHADDW, phaddw) 94316fc5726SPaolo BonziniBINARY_INT_MMX(PHADDSW, phaddsw) 94416fc5726SPaolo BonziniBINARY_INT_MMX(PHADDD, phaddd) 94516fc5726SPaolo BonziniBINARY_INT_MMX(PHSUBW, phsubw) 94616fc5726SPaolo BonziniBINARY_INT_MMX(PHSUBSW, phsubsw) 94716fc5726SPaolo BonziniBINARY_INT_MMX(PHSUBD, phsubd) 94816fc5726SPaolo BonziniBINARY_INT_MMX(PMADDUBSW, pmaddubsw) 94916fc5726SPaolo BonziniBINARY_INT_MMX(PSHUFB, pshufb) 95016fc5726SPaolo BonziniBINARY_INT_MMX(PSIGNB, psignb) 95116fc5726SPaolo BonziniBINARY_INT_MMX(PSIGNW, psignw) 95216fc5726SPaolo BonziniBINARY_INT_MMX(PSIGND, psignd) 95316fc5726SPaolo BonziniBINARY_INT_MMX(PMULHRSW, pmulhrsw) 95416fc5726SPaolo Bonzini 95592ec056aSPaolo Bonzini/* Instructions with no MMX equivalent. */ 95692ec056aSPaolo Bonzini#define BINARY_INT_SSE(uname, lname) \ 9574228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 95892ec056aSPaolo Bonzini{ \ 9594228eb8cSPaolo Bonzini gen_binary_int_sse(s, decode, \ 96092ec056aSPaolo Bonzini NULL, \ 96192ec056aSPaolo Bonzini gen_helper_##lname##_xmm, \ 96292ec056aSPaolo Bonzini gen_helper_##lname##_ymm); \ 96392ec056aSPaolo Bonzini} 96492ec056aSPaolo Bonzini 96516fc5726SPaolo Bonzini/* Instructions with no MMX equivalent. */ 96692ec056aSPaolo BonziniBINARY_INT_SSE(PUNPCKLQDQ, punpcklqdq) 96792ec056aSPaolo BonziniBINARY_INT_SSE(PUNPCKHQDQ, punpckhqdq) 96816fc5726SPaolo BonziniBINARY_INT_SSE(VPACKUSDW, packusdw) 96916fc5726SPaolo BonziniBINARY_INT_SSE(VPERMILPS, vpermilps) 97016fc5726SPaolo BonziniBINARY_INT_SSE(VPERMILPD, vpermilpd) 97116fc5726SPaolo BonziniBINARY_INT_SSE(VMASKMOVPS, vpmaskmovd) 97216fc5726SPaolo BonziniBINARY_INT_SSE(VMASKMOVPD, vpmaskmovq) 97316fc5726SPaolo Bonzini 97416fc5726SPaolo BonziniBINARY_INT_SSE(PMULDQ, pmuldq) 97516fc5726SPaolo Bonzini 97616fc5726SPaolo BonziniBINARY_INT_SSE(VAESDEC, aesdec) 97716fc5726SPaolo BonziniBINARY_INT_SSE(VAESDECLAST, aesdeclast) 97816fc5726SPaolo BonziniBINARY_INT_SSE(VAESENC, aesenc) 97916fc5726SPaolo BonziniBINARY_INT_SSE(VAESENCLAST, aesenclast) 98016fc5726SPaolo Bonzini 98116fc5726SPaolo Bonzini#define UNARY_CMP_SSE(uname, lname) \ 9824228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 98316fc5726SPaolo Bonzini{ \ 98416fc5726SPaolo Bonzini if (!s->vex_l) { \ 985ad75a51eSRichard Henderson gen_helper_##lname##_xmm(tcg_env, OP_PTR1, OP_PTR2); \ 98616fc5726SPaolo Bonzini } else { \ 987ad75a51eSRichard Henderson gen_helper_##lname##_ymm(tcg_env, OP_PTR1, OP_PTR2); \ 98816fc5726SPaolo Bonzini } \ 989abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); \ 99016fc5726SPaolo Bonzini} 99116fc5726SPaolo BonziniUNARY_CMP_SSE(VPTEST, ptest) 99216fc5726SPaolo BonziniUNARY_CMP_SSE(VTESTPS, vtestps) 99316fc5726SPaolo BonziniUNARY_CMP_SSE(VTESTPD, vtestpd) 99492ec056aSPaolo Bonzini 9954228eb8cSPaolo Bonzinistatic inline void gen_unary_int_sse(DisasContext *s, X86DecodedInsn *decode, 99603b45880SPaolo Bonzini SSEFunc_0_epp xmm, SSEFunc_0_epp ymm) 99703b45880SPaolo Bonzini{ 99803b45880SPaolo Bonzini if (!s->vex_l) { 999ad75a51eSRichard Henderson xmm(tcg_env, OP_PTR0, OP_PTR2); 100003b45880SPaolo Bonzini } else { 1001ad75a51eSRichard Henderson ymm(tcg_env, OP_PTR0, OP_PTR2); 100203b45880SPaolo Bonzini } 100303b45880SPaolo Bonzini} 100403b45880SPaolo Bonzini 100503b45880SPaolo Bonzini#define UNARY_INT_SSE(uname, lname) \ 10064228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 100703b45880SPaolo Bonzini{ \ 10084228eb8cSPaolo Bonzini gen_unary_int_sse(s, decode, \ 100903b45880SPaolo Bonzini gen_helper_##lname##_xmm, \ 101003b45880SPaolo Bonzini gen_helper_##lname##_ymm); \ 101103b45880SPaolo Bonzini} 101203b45880SPaolo Bonzini 101316fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVSXBW, pmovsxbw) 101416fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVSXBD, pmovsxbd) 101516fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVSXBQ, pmovsxbq) 101616fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVSXWD, pmovsxwd) 101716fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVSXWQ, pmovsxwq) 101816fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVSXDQ, pmovsxdq) 101916fc5726SPaolo Bonzini 102016fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVZXBW, pmovzxbw) 102116fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVZXBD, pmovzxbd) 102216fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVZXBQ, pmovzxbq) 102316fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVZXWD, pmovzxwd) 102416fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVZXWQ, pmovzxwq) 102516fc5726SPaolo BonziniUNARY_INT_SSE(VPMOVZXDQ, pmovzxdq) 102616fc5726SPaolo Bonzini 10277170a17eSPaolo BonziniUNARY_INT_SSE(VMOVSLDUP, pmovsldup) 10287170a17eSPaolo BonziniUNARY_INT_SSE(VMOVSHDUP, pmovshdup) 10297170a17eSPaolo BonziniUNARY_INT_SSE(VMOVDDUP, pmovdldup) 10307170a17eSPaolo Bonzini 10316bbeb98dSPaolo BonziniUNARY_INT_SSE(VCVTDQ2PD, cvtdq2pd) 10326bbeb98dSPaolo BonziniUNARY_INT_SSE(VCVTPD2DQ, cvtpd2dq) 10336bbeb98dSPaolo BonziniUNARY_INT_SSE(VCVTTPD2DQ, cvttpd2dq) 103403b45880SPaolo BonziniUNARY_INT_SSE(VCVTDQ2PS, cvtdq2ps) 103503b45880SPaolo BonziniUNARY_INT_SSE(VCVTPS2DQ, cvtps2dq) 103603b45880SPaolo BonziniUNARY_INT_SSE(VCVTTPS2DQ, cvttps2dq) 1037cf5ec664SPaolo BonziniUNARY_INT_SSE(VCVTPH2PS, cvtph2ps) 103803b45880SPaolo Bonzini 103903b45880SPaolo Bonzini 10404228eb8cSPaolo Bonzinistatic inline void gen_unary_imm_sse(DisasContext *s, X86DecodedInsn *decode, 1041ce4fcb94SPaolo Bonzini SSEFunc_0_ppi xmm, SSEFunc_0_ppi ymm) 1042ce4fcb94SPaolo Bonzini{ 1043ce4fcb94SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 1044ce4fcb94SPaolo Bonzini if (!s->vex_l) { 1045ce4fcb94SPaolo Bonzini xmm(OP_PTR0, OP_PTR1, imm); 1046ce4fcb94SPaolo Bonzini } else { 1047ce4fcb94SPaolo Bonzini ymm(OP_PTR0, OP_PTR1, imm); 1048ce4fcb94SPaolo Bonzini } 1049ce4fcb94SPaolo Bonzini} 1050ce4fcb94SPaolo Bonzini 1051ce4fcb94SPaolo Bonzini#define UNARY_IMM_SSE(uname, lname) \ 10524228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 1053ce4fcb94SPaolo Bonzini{ \ 10544228eb8cSPaolo Bonzini gen_unary_imm_sse(s, decode, \ 1055ce4fcb94SPaolo Bonzini gen_helper_##lname##_xmm, \ 1056ce4fcb94SPaolo Bonzini gen_helper_##lname##_ymm); \ 1057ce4fcb94SPaolo Bonzini} 1058ce4fcb94SPaolo Bonzini 1059ce4fcb94SPaolo BonziniUNARY_IMM_SSE(PSHUFD, pshufd) 1060ce4fcb94SPaolo BonziniUNARY_IMM_SSE(PSHUFHW, pshufhw) 1061ce4fcb94SPaolo BonziniUNARY_IMM_SSE(PSHUFLW, pshuflw) 106279068477SPaolo Bonzini#define gen_helper_vpermq_xmm NULL 106379068477SPaolo BonziniUNARY_IMM_SSE(VPERMQ, vpermq) 106479068477SPaolo BonziniUNARY_IMM_SSE(VPERMILPS_i, vpermilps_imm) 106579068477SPaolo BonziniUNARY_IMM_SSE(VPERMILPD_i, vpermilpd_imm) 106679068477SPaolo Bonzini 10674228eb8cSPaolo Bonzinistatic inline void gen_unary_imm_fp_sse(DisasContext *s, X86DecodedInsn *decode, 106879068477SPaolo Bonzini SSEFunc_0_eppi xmm, SSEFunc_0_eppi ymm) 106979068477SPaolo Bonzini{ 107079068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 107179068477SPaolo Bonzini if (!s->vex_l) { 1072ad75a51eSRichard Henderson xmm(tcg_env, OP_PTR0, OP_PTR1, imm); 107379068477SPaolo Bonzini } else { 1074ad75a51eSRichard Henderson ymm(tcg_env, OP_PTR0, OP_PTR1, imm); 107579068477SPaolo Bonzini } 107679068477SPaolo Bonzini} 107779068477SPaolo Bonzini 107879068477SPaolo Bonzini#define UNARY_IMM_FP_SSE(uname, lname) \ 10794228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 108079068477SPaolo Bonzini{ \ 10814228eb8cSPaolo Bonzini gen_unary_imm_fp_sse(s, decode, \ 108279068477SPaolo Bonzini gen_helper_##lname##_xmm, \ 108379068477SPaolo Bonzini gen_helper_##lname##_ymm); \ 108479068477SPaolo Bonzini} 108579068477SPaolo Bonzini 108679068477SPaolo BonziniUNARY_IMM_FP_SSE(VROUNDPS, roundps) 108779068477SPaolo BonziniUNARY_IMM_FP_SSE(VROUNDPD, roundpd) 1088ce4fcb94SPaolo Bonzini 10894228eb8cSPaolo Bonzinistatic inline void gen_vexw_avx(DisasContext *s, X86DecodedInsn *decode, 109016fc5726SPaolo Bonzini SSEFunc_0_eppp d_xmm, SSEFunc_0_eppp q_xmm, 109116fc5726SPaolo Bonzini SSEFunc_0_eppp d_ymm, SSEFunc_0_eppp q_ymm) 109216fc5726SPaolo Bonzini{ 109316fc5726SPaolo Bonzini SSEFunc_0_eppp d = s->vex_l ? d_ymm : d_xmm; 109416fc5726SPaolo Bonzini SSEFunc_0_eppp q = s->vex_l ? q_ymm : q_xmm; 109516fc5726SPaolo Bonzini SSEFunc_0_eppp fn = s->vex_w ? q : d; 1096ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 109716fc5726SPaolo Bonzini} 109816fc5726SPaolo Bonzini 109916fc5726SPaolo Bonzini/* VEX.W affects whether to operate on 32- or 64-bit elements. */ 110016fc5726SPaolo Bonzini#define VEXW_AVX(uname, lname) \ 11014228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 110216fc5726SPaolo Bonzini{ \ 11034228eb8cSPaolo Bonzini gen_vexw_avx(s, decode, \ 110416fc5726SPaolo Bonzini gen_helper_##lname##d_xmm, gen_helper_##lname##q_xmm, \ 110516fc5726SPaolo Bonzini gen_helper_##lname##d_ymm, gen_helper_##lname##q_ymm); \ 110616fc5726SPaolo Bonzini} 110716fc5726SPaolo BonziniVEXW_AVX(VPSLLV, vpsllv) 110816fc5726SPaolo BonziniVEXW_AVX(VPSRLV, vpsrlv) 110916fc5726SPaolo BonziniVEXW_AVX(VPSRAV, vpsrav) 111016fc5726SPaolo BonziniVEXW_AVX(VPMASKMOV, vpmaskmov) 111116fc5726SPaolo Bonzini 111216fc5726SPaolo Bonzini/* Same as above, but with extra arguments to the helper. */ 11134228eb8cSPaolo Bonzinistatic inline void gen_vsib_avx(DisasContext *s, X86DecodedInsn *decode, 111416fc5726SPaolo Bonzini SSEFunc_0_epppti d_xmm, SSEFunc_0_epppti q_xmm, 111516fc5726SPaolo Bonzini SSEFunc_0_epppti d_ymm, SSEFunc_0_epppti q_ymm) 111616fc5726SPaolo Bonzini{ 111716fc5726SPaolo Bonzini SSEFunc_0_epppti d = s->vex_l ? d_ymm : d_xmm; 111816fc5726SPaolo Bonzini SSEFunc_0_epppti q = s->vex_l ? q_ymm : q_xmm; 111916fc5726SPaolo Bonzini SSEFunc_0_epppti fn = s->vex_w ? q : d; 112016fc5726SPaolo Bonzini TCGv_i32 scale = tcg_constant_i32(decode->mem.scale); 112116fc5726SPaolo Bonzini TCGv_ptr index = tcg_temp_new_ptr(); 112216fc5726SPaolo Bonzini 112316fc5726SPaolo Bonzini /* Pass third input as (index, base, scale) */ 1124ad75a51eSRichard Henderson tcg_gen_addi_ptr(index, tcg_env, ZMM_OFFSET(decode->mem.index)); 1125ad75a51eSRichard Henderson fn(tcg_env, OP_PTR0, OP_PTR1, index, s->A0, scale); 112616fc5726SPaolo Bonzini 112716fc5726SPaolo Bonzini /* 112816fc5726SPaolo Bonzini * There are two output operands, so zero OP1's high 128 bits 112916fc5726SPaolo Bonzini * in the VEX.128 case. 113016fc5726SPaolo Bonzini */ 113116fc5726SPaolo Bonzini if (!s->vex_l) { 113216fc5726SPaolo Bonzini int ymmh_ofs = vector_elem_offset(&decode->op[1], MO_128, 1); 113316fc5726SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, ymmh_ofs, 16, 16, 0); 113416fc5726SPaolo Bonzini } 113516fc5726SPaolo Bonzini} 113616fc5726SPaolo Bonzini#define VSIB_AVX(uname, lname) \ 11374228eb8cSPaolo Bonzinistatic void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \ 113816fc5726SPaolo Bonzini{ \ 11394228eb8cSPaolo Bonzini gen_vsib_avx(s, decode, \ 114016fc5726SPaolo Bonzini gen_helper_##lname##d_xmm, gen_helper_##lname##q_xmm, \ 114116fc5726SPaolo Bonzini gen_helper_##lname##d_ymm, gen_helper_##lname##q_ymm); \ 114216fc5726SPaolo Bonzini} 114316fc5726SPaolo BonziniVSIB_AVX(VPGATHERD, vpgatherd) 114416fc5726SPaolo BonziniVSIB_AVX(VPGATHERQ, vpgatherq) 114516fc5726SPaolo Bonzini 11464228eb8cSPaolo Bonzinistatic void gen_AAA(DisasContext *s, X86DecodedInsn *decode) 1147cc1d28bdSPaolo Bonzini{ 1148cc1d28bdSPaolo Bonzini gen_update_cc_op(s); 1149cc1d28bdSPaolo Bonzini gen_helper_aaa(tcg_env); 1150abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 1151cc1d28bdSPaolo Bonzini} 1152cc1d28bdSPaolo Bonzini 11534228eb8cSPaolo Bonzinistatic void gen_AAD(DisasContext *s, X86DecodedInsn *decode) 1154d7c41a60SPaolo Bonzini{ 1155ec568919SPaolo Bonzini gen_helper_aad(s->T0, s->T0, s->T1); 1156ec568919SPaolo Bonzini prepare_update1_cc(decode, s, CC_OP_LOGICB); 1157d7c41a60SPaolo Bonzini} 1158d7c41a60SPaolo Bonzini 11594228eb8cSPaolo Bonzinistatic void gen_AAM(DisasContext *s, X86DecodedInsn *decode) 1160d7c41a60SPaolo Bonzini{ 1161d7c41a60SPaolo Bonzini if (decode->immediate == 0) { 1162d7c41a60SPaolo Bonzini gen_exception(s, EXCP00_DIVZ); 1163d7c41a60SPaolo Bonzini } else { 1164ec568919SPaolo Bonzini gen_helper_aam(s->T0, s->T0, s->T1); 1165ec568919SPaolo Bonzini prepare_update1_cc(decode, s, CC_OP_LOGICB); 1166d7c41a60SPaolo Bonzini } 1167d7c41a60SPaolo Bonzini} 1168d7c41a60SPaolo Bonzini 11694228eb8cSPaolo Bonzinistatic void gen_AAS(DisasContext *s, X86DecodedInsn *decode) 1170cc1d28bdSPaolo Bonzini{ 1171cc1d28bdSPaolo Bonzini gen_update_cc_op(s); 1172cc1d28bdSPaolo Bonzini gen_helper_aas(tcg_env); 1173abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 1174cc1d28bdSPaolo Bonzini} 1175cc1d28bdSPaolo Bonzini 11764228eb8cSPaolo Bonzinistatic void gen_ADC(DisasContext *s, X86DecodedInsn *decode) 1177cc1d28bdSPaolo Bonzini{ 1178cc1d28bdSPaolo Bonzini MemOp ot = decode->op[1].ot; 1179cc1d28bdSPaolo Bonzini TCGv c_in = tcg_temp_new(); 1180cc1d28bdSPaolo Bonzini 1181cc1d28bdSPaolo Bonzini gen_compute_eflags_c(s, c_in); 1182cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 1183cc1d28bdSPaolo Bonzini tcg_gen_add_tl(s->T0, c_in, s->T1); 1184cc1d28bdSPaolo Bonzini tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T0, 1185cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 1186cc1d28bdSPaolo Bonzini } else { 1187cc1d28bdSPaolo Bonzini tcg_gen_add_tl(s->T0, s->T0, s->T1); 1188cc1d28bdSPaolo Bonzini tcg_gen_add_tl(s->T0, s->T0, c_in); 1189cc1d28bdSPaolo Bonzini } 1190cc1d28bdSPaolo Bonzini prepare_update3_cc(decode, s, CC_OP_ADCB + ot, c_in); 1191cc1d28bdSPaolo Bonzini} 1192cc1d28bdSPaolo Bonzini 1193cc155f19SPaolo Bonzinistatic void gen_ADCOX(DisasContext *s, X86DecodedInsn *decode, int cc_op) 11941d0b9261SPaolo Bonzini{ 1195cc155f19SPaolo Bonzini MemOp ot = decode->op[0].ot; 11961d0b9261SPaolo Bonzini TCGv carry_in = NULL; 1197cc155f19SPaolo Bonzini TCGv *carry_out = (cc_op == CC_OP_ADCX ? &decode->cc_dst : &decode->cc_src2); 11981d0b9261SPaolo Bonzini TCGv zero; 11991d0b9261SPaolo Bonzini 1200cc155f19SPaolo Bonzini decode->cc_op = cc_op; 1201cc155f19SPaolo Bonzini *carry_out = tcg_temp_new(); 1202cc155f19SPaolo Bonzini if (CC_OP_HAS_EFLAGS(s->cc_op)) { 1203cc155f19SPaolo Bonzini decode->cc_src = cpu_cc_src; 1204cc155f19SPaolo Bonzini 1205cc155f19SPaolo Bonzini /* Re-use the carry-out from a previous round? */ 1206cc155f19SPaolo Bonzini if (s->cc_op == cc_op || s->cc_op == CC_OP_ADCOX) { 1207cc155f19SPaolo Bonzini carry_in = (cc_op == CC_OP_ADCX ? cpu_cc_dst : cpu_cc_src2); 12081d0b9261SPaolo Bonzini } 1209cc155f19SPaolo Bonzini 1210cc155f19SPaolo Bonzini /* Preserve the opposite carry from previous rounds? */ 1211cc155f19SPaolo Bonzini if (s->cc_op != cc_op && s->cc_op != CC_OP_EFLAGS) { 1212cc155f19SPaolo Bonzini decode->cc_op = CC_OP_ADCOX; 1213cc155f19SPaolo Bonzini if (carry_out == &decode->cc_dst) { 1214cc155f19SPaolo Bonzini decode->cc_src2 = cpu_cc_src2; 1215cc155f19SPaolo Bonzini } else { 1216cc155f19SPaolo Bonzini decode->cc_dst = cpu_cc_dst; 1217cc155f19SPaolo Bonzini } 1218cc155f19SPaolo Bonzini } 1219cc155f19SPaolo Bonzini } else { 1220cc155f19SPaolo Bonzini decode->cc_src = tcg_temp_new(); 1221cc155f19SPaolo Bonzini gen_mov_eflags(s, decode->cc_src); 1222cc155f19SPaolo Bonzini } 1223cc155f19SPaolo Bonzini 1224cc155f19SPaolo Bonzini if (!carry_in) { 1225cc155f19SPaolo Bonzini /* Get carry_in out of EFLAGS. */ 1226cc155f19SPaolo Bonzini carry_in = tcg_temp_new(); 1227cc155f19SPaolo Bonzini tcg_gen_extract_tl(carry_in, decode->cc_src, 12281d0b9261SPaolo Bonzini ctz32(cc_op == CC_OP_ADCX ? CC_C : CC_O), 1); 12291d0b9261SPaolo Bonzini } 12301d0b9261SPaolo Bonzini 12311d0b9261SPaolo Bonzini switch (ot) { 12321d0b9261SPaolo Bonzini#ifdef TARGET_X86_64 12331d0b9261SPaolo Bonzini case MO_32: 12341d0b9261SPaolo Bonzini /* If TL is 64-bit just do everything in 64-bit arithmetic. */ 12356fbef942SRichard Henderson tcg_gen_ext32u_tl(s->T0, s->T0); 12366fbef942SRichard Henderson tcg_gen_ext32u_tl(s->T1, s->T1); 12371d0b9261SPaolo Bonzini tcg_gen_add_i64(s->T0, s->T0, s->T1); 12381d0b9261SPaolo Bonzini tcg_gen_add_i64(s->T0, s->T0, carry_in); 1239cc155f19SPaolo Bonzini tcg_gen_shri_i64(*carry_out, s->T0, 32); 12401d0b9261SPaolo Bonzini break; 12411d0b9261SPaolo Bonzini#endif 12421d0b9261SPaolo Bonzini default: 12431d0b9261SPaolo Bonzini zero = tcg_constant_tl(0); 1244cc155f19SPaolo Bonzini tcg_gen_add2_tl(s->T0, *carry_out, s->T0, zero, carry_in, zero); 1245cc155f19SPaolo Bonzini tcg_gen_add2_tl(s->T0, *carry_out, s->T0, *carry_out, s->T1, zero); 12461d0b9261SPaolo Bonzini break; 12471d0b9261SPaolo Bonzini } 124860c7dd22SPaolo Bonzini} 12491d0b9261SPaolo Bonzini 12504228eb8cSPaolo Bonzinistatic void gen_ADCX(DisasContext *s, X86DecodedInsn *decode) 12511d0b9261SPaolo Bonzini{ 1252cc155f19SPaolo Bonzini gen_ADCOX(s, decode, CC_OP_ADCX); 12531d0b9261SPaolo Bonzini} 12541d0b9261SPaolo Bonzini 12554228eb8cSPaolo Bonzinistatic void gen_ADD(DisasContext *s, X86DecodedInsn *decode) 1256cc1d28bdSPaolo Bonzini{ 1257cc1d28bdSPaolo Bonzini MemOp ot = decode->op[1].ot; 1258cc1d28bdSPaolo Bonzini 1259cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 1260cc1d28bdSPaolo Bonzini tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T1, 1261cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 1262cc1d28bdSPaolo Bonzini } else { 1263cc1d28bdSPaolo Bonzini tcg_gen_add_tl(s->T0, s->T0, s->T1); 1264cc1d28bdSPaolo Bonzini } 1265cc1d28bdSPaolo Bonzini prepare_update2_cc(decode, s, CC_OP_ADDB + ot); 1266cc1d28bdSPaolo Bonzini} 1267cc1d28bdSPaolo Bonzini 12684228eb8cSPaolo Bonzinistatic void gen_ADOX(DisasContext *s, X86DecodedInsn *decode) 12691d0b9261SPaolo Bonzini{ 1270cc155f19SPaolo Bonzini gen_ADCOX(s, decode, CC_OP_ADOX); 12711d0b9261SPaolo Bonzini} 12721d0b9261SPaolo Bonzini 12734228eb8cSPaolo Bonzinistatic void gen_AND(DisasContext *s, X86DecodedInsn *decode) 1274cc1d28bdSPaolo Bonzini{ 1275cc1d28bdSPaolo Bonzini MemOp ot = decode->op[1].ot; 1276cc1d28bdSPaolo Bonzini 1277cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 1278cc1d28bdSPaolo Bonzini tcg_gen_atomic_and_fetch_tl(s->T0, s->A0, s->T1, 1279cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 1280cc1d28bdSPaolo Bonzini } else { 1281cc1d28bdSPaolo Bonzini tcg_gen_and_tl(s->T0, s->T0, s->T1); 1282cc1d28bdSPaolo Bonzini } 1283cc1d28bdSPaolo Bonzini prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); 1284cc1d28bdSPaolo Bonzini} 1285cc1d28bdSPaolo Bonzini 12864228eb8cSPaolo Bonzinistatic void gen_ANDN(DisasContext *s, X86DecodedInsn *decode) 12871d0b9261SPaolo Bonzini{ 12881d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 12891d0b9261SPaolo Bonzini 12901d0b9261SPaolo Bonzini tcg_gen_andc_tl(s->T0, s->T1, s->T0); 1291e7bbb7cbSPaolo Bonzini prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); 12921d0b9261SPaolo Bonzini} 12931d0b9261SPaolo Bonzini 12944228eb8cSPaolo Bonzinistatic void gen_ARPL(DisasContext *s, X86DecodedInsn *decode) 12955e9e21bcSPaolo Bonzini{ 12965e9e21bcSPaolo Bonzini TCGv zf = tcg_temp_new(); 12975e9e21bcSPaolo Bonzini TCGv flags = tcg_temp_new(); 12985e9e21bcSPaolo Bonzini 12995e9e21bcSPaolo Bonzini gen_mov_eflags(s, flags); 13005e9e21bcSPaolo Bonzini 13015e9e21bcSPaolo Bonzini /* Compute adjusted DST in T1, merging in SRC[RPL]. */ 13025e9e21bcSPaolo Bonzini tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 0, 2); 13035e9e21bcSPaolo Bonzini 13045e9e21bcSPaolo Bonzini /* Z flag set if DST[RPL] < SRC[RPL] */ 13055e9e21bcSPaolo Bonzini tcg_gen_setcond_tl(TCG_COND_LTU, zf, s->T0, s->T1); 13065e9e21bcSPaolo Bonzini tcg_gen_deposit_tl(flags, flags, zf, ctz32(CC_Z), 1); 13075e9e21bcSPaolo Bonzini 13085e9e21bcSPaolo Bonzini /* Place maximum RPL in DST */ 13095e9e21bcSPaolo Bonzini tcg_gen_umax_tl(s->T0, s->T0, s->T1); 13105e9e21bcSPaolo Bonzini 13115e9e21bcSPaolo Bonzini decode->cc_src = flags; 13125e9e21bcSPaolo Bonzini decode->cc_op = CC_OP_EFLAGS; 13135e9e21bcSPaolo Bonzini} 13145e9e21bcSPaolo Bonzini 13154228eb8cSPaolo Bonzinistatic void gen_BEXTR(DisasContext *s, X86DecodedInsn *decode) 13161d0b9261SPaolo Bonzini{ 13171d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 1318b14c0098SRichard Henderson TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31); 1319b14c0098SRichard Henderson TCGv zero = tcg_constant_tl(0); 1320b14c0098SRichard Henderson TCGv mone = tcg_constant_tl(-1); 13211d0b9261SPaolo Bonzini 13221d0b9261SPaolo Bonzini /* 13231d0b9261SPaolo Bonzini * Extract START, and shift the operand. 13241d0b9261SPaolo Bonzini * Shifts larger than operand size get zeros. 13251d0b9261SPaolo Bonzini */ 13261d0b9261SPaolo Bonzini tcg_gen_ext8u_tl(s->A0, s->T1); 13271d0b9261SPaolo Bonzini tcg_gen_shr_tl(s->T0, s->T0, s->A0); 13281d0b9261SPaolo Bonzini 13291d0b9261SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound, s->T0, zero); 13301d0b9261SPaolo Bonzini 13311d0b9261SPaolo Bonzini /* 1332b14c0098SRichard Henderson * Extract the LEN into an inverse mask. Lengths larger than 1333b14c0098SRichard Henderson * operand size get all zeros, length 0 gets all ones. 13341d0b9261SPaolo Bonzini */ 13351d0b9261SPaolo Bonzini tcg_gen_extract_tl(s->A0, s->T1, 8, 8); 1336b14c0098SRichard Henderson tcg_gen_shl_tl(s->T1, mone, s->A0); 1337b14c0098SRichard Henderson tcg_gen_movcond_tl(TCG_COND_LEU, s->T1, s->A0, bound, s->T1, zero); 1338b14c0098SRichard Henderson tcg_gen_andc_tl(s->T0, s->T0, s->T1); 13391d0b9261SPaolo Bonzini 1340e7bbb7cbSPaolo Bonzini prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); 13411d0b9261SPaolo Bonzini} 13421d0b9261SPaolo Bonzini 13434228eb8cSPaolo Bonzinistatic void gen_BLSI(DisasContext *s, X86DecodedInsn *decode) 13441d0b9261SPaolo Bonzini{ 13451d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 13461d0b9261SPaolo Bonzini 1347e628387cSPaolo Bonzini /* input in T1, which is ready for prepare_update2_cc */ 1348e628387cSPaolo Bonzini tcg_gen_neg_tl(s->T0, s->T1); 13491d0b9261SPaolo Bonzini tcg_gen_and_tl(s->T0, s->T0, s->T1); 135083a3a20eSRichard Henderson prepare_update2_cc(decode, s, CC_OP_BLSIB + ot); 13511d0b9261SPaolo Bonzini} 13521d0b9261SPaolo Bonzini 13534228eb8cSPaolo Bonzinistatic void gen_BLSMSK(DisasContext *s, X86DecodedInsn *decode) 13541d0b9261SPaolo Bonzini{ 13551d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 13561d0b9261SPaolo Bonzini 1357e628387cSPaolo Bonzini /* input in T1, which is ready for prepare_update2_cc */ 1358e628387cSPaolo Bonzini tcg_gen_subi_tl(s->T0, s->T1, 1); 13591d0b9261SPaolo Bonzini tcg_gen_xor_tl(s->T0, s->T0, s->T1); 1360e628387cSPaolo Bonzini prepare_update2_cc(decode, s, CC_OP_BMILGB + ot); 13611d0b9261SPaolo Bonzini} 13621d0b9261SPaolo Bonzini 13634228eb8cSPaolo Bonzinistatic void gen_BLSR(DisasContext *s, X86DecodedInsn *decode) 13641d0b9261SPaolo Bonzini{ 13651d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 13661d0b9261SPaolo Bonzini 1367e628387cSPaolo Bonzini /* input in T1, which is ready for prepare_update2_cc */ 1368e628387cSPaolo Bonzini tcg_gen_subi_tl(s->T0, s->T1, 1); 13691d0b9261SPaolo Bonzini tcg_gen_and_tl(s->T0, s->T0, s->T1); 1370e628387cSPaolo Bonzini prepare_update2_cc(decode, s, CC_OP_BMILGB + ot); 13711d0b9261SPaolo Bonzini} 13721d0b9261SPaolo Bonzini 13734228eb8cSPaolo Bonzinistatic void gen_BOUND(DisasContext *s, X86DecodedInsn *decode) 13745e9e21bcSPaolo Bonzini{ 13755e9e21bcSPaolo Bonzini TCGv_i32 op = tcg_temp_new_i32(); 13765e9e21bcSPaolo Bonzini tcg_gen_trunc_tl_i32(op, s->T0); 13775e9e21bcSPaolo Bonzini if (decode->op[1].ot == MO_16) { 13785e9e21bcSPaolo Bonzini gen_helper_boundw(tcg_env, s->A0, op); 13795e9e21bcSPaolo Bonzini } else { 13805e9e21bcSPaolo Bonzini gen_helper_boundl(tcg_env, s->A0, op); 13815e9e21bcSPaolo Bonzini } 13825e9e21bcSPaolo Bonzini} 13835e9e21bcSPaolo Bonzini 138411ffaf8cSPaolo Bonzini/* Non-standard convention - on entry T0 is zero-extended input, T1 is the output. */ 138511ffaf8cSPaolo Bonzinistatic void gen_BSF(DisasContext *s, X86DecodedInsn *decode) 138611ffaf8cSPaolo Bonzini{ 138711ffaf8cSPaolo Bonzini MemOp ot = decode->op[0].ot; 138811ffaf8cSPaolo Bonzini 138911ffaf8cSPaolo Bonzini /* Only the Z bit is defined and it is related to the input. */ 139011ffaf8cSPaolo Bonzini decode->cc_dst = tcg_temp_new(); 139111ffaf8cSPaolo Bonzini decode->cc_op = CC_OP_LOGICB + ot; 139211ffaf8cSPaolo Bonzini tcg_gen_mov_tl(decode->cc_dst, s->T0); 139311ffaf8cSPaolo Bonzini 139411ffaf8cSPaolo Bonzini /* 139511ffaf8cSPaolo Bonzini * The manual says that the output is undefined when the 139611ffaf8cSPaolo Bonzini * input is zero, but real hardware leaves it unchanged, and 139711ffaf8cSPaolo Bonzini * real programs appear to depend on that. Accomplish this 139811ffaf8cSPaolo Bonzini * by passing the output as the value to return upon zero. 139911ffaf8cSPaolo Bonzini */ 140011ffaf8cSPaolo Bonzini tcg_gen_ctz_tl(s->T0, s->T0, s->T1); 140111ffaf8cSPaolo Bonzini} 140211ffaf8cSPaolo Bonzini 140311ffaf8cSPaolo Bonzini/* Non-standard convention - on entry T0 is zero-extended input, T1 is the output. */ 140411ffaf8cSPaolo Bonzinistatic void gen_BSR(DisasContext *s, X86DecodedInsn *decode) 140511ffaf8cSPaolo Bonzini{ 140611ffaf8cSPaolo Bonzini MemOp ot = decode->op[0].ot; 140711ffaf8cSPaolo Bonzini 140811ffaf8cSPaolo Bonzini /* Only the Z bit is defined and it is related to the input. */ 140911ffaf8cSPaolo Bonzini decode->cc_dst = tcg_temp_new(); 141011ffaf8cSPaolo Bonzini decode->cc_op = CC_OP_LOGICB + ot; 141111ffaf8cSPaolo Bonzini tcg_gen_mov_tl(decode->cc_dst, s->T0); 141211ffaf8cSPaolo Bonzini 141311ffaf8cSPaolo Bonzini /* 141411ffaf8cSPaolo Bonzini * The manual says that the output is undefined when the 141511ffaf8cSPaolo Bonzini * input is zero, but real hardware leaves it unchanged, and 141611ffaf8cSPaolo Bonzini * real programs appear to depend on that. Accomplish this 141711ffaf8cSPaolo Bonzini * by passing the output as the value to return upon zero. 141811ffaf8cSPaolo Bonzini * Plus, return the bit index of the first 1 bit. 141911ffaf8cSPaolo Bonzini */ 142011ffaf8cSPaolo Bonzini tcg_gen_xori_tl(s->T1, s->T1, TARGET_LONG_BITS - 1); 142111ffaf8cSPaolo Bonzini tcg_gen_clz_tl(s->T0, s->T0, s->T1); 142211ffaf8cSPaolo Bonzini tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1); 142311ffaf8cSPaolo Bonzini} 142411ffaf8cSPaolo Bonzini 14254228eb8cSPaolo Bonzinistatic void gen_BSWAP(DisasContext *s, X86DecodedInsn *decode) 142637861fa5SPaolo Bonzini{ 142737861fa5SPaolo Bonzini#ifdef TARGET_X86_64 142837861fa5SPaolo Bonzini if (s->dflag == MO_64) { 142937861fa5SPaolo Bonzini tcg_gen_bswap64_i64(s->T0, s->T0); 143037861fa5SPaolo Bonzini return; 143137861fa5SPaolo Bonzini } 143237861fa5SPaolo Bonzini#endif 143337861fa5SPaolo Bonzini tcg_gen_bswap32_tl(s->T0, s->T0, TCG_BSWAP_OZ); 143437861fa5SPaolo Bonzini} 143537861fa5SPaolo Bonzini 143610eae899SPaolo Bonzinistatic TCGv gen_bt_mask(DisasContext *s, X86DecodedInsn *decode) 143710eae899SPaolo Bonzini{ 143810eae899SPaolo Bonzini MemOp ot = decode->op[1].ot; 143910eae899SPaolo Bonzini TCGv mask = tcg_temp_new(); 144010eae899SPaolo Bonzini 144110eae899SPaolo Bonzini tcg_gen_andi_tl(s->T1, s->T1, (8 << ot) - 1); 144210eae899SPaolo Bonzini tcg_gen_shl_tl(mask, tcg_constant_tl(1), s->T1); 144310eae899SPaolo Bonzini return mask; 144410eae899SPaolo Bonzini} 144510eae899SPaolo Bonzini 144610eae899SPaolo Bonzini/* Expects truncated bit index in s->T1, 1 << s->T1 in MASK. */ 144710eae899SPaolo Bonzinistatic void gen_bt_flags(DisasContext *s, X86DecodedInsn *decode, TCGv src, TCGv mask) 144810eae899SPaolo Bonzini{ 144910eae899SPaolo Bonzini TCGv cf; 145010eae899SPaolo Bonzini 145110eae899SPaolo Bonzini /* 145210eae899SPaolo Bonzini * C is the result of the test, Z is unchanged, and the others 145310eae899SPaolo Bonzini * are all undefined. 145410eae899SPaolo Bonzini */ 1455e09447c3SPaolo Bonzini if (s->cc_op == CC_OP_DYNAMIC || CC_OP_HAS_EFLAGS(s->cc_op)) { 145610eae899SPaolo Bonzini /* Generate EFLAGS and replace the C bit. */ 145710eae899SPaolo Bonzini cf = tcg_temp_new(); 145810eae899SPaolo Bonzini tcg_gen_setcond_tl(TCG_COND_TSTNE, cf, src, mask); 145910eae899SPaolo Bonzini prepare_update_cf(decode, s, cf); 1460e09447c3SPaolo Bonzini } else { 146110eae899SPaolo Bonzini /* 146210eae899SPaolo Bonzini * Z was going to be computed from the non-zero status of CC_DST. 146310eae899SPaolo Bonzini * We can get that same Z value (and the new C value) by leaving 146410eae899SPaolo Bonzini * CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the 146510eae899SPaolo Bonzini * same width. 146610eae899SPaolo Bonzini */ 146710eae899SPaolo Bonzini decode->cc_src = tcg_temp_new(); 146810eae899SPaolo Bonzini decode->cc_dst = cpu_cc_dst; 1469f359b2fbSRichard Henderson decode->cc_op = CC_OP_SARB + cc_op_size(s->cc_op); 147010eae899SPaolo Bonzini tcg_gen_shr_tl(decode->cc_src, src, s->T1); 147110eae899SPaolo Bonzini } 147210eae899SPaolo Bonzini} 147310eae899SPaolo Bonzini 147410eae899SPaolo Bonzinistatic void gen_BT(DisasContext *s, X86DecodedInsn *decode) 147510eae899SPaolo Bonzini{ 147610eae899SPaolo Bonzini TCGv mask = gen_bt_mask(s, decode); 147710eae899SPaolo Bonzini 147810eae899SPaolo Bonzini gen_bt_flags(s, decode, s->T0, mask); 147910eae899SPaolo Bonzini} 148010eae899SPaolo Bonzini 148110eae899SPaolo Bonzinistatic void gen_BTC(DisasContext *s, X86DecodedInsn *decode) 148210eae899SPaolo Bonzini{ 148310eae899SPaolo Bonzini MemOp ot = decode->op[0].ot; 148410eae899SPaolo Bonzini TCGv old = tcg_temp_new(); 148510eae899SPaolo Bonzini TCGv mask = gen_bt_mask(s, decode); 148610eae899SPaolo Bonzini 148710eae899SPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 148810eae899SPaolo Bonzini tcg_gen_atomic_fetch_xor_tl(old, s->A0, mask, s->mem_index, ot | MO_LE); 148910eae899SPaolo Bonzini } else { 149010eae899SPaolo Bonzini tcg_gen_mov_tl(old, s->T0); 149110eae899SPaolo Bonzini tcg_gen_xor_tl(s->T0, s->T0, mask); 149210eae899SPaolo Bonzini } 149310eae899SPaolo Bonzini 149410eae899SPaolo Bonzini gen_bt_flags(s, decode, old, mask); 149510eae899SPaolo Bonzini} 149610eae899SPaolo Bonzini 149710eae899SPaolo Bonzinistatic void gen_BTR(DisasContext *s, X86DecodedInsn *decode) 149810eae899SPaolo Bonzini{ 149910eae899SPaolo Bonzini MemOp ot = decode->op[0].ot; 150010eae899SPaolo Bonzini TCGv old = tcg_temp_new(); 150110eae899SPaolo Bonzini TCGv mask = gen_bt_mask(s, decode); 150210eae899SPaolo Bonzini 150310eae899SPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 150410eae899SPaolo Bonzini TCGv maskc = tcg_temp_new(); 150510eae899SPaolo Bonzini tcg_gen_not_tl(maskc, mask); 150610eae899SPaolo Bonzini tcg_gen_atomic_fetch_and_tl(old, s->A0, maskc, s->mem_index, ot | MO_LE); 150710eae899SPaolo Bonzini } else { 150810eae899SPaolo Bonzini tcg_gen_mov_tl(old, s->T0); 150910eae899SPaolo Bonzini tcg_gen_andc_tl(s->T0, s->T0, mask); 151010eae899SPaolo Bonzini } 151110eae899SPaolo Bonzini 151210eae899SPaolo Bonzini gen_bt_flags(s, decode, old, mask); 151310eae899SPaolo Bonzini} 151410eae899SPaolo Bonzini 151510eae899SPaolo Bonzinistatic void gen_BTS(DisasContext *s, X86DecodedInsn *decode) 151610eae899SPaolo Bonzini{ 151710eae899SPaolo Bonzini MemOp ot = decode->op[0].ot; 151810eae899SPaolo Bonzini TCGv old = tcg_temp_new(); 151910eae899SPaolo Bonzini TCGv mask = gen_bt_mask(s, decode); 152010eae899SPaolo Bonzini 152110eae899SPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 152210eae899SPaolo Bonzini tcg_gen_atomic_fetch_or_tl(old, s->A0, mask, s->mem_index, ot | MO_LE); 152310eae899SPaolo Bonzini } else { 152410eae899SPaolo Bonzini tcg_gen_mov_tl(old, s->T0); 152510eae899SPaolo Bonzini tcg_gen_or_tl(s->T0, s->T0, mask); 152610eae899SPaolo Bonzini } 152710eae899SPaolo Bonzini 152810eae899SPaolo Bonzini gen_bt_flags(s, decode, old, mask); 152910eae899SPaolo Bonzini} 153010eae899SPaolo Bonzini 15314228eb8cSPaolo Bonzinistatic void gen_BZHI(DisasContext *s, X86DecodedInsn *decode) 15321d0b9261SPaolo Bonzini{ 15331d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 15349ad2ba6eSRichard Henderson TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31); 15359ad2ba6eSRichard Henderson TCGv zero = tcg_constant_tl(0); 15369ad2ba6eSRichard Henderson TCGv mone = tcg_constant_tl(-1); 15371d0b9261SPaolo Bonzini 15389ad2ba6eSRichard Henderson tcg_gen_ext8u_tl(s->T1, s->T1); 15391d0b9261SPaolo Bonzini 1540e7bbb7cbSPaolo Bonzini tcg_gen_shl_tl(s->A0, mone, s->T1); 1541e7bbb7cbSPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->T1, bound, s->A0, zero); 1542e7bbb7cbSPaolo Bonzini tcg_gen_andc_tl(s->T0, s->T0, s->A0); 15431d0b9261SPaolo Bonzini /* 15441d0b9261SPaolo Bonzini * Note that since we're using BMILG (in order to get O 15451d0b9261SPaolo Bonzini * cleared) we need to store the inverse into C. 15461d0b9261SPaolo Bonzini */ 1547e7bbb7cbSPaolo Bonzini tcg_gen_setcond_tl(TCG_COND_LEU, s->T1, s->T1, bound); 1548e7bbb7cbSPaolo Bonzini prepare_update2_cc(decode, s, CC_OP_BMILGB + ot); 15491d0b9261SPaolo Bonzini} 15501d0b9261SPaolo Bonzini 15514228eb8cSPaolo Bonzinistatic void gen_CALL(DisasContext *s, X86DecodedInsn *decode) 1552d7c41a60SPaolo Bonzini{ 1553d7c41a60SPaolo Bonzini gen_push_v(s, eip_next_tl(s)); 15544228eb8cSPaolo Bonzini gen_JMP(s, decode); 1555d7c41a60SPaolo Bonzini} 1556d7c41a60SPaolo Bonzini 15574228eb8cSPaolo Bonzinistatic void gen_CALL_m(DisasContext *s, X86DecodedInsn *decode) 1558d7c41a60SPaolo Bonzini{ 1559d7c41a60SPaolo Bonzini gen_push_v(s, eip_next_tl(s)); 15604228eb8cSPaolo Bonzini gen_JMP_m(s, decode); 1561d7c41a60SPaolo Bonzini} 1562d7c41a60SPaolo Bonzini 15634228eb8cSPaolo Bonzinistatic void gen_CALLF(DisasContext *s, X86DecodedInsn *decode) 15645e9e21bcSPaolo Bonzini{ 15655e9e21bcSPaolo Bonzini gen_far_call(s); 15665e9e21bcSPaolo Bonzini} 15675e9e21bcSPaolo Bonzini 15684228eb8cSPaolo Bonzinistatic void gen_CALLF_m(DisasContext *s, X86DecodedInsn *decode) 1569d7c41a60SPaolo Bonzini{ 1570c2b6b6a6SPaolo Bonzini MemOp ot = decode->op[1].ot; 1571d7c41a60SPaolo Bonzini 1572d7c41a60SPaolo Bonzini gen_op_ld_v(s, ot, s->T0, s->A0); 1573d7c41a60SPaolo Bonzini gen_add_A0_im(s, 1 << ot); 1574d7c41a60SPaolo Bonzini gen_op_ld_v(s, MO_16, s->T1, s->A0); 1575d7c41a60SPaolo Bonzini gen_far_call(s); 1576d7c41a60SPaolo Bonzini} 1577d7c41a60SPaolo Bonzini 15784228eb8cSPaolo Bonzinistatic void gen_CBW(DisasContext *s, X86DecodedInsn *decode) 15795e9e21bcSPaolo Bonzini{ 15805e9e21bcSPaolo Bonzini MemOp src_ot = decode->op[0].ot - 1; 15815e9e21bcSPaolo Bonzini 15825e9e21bcSPaolo Bonzini tcg_gen_ext_tl(s->T0, s->T0, src_ot | MO_SIGN); 15835e9e21bcSPaolo Bonzini} 15845e9e21bcSPaolo Bonzini 15854228eb8cSPaolo Bonzinistatic void gen_CLC(DisasContext *s, X86DecodedInsn *decode) 1586d7c41a60SPaolo Bonzini{ 1587d7c41a60SPaolo Bonzini gen_compute_eflags(s); 1588d7c41a60SPaolo Bonzini tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C); 1589d7c41a60SPaolo Bonzini} 1590d7c41a60SPaolo Bonzini 15914228eb8cSPaolo Bonzinistatic void gen_CLD(DisasContext *s, X86DecodedInsn *decode) 1592d7c41a60SPaolo Bonzini{ 1593d7c41a60SPaolo Bonzini tcg_gen_st_i32(tcg_constant_i32(1), tcg_env, offsetof(CPUX86State, df)); 1594d7c41a60SPaolo Bonzini} 1595d7c41a60SPaolo Bonzini 15964228eb8cSPaolo Bonzinistatic void gen_CLI(DisasContext *s, X86DecodedInsn *decode) 1597d7c41a60SPaolo Bonzini{ 1598d7c41a60SPaolo Bonzini gen_reset_eflags(s, IF_MASK); 1599d7c41a60SPaolo Bonzini} 1600d7c41a60SPaolo Bonzini 1601ae541c0eSPaolo Bonzinistatic void gen_CLTS(DisasContext *s, X86DecodedInsn *decode) 1602ae541c0eSPaolo Bonzini{ 1603ae541c0eSPaolo Bonzini gen_helper_clts(tcg_env); 1604ae541c0eSPaolo Bonzini /* abort block because static cpu state changed */ 1605ae541c0eSPaolo Bonzini s->base.is_jmp = DISAS_EOB_NEXT; 1606ae541c0eSPaolo Bonzini} 1607ae541c0eSPaolo Bonzini 16084228eb8cSPaolo Bonzinistatic void gen_CMC(DisasContext *s, X86DecodedInsn *decode) 1609d7c41a60SPaolo Bonzini{ 1610d7c41a60SPaolo Bonzini gen_compute_eflags(s); 1611d7c41a60SPaolo Bonzini tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); 1612d7c41a60SPaolo Bonzini} 1613d7c41a60SPaolo Bonzini 16144228eb8cSPaolo Bonzinistatic void gen_CMOVcc(DisasContext *s, X86DecodedInsn *decode) 16152b8046f3SPaolo Bonzini{ 16162b8046f3SPaolo Bonzini gen_cmovcc1(s, decode->b & 0xf, s->T0, s->T1); 16172b8046f3SPaolo Bonzini} 16182b8046f3SPaolo Bonzini 16194228eb8cSPaolo Bonzinistatic void gen_CMPccXADD(DisasContext *s, X86DecodedInsn *decode) 1620405c7c07SPaolo Bonzini{ 1621405c7c07SPaolo Bonzini TCGLabel *label_top = gen_new_label(); 1622405c7c07SPaolo Bonzini TCGLabel *label_bottom = gen_new_label(); 1623405c7c07SPaolo Bonzini TCGv oldv = tcg_temp_new(); 1624405c7c07SPaolo Bonzini TCGv newv = tcg_temp_new(); 1625405c7c07SPaolo Bonzini TCGv cmpv = tcg_temp_new(); 1626405c7c07SPaolo Bonzini TCGCond cond; 1627405c7c07SPaolo Bonzini 1628405c7c07SPaolo Bonzini TCGv cmp_lhs, cmp_rhs; 1629405c7c07SPaolo Bonzini MemOp ot, ot_full; 1630405c7c07SPaolo Bonzini 1631405c7c07SPaolo Bonzini int jcc_op = (decode->b >> 1) & 7; 1632405c7c07SPaolo Bonzini static const TCGCond cond_table[8] = { 1633405c7c07SPaolo Bonzini [JCC_O] = TCG_COND_LT, /* test sign bit by comparing against 0 */ 1634405c7c07SPaolo Bonzini [JCC_B] = TCG_COND_LTU, 1635405c7c07SPaolo Bonzini [JCC_Z] = TCG_COND_EQ, 1636405c7c07SPaolo Bonzini [JCC_BE] = TCG_COND_LEU, 1637405c7c07SPaolo Bonzini [JCC_S] = TCG_COND_LT, /* test sign bit by comparing against 0 */ 163815957eb9SPaolo Bonzini [JCC_P] = TCG_COND_TSTEQ, /* even parity - tests low bit of popcount */ 1639405c7c07SPaolo Bonzini [JCC_L] = TCG_COND_LT, 1640405c7c07SPaolo Bonzini [JCC_LE] = TCG_COND_LE, 1641405c7c07SPaolo Bonzini }; 1642405c7c07SPaolo Bonzini 1643405c7c07SPaolo Bonzini cond = cond_table[jcc_op]; 1644405c7c07SPaolo Bonzini if (decode->b & 1) { 1645405c7c07SPaolo Bonzini cond = tcg_invert_cond(cond); 1646405c7c07SPaolo Bonzini } 1647405c7c07SPaolo Bonzini 1648405c7c07SPaolo Bonzini ot = decode->op[0].ot; 1649405c7c07SPaolo Bonzini ot_full = ot | MO_LE; 1650405c7c07SPaolo Bonzini if (jcc_op >= JCC_S) { 1651405c7c07SPaolo Bonzini /* 1652405c7c07SPaolo Bonzini * Sign-extend values before subtracting for S, P (zero/sign extension 1653405c7c07SPaolo Bonzini * does not matter there) L, LE and their inverses. 1654405c7c07SPaolo Bonzini */ 1655405c7c07SPaolo Bonzini ot_full |= MO_SIGN; 1656405c7c07SPaolo Bonzini } 1657405c7c07SPaolo Bonzini 1658405c7c07SPaolo Bonzini /* 1659405c7c07SPaolo Bonzini * cmpv will be moved to cc_src *after* cpu_regs[] is written back, so use 1660405c7c07SPaolo Bonzini * tcg_gen_ext_tl instead of gen_ext_tl. 1661405c7c07SPaolo Bonzini */ 1662405c7c07SPaolo Bonzini tcg_gen_ext_tl(cmpv, cpu_regs[decode->op[1].n], ot_full); 1663405c7c07SPaolo Bonzini 1664405c7c07SPaolo Bonzini /* 1665405c7c07SPaolo Bonzini * Cmpxchg loop starts here. 1666405c7c07SPaolo Bonzini * - s->T1: addition operand (from decoder) 1667405c7c07SPaolo Bonzini * - s->A0: dest address (from decoder) 1668405c7c07SPaolo Bonzini * - s->cc_srcT: memory operand (lhs for comparison) 1669405c7c07SPaolo Bonzini * - cmpv: rhs for comparison 1670405c7c07SPaolo Bonzini */ 1671405c7c07SPaolo Bonzini gen_set_label(label_top); 1672405c7c07SPaolo Bonzini gen_op_ld_v(s, ot_full, s->cc_srcT, s->A0); 1673405c7c07SPaolo Bonzini tcg_gen_sub_tl(s->T0, s->cc_srcT, cmpv); 1674405c7c07SPaolo Bonzini 1675405c7c07SPaolo Bonzini /* Compute the comparison result by hand, to avoid clobbering cc_*. */ 1676405c7c07SPaolo Bonzini switch (jcc_op) { 1677405c7c07SPaolo Bonzini case JCC_O: 1678405c7c07SPaolo Bonzini /* (src1 ^ src2) & (src1 ^ dst). newv is only used here for a moment */ 1679405c7c07SPaolo Bonzini tcg_gen_xor_tl(newv, s->cc_srcT, s->T0); 1680405c7c07SPaolo Bonzini tcg_gen_xor_tl(s->tmp0, s->cc_srcT, cmpv); 1681405c7c07SPaolo Bonzini tcg_gen_and_tl(s->tmp0, s->tmp0, newv); 1682405c7c07SPaolo Bonzini tcg_gen_sextract_tl(s->tmp0, s->tmp0, 0, 8 << ot); 1683405c7c07SPaolo Bonzini cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(0); 1684405c7c07SPaolo Bonzini break; 1685405c7c07SPaolo Bonzini 1686405c7c07SPaolo Bonzini case JCC_P: 1687405c7c07SPaolo Bonzini tcg_gen_ext8u_tl(s->tmp0, s->T0); 1688405c7c07SPaolo Bonzini tcg_gen_ctpop_tl(s->tmp0, s->tmp0); 168915957eb9SPaolo Bonzini cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(1); 1690405c7c07SPaolo Bonzini break; 1691405c7c07SPaolo Bonzini 1692405c7c07SPaolo Bonzini case JCC_S: 1693405c7c07SPaolo Bonzini tcg_gen_sextract_tl(s->tmp0, s->T0, 0, 8 << ot); 1694405c7c07SPaolo Bonzini cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(0); 1695405c7c07SPaolo Bonzini break; 1696405c7c07SPaolo Bonzini 1697405c7c07SPaolo Bonzini default: 1698405c7c07SPaolo Bonzini cmp_lhs = s->cc_srcT, cmp_rhs = cmpv; 1699405c7c07SPaolo Bonzini break; 1700405c7c07SPaolo Bonzini } 1701405c7c07SPaolo Bonzini 1702405c7c07SPaolo Bonzini /* Compute new value: if condition does not hold, just store back s->cc_srcT */ 1703405c7c07SPaolo Bonzini tcg_gen_add_tl(newv, s->cc_srcT, s->T1); 1704405c7c07SPaolo Bonzini tcg_gen_movcond_tl(cond, newv, cmp_lhs, cmp_rhs, newv, s->cc_srcT); 1705405c7c07SPaolo Bonzini tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, s->cc_srcT, newv, s->mem_index, ot_full); 1706405c7c07SPaolo Bonzini 1707405c7c07SPaolo Bonzini /* Exit unconditionally if cmpxchg succeeded. */ 1708405c7c07SPaolo Bonzini tcg_gen_brcond_tl(TCG_COND_EQ, oldv, s->cc_srcT, label_bottom); 1709405c7c07SPaolo Bonzini 1710405c7c07SPaolo Bonzini /* Try again if there was actually a store to make. */ 1711405c7c07SPaolo Bonzini tcg_gen_brcond_tl(cond, cmp_lhs, cmp_rhs, label_top); 1712405c7c07SPaolo Bonzini gen_set_label(label_bottom); 1713405c7c07SPaolo Bonzini 1714405c7c07SPaolo Bonzini /* Store old value to registers only after a successful store. */ 1715405c7c07SPaolo Bonzini gen_writeback(s, decode, 1, s->cc_srcT); 1716405c7c07SPaolo Bonzini 1717405c7c07SPaolo Bonzini decode->cc_dst = s->T0; 1718405c7c07SPaolo Bonzini decode->cc_src = cmpv; 1719405c7c07SPaolo Bonzini decode->cc_op = CC_OP_SUBB + ot; 1720405c7c07SPaolo Bonzini} 1721405c7c07SPaolo Bonzini 17224228eb8cSPaolo Bonzinistatic void gen_CMPS(DisasContext *s, X86DecodedInsn *decode) 17235e9e21bcSPaolo Bonzini{ 17245e9e21bcSPaolo Bonzini MemOp ot = decode->op[2].ot; 17256605817bSPaolo Bonzini if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { 17266605817bSPaolo Bonzini gen_repz_nz(s, ot, gen_cmps); 17275e9e21bcSPaolo Bonzini } else { 17285e9e21bcSPaolo Bonzini gen_cmps(s, ot); 17295e9e21bcSPaolo Bonzini } 17305e9e21bcSPaolo Bonzini} 17315e9e21bcSPaolo Bonzini 17320c4da548SPaolo Bonzinistatic void gen_CMPXCHG(DisasContext *s, X86DecodedInsn *decode) 17330c4da548SPaolo Bonzini{ 17340c4da548SPaolo Bonzini MemOp ot = decode->op[2].ot; 17350c4da548SPaolo Bonzini TCGv cmpv = tcg_temp_new(); 17360c4da548SPaolo Bonzini TCGv oldv = tcg_temp_new(); 17370c4da548SPaolo Bonzini TCGv newv = tcg_temp_new(); 17380c4da548SPaolo Bonzini TCGv dest; 17390c4da548SPaolo Bonzini 17400c4da548SPaolo Bonzini tcg_gen_ext_tl(cmpv, cpu_regs[R_EAX], ot); 17410c4da548SPaolo Bonzini tcg_gen_ext_tl(newv, s->T1, ot); 17420c4da548SPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 17430c4da548SPaolo Bonzini tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv, 17440c4da548SPaolo Bonzini s->mem_index, ot | MO_LE); 17450c4da548SPaolo Bonzini } else { 17460c4da548SPaolo Bonzini tcg_gen_ext_tl(oldv, s->T0, ot); 17470c4da548SPaolo Bonzini if (decode->op[0].has_ea) { 17480c4da548SPaolo Bonzini /* 17490c4da548SPaolo Bonzini * Perform an unconditional store cycle like physical cpu; 17500c4da548SPaolo Bonzini * must be before changing accumulator to ensure 17510c4da548SPaolo Bonzini * idempotency if the store faults and the instruction 17520c4da548SPaolo Bonzini * is restarted 17530c4da548SPaolo Bonzini */ 17540c4da548SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv); 17550c4da548SPaolo Bonzini gen_op_st_v(s, ot, newv, s->A0); 17560c4da548SPaolo Bonzini } else { 17570c4da548SPaolo Bonzini /* 17580c4da548SPaolo Bonzini * Unlike the memory case, where "the destination operand receives 17590c4da548SPaolo Bonzini * a write cycle without regard to the result of the comparison", 17600c4da548SPaolo Bonzini * rm must not be touched altogether if the write fails, including 17610c4da548SPaolo Bonzini * not zero-extending it on 64-bit processors. So, precompute 17620c4da548SPaolo Bonzini * the result of a successful writeback and perform the movcond 17630c4da548SPaolo Bonzini * directly on cpu_regs. In case rm is part of RAX, note that this 17640c4da548SPaolo Bonzini * movcond and the one below are mutually exclusive is executed. 17650c4da548SPaolo Bonzini */ 17660c4da548SPaolo Bonzini dest = gen_op_deposit_reg_v(s, ot, decode->op[0].n, newv, newv); 17670c4da548SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_EQ, dest, oldv, cmpv, newv, dest); 17680c4da548SPaolo Bonzini } 17690c4da548SPaolo Bonzini decode->op[0].unit = X86_OP_SKIP; 17700c4da548SPaolo Bonzini } 17710c4da548SPaolo Bonzini 17720c4da548SPaolo Bonzini /* Write RAX only if the cmpxchg fails. */ 17730c4da548SPaolo Bonzini dest = gen_op_deposit_reg_v(s, ot, R_EAX, s->T0, oldv); 17740c4da548SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_NE, dest, oldv, cmpv, s->T0, dest); 17750c4da548SPaolo Bonzini 17760c4da548SPaolo Bonzini tcg_gen_mov_tl(s->cc_srcT, cmpv); 17770c4da548SPaolo Bonzini tcg_gen_sub_tl(cmpv, cmpv, oldv); 17780c4da548SPaolo Bonzini decode->cc_dst = cmpv; 17790c4da548SPaolo Bonzini decode->cc_src = oldv; 17800c4da548SPaolo Bonzini decode->cc_op = CC_OP_SUBB + ot; 17810c4da548SPaolo Bonzini} 17820c4da548SPaolo Bonzini 1783fcd16539SPaolo Bonzinistatic void gen_CMPXCHG16B(DisasContext *s, X86DecodedInsn *decode) 1784fcd16539SPaolo Bonzini{ 1785fcd16539SPaolo Bonzini#ifdef TARGET_X86_64 1786fcd16539SPaolo Bonzini MemOp mop = MO_TE | MO_128 | MO_ALIGN; 1787fcd16539SPaolo Bonzini TCGv_i64 t0, t1; 1788fcd16539SPaolo Bonzini TCGv_i128 cmp, val; 1789fcd16539SPaolo Bonzini 1790fcd16539SPaolo Bonzini cmp = tcg_temp_new_i128(); 1791fcd16539SPaolo Bonzini val = tcg_temp_new_i128(); 1792fcd16539SPaolo Bonzini tcg_gen_concat_i64_i128(cmp, cpu_regs[R_EAX], cpu_regs[R_EDX]); 1793fcd16539SPaolo Bonzini tcg_gen_concat_i64_i128(val, cpu_regs[R_EBX], cpu_regs[R_ECX]); 1794fcd16539SPaolo Bonzini 1795fcd16539SPaolo Bonzini /* Only require atomic with LOCK; non-parallel handled in generator. */ 1796fcd16539SPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 1797fcd16539SPaolo Bonzini tcg_gen_atomic_cmpxchg_i128(val, s->A0, cmp, val, s->mem_index, mop); 1798fcd16539SPaolo Bonzini } else { 1799fcd16539SPaolo Bonzini tcg_gen_nonatomic_cmpxchg_i128(val, s->A0, cmp, val, s->mem_index, mop); 1800fcd16539SPaolo Bonzini } 1801fcd16539SPaolo Bonzini 1802fcd16539SPaolo Bonzini tcg_gen_extr_i128_i64(s->T0, s->T1, val); 1803fcd16539SPaolo Bonzini 1804fcd16539SPaolo Bonzini /* Determine success after the fact. */ 1805fcd16539SPaolo Bonzini t0 = tcg_temp_new_i64(); 1806fcd16539SPaolo Bonzini t1 = tcg_temp_new_i64(); 1807fcd16539SPaolo Bonzini tcg_gen_xor_i64(t0, s->T0, cpu_regs[R_EAX]); 1808fcd16539SPaolo Bonzini tcg_gen_xor_i64(t1, s->T1, cpu_regs[R_EDX]); 1809fcd16539SPaolo Bonzini tcg_gen_or_i64(t0, t0, t1); 1810fcd16539SPaolo Bonzini 1811fcd16539SPaolo Bonzini /* Update Z. */ 1812fcd16539SPaolo Bonzini gen_compute_eflags(s); 1813fcd16539SPaolo Bonzini tcg_gen_setcondi_i64(TCG_COND_EQ, t0, t0, 0); 1814fcd16539SPaolo Bonzini tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, t0, ctz32(CC_Z), 1); 1815fcd16539SPaolo Bonzini 1816fcd16539SPaolo Bonzini /* 1817fcd16539SPaolo Bonzini * Extract the result values for the register pair. We may do this 1818fcd16539SPaolo Bonzini * unconditionally, because on success (Z=1), the old value matches 1819fcd16539SPaolo Bonzini * the previous value in RDX:RAX. 1820fcd16539SPaolo Bonzini */ 1821fcd16539SPaolo Bonzini tcg_gen_mov_i64(cpu_regs[R_EAX], s->T0); 1822fcd16539SPaolo Bonzini tcg_gen_mov_i64(cpu_regs[R_EDX], s->T1); 1823fcd16539SPaolo Bonzini#else 1824fcd16539SPaolo Bonzini abort(); 1825fcd16539SPaolo Bonzini#endif 1826fcd16539SPaolo Bonzini} 1827fcd16539SPaolo Bonzini 1828fcd16539SPaolo Bonzinistatic void gen_CMPXCHG8B(DisasContext *s, X86DecodedInsn *decode) 1829fcd16539SPaolo Bonzini{ 1830fcd16539SPaolo Bonzini TCGv_i64 cmp, val, old; 1831fcd16539SPaolo Bonzini TCGv Z; 1832fcd16539SPaolo Bonzini 1833fcd16539SPaolo Bonzini cmp = tcg_temp_new_i64(); 1834fcd16539SPaolo Bonzini val = tcg_temp_new_i64(); 1835fcd16539SPaolo Bonzini old = tcg_temp_new_i64(); 1836fcd16539SPaolo Bonzini 1837fcd16539SPaolo Bonzini /* Construct the comparison values from the register pair. */ 1838fcd16539SPaolo Bonzini tcg_gen_concat_tl_i64(cmp, cpu_regs[R_EAX], cpu_regs[R_EDX]); 1839fcd16539SPaolo Bonzini tcg_gen_concat_tl_i64(val, cpu_regs[R_EBX], cpu_regs[R_ECX]); 1840fcd16539SPaolo Bonzini 1841fcd16539SPaolo Bonzini /* Only require atomic with LOCK; non-parallel handled in generator. */ 1842fcd16539SPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 1843fcd16539SPaolo Bonzini tcg_gen_atomic_cmpxchg_i64(old, s->A0, cmp, val, s->mem_index, MO_TEUQ); 1844fcd16539SPaolo Bonzini } else { 1845fcd16539SPaolo Bonzini tcg_gen_nonatomic_cmpxchg_i64(old, s->A0, cmp, val, 1846fcd16539SPaolo Bonzini s->mem_index, MO_TEUQ); 1847fcd16539SPaolo Bonzini } 1848fcd16539SPaolo Bonzini 1849fcd16539SPaolo Bonzini /* Set tmp0 to match the required value of Z. */ 1850fcd16539SPaolo Bonzini tcg_gen_setcond_i64(TCG_COND_EQ, cmp, old, cmp); 1851fcd16539SPaolo Bonzini Z = tcg_temp_new(); 1852fcd16539SPaolo Bonzini tcg_gen_trunc_i64_tl(Z, cmp); 1853fcd16539SPaolo Bonzini 1854fcd16539SPaolo Bonzini /* 1855fcd16539SPaolo Bonzini * Extract the result values for the register pair. 1856fcd16539SPaolo Bonzini * For 32-bit, we may do this unconditionally, because on success (Z=1), 1857fcd16539SPaolo Bonzini * the old value matches the previous value in EDX:EAX. For x86_64, 1858fcd16539SPaolo Bonzini * the store must be conditional, because we must leave the source 1859fcd16539SPaolo Bonzini * registers unchanged on success, and zero-extend the writeback 1860fcd16539SPaolo Bonzini * on failure (Z=0). 1861fcd16539SPaolo Bonzini */ 1862fcd16539SPaolo Bonzini if (TARGET_LONG_BITS == 32) { 1863fcd16539SPaolo Bonzini tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], old); 1864fcd16539SPaolo Bonzini } else { 1865fcd16539SPaolo Bonzini TCGv zero = tcg_constant_tl(0); 1866fcd16539SPaolo Bonzini 1867fcd16539SPaolo Bonzini tcg_gen_extr_i64_tl(s->T0, s->T1, old); 1868fcd16539SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_EQ, cpu_regs[R_EAX], Z, zero, 1869fcd16539SPaolo Bonzini s->T0, cpu_regs[R_EAX]); 1870fcd16539SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_EQ, cpu_regs[R_EDX], Z, zero, 1871fcd16539SPaolo Bonzini s->T1, cpu_regs[R_EDX]); 1872fcd16539SPaolo Bonzini } 1873fcd16539SPaolo Bonzini 1874fcd16539SPaolo Bonzini /* Update Z. */ 1875fcd16539SPaolo Bonzini gen_compute_eflags(s); 1876fcd16539SPaolo Bonzini tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, Z, ctz32(CC_Z), 1); 1877fcd16539SPaolo Bonzini} 1878fcd16539SPaolo Bonzini 1879ae541c0eSPaolo Bonzinistatic void gen_CPUID(DisasContext *s, X86DecodedInsn *decode) 1880ae541c0eSPaolo Bonzini{ 1881ae541c0eSPaolo Bonzini gen_update_cc_op(s); 1882ae541c0eSPaolo Bonzini gen_update_eip_cur(s); 1883ae541c0eSPaolo Bonzini gen_helper_cpuid(tcg_env); 1884ae541c0eSPaolo Bonzini} 1885ae541c0eSPaolo Bonzini 18864228eb8cSPaolo Bonzinistatic void gen_CRC32(DisasContext *s, X86DecodedInsn *decode) 18871d0b9261SPaolo Bonzini{ 18881d0b9261SPaolo Bonzini MemOp ot = decode->op[2].ot; 18891d0b9261SPaolo Bonzini 18901d0b9261SPaolo Bonzini tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); 18911d0b9261SPaolo Bonzini gen_helper_crc32(s->T0, s->tmp2_i32, s->T1, tcg_constant_i32(8 << ot)); 18921d0b9261SPaolo Bonzini} 18931d0b9261SPaolo Bonzini 18944228eb8cSPaolo Bonzinistatic void gen_CVTPI2Px(DisasContext *s, X86DecodedInsn *decode) 1895f8d19eecSPaolo Bonzini{ 1896ad75a51eSRichard Henderson gen_helper_enter_mmx(tcg_env); 1897f8d19eecSPaolo Bonzini if (s->prefix & PREFIX_DATA) { 1898ad75a51eSRichard Henderson gen_helper_cvtpi2pd(tcg_env, OP_PTR0, OP_PTR2); 1899f8d19eecSPaolo Bonzini } else { 1900ad75a51eSRichard Henderson gen_helper_cvtpi2ps(tcg_env, OP_PTR0, OP_PTR2); 1901f8d19eecSPaolo Bonzini } 1902f8d19eecSPaolo Bonzini} 1903f8d19eecSPaolo Bonzini 19044228eb8cSPaolo Bonzinistatic void gen_CVTPx2PI(DisasContext *s, X86DecodedInsn *decode) 1905f8d19eecSPaolo Bonzini{ 1906ad75a51eSRichard Henderson gen_helper_enter_mmx(tcg_env); 1907f8d19eecSPaolo Bonzini if (s->prefix & PREFIX_DATA) { 1908ad75a51eSRichard Henderson gen_helper_cvtpd2pi(tcg_env, OP_PTR0, OP_PTR2); 1909f8d19eecSPaolo Bonzini } else { 1910ad75a51eSRichard Henderson gen_helper_cvtps2pi(tcg_env, OP_PTR0, OP_PTR2); 1911f8d19eecSPaolo Bonzini } 1912f8d19eecSPaolo Bonzini} 1913f8d19eecSPaolo Bonzini 19144228eb8cSPaolo Bonzinistatic void gen_CVTTPx2PI(DisasContext *s, X86DecodedInsn *decode) 1915f8d19eecSPaolo Bonzini{ 1916ad75a51eSRichard Henderson gen_helper_enter_mmx(tcg_env); 1917f8d19eecSPaolo Bonzini if (s->prefix & PREFIX_DATA) { 1918ad75a51eSRichard Henderson gen_helper_cvttpd2pi(tcg_env, OP_PTR0, OP_PTR2); 1919f8d19eecSPaolo Bonzini } else { 1920ad75a51eSRichard Henderson gen_helper_cvttps2pi(tcg_env, OP_PTR0, OP_PTR2); 1921f8d19eecSPaolo Bonzini } 1922f8d19eecSPaolo Bonzini} 1923f8d19eecSPaolo Bonzini 19244228eb8cSPaolo Bonzinistatic void gen_CWD(DisasContext *s, X86DecodedInsn *decode) 19255e9e21bcSPaolo Bonzini{ 19265e9e21bcSPaolo Bonzini int shift = 8 << decode->op[0].ot; 19275e9e21bcSPaolo Bonzini 19285e9e21bcSPaolo Bonzini tcg_gen_sextract_tl(s->T0, s->T0, shift - 1, 1); 19295e9e21bcSPaolo Bonzini} 19305e9e21bcSPaolo Bonzini 19314228eb8cSPaolo Bonzinistatic void gen_DAA(DisasContext *s, X86DecodedInsn *decode) 1932cc1d28bdSPaolo Bonzini{ 1933cc1d28bdSPaolo Bonzini gen_update_cc_op(s); 1934cc1d28bdSPaolo Bonzini gen_helper_daa(tcg_env); 1935abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 1936cc1d28bdSPaolo Bonzini} 1937cc1d28bdSPaolo Bonzini 19384228eb8cSPaolo Bonzinistatic void gen_DAS(DisasContext *s, X86DecodedInsn *decode) 1939cc1d28bdSPaolo Bonzini{ 1940cc1d28bdSPaolo Bonzini gen_update_cc_op(s); 1941cc1d28bdSPaolo Bonzini gen_helper_das(tcg_env); 1942abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 1943cc1d28bdSPaolo Bonzini} 1944cc1d28bdSPaolo Bonzini 19454228eb8cSPaolo Bonzinistatic void gen_DEC(DisasContext *s, X86DecodedInsn *decode) 1946cc1d28bdSPaolo Bonzini{ 1947cc1d28bdSPaolo Bonzini MemOp ot = decode->op[1].ot; 1948cc1d28bdSPaolo Bonzini 1949cc1d28bdSPaolo Bonzini tcg_gen_movi_tl(s->T1, -1); 1950cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 1951cc1d28bdSPaolo Bonzini tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T1, 1952cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 1953cc1d28bdSPaolo Bonzini } else { 1954cc1d28bdSPaolo Bonzini tcg_gen_add_tl(s->T0, s->T0, s->T1); 1955cc1d28bdSPaolo Bonzini } 1956cc1d28bdSPaolo Bonzini prepare_update_cc_incdec(decode, s, CC_OP_DECB + ot); 1957cc1d28bdSPaolo Bonzini} 1958cc1d28bdSPaolo Bonzini 19594228eb8cSPaolo Bonzinistatic void gen_DIV(DisasContext *s, X86DecodedInsn *decode) 1960d7c41a60SPaolo Bonzini{ 1961c2b6b6a6SPaolo Bonzini MemOp ot = decode->op[1].ot; 1962d7c41a60SPaolo Bonzini 1963d7c41a60SPaolo Bonzini switch(ot) { 1964d7c41a60SPaolo Bonzini case MO_8: 1965c2b6b6a6SPaolo Bonzini gen_helper_divb_AL(tcg_env, s->T0); 1966d7c41a60SPaolo Bonzini break; 1967d7c41a60SPaolo Bonzini case MO_16: 1968c2b6b6a6SPaolo Bonzini gen_helper_divw_AX(tcg_env, s->T0); 1969d7c41a60SPaolo Bonzini break; 1970d7c41a60SPaolo Bonzini default: 1971d7c41a60SPaolo Bonzini case MO_32: 1972c2b6b6a6SPaolo Bonzini gen_helper_divl_EAX(tcg_env, s->T0); 1973d7c41a60SPaolo Bonzini break; 1974d7c41a60SPaolo Bonzini#ifdef TARGET_X86_64 1975d7c41a60SPaolo Bonzini case MO_64: 1976c2b6b6a6SPaolo Bonzini gen_helper_divq_EAX(tcg_env, s->T0); 1977d7c41a60SPaolo Bonzini break; 1978d7c41a60SPaolo Bonzini#endif 1979d7c41a60SPaolo Bonzini } 1980d7c41a60SPaolo Bonzini} 1981d7c41a60SPaolo Bonzini 19824228eb8cSPaolo Bonzinistatic void gen_EMMS(DisasContext *s, X86DecodedInsn *decode) 1983ce4fcb94SPaolo Bonzini{ 1984ad75a51eSRichard Henderson gen_helper_emms(tcg_env); 1985ce4fcb94SPaolo Bonzini} 1986ce4fcb94SPaolo Bonzini 19874228eb8cSPaolo Bonzinistatic void gen_ENTER(DisasContext *s, X86DecodedInsn *decode) 1988d7c41a60SPaolo Bonzini{ 1989d7c41a60SPaolo Bonzini gen_enter(s, decode->op[1].imm, decode->op[2].imm); 1990d7c41a60SPaolo Bonzini} 1991d7c41a60SPaolo Bonzini 19924228eb8cSPaolo Bonzinistatic void gen_EXTRQ_i(DisasContext *s, X86DecodedInsn *decode) 1993d1c1a422SPaolo Bonzini{ 1994d1c1a422SPaolo Bonzini TCGv_i32 length = tcg_constant_i32(decode->immediate & 63); 1995d1c1a422SPaolo Bonzini TCGv_i32 index = tcg_constant_i32((decode->immediate >> 8) & 63); 1996d1c1a422SPaolo Bonzini 1997ad75a51eSRichard Henderson gen_helper_extrq_i(tcg_env, OP_PTR0, index, length); 1998d1c1a422SPaolo Bonzini} 1999d1c1a422SPaolo Bonzini 20004228eb8cSPaolo Bonzinistatic void gen_EXTRQ_r(DisasContext *s, X86DecodedInsn *decode) 2001d1c1a422SPaolo Bonzini{ 2002ad75a51eSRichard Henderson gen_helper_extrq_r(tcg_env, OP_PTR0, OP_PTR2); 2003d1c1a422SPaolo Bonzini} 2004d1c1a422SPaolo Bonzini 2005ea89aa89SPaolo Bonzinistatic void gen_FXRSTOR(DisasContext *s, X86DecodedInsn *decode) 2006ea89aa89SPaolo Bonzini{ 2007ea89aa89SPaolo Bonzini if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) { 2008ea89aa89SPaolo Bonzini gen_NM_exception(s); 2009ae541c0eSPaolo Bonzini } else { 2010ea89aa89SPaolo Bonzini gen_helper_fxrstor(tcg_env, s->A0); 2011ea89aa89SPaolo Bonzini } 2012ae541c0eSPaolo Bonzini} 2013ea89aa89SPaolo Bonzini 2014ea89aa89SPaolo Bonzinistatic void gen_FXSAVE(DisasContext *s, X86DecodedInsn *decode) 2015ea89aa89SPaolo Bonzini{ 2016ea89aa89SPaolo Bonzini if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) { 2017ea89aa89SPaolo Bonzini gen_NM_exception(s); 2018ae541c0eSPaolo Bonzini } else { 2019ea89aa89SPaolo Bonzini gen_helper_fxsave(tcg_env, s->A0); 2020ea89aa89SPaolo Bonzini } 2021ae541c0eSPaolo Bonzini} 2022ea89aa89SPaolo Bonzini 20234228eb8cSPaolo Bonzinistatic void gen_HLT(DisasContext *s, X86DecodedInsn *decode) 2024d7c41a60SPaolo Bonzini{ 2025d7c41a60SPaolo Bonzini#ifdef CONFIG_SYSTEM_ONLY 2026d7c41a60SPaolo Bonzini gen_update_cc_op(s); 202753603256SPaolo Bonzini gen_update_eip_next(s); 202853603256SPaolo Bonzini gen_helper_hlt(tcg_env); 2029d7c41a60SPaolo Bonzini s->base.is_jmp = DISAS_NORETURN; 2030d7c41a60SPaolo Bonzini#endif 2031d7c41a60SPaolo Bonzini} 2032d7c41a60SPaolo Bonzini 20334228eb8cSPaolo Bonzinistatic void gen_IDIV(DisasContext *s, X86DecodedInsn *decode) 2034d7c41a60SPaolo Bonzini{ 2035c2b6b6a6SPaolo Bonzini MemOp ot = decode->op[1].ot; 2036d7c41a60SPaolo Bonzini 2037d7c41a60SPaolo Bonzini switch(ot) { 2038d7c41a60SPaolo Bonzini case MO_8: 2039c2b6b6a6SPaolo Bonzini gen_helper_idivb_AL(tcg_env, s->T0); 2040d7c41a60SPaolo Bonzini break; 2041d7c41a60SPaolo Bonzini case MO_16: 2042c2b6b6a6SPaolo Bonzini gen_helper_idivw_AX(tcg_env, s->T0); 2043d7c41a60SPaolo Bonzini break; 2044d7c41a60SPaolo Bonzini default: 2045d7c41a60SPaolo Bonzini case MO_32: 2046c2b6b6a6SPaolo Bonzini gen_helper_idivl_EAX(tcg_env, s->T0); 2047d7c41a60SPaolo Bonzini break; 2048d7c41a60SPaolo Bonzini#ifdef TARGET_X86_64 2049d7c41a60SPaolo Bonzini case MO_64: 2050c2b6b6a6SPaolo Bonzini gen_helper_idivq_EAX(tcg_env, s->T0); 2051d7c41a60SPaolo Bonzini break; 2052d7c41a60SPaolo Bonzini#endif 2053d7c41a60SPaolo Bonzini } 2054d7c41a60SPaolo Bonzini} 2055d7c41a60SPaolo Bonzini 20564228eb8cSPaolo Bonzinistatic void gen_IMUL3(DisasContext *s, X86DecodedInsn *decode) 20575e9e21bcSPaolo Bonzini{ 20585e9e21bcSPaolo Bonzini MemOp ot = decode->op[0].ot; 20595e9e21bcSPaolo Bonzini TCGv cc_src_rhs; 20605e9e21bcSPaolo Bonzini 20615e9e21bcSPaolo Bonzini switch (ot) { 20625e9e21bcSPaolo Bonzini case MO_16: 20635e9e21bcSPaolo Bonzini /* s->T0 already sign-extended */ 20645e9e21bcSPaolo Bonzini tcg_gen_ext16s_tl(s->T1, s->T1); 20655e9e21bcSPaolo Bonzini tcg_gen_mul_tl(s->T0, s->T0, s->T1); 20665e9e21bcSPaolo Bonzini /* Compare the full result to the extension of the truncated result. */ 20675e9e21bcSPaolo Bonzini tcg_gen_ext16s_tl(s->T1, s->T0); 20685e9e21bcSPaolo Bonzini cc_src_rhs = s->T0; 20695e9e21bcSPaolo Bonzini break; 20705e9e21bcSPaolo Bonzini 20715e9e21bcSPaolo Bonzini case MO_32: 20725e9e21bcSPaolo Bonzini#ifdef TARGET_X86_64 20735e9e21bcSPaolo Bonzini if (TCG_TARGET_REG_BITS == 64) { 20745e9e21bcSPaolo Bonzini /* 20755e9e21bcSPaolo Bonzini * This produces fewer TCG ops, and better code if flags are needed, 20765e9e21bcSPaolo Bonzini * but it requires a 64-bit multiply even if they are not. Use it 20775e9e21bcSPaolo Bonzini * only if the target has 64-bits registers. 20785e9e21bcSPaolo Bonzini * 20795e9e21bcSPaolo Bonzini * s->T0 is already sign-extended. 20805e9e21bcSPaolo Bonzini */ 20815e9e21bcSPaolo Bonzini tcg_gen_ext32s_tl(s->T1, s->T1); 20825e9e21bcSPaolo Bonzini tcg_gen_mul_tl(s->T0, s->T0, s->T1); 20835e9e21bcSPaolo Bonzini /* Compare the full result to the extension of the truncated result. */ 20845e9e21bcSPaolo Bonzini tcg_gen_ext32s_tl(s->T1, s->T0); 20855e9e21bcSPaolo Bonzini cc_src_rhs = s->T0; 20865e9e21bcSPaolo Bonzini } else { 20875e9e21bcSPaolo Bonzini /* Variant that only needs a 32-bit widening multiply. */ 20885e9e21bcSPaolo Bonzini TCGv_i32 hi = tcg_temp_new_i32(); 20895e9e21bcSPaolo Bonzini TCGv_i32 lo = tcg_temp_new_i32(); 20905e9e21bcSPaolo Bonzini tcg_gen_trunc_tl_i32(lo, s->T0); 20915e9e21bcSPaolo Bonzini tcg_gen_trunc_tl_i32(hi, s->T1); 20925e9e21bcSPaolo Bonzini tcg_gen_muls2_i32(lo, hi, lo, hi); 20935e9e21bcSPaolo Bonzini tcg_gen_extu_i32_tl(s->T0, lo); 20945e9e21bcSPaolo Bonzini 20955e9e21bcSPaolo Bonzini cc_src_rhs = tcg_temp_new(); 20965e9e21bcSPaolo Bonzini tcg_gen_extu_i32_tl(cc_src_rhs, hi); 20975e9e21bcSPaolo Bonzini /* Compare the high part to the sign bit of the truncated result */ 20985e9e21bcSPaolo Bonzini tcg_gen_sari_i32(lo, lo, 31); 20995e9e21bcSPaolo Bonzini tcg_gen_extu_i32_tl(s->T1, lo); 21005e9e21bcSPaolo Bonzini } 21015e9e21bcSPaolo Bonzini break; 21025e9e21bcSPaolo Bonzini 21035e9e21bcSPaolo Bonzini case MO_64: 21045e9e21bcSPaolo Bonzini#endif 21055e9e21bcSPaolo Bonzini cc_src_rhs = tcg_temp_new(); 21065e9e21bcSPaolo Bonzini tcg_gen_muls2_tl(s->T0, cc_src_rhs, s->T0, s->T1); 21075e9e21bcSPaolo Bonzini /* Compare the high part to the sign bit of the truncated result */ 21085e9e21bcSPaolo Bonzini tcg_gen_sari_tl(s->T1, s->T0, TARGET_LONG_BITS - 1); 21095e9e21bcSPaolo Bonzini break; 21105e9e21bcSPaolo Bonzini 21115e9e21bcSPaolo Bonzini default: 21125e9e21bcSPaolo Bonzini g_assert_not_reached(); 21135e9e21bcSPaolo Bonzini } 21145e9e21bcSPaolo Bonzini 21155e9e21bcSPaolo Bonzini tcg_gen_sub_tl(s->T1, s->T1, cc_src_rhs); 21165e9e21bcSPaolo Bonzini prepare_update2_cc(decode, s, CC_OP_MULB + ot); 21175e9e21bcSPaolo Bonzini} 21185e9e21bcSPaolo Bonzini 21194228eb8cSPaolo Bonzinistatic void gen_IMUL(DisasContext *s, X86DecodedInsn *decode) 2120d7c41a60SPaolo Bonzini{ 2121d7c41a60SPaolo Bonzini MemOp ot = decode->op[1].ot; 2122d7c41a60SPaolo Bonzini TCGv cc_src_rhs; 2123d7c41a60SPaolo Bonzini 2124d7c41a60SPaolo Bonzini switch (ot) { 2125d7c41a60SPaolo Bonzini case MO_8: 2126d7c41a60SPaolo Bonzini /* s->T0 already sign-extended */ 2127d7c41a60SPaolo Bonzini tcg_gen_ext8s_tl(s->T1, s->T1); 2128d7c41a60SPaolo Bonzini tcg_gen_mul_tl(s->T0, s->T0, s->T1); 2129d7c41a60SPaolo Bonzini gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); 2130d7c41a60SPaolo Bonzini /* Compare the full result to the extension of the truncated result. */ 2131d7c41a60SPaolo Bonzini tcg_gen_ext8s_tl(s->T1, s->T0); 2132d7c41a60SPaolo Bonzini cc_src_rhs = s->T0; 2133d7c41a60SPaolo Bonzini break; 2134d7c41a60SPaolo Bonzini 2135d7c41a60SPaolo Bonzini case MO_16: 2136d7c41a60SPaolo Bonzini /* s->T0 already sign-extended */ 2137d7c41a60SPaolo Bonzini tcg_gen_ext16s_tl(s->T1, s->T1); 2138d7c41a60SPaolo Bonzini tcg_gen_mul_tl(s->T0, s->T0, s->T1); 2139d7c41a60SPaolo Bonzini gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); 2140d7c41a60SPaolo Bonzini tcg_gen_shri_tl(s->T1, s->T0, 16); 2141d7c41a60SPaolo Bonzini gen_op_mov_reg_v(s, MO_16, R_EDX, s->T1); 2142d7c41a60SPaolo Bonzini /* Compare the full result to the extension of the truncated result. */ 2143d7c41a60SPaolo Bonzini tcg_gen_ext16s_tl(s->T1, s->T0); 2144d7c41a60SPaolo Bonzini cc_src_rhs = s->T0; 2145d7c41a60SPaolo Bonzini break; 2146d7c41a60SPaolo Bonzini 2147d7c41a60SPaolo Bonzini case MO_32: 2148d7c41a60SPaolo Bonzini#ifdef TARGET_X86_64 2149d7c41a60SPaolo Bonzini /* s->T0 already sign-extended */ 2150d7c41a60SPaolo Bonzini tcg_gen_ext32s_tl(s->T1, s->T1); 2151d7c41a60SPaolo Bonzini tcg_gen_mul_tl(s->T0, s->T0, s->T1); 2152d7c41a60SPaolo Bonzini tcg_gen_ext32u_tl(cpu_regs[R_EAX], s->T0); 2153d7c41a60SPaolo Bonzini tcg_gen_shri_tl(cpu_regs[R_EDX], s->T0, 32); 2154d7c41a60SPaolo Bonzini /* Compare the full result to the extension of the truncated result. */ 2155d7c41a60SPaolo Bonzini tcg_gen_ext32s_tl(s->T1, s->T0); 2156d7c41a60SPaolo Bonzini cc_src_rhs = s->T0; 2157d7c41a60SPaolo Bonzini break; 2158d7c41a60SPaolo Bonzini 2159d7c41a60SPaolo Bonzini case MO_64: 2160d7c41a60SPaolo Bonzini#endif 2161d7c41a60SPaolo Bonzini tcg_gen_muls2_tl(s->T0, cpu_regs[R_EDX], s->T0, s->T1); 2162d7c41a60SPaolo Bonzini tcg_gen_mov_tl(cpu_regs[R_EAX], s->T0); 2163d7c41a60SPaolo Bonzini 2164d7c41a60SPaolo Bonzini /* Compare the high part to the sign bit of the truncated result */ 2165d7c41a60SPaolo Bonzini tcg_gen_negsetcondi_tl(TCG_COND_LT, s->T1, s->T0, 0); 2166d7c41a60SPaolo Bonzini cc_src_rhs = cpu_regs[R_EDX]; 2167d7c41a60SPaolo Bonzini break; 2168d7c41a60SPaolo Bonzini 2169d7c41a60SPaolo Bonzini default: 2170d7c41a60SPaolo Bonzini g_assert_not_reached(); 2171d7c41a60SPaolo Bonzini } 2172d7c41a60SPaolo Bonzini 2173d7c41a60SPaolo Bonzini tcg_gen_sub_tl(s->T1, s->T1, cc_src_rhs); 2174d7c41a60SPaolo Bonzini prepare_update2_cc(decode, s, CC_OP_MULB + ot); 2175d7c41a60SPaolo Bonzini} 2176d7c41a60SPaolo Bonzini 21774228eb8cSPaolo Bonzinistatic void gen_IN(DisasContext *s, X86DecodedInsn *decode) 2178d7c41a60SPaolo Bonzini{ 2179d7c41a60SPaolo Bonzini MemOp ot = decode->op[0].ot; 2180d7c41a60SPaolo Bonzini TCGv_i32 port = tcg_temp_new_i32(); 2181d7c41a60SPaolo Bonzini 21824e2dc59cSPaolo Bonzini tcg_gen_trunc_tl_i32(port, s->T0); 2183d7c41a60SPaolo Bonzini tcg_gen_ext16u_i32(port, port); 2184d7c41a60SPaolo Bonzini if (!gen_check_io(s, ot, port, SVM_IOIO_TYPE_MASK)) { 2185d7c41a60SPaolo Bonzini return; 2186d7c41a60SPaolo Bonzini } 2187d7c41a60SPaolo Bonzini translator_io_start(&s->base); 2188d7c41a60SPaolo Bonzini gen_helper_in_func(ot, s->T0, port); 2189d7c41a60SPaolo Bonzini gen_writeback(s, decode, 0, s->T0); 2190d7c41a60SPaolo Bonzini gen_bpt_io(s, port, ot); 2191d7c41a60SPaolo Bonzini} 2192d7c41a60SPaolo Bonzini 21934228eb8cSPaolo Bonzinistatic void gen_INC(DisasContext *s, X86DecodedInsn *decode) 2194cc1d28bdSPaolo Bonzini{ 2195cc1d28bdSPaolo Bonzini MemOp ot = decode->op[1].ot; 2196cc1d28bdSPaolo Bonzini 2197cc1d28bdSPaolo Bonzini tcg_gen_movi_tl(s->T1, 1); 2198cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 2199cc1d28bdSPaolo Bonzini tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T1, 2200cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 2201cc1d28bdSPaolo Bonzini } else { 2202cc1d28bdSPaolo Bonzini tcg_gen_add_tl(s->T0, s->T0, s->T1); 2203cc1d28bdSPaolo Bonzini } 2204cc1d28bdSPaolo Bonzini prepare_update_cc_incdec(decode, s, CC_OP_INCB + ot); 2205cc1d28bdSPaolo Bonzini} 2206cc1d28bdSPaolo Bonzini 22074228eb8cSPaolo Bonzinistatic void gen_INS(DisasContext *s, X86DecodedInsn *decode) 22085e9e21bcSPaolo Bonzini{ 22095e9e21bcSPaolo Bonzini MemOp ot = decode->op[1].ot; 22105e9e21bcSPaolo Bonzini TCGv_i32 port = tcg_temp_new_i32(); 22115e9e21bcSPaolo Bonzini 22125e9e21bcSPaolo Bonzini tcg_gen_trunc_tl_i32(port, s->T1); 22135e9e21bcSPaolo Bonzini tcg_gen_ext16u_i32(port, port); 22145e9e21bcSPaolo Bonzini if (!gen_check_io(s, ot, port, 22155e9e21bcSPaolo Bonzini SVM_IOIO_TYPE_MASK | SVM_IOIO_STR_MASK)) { 22165e9e21bcSPaolo Bonzini return; 22175e9e21bcSPaolo Bonzini } 22185e9e21bcSPaolo Bonzini 22195e9e21bcSPaolo Bonzini translator_io_start(&s->base); 22205e9e21bcSPaolo Bonzini if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { 22216605817bSPaolo Bonzini gen_repz(s, ot, gen_ins); 22225e9e21bcSPaolo Bonzini } else { 22235e9e21bcSPaolo Bonzini gen_ins(s, ot); 22245e9e21bcSPaolo Bonzini } 22255e9e21bcSPaolo Bonzini} 22265e9e21bcSPaolo Bonzini 22274228eb8cSPaolo Bonzinistatic void gen_INSERTQ_i(DisasContext *s, X86DecodedInsn *decode) 2228d1c1a422SPaolo Bonzini{ 2229d1c1a422SPaolo Bonzini TCGv_i32 length = tcg_constant_i32(decode->immediate & 63); 2230d1c1a422SPaolo Bonzini TCGv_i32 index = tcg_constant_i32((decode->immediate >> 8) & 63); 2231d1c1a422SPaolo Bonzini 2232ad75a51eSRichard Henderson gen_helper_insertq_i(tcg_env, OP_PTR0, OP_PTR1, index, length); 2233d1c1a422SPaolo Bonzini} 2234d1c1a422SPaolo Bonzini 22354228eb8cSPaolo Bonzinistatic void gen_INSERTQ_r(DisasContext *s, X86DecodedInsn *decode) 2236d1c1a422SPaolo Bonzini{ 2237ad75a51eSRichard Henderson gen_helper_insertq_r(tcg_env, OP_PTR0, OP_PTR2); 2238d1c1a422SPaolo Bonzini} 2239d1c1a422SPaolo Bonzini 22404228eb8cSPaolo Bonzinistatic void gen_INT(DisasContext *s, X86DecodedInsn *decode) 2241d7c41a60SPaolo Bonzini{ 2242d7c41a60SPaolo Bonzini gen_interrupt(s, decode->immediate); 2243d7c41a60SPaolo Bonzini} 2244d7c41a60SPaolo Bonzini 22454228eb8cSPaolo Bonzinistatic void gen_INT1(DisasContext *s, X86DecodedInsn *decode) 2246d7c41a60SPaolo Bonzini{ 224773fb7b3cSPaolo Bonzini gen_update_cc_op(s); 224873fb7b3cSPaolo Bonzini gen_update_eip_next(s); 224973fb7b3cSPaolo Bonzini gen_helper_icebp(tcg_env); 225073fb7b3cSPaolo Bonzini s->base.is_jmp = DISAS_NORETURN; 2251d7c41a60SPaolo Bonzini} 2252d7c41a60SPaolo Bonzini 22534228eb8cSPaolo Bonzinistatic void gen_INT3(DisasContext *s, X86DecodedInsn *decode) 2254d7c41a60SPaolo Bonzini{ 2255d7c41a60SPaolo Bonzini gen_interrupt(s, EXCP03_INT3); 2256d7c41a60SPaolo Bonzini} 2257d7c41a60SPaolo Bonzini 22584228eb8cSPaolo Bonzinistatic void gen_INTO(DisasContext *s, X86DecodedInsn *decode) 2259d7c41a60SPaolo Bonzini{ 2260d7c41a60SPaolo Bonzini gen_update_cc_op(s); 2261d7c41a60SPaolo Bonzini gen_update_eip_cur(s); 2262d7c41a60SPaolo Bonzini gen_helper_into(tcg_env, cur_insn_len_i32(s)); 2263d7c41a60SPaolo Bonzini} 2264d7c41a60SPaolo Bonzini 22654228eb8cSPaolo Bonzinistatic void gen_IRET(DisasContext *s, X86DecodedInsn *decode) 2266d7c41a60SPaolo Bonzini{ 2267d7c41a60SPaolo Bonzini if (!PE(s) || VM86(s)) { 2268d7c41a60SPaolo Bonzini gen_helper_iret_real(tcg_env, tcg_constant_i32(s->dflag - 1)); 2269d7c41a60SPaolo Bonzini } else { 2270d7c41a60SPaolo Bonzini gen_helper_iret_protected(tcg_env, tcg_constant_i32(s->dflag - 1), 2271d7c41a60SPaolo Bonzini eip_next_i32(s)); 2272d7c41a60SPaolo Bonzini } 2273a0625efdSPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 2274d7c41a60SPaolo Bonzini s->base.is_jmp = DISAS_EOB_ONLY; 2275d7c41a60SPaolo Bonzini} 2276d7c41a60SPaolo Bonzini 22774228eb8cSPaolo Bonzinistatic void gen_Jcc(DisasContext *s, X86DecodedInsn *decode) 22785e9e21bcSPaolo Bonzini{ 22795e9e21bcSPaolo Bonzini gen_bnd_jmp(s); 22805e9e21bcSPaolo Bonzini gen_jcc(s, decode->b & 0xf, decode->immediate); 22815e9e21bcSPaolo Bonzini} 22825e9e21bcSPaolo Bonzini 22834228eb8cSPaolo Bonzinistatic void gen_JCXZ(DisasContext *s, X86DecodedInsn *decode) 2284d7c41a60SPaolo Bonzini{ 2285d7c41a60SPaolo Bonzini TCGLabel *taken = gen_new_label(); 2286d7c41a60SPaolo Bonzini 2287d7c41a60SPaolo Bonzini gen_update_cc_op(s); 2288d7c41a60SPaolo Bonzini gen_op_jz_ecx(s, taken); 2289d7c41a60SPaolo Bonzini gen_conditional_jump_labels(s, decode->immediate, NULL, taken); 2290d7c41a60SPaolo Bonzini} 2291d7c41a60SPaolo Bonzini 22924228eb8cSPaolo Bonzinistatic void gen_JMP(DisasContext *s, X86DecodedInsn *decode) 2293d7c41a60SPaolo Bonzini{ 2294d7c41a60SPaolo Bonzini gen_update_cc_op(s); 2295d7c41a60SPaolo Bonzini gen_jmp_rel(s, s->dflag, decode->immediate, 0); 2296d7c41a60SPaolo Bonzini} 2297d7c41a60SPaolo Bonzini 22984228eb8cSPaolo Bonzinistatic void gen_JMP_m(DisasContext *s, X86DecodedInsn *decode) 2299d7c41a60SPaolo Bonzini{ 2300d7c41a60SPaolo Bonzini gen_op_jmp_v(s, s->T0); 2301d7c41a60SPaolo Bonzini gen_bnd_jmp(s); 2302d7c41a60SPaolo Bonzini s->base.is_jmp = DISAS_JUMP; 2303d7c41a60SPaolo Bonzini} 2304d7c41a60SPaolo Bonzini 23054228eb8cSPaolo Bonzinistatic void gen_JMPF(DisasContext *s, X86DecodedInsn *decode) 2306d7c41a60SPaolo Bonzini{ 2307d7c41a60SPaolo Bonzini gen_far_jmp(s); 2308d7c41a60SPaolo Bonzini} 2309d7c41a60SPaolo Bonzini 23104228eb8cSPaolo Bonzinistatic void gen_JMPF_m(DisasContext *s, X86DecodedInsn *decode) 2311d7c41a60SPaolo Bonzini{ 2312c2b6b6a6SPaolo Bonzini MemOp ot = decode->op[1].ot; 2313d7c41a60SPaolo Bonzini 2314d7c41a60SPaolo Bonzini gen_op_ld_v(s, ot, s->T0, s->A0); 2315d7c41a60SPaolo Bonzini gen_add_A0_im(s, 1 << ot); 2316d7c41a60SPaolo Bonzini gen_op_ld_v(s, MO_16, s->T1, s->A0); 2317d7c41a60SPaolo Bonzini gen_far_jmp(s); 2318d7c41a60SPaolo Bonzini} 2319d7c41a60SPaolo Bonzini 23204228eb8cSPaolo Bonzinistatic void gen_LAHF(DisasContext *s, X86DecodedInsn *decode) 23215e9e21bcSPaolo Bonzini{ 23225e9e21bcSPaolo Bonzini if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) { 23235e9e21bcSPaolo Bonzini return gen_illegal_opcode(s); 23245e9e21bcSPaolo Bonzini } 23255e9e21bcSPaolo Bonzini gen_compute_eflags(s); 23265e9e21bcSPaolo Bonzini /* Note: gen_compute_eflags() only gives the condition codes */ 23275e9e21bcSPaolo Bonzini tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02); 23285e9e21bcSPaolo Bonzini tcg_gen_deposit_tl(cpu_regs[R_EAX], cpu_regs[R_EAX], s->T0, 8, 8); 23295e9e21bcSPaolo Bonzini} 23305e9e21bcSPaolo Bonzini 2331ae541c0eSPaolo Bonzinistatic void gen_LAR(DisasContext *s, X86DecodedInsn *decode) 2332ae541c0eSPaolo Bonzini{ 2333ae541c0eSPaolo Bonzini MemOp ot = decode->op[0].ot; 2334ae541c0eSPaolo Bonzini TCGv result = tcg_temp_new(); 2335ae541c0eSPaolo Bonzini TCGv dest; 2336ae541c0eSPaolo Bonzini 2337ae541c0eSPaolo Bonzini gen_compute_eflags(s); 2338ae541c0eSPaolo Bonzini gen_update_cc_op(s); 2339ae541c0eSPaolo Bonzini gen_helper_lar(result, tcg_env, s->T0); 2340ae541c0eSPaolo Bonzini 2341ae541c0eSPaolo Bonzini /* Perform writeback here to skip it if ZF=0. */ 2342ae541c0eSPaolo Bonzini decode->op[0].unit = X86_OP_SKIP; 2343ae541c0eSPaolo Bonzini dest = gen_op_deposit_reg_v(s, ot, decode->op[0].n, result, result); 2344ae541c0eSPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_TSTNE, dest, cpu_cc_src, tcg_constant_tl(CC_Z), 2345ae541c0eSPaolo Bonzini result, dest); 2346ae541c0eSPaolo Bonzini} 2347ae541c0eSPaolo Bonzini 23484228eb8cSPaolo Bonzinistatic void gen_LDMXCSR(DisasContext *s, X86DecodedInsn *decode) 234957f6bba0SPaolo Bonzini{ 2350c2b6b6a6SPaolo Bonzini tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); 2351ad75a51eSRichard Henderson gen_helper_ldmxcsr(tcg_env, s->tmp2_i32); 235257f6bba0SPaolo Bonzini} 235357f6bba0SPaolo Bonzini 23544228eb8cSPaolo Bonzinistatic void gen_lxx_seg(DisasContext *s, X86DecodedInsn *decode, int seg) 2355d7c41a60SPaolo Bonzini{ 2356d7c41a60SPaolo Bonzini MemOp ot = decode->op[0].ot; 2357d7c41a60SPaolo Bonzini 2358d7c41a60SPaolo Bonzini /* Offset already in s->T0. */ 2359d7c41a60SPaolo Bonzini gen_add_A0_im(s, 1 << ot); 2360d7c41a60SPaolo Bonzini gen_op_ld_v(s, MO_16, s->T1, s->A0); 2361d7c41a60SPaolo Bonzini 2362d7c41a60SPaolo Bonzini /* load the segment here to handle exceptions properly */ 2363d7c41a60SPaolo Bonzini gen_movl_seg(s, seg, s->T1); 2364d7c41a60SPaolo Bonzini} 2365d7c41a60SPaolo Bonzini 23664228eb8cSPaolo Bonzinistatic void gen_LDS(DisasContext *s, X86DecodedInsn *decode) 2367d7c41a60SPaolo Bonzini{ 23684228eb8cSPaolo Bonzini gen_lxx_seg(s, decode, R_DS); 2369d7c41a60SPaolo Bonzini} 2370d7c41a60SPaolo Bonzini 23714228eb8cSPaolo Bonzinistatic void gen_LEA(DisasContext *s, X86DecodedInsn *decode) 23725e9e21bcSPaolo Bonzini{ 2373c0df9563SPaolo Bonzini TCGv ea = gen_lea_modrm_1(s, decode->mem, false); 2374c0df9563SPaolo Bonzini gen_lea_v_seg_dest(s, s->aflag, s->T0, ea, -1, -1); 23755e9e21bcSPaolo Bonzini} 23765e9e21bcSPaolo Bonzini 23774228eb8cSPaolo Bonzinistatic void gen_LEAVE(DisasContext *s, X86DecodedInsn *decode) 2378d7c41a60SPaolo Bonzini{ 2379d7c41a60SPaolo Bonzini gen_leave(s); 2380d7c41a60SPaolo Bonzini} 2381d7c41a60SPaolo Bonzini 23824228eb8cSPaolo Bonzinistatic void gen_LES(DisasContext *s, X86DecodedInsn *decode) 2383d7c41a60SPaolo Bonzini{ 23844228eb8cSPaolo Bonzini gen_lxx_seg(s, decode, R_ES); 2385d7c41a60SPaolo Bonzini} 2386d7c41a60SPaolo Bonzini 2387ea89aa89SPaolo Bonzinistatic void gen_LFENCE(DisasContext *s, X86DecodedInsn *decode) 2388ea89aa89SPaolo Bonzini{ 2389ea89aa89SPaolo Bonzini tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC); 2390ea89aa89SPaolo Bonzini} 2391ea89aa89SPaolo Bonzini 23924228eb8cSPaolo Bonzinistatic void gen_LFS(DisasContext *s, X86DecodedInsn *decode) 23933519b813SPaolo Bonzini{ 23944228eb8cSPaolo Bonzini gen_lxx_seg(s, decode, R_FS); 23953519b813SPaolo Bonzini} 23963519b813SPaolo Bonzini 23974228eb8cSPaolo Bonzinistatic void gen_LGS(DisasContext *s, X86DecodedInsn *decode) 23983519b813SPaolo Bonzini{ 23994228eb8cSPaolo Bonzini gen_lxx_seg(s, decode, R_GS); 24003519b813SPaolo Bonzini} 24013519b813SPaolo Bonzini 24024228eb8cSPaolo Bonzinistatic void gen_LODS(DisasContext *s, X86DecodedInsn *decode) 24035e9e21bcSPaolo Bonzini{ 2404c2b6b6a6SPaolo Bonzini MemOp ot = decode->op[1].ot; 24055e9e21bcSPaolo Bonzini if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { 24066605817bSPaolo Bonzini gen_repz(s, ot, gen_lods); 24075e9e21bcSPaolo Bonzini } else { 24085e9e21bcSPaolo Bonzini gen_lods(s, ot); 24095e9e21bcSPaolo Bonzini } 24105e9e21bcSPaolo Bonzini} 24115e9e21bcSPaolo Bonzini 24124228eb8cSPaolo Bonzinistatic void gen_LOOP(DisasContext *s, X86DecodedInsn *decode) 2413d7c41a60SPaolo Bonzini{ 2414d7c41a60SPaolo Bonzini TCGLabel *taken = gen_new_label(); 2415d7c41a60SPaolo Bonzini 2416d7c41a60SPaolo Bonzini gen_update_cc_op(s); 2417d7c41a60SPaolo Bonzini gen_op_add_reg_im(s, s->aflag, R_ECX, -1); 2418d7c41a60SPaolo Bonzini gen_op_jnz_ecx(s, taken); 2419d7c41a60SPaolo Bonzini gen_conditional_jump_labels(s, decode->immediate, NULL, taken); 2420d7c41a60SPaolo Bonzini} 2421d7c41a60SPaolo Bonzini 24224228eb8cSPaolo Bonzinistatic void gen_LOOPE(DisasContext *s, X86DecodedInsn *decode) 2423d7c41a60SPaolo Bonzini{ 2424d7c41a60SPaolo Bonzini TCGLabel *taken = gen_new_label(); 2425d7c41a60SPaolo Bonzini TCGLabel *not_taken = gen_new_label(); 2426d7c41a60SPaolo Bonzini 2427d7c41a60SPaolo Bonzini gen_update_cc_op(s); 2428d7c41a60SPaolo Bonzini gen_op_add_reg_im(s, s->aflag, R_ECX, -1); 2429d7c41a60SPaolo Bonzini gen_op_jz_ecx(s, not_taken); 2430d7c41a60SPaolo Bonzini gen_jcc1(s, (JCC_Z << 1), taken); /* jz taken */ 2431d7c41a60SPaolo Bonzini gen_conditional_jump_labels(s, decode->immediate, not_taken, taken); 2432d7c41a60SPaolo Bonzini} 2433d7c41a60SPaolo Bonzini 24344228eb8cSPaolo Bonzinistatic void gen_LOOPNE(DisasContext *s, X86DecodedInsn *decode) 2435d7c41a60SPaolo Bonzini{ 2436d7c41a60SPaolo Bonzini TCGLabel *taken = gen_new_label(); 2437d7c41a60SPaolo Bonzini TCGLabel *not_taken = gen_new_label(); 2438d7c41a60SPaolo Bonzini 2439d7c41a60SPaolo Bonzini gen_update_cc_op(s); 2440d7c41a60SPaolo Bonzini gen_op_add_reg_im(s, s->aflag, R_ECX, -1); 2441d7c41a60SPaolo Bonzini gen_op_jz_ecx(s, not_taken); 2442d7c41a60SPaolo Bonzini gen_jcc1(s, (JCC_Z << 1) | 1, taken); /* jnz taken */ 2443d7c41a60SPaolo Bonzini gen_conditional_jump_labels(s, decode->immediate, not_taken, taken); 2444d7c41a60SPaolo Bonzini} 2445d7c41a60SPaolo Bonzini 2446ae541c0eSPaolo Bonzinistatic void gen_LSL(DisasContext *s, X86DecodedInsn *decode) 2447ae541c0eSPaolo Bonzini{ 2448ae541c0eSPaolo Bonzini MemOp ot = decode->op[0].ot; 2449ae541c0eSPaolo Bonzini TCGv result = tcg_temp_new(); 2450ae541c0eSPaolo Bonzini TCGv dest; 2451ae541c0eSPaolo Bonzini 2452ae541c0eSPaolo Bonzini gen_compute_eflags(s); 2453ae541c0eSPaolo Bonzini gen_update_cc_op(s); 2454ae541c0eSPaolo Bonzini gen_helper_lsl(result, tcg_env, s->T0); 2455ae541c0eSPaolo Bonzini 2456ae541c0eSPaolo Bonzini /* Perform writeback here to skip it if ZF=0. */ 2457ae541c0eSPaolo Bonzini decode->op[0].unit = X86_OP_SKIP; 2458ae541c0eSPaolo Bonzini dest = gen_op_deposit_reg_v(s, ot, decode->op[0].n, result, result); 2459ae541c0eSPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_TSTNE, dest, cpu_cc_src, tcg_constant_tl(CC_Z), 2460ae541c0eSPaolo Bonzini result, dest); 2461ae541c0eSPaolo Bonzini} 2462ae541c0eSPaolo Bonzini 24634228eb8cSPaolo Bonzinistatic void gen_LSS(DisasContext *s, X86DecodedInsn *decode) 24643519b813SPaolo Bonzini{ 24654228eb8cSPaolo Bonzini gen_lxx_seg(s, decode, R_SS); 24663519b813SPaolo Bonzini} 24673519b813SPaolo Bonzini 246811ffaf8cSPaolo Bonzinistatic void gen_LZCNT(DisasContext *s, X86DecodedInsn *decode) 246911ffaf8cSPaolo Bonzini{ 247011ffaf8cSPaolo Bonzini MemOp ot = decode->op[0].ot; 247111ffaf8cSPaolo Bonzini 247211ffaf8cSPaolo Bonzini /* C bit (cc_src) is defined related to the input. */ 247311ffaf8cSPaolo Bonzini decode->cc_src = tcg_temp_new(); 247411ffaf8cSPaolo Bonzini decode->cc_dst = s->T0; 247511ffaf8cSPaolo Bonzini decode->cc_op = CC_OP_BMILGB + ot; 247611ffaf8cSPaolo Bonzini tcg_gen_mov_tl(decode->cc_src, s->T0); 247711ffaf8cSPaolo Bonzini 247811ffaf8cSPaolo Bonzini /* 247911ffaf8cSPaolo Bonzini * Reduce the target_ulong result by the number of zeros that 248011ffaf8cSPaolo Bonzini * we expect to find at the top. 248111ffaf8cSPaolo Bonzini */ 248211ffaf8cSPaolo Bonzini tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS); 248311ffaf8cSPaolo Bonzini tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - (8 << ot)); 248411ffaf8cSPaolo Bonzini} 248511ffaf8cSPaolo Bonzini 2486ea89aa89SPaolo Bonzinistatic void gen_MFENCE(DisasContext *s, X86DecodedInsn *decode) 2487ea89aa89SPaolo Bonzini{ 2488ea89aa89SPaolo Bonzini tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); 2489ea89aa89SPaolo Bonzini} 2490ea89aa89SPaolo Bonzini 24914228eb8cSPaolo Bonzinistatic void gen_MOV(DisasContext *s, X86DecodedInsn *decode) 24925e9e21bcSPaolo Bonzini{ 24935e9e21bcSPaolo Bonzini /* nothing to do! */ 24945e9e21bcSPaolo Bonzini} 24955e9e21bcSPaolo Bonzini#define gen_NOP gen_MOV 24965e9e21bcSPaolo Bonzini 24974228eb8cSPaolo Bonzinistatic void gen_MASKMOV(DisasContext *s, X86DecodedInsn *decode) 24986bbeb98dSPaolo Bonzini{ 249956da568fSPaolo Bonzini gen_lea_v_seg(s, cpu_regs[R_EDI], R_DS, s->override); 25006bbeb98dSPaolo Bonzini 25016bbeb98dSPaolo Bonzini if (s->prefix & PREFIX_DATA) { 2502ad75a51eSRichard Henderson gen_helper_maskmov_xmm(tcg_env, OP_PTR1, OP_PTR2, s->A0); 25036bbeb98dSPaolo Bonzini } else { 2504ad75a51eSRichard Henderson gen_helper_maskmov_mmx(tcg_env, OP_PTR1, OP_PTR2, s->A0); 25056bbeb98dSPaolo Bonzini } 25066bbeb98dSPaolo Bonzini} 25076bbeb98dSPaolo Bonzini 25084228eb8cSPaolo Bonzinistatic void gen_MOVBE(DisasContext *s, X86DecodedInsn *decode) 25091d0b9261SPaolo Bonzini{ 25101d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 25111d0b9261SPaolo Bonzini 25121d0b9261SPaolo Bonzini /* M operand type does not load/store */ 25131d0b9261SPaolo Bonzini if (decode->e.op0 == X86_TYPE_M) { 25141d0b9261SPaolo Bonzini tcg_gen_qemu_st_tl(s->T0, s->A0, s->mem_index, ot | MO_BE); 25151d0b9261SPaolo Bonzini } else { 25161d0b9261SPaolo Bonzini tcg_gen_qemu_ld_tl(s->T0, s->A0, s->mem_index, ot | MO_BE); 25171d0b9261SPaolo Bonzini } 25181d0b9261SPaolo Bonzini} 25191d0b9261SPaolo Bonzini 25204228eb8cSPaolo Bonzinistatic void gen_MOVD_from(DisasContext *s, X86DecodedInsn *decode) 2521d1c1a422SPaolo Bonzini{ 2522d1c1a422SPaolo Bonzini MemOp ot = decode->op[2].ot; 2523d1c1a422SPaolo Bonzini 2524d1c1a422SPaolo Bonzini switch (ot) { 2525d1c1a422SPaolo Bonzini case MO_32: 2526d1c1a422SPaolo Bonzini#ifdef TARGET_X86_64 2527ad75a51eSRichard Henderson tcg_gen_ld32u_tl(s->T0, tcg_env, decode->op[2].offset); 2528d1c1a422SPaolo Bonzini break; 2529d1c1a422SPaolo Bonzini case MO_64: 2530d1c1a422SPaolo Bonzini#endif 2531ad75a51eSRichard Henderson tcg_gen_ld_tl(s->T0, tcg_env, decode->op[2].offset); 2532d1c1a422SPaolo Bonzini break; 2533d1c1a422SPaolo Bonzini default: 2534d1c1a422SPaolo Bonzini abort(); 2535d1c1a422SPaolo Bonzini } 2536d1c1a422SPaolo Bonzini} 2537d1c1a422SPaolo Bonzini 25384228eb8cSPaolo Bonzinistatic void gen_MOVD_to(DisasContext *s, X86DecodedInsn *decode) 253992ec056aSPaolo Bonzini{ 254092ec056aSPaolo Bonzini MemOp ot = decode->op[2].ot; 254192ec056aSPaolo Bonzini int vec_len = vector_len(s, decode); 254292ec056aSPaolo Bonzini int lo_ofs = vector_elem_offset(&decode->op[0], ot, 0); 254392ec056aSPaolo Bonzini 254492ec056aSPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 254592ec056aSPaolo Bonzini 254692ec056aSPaolo Bonzini switch (ot) { 254792ec056aSPaolo Bonzini case MO_32: 254892ec056aSPaolo Bonzini#ifdef TARGET_X86_64 2549ad75a51eSRichard Henderson tcg_gen_st32_tl(s->T1, tcg_env, lo_ofs); 255092ec056aSPaolo Bonzini break; 255192ec056aSPaolo Bonzini case MO_64: 255292ec056aSPaolo Bonzini#endif 2553ad75a51eSRichard Henderson tcg_gen_st_tl(s->T1, tcg_env, lo_ofs); 255492ec056aSPaolo Bonzini break; 255592ec056aSPaolo Bonzini default: 255692ec056aSPaolo Bonzini g_assert_not_reached(); 255792ec056aSPaolo Bonzini } 255892ec056aSPaolo Bonzini} 255992ec056aSPaolo Bonzini 25604228eb8cSPaolo Bonzinistatic void gen_MOVDQ(DisasContext *s, X86DecodedInsn *decode) 256192ec056aSPaolo Bonzini{ 256292ec056aSPaolo Bonzini gen_store_sse(s, decode, decode->op[2].offset); 256392ec056aSPaolo Bonzini} 256492ec056aSPaolo Bonzini 25654228eb8cSPaolo Bonzinistatic void gen_MOVMSK(DisasContext *s, X86DecodedInsn *decode) 256603b45880SPaolo Bonzini{ 256703b45880SPaolo Bonzini typeof(gen_helper_movmskps_ymm) *ps, *pd, *fn; 256803b45880SPaolo Bonzini ps = s->vex_l ? gen_helper_movmskps_ymm : gen_helper_movmskps_xmm; 256903b45880SPaolo Bonzini pd = s->vex_l ? gen_helper_movmskpd_ymm : gen_helper_movmskpd_xmm; 257003b45880SPaolo Bonzini fn = s->prefix & PREFIX_DATA ? pd : ps; 2571ad75a51eSRichard Henderson fn(s->tmp2_i32, tcg_env, OP_PTR2); 257203b45880SPaolo Bonzini tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); 257303b45880SPaolo Bonzini} 257403b45880SPaolo Bonzini 25754228eb8cSPaolo Bonzinistatic void gen_MOVQ(DisasContext *s, X86DecodedInsn *decode) 2576d1c1a422SPaolo Bonzini{ 2577d1c1a422SPaolo Bonzini int vec_len = vector_len(s, decode); 2578d1c1a422SPaolo Bonzini int lo_ofs = vector_elem_offset(&decode->op[0], MO_64, 0); 2579d1c1a422SPaolo Bonzini 2580ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[2].offset); 25816bbeb98dSPaolo Bonzini if (decode->op[0].has_ea) { 25826bbeb98dSPaolo Bonzini tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ); 25836bbeb98dSPaolo Bonzini } else { 2584d1c1a422SPaolo Bonzini /* 2585d1c1a422SPaolo Bonzini * tcg_gen_gvec_dup_i64(MO_64, op0.offset, 8, vec_len, s->tmp1_64) would 2586d1c1a422SPaolo Bonzini * seem to work, but it does not on big-endian platforms; the cleared parts 2587d1c1a422SPaolo Bonzini * are always at higher addresses, but cross-endian emulation inverts the 2588d1c1a422SPaolo Bonzini * byte order so that the cleared parts need to be at *lower* addresses. 2589d1c1a422SPaolo Bonzini * Because oprsz is 8, we see this here even for SSE; but more in general, 2590d1c1a422SPaolo Bonzini * it disqualifies using oprsz < maxsz to emulate VEX128. 2591d1c1a422SPaolo Bonzini */ 2592d1c1a422SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 2593ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, lo_ofs); 2594d1c1a422SPaolo Bonzini } 25956bbeb98dSPaolo Bonzini} 25966bbeb98dSPaolo Bonzini 25974228eb8cSPaolo Bonzinistatic void gen_MOVq_dq(DisasContext *s, X86DecodedInsn *decode) 25986bbeb98dSPaolo Bonzini{ 2599ad75a51eSRichard Henderson gen_helper_enter_mmx(tcg_env); 26006bbeb98dSPaolo Bonzini /* Otherwise the same as any other movq. */ 26014228eb8cSPaolo Bonzini return gen_MOVQ(s, decode); 26026bbeb98dSPaolo Bonzini} 2603d1c1a422SPaolo Bonzini 26044228eb8cSPaolo Bonzinistatic void gen_MOVS(DisasContext *s, X86DecodedInsn *decode) 26055e9e21bcSPaolo Bonzini{ 26065e9e21bcSPaolo Bonzini MemOp ot = decode->op[2].ot; 26075e9e21bcSPaolo Bonzini if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { 26086605817bSPaolo Bonzini gen_repz(s, ot, gen_movs); 26095e9e21bcSPaolo Bonzini } else { 26105e9e21bcSPaolo Bonzini gen_movs(s, ot); 26115e9e21bcSPaolo Bonzini } 26125e9e21bcSPaolo Bonzini} 26135e9e21bcSPaolo Bonzini 26144228eb8cSPaolo Bonzinistatic void gen_MUL(DisasContext *s, X86DecodedInsn *decode) 2615d7c41a60SPaolo Bonzini{ 2616d7c41a60SPaolo Bonzini MemOp ot = decode->op[1].ot; 2617d7c41a60SPaolo Bonzini 2618d7c41a60SPaolo Bonzini switch (ot) { 2619d7c41a60SPaolo Bonzini case MO_8: 2620d7c41a60SPaolo Bonzini /* s->T0 already zero-extended */ 2621d7c41a60SPaolo Bonzini tcg_gen_ext8u_tl(s->T1, s->T1); 2622d7c41a60SPaolo Bonzini tcg_gen_mul_tl(s->T0, s->T0, s->T1); 2623d7c41a60SPaolo Bonzini gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); 2624d7c41a60SPaolo Bonzini tcg_gen_andi_tl(s->T1, s->T0, 0xff00); 2625d7c41a60SPaolo Bonzini decode->cc_dst = s->T0; 2626d7c41a60SPaolo Bonzini decode->cc_src = s->T1; 2627d7c41a60SPaolo Bonzini break; 2628d7c41a60SPaolo Bonzini 2629d7c41a60SPaolo Bonzini case MO_16: 2630d7c41a60SPaolo Bonzini /* s->T0 already zero-extended */ 2631d7c41a60SPaolo Bonzini tcg_gen_ext16u_tl(s->T1, s->T1); 2632d7c41a60SPaolo Bonzini tcg_gen_mul_tl(s->T0, s->T0, s->T1); 2633d7c41a60SPaolo Bonzini gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); 2634d7c41a60SPaolo Bonzini tcg_gen_shri_tl(s->T1, s->T0, 16); 2635d7c41a60SPaolo Bonzini gen_op_mov_reg_v(s, MO_16, R_EDX, s->T1); 2636d7c41a60SPaolo Bonzini decode->cc_dst = s->T0; 2637d7c41a60SPaolo Bonzini decode->cc_src = s->T1; 2638d7c41a60SPaolo Bonzini break; 2639d7c41a60SPaolo Bonzini 2640d7c41a60SPaolo Bonzini case MO_32: 2641d7c41a60SPaolo Bonzini#ifdef TARGET_X86_64 2642d7c41a60SPaolo Bonzini /* s->T0 already zero-extended */ 2643d7c41a60SPaolo Bonzini tcg_gen_ext32u_tl(s->T1, s->T1); 2644d7c41a60SPaolo Bonzini tcg_gen_mul_tl(s->T0, s->T0, s->T1); 2645d7c41a60SPaolo Bonzini tcg_gen_ext32u_tl(cpu_regs[R_EAX], s->T0); 2646d7c41a60SPaolo Bonzini tcg_gen_shri_tl(cpu_regs[R_EDX], s->T0, 32); 2647d7c41a60SPaolo Bonzini decode->cc_dst = cpu_regs[R_EAX]; 2648d7c41a60SPaolo Bonzini decode->cc_src = cpu_regs[R_EDX]; 2649d7c41a60SPaolo Bonzini break; 2650d7c41a60SPaolo Bonzini 2651d7c41a60SPaolo Bonzini case MO_64: 2652d7c41a60SPaolo Bonzini#endif 2653d7c41a60SPaolo Bonzini tcg_gen_mulu2_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->T0, s->T1); 2654d7c41a60SPaolo Bonzini decode->cc_dst = cpu_regs[R_EAX]; 2655d7c41a60SPaolo Bonzini decode->cc_src = cpu_regs[R_EDX]; 2656d7c41a60SPaolo Bonzini break; 2657d7c41a60SPaolo Bonzini 2658d7c41a60SPaolo Bonzini default: 2659d7c41a60SPaolo Bonzini g_assert_not_reached(); 2660d7c41a60SPaolo Bonzini } 2661d7c41a60SPaolo Bonzini 2662d7c41a60SPaolo Bonzini decode->cc_op = CC_OP_MULB + ot; 2663d7c41a60SPaolo Bonzini} 2664d7c41a60SPaolo Bonzini 26654228eb8cSPaolo Bonzinistatic void gen_MULX(DisasContext *s, X86DecodedInsn *decode) 26661d0b9261SPaolo Bonzini{ 26671d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 26681d0b9261SPaolo Bonzini 26691d0b9261SPaolo Bonzini /* low part of result in VEX.vvvv, high in MODRM */ 26701d0b9261SPaolo Bonzini switch (ot) { 26716dd2afedSPaolo Bonzini case MO_32: 26726dd2afedSPaolo Bonzini#ifdef TARGET_X86_64 26731d0b9261SPaolo Bonzini tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); 26741d0b9261SPaolo Bonzini tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); 26751d0b9261SPaolo Bonzini tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32, 26761d0b9261SPaolo Bonzini s->tmp2_i32, s->tmp3_i32); 26771d0b9261SPaolo Bonzini tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32); 26781d0b9261SPaolo Bonzini tcg_gen_extu_i32_tl(s->T0, s->tmp3_i32); 26791d0b9261SPaolo Bonzini break; 26801d0b9261SPaolo Bonzini 26816dd2afedSPaolo Bonzini case MO_64: 26826dd2afedSPaolo Bonzini#endif 26836dd2afedSPaolo Bonzini tcg_gen_mulu2_tl(cpu_regs[s->vex_v], s->T0, s->T0, s->T1); 26846dd2afedSPaolo Bonzini break; 26856dd2afedSPaolo Bonzini 26866dd2afedSPaolo Bonzini default: 26876dd2afedSPaolo Bonzini g_assert_not_reached(); 26886dd2afedSPaolo Bonzini } 26891d0b9261SPaolo Bonzini} 26901d0b9261SPaolo Bonzini 26914228eb8cSPaolo Bonzinistatic void gen_NEG(DisasContext *s, X86DecodedInsn *decode) 2692d7c41a60SPaolo Bonzini{ 2693d7c41a60SPaolo Bonzini MemOp ot = decode->op[0].ot; 2694d7c41a60SPaolo Bonzini TCGv oldv = tcg_temp_new(); 2695d7c41a60SPaolo Bonzini 2696d7c41a60SPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 2697d7c41a60SPaolo Bonzini TCGv newv = tcg_temp_new(); 2698d7c41a60SPaolo Bonzini TCGv cmpv = tcg_temp_new(); 2699d7c41a60SPaolo Bonzini TCGLabel *label1 = gen_new_label(); 2700d7c41a60SPaolo Bonzini 2701d7c41a60SPaolo Bonzini gen_set_label(label1); 2702d7c41a60SPaolo Bonzini gen_op_ld_v(s, ot, oldv, s->A0); 2703d7c41a60SPaolo Bonzini tcg_gen_neg_tl(newv, oldv); 2704d7c41a60SPaolo Bonzini tcg_gen_atomic_cmpxchg_tl(cmpv, s->A0, oldv, newv, 2705d7c41a60SPaolo Bonzini s->mem_index, ot | MO_LE); 2706d7c41a60SPaolo Bonzini tcg_gen_brcond_tl(TCG_COND_NE, oldv, cmpv, label1); 2707d7c41a60SPaolo Bonzini } else { 2708d7c41a60SPaolo Bonzini tcg_gen_mov_tl(oldv, s->T0); 2709d7c41a60SPaolo Bonzini } 2710d7c41a60SPaolo Bonzini tcg_gen_neg_tl(s->T0, oldv); 2711d7c41a60SPaolo Bonzini 2712d7c41a60SPaolo Bonzini decode->cc_dst = s->T0; 2713d7c41a60SPaolo Bonzini decode->cc_src = oldv; 2714d7c41a60SPaolo Bonzini tcg_gen_movi_tl(s->cc_srcT, 0); 2715d7c41a60SPaolo Bonzini decode->cc_op = CC_OP_SUBB + ot; 2716d7c41a60SPaolo Bonzini} 2717d7c41a60SPaolo Bonzini 27184228eb8cSPaolo Bonzinistatic void gen_NOT(DisasContext *s, X86DecodedInsn *decode) 2719d7c41a60SPaolo Bonzini{ 2720d7c41a60SPaolo Bonzini MemOp ot = decode->op[0].ot; 2721d7c41a60SPaolo Bonzini 2722d7c41a60SPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 2723d7c41a60SPaolo Bonzini tcg_gen_movi_tl(s->T0, ~0); 2724d7c41a60SPaolo Bonzini tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0, 2725d7c41a60SPaolo Bonzini s->mem_index, ot | MO_LE); 2726d7c41a60SPaolo Bonzini } else { 2727d7c41a60SPaolo Bonzini tcg_gen_not_tl(s->T0, s->T0); 2728d7c41a60SPaolo Bonzini } 2729d7c41a60SPaolo Bonzini} 2730d7c41a60SPaolo Bonzini 27314228eb8cSPaolo Bonzinistatic void gen_OR(DisasContext *s, X86DecodedInsn *decode) 2732cc1d28bdSPaolo Bonzini{ 2733cc1d28bdSPaolo Bonzini MemOp ot = decode->op[1].ot; 2734cc1d28bdSPaolo Bonzini 2735cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 2736cc1d28bdSPaolo Bonzini tcg_gen_atomic_or_fetch_tl(s->T0, s->A0, s->T1, 2737cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 2738cc1d28bdSPaolo Bonzini } else { 2739cc1d28bdSPaolo Bonzini tcg_gen_or_tl(s->T0, s->T0, s->T1); 2740cc1d28bdSPaolo Bonzini } 2741cc1d28bdSPaolo Bonzini prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); 2742cc1d28bdSPaolo Bonzini} 2743cc1d28bdSPaolo Bonzini 27444228eb8cSPaolo Bonzinistatic void gen_OUT(DisasContext *s, X86DecodedInsn *decode) 2745d7c41a60SPaolo Bonzini{ 2746d7c41a60SPaolo Bonzini MemOp ot = decode->op[1].ot; 2747d7c41a60SPaolo Bonzini TCGv_i32 port = tcg_temp_new_i32(); 2748d7c41a60SPaolo Bonzini TCGv_i32 value = tcg_temp_new_i32(); 2749d7c41a60SPaolo Bonzini 2750d7c41a60SPaolo Bonzini tcg_gen_trunc_tl_i32(port, s->T1); 2751d7c41a60SPaolo Bonzini tcg_gen_ext16u_i32(port, port); 2752d7c41a60SPaolo Bonzini if (!gen_check_io(s, ot, port, 0)) { 2753d7c41a60SPaolo Bonzini return; 2754d7c41a60SPaolo Bonzini } 2755d7c41a60SPaolo Bonzini tcg_gen_trunc_tl_i32(value, s->T0); 2756d7c41a60SPaolo Bonzini translator_io_start(&s->base); 2757d7c41a60SPaolo Bonzini gen_helper_out_func(ot, port, value); 2758d7c41a60SPaolo Bonzini gen_bpt_io(s, port, ot); 2759d7c41a60SPaolo Bonzini} 2760d7c41a60SPaolo Bonzini 27614228eb8cSPaolo Bonzinistatic void gen_OUTS(DisasContext *s, X86DecodedInsn *decode) 27625e9e21bcSPaolo Bonzini{ 27635e9e21bcSPaolo Bonzini MemOp ot = decode->op[1].ot; 27645e9e21bcSPaolo Bonzini TCGv_i32 port = tcg_temp_new_i32(); 27655e9e21bcSPaolo Bonzini 27665e9e21bcSPaolo Bonzini tcg_gen_trunc_tl_i32(port, s->T1); 27675e9e21bcSPaolo Bonzini tcg_gen_ext16u_i32(port, port); 27685e9e21bcSPaolo Bonzini if (!gen_check_io(s, ot, port, SVM_IOIO_STR_MASK)) { 27695e9e21bcSPaolo Bonzini return; 27705e9e21bcSPaolo Bonzini } 27715e9e21bcSPaolo Bonzini 27725e9e21bcSPaolo Bonzini translator_io_start(&s->base); 27735e9e21bcSPaolo Bonzini if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { 27746605817bSPaolo Bonzini gen_repz(s, ot, gen_outs); 27755e9e21bcSPaolo Bonzini } else { 27765e9e21bcSPaolo Bonzini gen_outs(s, ot); 27775e9e21bcSPaolo Bonzini } 27785e9e21bcSPaolo Bonzini} 27795e9e21bcSPaolo Bonzini 27804228eb8cSPaolo Bonzinistatic void gen_PALIGNR(DisasContext *s, X86DecodedInsn *decode) 278179068477SPaolo Bonzini{ 278279068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 278379068477SPaolo Bonzini if (!(s->prefix & PREFIX_DATA)) { 2784ad75a51eSRichard Henderson gen_helper_palignr_mmx(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm); 278579068477SPaolo Bonzini } else if (!s->vex_l) { 2786ad75a51eSRichard Henderson gen_helper_palignr_xmm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm); 278779068477SPaolo Bonzini } else { 2788ad75a51eSRichard Henderson gen_helper_palignr_ymm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm); 278979068477SPaolo Bonzini } 279079068477SPaolo Bonzini} 279179068477SPaolo Bonzini 27924228eb8cSPaolo Bonzinistatic void gen_PANDN(DisasContext *s, X86DecodedInsn *decode) 27931d0efbdbSPaolo Bonzini{ 27941d0efbdbSPaolo Bonzini int vec_len = vector_len(s, decode); 27951d0efbdbSPaolo Bonzini 27961d0efbdbSPaolo Bonzini /* Careful, operand order is reversed! */ 27971d0efbdbSPaolo Bonzini tcg_gen_gvec_andc(MO_64, 27981d0efbdbSPaolo Bonzini decode->op[0].offset, decode->op[2].offset, 27991d0efbdbSPaolo Bonzini decode->op[1].offset, vec_len, vec_len); 28001d0efbdbSPaolo Bonzini} 28011d0efbdbSPaolo Bonzini 28024228eb8cSPaolo Bonzinistatic void gen_PAUSE(DisasContext *s, X86DecodedInsn *decode) 2803330e6adcSPaolo Bonzini{ 2804330e6adcSPaolo Bonzini gen_update_cc_op(s); 2805330e6adcSPaolo Bonzini gen_update_eip_next(s); 2806330e6adcSPaolo Bonzini gen_helper_pause(tcg_env); 2807330e6adcSPaolo Bonzini s->base.is_jmp = DISAS_NORETURN; 2808330e6adcSPaolo Bonzini} 2809330e6adcSPaolo Bonzini 28104228eb8cSPaolo Bonzinistatic void gen_PCMPESTRI(DisasContext *s, X86DecodedInsn *decode) 281179068477SPaolo Bonzini{ 281279068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 2813ad75a51eSRichard Henderson gen_helper_pcmpestri_xmm(tcg_env, OP_PTR1, OP_PTR2, imm); 2814abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 281579068477SPaolo Bonzini} 281679068477SPaolo Bonzini 28174228eb8cSPaolo Bonzinistatic void gen_PCMPESTRM(DisasContext *s, X86DecodedInsn *decode) 281879068477SPaolo Bonzini{ 281979068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 2820ad75a51eSRichard Henderson gen_helper_pcmpestrm_xmm(tcg_env, OP_PTR1, OP_PTR2, imm); 2821abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 282279068477SPaolo Bonzini if ((s->prefix & PREFIX_VEX) && !s->vex_l) { 282379068477SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, offsetof(CPUX86State, xmm_regs[0].ZMM_X(1)), 282479068477SPaolo Bonzini 16, 16, 0); 282579068477SPaolo Bonzini } 282679068477SPaolo Bonzini} 282779068477SPaolo Bonzini 28284228eb8cSPaolo Bonzinistatic void gen_PCMPISTRI(DisasContext *s, X86DecodedInsn *decode) 282979068477SPaolo Bonzini{ 283079068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 2831ad75a51eSRichard Henderson gen_helper_pcmpistri_xmm(tcg_env, OP_PTR1, OP_PTR2, imm); 2832abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 283379068477SPaolo Bonzini} 283479068477SPaolo Bonzini 28354228eb8cSPaolo Bonzinistatic void gen_PCMPISTRM(DisasContext *s, X86DecodedInsn *decode) 283679068477SPaolo Bonzini{ 283779068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 2838ad75a51eSRichard Henderson gen_helper_pcmpistrm_xmm(tcg_env, OP_PTR1, OP_PTR2, imm); 2839abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 284079068477SPaolo Bonzini if ((s->prefix & PREFIX_VEX) && !s->vex_l) { 284179068477SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, offsetof(CPUX86State, xmm_regs[0].ZMM_X(1)), 284279068477SPaolo Bonzini 16, 16, 0); 284379068477SPaolo Bonzini } 284479068477SPaolo Bonzini} 284579068477SPaolo Bonzini 28464228eb8cSPaolo Bonzinistatic void gen_PDEP(DisasContext *s, X86DecodedInsn *decode) 28471d0b9261SPaolo Bonzini{ 28481d0b9261SPaolo Bonzini gen_helper_pdep(s->T0, s->T0, s->T1); 28491d0b9261SPaolo Bonzini} 28501d0b9261SPaolo Bonzini 28514228eb8cSPaolo Bonzinistatic void gen_PEXT(DisasContext *s, X86DecodedInsn *decode) 28521d0b9261SPaolo Bonzini{ 28531d0b9261SPaolo Bonzini gen_helper_pext(s->T0, s->T0, s->T1); 28541d0b9261SPaolo Bonzini} 28551d0b9261SPaolo Bonzini 28564228eb8cSPaolo Bonzinistatic inline void gen_pextr(DisasContext *s, X86DecodedInsn *decode, MemOp ot) 285779068477SPaolo Bonzini{ 285879068477SPaolo Bonzini int vec_len = vector_len(s, decode); 285979068477SPaolo Bonzini int mask = (vec_len >> ot) - 1; 286079068477SPaolo Bonzini int val = decode->immediate & mask; 286179068477SPaolo Bonzini 286279068477SPaolo Bonzini switch (ot) { 286379068477SPaolo Bonzini case MO_8: 2864ad75a51eSRichard Henderson tcg_gen_ld8u_tl(s->T0, tcg_env, vector_elem_offset(&decode->op[1], ot, val)); 286579068477SPaolo Bonzini break; 286679068477SPaolo Bonzini case MO_16: 2867ad75a51eSRichard Henderson tcg_gen_ld16u_tl(s->T0, tcg_env, vector_elem_offset(&decode->op[1], ot, val)); 286879068477SPaolo Bonzini break; 286979068477SPaolo Bonzini case MO_32: 287079068477SPaolo Bonzini#ifdef TARGET_X86_64 2871ad75a51eSRichard Henderson tcg_gen_ld32u_tl(s->T0, tcg_env, vector_elem_offset(&decode->op[1], ot, val)); 287279068477SPaolo Bonzini break; 287379068477SPaolo Bonzini case MO_64: 287479068477SPaolo Bonzini#endif 2875ad75a51eSRichard Henderson tcg_gen_ld_tl(s->T0, tcg_env, vector_elem_offset(&decode->op[1], ot, val)); 287679068477SPaolo Bonzini break; 287779068477SPaolo Bonzini default: 287879068477SPaolo Bonzini abort(); 287979068477SPaolo Bonzini } 288079068477SPaolo Bonzini} 288179068477SPaolo Bonzini 28824228eb8cSPaolo Bonzinistatic void gen_PEXTRB(DisasContext *s, X86DecodedInsn *decode) 288379068477SPaolo Bonzini{ 28844228eb8cSPaolo Bonzini gen_pextr(s, decode, MO_8); 288579068477SPaolo Bonzini} 288679068477SPaolo Bonzini 28874228eb8cSPaolo Bonzinistatic void gen_PEXTRW(DisasContext *s, X86DecodedInsn *decode) 288879068477SPaolo Bonzini{ 28894228eb8cSPaolo Bonzini gen_pextr(s, decode, MO_16); 289079068477SPaolo Bonzini} 289179068477SPaolo Bonzini 28924228eb8cSPaolo Bonzinistatic void gen_PEXTR(DisasContext *s, X86DecodedInsn *decode) 289379068477SPaolo Bonzini{ 289479068477SPaolo Bonzini MemOp ot = decode->op[0].ot; 28954228eb8cSPaolo Bonzini gen_pextr(s, decode, ot); 289679068477SPaolo Bonzini} 289779068477SPaolo Bonzini 28984228eb8cSPaolo Bonzinistatic inline void gen_pinsr(DisasContext *s, X86DecodedInsn *decode, MemOp ot) 289979068477SPaolo Bonzini{ 290079068477SPaolo Bonzini int vec_len = vector_len(s, decode); 290179068477SPaolo Bonzini int mask = (vec_len >> ot) - 1; 290279068477SPaolo Bonzini int val = decode->immediate & mask; 290379068477SPaolo Bonzini 290479068477SPaolo Bonzini if (decode->op[1].offset != decode->op[0].offset) { 290579068477SPaolo Bonzini assert(vec_len == 16); 290679068477SPaolo Bonzini gen_store_sse(s, decode, decode->op[1].offset); 290779068477SPaolo Bonzini } 290879068477SPaolo Bonzini 290979068477SPaolo Bonzini switch (ot) { 291079068477SPaolo Bonzini case MO_8: 2911ad75a51eSRichard Henderson tcg_gen_st8_tl(s->T1, tcg_env, vector_elem_offset(&decode->op[0], ot, val)); 291279068477SPaolo Bonzini break; 291379068477SPaolo Bonzini case MO_16: 2914ad75a51eSRichard Henderson tcg_gen_st16_tl(s->T1, tcg_env, vector_elem_offset(&decode->op[0], ot, val)); 291579068477SPaolo Bonzini break; 291679068477SPaolo Bonzini case MO_32: 291779068477SPaolo Bonzini#ifdef TARGET_X86_64 2918ad75a51eSRichard Henderson tcg_gen_st32_tl(s->T1, tcg_env, vector_elem_offset(&decode->op[0], ot, val)); 291979068477SPaolo Bonzini break; 292079068477SPaolo Bonzini case MO_64: 292179068477SPaolo Bonzini#endif 2922ad75a51eSRichard Henderson tcg_gen_st_tl(s->T1, tcg_env, vector_elem_offset(&decode->op[0], ot, val)); 292379068477SPaolo Bonzini break; 292479068477SPaolo Bonzini default: 292579068477SPaolo Bonzini abort(); 292679068477SPaolo Bonzini } 292779068477SPaolo Bonzini} 292879068477SPaolo Bonzini 29294228eb8cSPaolo Bonzinistatic void gen_PINSRB(DisasContext *s, X86DecodedInsn *decode) 293079068477SPaolo Bonzini{ 29314228eb8cSPaolo Bonzini gen_pinsr(s, decode, MO_8); 293279068477SPaolo Bonzini} 293379068477SPaolo Bonzini 29344228eb8cSPaolo Bonzinistatic void gen_PINSRW(DisasContext *s, X86DecodedInsn *decode) 2935aba2b8ecSPaolo Bonzini{ 29364228eb8cSPaolo Bonzini gen_pinsr(s, decode, MO_16); 2937aba2b8ecSPaolo Bonzini} 2938aba2b8ecSPaolo Bonzini 29394228eb8cSPaolo Bonzinistatic void gen_PINSR(DisasContext *s, X86DecodedInsn *decode) 294079068477SPaolo Bonzini{ 29414228eb8cSPaolo Bonzini gen_pinsr(s, decode, decode->op[2].ot); 294279068477SPaolo Bonzini} 294379068477SPaolo Bonzini 2944d4af67a2SRichard Hendersonstatic void gen_pmovmskb_i64(TCGv_i64 d, TCGv_i64 s) 2945d4af67a2SRichard Henderson{ 2946d4af67a2SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 2947d4af67a2SRichard Henderson 2948d4af67a2SRichard Henderson tcg_gen_andi_i64(d, s, 0x8080808080808080ull); 2949d4af67a2SRichard Henderson 2950d4af67a2SRichard Henderson /* 2951d4af67a2SRichard Henderson * After each shift+or pair: 2952d4af67a2SRichard Henderson * 0: a.......b.......c.......d.......e.......f.......g.......h....... 2953d4af67a2SRichard Henderson * 7: ab......bc......cd......de......ef......fg......gh......h....... 2954d4af67a2SRichard Henderson * 14: abcd....bcde....cdef....defg....efgh....fgh.....gh......h....... 2955d4af67a2SRichard Henderson * 28: abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h....... 2956d4af67a2SRichard Henderson * The result is left in the high bits of the word. 2957d4af67a2SRichard Henderson */ 2958d4af67a2SRichard Henderson tcg_gen_shli_i64(t, d, 7); 2959d4af67a2SRichard Henderson tcg_gen_or_i64(d, d, t); 2960d4af67a2SRichard Henderson tcg_gen_shli_i64(t, d, 14); 2961d4af67a2SRichard Henderson tcg_gen_or_i64(d, d, t); 2962d4af67a2SRichard Henderson tcg_gen_shli_i64(t, d, 28); 2963d4af67a2SRichard Henderson tcg_gen_or_i64(d, d, t); 2964d4af67a2SRichard Henderson} 2965d4af67a2SRichard Henderson 2966d4af67a2SRichard Hendersonstatic void gen_pmovmskb_vec(unsigned vece, TCGv_vec d, TCGv_vec s) 2967d4af67a2SRichard Henderson{ 2968d4af67a2SRichard Henderson TCGv_vec t = tcg_temp_new_vec_matching(d); 2969d4af67a2SRichard Henderson TCGv_vec m = tcg_constant_vec_matching(d, MO_8, 0x80); 2970d4af67a2SRichard Henderson 2971d4af67a2SRichard Henderson /* See above */ 2972d4af67a2SRichard Henderson tcg_gen_and_vec(vece, d, s, m); 2973d4af67a2SRichard Henderson tcg_gen_shli_vec(vece, t, d, 7); 2974d4af67a2SRichard Henderson tcg_gen_or_vec(vece, d, d, t); 2975d4af67a2SRichard Henderson tcg_gen_shli_vec(vece, t, d, 14); 2976d4af67a2SRichard Henderson tcg_gen_or_vec(vece, d, d, t); 2977d4af67a2SRichard Henderson tcg_gen_shli_vec(vece, t, d, 28); 2978d4af67a2SRichard Henderson tcg_gen_or_vec(vece, d, d, t); 2979d4af67a2SRichard Henderson} 2980d4af67a2SRichard Henderson 29814228eb8cSPaolo Bonzinistatic void gen_PMOVMSKB(DisasContext *s, X86DecodedInsn *decode) 29826bbeb98dSPaolo Bonzini{ 2983d4af67a2SRichard Henderson static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 }; 2984d4af67a2SRichard Henderson static const GVecGen2 g = { 2985d4af67a2SRichard Henderson .fni8 = gen_pmovmskb_i64, 2986d4af67a2SRichard Henderson .fniv = gen_pmovmskb_vec, 2987d4af67a2SRichard Henderson .opt_opc = vecop_list, 2988d4af67a2SRichard Henderson .vece = MO_64, 2989d4af67a2SRichard Henderson .prefer_i64 = TCG_TARGET_REG_BITS == 64 2990d4af67a2SRichard Henderson }; 2991d4af67a2SRichard Henderson MemOp ot = decode->op[2].ot; 2992d4af67a2SRichard Henderson int vec_len = vector_len(s, decode); 2993d4af67a2SRichard Henderson TCGv t = tcg_temp_new(); 2994d4af67a2SRichard Henderson 2995d4af67a2SRichard Henderson tcg_gen_gvec_2(offsetof(CPUX86State, xmm_t0) + xmm_offset(ot), decode->op[2].offset, 2996d4af67a2SRichard Henderson vec_len, vec_len, &g); 2997ad75a51eSRichard Henderson tcg_gen_ld8u_tl(s->T0, tcg_env, offsetof(CPUX86State, xmm_t0.ZMM_B(vec_len - 1))); 2998d4af67a2SRichard Henderson while (vec_len > 8) { 2999d4af67a2SRichard Henderson vec_len -= 8; 3000d4af67a2SRichard Henderson if (TCG_TARGET_HAS_extract2_tl) { 3001d4af67a2SRichard Henderson /* 3002d4af67a2SRichard Henderson * Load the next byte of the result into the high byte of T. 3003d4af67a2SRichard Henderson * TCG does a similar expansion of deposit to shl+extract2; by 3004d4af67a2SRichard Henderson * loading the whole word, the shift left is avoided. 3005d4af67a2SRichard Henderson */ 3006d4af67a2SRichard Henderson#ifdef TARGET_X86_64 3007ad75a51eSRichard Henderson tcg_gen_ld_tl(t, tcg_env, offsetof(CPUX86State, xmm_t0.ZMM_Q((vec_len - 1) / 8))); 3008d4af67a2SRichard Henderson#else 3009ad75a51eSRichard Henderson tcg_gen_ld_tl(t, tcg_env, offsetof(CPUX86State, xmm_t0.ZMM_L((vec_len - 1) / 4))); 3010d4af67a2SRichard Henderson#endif 3011d4af67a2SRichard Henderson 3012d4af67a2SRichard Henderson tcg_gen_extract2_tl(s->T0, t, s->T0, TARGET_LONG_BITS - 8); 30136bbeb98dSPaolo Bonzini } else { 3014d4af67a2SRichard Henderson /* 3015d4af67a2SRichard Henderson * The _previous_ value is deposited into bits 8 and higher of t. Because 3016d4af67a2SRichard Henderson * those bits are known to be zero after ld8u, this becomes a shift+or 3017d4af67a2SRichard Henderson * if deposit is not available. 3018d4af67a2SRichard Henderson */ 3019ad75a51eSRichard Henderson tcg_gen_ld8u_tl(t, tcg_env, offsetof(CPUX86State, xmm_t0.ZMM_B(vec_len - 1))); 3020d4af67a2SRichard Henderson tcg_gen_deposit_tl(s->T0, t, s->T0, 8, TARGET_LONG_BITS - 8); 30216bbeb98dSPaolo Bonzini } 3022d4af67a2SRichard Henderson } 30236bbeb98dSPaolo Bonzini} 30246bbeb98dSPaolo Bonzini 30254228eb8cSPaolo Bonzinistatic void gen_POP(DisasContext *s, X86DecodedInsn *decode) 3026cc1d28bdSPaolo Bonzini{ 3027f41990f5SMark Cave-Ayland X86DecodedOp *op = &decode->op[0]; 3028cc1d28bdSPaolo Bonzini MemOp ot = gen_pop_T0(s); 3029f41990f5SMark Cave-Ayland 30303afc6539SPaolo Bonzini assert(ot >= op->ot); 3031f1b8613dSMark Cave-Ayland if (op->has_ea || op->unit == X86_OP_SEG) { 3032cc1d28bdSPaolo Bonzini /* NOTE: order is important for MMU exceptions */ 3033aea49fbbSMark Cave-Ayland gen_writeback(s, decode, 0, s->T0); 3034cc1d28bdSPaolo Bonzini } 3035aea49fbbSMark Cave-Ayland 3036cc1d28bdSPaolo Bonzini /* NOTE: writing back registers after update is important for pop %sp */ 3037cc1d28bdSPaolo Bonzini gen_pop_update(s, ot); 3038cc1d28bdSPaolo Bonzini} 3039cc1d28bdSPaolo Bonzini 30404228eb8cSPaolo Bonzinistatic void gen_POPA(DisasContext *s, X86DecodedInsn *decode) 30415e9e21bcSPaolo Bonzini{ 30425e9e21bcSPaolo Bonzini gen_popa(s); 30435e9e21bcSPaolo Bonzini} 30445e9e21bcSPaolo Bonzini 304511ffaf8cSPaolo Bonzinistatic void gen_POPCNT(DisasContext *s, X86DecodedInsn *decode) 304611ffaf8cSPaolo Bonzini{ 3047944f4001SPaolo Bonzini decode->cc_dst = tcg_temp_new(); 304811ffaf8cSPaolo Bonzini decode->cc_op = CC_OP_POPCNT; 304911ffaf8cSPaolo Bonzini 3050944f4001SPaolo Bonzini tcg_gen_mov_tl(decode->cc_dst, s->T0); 305111ffaf8cSPaolo Bonzini tcg_gen_ctpop_tl(s->T0, s->T0); 305211ffaf8cSPaolo Bonzini} 305311ffaf8cSPaolo Bonzini 30544228eb8cSPaolo Bonzinistatic void gen_POPF(DisasContext *s, X86DecodedInsn *decode) 30555e9e21bcSPaolo Bonzini{ 30565e9e21bcSPaolo Bonzini MemOp ot; 30575e9e21bcSPaolo Bonzini int mask = TF_MASK | AC_MASK | ID_MASK | NT_MASK; 30585e9e21bcSPaolo Bonzini 30595e9e21bcSPaolo Bonzini if (CPL(s) == 0) { 30605e9e21bcSPaolo Bonzini mask |= IF_MASK | IOPL_MASK; 30615e9e21bcSPaolo Bonzini } else if (CPL(s) <= IOPL(s)) { 30625e9e21bcSPaolo Bonzini mask |= IF_MASK; 30635e9e21bcSPaolo Bonzini } 30645e9e21bcSPaolo Bonzini if (s->dflag == MO_16) { 30655e9e21bcSPaolo Bonzini mask &= 0xffff; 30665e9e21bcSPaolo Bonzini } 30675e9e21bcSPaolo Bonzini 30685e9e21bcSPaolo Bonzini ot = gen_pop_T0(s); 30695e9e21bcSPaolo Bonzini gen_helper_write_eflags(tcg_env, s->T0, tcg_constant_i32(mask)); 30705e9e21bcSPaolo Bonzini gen_pop_update(s, ot); 30715e9e21bcSPaolo Bonzini set_cc_op(s, CC_OP_EFLAGS); 30725e9e21bcSPaolo Bonzini /* abort translation because TF/AC flag may change */ 30735e9e21bcSPaolo Bonzini s->base.is_jmp = DISAS_EOB_NEXT; 30745e9e21bcSPaolo Bonzini} 30755e9e21bcSPaolo Bonzini 30764228eb8cSPaolo Bonzinistatic void gen_PSHUFW(DisasContext *s, X86DecodedInsn *decode) 3077ce4fcb94SPaolo Bonzini{ 3078ce4fcb94SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 3079ce4fcb94SPaolo Bonzini gen_helper_pshufw_mmx(OP_PTR0, OP_PTR1, imm); 3080ce4fcb94SPaolo Bonzini} 3081ce4fcb94SPaolo Bonzini 30824228eb8cSPaolo Bonzinistatic void gen_PSRLW_i(DisasContext *s, X86DecodedInsn *decode) 3083ce4fcb94SPaolo Bonzini{ 3084ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3085ce4fcb94SPaolo Bonzini 3086ce4fcb94SPaolo Bonzini if (decode->immediate >= 16) { 3087ce4fcb94SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 3088ce4fcb94SPaolo Bonzini } else { 3089ce4fcb94SPaolo Bonzini tcg_gen_gvec_shri(MO_16, 3090ce4fcb94SPaolo Bonzini decode->op[0].offset, decode->op[1].offset, 3091ce4fcb94SPaolo Bonzini decode->immediate, vec_len, vec_len); 3092ce4fcb94SPaolo Bonzini } 3093ce4fcb94SPaolo Bonzini} 3094ce4fcb94SPaolo Bonzini 30954228eb8cSPaolo Bonzinistatic void gen_PSLLW_i(DisasContext *s, X86DecodedInsn *decode) 3096ce4fcb94SPaolo Bonzini{ 3097ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3098ce4fcb94SPaolo Bonzini 3099ce4fcb94SPaolo Bonzini if (decode->immediate >= 16) { 3100ce4fcb94SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 3101ce4fcb94SPaolo Bonzini } else { 3102ce4fcb94SPaolo Bonzini tcg_gen_gvec_shli(MO_16, 3103ce4fcb94SPaolo Bonzini decode->op[0].offset, decode->op[1].offset, 3104ce4fcb94SPaolo Bonzini decode->immediate, vec_len, vec_len); 3105ce4fcb94SPaolo Bonzini } 3106ce4fcb94SPaolo Bonzini} 3107ce4fcb94SPaolo Bonzini 31084228eb8cSPaolo Bonzinistatic void gen_PSRAW_i(DisasContext *s, X86DecodedInsn *decode) 3109ce4fcb94SPaolo Bonzini{ 3110ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3111ce4fcb94SPaolo Bonzini 3112ce4fcb94SPaolo Bonzini if (decode->immediate >= 16) { 3113ce4fcb94SPaolo Bonzini decode->immediate = 15; 3114ce4fcb94SPaolo Bonzini } 3115ce4fcb94SPaolo Bonzini tcg_gen_gvec_sari(MO_16, 3116ce4fcb94SPaolo Bonzini decode->op[0].offset, decode->op[1].offset, 3117ce4fcb94SPaolo Bonzini decode->immediate, vec_len, vec_len); 3118ce4fcb94SPaolo Bonzini} 3119ce4fcb94SPaolo Bonzini 31204228eb8cSPaolo Bonzinistatic void gen_PSRLD_i(DisasContext *s, X86DecodedInsn *decode) 3121ce4fcb94SPaolo Bonzini{ 3122ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3123ce4fcb94SPaolo Bonzini 3124ce4fcb94SPaolo Bonzini if (decode->immediate >= 32) { 3125ce4fcb94SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 3126ce4fcb94SPaolo Bonzini } else { 3127ce4fcb94SPaolo Bonzini tcg_gen_gvec_shri(MO_32, 3128ce4fcb94SPaolo Bonzini decode->op[0].offset, decode->op[1].offset, 3129ce4fcb94SPaolo Bonzini decode->immediate, vec_len, vec_len); 3130ce4fcb94SPaolo Bonzini } 3131ce4fcb94SPaolo Bonzini} 3132ce4fcb94SPaolo Bonzini 31334228eb8cSPaolo Bonzinistatic void gen_PSLLD_i(DisasContext *s, X86DecodedInsn *decode) 3134ce4fcb94SPaolo Bonzini{ 3135ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3136ce4fcb94SPaolo Bonzini 3137ce4fcb94SPaolo Bonzini if (decode->immediate >= 32) { 3138ce4fcb94SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 3139ce4fcb94SPaolo Bonzini } else { 3140ce4fcb94SPaolo Bonzini tcg_gen_gvec_shli(MO_32, 3141ce4fcb94SPaolo Bonzini decode->op[0].offset, decode->op[1].offset, 3142ce4fcb94SPaolo Bonzini decode->immediate, vec_len, vec_len); 3143ce4fcb94SPaolo Bonzini } 3144ce4fcb94SPaolo Bonzini} 3145ce4fcb94SPaolo Bonzini 31464228eb8cSPaolo Bonzinistatic void gen_PSRAD_i(DisasContext *s, X86DecodedInsn *decode) 3147ce4fcb94SPaolo Bonzini{ 3148ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3149ce4fcb94SPaolo Bonzini 3150ce4fcb94SPaolo Bonzini if (decode->immediate >= 32) { 3151ce4fcb94SPaolo Bonzini decode->immediate = 31; 3152ce4fcb94SPaolo Bonzini } 3153ce4fcb94SPaolo Bonzini tcg_gen_gvec_sari(MO_32, 3154ce4fcb94SPaolo Bonzini decode->op[0].offset, decode->op[1].offset, 3155ce4fcb94SPaolo Bonzini decode->immediate, vec_len, vec_len); 3156ce4fcb94SPaolo Bonzini} 3157ce4fcb94SPaolo Bonzini 31584228eb8cSPaolo Bonzinistatic void gen_PSRLQ_i(DisasContext *s, X86DecodedInsn *decode) 3159ce4fcb94SPaolo Bonzini{ 3160ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3161ce4fcb94SPaolo Bonzini 3162ce4fcb94SPaolo Bonzini if (decode->immediate >= 64) { 3163ce4fcb94SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 3164ce4fcb94SPaolo Bonzini } else { 3165ce4fcb94SPaolo Bonzini tcg_gen_gvec_shri(MO_64, 3166ce4fcb94SPaolo Bonzini decode->op[0].offset, decode->op[1].offset, 3167ce4fcb94SPaolo Bonzini decode->immediate, vec_len, vec_len); 3168ce4fcb94SPaolo Bonzini } 3169ce4fcb94SPaolo Bonzini} 3170ce4fcb94SPaolo Bonzini 31714228eb8cSPaolo Bonzinistatic void gen_PSLLQ_i(DisasContext *s, X86DecodedInsn *decode) 3172ce4fcb94SPaolo Bonzini{ 3173ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3174ce4fcb94SPaolo Bonzini 3175ce4fcb94SPaolo Bonzini if (decode->immediate >= 64) { 3176ce4fcb94SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 3177ce4fcb94SPaolo Bonzini } else { 3178ce4fcb94SPaolo Bonzini tcg_gen_gvec_shli(MO_64, 3179ce4fcb94SPaolo Bonzini decode->op[0].offset, decode->op[1].offset, 3180ce4fcb94SPaolo Bonzini decode->immediate, vec_len, vec_len); 3181ce4fcb94SPaolo Bonzini } 3182ce4fcb94SPaolo Bonzini} 3183ce4fcb94SPaolo Bonzini 3184ce4fcb94SPaolo Bonzinistatic TCGv_ptr make_imm8u_xmm_vec(uint8_t imm, int vec_len) 3185ce4fcb94SPaolo Bonzini{ 3186ce4fcb94SPaolo Bonzini MemOp ot = vec_len == 16 ? MO_128 : MO_256; 3187ce4fcb94SPaolo Bonzini TCGv_i32 imm_v = tcg_constant8u_i32(imm); 3188ce4fcb94SPaolo Bonzini TCGv_ptr ptr = tcg_temp_new_ptr(); 3189ce4fcb94SPaolo Bonzini 3190ce4fcb94SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, offsetof(CPUX86State, xmm_t0) + xmm_offset(ot), 3191ce4fcb94SPaolo Bonzini vec_len, vec_len, 0); 3192ce4fcb94SPaolo Bonzini 3193ad75a51eSRichard Henderson tcg_gen_addi_ptr(ptr, tcg_env, offsetof(CPUX86State, xmm_t0)); 3194ad75a51eSRichard Henderson tcg_gen_st_i32(imm_v, tcg_env, offsetof(CPUX86State, xmm_t0.ZMM_L(0))); 3195ce4fcb94SPaolo Bonzini return ptr; 3196ce4fcb94SPaolo Bonzini} 3197ce4fcb94SPaolo Bonzini 31984228eb8cSPaolo Bonzinistatic void gen_PSRLDQ_i(DisasContext *s, X86DecodedInsn *decode) 3199ce4fcb94SPaolo Bonzini{ 3200ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3201ce4fcb94SPaolo Bonzini TCGv_ptr imm_vec = make_imm8u_xmm_vec(decode->immediate, vec_len); 3202ce4fcb94SPaolo Bonzini 3203ce4fcb94SPaolo Bonzini if (s->vex_l) { 3204ad75a51eSRichard Henderson gen_helper_psrldq_ymm(tcg_env, OP_PTR0, OP_PTR1, imm_vec); 3205ce4fcb94SPaolo Bonzini } else { 3206ad75a51eSRichard Henderson gen_helper_psrldq_xmm(tcg_env, OP_PTR0, OP_PTR1, imm_vec); 3207ce4fcb94SPaolo Bonzini } 3208ce4fcb94SPaolo Bonzini} 3209ce4fcb94SPaolo Bonzini 32104228eb8cSPaolo Bonzinistatic void gen_PSLLDQ_i(DisasContext *s, X86DecodedInsn *decode) 3211ce4fcb94SPaolo Bonzini{ 3212ce4fcb94SPaolo Bonzini int vec_len = vector_len(s, decode); 3213ce4fcb94SPaolo Bonzini TCGv_ptr imm_vec = make_imm8u_xmm_vec(decode->immediate, vec_len); 3214ce4fcb94SPaolo Bonzini 3215ce4fcb94SPaolo Bonzini if (s->vex_l) { 3216ad75a51eSRichard Henderson gen_helper_pslldq_ymm(tcg_env, OP_PTR0, OP_PTR1, imm_vec); 3217ce4fcb94SPaolo Bonzini } else { 3218ad75a51eSRichard Henderson gen_helper_pslldq_xmm(tcg_env, OP_PTR0, OP_PTR1, imm_vec); 3219ce4fcb94SPaolo Bonzini } 3220ce4fcb94SPaolo Bonzini} 3221ce4fcb94SPaolo Bonzini 32224228eb8cSPaolo Bonzinistatic void gen_PUSH(DisasContext *s, X86DecodedInsn *decode) 3223cc1d28bdSPaolo Bonzini{ 3224c2b6b6a6SPaolo Bonzini gen_push_v(s, s->T0); 3225cc1d28bdSPaolo Bonzini} 3226cc1d28bdSPaolo Bonzini 32274228eb8cSPaolo Bonzinistatic void gen_PUSHA(DisasContext *s, X86DecodedInsn *decode) 32285e9e21bcSPaolo Bonzini{ 32295e9e21bcSPaolo Bonzini gen_pusha(s); 32305e9e21bcSPaolo Bonzini} 32315e9e21bcSPaolo Bonzini 32324228eb8cSPaolo Bonzinistatic void gen_PUSHF(DisasContext *s, X86DecodedInsn *decode) 32335e9e21bcSPaolo Bonzini{ 32345e9e21bcSPaolo Bonzini gen_update_cc_op(s); 32355e9e21bcSPaolo Bonzini gen_helper_read_eflags(s->T0, tcg_env); 32365e9e21bcSPaolo Bonzini gen_push_v(s, s->T0); 32375e9e21bcSPaolo Bonzini} 32385e9e21bcSPaolo Bonzini 3239d7c41a60SPaolo Bonzinistatic MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode, 3240e4e5981dSPaolo Bonzini bool *can_be_zero, TCGv *count, int unit) 3241d7c41a60SPaolo Bonzini{ 3242d7c41a60SPaolo Bonzini MemOp ot = decode->op[0].ot; 3243d7c41a60SPaolo Bonzini int mask = (ot <= MO_32 ? 0x1f : 0x3f); 3244d7c41a60SPaolo Bonzini 3245d7c41a60SPaolo Bonzini *can_be_zero = false; 3246e4e5981dSPaolo Bonzini switch (unit) { 3247d7c41a60SPaolo Bonzini case X86_OP_INT: 3248d7c41a60SPaolo Bonzini *count = tcg_temp_new(); 3249e4e5981dSPaolo Bonzini tcg_gen_andi_tl(*count, cpu_regs[R_ECX], mask); 3250d7c41a60SPaolo Bonzini *can_be_zero = true; 3251d7c41a60SPaolo Bonzini break; 3252d7c41a60SPaolo Bonzini 3253d7c41a60SPaolo Bonzini case X86_OP_IMM: 3254d7c41a60SPaolo Bonzini if ((decode->immediate & mask) == 0) { 3255d7c41a60SPaolo Bonzini *count = NULL; 3256d7c41a60SPaolo Bonzini break; 3257d7c41a60SPaolo Bonzini } 3258d7c41a60SPaolo Bonzini *count = tcg_temp_new(); 3259d7c41a60SPaolo Bonzini tcg_gen_movi_tl(*count, decode->immediate & mask); 3260d7c41a60SPaolo Bonzini break; 3261d7c41a60SPaolo Bonzini 3262d7c41a60SPaolo Bonzini case X86_OP_SKIP: 3263d7c41a60SPaolo Bonzini *count = tcg_temp_new(); 3264d7c41a60SPaolo Bonzini tcg_gen_movi_tl(*count, 1); 3265d7c41a60SPaolo Bonzini break; 3266d7c41a60SPaolo Bonzini 3267d7c41a60SPaolo Bonzini default: 3268d7c41a60SPaolo Bonzini g_assert_not_reached(); 3269d7c41a60SPaolo Bonzini } 3270d7c41a60SPaolo Bonzini 3271d7c41a60SPaolo Bonzini return ot; 3272d7c41a60SPaolo Bonzini} 3273d7c41a60SPaolo Bonzini 3274d7c41a60SPaolo Bonzini/* 3275d7c41a60SPaolo Bonzini * Compute existing flags in decode->cc_src, for gen_* functions that wants 3276d7c41a60SPaolo Bonzini * to set the cc_op set to CC_OP_ADCOX. In particular, this allows rotate 3277d7c41a60SPaolo Bonzini * operations to compute the carry in decode->cc_dst and the overflow in 3278d7c41a60SPaolo Bonzini * decode->cc_src2. 3279d7c41a60SPaolo Bonzini * 3280d7c41a60SPaolo Bonzini * If need_flags is true, decode->cc_dst and decode->cc_src2 are preloaded 3281d7c41a60SPaolo Bonzini * with the value of CF and OF before the instruction, so that it is possible 3282d7c41a60SPaolo Bonzini * to keep the flags unmodified. 3283d7c41a60SPaolo Bonzini * 3284d7c41a60SPaolo Bonzini * Return true if carry could be made available cheaply as a 1-bit value in 3285d7c41a60SPaolo Bonzini * decode->cc_dst (trying a bit harder if want_carry is true). If false is 3286d7c41a60SPaolo Bonzini * returned, decode->cc_dst is uninitialized and the carry is only available 3287d7c41a60SPaolo Bonzini * as bit 0 of decode->cc_src. 3288d7c41a60SPaolo Bonzini */ 3289d7c41a60SPaolo Bonzinistatic bool gen_eflags_adcox(DisasContext *s, X86DecodedInsn *decode, bool want_carry, bool need_flags) 3290d7c41a60SPaolo Bonzini{ 3291d7c41a60SPaolo Bonzini bool got_cf = false; 3292d7c41a60SPaolo Bonzini bool got_of = false; 3293d7c41a60SPaolo Bonzini 3294d7c41a60SPaolo Bonzini decode->cc_dst = tcg_temp_new(); 3295d7c41a60SPaolo Bonzini decode->cc_src = tcg_temp_new(); 3296d7c41a60SPaolo Bonzini decode->cc_src2 = tcg_temp_new(); 3297d7c41a60SPaolo Bonzini decode->cc_op = CC_OP_ADCOX; 3298d7c41a60SPaolo Bonzini 3299d7c41a60SPaolo Bonzini /* A lot more cc_ops could be "optimized" to avoid the extracts at 3300d7c41a60SPaolo Bonzini * the end (INC/DEC, BMILG, MUL), but they are all really unlikely 3301d7c41a60SPaolo Bonzini * to be followed by rotations within the same basic block. 3302d7c41a60SPaolo Bonzini */ 3303d7c41a60SPaolo Bonzini switch (s->cc_op) { 3304d7c41a60SPaolo Bonzini case CC_OP_ADCOX: 3305d7c41a60SPaolo Bonzini /* No need to compute the full EFLAGS, CF/OF are already isolated. */ 3306d7c41a60SPaolo Bonzini tcg_gen_mov_tl(decode->cc_src, cpu_cc_src); 3307d7c41a60SPaolo Bonzini if (need_flags) { 3308d7c41a60SPaolo Bonzini tcg_gen_mov_tl(decode->cc_src2, cpu_cc_src2); 3309d7c41a60SPaolo Bonzini got_of = true; 3310d7c41a60SPaolo Bonzini } 3311d7c41a60SPaolo Bonzini if (want_carry || need_flags) { 3312d7c41a60SPaolo Bonzini tcg_gen_mov_tl(decode->cc_dst, cpu_cc_dst); 3313d7c41a60SPaolo Bonzini got_cf = true; 3314d7c41a60SPaolo Bonzini } 3315d7c41a60SPaolo Bonzini break; 3316d7c41a60SPaolo Bonzini 3317d7c41a60SPaolo Bonzini case CC_OP_LOGICB ... CC_OP_LOGICQ: 3318d7c41a60SPaolo Bonzini /* CF and OF are zero, do it just because it's easy. */ 3319d7c41a60SPaolo Bonzini gen_mov_eflags(s, decode->cc_src); 3320d7c41a60SPaolo Bonzini if (need_flags) { 3321d7c41a60SPaolo Bonzini tcg_gen_movi_tl(decode->cc_src2, 0); 3322d7c41a60SPaolo Bonzini got_of = true; 3323d7c41a60SPaolo Bonzini } 3324d7c41a60SPaolo Bonzini if (want_carry || need_flags) { 3325d7c41a60SPaolo Bonzini tcg_gen_movi_tl(decode->cc_dst, 0); 3326d7c41a60SPaolo Bonzini got_cf = true; 3327d7c41a60SPaolo Bonzini } 3328d7c41a60SPaolo Bonzini break; 3329d7c41a60SPaolo Bonzini 3330d7c41a60SPaolo Bonzini case CC_OP_SARB ... CC_OP_SARQ: 3331d7c41a60SPaolo Bonzini /* 3332d7c41a60SPaolo Bonzini * SHR/RCR/SHR/RCR/... is a relatively common occurrence of RCR. 3333d7c41a60SPaolo Bonzini * By computing CF without using eflags, the calls to cc_compute_all 3334d7c41a60SPaolo Bonzini * can be eliminated as dead code (except for the last RCR). 3335d7c41a60SPaolo Bonzini */ 3336d7c41a60SPaolo Bonzini if (want_carry || need_flags) { 3337d7c41a60SPaolo Bonzini tcg_gen_andi_tl(decode->cc_dst, cpu_cc_src, 1); 3338d7c41a60SPaolo Bonzini got_cf = true; 3339d7c41a60SPaolo Bonzini } 3340d7c41a60SPaolo Bonzini gen_mov_eflags(s, decode->cc_src); 3341d7c41a60SPaolo Bonzini break; 3342d7c41a60SPaolo Bonzini 3343d7c41a60SPaolo Bonzini case CC_OP_SHLB ... CC_OP_SHLQ: 3344d7c41a60SPaolo Bonzini /* 3345d7c41a60SPaolo Bonzini * Likewise for SHL/RCL/SHL/RCL/... but, if CF is not in the sign 3346d7c41a60SPaolo Bonzini * bit, we might as well fish CF out of EFLAGS and save a shift. 3347d7c41a60SPaolo Bonzini */ 3348d7c41a60SPaolo Bonzini if (want_carry && (!need_flags || s->cc_op == CC_OP_SHLB + MO_TL)) { 3349f359b2fbSRichard Henderson MemOp size = cc_op_size(s->cc_op); 3350f359b2fbSRichard Henderson tcg_gen_shri_tl(decode->cc_dst, cpu_cc_src, (8 << size) - 1); 3351d7c41a60SPaolo Bonzini got_cf = true; 3352d7c41a60SPaolo Bonzini } 3353d7c41a60SPaolo Bonzini gen_mov_eflags(s, decode->cc_src); 3354d7c41a60SPaolo Bonzini break; 3355d7c41a60SPaolo Bonzini 3356d7c41a60SPaolo Bonzini default: 3357d7c41a60SPaolo Bonzini gen_mov_eflags(s, decode->cc_src); 3358d7c41a60SPaolo Bonzini break; 3359d7c41a60SPaolo Bonzini } 3360d7c41a60SPaolo Bonzini 3361d7c41a60SPaolo Bonzini if (need_flags) { 3362d7c41a60SPaolo Bonzini /* If the flags could be left unmodified, always load them. */ 3363d7c41a60SPaolo Bonzini if (!got_of) { 3364d7c41a60SPaolo Bonzini tcg_gen_extract_tl(decode->cc_src2, decode->cc_src, ctz32(CC_O), 1); 3365d7c41a60SPaolo Bonzini got_of = true; 3366d7c41a60SPaolo Bonzini } 3367d7c41a60SPaolo Bonzini if (!got_cf) { 3368d7c41a60SPaolo Bonzini tcg_gen_extract_tl(decode->cc_dst, decode->cc_src, ctz32(CC_C), 1); 3369d7c41a60SPaolo Bonzini got_cf = true; 3370d7c41a60SPaolo Bonzini } 3371d7c41a60SPaolo Bonzini } 3372d7c41a60SPaolo Bonzini return got_cf; 3373d7c41a60SPaolo Bonzini} 3374d7c41a60SPaolo Bonzini 3375d0414d71SPaolo Bonzinistatic void gen_rot_overflow(X86DecodedInsn *decode, TCGv result, TCGv old, 3376d0414d71SPaolo Bonzini bool can_be_zero, TCGv count) 3377d7c41a60SPaolo Bonzini{ 3378d7c41a60SPaolo Bonzini MemOp ot = decode->op[0].ot; 3379d0414d71SPaolo Bonzini TCGv temp = can_be_zero ? tcg_temp_new() : decode->cc_src2; 3380d7c41a60SPaolo Bonzini 3381d7c41a60SPaolo Bonzini tcg_gen_xor_tl(temp, old, result); 3382d7c41a60SPaolo Bonzini tcg_gen_extract_tl(temp, temp, (8 << ot) - 1, 1); 3383d0414d71SPaolo Bonzini if (can_be_zero) { 3384d7c41a60SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_EQ, decode->cc_src2, count, tcg_constant_tl(0), 3385d7c41a60SPaolo Bonzini decode->cc_src2, temp); 3386d7c41a60SPaolo Bonzini } 3387d7c41a60SPaolo Bonzini} 3388d7c41a60SPaolo Bonzini 3389d7c41a60SPaolo Bonzini/* 3390d7c41a60SPaolo Bonzini * RCx operations are invariant modulo 8*operand_size+1. For 8 and 16-bit operands, 3391d7c41a60SPaolo Bonzini * this is less than 0x1f (the mask applied by gen_shift_count) so reduce further. 3392d7c41a60SPaolo Bonzini */ 3393d7c41a60SPaolo Bonzinistatic void gen_rotc_mod(MemOp ot, TCGv count) 3394d7c41a60SPaolo Bonzini{ 3395d7c41a60SPaolo Bonzini TCGv temp; 3396d7c41a60SPaolo Bonzini 3397d7c41a60SPaolo Bonzini switch (ot) { 3398d7c41a60SPaolo Bonzini case MO_8: 3399d7c41a60SPaolo Bonzini temp = tcg_temp_new(); 3400d7c41a60SPaolo Bonzini tcg_gen_subi_tl(temp, count, 18); 3401d7c41a60SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count); 3402d7c41a60SPaolo Bonzini tcg_gen_subi_tl(temp, count, 9); 3403d7c41a60SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count); 3404d7c41a60SPaolo Bonzini break; 3405d7c41a60SPaolo Bonzini 3406d7c41a60SPaolo Bonzini case MO_16: 3407d7c41a60SPaolo Bonzini temp = tcg_temp_new(); 3408d7c41a60SPaolo Bonzini tcg_gen_subi_tl(temp, count, 17); 3409d7c41a60SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count); 3410d7c41a60SPaolo Bonzini break; 3411d7c41a60SPaolo Bonzini 3412d7c41a60SPaolo Bonzini default: 3413d7c41a60SPaolo Bonzini break; 3414d7c41a60SPaolo Bonzini } 3415d7c41a60SPaolo Bonzini} 3416d7c41a60SPaolo Bonzini 3417d7c41a60SPaolo Bonzini/* 3418d7c41a60SPaolo Bonzini * The idea here is that the bit to the right of the new bit 0 is the 3419d7c41a60SPaolo Bonzini * new carry, and the bit to the right of the old bit 0 is the old carry. 3420d7c41a60SPaolo Bonzini * Just like a regular rotation, the result of the rotation is composed 3421d7c41a60SPaolo Bonzini * from a right shifted part and a left shifted part of s->T0. The new carry 3422d7c41a60SPaolo Bonzini * is extracted from the right-shifted portion, and the old carry is 3423d7c41a60SPaolo Bonzini * inserted at the end of the left-shifted portion. 3424d7c41a60SPaolo Bonzini * 3425d7c41a60SPaolo Bonzini * Because of the separate shifts involving the carry, gen_RCL and gen_RCR 3426d7c41a60SPaolo Bonzini * mostly operate on count-1. This also comes in handy when computing 3427d7c41a60SPaolo Bonzini * length - count, because (length-1) - (count-1) can be computed with 3428d7c41a60SPaolo Bonzini * a XOR, and that is commutative unlike subtraction. 3429d7c41a60SPaolo Bonzini */ 34304228eb8cSPaolo Bonzinistatic void gen_RCL(DisasContext *s, X86DecodedInsn *decode) 3431d7c41a60SPaolo Bonzini{ 3432d7c41a60SPaolo Bonzini bool have_1bit_cin, can_be_zero; 3433d7c41a60SPaolo Bonzini TCGv count; 3434d7c41a60SPaolo Bonzini TCGLabel *zero_label = NULL; 3435e4e5981dSPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit); 3436d7c41a60SPaolo Bonzini TCGv low, high, low_count; 3437d7c41a60SPaolo Bonzini 3438d7c41a60SPaolo Bonzini if (!count) { 3439d7c41a60SPaolo Bonzini return; 3440d7c41a60SPaolo Bonzini } 3441d7c41a60SPaolo Bonzini 3442d7c41a60SPaolo Bonzini low = tcg_temp_new(); 3443d7c41a60SPaolo Bonzini high = tcg_temp_new(); 3444d7c41a60SPaolo Bonzini low_count = tcg_temp_new(); 3445d7c41a60SPaolo Bonzini 3446d7c41a60SPaolo Bonzini gen_rotc_mod(ot, count); 3447d7c41a60SPaolo Bonzini have_1bit_cin = gen_eflags_adcox(s, decode, true, can_be_zero); 3448d7c41a60SPaolo Bonzini if (can_be_zero) { 3449d7c41a60SPaolo Bonzini zero_label = gen_new_label(); 3450d7c41a60SPaolo Bonzini tcg_gen_brcondi_tl(TCG_COND_EQ, count, 0, zero_label); 3451d7c41a60SPaolo Bonzini } 3452d7c41a60SPaolo Bonzini 3453d7c41a60SPaolo Bonzini /* Compute high part, including incoming carry. */ 3454d7c41a60SPaolo Bonzini if (!have_1bit_cin || TCG_TARGET_deposit_tl_valid(1, TARGET_LONG_BITS - 1)) { 3455d7c41a60SPaolo Bonzini /* high = (T0 << 1) | cin */ 3456d7c41a60SPaolo Bonzini TCGv cin = have_1bit_cin ? decode->cc_dst : decode->cc_src; 3457d7c41a60SPaolo Bonzini tcg_gen_deposit_tl(high, cin, s->T0, 1, TARGET_LONG_BITS - 1); 3458d7c41a60SPaolo Bonzini } else { 3459d7c41a60SPaolo Bonzini /* Same as above but without deposit; cin in cc_dst. */ 3460d7c41a60SPaolo Bonzini tcg_gen_add_tl(high, s->T0, decode->cc_dst); 3461d7c41a60SPaolo Bonzini tcg_gen_add_tl(high, high, s->T0); 3462d7c41a60SPaolo Bonzini } 3463d7c41a60SPaolo Bonzini tcg_gen_subi_tl(count, count, 1); 3464d7c41a60SPaolo Bonzini tcg_gen_shl_tl(high, high, count); 3465d7c41a60SPaolo Bonzini 3466d7c41a60SPaolo Bonzini /* Compute low part and outgoing carry, incoming s->T0 is zero extended */ 3467d7c41a60SPaolo Bonzini tcg_gen_xori_tl(low_count, count, (8 << ot) - 1); /* LENGTH - 1 - (count - 1) */ 3468d7c41a60SPaolo Bonzini tcg_gen_shr_tl(low, s->T0, low_count); 3469d7c41a60SPaolo Bonzini tcg_gen_andi_tl(decode->cc_dst, low, 1); 3470d7c41a60SPaolo Bonzini tcg_gen_shri_tl(low, low, 1); 3471d7c41a60SPaolo Bonzini 3472d7c41a60SPaolo Bonzini /* Compute result and outgoing overflow */ 3473d7c41a60SPaolo Bonzini tcg_gen_mov_tl(decode->cc_src2, s->T0); 3474d7c41a60SPaolo Bonzini tcg_gen_or_tl(s->T0, low, high); 3475d0414d71SPaolo Bonzini gen_rot_overflow(decode, s->T0, decode->cc_src2, false, NULL); 3476d7c41a60SPaolo Bonzini 3477d7c41a60SPaolo Bonzini if (zero_label) { 3478d7c41a60SPaolo Bonzini gen_set_label(zero_label); 3479d7c41a60SPaolo Bonzini } 3480d7c41a60SPaolo Bonzini} 3481d7c41a60SPaolo Bonzini 34824228eb8cSPaolo Bonzinistatic void gen_RCR(DisasContext *s, X86DecodedInsn *decode) 3483d7c41a60SPaolo Bonzini{ 3484d7c41a60SPaolo Bonzini bool have_1bit_cin, can_be_zero; 3485d7c41a60SPaolo Bonzini TCGv count; 3486d7c41a60SPaolo Bonzini TCGLabel *zero_label = NULL; 3487e4e5981dSPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit); 3488d7c41a60SPaolo Bonzini TCGv low, high, high_count; 3489d7c41a60SPaolo Bonzini 3490d7c41a60SPaolo Bonzini if (!count) { 3491d7c41a60SPaolo Bonzini return; 3492d7c41a60SPaolo Bonzini } 3493d7c41a60SPaolo Bonzini 3494d7c41a60SPaolo Bonzini low = tcg_temp_new(); 3495d7c41a60SPaolo Bonzini high = tcg_temp_new(); 3496d7c41a60SPaolo Bonzini high_count = tcg_temp_new(); 3497d7c41a60SPaolo Bonzini 3498d7c41a60SPaolo Bonzini gen_rotc_mod(ot, count); 3499d7c41a60SPaolo Bonzini have_1bit_cin = gen_eflags_adcox(s, decode, true, can_be_zero); 3500d7c41a60SPaolo Bonzini if (can_be_zero) { 3501d7c41a60SPaolo Bonzini zero_label = gen_new_label(); 3502d7c41a60SPaolo Bonzini tcg_gen_brcondi_tl(TCG_COND_EQ, count, 0, zero_label); 3503d7c41a60SPaolo Bonzini } 3504d7c41a60SPaolo Bonzini 3505d7c41a60SPaolo Bonzini /* Save incoming carry into high, it will be shifted later. */ 3506d7c41a60SPaolo Bonzini if (!have_1bit_cin || TCG_TARGET_deposit_tl_valid(1, TARGET_LONG_BITS - 1)) { 3507d7c41a60SPaolo Bonzini TCGv cin = have_1bit_cin ? decode->cc_dst : decode->cc_src; 3508d7c41a60SPaolo Bonzini tcg_gen_deposit_tl(high, cin, s->T0, 1, TARGET_LONG_BITS - 1); 3509d7c41a60SPaolo Bonzini } else { 3510d7c41a60SPaolo Bonzini /* Same as above but without deposit; cin in cc_dst. */ 3511d7c41a60SPaolo Bonzini tcg_gen_add_tl(high, s->T0, decode->cc_dst); 3512d7c41a60SPaolo Bonzini tcg_gen_add_tl(high, high, s->T0); 3513d7c41a60SPaolo Bonzini } 3514d7c41a60SPaolo Bonzini 3515d7c41a60SPaolo Bonzini /* Compute low part and outgoing carry, incoming s->T0 is zero extended */ 3516d7c41a60SPaolo Bonzini tcg_gen_subi_tl(count, count, 1); 3517d7c41a60SPaolo Bonzini tcg_gen_shr_tl(low, s->T0, count); 3518d7c41a60SPaolo Bonzini tcg_gen_andi_tl(decode->cc_dst, low, 1); 3519d7c41a60SPaolo Bonzini tcg_gen_shri_tl(low, low, 1); 3520d7c41a60SPaolo Bonzini 3521d7c41a60SPaolo Bonzini /* Move high part to the right position */ 3522d7c41a60SPaolo Bonzini tcg_gen_xori_tl(high_count, count, (8 << ot) - 1); /* LENGTH - 1 - (count - 1) */ 3523d7c41a60SPaolo Bonzini tcg_gen_shl_tl(high, high, high_count); 3524d7c41a60SPaolo Bonzini 3525d7c41a60SPaolo Bonzini /* Compute result and outgoing overflow */ 3526d7c41a60SPaolo Bonzini tcg_gen_mov_tl(decode->cc_src2, s->T0); 3527d7c41a60SPaolo Bonzini tcg_gen_or_tl(s->T0, low, high); 3528d0414d71SPaolo Bonzini gen_rot_overflow(decode, s->T0, decode->cc_src2, false, NULL); 3529d7c41a60SPaolo Bonzini 3530d7c41a60SPaolo Bonzini if (zero_label) { 3531d7c41a60SPaolo Bonzini gen_set_label(zero_label); 3532d7c41a60SPaolo Bonzini } 3533d7c41a60SPaolo Bonzini} 3534d7c41a60SPaolo Bonzini 3535ae541c0eSPaolo Bonzini#ifdef CONFIG_USER_ONLY 3536ae541c0eSPaolo Bonzinistatic void gen_unreachable(DisasContext *s, X86DecodedInsn *decode) 3537ae541c0eSPaolo Bonzini{ 3538ae541c0eSPaolo Bonzini g_assert_not_reached(); 3539ae541c0eSPaolo Bonzini} 3540ae541c0eSPaolo Bonzini#endif 3541ae541c0eSPaolo Bonzini 3542ae541c0eSPaolo Bonzini#ifndef CONFIG_USER_ONLY 3543ae541c0eSPaolo Bonzinistatic void gen_RDMSR(DisasContext *s, X86DecodedInsn *decode) 3544ae541c0eSPaolo Bonzini{ 3545ae541c0eSPaolo Bonzini gen_update_cc_op(s); 3546ae541c0eSPaolo Bonzini gen_update_eip_cur(s); 3547ae541c0eSPaolo Bonzini gen_helper_rdmsr(tcg_env); 3548ae541c0eSPaolo Bonzini} 3549ae541c0eSPaolo Bonzini#else 3550ae541c0eSPaolo Bonzini#define gen_RDMSR gen_unreachable 3551ae541c0eSPaolo Bonzini#endif 3552ae541c0eSPaolo Bonzini 3553ae541c0eSPaolo Bonzinistatic void gen_RDPMC(DisasContext *s, X86DecodedInsn *decode) 3554ae541c0eSPaolo Bonzini{ 3555ae541c0eSPaolo Bonzini gen_update_cc_op(s); 3556ae541c0eSPaolo Bonzini gen_update_eip_cur(s); 3557ae541c0eSPaolo Bonzini translator_io_start(&s->base); 3558ae541c0eSPaolo Bonzini gen_helper_rdpmc(tcg_env); 3559ae541c0eSPaolo Bonzini s->base.is_jmp = DISAS_NORETURN; 3560ae541c0eSPaolo Bonzini} 3561ae541c0eSPaolo Bonzini 3562ae541c0eSPaolo Bonzinistatic void gen_RDTSC(DisasContext *s, X86DecodedInsn *decode) 3563ae541c0eSPaolo Bonzini{ 3564ae541c0eSPaolo Bonzini gen_update_cc_op(s); 3565ae541c0eSPaolo Bonzini gen_update_eip_cur(s); 3566ae541c0eSPaolo Bonzini translator_io_start(&s->base); 3567ae541c0eSPaolo Bonzini gen_helper_rdtsc(tcg_env); 3568ae541c0eSPaolo Bonzini} 3569ae541c0eSPaolo Bonzini 3570ea89aa89SPaolo Bonzinistatic void gen_RDxxBASE(DisasContext *s, X86DecodedInsn *decode) 3571ea89aa89SPaolo Bonzini{ 3572ea89aa89SPaolo Bonzini TCGv base = cpu_seg_base[s->modrm & 8 ? R_GS : R_FS]; 3573ea89aa89SPaolo Bonzini 3574ea89aa89SPaolo Bonzini /* Preserve hflags bits by testing CR4 at runtime. */ 3575ea89aa89SPaolo Bonzini gen_helper_cr4_testbit(tcg_env, tcg_constant_i32(CR4_FSGSBASE_MASK)); 3576ea89aa89SPaolo Bonzini tcg_gen_mov_tl(s->T0, base); 3577ea89aa89SPaolo Bonzini} 3578ea89aa89SPaolo Bonzini 35794228eb8cSPaolo Bonzinistatic void gen_RET(DisasContext *s, X86DecodedInsn *decode) 3580d7c41a60SPaolo Bonzini{ 3581c2b6b6a6SPaolo Bonzini int16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0; 3582d7c41a60SPaolo Bonzini 3583d7c41a60SPaolo Bonzini MemOp ot = gen_pop_T0(s); 3584d7c41a60SPaolo Bonzini gen_stack_update(s, adjust + (1 << ot)); 3585d7c41a60SPaolo Bonzini gen_op_jmp_v(s, s->T0); 3586d7c41a60SPaolo Bonzini gen_bnd_jmp(s); 3587d7c41a60SPaolo Bonzini s->base.is_jmp = DISAS_JUMP; 3588d7c41a60SPaolo Bonzini} 3589d7c41a60SPaolo Bonzini 35904228eb8cSPaolo Bonzinistatic void gen_RETF(DisasContext *s, X86DecodedInsn *decode) 3591d7c41a60SPaolo Bonzini{ 3592c2b6b6a6SPaolo Bonzini int16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0; 3593d7c41a60SPaolo Bonzini 3594d7c41a60SPaolo Bonzini if (!PE(s) || VM86(s)) { 3595f0e754d3SPaolo Bonzini gen_lea_ss_ofs(s, s->A0, cpu_regs[R_ESP], 0); 3596d7c41a60SPaolo Bonzini /* pop offset */ 3597d7c41a60SPaolo Bonzini gen_op_ld_v(s, s->dflag, s->T0, s->A0); 3598d7c41a60SPaolo Bonzini /* NOTE: keeping EIP updated is not a problem in case of 3599d7c41a60SPaolo Bonzini exception */ 3600d7c41a60SPaolo Bonzini gen_op_jmp_v(s, s->T0); 3601d7c41a60SPaolo Bonzini /* pop selector */ 3602d7c41a60SPaolo Bonzini gen_add_A0_im(s, 1 << s->dflag); 3603d7c41a60SPaolo Bonzini gen_op_ld_v(s, s->dflag, s->T0, s->A0); 3604d7c41a60SPaolo Bonzini gen_op_movl_seg_real(s, R_CS, s->T0); 3605d7c41a60SPaolo Bonzini /* add stack offset */ 3606d7c41a60SPaolo Bonzini gen_stack_update(s, adjust + (2 << s->dflag)); 3607d7c41a60SPaolo Bonzini } else { 3608d7c41a60SPaolo Bonzini gen_update_cc_op(s); 3609d7c41a60SPaolo Bonzini gen_update_eip_cur(s); 3610d7c41a60SPaolo Bonzini gen_helper_lret_protected(tcg_env, tcg_constant_i32(s->dflag - 1), 3611d7c41a60SPaolo Bonzini tcg_constant_i32(adjust)); 3612d7c41a60SPaolo Bonzini } 3613d7c41a60SPaolo Bonzini s->base.is_jmp = DISAS_EOB_ONLY; 3614d7c41a60SPaolo Bonzini} 3615d7c41a60SPaolo Bonzini 3616d7c41a60SPaolo Bonzini/* 3617d7c41a60SPaolo Bonzini * Return non-NULL if a 32-bit rotate works, after possibly replicating the input. 3618d7c41a60SPaolo Bonzini * The input has already been zero-extended upon operand decode. 3619d7c41a60SPaolo Bonzini */ 3620d7c41a60SPaolo Bonzinistatic TCGv_i32 gen_rot_replicate(MemOp ot, TCGv in) 3621d7c41a60SPaolo Bonzini{ 3622d7c41a60SPaolo Bonzini TCGv_i32 temp; 3623d7c41a60SPaolo Bonzini switch (ot) { 3624d7c41a60SPaolo Bonzini case MO_8: 3625d7c41a60SPaolo Bonzini temp = tcg_temp_new_i32(); 3626d7c41a60SPaolo Bonzini tcg_gen_trunc_tl_i32(temp, in); 3627d7c41a60SPaolo Bonzini tcg_gen_muli_i32(temp, temp, 0x01010101); 3628d7c41a60SPaolo Bonzini return temp; 3629d7c41a60SPaolo Bonzini 3630d7c41a60SPaolo Bonzini case MO_16: 3631d7c41a60SPaolo Bonzini temp = tcg_temp_new_i32(); 3632d7c41a60SPaolo Bonzini tcg_gen_trunc_tl_i32(temp, in); 3633d7c41a60SPaolo Bonzini tcg_gen_deposit_i32(temp, temp, temp, 16, 16); 3634d7c41a60SPaolo Bonzini return temp; 3635d7c41a60SPaolo Bonzini 3636d7c41a60SPaolo Bonzini#ifdef TARGET_X86_64 3637d7c41a60SPaolo Bonzini case MO_32: 3638d7c41a60SPaolo Bonzini temp = tcg_temp_new_i32(); 3639d7c41a60SPaolo Bonzini tcg_gen_trunc_tl_i32(temp, in); 3640d7c41a60SPaolo Bonzini return temp; 3641d7c41a60SPaolo Bonzini#endif 3642d7c41a60SPaolo Bonzini 3643d7c41a60SPaolo Bonzini default: 3644d7c41a60SPaolo Bonzini return NULL; 3645d7c41a60SPaolo Bonzini } 3646d7c41a60SPaolo Bonzini} 3647d7c41a60SPaolo Bonzini 3648d0414d71SPaolo Bonzinistatic void gen_rot_carry(X86DecodedInsn *decode, TCGv result, 3649d0414d71SPaolo Bonzini bool can_be_zero, TCGv count, int bit) 3650d7c41a60SPaolo Bonzini{ 3651d0414d71SPaolo Bonzini if (!can_be_zero) { 3652d7c41a60SPaolo Bonzini tcg_gen_extract_tl(decode->cc_dst, result, bit, 1); 3653d7c41a60SPaolo Bonzini } else { 3654d7c41a60SPaolo Bonzini TCGv temp = tcg_temp_new(); 3655d7c41a60SPaolo Bonzini tcg_gen_extract_tl(temp, result, bit, 1); 3656d7c41a60SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_EQ, decode->cc_dst, count, tcg_constant_tl(0), 3657d7c41a60SPaolo Bonzini decode->cc_dst, temp); 3658d7c41a60SPaolo Bonzini } 3659d7c41a60SPaolo Bonzini} 3660d7c41a60SPaolo Bonzini 36614228eb8cSPaolo Bonzinistatic void gen_ROL(DisasContext *s, X86DecodedInsn *decode) 3662d7c41a60SPaolo Bonzini{ 3663d7c41a60SPaolo Bonzini bool can_be_zero; 3664d7c41a60SPaolo Bonzini TCGv count; 3665e4e5981dSPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit); 3666d7c41a60SPaolo Bonzini TCGv_i32 temp32, count32; 3667d7c41a60SPaolo Bonzini TCGv old = tcg_temp_new(); 3668d7c41a60SPaolo Bonzini 3669d7c41a60SPaolo Bonzini if (!count) { 3670d7c41a60SPaolo Bonzini return; 3671d7c41a60SPaolo Bonzini } 3672d7c41a60SPaolo Bonzini 3673d7c41a60SPaolo Bonzini gen_eflags_adcox(s, decode, false, can_be_zero); 3674d7c41a60SPaolo Bonzini tcg_gen_mov_tl(old, s->T0); 3675d7c41a60SPaolo Bonzini temp32 = gen_rot_replicate(ot, s->T0); 3676d7c41a60SPaolo Bonzini if (temp32) { 3677d7c41a60SPaolo Bonzini count32 = tcg_temp_new_i32(); 3678d7c41a60SPaolo Bonzini tcg_gen_trunc_tl_i32(count32, count); 3679d7c41a60SPaolo Bonzini tcg_gen_rotl_i32(temp32, temp32, count32); 3680d7c41a60SPaolo Bonzini /* Zero extend to facilitate later optimization. */ 3681d7c41a60SPaolo Bonzini tcg_gen_extu_i32_tl(s->T0, temp32); 3682d7c41a60SPaolo Bonzini } else { 3683d7c41a60SPaolo Bonzini tcg_gen_rotl_tl(s->T0, s->T0, count); 3684d7c41a60SPaolo Bonzini } 3685d0414d71SPaolo Bonzini gen_rot_carry(decode, s->T0, can_be_zero, count, 0); 3686d0414d71SPaolo Bonzini gen_rot_overflow(decode, s->T0, old, can_be_zero, count); 3687d7c41a60SPaolo Bonzini} 3688d7c41a60SPaolo Bonzini 36894228eb8cSPaolo Bonzinistatic void gen_ROR(DisasContext *s, X86DecodedInsn *decode) 3690d7c41a60SPaolo Bonzini{ 3691d7c41a60SPaolo Bonzini bool can_be_zero; 3692d7c41a60SPaolo Bonzini TCGv count; 3693e4e5981dSPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit); 3694d7c41a60SPaolo Bonzini TCGv_i32 temp32, count32; 3695d7c41a60SPaolo Bonzini TCGv old = tcg_temp_new(); 3696d7c41a60SPaolo Bonzini 3697d7c41a60SPaolo Bonzini if (!count) { 3698d7c41a60SPaolo Bonzini return; 3699d7c41a60SPaolo Bonzini } 3700d7c41a60SPaolo Bonzini 3701d7c41a60SPaolo Bonzini gen_eflags_adcox(s, decode, false, can_be_zero); 3702d7c41a60SPaolo Bonzini tcg_gen_mov_tl(old, s->T0); 3703d7c41a60SPaolo Bonzini temp32 = gen_rot_replicate(ot, s->T0); 3704d7c41a60SPaolo Bonzini if (temp32) { 3705d7c41a60SPaolo Bonzini count32 = tcg_temp_new_i32(); 3706d7c41a60SPaolo Bonzini tcg_gen_trunc_tl_i32(count32, count); 3707d7c41a60SPaolo Bonzini tcg_gen_rotr_i32(temp32, temp32, count32); 3708d7c41a60SPaolo Bonzini /* Zero extend to facilitate later optimization. */ 3709d7c41a60SPaolo Bonzini tcg_gen_extu_i32_tl(s->T0, temp32); 3710d0414d71SPaolo Bonzini gen_rot_carry(decode, s->T0, can_be_zero, count, 31); 3711d7c41a60SPaolo Bonzini } else { 3712d7c41a60SPaolo Bonzini tcg_gen_rotr_tl(s->T0, s->T0, count); 3713d0414d71SPaolo Bonzini gen_rot_carry(decode, s->T0, can_be_zero, count, TARGET_LONG_BITS - 1); 3714d7c41a60SPaolo Bonzini } 3715d0414d71SPaolo Bonzini gen_rot_overflow(decode, s->T0, old, can_be_zero, count); 3716d7c41a60SPaolo Bonzini} 3717d7c41a60SPaolo Bonzini 37184228eb8cSPaolo Bonzinistatic void gen_RORX(DisasContext *s, X86DecodedInsn *decode) 37191d0b9261SPaolo Bonzini{ 37201d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 37216dd2afedSPaolo Bonzini int mask = ot == MO_64 ? 63 : 31; 37226dd2afedSPaolo Bonzini int b = decode->immediate & mask; 37231d0b9261SPaolo Bonzini 37246dd2afedSPaolo Bonzini switch (ot) { 37256dd2afedSPaolo Bonzini case MO_32: 37266dd2afedSPaolo Bonzini#ifdef TARGET_X86_64 37271d0b9261SPaolo Bonzini tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); 37286dd2afedSPaolo Bonzini tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b); 37291d0b9261SPaolo Bonzini tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); 37306dd2afedSPaolo Bonzini break; 37316dd2afedSPaolo Bonzini 37326dd2afedSPaolo Bonzini case MO_64: 37336dd2afedSPaolo Bonzini#endif 37346dd2afedSPaolo Bonzini tcg_gen_rotri_tl(s->T0, s->T0, b); 37356dd2afedSPaolo Bonzini break; 37366dd2afedSPaolo Bonzini 37376dd2afedSPaolo Bonzini default: 37386dd2afedSPaolo Bonzini g_assert_not_reached(); 37391d0b9261SPaolo Bonzini } 37401d0b9261SPaolo Bonzini} 37411d0b9261SPaolo Bonzini 3742ae541c0eSPaolo Bonzini#ifndef CONFIG_USER_ONLY 3743ae541c0eSPaolo Bonzinistatic void gen_RSM(DisasContext *s, X86DecodedInsn *decode) 3744ae541c0eSPaolo Bonzini{ 3745ae541c0eSPaolo Bonzini gen_helper_rsm(tcg_env); 3746ae541c0eSPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 3747ae541c0eSPaolo Bonzini s->base.is_jmp = DISAS_EOB_ONLY; 3748ae541c0eSPaolo Bonzini} 3749ae541c0eSPaolo Bonzini#else 3750ae541c0eSPaolo Bonzini#define gen_RSM gen_UD 3751ae541c0eSPaolo Bonzini#endif 3752ae541c0eSPaolo Bonzini 37534228eb8cSPaolo Bonzinistatic void gen_SAHF(DisasContext *s, X86DecodedInsn *decode) 37545e9e21bcSPaolo Bonzini{ 37555e9e21bcSPaolo Bonzini if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) { 37565e9e21bcSPaolo Bonzini return gen_illegal_opcode(s); 37575e9e21bcSPaolo Bonzini } 37585e9e21bcSPaolo Bonzini tcg_gen_shri_tl(s->T0, cpu_regs[R_EAX], 8); 37595e9e21bcSPaolo Bonzini gen_compute_eflags(s); 37605e9e21bcSPaolo Bonzini tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); 37615e9e21bcSPaolo Bonzini tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C); 37625e9e21bcSPaolo Bonzini tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0); 37635e9e21bcSPaolo Bonzini} 37645e9e21bcSPaolo Bonzini 37654228eb8cSPaolo Bonzinistatic void gen_SALC(DisasContext *s, X86DecodedInsn *decode) 3766d7c41a60SPaolo Bonzini{ 3767d7c41a60SPaolo Bonzini gen_compute_eflags_c(s, s->T0); 3768d7c41a60SPaolo Bonzini tcg_gen_neg_tl(s->T0, s->T0); 3769d7c41a60SPaolo Bonzini} 3770d7c41a60SPaolo Bonzini 3771d7c41a60SPaolo Bonzinistatic void gen_shift_dynamic_flags(DisasContext *s, X86DecodedInsn *decode, TCGv count, CCOp cc_op) 3772d7c41a60SPaolo Bonzini{ 3773d7c41a60SPaolo Bonzini TCGv_i32 count32 = tcg_temp_new_i32(); 3774d7c41a60SPaolo Bonzini TCGv_i32 old_cc_op; 3775d7c41a60SPaolo Bonzini 3776d7c41a60SPaolo Bonzini decode->cc_op = CC_OP_DYNAMIC; 3777d7c41a60SPaolo Bonzini decode->cc_op_dynamic = tcg_temp_new_i32(); 3778d7c41a60SPaolo Bonzini 3779d7c41a60SPaolo Bonzini assert(decode->cc_dst == s->T0); 3780*1f7f72bdSRichard Henderson if (cc_op_live(s->cc_op) & USES_CC_DST) { 3781d7c41a60SPaolo Bonzini decode->cc_dst = tcg_temp_new(); 3782d7c41a60SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_EQ, decode->cc_dst, count, tcg_constant_tl(0), 3783d7c41a60SPaolo Bonzini cpu_cc_dst, s->T0); 3784d7c41a60SPaolo Bonzini } 3785d7c41a60SPaolo Bonzini 3786*1f7f72bdSRichard Henderson if (cc_op_live(s->cc_op) & USES_CC_SRC) { 3787d7c41a60SPaolo Bonzini tcg_gen_movcond_tl(TCG_COND_EQ, decode->cc_src, count, tcg_constant_tl(0), 3788d7c41a60SPaolo Bonzini cpu_cc_src, decode->cc_src); 3789d7c41a60SPaolo Bonzini } 3790d7c41a60SPaolo Bonzini 3791d7c41a60SPaolo Bonzini tcg_gen_trunc_tl_i32(count32, count); 3792d7c41a60SPaolo Bonzini if (s->cc_op == CC_OP_DYNAMIC) { 3793d7c41a60SPaolo Bonzini old_cc_op = cpu_cc_op; 3794d7c41a60SPaolo Bonzini } else { 3795d7c41a60SPaolo Bonzini old_cc_op = tcg_constant_i32(s->cc_op); 3796d7c41a60SPaolo Bonzini } 3797d7c41a60SPaolo Bonzini tcg_gen_movcond_i32(TCG_COND_EQ, decode->cc_op_dynamic, count32, tcg_constant_i32(0), 3798d7c41a60SPaolo Bonzini old_cc_op, tcg_constant_i32(cc_op)); 3799d7c41a60SPaolo Bonzini} 3800d7c41a60SPaolo Bonzini 38014228eb8cSPaolo Bonzinistatic void gen_SAR(DisasContext *s, X86DecodedInsn *decode) 3802d7c41a60SPaolo Bonzini{ 3803d7c41a60SPaolo Bonzini bool can_be_zero; 3804d7c41a60SPaolo Bonzini TCGv count; 3805e4e5981dSPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit); 3806d7c41a60SPaolo Bonzini 3807d7c41a60SPaolo Bonzini if (!count) { 3808d7c41a60SPaolo Bonzini return; 3809d7c41a60SPaolo Bonzini } 3810d7c41a60SPaolo Bonzini 3811d7c41a60SPaolo Bonzini decode->cc_dst = s->T0; 3812d7c41a60SPaolo Bonzini decode->cc_src = tcg_temp_new(); 3813d7c41a60SPaolo Bonzini tcg_gen_subi_tl(decode->cc_src, count, 1); 3814d7c41a60SPaolo Bonzini tcg_gen_sar_tl(decode->cc_src, s->T0, decode->cc_src); 3815d7c41a60SPaolo Bonzini tcg_gen_sar_tl(s->T0, s->T0, count); 3816d7c41a60SPaolo Bonzini if (can_be_zero) { 3817d7c41a60SPaolo Bonzini gen_shift_dynamic_flags(s, decode, count, CC_OP_SARB + ot); 3818d7c41a60SPaolo Bonzini } else { 3819d7c41a60SPaolo Bonzini decode->cc_op = CC_OP_SARB + ot; 3820d7c41a60SPaolo Bonzini } 3821d7c41a60SPaolo Bonzini} 3822d7c41a60SPaolo Bonzini 38234228eb8cSPaolo Bonzinistatic void gen_SARX(DisasContext *s, X86DecodedInsn *decode) 38241d0b9261SPaolo Bonzini{ 38251d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 38261d0b9261SPaolo Bonzini int mask; 38271d0b9261SPaolo Bonzini 38281d0b9261SPaolo Bonzini mask = ot == MO_64 ? 63 : 31; 38291d0b9261SPaolo Bonzini tcg_gen_andi_tl(s->T1, s->T1, mask); 38301d0b9261SPaolo Bonzini tcg_gen_sar_tl(s->T0, s->T0, s->T1); 38311d0b9261SPaolo Bonzini} 38321d0b9261SPaolo Bonzini 38334228eb8cSPaolo Bonzinistatic void gen_SBB(DisasContext *s, X86DecodedInsn *decode) 3834cc1d28bdSPaolo Bonzini{ 3835cc1d28bdSPaolo Bonzini MemOp ot = decode->op[0].ot; 3836cc1d28bdSPaolo Bonzini TCGv c_in = tcg_temp_new(); 3837cc1d28bdSPaolo Bonzini 3838cc1d28bdSPaolo Bonzini gen_compute_eflags_c(s, c_in); 3839cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 3840cc1d28bdSPaolo Bonzini tcg_gen_add_tl(s->T0, s->T1, c_in); 3841cc1d28bdSPaolo Bonzini tcg_gen_neg_tl(s->T0, s->T0); 3842cc1d28bdSPaolo Bonzini tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T0, 3843cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 3844cc1d28bdSPaolo Bonzini } else { 3845cc1d28bdSPaolo Bonzini /* 3846cc1d28bdSPaolo Bonzini * TODO: SBB reg, reg could use gen_prepare_eflags_c followed by 3847cc1d28bdSPaolo Bonzini * negsetcond, and CC_OP_SUBB as the cc_op. 3848cc1d28bdSPaolo Bonzini */ 3849cc1d28bdSPaolo Bonzini tcg_gen_sub_tl(s->T0, s->T0, s->T1); 3850cc1d28bdSPaolo Bonzini tcg_gen_sub_tl(s->T0, s->T0, c_in); 3851cc1d28bdSPaolo Bonzini } 3852cc1d28bdSPaolo Bonzini prepare_update3_cc(decode, s, CC_OP_SBBB + ot, c_in); 3853cc1d28bdSPaolo Bonzini} 3854cc1d28bdSPaolo Bonzini 38554228eb8cSPaolo Bonzinistatic void gen_SCAS(DisasContext *s, X86DecodedInsn *decode) 38565e9e21bcSPaolo Bonzini{ 38575e9e21bcSPaolo Bonzini MemOp ot = decode->op[2].ot; 38586605817bSPaolo Bonzini if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { 38596605817bSPaolo Bonzini gen_repz_nz(s, ot, gen_scas); 38605e9e21bcSPaolo Bonzini } else { 38615e9e21bcSPaolo Bonzini gen_scas(s, ot); 38625e9e21bcSPaolo Bonzini } 38635e9e21bcSPaolo Bonzini} 38645e9e21bcSPaolo Bonzini 38654228eb8cSPaolo Bonzinistatic void gen_SETcc(DisasContext *s, X86DecodedInsn *decode) 38662b8046f3SPaolo Bonzini{ 38672b8046f3SPaolo Bonzini gen_setcc1(s, decode->b & 0xf, s->T0); 38682b8046f3SPaolo Bonzini} 38692b8046f3SPaolo Bonzini 3870ea89aa89SPaolo Bonzinistatic void gen_SFENCE(DisasContext *s, X86DecodedInsn *decode) 3871ea89aa89SPaolo Bonzini{ 3872ea89aa89SPaolo Bonzini tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 3873ea89aa89SPaolo Bonzini} 3874ea89aa89SPaolo Bonzini 38754228eb8cSPaolo Bonzinistatic void gen_SHA1NEXTE(DisasContext *s, X86DecodedInsn *decode) 3876e582b629SPaolo Bonzini{ 3877e582b629SPaolo Bonzini gen_helper_sha1nexte(OP_PTR0, OP_PTR1, OP_PTR2); 3878e582b629SPaolo Bonzini} 3879e582b629SPaolo Bonzini 38804228eb8cSPaolo Bonzinistatic void gen_SHA1MSG1(DisasContext *s, X86DecodedInsn *decode) 3881e582b629SPaolo Bonzini{ 3882e582b629SPaolo Bonzini gen_helper_sha1msg1(OP_PTR0, OP_PTR1, OP_PTR2); 3883e582b629SPaolo Bonzini} 3884e582b629SPaolo Bonzini 38854228eb8cSPaolo Bonzinistatic void gen_SHA1MSG2(DisasContext *s, X86DecodedInsn *decode) 3886e582b629SPaolo Bonzini{ 3887e582b629SPaolo Bonzini gen_helper_sha1msg2(OP_PTR0, OP_PTR1, OP_PTR2); 3888e582b629SPaolo Bonzini} 3889e582b629SPaolo Bonzini 38904228eb8cSPaolo Bonzinistatic void gen_SHA1RNDS4(DisasContext *s, X86DecodedInsn *decode) 3891e582b629SPaolo Bonzini{ 3892e582b629SPaolo Bonzini switch(decode->immediate & 3) { 3893e582b629SPaolo Bonzini case 0: 3894e582b629SPaolo Bonzini gen_helper_sha1rnds4_f0(OP_PTR0, OP_PTR0, OP_PTR1); 3895e582b629SPaolo Bonzini break; 3896e582b629SPaolo Bonzini case 1: 3897e582b629SPaolo Bonzini gen_helper_sha1rnds4_f1(OP_PTR0, OP_PTR0, OP_PTR1); 3898e582b629SPaolo Bonzini break; 3899e582b629SPaolo Bonzini case 2: 3900e582b629SPaolo Bonzini gen_helper_sha1rnds4_f2(OP_PTR0, OP_PTR0, OP_PTR1); 3901e582b629SPaolo Bonzini break; 3902e582b629SPaolo Bonzini case 3: 3903e582b629SPaolo Bonzini gen_helper_sha1rnds4_f3(OP_PTR0, OP_PTR0, OP_PTR1); 3904e582b629SPaolo Bonzini break; 3905e582b629SPaolo Bonzini } 3906e582b629SPaolo Bonzini} 3907e582b629SPaolo Bonzini 39084228eb8cSPaolo Bonzinistatic void gen_SHA256MSG1(DisasContext *s, X86DecodedInsn *decode) 3909e582b629SPaolo Bonzini{ 3910e582b629SPaolo Bonzini gen_helper_sha256msg1(OP_PTR0, OP_PTR1, OP_PTR2); 3911e582b629SPaolo Bonzini} 3912e582b629SPaolo Bonzini 39134228eb8cSPaolo Bonzinistatic void gen_SHA256MSG2(DisasContext *s, X86DecodedInsn *decode) 3914e582b629SPaolo Bonzini{ 3915e582b629SPaolo Bonzini gen_helper_sha256msg2(OP_PTR0, OP_PTR1, OP_PTR2); 3916e582b629SPaolo Bonzini} 3917e582b629SPaolo Bonzini 39184228eb8cSPaolo Bonzinistatic void gen_SHA256RNDS2(DisasContext *s, X86DecodedInsn *decode) 3919e582b629SPaolo Bonzini{ 3920e582b629SPaolo Bonzini TCGv_i32 wk0 = tcg_temp_new_i32(); 3921e582b629SPaolo Bonzini TCGv_i32 wk1 = tcg_temp_new_i32(); 3922e582b629SPaolo Bonzini 3923e582b629SPaolo Bonzini tcg_gen_ld_i32(wk0, tcg_env, ZMM_OFFSET(0) + offsetof(ZMMReg, ZMM_L(0))); 3924e582b629SPaolo Bonzini tcg_gen_ld_i32(wk1, tcg_env, ZMM_OFFSET(0) + offsetof(ZMMReg, ZMM_L(1))); 3925e582b629SPaolo Bonzini 3926e582b629SPaolo Bonzini gen_helper_sha256rnds2(OP_PTR0, OP_PTR1, OP_PTR2, wk0, wk1); 3927e582b629SPaolo Bonzini} 3928e582b629SPaolo Bonzini 39294228eb8cSPaolo Bonzinistatic void gen_SHL(DisasContext *s, X86DecodedInsn *decode) 3930d7c41a60SPaolo Bonzini{ 3931d7c41a60SPaolo Bonzini bool can_be_zero; 3932d7c41a60SPaolo Bonzini TCGv count; 3933e4e5981dSPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit); 3934d7c41a60SPaolo Bonzini 3935d7c41a60SPaolo Bonzini if (!count) { 3936d7c41a60SPaolo Bonzini return; 3937d7c41a60SPaolo Bonzini } 3938d7c41a60SPaolo Bonzini 3939d7c41a60SPaolo Bonzini decode->cc_dst = s->T0; 3940d7c41a60SPaolo Bonzini decode->cc_src = tcg_temp_new(); 3941d7c41a60SPaolo Bonzini tcg_gen_subi_tl(decode->cc_src, count, 1); 3942d7c41a60SPaolo Bonzini tcg_gen_shl_tl(decode->cc_src, s->T0, decode->cc_src); 3943d7c41a60SPaolo Bonzini tcg_gen_shl_tl(s->T0, s->T0, count); 3944d7c41a60SPaolo Bonzini if (can_be_zero) { 3945d7c41a60SPaolo Bonzini gen_shift_dynamic_flags(s, decode, count, CC_OP_SHLB + ot); 3946d7c41a60SPaolo Bonzini } else { 3947d7c41a60SPaolo Bonzini decode->cc_op = CC_OP_SHLB + ot; 3948d7c41a60SPaolo Bonzini } 3949d7c41a60SPaolo Bonzini} 3950d7c41a60SPaolo Bonzini 395164769027SPaolo Bonzinistatic void gen_SHLD(DisasContext *s, X86DecodedInsn *decode) 395264769027SPaolo Bonzini{ 395364769027SPaolo Bonzini bool can_be_zero; 395464769027SPaolo Bonzini TCGv count; 395564769027SPaolo Bonzini int unit = decode->e.op3 == X86_TYPE_I ? X86_OP_IMM : X86_OP_INT; 395664769027SPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, unit); 395764769027SPaolo Bonzini 395864769027SPaolo Bonzini if (!count) { 395964769027SPaolo Bonzini return; 396064769027SPaolo Bonzini } 396164769027SPaolo Bonzini 396264769027SPaolo Bonzini decode->cc_dst = s->T0; 396364769027SPaolo Bonzini decode->cc_src = s->tmp0; 396464769027SPaolo Bonzini gen_shiftd_rm_T1(s, ot, false, count); 396564769027SPaolo Bonzini if (can_be_zero) { 396664769027SPaolo Bonzini gen_shift_dynamic_flags(s, decode, count, CC_OP_SHLB + ot); 396764769027SPaolo Bonzini } else { 396864769027SPaolo Bonzini decode->cc_op = CC_OP_SHLB + ot; 396964769027SPaolo Bonzini } 397064769027SPaolo Bonzini} 397164769027SPaolo Bonzini 39724228eb8cSPaolo Bonzinistatic void gen_SHLX(DisasContext *s, X86DecodedInsn *decode) 39731d0b9261SPaolo Bonzini{ 39741d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 39751d0b9261SPaolo Bonzini int mask; 39761d0b9261SPaolo Bonzini 39771d0b9261SPaolo Bonzini mask = ot == MO_64 ? 63 : 31; 39781d0b9261SPaolo Bonzini tcg_gen_andi_tl(s->T1, s->T1, mask); 39791d0b9261SPaolo Bonzini tcg_gen_shl_tl(s->T0, s->T0, s->T1); 39801d0b9261SPaolo Bonzini} 39811d0b9261SPaolo Bonzini 39824228eb8cSPaolo Bonzinistatic void gen_SHR(DisasContext *s, X86DecodedInsn *decode) 3983d7c41a60SPaolo Bonzini{ 3984d7c41a60SPaolo Bonzini bool can_be_zero; 3985d7c41a60SPaolo Bonzini TCGv count; 3986e4e5981dSPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit); 3987d7c41a60SPaolo Bonzini 3988d7c41a60SPaolo Bonzini if (!count) { 3989d7c41a60SPaolo Bonzini return; 3990d7c41a60SPaolo Bonzini } 3991d7c41a60SPaolo Bonzini 3992d7c41a60SPaolo Bonzini decode->cc_dst = s->T0; 3993d7c41a60SPaolo Bonzini decode->cc_src = tcg_temp_new(); 3994d7c41a60SPaolo Bonzini tcg_gen_subi_tl(decode->cc_src, count, 1); 3995d7c41a60SPaolo Bonzini tcg_gen_shr_tl(decode->cc_src, s->T0, decode->cc_src); 3996d7c41a60SPaolo Bonzini tcg_gen_shr_tl(s->T0, s->T0, count); 3997d7c41a60SPaolo Bonzini if (can_be_zero) { 3998d7c41a60SPaolo Bonzini gen_shift_dynamic_flags(s, decode, count, CC_OP_SARB + ot); 3999d7c41a60SPaolo Bonzini } else { 4000d7c41a60SPaolo Bonzini decode->cc_op = CC_OP_SARB + ot; 4001d7c41a60SPaolo Bonzini } 4002d7c41a60SPaolo Bonzini} 4003d7c41a60SPaolo Bonzini 400464769027SPaolo Bonzinistatic void gen_SHRD(DisasContext *s, X86DecodedInsn *decode) 400564769027SPaolo Bonzini{ 400664769027SPaolo Bonzini bool can_be_zero; 400764769027SPaolo Bonzini TCGv count; 400864769027SPaolo Bonzini int unit = decode->e.op3 == X86_TYPE_I ? X86_OP_IMM : X86_OP_INT; 400964769027SPaolo Bonzini MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, unit); 401064769027SPaolo Bonzini 401164769027SPaolo Bonzini if (!count) { 401264769027SPaolo Bonzini return; 401364769027SPaolo Bonzini } 401464769027SPaolo Bonzini 401564769027SPaolo Bonzini decode->cc_dst = s->T0; 401664769027SPaolo Bonzini decode->cc_src = s->tmp0; 401764769027SPaolo Bonzini gen_shiftd_rm_T1(s, ot, true, count); 401864769027SPaolo Bonzini if (can_be_zero) { 401964769027SPaolo Bonzini gen_shift_dynamic_flags(s, decode, count, CC_OP_SARB + ot); 402064769027SPaolo Bonzini } else { 402164769027SPaolo Bonzini decode->cc_op = CC_OP_SARB + ot; 402264769027SPaolo Bonzini } 402364769027SPaolo Bonzini} 402464769027SPaolo Bonzini 40254228eb8cSPaolo Bonzinistatic void gen_SHRX(DisasContext *s, X86DecodedInsn *decode) 40261d0b9261SPaolo Bonzini{ 40271d0b9261SPaolo Bonzini MemOp ot = decode->op[0].ot; 40281d0b9261SPaolo Bonzini int mask; 40291d0b9261SPaolo Bonzini 40301d0b9261SPaolo Bonzini mask = ot == MO_64 ? 63 : 31; 40311d0b9261SPaolo Bonzini tcg_gen_andi_tl(s->T1, s->T1, mask); 40321d0b9261SPaolo Bonzini tcg_gen_shr_tl(s->T0, s->T0, s->T1); 40331d0b9261SPaolo Bonzini} 403403b45880SPaolo Bonzini 40354228eb8cSPaolo Bonzinistatic void gen_STC(DisasContext *s, X86DecodedInsn *decode) 4036d7c41a60SPaolo Bonzini{ 4037d7c41a60SPaolo Bonzini gen_compute_eflags(s); 4038d7c41a60SPaolo Bonzini tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); 4039d7c41a60SPaolo Bonzini} 4040d7c41a60SPaolo Bonzini 40414228eb8cSPaolo Bonzinistatic void gen_STD(DisasContext *s, X86DecodedInsn *decode) 4042d7c41a60SPaolo Bonzini{ 4043d7c41a60SPaolo Bonzini tcg_gen_st_i32(tcg_constant_i32(-1), tcg_env, offsetof(CPUX86State, df)); 4044d7c41a60SPaolo Bonzini} 4045d7c41a60SPaolo Bonzini 40464228eb8cSPaolo Bonzinistatic void gen_STI(DisasContext *s, X86DecodedInsn *decode) 4047d7c41a60SPaolo Bonzini{ 4048d7c41a60SPaolo Bonzini gen_set_eflags(s, IF_MASK); 40492512f786SPaolo Bonzini s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ; 4050d7c41a60SPaolo Bonzini} 4051d7c41a60SPaolo Bonzini 40524228eb8cSPaolo Bonzinistatic void gen_VAESKEYGEN(DisasContext *s, X86DecodedInsn *decode) 405379068477SPaolo Bonzini{ 405479068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 405579068477SPaolo Bonzini assert(!s->vex_l); 4056ad75a51eSRichard Henderson gen_helper_aeskeygenassist_xmm(tcg_env, OP_PTR0, OP_PTR1, imm); 405779068477SPaolo Bonzini} 405879068477SPaolo Bonzini 40594228eb8cSPaolo Bonzinistatic void gen_STMXCSR(DisasContext *s, X86DecodedInsn *decode) 406057f6bba0SPaolo Bonzini{ 4061ad75a51eSRichard Henderson gen_helper_update_mxcsr(tcg_env); 4062ad75a51eSRichard Henderson tcg_gen_ld32u_tl(s->T0, tcg_env, offsetof(CPUX86State, mxcsr)); 406357f6bba0SPaolo Bonzini} 406457f6bba0SPaolo Bonzini 40654228eb8cSPaolo Bonzinistatic void gen_STOS(DisasContext *s, X86DecodedInsn *decode) 40665e9e21bcSPaolo Bonzini{ 40675e9e21bcSPaolo Bonzini MemOp ot = decode->op[1].ot; 40685e9e21bcSPaolo Bonzini if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { 40696605817bSPaolo Bonzini gen_repz(s, ot, gen_stos); 40705e9e21bcSPaolo Bonzini } else { 40715e9e21bcSPaolo Bonzini gen_stos(s, ot); 40725e9e21bcSPaolo Bonzini } 40735e9e21bcSPaolo Bonzini} 40745e9e21bcSPaolo Bonzini 40754228eb8cSPaolo Bonzinistatic void gen_SUB(DisasContext *s, X86DecodedInsn *decode) 4076cc1d28bdSPaolo Bonzini{ 4077cc1d28bdSPaolo Bonzini MemOp ot = decode->op[1].ot; 4078cc1d28bdSPaolo Bonzini 4079cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 4080cc1d28bdSPaolo Bonzini tcg_gen_neg_tl(s->T0, s->T1); 4081cc1d28bdSPaolo Bonzini tcg_gen_atomic_fetch_add_tl(s->cc_srcT, s->A0, s->T0, 4082cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 4083cc1d28bdSPaolo Bonzini tcg_gen_sub_tl(s->T0, s->cc_srcT, s->T1); 4084cc1d28bdSPaolo Bonzini } else { 4085cc1d28bdSPaolo Bonzini tcg_gen_mov_tl(s->cc_srcT, s->T0); 4086cc1d28bdSPaolo Bonzini tcg_gen_sub_tl(s->T0, s->T0, s->T1); 4087cc1d28bdSPaolo Bonzini } 4088cc1d28bdSPaolo Bonzini prepare_update2_cc(decode, s, CC_OP_SUBB + ot); 4089cc1d28bdSPaolo Bonzini} 4090cc1d28bdSPaolo Bonzini 4091ae541c0eSPaolo Bonzinistatic void gen_SYSCALL(DisasContext *s, X86DecodedInsn *decode) 4092ae541c0eSPaolo Bonzini{ 4093ae541c0eSPaolo Bonzini gen_update_cc_op(s); 4094ae541c0eSPaolo Bonzini gen_update_eip_cur(s); 4095ae541c0eSPaolo Bonzini gen_helper_syscall(tcg_env, cur_insn_len_i32(s)); 4096ae541c0eSPaolo Bonzini if (LMA(s)) { 4097ae541c0eSPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 4098ae541c0eSPaolo Bonzini } 4099ae541c0eSPaolo Bonzini 4100ae541c0eSPaolo Bonzini /* 4101ae541c0eSPaolo Bonzini * TF handling for the syscall insn is different. The TF bit is checked 4102ae541c0eSPaolo Bonzini * after the syscall insn completes. This allows #DB to not be 4103ae541c0eSPaolo Bonzini * generated after one has entered CPL0 if TF is set in FMASK. 4104ae541c0eSPaolo Bonzini */ 4105ae541c0eSPaolo Bonzini s->base.is_jmp = DISAS_EOB_RECHECK_TF; 4106ae541c0eSPaolo Bonzini} 4107ae541c0eSPaolo Bonzini 4108ae541c0eSPaolo Bonzinistatic void gen_SYSENTER(DisasContext *s, X86DecodedInsn *decode) 4109ae541c0eSPaolo Bonzini{ 4110ae541c0eSPaolo Bonzini gen_helper_sysenter(tcg_env); 4111ae541c0eSPaolo Bonzini s->base.is_jmp = DISAS_EOB_ONLY; 4112ae541c0eSPaolo Bonzini} 4113ae541c0eSPaolo Bonzini 4114ae541c0eSPaolo Bonzinistatic void gen_SYSEXIT(DisasContext *s, X86DecodedInsn *decode) 4115ae541c0eSPaolo Bonzini{ 4116ae541c0eSPaolo Bonzini gen_helper_sysexit(tcg_env, tcg_constant_i32(s->dflag - 1)); 4117ae541c0eSPaolo Bonzini s->base.is_jmp = DISAS_EOB_ONLY; 4118ae541c0eSPaolo Bonzini} 4119ae541c0eSPaolo Bonzini 4120ae541c0eSPaolo Bonzinistatic void gen_SYSRET(DisasContext *s, X86DecodedInsn *decode) 4121ae541c0eSPaolo Bonzini{ 4122ae541c0eSPaolo Bonzini gen_helper_sysret(tcg_env, tcg_constant_i32(s->dflag - 1)); 4123ae541c0eSPaolo Bonzini if (LMA(s)) { 4124ae541c0eSPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 4125ae541c0eSPaolo Bonzini } 4126ae541c0eSPaolo Bonzini 4127ae541c0eSPaolo Bonzini /* 4128ae541c0eSPaolo Bonzini * TF handling for the sysret insn is different. The TF bit is checked 4129ae541c0eSPaolo Bonzini * after the sysret insn completes. This allows #DB to be 4130ae541c0eSPaolo Bonzini * generated "as if" the syscall insn in userspace has just 4131ae541c0eSPaolo Bonzini * completed. 4132ae541c0eSPaolo Bonzini */ 4133ae541c0eSPaolo Bonzini s->base.is_jmp = DISAS_EOB_RECHECK_TF; 4134ae541c0eSPaolo Bonzini} 4135ae541c0eSPaolo Bonzini 413611ffaf8cSPaolo Bonzinistatic void gen_TZCNT(DisasContext *s, X86DecodedInsn *decode) 413711ffaf8cSPaolo Bonzini{ 413811ffaf8cSPaolo Bonzini MemOp ot = decode->op[0].ot; 413911ffaf8cSPaolo Bonzini 414011ffaf8cSPaolo Bonzini /* C bit (cc_src) is defined related to the input. */ 414111ffaf8cSPaolo Bonzini decode->cc_src = tcg_temp_new(); 414211ffaf8cSPaolo Bonzini decode->cc_dst = s->T0; 414311ffaf8cSPaolo Bonzini decode->cc_op = CC_OP_BMILGB + ot; 414411ffaf8cSPaolo Bonzini tcg_gen_mov_tl(decode->cc_src, s->T0); 414511ffaf8cSPaolo Bonzini 414611ffaf8cSPaolo Bonzini /* A zero input returns the operand size. */ 414711ffaf8cSPaolo Bonzini tcg_gen_ctzi_tl(s->T0, s->T0, 8 << ot); 414811ffaf8cSPaolo Bonzini} 414911ffaf8cSPaolo Bonzini 41504228eb8cSPaolo Bonzinistatic void gen_UD(DisasContext *s, X86DecodedInsn *decode) 41513fabbe0bSPaolo Bonzini{ 41523fabbe0bSPaolo Bonzini gen_illegal_opcode(s); 41533fabbe0bSPaolo Bonzini} 41543fabbe0bSPaolo Bonzini 41554228eb8cSPaolo Bonzinistatic void gen_VAESIMC(DisasContext *s, X86DecodedInsn *decode) 415616fc5726SPaolo Bonzini{ 415716fc5726SPaolo Bonzini assert(!s->vex_l); 4158ad75a51eSRichard Henderson gen_helper_aesimc_xmm(tcg_env, OP_PTR0, OP_PTR2); 415916fc5726SPaolo Bonzini} 416016fc5726SPaolo Bonzini 4161aba2b8ecSPaolo Bonzini/* 4162aba2b8ecSPaolo Bonzini * 00 = v*ps Vps, Hps, Wpd 4163aba2b8ecSPaolo Bonzini * 66 = v*pd Vpd, Hpd, Wps 4164aba2b8ecSPaolo Bonzini * f3 = v*ss Vss, Hss, Wps 4165aba2b8ecSPaolo Bonzini * f2 = v*sd Vsd, Hsd, Wps 4166aba2b8ecSPaolo Bonzini */ 4167aba2b8ecSPaolo Bonzini#define SSE_CMP(x) { \ 4168aba2b8ecSPaolo Bonzini gen_helper_ ## x ## ps ## _xmm, gen_helper_ ## x ## pd ## _xmm, \ 4169aba2b8ecSPaolo Bonzini gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, \ 4170aba2b8ecSPaolo Bonzini gen_helper_ ## x ## ps ## _ymm, gen_helper_ ## x ## pd ## _ymm} 4171aba2b8ecSPaolo Bonzinistatic const SSEFunc_0_eppp gen_helper_cmp_funcs[32][6] = { 4172aba2b8ecSPaolo Bonzini SSE_CMP(cmpeq), 4173aba2b8ecSPaolo Bonzini SSE_CMP(cmplt), 4174aba2b8ecSPaolo Bonzini SSE_CMP(cmple), 4175aba2b8ecSPaolo Bonzini SSE_CMP(cmpunord), 4176aba2b8ecSPaolo Bonzini SSE_CMP(cmpneq), 4177aba2b8ecSPaolo Bonzini SSE_CMP(cmpnlt), 4178aba2b8ecSPaolo Bonzini SSE_CMP(cmpnle), 4179aba2b8ecSPaolo Bonzini SSE_CMP(cmpord), 4180aba2b8ecSPaolo Bonzini 4181aba2b8ecSPaolo Bonzini SSE_CMP(cmpequ), 4182aba2b8ecSPaolo Bonzini SSE_CMP(cmpnge), 4183aba2b8ecSPaolo Bonzini SSE_CMP(cmpngt), 4184aba2b8ecSPaolo Bonzini SSE_CMP(cmpfalse), 4185aba2b8ecSPaolo Bonzini SSE_CMP(cmpnequ), 4186aba2b8ecSPaolo Bonzini SSE_CMP(cmpge), 4187aba2b8ecSPaolo Bonzini SSE_CMP(cmpgt), 4188aba2b8ecSPaolo Bonzini SSE_CMP(cmptrue), 4189aba2b8ecSPaolo Bonzini 4190aba2b8ecSPaolo Bonzini SSE_CMP(cmpeqs), 4191aba2b8ecSPaolo Bonzini SSE_CMP(cmpltq), 4192aba2b8ecSPaolo Bonzini SSE_CMP(cmpleq), 4193aba2b8ecSPaolo Bonzini SSE_CMP(cmpunords), 4194aba2b8ecSPaolo Bonzini SSE_CMP(cmpneqq), 4195aba2b8ecSPaolo Bonzini SSE_CMP(cmpnltq), 4196aba2b8ecSPaolo Bonzini SSE_CMP(cmpnleq), 4197aba2b8ecSPaolo Bonzini SSE_CMP(cmpords), 4198aba2b8ecSPaolo Bonzini 4199aba2b8ecSPaolo Bonzini SSE_CMP(cmpequs), 4200aba2b8ecSPaolo Bonzini SSE_CMP(cmpngeq), 4201aba2b8ecSPaolo Bonzini SSE_CMP(cmpngtq), 4202aba2b8ecSPaolo Bonzini SSE_CMP(cmpfalses), 4203aba2b8ecSPaolo Bonzini SSE_CMP(cmpnequs), 4204aba2b8ecSPaolo Bonzini SSE_CMP(cmpgeq), 4205aba2b8ecSPaolo Bonzini SSE_CMP(cmpgtq), 4206aba2b8ecSPaolo Bonzini SSE_CMP(cmptrues), 4207aba2b8ecSPaolo Bonzini}; 4208aba2b8ecSPaolo Bonzini#undef SSE_CMP 4209aba2b8ecSPaolo Bonzini 42104228eb8cSPaolo Bonzinistatic void gen_VCMP(DisasContext *s, X86DecodedInsn *decode) 4211aba2b8ecSPaolo Bonzini{ 4212aba2b8ecSPaolo Bonzini int index = decode->immediate & (s->prefix & PREFIX_VEX ? 31 : 7); 4213aba2b8ecSPaolo Bonzini int b = 4214aba2b8ecSPaolo Bonzini s->prefix & PREFIX_REPZ ? 2 /* ss */ : 4215aba2b8ecSPaolo Bonzini s->prefix & PREFIX_REPNZ ? 3 /* sd */ : 4216aba2b8ecSPaolo Bonzini !!(s->prefix & PREFIX_DATA) /* pd */ + (s->vex_l << 2); 4217aba2b8ecSPaolo Bonzini 4218ad75a51eSRichard Henderson gen_helper_cmp_funcs[index][b](tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 4219aba2b8ecSPaolo Bonzini} 4220aba2b8ecSPaolo Bonzini 42214228eb8cSPaolo Bonzinistatic void gen_VCOMI(DisasContext *s, X86DecodedInsn *decode) 4222f8d19eecSPaolo Bonzini{ 4223f8d19eecSPaolo Bonzini SSEFunc_0_epp fn; 4224f8d19eecSPaolo Bonzini fn = s->prefix & PREFIX_DATA ? gen_helper_comisd : gen_helper_comiss; 4225ad75a51eSRichard Henderson fn(tcg_env, OP_PTR1, OP_PTR2); 4226abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 4227f8d19eecSPaolo Bonzini} 4228f8d19eecSPaolo Bonzini 42294228eb8cSPaolo Bonzinistatic void gen_VCVTPD2PS(DisasContext *s, X86DecodedInsn *decode) 423003b45880SPaolo Bonzini{ 4231abd41884SPaolo Bonzini if (s->vex_l) { 4232ad75a51eSRichard Henderson gen_helper_cvtpd2ps_ymm(tcg_env, OP_PTR0, OP_PTR2); 4233abd41884SPaolo Bonzini } else { 4234ad75a51eSRichard Henderson gen_helper_cvtpd2ps_xmm(tcg_env, OP_PTR0, OP_PTR2); 4235abd41884SPaolo Bonzini } 4236abd41884SPaolo Bonzini} 4237abd41884SPaolo Bonzini 42384228eb8cSPaolo Bonzinistatic void gen_VCVTPS2PD(DisasContext *s, X86DecodedInsn *decode) 4239abd41884SPaolo Bonzini{ 4240abd41884SPaolo Bonzini if (s->vex_l) { 4241ad75a51eSRichard Henderson gen_helper_cvtps2pd_ymm(tcg_env, OP_PTR0, OP_PTR2); 4242abd41884SPaolo Bonzini } else { 4243ad75a51eSRichard Henderson gen_helper_cvtps2pd_xmm(tcg_env, OP_PTR0, OP_PTR2); 4244abd41884SPaolo Bonzini } 424503b45880SPaolo Bonzini} 4246ce4fcb94SPaolo Bonzini 42474228eb8cSPaolo Bonzinistatic void gen_VCVTPS2PH(DisasContext *s, X86DecodedInsn *decode) 4248cf5ec664SPaolo Bonzini{ 42494228eb8cSPaolo Bonzini gen_unary_imm_fp_sse(s, decode, 4250cf5ec664SPaolo Bonzini gen_helper_cvtps2ph_xmm, 4251cf5ec664SPaolo Bonzini gen_helper_cvtps2ph_ymm); 4252cf5ec664SPaolo Bonzini /* 4253cf5ec664SPaolo Bonzini * VCVTPS2PH is the only instruction that performs an operation on a 4254cf5ec664SPaolo Bonzini * register source and then *stores* into memory. 4255cf5ec664SPaolo Bonzini */ 4256cf5ec664SPaolo Bonzini if (decode->op[0].has_ea) { 4257cf5ec664SPaolo Bonzini gen_store_sse(s, decode, decode->op[0].offset); 4258cf5ec664SPaolo Bonzini } 4259cf5ec664SPaolo Bonzini} 4260cf5ec664SPaolo Bonzini 42614228eb8cSPaolo Bonzinistatic void gen_VCVTSD2SS(DisasContext *s, X86DecodedInsn *decode) 4262abd41884SPaolo Bonzini{ 4263ad75a51eSRichard Henderson gen_helper_cvtsd2ss(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 4264abd41884SPaolo Bonzini} 4265abd41884SPaolo Bonzini 42664228eb8cSPaolo Bonzinistatic void gen_VCVTSS2SD(DisasContext *s, X86DecodedInsn *decode) 4267abd41884SPaolo Bonzini{ 4268ad75a51eSRichard Henderson gen_helper_cvtss2sd(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2); 4269abd41884SPaolo Bonzini} 4270abd41884SPaolo Bonzini 42714228eb8cSPaolo Bonzinistatic void gen_VCVTSI2Sx(DisasContext *s, X86DecodedInsn *decode) 4272f8d19eecSPaolo Bonzini{ 4273f8d19eecSPaolo Bonzini int vec_len = vector_len(s, decode); 4274f8d19eecSPaolo Bonzini TCGv_i32 in; 4275f8d19eecSPaolo Bonzini 4276f8d19eecSPaolo Bonzini tcg_gen_gvec_mov(MO_64, decode->op[0].offset, decode->op[1].offset, vec_len, vec_len); 4277f8d19eecSPaolo Bonzini 4278f8d19eecSPaolo Bonzini#ifdef TARGET_X86_64 4279f8d19eecSPaolo Bonzini MemOp ot = decode->op[2].ot; 4280f8d19eecSPaolo Bonzini if (ot == MO_64) { 4281f8d19eecSPaolo Bonzini if (s->prefix & PREFIX_REPNZ) { 4282ad75a51eSRichard Henderson gen_helper_cvtsq2sd(tcg_env, OP_PTR0, s->T1); 4283f8d19eecSPaolo Bonzini } else { 4284ad75a51eSRichard Henderson gen_helper_cvtsq2ss(tcg_env, OP_PTR0, s->T1); 4285f8d19eecSPaolo Bonzini } 4286f8d19eecSPaolo Bonzini return; 4287f8d19eecSPaolo Bonzini } 4288f8d19eecSPaolo Bonzini in = s->tmp2_i32; 4289f8d19eecSPaolo Bonzini tcg_gen_trunc_tl_i32(in, s->T1); 4290f8d19eecSPaolo Bonzini#else 4291f8d19eecSPaolo Bonzini in = s->T1; 4292f8d19eecSPaolo Bonzini#endif 4293f8d19eecSPaolo Bonzini 4294f8d19eecSPaolo Bonzini if (s->prefix & PREFIX_REPNZ) { 4295ad75a51eSRichard Henderson gen_helper_cvtsi2sd(tcg_env, OP_PTR0, in); 4296f8d19eecSPaolo Bonzini } else { 4297ad75a51eSRichard Henderson gen_helper_cvtsi2ss(tcg_env, OP_PTR0, in); 4298f8d19eecSPaolo Bonzini } 4299f8d19eecSPaolo Bonzini} 4300f8d19eecSPaolo Bonzini 43014228eb8cSPaolo Bonzinistatic inline void gen_VCVTtSx2SI(DisasContext *s, X86DecodedInsn *decode, 4302f8d19eecSPaolo Bonzini SSEFunc_i_ep ss2si, SSEFunc_l_ep ss2sq, 4303f8d19eecSPaolo Bonzini SSEFunc_i_ep sd2si, SSEFunc_l_ep sd2sq) 4304f8d19eecSPaolo Bonzini{ 4305f8d19eecSPaolo Bonzini TCGv_i32 out; 4306f8d19eecSPaolo Bonzini 4307f8d19eecSPaolo Bonzini#ifdef TARGET_X86_64 4308f8d19eecSPaolo Bonzini MemOp ot = decode->op[0].ot; 4309f8d19eecSPaolo Bonzini if (ot == MO_64) { 4310f8d19eecSPaolo Bonzini if (s->prefix & PREFIX_REPNZ) { 4311ad75a51eSRichard Henderson sd2sq(s->T0, tcg_env, OP_PTR2); 4312f8d19eecSPaolo Bonzini } else { 4313ad75a51eSRichard Henderson ss2sq(s->T0, tcg_env, OP_PTR2); 4314f8d19eecSPaolo Bonzini } 4315f8d19eecSPaolo Bonzini return; 4316f8d19eecSPaolo Bonzini } 4317f8d19eecSPaolo Bonzini 4318f8d19eecSPaolo Bonzini out = s->tmp2_i32; 4319f8d19eecSPaolo Bonzini#else 4320f8d19eecSPaolo Bonzini out = s->T0; 4321f8d19eecSPaolo Bonzini#endif 4322f8d19eecSPaolo Bonzini if (s->prefix & PREFIX_REPNZ) { 4323ad75a51eSRichard Henderson sd2si(out, tcg_env, OP_PTR2); 4324f8d19eecSPaolo Bonzini } else { 4325ad75a51eSRichard Henderson ss2si(out, tcg_env, OP_PTR2); 4326f8d19eecSPaolo Bonzini } 4327f8d19eecSPaolo Bonzini#ifdef TARGET_X86_64 4328f8d19eecSPaolo Bonzini tcg_gen_extu_i32_tl(s->T0, out); 4329f8d19eecSPaolo Bonzini#endif 4330f8d19eecSPaolo Bonzini} 4331f8d19eecSPaolo Bonzini 4332f8d19eecSPaolo Bonzini#ifndef TARGET_X86_64 4333f8d19eecSPaolo Bonzini#define gen_helper_cvtss2sq NULL 4334f8d19eecSPaolo Bonzini#define gen_helper_cvtsd2sq NULL 4335f8d19eecSPaolo Bonzini#define gen_helper_cvttss2sq NULL 4336f8d19eecSPaolo Bonzini#define gen_helper_cvttsd2sq NULL 4337f8d19eecSPaolo Bonzini#endif 4338f8d19eecSPaolo Bonzini 43394228eb8cSPaolo Bonzinistatic void gen_VCVTSx2SI(DisasContext *s, X86DecodedInsn *decode) 4340f8d19eecSPaolo Bonzini{ 43414228eb8cSPaolo Bonzini gen_VCVTtSx2SI(s, decode, 4342f8d19eecSPaolo Bonzini gen_helper_cvtss2si, gen_helper_cvtss2sq, 4343f8d19eecSPaolo Bonzini gen_helper_cvtsd2si, gen_helper_cvtsd2sq); 4344f8d19eecSPaolo Bonzini} 4345f8d19eecSPaolo Bonzini 43464228eb8cSPaolo Bonzinistatic void gen_VCVTTSx2SI(DisasContext *s, X86DecodedInsn *decode) 4347f8d19eecSPaolo Bonzini{ 43484228eb8cSPaolo Bonzini gen_VCVTtSx2SI(s, decode, 4349f8d19eecSPaolo Bonzini gen_helper_cvttss2si, gen_helper_cvttss2sq, 4350f8d19eecSPaolo Bonzini gen_helper_cvttsd2si, gen_helper_cvttsd2sq); 4351f8d19eecSPaolo Bonzini} 4352f8d19eecSPaolo Bonzini 43534228eb8cSPaolo Bonzinistatic void gen_VEXTRACTx128(DisasContext *s, X86DecodedInsn *decode) 435479068477SPaolo Bonzini{ 435579068477SPaolo Bonzini int mask = decode->immediate & 1; 435679068477SPaolo Bonzini int src_ofs = vector_elem_offset(&decode->op[1], MO_128, mask); 435779068477SPaolo Bonzini if (decode->op[0].has_ea) { 435879068477SPaolo Bonzini /* VEX-only instruction, no alignment requirements. */ 435979068477SPaolo Bonzini gen_sto_env_A0(s, src_ofs, false); 436079068477SPaolo Bonzini } else { 436179068477SPaolo Bonzini tcg_gen_gvec_mov(MO_64, decode->op[0].offset, src_ofs, 16, 16); 436279068477SPaolo Bonzini } 436379068477SPaolo Bonzini} 436479068477SPaolo Bonzini 43654228eb8cSPaolo Bonzinistatic void gen_VEXTRACTPS(DisasContext *s, X86DecodedInsn *decode) 436679068477SPaolo Bonzini{ 43674228eb8cSPaolo Bonzini gen_pextr(s, decode, MO_32); 436879068477SPaolo Bonzini} 436979068477SPaolo Bonzini 43704228eb8cSPaolo Bonzinistatic void gen_vinsertps(DisasContext *s, X86DecodedInsn *decode) 437179068477SPaolo Bonzini{ 437279068477SPaolo Bonzini int val = decode->immediate; 437379068477SPaolo Bonzini int dest_word = (val >> 4) & 3; 437479068477SPaolo Bonzini int new_mask = (val & 15) | (1 << dest_word); 437579068477SPaolo Bonzini int vec_len = 16; 437679068477SPaolo Bonzini 437779068477SPaolo Bonzini assert(!s->vex_l); 437879068477SPaolo Bonzini 437979068477SPaolo Bonzini if (new_mask == 15) { 438079068477SPaolo Bonzini /* All zeroes except possibly for the inserted element */ 438179068477SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 438279068477SPaolo Bonzini } else if (decode->op[1].offset != decode->op[0].offset) { 438379068477SPaolo Bonzini gen_store_sse(s, decode, decode->op[1].offset); 438479068477SPaolo Bonzini } 438579068477SPaolo Bonzini 438679068477SPaolo Bonzini if (new_mask != (val & 15)) { 4387ad75a51eSRichard Henderson tcg_gen_st_i32(s->tmp2_i32, tcg_env, 438879068477SPaolo Bonzini vector_elem_offset(&decode->op[0], MO_32, dest_word)); 438979068477SPaolo Bonzini } 439079068477SPaolo Bonzini 439179068477SPaolo Bonzini if (new_mask != 15) { 439279068477SPaolo Bonzini TCGv_i32 zero = tcg_constant_i32(0); /* float32_zero */ 439379068477SPaolo Bonzini int i; 439479068477SPaolo Bonzini for (i = 0; i < 4; i++) { 439579068477SPaolo Bonzini if ((val >> i) & 1) { 4396ad75a51eSRichard Henderson tcg_gen_st_i32(zero, tcg_env, 439779068477SPaolo Bonzini vector_elem_offset(&decode->op[0], MO_32, i)); 439879068477SPaolo Bonzini } 439979068477SPaolo Bonzini } 440079068477SPaolo Bonzini } 440179068477SPaolo Bonzini} 440279068477SPaolo Bonzini 44034228eb8cSPaolo Bonzinistatic void gen_VINSERTPS_r(DisasContext *s, X86DecodedInsn *decode) 440479068477SPaolo Bonzini{ 440579068477SPaolo Bonzini int val = decode->immediate; 4406ad75a51eSRichard Henderson tcg_gen_ld_i32(s->tmp2_i32, tcg_env, 440779068477SPaolo Bonzini vector_elem_offset(&decode->op[2], MO_32, (val >> 6) & 3)); 44084228eb8cSPaolo Bonzini gen_vinsertps(s, decode); 440979068477SPaolo Bonzini} 441079068477SPaolo Bonzini 44114228eb8cSPaolo Bonzinistatic void gen_VINSERTPS_m(DisasContext *s, X86DecodedInsn *decode) 441279068477SPaolo Bonzini{ 441379068477SPaolo Bonzini tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); 44144228eb8cSPaolo Bonzini gen_vinsertps(s, decode); 441579068477SPaolo Bonzini} 441679068477SPaolo Bonzini 44174228eb8cSPaolo Bonzinistatic void gen_VINSERTx128(DisasContext *s, X86DecodedInsn *decode) 441879068477SPaolo Bonzini{ 441979068477SPaolo Bonzini int mask = decode->immediate & 1; 442079068477SPaolo Bonzini tcg_gen_gvec_mov(MO_64, 442179068477SPaolo Bonzini decode->op[0].offset + offsetof(YMMReg, YMM_X(mask)), 442279068477SPaolo Bonzini decode->op[2].offset + offsetof(YMMReg, YMM_X(0)), 16, 16); 442379068477SPaolo Bonzini tcg_gen_gvec_mov(MO_64, 442479068477SPaolo Bonzini decode->op[0].offset + offsetof(YMMReg, YMM_X(!mask)), 442579068477SPaolo Bonzini decode->op[1].offset + offsetof(YMMReg, YMM_X(!mask)), 16, 16); 442679068477SPaolo Bonzini} 442779068477SPaolo Bonzini 44284228eb8cSPaolo Bonzinistatic inline void gen_maskmov(DisasContext *s, X86DecodedInsn *decode, 442916fc5726SPaolo Bonzini SSEFunc_0_eppt xmm, SSEFunc_0_eppt ymm) 443016fc5726SPaolo Bonzini{ 443116fc5726SPaolo Bonzini if (!s->vex_l) { 4432ad75a51eSRichard Henderson xmm(tcg_env, OP_PTR2, OP_PTR1, s->A0); 443316fc5726SPaolo Bonzini } else { 4434ad75a51eSRichard Henderson ymm(tcg_env, OP_PTR2, OP_PTR1, s->A0); 443516fc5726SPaolo Bonzini } 443616fc5726SPaolo Bonzini} 443716fc5726SPaolo Bonzini 44384228eb8cSPaolo Bonzinistatic void gen_VMASKMOVPD_st(DisasContext *s, X86DecodedInsn *decode) 443916fc5726SPaolo Bonzini{ 44404228eb8cSPaolo Bonzini gen_maskmov(s, decode, gen_helper_vpmaskmovq_st_xmm, gen_helper_vpmaskmovq_st_ymm); 444116fc5726SPaolo Bonzini} 444216fc5726SPaolo Bonzini 44434228eb8cSPaolo Bonzinistatic void gen_VMASKMOVPS_st(DisasContext *s, X86DecodedInsn *decode) 444416fc5726SPaolo Bonzini{ 44454228eb8cSPaolo Bonzini gen_maskmov(s, decode, gen_helper_vpmaskmovd_st_xmm, gen_helper_vpmaskmovd_st_ymm); 444616fc5726SPaolo Bonzini} 444716fc5726SPaolo Bonzini 44484228eb8cSPaolo Bonzinistatic void gen_VMOVHPx_ld(DisasContext *s, X86DecodedInsn *decode) 44497170a17eSPaolo Bonzini{ 44507170a17eSPaolo Bonzini gen_ldq_env_A0(s, decode->op[0].offset + offsetof(XMMReg, XMM_Q(1))); 44517170a17eSPaolo Bonzini if (decode->op[0].offset != decode->op[1].offset) { 4452ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[1].offset + offsetof(XMMReg, XMM_Q(0))); 4453ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(0))); 44547170a17eSPaolo Bonzini } 44557170a17eSPaolo Bonzini} 44567170a17eSPaolo Bonzini 44574228eb8cSPaolo Bonzinistatic void gen_VMOVHPx_st(DisasContext *s, X86DecodedInsn *decode) 44587170a17eSPaolo Bonzini{ 44597170a17eSPaolo Bonzini gen_stq_env_A0(s, decode->op[2].offset + offsetof(XMMReg, XMM_Q(1))); 44607170a17eSPaolo Bonzini} 44617170a17eSPaolo Bonzini 44624228eb8cSPaolo Bonzinistatic void gen_VMOVHPx(DisasContext *s, X86DecodedInsn *decode) 44637170a17eSPaolo Bonzini{ 44647170a17eSPaolo Bonzini if (decode->op[0].offset != decode->op[2].offset) { 4465ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[2].offset + offsetof(XMMReg, XMM_Q(1))); 4466ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(1))); 44677170a17eSPaolo Bonzini } 44687170a17eSPaolo Bonzini if (decode->op[0].offset != decode->op[1].offset) { 4469ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[1].offset + offsetof(XMMReg, XMM_Q(0))); 4470ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(0))); 44717170a17eSPaolo Bonzini } 44727170a17eSPaolo Bonzini} 44737170a17eSPaolo Bonzini 44744228eb8cSPaolo Bonzinistatic void gen_VMOVHLPS(DisasContext *s, X86DecodedInsn *decode) 44757170a17eSPaolo Bonzini{ 4476ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[2].offset + offsetof(XMMReg, XMM_Q(1))); 4477ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(0))); 44787170a17eSPaolo Bonzini if (decode->op[0].offset != decode->op[1].offset) { 4479ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[1].offset + offsetof(XMMReg, XMM_Q(1))); 4480ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(1))); 44817170a17eSPaolo Bonzini } 44827170a17eSPaolo Bonzini} 44837170a17eSPaolo Bonzini 44844228eb8cSPaolo Bonzinistatic void gen_VMOVLHPS(DisasContext *s, X86DecodedInsn *decode) 44857170a17eSPaolo Bonzini{ 4486ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[2].offset); 4487ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(1))); 44887170a17eSPaolo Bonzini if (decode->op[0].offset != decode->op[1].offset) { 4489ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[1].offset + offsetof(XMMReg, XMM_Q(0))); 4490ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(0))); 44917170a17eSPaolo Bonzini } 44927170a17eSPaolo Bonzini} 44937170a17eSPaolo Bonzini 44947170a17eSPaolo Bonzini/* 44957170a17eSPaolo Bonzini * Note that MOVLPx supports 256-bit operation unlike MOVHLPx, MOVLHPx, MOXHPx. 44967170a17eSPaolo Bonzini * Use a gvec move to move everything above the bottom 64 bits. 44977170a17eSPaolo Bonzini */ 44987170a17eSPaolo Bonzini 44994228eb8cSPaolo Bonzinistatic void gen_VMOVLPx(DisasContext *s, X86DecodedInsn *decode) 45007170a17eSPaolo Bonzini{ 45017170a17eSPaolo Bonzini int vec_len = vector_len(s, decode); 45027170a17eSPaolo Bonzini 4503ad75a51eSRichard Henderson tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[2].offset + offsetof(XMMReg, XMM_Q(0))); 45047170a17eSPaolo Bonzini tcg_gen_gvec_mov(MO_64, decode->op[0].offset, decode->op[1].offset, vec_len, vec_len); 4505ad75a51eSRichard Henderson tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(0))); 45067170a17eSPaolo Bonzini} 45077170a17eSPaolo Bonzini 45084228eb8cSPaolo Bonzinistatic void gen_VMOVLPx_ld(DisasContext *s, X86DecodedInsn *decode) 45097170a17eSPaolo Bonzini{ 45107170a17eSPaolo Bonzini int vec_len = vector_len(s, decode); 45117170a17eSPaolo Bonzini 45127170a17eSPaolo Bonzini tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ); 45137170a17eSPaolo Bonzini tcg_gen_gvec_mov(MO_64, decode->op[0].offset, decode->op[1].offset, vec_len, vec_len); 45147170a17eSPaolo Bonzini tcg_gen_st_i64(s->tmp1_i64, OP_PTR0, offsetof(ZMMReg, ZMM_Q(0))); 45157170a17eSPaolo Bonzini} 45167170a17eSPaolo Bonzini 45174228eb8cSPaolo Bonzinistatic void gen_VMOVLPx_st(DisasContext *s, X86DecodedInsn *decode) 45187170a17eSPaolo Bonzini{ 45197170a17eSPaolo Bonzini tcg_gen_ld_i64(s->tmp1_i64, OP_PTR2, offsetof(ZMMReg, ZMM_Q(0))); 45207170a17eSPaolo Bonzini tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ); 45217170a17eSPaolo Bonzini} 45227170a17eSPaolo Bonzini 45234228eb8cSPaolo Bonzinistatic void gen_VMOVSD_ld(DisasContext *s, X86DecodedInsn *decode) 45247170a17eSPaolo Bonzini{ 45257170a17eSPaolo Bonzini TCGv_i64 zero = tcg_constant_i64(0); 45267170a17eSPaolo Bonzini 45277170a17eSPaolo Bonzini tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ); 45287170a17eSPaolo Bonzini tcg_gen_st_i64(zero, OP_PTR0, offsetof(ZMMReg, ZMM_Q(1))); 45297170a17eSPaolo Bonzini tcg_gen_st_i64(s->tmp1_i64, OP_PTR0, offsetof(ZMMReg, ZMM_Q(0))); 45307170a17eSPaolo Bonzini} 45317170a17eSPaolo Bonzini 45324228eb8cSPaolo Bonzinistatic void gen_VMOVSS(DisasContext *s, X86DecodedInsn *decode) 45337170a17eSPaolo Bonzini{ 45347170a17eSPaolo Bonzini int vec_len = vector_len(s, decode); 45357170a17eSPaolo Bonzini 45367170a17eSPaolo Bonzini tcg_gen_ld_i32(s->tmp2_i32, OP_PTR2, offsetof(ZMMReg, ZMM_L(0))); 45377170a17eSPaolo Bonzini tcg_gen_gvec_mov(MO_64, decode->op[0].offset, decode->op[1].offset, vec_len, vec_len); 45387170a17eSPaolo Bonzini tcg_gen_st_i32(s->tmp2_i32, OP_PTR0, offsetof(ZMMReg, ZMM_L(0))); 45397170a17eSPaolo Bonzini} 45407170a17eSPaolo Bonzini 45414228eb8cSPaolo Bonzinistatic void gen_VMOVSS_ld(DisasContext *s, X86DecodedInsn *decode) 45427170a17eSPaolo Bonzini{ 45437170a17eSPaolo Bonzini int vec_len = vector_len(s, decode); 45447170a17eSPaolo Bonzini 45457170a17eSPaolo Bonzini tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); 45467170a17eSPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, decode->op[0].offset, vec_len, vec_len, 0); 45477170a17eSPaolo Bonzini tcg_gen_st_i32(s->tmp2_i32, OP_PTR0, offsetof(ZMMReg, ZMM_L(0))); 45487170a17eSPaolo Bonzini} 45497170a17eSPaolo Bonzini 45504228eb8cSPaolo Bonzinistatic void gen_VMOVSS_st(DisasContext *s, X86DecodedInsn *decode) 45517170a17eSPaolo Bonzini{ 45527170a17eSPaolo Bonzini tcg_gen_ld_i32(s->tmp2_i32, OP_PTR2, offsetof(ZMMReg, ZMM_L(0))); 45537170a17eSPaolo Bonzini tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); 45547170a17eSPaolo Bonzini} 45557170a17eSPaolo Bonzini 45564228eb8cSPaolo Bonzinistatic void gen_VPMASKMOV_st(DisasContext *s, X86DecodedInsn *decode) 455716fc5726SPaolo Bonzini{ 455816fc5726SPaolo Bonzini if (s->vex_w) { 45594228eb8cSPaolo Bonzini gen_VMASKMOVPD_st(s, decode); 456016fc5726SPaolo Bonzini } else { 45614228eb8cSPaolo Bonzini gen_VMASKMOVPS_st(s, decode); 456216fc5726SPaolo Bonzini } 456316fc5726SPaolo Bonzini} 456416fc5726SPaolo Bonzini 45654228eb8cSPaolo Bonzinistatic void gen_VPERMD(DisasContext *s, X86DecodedInsn *decode) 456616fc5726SPaolo Bonzini{ 456716fc5726SPaolo Bonzini assert(s->vex_l); 456816fc5726SPaolo Bonzini gen_helper_vpermd_ymm(OP_PTR0, OP_PTR1, OP_PTR2); 456916fc5726SPaolo Bonzini} 457016fc5726SPaolo Bonzini 45714228eb8cSPaolo Bonzinistatic void gen_VPERM2x128(DisasContext *s, X86DecodedInsn *decode) 457279068477SPaolo Bonzini{ 457379068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 457479068477SPaolo Bonzini assert(s->vex_l); 457579068477SPaolo Bonzini gen_helper_vpermdq_ymm(OP_PTR0, OP_PTR1, OP_PTR2, imm); 457679068477SPaolo Bonzini} 457779068477SPaolo Bonzini 45784228eb8cSPaolo Bonzinistatic void gen_VPHMINPOSUW(DisasContext *s, X86DecodedInsn *decode) 457916fc5726SPaolo Bonzini{ 458016fc5726SPaolo Bonzini assert(!s->vex_l); 4581ad75a51eSRichard Henderson gen_helper_phminposuw_xmm(tcg_env, OP_PTR0, OP_PTR2); 458216fc5726SPaolo Bonzini} 458316fc5726SPaolo Bonzini 45844228eb8cSPaolo Bonzinistatic void gen_VROUNDSD(DisasContext *s, X86DecodedInsn *decode) 458579068477SPaolo Bonzini{ 458679068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 458779068477SPaolo Bonzini assert(!s->vex_l); 4588ad75a51eSRichard Henderson gen_helper_roundsd_xmm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm); 458979068477SPaolo Bonzini} 459079068477SPaolo Bonzini 45914228eb8cSPaolo Bonzinistatic void gen_VROUNDSS(DisasContext *s, X86DecodedInsn *decode) 459279068477SPaolo Bonzini{ 459379068477SPaolo Bonzini TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); 459479068477SPaolo Bonzini assert(!s->vex_l); 4595ad75a51eSRichard Henderson gen_helper_roundss_xmm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm); 459679068477SPaolo Bonzini} 459779068477SPaolo Bonzini 45984228eb8cSPaolo Bonzinistatic void gen_VSHUF(DisasContext *s, X86DecodedInsn *decode) 4599aba2b8ecSPaolo Bonzini{ 4600aba2b8ecSPaolo Bonzini TCGv_i32 imm = tcg_constant_i32(decode->immediate); 4601aba2b8ecSPaolo Bonzini SSEFunc_0_pppi ps, pd, fn; 4602aba2b8ecSPaolo Bonzini ps = s->vex_l ? gen_helper_shufps_ymm : gen_helper_shufps_xmm; 4603aba2b8ecSPaolo Bonzini pd = s->vex_l ? gen_helper_shufpd_ymm : gen_helper_shufpd_xmm; 4604aba2b8ecSPaolo Bonzini fn = s->prefix & PREFIX_DATA ? pd : ps; 4605aba2b8ecSPaolo Bonzini fn(OP_PTR0, OP_PTR1, OP_PTR2, imm); 4606aba2b8ecSPaolo Bonzini} 4607aba2b8ecSPaolo Bonzini 46084228eb8cSPaolo Bonzinistatic void gen_VUCOMI(DisasContext *s, X86DecodedInsn *decode) 4609f8d19eecSPaolo Bonzini{ 4610f8d19eecSPaolo Bonzini SSEFunc_0_epp fn; 4611f8d19eecSPaolo Bonzini fn = s->prefix & PREFIX_DATA ? gen_helper_ucomisd : gen_helper_ucomiss; 4612ad75a51eSRichard Henderson fn(tcg_env, OP_PTR1, OP_PTR2); 4613abdcc5c8SPaolo Bonzini assume_cc_op(s, CC_OP_EFLAGS); 4614f8d19eecSPaolo Bonzini} 4615f8d19eecSPaolo Bonzini 46164228eb8cSPaolo Bonzinistatic void gen_VZEROALL(DisasContext *s, X86DecodedInsn *decode) 4617ce4fcb94SPaolo Bonzini{ 4618ce4fcb94SPaolo Bonzini TCGv_ptr ptr = tcg_temp_new_ptr(); 4619ce4fcb94SPaolo Bonzini 4620ad75a51eSRichard Henderson tcg_gen_addi_ptr(ptr, tcg_env, offsetof(CPUX86State, xmm_regs)); 4621ce4fcb94SPaolo Bonzini gen_helper_memset(ptr, ptr, tcg_constant_i32(0), 4622ce4fcb94SPaolo Bonzini tcg_constant_ptr(CPU_NB_REGS * sizeof(ZMMReg))); 4623ce4fcb94SPaolo Bonzini} 4624ce4fcb94SPaolo Bonzini 46254228eb8cSPaolo Bonzinistatic void gen_VZEROUPPER(DisasContext *s, X86DecodedInsn *decode) 4626ce4fcb94SPaolo Bonzini{ 4627ce4fcb94SPaolo Bonzini int i; 4628ce4fcb94SPaolo Bonzini 4629ce4fcb94SPaolo Bonzini for (i = 0; i < CPU_NB_REGS; i++) { 4630ce4fcb94SPaolo Bonzini int offset = offsetof(CPUX86State, xmm_regs[i].ZMM_X(1)); 4631ce4fcb94SPaolo Bonzini tcg_gen_gvec_dup_imm(MO_64, offset, 16, 16, 0); 4632ce4fcb94SPaolo Bonzini } 4633ce4fcb94SPaolo Bonzini} 4634cc1d28bdSPaolo Bonzini 46354228eb8cSPaolo Bonzinistatic void gen_WAIT(DisasContext *s, X86DecodedInsn *decode) 46365e9e21bcSPaolo Bonzini{ 46375e9e21bcSPaolo Bonzini if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == (HF_MP_MASK | HF_TS_MASK)) { 46385e9e21bcSPaolo Bonzini gen_NM_exception(s); 46395e9e21bcSPaolo Bonzini } else { 46405e9e21bcSPaolo Bonzini /* needs to be treated as I/O because of ferr_irq */ 46415e9e21bcSPaolo Bonzini translator_io_start(&s->base); 46425e9e21bcSPaolo Bonzini gen_helper_fwait(tcg_env); 46435e9e21bcSPaolo Bonzini } 46445e9e21bcSPaolo Bonzini} 46455e9e21bcSPaolo Bonzini 4646ae541c0eSPaolo Bonzini#ifndef CONFIG_USER_ONLY 4647ae541c0eSPaolo Bonzinistatic void gen_WRMSR(DisasContext *s, X86DecodedInsn *decode) 4648ae541c0eSPaolo Bonzini{ 4649ae541c0eSPaolo Bonzini gen_update_cc_op(s); 4650ae541c0eSPaolo Bonzini gen_update_eip_cur(s); 4651ae541c0eSPaolo Bonzini gen_helper_wrmsr(tcg_env); 4652ae541c0eSPaolo Bonzini s->base.is_jmp = DISAS_EOB_NEXT; 4653ae541c0eSPaolo Bonzini} 4654ae541c0eSPaolo Bonzini#else 4655ae541c0eSPaolo Bonzini#define gen_WRMSR gen_unreachable 4656ae541c0eSPaolo Bonzini#endif 4657ae541c0eSPaolo Bonzini 4658ea89aa89SPaolo Bonzinistatic void gen_WRxxBASE(DisasContext *s, X86DecodedInsn *decode) 4659ea89aa89SPaolo Bonzini{ 4660ea89aa89SPaolo Bonzini TCGv base = cpu_seg_base[s->modrm & 8 ? R_GS : R_FS]; 4661ea89aa89SPaolo Bonzini 4662ea89aa89SPaolo Bonzini /* Preserve hflags bits by testing CR4 at runtime. */ 4663ea89aa89SPaolo Bonzini gen_helper_cr4_testbit(tcg_env, tcg_constant_i32(CR4_FSGSBASE_MASK)); 4664ea89aa89SPaolo Bonzini tcg_gen_mov_tl(base, s->T0); 4665ea89aa89SPaolo Bonzini} 4666ea89aa89SPaolo Bonzini 46677b1f25acSPaolo Bonzinistatic void gen_XADD(DisasContext *s, X86DecodedInsn *decode) 46687b1f25acSPaolo Bonzini{ 46697b1f25acSPaolo Bonzini MemOp ot = decode->op[1].ot; 46707b1f25acSPaolo Bonzini 46717b1f25acSPaolo Bonzini decode->cc_dst = tcg_temp_new(); 46727b1f25acSPaolo Bonzini decode->cc_src = s->T1; 46737b1f25acSPaolo Bonzini decode->cc_op = CC_OP_ADDB + ot; 46747b1f25acSPaolo Bonzini 46757b1f25acSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 46767b1f25acSPaolo Bonzini tcg_gen_atomic_fetch_add_tl(s->T0, s->A0, s->T1, s->mem_index, ot | MO_LE); 46777b1f25acSPaolo Bonzini tcg_gen_add_tl(decode->cc_dst, s->T0, s->T1); 46787b1f25acSPaolo Bonzini } else { 46797b1f25acSPaolo Bonzini tcg_gen_add_tl(decode->cc_dst, s->T0, s->T1); 46807b1f25acSPaolo Bonzini /* 46817b1f25acSPaolo Bonzini * NOTE: writing memory first is important for MMU exceptions, 46827b1f25acSPaolo Bonzini * but "new result" wins for XADD AX, AX. 46837b1f25acSPaolo Bonzini */ 46847b1f25acSPaolo Bonzini gen_writeback(s, decode, 0, decode->cc_dst); 46857b1f25acSPaolo Bonzini } 46867b1f25acSPaolo Bonzini if (decode->op[0].has_ea || decode->op[2].n != decode->op[0].n) { 46877b1f25acSPaolo Bonzini gen_writeback(s, decode, 2, s->T0); 46887b1f25acSPaolo Bonzini } 46897b1f25acSPaolo Bonzini} 46907b1f25acSPaolo Bonzini 46914228eb8cSPaolo Bonzinistatic void gen_XCHG(DisasContext *s, X86DecodedInsn *decode) 46925e9e21bcSPaolo Bonzini{ 46935e9e21bcSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 46945e9e21bcSPaolo Bonzini tcg_gen_atomic_xchg_tl(s->T0, s->A0, s->T1, 46955e9e21bcSPaolo Bonzini s->mem_index, decode->op[0].ot | MO_LE); 46965e9e21bcSPaolo Bonzini /* now store old value into register operand */ 46975e9e21bcSPaolo Bonzini gen_op_mov_reg_v(s, decode->op[2].ot, decode->op[2].n, s->T0); 46985e9e21bcSPaolo Bonzini } else { 46995e9e21bcSPaolo Bonzini /* move destination value into source operand, source preserved in T1 */ 47005e9e21bcSPaolo Bonzini gen_op_mov_reg_v(s, decode->op[2].ot, decode->op[2].n, s->T0); 47015e9e21bcSPaolo Bonzini tcg_gen_mov_tl(s->T0, s->T1); 47025e9e21bcSPaolo Bonzini } 47035e9e21bcSPaolo Bonzini} 47045e9e21bcSPaolo Bonzini 47054228eb8cSPaolo Bonzinistatic void gen_XLAT(DisasContext *s, X86DecodedInsn *decode) 4706d7c41a60SPaolo Bonzini{ 4707d7c41a60SPaolo Bonzini /* AL is already zero-extended into s->T0. */ 4708d7c41a60SPaolo Bonzini tcg_gen_add_tl(s->A0, cpu_regs[R_EBX], s->T0); 470956da568fSPaolo Bonzini gen_lea_v_seg(s, s->A0, R_DS, s->override); 4710d7c41a60SPaolo Bonzini gen_op_ld_v(s, MO_8, s->T0, s->A0); 4711d7c41a60SPaolo Bonzini} 4712d7c41a60SPaolo Bonzini 47134228eb8cSPaolo Bonzinistatic void gen_XOR(DisasContext *s, X86DecodedInsn *decode) 4714cc1d28bdSPaolo Bonzini{ 4715cc1d28bdSPaolo Bonzini /* special case XOR reg, reg */ 4716cc1d28bdSPaolo Bonzini if (decode->op[1].unit == X86_OP_INT && 4717cc1d28bdSPaolo Bonzini decode->op[2].unit == X86_OP_INT && 4718cc1d28bdSPaolo Bonzini decode->op[1].n == decode->op[2].n) { 4719cc1d28bdSPaolo Bonzini tcg_gen_movi_tl(s->T0, 0); 4720e09447c3SPaolo Bonzini decode->cc_op = CC_OP_EFLAGS; 4721e09447c3SPaolo Bonzini decode->cc_src = tcg_constant_tl(CC_Z | CC_P); 4722cc1d28bdSPaolo Bonzini } else { 4723cc1d28bdSPaolo Bonzini MemOp ot = decode->op[1].ot; 4724cc1d28bdSPaolo Bonzini 4725cc1d28bdSPaolo Bonzini if (s->prefix & PREFIX_LOCK) { 4726cc1d28bdSPaolo Bonzini tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T1, 4727cc1d28bdSPaolo Bonzini s->mem_index, ot | MO_LE); 4728cc1d28bdSPaolo Bonzini } else { 4729cc1d28bdSPaolo Bonzini tcg_gen_xor_tl(s->T0, s->T0, s->T1); 4730cc1d28bdSPaolo Bonzini } 4731cc1d28bdSPaolo Bonzini prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); 4732cc1d28bdSPaolo Bonzini } 4733cc1d28bdSPaolo Bonzini} 4734ea89aa89SPaolo Bonzini 4735ea89aa89SPaolo Bonzinistatic void gen_XRSTOR(DisasContext *s, X86DecodedInsn *decode) 4736ea89aa89SPaolo Bonzini{ 4737ea89aa89SPaolo Bonzini TCGv_i64 features = tcg_temp_new_i64(); 4738ea89aa89SPaolo Bonzini 4739ea89aa89SPaolo Bonzini tcg_gen_concat_tl_i64(features, cpu_regs[R_EAX], cpu_regs[R_EDX]); 4740ea89aa89SPaolo Bonzini gen_helper_xrstor(tcg_env, s->A0, features); 4741ea89aa89SPaolo Bonzini if (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_MPX) { 4742ea89aa89SPaolo Bonzini /* 4743ea89aa89SPaolo Bonzini * XRSTOR is how MPX is enabled, which changes how 4744ea89aa89SPaolo Bonzini * we translate. Thus we need to end the TB. 4745ea89aa89SPaolo Bonzini */ 4746ea89aa89SPaolo Bonzini s->base.is_jmp = DISAS_EOB_NEXT; 4747ea89aa89SPaolo Bonzini } 4748ea89aa89SPaolo Bonzini} 4749ea89aa89SPaolo Bonzini 4750ea89aa89SPaolo Bonzinistatic void gen_XSAVE(DisasContext *s, X86DecodedInsn *decode) 4751ea89aa89SPaolo Bonzini{ 4752ea89aa89SPaolo Bonzini TCGv_i64 features = tcg_temp_new_i64(); 4753ea89aa89SPaolo Bonzini 4754ea89aa89SPaolo Bonzini tcg_gen_concat_tl_i64(features, cpu_regs[R_EAX], cpu_regs[R_EDX]); 4755ea89aa89SPaolo Bonzini gen_helper_xsave(tcg_env, s->A0, features); 4756ea89aa89SPaolo Bonzini} 4757ea89aa89SPaolo Bonzini 4758ea89aa89SPaolo Bonzinistatic void gen_XSAVEOPT(DisasContext *s, X86DecodedInsn *decode) 4759ea89aa89SPaolo Bonzini{ 4760ea89aa89SPaolo Bonzini TCGv_i64 features = tcg_temp_new_i64(); 4761ea89aa89SPaolo Bonzini 4762ea89aa89SPaolo Bonzini tcg_gen_concat_tl_i64(features, cpu_regs[R_EAX], cpu_regs[R_EDX]); 4763ea89aa89SPaolo Bonzini gen_helper_xsave(tcg_env, s->A0, features); 4764ea89aa89SPaolo Bonzini} 4765