1606 |
*offset_ptr = disp; |
*offset_ptr = disp; |
1607 |
} |
} |
1608 |
|
|
1609 |
|
/* used for LEA and MOV AX, mem */ |
1610 |
|
static void gen_add_A0_ds_seg(DisasContext *s) |
1611 |
|
{ |
1612 |
|
int override, must_add_seg; |
1613 |
|
must_add_seg = s->addseg; |
1614 |
|
override = R_DS; |
1615 |
|
if (s->override >= 0) { |
1616 |
|
override = s->override; |
1617 |
|
must_add_seg = 1; |
1618 |
|
} else { |
1619 |
|
override = R_DS; |
1620 |
|
} |
1621 |
|
if (must_add_seg) { |
1622 |
|
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
1623 |
|
} |
1624 |
|
} |
1625 |
|
|
1626 |
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg != |
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg != |
1627 |
OR_TMP0 */ |
OR_TMP0 */ |
1628 |
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store) |
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store) |
2210 |
#endif |
#endif |
2211 |
} |
} |
2212 |
|
|
2213 |
|
static GenOpFunc1 *gen_ldq_env_A0[3] = { |
2214 |
|
gen_op_ldq_raw_env_A0, |
2215 |
|
#ifndef CONFIG_USER_ONLY |
2216 |
|
gen_op_ldq_kernel_env_A0, |
2217 |
|
gen_op_ldq_user_env_A0, |
2218 |
|
#endif |
2219 |
|
}; |
2220 |
|
|
2221 |
|
static GenOpFunc1 *gen_stq_env_A0[3] = { |
2222 |
|
gen_op_stq_raw_env_A0, |
2223 |
|
#ifndef CONFIG_USER_ONLY |
2224 |
|
gen_op_stq_kernel_env_A0, |
2225 |
|
gen_op_stq_user_env_A0, |
2226 |
|
#endif |
2227 |
|
}; |
2228 |
|
|
2229 |
static GenOpFunc1 *gen_ldo_env_A0[3] = { |
static GenOpFunc1 *gen_ldo_env_A0[3] = { |
2230 |
gen_op_ldo_raw_env_A0, |
gen_op_ldo_raw_env_A0, |
2231 |
#ifndef CONFIG_USER_ONLY |
#ifndef CONFIG_USER_ONLY |
2242 |
#endif |
#endif |
2243 |
}; |
}; |
2244 |
|
|
2245 |
|
#define SSE_SPECIAL ((GenOpFunc2 *)1) |
2246 |
|
|
2247 |
|
#define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm } |
2248 |
|
#define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \ |
2249 |
|
gen_op_ ## x ## ss, gen_op_ ## x ## sd, } |
2250 |
|
|
2251 |
|
static GenOpFunc2 *sse_op_table1[256][4] = { |
2252 |
|
/* pure SSE operations */ |
2253 |
|
[0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ |
2254 |
|
[0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ |
2255 |
|
[0x12] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */ |
2256 |
|
[0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */ |
2257 |
|
[0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm }, |
2258 |
|
[0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm }, |
2259 |
|
[0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */ |
2260 |
|
[0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */ |
2261 |
|
|
2262 |
|
[0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */ |
2263 |
|
[0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */ |
2264 |
|
[0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */ |
2265 |
|
[0x2b] = { SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd */ |
2266 |
|
[0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */ |
2267 |
|
[0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */ |
2268 |
|
[0x2e] = { gen_op_ucomiss, gen_op_ucomisd }, |
2269 |
|
[0x2f] = { gen_op_comiss, gen_op_comisd }, |
2270 |
|
[0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */ |
2271 |
|
[0x51] = SSE_FOP(sqrt), |
2272 |
|
[0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL }, |
2273 |
|
[0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL }, |
2274 |
|
[0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */ |
2275 |
|
[0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */ |
2276 |
|
[0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */ |
2277 |
|
[0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */ |
2278 |
|
[0x58] = SSE_FOP(add), |
2279 |
|
[0x59] = SSE_FOP(mul), |
2280 |
|
[0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps, |
2281 |
|
gen_op_cvtss2sd, gen_op_cvtsd2ss }, |
2282 |
|
[0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq }, |
2283 |
|
[0x5c] = SSE_FOP(sub), |
2284 |
|
[0x5d] = SSE_FOP(min), |
2285 |
|
[0x5e] = SSE_FOP(div), |
2286 |
|
[0x5f] = SSE_FOP(max), |
2287 |
|
|
2288 |
|
[0xc2] = SSE_FOP(cmpeq), |
2289 |
|
[0xc6] = { (GenOpFunc2 *)gen_op_pshufd_xmm, (GenOpFunc2 *)gen_op_shufpd }, |
2290 |
|
|
2291 |
|
/* MMX ops and their SSE extensions */ |
2292 |
|
[0x60] = MMX_OP2(punpcklbw), |
2293 |
|
[0x61] = MMX_OP2(punpcklwd), |
2294 |
|
[0x62] = MMX_OP2(punpckldq), |
2295 |
|
[0x63] = MMX_OP2(packsswb), |
2296 |
|
[0x64] = MMX_OP2(pcmpgtb), |
2297 |
|
[0x65] = MMX_OP2(pcmpgtw), |
2298 |
|
[0x66] = MMX_OP2(pcmpgtl), |
2299 |
|
[0x67] = MMX_OP2(packuswb), |
2300 |
|
[0x68] = MMX_OP2(punpckhbw), |
2301 |
|
[0x69] = MMX_OP2(punpckhwd), |
2302 |
|
[0x6a] = MMX_OP2(punpckhdq), |
2303 |
|
[0x6b] = MMX_OP2(packssdw), |
2304 |
|
[0x6c] = { NULL, gen_op_punpcklqdq_xmm }, |
2305 |
|
[0x6d] = { NULL, gen_op_punpckhqdq_xmm }, |
2306 |
|
[0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */ |
2307 |
|
[0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */ |
2308 |
|
[0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx, |
2309 |
|
(GenOpFunc2 *)gen_op_pshufd_xmm, |
2310 |
|
(GenOpFunc2 *)gen_op_pshufhw_xmm, |
2311 |
|
(GenOpFunc2 *)gen_op_pshuflw_xmm }, |
2312 |
|
[0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */ |
2313 |
|
[0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */ |
2314 |
|
[0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */ |
2315 |
|
[0x74] = MMX_OP2(pcmpeqb), |
2316 |
|
[0x75] = MMX_OP2(pcmpeqw), |
2317 |
|
[0x76] = MMX_OP2(pcmpeql), |
2318 |
|
[0x77] = { SSE_SPECIAL }, /* emms */ |
2319 |
|
[0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps }, |
2320 |
|
[0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps }, |
2321 |
|
[0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */ |
2322 |
|
[0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */ |
2323 |
|
[0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */ |
2324 |
|
[0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */ |
2325 |
|
[0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps }, |
2326 |
|
[0xd1] = MMX_OP2(psrlw), |
2327 |
|
[0xd2] = MMX_OP2(psrld), |
2328 |
|
[0xd3] = MMX_OP2(psrlq), |
2329 |
|
[0xd4] = MMX_OP2(paddq), |
2330 |
|
[0xd5] = MMX_OP2(pmullw), |
2331 |
|
[0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, |
2332 |
|
[0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */ |
2333 |
|
[0xd8] = MMX_OP2(psubusb), |
2334 |
|
[0xd9] = MMX_OP2(psubusw), |
2335 |
|
[0xda] = MMX_OP2(pminub), |
2336 |
|
[0xdb] = MMX_OP2(pand), |
2337 |
|
[0xdc] = MMX_OP2(paddusb), |
2338 |
|
[0xdd] = MMX_OP2(paddusw), |
2339 |
|
[0xde] = MMX_OP2(pmaxub), |
2340 |
|
[0xdf] = MMX_OP2(pandn), |
2341 |
|
[0xe0] = MMX_OP2(pavgb), |
2342 |
|
[0xe1] = MMX_OP2(psraw), |
2343 |
|
[0xe2] = MMX_OP2(psrad), |
2344 |
|
[0xe3] = MMX_OP2(pavgw), |
2345 |
|
[0xe4] = MMX_OP2(pmulhuw), |
2346 |
|
[0xe5] = MMX_OP2(pmulhw), |
2347 |
|
[0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq }, |
2348 |
|
[0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */ |
2349 |
|
[0xe8] = MMX_OP2(psubsb), |
2350 |
|
[0xe9] = MMX_OP2(psubsw), |
2351 |
|
[0xea] = MMX_OP2(pminsw), |
2352 |
|
[0xeb] = MMX_OP2(por), |
2353 |
|
[0xec] = MMX_OP2(paddsb), |
2354 |
|
[0xed] = MMX_OP2(paddsw), |
2355 |
|
[0xee] = MMX_OP2(pmaxsw), |
2356 |
|
[0xef] = MMX_OP2(pxor), |
2357 |
|
[0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu (PNI) */ |
2358 |
|
[0xf1] = MMX_OP2(psllw), |
2359 |
|
[0xf2] = MMX_OP2(pslld), |
2360 |
|
[0xf3] = MMX_OP2(psllq), |
2361 |
|
[0xf4] = MMX_OP2(pmuludq), |
2362 |
|
[0xf5] = MMX_OP2(pmaddwd), |
2363 |
|
[0xf6] = MMX_OP2(psadbw), |
2364 |
|
[0xf7] = MMX_OP2(maskmov), |
2365 |
|
[0xf8] = MMX_OP2(psubb), |
2366 |
|
[0xf9] = MMX_OP2(psubw), |
2367 |
|
[0xfa] = MMX_OP2(psubl), |
2368 |
|
[0xfb] = MMX_OP2(psubq), |
2369 |
|
[0xfc] = MMX_OP2(paddb), |
2370 |
|
[0xfd] = MMX_OP2(paddw), |
2371 |
|
[0xfe] = MMX_OP2(paddl), |
2372 |
|
}; |
2373 |
|
|
2374 |
|
static GenOpFunc2 *sse_op_table2[3 * 8][2] = { |
2375 |
|
[0 + 2] = MMX_OP2(psrlw), |
2376 |
|
[0 + 4] = MMX_OP2(psraw), |
2377 |
|
[0 + 6] = MMX_OP2(psllw), |
2378 |
|
[8 + 2] = MMX_OP2(psrld), |
2379 |
|
[8 + 4] = MMX_OP2(psrad), |
2380 |
|
[8 + 6] = MMX_OP2(pslld), |
2381 |
|
[16 + 2] = MMX_OP2(psrlq), |
2382 |
|
[16 + 3] = { NULL, gen_op_psrldq_xmm }, |
2383 |
|
[16 + 6] = MMX_OP2(psllq), |
2384 |
|
[16 + 7] = { NULL, gen_op_pslldq_xmm }, |
2385 |
|
}; |
2386 |
|
|
2387 |
|
static GenOpFunc1 *sse_op_table3[4 * 3] = { |
2388 |
|
gen_op_cvtsi2ss, |
2389 |
|
gen_op_cvtsi2sd, |
2390 |
|
X86_64_ONLY(gen_op_cvtsq2ss), |
2391 |
|
X86_64_ONLY(gen_op_cvtsq2sd), |
2392 |
|
|
2393 |
|
gen_op_cvttss2si, |
2394 |
|
gen_op_cvttsd2si, |
2395 |
|
X86_64_ONLY(gen_op_cvttss2sq), |
2396 |
|
X86_64_ONLY(gen_op_cvttsd2sq), |
2397 |
|
|
2398 |
|
gen_op_cvtss2si, |
2399 |
|
gen_op_cvtsd2si, |
2400 |
|
X86_64_ONLY(gen_op_cvtss2sq), |
2401 |
|
X86_64_ONLY(gen_op_cvtsd2sq), |
2402 |
|
}; |
2403 |
|
|
2404 |
|
static GenOpFunc2 *sse_op_table4[8][4] = { |
2405 |
|
SSE_FOP(cmpeq), |
2406 |
|
SSE_FOP(cmplt), |
2407 |
|
SSE_FOP(cmple), |
2408 |
|
SSE_FOP(cmpunord), |
2409 |
|
SSE_FOP(cmpneq), |
2410 |
|
SSE_FOP(cmpnlt), |
2411 |
|
SSE_FOP(cmpnle), |
2412 |
|
SSE_FOP(cmpord), |
2413 |
|
}; |
2414 |
|
|
2415 |
|
static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) |
2416 |
|
{ |
2417 |
|
int b1, op1_offset, op2_offset, is_xmm, val, ot; |
2418 |
|
int modrm, mod, rm, reg, reg_addr, offset_addr; |
2419 |
|
GenOpFunc2 *sse_op2; |
2420 |
|
GenOpFunc3 *sse_op3; |
2421 |
|
|
2422 |
|
b &= 0xff; |
2423 |
|
if (s->prefix & PREFIX_DATA) |
2424 |
|
b1 = 1; |
2425 |
|
else if (s->prefix & PREFIX_REPZ) |
2426 |
|
b1 = 2; |
2427 |
|
else if (s->prefix & PREFIX_REPNZ) |
2428 |
|
b1 = 3; |
2429 |
|
else |
2430 |
|
b1 = 0; |
2431 |
|
sse_op2 = sse_op_table1[b][b1]; |
2432 |
|
if (!sse_op2) |
2433 |
|
goto illegal_op; |
2434 |
|
if (b <= 0x5f || b == 0xc6 || b == 0xc2) { |
2435 |
|
is_xmm = 1; |
2436 |
|
} else { |
2437 |
|
if (b1 == 0) { |
2438 |
|
/* MMX case */ |
2439 |
|
is_xmm = 0; |
2440 |
|
} else { |
2441 |
|
is_xmm = 1; |
2442 |
|
} |
2443 |
|
} |
2444 |
|
/* simple MMX/SSE operation */ |
2445 |
|
if (s->flags & HF_TS_MASK) { |
2446 |
|
gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); |
2447 |
|
return; |
2448 |
|
} |
2449 |
|
if (s->flags & HF_EM_MASK) { |
2450 |
|
illegal_op: |
2451 |
|
gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); |
2452 |
|
return; |
2453 |
|
} |
2454 |
|
if (is_xmm && !(s->flags & HF_OSFXSR_MASK)) |
2455 |
|
goto illegal_op; |
2456 |
|
if (b == 0x77) { |
2457 |
|
/* emms */ |
2458 |
|
gen_op_emms(); |
2459 |
|
return; |
2460 |
|
} |
2461 |
|
/* prepare MMX state (XXX: optimize by storing fptt and fptags in |
2462 |
|
the static cpu state) */ |
2463 |
|
if (!is_xmm) { |
2464 |
|
gen_op_enter_mmx(); |
2465 |
|
} |
2466 |
|
|
2467 |
|
modrm = ldub_code(s->pc++); |
2468 |
|
reg = ((modrm >> 3) & 7); |
2469 |
|
if (is_xmm) |
2470 |
|
reg |= rex_r; |
2471 |
|
mod = (modrm >> 6) & 3; |
2472 |
|
if (sse_op2 == SSE_SPECIAL) { |
2473 |
|
b |= (b1 << 8); |
2474 |
|
switch(b) { |
2475 |
|
case 0x0e7: /* movntq */ |
2476 |
|
if (mod == 3) |
2477 |
|
goto illegal_op; |
2478 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2479 |
|
gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx)); |
2480 |
|
break; |
2481 |
|
case 0x1e7: /* movntdq */ |
2482 |
|
case 0x02b: /* movntps */ |
2483 |
|
case 0x12b: /* movntps */ |
2484 |
|
case 0x2f0: /* lddqu */ |
2485 |
|
if (mod == 3) |
2486 |
|
goto illegal_op; |
2487 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2488 |
|
gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); |
2489 |
|
break; |
2490 |
|
case 0x6e: /* movd mm, ea */ |
2491 |
|
gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0); |
2492 |
|
gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx)); |
2493 |
|
break; |
2494 |
|
case 0x16e: /* movd xmm, ea */ |
2495 |
|
gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0); |
2496 |
|
gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg])); |
2497 |
|
break; |
2498 |
|
case 0x6f: /* movq mm, ea */ |
2499 |
|
if (mod != 3) { |
2500 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2501 |
|
gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx)); |
2502 |
|
} else { |
2503 |
|
rm = (modrm & 7); |
2504 |
|
gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx), |
2505 |
|
offsetof(CPUX86State,fpregs[rm].mmx)); |
2506 |
|
} |
2507 |
|
break; |
2508 |
|
case 0x010: /* movups */ |
2509 |
|
case 0x110: /* movupd */ |
2510 |
|
case 0x028: /* movaps */ |
2511 |
|
case 0x128: /* movapd */ |
2512 |
|
case 0x16f: /* movdqa xmm, ea */ |
2513 |
|
case 0x26f: /* movdqu xmm, ea */ |
2514 |
|
if (mod != 3) { |
2515 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2516 |
|
gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); |
2517 |
|
} else { |
2518 |
|
rm = (modrm & 7) | REX_B(s); |
2519 |
|
gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]), |
2520 |
|
offsetof(CPUX86State,xmm_regs[rm])); |
2521 |
|
} |
2522 |
|
break; |
2523 |
|
case 0x210: /* movss xmm, ea */ |
2524 |
|
if (mod != 3) { |
2525 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2526 |
|
gen_op_ld_T0_A0[OT_LONG + s->mem_index](); |
2527 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); |
2528 |
|
gen_op_movl_T0_0(); |
2529 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1))); |
2530 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2))); |
2531 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); |
2532 |
|
} else { |
2533 |
|
rm = (modrm & 7) | REX_B(s); |
2534 |
|
gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)), |
2535 |
|
offsetof(CPUX86State,xmm_regs[rm].XMM_L(0))); |
2536 |
|
} |
2537 |
|
break; |
2538 |
|
case 0x310: /* movsd xmm, ea */ |
2539 |
|
if (mod != 3) { |
2540 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2541 |
|
gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2542 |
|
gen_op_movl_T0_0(); |
2543 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2))); |
2544 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); |
2545 |
|
} else { |
2546 |
|
rm = (modrm & 7) | REX_B(s); |
2547 |
|
gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), |
2548 |
|
offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); |
2549 |
|
} |
2550 |
|
break; |
2551 |
|
case 0x012: /* movlps */ |
2552 |
|
case 0x112: /* movlpd */ |
2553 |
|
if (mod != 3) { |
2554 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2555 |
|
gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2556 |
|
} else { |
2557 |
|
/* movhlps */ |
2558 |
|
rm = (modrm & 7) | REX_B(s); |
2559 |
|
gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), |
2560 |
|
offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1))); |
2561 |
|
} |
2562 |
|
break; |
2563 |
|
case 0x016: /* movhps */ |
2564 |
|
case 0x116: /* movhpd */ |
2565 |
|
if (mod != 3) { |
2566 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2567 |
|
gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); |
2568 |
|
} else { |
2569 |
|
/* movlhps */ |
2570 |
|
rm = (modrm & 7) | REX_B(s); |
2571 |
|
gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)), |
2572 |
|
offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); |
2573 |
|
} |
2574 |
|
break; |
2575 |
|
case 0x216: /* movshdup */ |
2576 |
|
if (mod != 3) { |
2577 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2578 |
|
gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); |
2579 |
|
} else { |
2580 |
|
rm = (modrm & 7) | REX_B(s); |
2581 |
|
gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)), |
2582 |
|
offsetof(CPUX86State,xmm_regs[rm].XMM_L(1))); |
2583 |
|
gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)), |
2584 |
|
offsetof(CPUX86State,xmm_regs[rm].XMM_L(3))); |
2585 |
|
} |
2586 |
|
gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)), |
2587 |
|
offsetof(CPUX86State,xmm_regs[reg].XMM_L(1))); |
2588 |
|
gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)), |
2589 |
|
offsetof(CPUX86State,xmm_regs[reg].XMM_L(3))); |
2590 |
|
break; |
2591 |
|
case 0x7e: /* movd ea, mm */ |
2592 |
|
gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx)); |
2593 |
|
gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1); |
2594 |
|
break; |
2595 |
|
case 0x17e: /* movd ea, xmm */ |
2596 |
|
gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg])); |
2597 |
|
gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1); |
2598 |
|
break; |
2599 |
|
case 0x27e: /* movq xmm, ea */ |
2600 |
|
if (mod != 3) { |
2601 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2602 |
|
gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2603 |
|
} else { |
2604 |
|
rm = (modrm & 7) | REX_B(s); |
2605 |
|
gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), |
2606 |
|
offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); |
2607 |
|
} |
2608 |
|
gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); |
2609 |
|
break; |
2610 |
|
case 0x7f: /* movq ea, mm */ |
2611 |
|
if (mod != 3) { |
2612 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2613 |
|
gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx)); |
2614 |
|
} else { |
2615 |
|
rm = (modrm & 7); |
2616 |
|
gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx), |
2617 |
|
offsetof(CPUX86State,fpregs[reg].mmx)); |
2618 |
|
} |
2619 |
|
break; |
2620 |
|
case 0x011: /* movups */ |
2621 |
|
case 0x111: /* movupd */ |
2622 |
|
case 0x029: /* movaps */ |
2623 |
|
case 0x129: /* movapd */ |
2624 |
|
case 0x17f: /* movdqa ea, xmm */ |
2625 |
|
case 0x27f: /* movdqu ea, xmm */ |
2626 |
|
if (mod != 3) { |
2627 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2628 |
|
gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); |
2629 |
|
} else { |
2630 |
|
rm = (modrm & 7) | REX_B(s); |
2631 |
|
gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]), |
2632 |
|
offsetof(CPUX86State,xmm_regs[reg])); |
2633 |
|
} |
2634 |
|
break; |
2635 |
|
case 0x211: /* movss ea, xmm */ |
2636 |
|
if (mod != 3) { |
2637 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2638 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); |
2639 |
|
gen_op_st_T0_A0[OT_LONG + s->mem_index](); |
2640 |
|
} else { |
2641 |
|
rm = (modrm & 7) | REX_B(s); |
2642 |
|
gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)), |
2643 |
|
offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); |
2644 |
|
} |
2645 |
|
break; |
2646 |
|
case 0x311: /* movsd ea, xmm */ |
2647 |
|
if (mod != 3) { |
2648 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2649 |
|
gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2650 |
|
} else { |
2651 |
|
rm = (modrm & 7) | REX_B(s); |
2652 |
|
gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)), |
2653 |
|
offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2654 |
|
} |
2655 |
|
break; |
2656 |
|
case 0x013: /* movlps */ |
2657 |
|
case 0x113: /* movlpd */ |
2658 |
|
if (mod != 3) { |
2659 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2660 |
|
gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2661 |
|
} else { |
2662 |
|
goto illegal_op; |
2663 |
|
} |
2664 |
|
break; |
2665 |
|
case 0x017: /* movhps */ |
2666 |
|
case 0x117: /* movhpd */ |
2667 |
|
if (mod != 3) { |
2668 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2669 |
|
gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); |
2670 |
|
} else { |
2671 |
|
goto illegal_op; |
2672 |
|
} |
2673 |
|
break; |
2674 |
|
case 0x71: /* shift mm, im */ |
2675 |
|
case 0x72: |
2676 |
|
case 0x73: |
2677 |
|
case 0x171: /* shift xmm, im */ |
2678 |
|
case 0x172: |
2679 |
|
case 0x173: |
2680 |
|
val = ldub_code(s->pc++); |
2681 |
|
if (is_xmm) { |
2682 |
|
gen_op_movl_T0_im(val); |
2683 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0))); |
2684 |
|
gen_op_movl_T0_0(); |
2685 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1))); |
2686 |
|
op1_offset = offsetof(CPUX86State,xmm_t0); |
2687 |
|
} else { |
2688 |
|
gen_op_movl_T0_im(val); |
2689 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0))); |
2690 |
|
gen_op_movl_T0_0(); |
2691 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1))); |
2692 |
|
op1_offset = offsetof(CPUX86State,mmx_t0); |
2693 |
|
} |
2694 |
|
sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1]; |
2695 |
|
if (!sse_op2) |
2696 |
|
goto illegal_op; |
2697 |
|
if (is_xmm) { |
2698 |
|
rm = (modrm & 7) | REX_B(s); |
2699 |
|
op2_offset = offsetof(CPUX86State,xmm_regs[rm]); |
2700 |
|
} else { |
2701 |
|
rm = (modrm & 7); |
2702 |
|
op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); |
2703 |
|
} |
2704 |
|
sse_op2(op2_offset, op1_offset); |
2705 |
|
break; |
2706 |
|
case 0x050: /* movmskps */ |
2707 |
|
gen_op_movmskps(offsetof(CPUX86State,xmm_regs[reg])); |
2708 |
|
rm = (modrm & 7) | REX_B(s); |
2709 |
|
gen_op_mov_reg_T0[OT_LONG][rm](); |
2710 |
|
break; |
2711 |
|
case 0x150: /* movmskpd */ |
2712 |
|
gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[reg])); |
2713 |
|
rm = (modrm & 7) | REX_B(s); |
2714 |
|
gen_op_mov_reg_T0[OT_LONG][rm](); |
2715 |
|
break; |
2716 |
|
case 0x02a: /* cvtpi2ps */ |
2717 |
|
case 0x12a: /* cvtpi2pd */ |
2718 |
|
gen_op_enter_mmx(); |
2719 |
|
if (mod != 3) { |
2720 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2721 |
|
op2_offset = offsetof(CPUX86State,mmx_t0); |
2722 |
|
gen_ldq_env_A0[s->mem_index >> 2](op2_offset); |
2723 |
|
} else { |
2724 |
|
rm = (modrm & 7); |
2725 |
|
op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); |
2726 |
|
} |
2727 |
|
op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
2728 |
|
switch(b >> 8) { |
2729 |
|
case 0x0: |
2730 |
|
gen_op_cvtpi2ps(op1_offset, op2_offset); |
2731 |
|
break; |
2732 |
|
default: |
2733 |
|
case 0x1: |
2734 |
|
gen_op_cvtpi2pd(op1_offset, op2_offset); |
2735 |
|
break; |
2736 |
|
} |
2737 |
|
break; |
2738 |
|
case 0x22a: /* cvtsi2ss */ |
2739 |
|
case 0x32a: /* cvtsi2sd */ |
2740 |
|
ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; |
2741 |
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
2742 |
|
op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
2743 |
|
sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset); |
2744 |
|
break; |
2745 |
|
case 0x02c: /* cvttps2pi */ |
2746 |
|
case 0x12c: /* cvttpd2pi */ |
2747 |
|
case 0x02d: /* cvtps2pi */ |
2748 |
|
case 0x12d: /* cvtpd2pi */ |
2749 |
|
gen_op_enter_mmx(); |
2750 |
|
if (mod != 3) { |
2751 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2752 |
|
op2_offset = offsetof(CPUX86State,xmm_t0); |
2753 |
|
gen_ldo_env_A0[s->mem_index >> 2](op2_offset); |
2754 |
|
} else { |
2755 |
|
rm = (modrm & 7) | REX_B(s); |
2756 |
|
op2_offset = offsetof(CPUX86State,xmm_regs[rm]); |
2757 |
|
} |
2758 |
|
op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx); |
2759 |
|
switch(b) { |
2760 |
|
case 0x02c: |
2761 |
|
gen_op_cvttps2pi(op1_offset, op2_offset); |
2762 |
|
break; |
2763 |
|
case 0x12c: |
2764 |
|
gen_op_cvttpd2pi(op1_offset, op2_offset); |
2765 |
|
break; |
2766 |
|
case 0x02d: |
2767 |
|
gen_op_cvtps2pi(op1_offset, op2_offset); |
2768 |
|
break; |
2769 |
|
case 0x12d: |
2770 |
|
gen_op_cvtpd2pi(op1_offset, op2_offset); |
2771 |
|
break; |
2772 |
|
} |
2773 |
|
break; |
2774 |
|
case 0x22c: /* cvttss2si */ |
2775 |
|
case 0x32c: /* cvttsd2si */ |
2776 |
|
case 0x22d: /* cvtss2si */ |
2777 |
|
case 0x32d: /* cvtsd2si */ |
2778 |
|
ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; |
2779 |
|
op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
2780 |
|
sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 + |
2781 |
|
(b & 1) * 4](op1_offset); |
2782 |
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
2783 |
|
break; |
2784 |
|
case 0xc4: /* pinsrw */ |
2785 |
|
case 0x1c4: |
2786 |
|
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
2787 |
|
val = ldub_code(s->pc++); |
2788 |
|
if (b1) { |
2789 |
|
val &= 7; |
2790 |
|
gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val); |
2791 |
|
} else { |
2792 |
|
val &= 3; |
2793 |
|
gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val); |
2794 |
|
} |
2795 |
|
break; |
2796 |
|
case 0xc5: /* pextrw */ |
2797 |
|
case 0x1c5: |
2798 |
|
if (mod != 3) |
2799 |
|
goto illegal_op; |
2800 |
|
val = ldub_code(s->pc++); |
2801 |
|
if (b1) { |
2802 |
|
val &= 7; |
2803 |
|
rm = (modrm & 7) | REX_B(s); |
2804 |
|
gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val); |
2805 |
|
} else { |
2806 |
|
val &= 3; |
2807 |
|
rm = (modrm & 7); |
2808 |
|
gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val); |
2809 |
|
} |
2810 |
|
reg = ((modrm >> 3) & 7) | rex_r; |
2811 |
|
gen_op_mov_reg_T0[OT_LONG][reg](); |
2812 |
|
break; |
2813 |
|
case 0x1d6: /* movq ea, xmm */ |
2814 |
|
if (mod != 3) { |
2815 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2816 |
|
gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2817 |
|
} else { |
2818 |
|
rm = (modrm & 7) | REX_B(s); |
2819 |
|
gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)), |
2820 |
|
offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2821 |
|
gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1))); |
2822 |
|
} |
2823 |
|
break; |
2824 |
|
case 0x2d6: /* movq2dq */ |
2825 |
|
gen_op_enter_mmx(); |
2826 |
|
rm = (modrm & 7) | REX_B(s); |
2827 |
|
gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)), |
2828 |
|
offsetof(CPUX86State,fpregs[reg & 7].mmx)); |
2829 |
|
gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1))); |
2830 |
|
break; |
2831 |
|
case 0x3d6: /* movdq2q */ |
2832 |
|
gen_op_enter_mmx(); |
2833 |
|
rm = (modrm & 7); |
2834 |
|
gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx), |
2835 |
|
offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0))); |
2836 |
|
break; |
2837 |
|
case 0xd7: /* pmovmskb */ |
2838 |
|
case 0x1d7: |
2839 |
|
if (mod != 3) |
2840 |
|
goto illegal_op; |
2841 |
|
if (b1) { |
2842 |
|
rm = (modrm & 7) | REX_B(s); |
2843 |
|
gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm])); |
2844 |
|
} else { |
2845 |
|
rm = (modrm & 7); |
2846 |
|
gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx)); |
2847 |
|
} |
2848 |
|
reg = ((modrm >> 3) & 7) | rex_r; |
2849 |
|
gen_op_mov_reg_T0[OT_LONG][reg](); |
2850 |
|
break; |
2851 |
|
default: |
2852 |
|
goto illegal_op; |
2853 |
|
} |
2854 |
|
} else { |
2855 |
|
/* generic MMX or SSE operation */ |
2856 |
|
if (b == 0xf7) { |
2857 |
|
/* maskmov : we must prepare A0 */ |
2858 |
|
if (mod != 3) |
2859 |
|
goto illegal_op; |
2860 |
|
#ifdef TARGET_X86_64 |
2861 |
|
if (CODE64(s)) { |
2862 |
|
gen_op_movq_A0_reg[R_EDI](); |
2863 |
|
} else |
2864 |
|
#endif |
2865 |
|
{ |
2866 |
|
gen_op_movl_A0_reg[R_EDI](); |
2867 |
|
if (s->aflag == 0) |
2868 |
|
gen_op_andl_A0_ffff(); |
2869 |
|
} |
2870 |
|
gen_add_A0_ds_seg(s); |
2871 |
|
} |
2872 |
|
if (is_xmm) { |
2873 |
|
op1_offset = offsetof(CPUX86State,xmm_regs[reg]); |
2874 |
|
if (mod != 3) { |
2875 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2876 |
|
op2_offset = offsetof(CPUX86State,xmm_t0); |
2877 |
|
if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f) || |
2878 |
|
b == 0xc2)) { |
2879 |
|
/* specific case for SSE single instructions */ |
2880 |
|
if (b1 == 2) { |
2881 |
|
/* 32 bit access */ |
2882 |
|
gen_op_ld_T0_A0[OT_LONG + s->mem_index](); |
2883 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0))); |
2884 |
|
} else { |
2885 |
|
/* 64 bit access */ |
2886 |
|
gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_D(0))); |
2887 |
|
} |
2888 |
|
} else { |
2889 |
|
gen_ldo_env_A0[s->mem_index >> 2](op2_offset); |
2890 |
|
} |
2891 |
|
} else { |
2892 |
|
rm = (modrm & 7) | REX_B(s); |
2893 |
|
op2_offset = offsetof(CPUX86State,xmm_regs[rm]); |
2894 |
|
} |
2895 |
|
} else { |
2896 |
|
op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); |
2897 |
|
if (mod != 3) { |
2898 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2899 |
|
op2_offset = offsetof(CPUX86State,mmx_t0); |
2900 |
|
gen_ldq_env_A0[s->mem_index >> 2](op2_offset); |
2901 |
|
} else { |
2902 |
|
rm = (modrm & 7); |
2903 |
|
op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); |
2904 |
|
} |
2905 |
|
} |
2906 |
|
switch(b) { |
2907 |
|
case 0x70: /* pshufx insn */ |
2908 |
|
case 0xc6: /* pshufx insn */ |
2909 |
|
val = ldub_code(s->pc++); |
2910 |
|
sse_op3 = (GenOpFunc3 *)sse_op2; |
2911 |
|
sse_op3(op1_offset, op2_offset, val); |
2912 |
|
break; |
2913 |
|
case 0xc2: |
2914 |
|
/* compare insns */ |
2915 |
|
val = ldub_code(s->pc++); |
2916 |
|
if (val >= 8) |
2917 |
|
goto illegal_op; |
2918 |
|
sse_op2 = sse_op_table4[val][b1]; |
2919 |
|
sse_op2(op1_offset, op2_offset); |
2920 |
|
break; |
2921 |
|
default: |
2922 |
|
sse_op2(op1_offset, op2_offset); |
2923 |
|
break; |
2924 |
|
} |
2925 |
|
if (b == 0x2e || b == 0x2f) { |
2926 |
|
s->cc_op = CC_OP_EFLAGS; |
2927 |
|
} |
2928 |
|
} |
2929 |
|
} |
2930 |
|
|
2931 |
|
|
2932 |
/* convert one instruction. s->is_jmp is set if the translation must |
/* convert one instruction. s->is_jmp is set if the translation must |
2933 |
be stopped. Return the next pc value */ |
be stopped. Return the next pc value */ |
2934 |
static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
3896 |
} |
} |
3897 |
gen_op_movl_A0_im(offset_addr); |
gen_op_movl_A0_im(offset_addr); |
3898 |
} |
} |
3899 |
/* handle override */ |
gen_add_A0_ds_seg(s); |
|
{ |
|
|
int override, must_add_seg; |
|
|
must_add_seg = s->addseg; |
|
|
if (s->override >= 0) { |
|
|
override = s->override; |
|
|
must_add_seg = 1; |
|
|
} else { |
|
|
override = R_DS; |
|
|
} |
|
|
if (must_add_seg) { |
|
|
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
|
|
} |
|
|
} |
|
3900 |
if ((b & 2) == 0) { |
if ((b & 2) == 0) { |
3901 |
gen_op_ld_T0_A0[ot + s->mem_index](); |
gen_op_ld_T0_A0[ot + s->mem_index](); |
3902 |
gen_op_mov_reg_T0[ot][R_EAX](); |
gen_op_mov_reg_T0[ot][R_EAX](); |
3919 |
if (s->aflag == 0) |
if (s->aflag == 0) |
3920 |
gen_op_andl_A0_ffff(); |
gen_op_andl_A0_ffff(); |
3921 |
} |
} |
3922 |
/* handle override */ |
gen_add_A0_ds_seg(s); |
|
{ |
|
|
int override, must_add_seg; |
|
|
must_add_seg = s->addseg; |
|
|
override = R_DS; |
|
|
if (s->override >= 0) { |
|
|
override = s->override; |
|
|
must_add_seg = 1; |
|
|
} else { |
|
|
override = R_DS; |
|
|
} |
|
|
if (must_add_seg) { |
|
|
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
|
|
} |
|
|
} |
|
3923 |
gen_op_ldu_T0_A0[OT_BYTE + s->mem_index](); |
gen_op_ldu_T0_A0[OT_BYTE + s->mem_index](); |
3924 |
gen_op_mov_reg_T0[OT_BYTE][R_EAX](); |
gen_op_mov_reg_T0[OT_BYTE][R_EAX](); |
3925 |
break; |
break; |
5520 |
/* nothing to do */ |
/* nothing to do */ |
5521 |
} |
} |
5522 |
break; |
break; |
|
case 0x1ae: |
|
|
modrm = ldub_code(s->pc++); |
|
|
mod = (modrm >> 6) & 3; |
|
|
op = (modrm >> 3) & 7; |
|
|
switch(op) { |
|
|
case 0: /* fxsave */ |
|
|
if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) |
|
|
goto illegal_op; |
|
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
|
gen_op_fxsave_A0((s->dflag == 2)); |
|
|
break; |
|
|
case 1: /* fxrstor */ |
|
|
if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) |
|
|
goto illegal_op; |
|
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
|
gen_op_fxrstor_A0((s->dflag == 2)); |
|
|
break; |
|
|
case 5: /* lfence */ |
|
|
case 6: /* mfence */ |
|
|
case 7: /* sfence */ |
|
|
if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) |
|
|
goto illegal_op; |
|
|
break; |
|
|
default: |
|
|
goto illegal_op; |
|
|
} |
|
|
break; |
|
5523 |
case 0x63: /* arpl or movslS (x86_64) */ |
case 0x63: /* arpl or movslS (x86_64) */ |
5524 |
#ifdef TARGET_X86_64 |
#ifdef TARGET_X86_64 |
5525 |
if (CODE64(s)) { |
if (CODE64(s)) { |
5684 |
gen_eob(s); |
gen_eob(s); |
5685 |
} |
} |
5686 |
break; |
break; |
5687 |
/* SSE support */ |
/* MMX/SSE/SSE2/PNI support */ |
5688 |
case 0x16f: |
case 0x1c3: /* MOVNTI reg, mem */ |
5689 |
if (prefixes & PREFIX_DATA) { |
if (!(s->cpuid_features & CPUID_SSE2)) |
|
/* movdqa xmm1, xmm2/mem128 */ |
|
|
if (!(s->cpuid_features & CPUID_SSE)) |
|
|
goto illegal_op; |
|
|
modrm = ldub_code(s->pc++); |
|
|
reg = ((modrm >> 3) & 7) | rex_r; |
|
|
mod = (modrm >> 6) & 3; |
|
|
if (mod != 3) { |
|
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
|
gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); |
|
|
} else { |
|
|
rm = (modrm & 7) | REX_B(s); |
|
|
gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]), |
|
|
offsetof(CPUX86State,xmm_regs[rm])); |
|
|
} |
|
|
} else { |
|
5690 |
goto illegal_op; |
goto illegal_op; |
5691 |
} |
ot = s->dflag == 2 ? OT_QUAD : OT_LONG; |
5692 |
|
modrm = ldub_code(s->pc++); |
5693 |
|
mod = (modrm >> 6) & 3; |
5694 |
|
if (mod == 3) |
5695 |
|
goto illegal_op; |
5696 |
|
reg = ((modrm >> 3) & 7) | rex_r; |
5697 |
|
/* generate a generic store */ |
5698 |
|
gen_ldst_modrm(s, modrm, ot, reg, 1); |
5699 |
break; |
break; |
5700 |
case 0x1e7: |
case 0x1ae: |
5701 |
if (prefixes & PREFIX_DATA) { |
modrm = ldub_code(s->pc++); |
5702 |
/* movntdq mem128, xmm1 */ |
mod = (modrm >> 6) & 3; |
5703 |
if (!(s->cpuid_features & CPUID_SSE)) |
op = (modrm >> 3) & 7; |
5704 |
|
switch(op) { |
5705 |
|
case 0: /* fxsave */ |
5706 |
|
if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) |
5707 |
goto illegal_op; |
goto illegal_op; |
5708 |
modrm = ldub_code(s->pc++); |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
5709 |
reg = ((modrm >> 3) & 7) | rex_r; |
gen_op_fxsave_A0((s->dflag == 2)); |
5710 |
mod = (modrm >> 6) & 3; |
break; |
5711 |
if (mod != 3) { |
case 1: /* fxrstor */ |
5712 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) |
|
gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); |
|
|
} else { |
|
5713 |
goto illegal_op; |
goto illegal_op; |
5714 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
5715 |
|
gen_op_fxrstor_A0((s->dflag == 2)); |
5716 |
|
break; |
5717 |
|
case 2: /* ldmxcsr */ |
5718 |
|
case 3: /* stmxcsr */ |
5719 |
|
if (s->flags & HF_TS_MASK) { |
5720 |
|
gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); |
5721 |
|
break; |
5722 |
} |
} |
5723 |
} else { |
if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) || |
5724 |
goto illegal_op; |
mod == 3) |
|
} |
|
|
break; |
|
|
case 0x17f: |
|
|
if (prefixes & PREFIX_DATA) { |
|
|
/* movdqa xmm2/mem128, xmm1 */ |
|
|
if (!(s->cpuid_features & CPUID_SSE)) |
|
5725 |
goto illegal_op; |
goto illegal_op; |
5726 |
modrm = ldub_code(s->pc++); |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
5727 |
reg = ((modrm >> 3) & 7) | rex_r; |
if (op == 2) { |
5728 |
mod = (modrm >> 6) & 3; |
gen_op_ld_T0_A0[OT_LONG + s->mem_index](); |
5729 |
if (mod != 3) { |
gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr)); |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
|
gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); |
|
5730 |
} else { |
} else { |
5731 |
rm = (modrm & 7) | REX_B(s); |
gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr)); |
5732 |
gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]), |
gen_op_st_T0_A0[OT_LONG + s->mem_index](); |
|
offsetof(CPUX86State,xmm_regs[reg])); |
|
5733 |
} |
} |
5734 |
} else { |
break; |
5735 |
|
case 5: /* lfence */ |
5736 |
|
case 6: /* mfence */ |
5737 |
|
case 7: /* sfence */ |
5738 |
|
if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) |
5739 |
|
goto illegal_op; |
5740 |
|
break; |
5741 |
|
default: |
5742 |
goto illegal_op; |
goto illegal_op; |
5743 |
} |
} |
5744 |
break; |
break; |
5745 |
|
case 0x110 ... 0x117: |
5746 |
|
case 0x128 ... 0x12f: |
5747 |
|
case 0x150 ... 0x177: |
5748 |
|
case 0x17c ... 0x17f: |
5749 |
|
case 0x1c2: |
5750 |
|
case 0x1c4 ... 0x1c6: |
5751 |
|
case 0x1d0 ... 0x1fe: |
5752 |
|
gen_sse(s, b, pc_start, rex_r); |
5753 |
|
break; |
5754 |
default: |
default: |
5755 |
goto illegal_op; |
goto illegal_op; |
5756 |
} |
} |
5924 |
[INDEX_op_imull_T0_T1] = CC_OSZAPC, |
[INDEX_op_imull_T0_T1] = CC_OSZAPC, |
5925 |
X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,) |
X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,) |
5926 |
|
|
5927 |
|
/* sse */ |
5928 |
|
[INDEX_op_ucomiss] = CC_OSZAPC, |
5929 |
|
[INDEX_op_ucomisd] = CC_OSZAPC, |
5930 |
|
[INDEX_op_comiss] = CC_OSZAPC, |
5931 |
|
[INDEX_op_comisd] = CC_OSZAPC, |
5932 |
|
|
5933 |
/* bcd */ |
/* bcd */ |
5934 |
[INDEX_op_aam] = CC_OSZAPC, |
[INDEX_op_aam] = CC_OSZAPC, |
5935 |
[INDEX_op_aad] = CC_OSZAPC, |
[INDEX_op_aad] = CC_OSZAPC, |