Revision a35f3ec7 target-i386/translate.c
b/target-i386/translate.c | ||
---|---|---|
2408 | 2408 |
}; |
2409 | 2409 |
|
2410 | 2410 |
#define SSE_SPECIAL ((GenOpFunc2 *)1) |
2411 |
#define SSE_DUMMY ((GenOpFunc2 *)2) |
|
2411 | 2412 |
|
2412 | 2413 |
#define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm } |
2413 | 2414 |
#define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \ |
2414 | 2415 |
gen_op_ ## x ## ss, gen_op_ ## x ## sd, } |
2415 | 2416 |
|
2416 | 2417 |
static GenOpFunc2 *sse_op_table1[256][4] = { |
2418 |
/* 3DNow! extensions */ |
|
2419 |
[0x0e] = { SSE_DUMMY }, /* femms */ |
|
2420 |
[0x0f] = { SSE_DUMMY }, /* pf... */ |
|
2417 | 2421 |
/* pure SSE operations */ |
2418 | 2422 |
[0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ |
2419 | 2423 |
[0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ |
... | ... | |
2480 | 2484 |
[0x74] = MMX_OP2(pcmpeqb), |
2481 | 2485 |
[0x75] = MMX_OP2(pcmpeqw), |
2482 | 2486 |
[0x76] = MMX_OP2(pcmpeql), |
2483 |
[0x77] = { SSE_SPECIAL }, /* emms */
|
|
2487 |
[0x77] = { SSE_DUMMY }, /* emms */
|
|
2484 | 2488 |
[0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps }, |
2485 | 2489 |
[0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps }, |
2486 | 2490 |
[0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */ |
... | ... | |
2577 | 2581 |
SSE_FOP(cmpord), |
2578 | 2582 |
}; |
2579 | 2583 |
|
2584 |
static GenOpFunc2 *sse_op_table5[256] = { |
|
2585 |
[0x0c] = gen_op_pi2fw, |
|
2586 |
[0x0d] = gen_op_pi2fd, |
|
2587 |
[0x1c] = gen_op_pf2iw, |
|
2588 |
[0x1d] = gen_op_pf2id, |
|
2589 |
[0x8a] = gen_op_pfnacc, |
|
2590 |
[0x8e] = gen_op_pfpnacc, |
|
2591 |
[0x90] = gen_op_pfcmpge, |
|
2592 |
[0x94] = gen_op_pfmin, |
|
2593 |
[0x96] = gen_op_pfrcp, |
|
2594 |
[0x97] = gen_op_pfrsqrt, |
|
2595 |
[0x9a] = gen_op_pfsub, |
|
2596 |
[0x9e] = gen_op_pfadd, |
|
2597 |
[0xa0] = gen_op_pfcmpgt, |
|
2598 |
[0xa4] = gen_op_pfmax, |
|
2599 |
[0xa6] = gen_op_movq, /* pfrcpit1; no need to actually increase precision */ |
|
2600 |
[0xa7] = gen_op_movq, /* pfrsqit1 */ |
|
2601 |
[0xaa] = gen_op_pfsubr, |
|
2602 |
[0xae] = gen_op_pfacc, |
|
2603 |
[0xb0] = gen_op_pfcmpeq, |
|
2604 |
[0xb4] = gen_op_pfmul, |
|
2605 |
[0xb6] = gen_op_movq, /* pfrcpit2 */ |
|
2606 |
[0xb7] = gen_op_pmulhrw_mmx, |
|
2607 |
[0xbb] = gen_op_pswapd, |
|
2608 |
[0xbf] = gen_op_pavgb_mmx /* pavgusb */ |
|
2609 |
}; |
|
2610 |
|
|
2580 | 2611 |
static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) |
2581 | 2612 |
{ |
2582 | 2613 |
int b1, op1_offset, op2_offset, is_xmm, val, ot; |
... | ... | |
2596 | 2627 |
sse_op2 = sse_op_table1[b][b1]; |
2597 | 2628 |
if (!sse_op2) |
2598 | 2629 |
goto illegal_op; |
2599 |
if (b <= 0x5f || b == 0xc6 || b == 0xc2) {
|
|
2630 |
if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
|
|
2600 | 2631 |
is_xmm = 1; |
2601 | 2632 |
} else { |
2602 | 2633 |
if (b1 == 0) { |
... | ... | |
2618 | 2649 |
} |
2619 | 2650 |
if (is_xmm && !(s->flags & HF_OSFXSR_MASK)) |
2620 | 2651 |
goto illegal_op; |
2621 |
if (b == 0x77) { |
|
2622 |
/* emms */ |
|
2652 |
if (b == 0x77 || b == 0x0e) {
|
|
2653 |
/* emms or femms */
|
|
2623 | 2654 |
gen_op_emms(); |
2624 | 2655 |
return; |
2625 | 2656 |
} |
... | ... | |
3151 | 3182 |
} |
3152 | 3183 |
} |
3153 | 3184 |
switch(b) { |
3185 |
case 0x0f: /* 3DNow! data insns */ |
|
3186 |
val = ldub_code(s->pc++); |
|
3187 |
sse_op2 = sse_op_table5[val]; |
|
3188 |
if (!sse_op2) |
|
3189 |
goto illegal_op; |
|
3190 |
sse_op2(op1_offset, op2_offset); |
|
3191 |
break; |
|
3154 | 3192 |
case 0x70: /* pshufx insn */ |
3155 | 3193 |
case 0xc6: /* pshufx insn */ |
3156 | 3194 |
val = ldub_code(s->pc++); |
... | ... | |
6148 | 6186 |
gen_eob(s); |
6149 | 6187 |
} |
6150 | 6188 |
break; |
6151 |
/* MMX/SSE/SSE2/PNI support */
|
|
6189 |
/* MMX/3DNow!/SSE/SSE2/SSE3 support */
|
|
6152 | 6190 |
case 0x1c3: /* MOVNTI reg, mem */ |
6153 | 6191 |
if (!(s->cpuid_features & CPUID_SSE2)) |
6154 | 6192 |
goto illegal_op; |
... | ... | |
6214 | 6252 |
case 7: /* sfence / clflush */ |
6215 | 6253 |
if ((modrm & 0xc7) == 0xc0) { |
6216 | 6254 |
/* sfence */ |
6255 |
/* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */ |
|
6217 | 6256 |
if (!(s->cpuid_features & CPUID_SSE)) |
6218 | 6257 |
goto illegal_op; |
6219 | 6258 |
} else { |
... | ... | |
6227 | 6266 |
goto illegal_op; |
6228 | 6267 |
} |
6229 | 6268 |
break; |
6230 |
case 0x10d: /* prefetch */
|
|
6269 |
case 0x10d: /* 3DNow! prefetch(w) */
|
|
6231 | 6270 |
modrm = ldub_code(s->pc++); |
6271 |
mod = (modrm >> 6) & 3; |
|
6272 |
if (mod == 3) |
|
6273 |
goto illegal_op; |
|
6232 | 6274 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
6233 | 6275 |
/* ignore for now */ |
6234 | 6276 |
break; |
... | ... | |
6245 | 6287 |
gen_op_rsm(); |
6246 | 6288 |
gen_eob(s); |
6247 | 6289 |
break; |
6290 |
case 0x10e ... 0x10f: |
|
6291 |
/* 3DNow! instructions, ignore prefixes */ |
|
6292 |
s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA); |
|
6248 | 6293 |
case 0x110 ... 0x117: |
6249 | 6294 |
case 0x128 ... 0x12f: |
6250 | 6295 |
case 0x150 ... 0x177: |
Also available in: Unified diff