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, &reg_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