Revision 5a5012ec target-mips/translate.c

b/target-mips/translate.c
333 333
    OPC_MFC1     = (0x00 << 21) | OPC_CP1,
334 334
    OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
335 335
    OPC_CFC1     = (0x02 << 21) | OPC_CP1,
336
    OPC_MFHCI    = (0x03 << 21) | OPC_CP1,
336
    OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
337 337
    OPC_MTC1     = (0x04 << 21) | OPC_CP1,
338 338
    OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
339 339
    OPC_CTC1     = (0x06 << 21) | OPC_CP1,
340
    OPC_MTHCI    = (0x07 << 21) | OPC_CP1,
340
    OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
341 341
    OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
342
    OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
343
    OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
342 344
    OPC_S_FMT    = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
343 345
    OPC_D_FMT    = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
344 346
    OPC_E_FMT    = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
345 347
    OPC_Q_FMT    = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
346 348
    OPC_W_FMT    = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
347 349
    OPC_L_FMT    = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
350
    OPC_PS_FMT   = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
348 351
};
349 352

  
353
#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
354
#define MASK_BC1(op)            MASK_CP1(op) | (op & (0x3 << 16))
355

  
350 356
enum {
351 357
    OPC_BC1F     = (0x00 << 16) | OPC_BC1,
352 358
    OPC_BC1T     = (0x01 << 16) | OPC_BC1,
......
354 360
    OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
355 361
};
356 362

  
357
#define MASK_CP1_BCOND(op)      MASK_CP1(op) | (op & (0x3 << 16))
358
#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
363
enum {
364
    OPC_BC1FANY2     = (0x00 << 16) | OPC_BC1ANY2,
365
    OPC_BC1TANY2     = (0x01 << 16) | OPC_BC1ANY2,
366
};
367

  
368
enum {
369
    OPC_BC1FANY4     = (0x00 << 16) | OPC_BC1ANY4,
370
    OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
371
};
359 372

  
360 373
#define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
361 374

  
......
404 417
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
405 418

  
406 419
/* Warning: no function for r0 register (hard wired to zero) */
407
#define GEN32(func, NAME) \
408
static GenOpFunc *NAME ## _table [32] = {                                     \
409
NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
410
NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
411
NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
412
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
413
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
414
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
415
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
416
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
417
};                                                                            \
418
static inline void func(int n)                                                \
419
{                                                                             \
420
    NAME ## _table[n]();                                                      \
420
#define GEN32(func, NAME)                        \
421
static GenOpFunc *NAME ## _table [32] = {        \
422
NULL,       NAME ## 1, NAME ## 2, NAME ## 3,     \
423
NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,     \
424
NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,   \
425
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,  \
426
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,  \
427
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,  \
428
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,  \
429
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,  \
430
};                                               \
431
static inline void func(int n)                   \
432
{                                                \
433
    NAME ## _table[n]();                         \
421 434
}
422 435

  
423 436
/* General purpose registers moves */
......
434 447
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
435 448
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
436 449

  
437
# define SFGEN32(func, NAME) \
438
static GenOpFunc *NAME ## _table [32] = {                                     \
439
NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
440
NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
441
NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
442
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
443
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
444
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
445
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
446
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
447
};                                                                            \
448
static inline void func(int n)                                                \
449
{                                                                             \
450
    NAME ## _table[n]();                                                      \
450
#define FGEN32(func, NAME)                       \
451
static GenOpFunc *NAME ## _table [32] = {        \
452
NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,   \
453
NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,   \
454
NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,  \
455
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,  \
456
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,  \
457
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,  \
458
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,  \
459
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,  \
460
};                                               \
461
static inline void func(int n)                   \
462
{                                                \
463
    NAME ## _table[n]();                         \
451 464
}
452 465

  
453
# define DFGEN32(func, NAME) \
454
static GenOpFunc *NAME ## _table [32] = {                                     \
455
NAME ## 0,  0, NAME ## 2,  0,                                                 \
456
NAME ## 4,  0, NAME ## 6,  0,                                                 \
457
NAME ## 8,  0, NAME ## 10, 0,                                                 \
458
NAME ## 12, 0, NAME ## 14, 0,                                                 \
459
NAME ## 16, 0, NAME ## 18, 0,                                                 \
460
NAME ## 20, 0, NAME ## 22, 0,                                                 \
461
NAME ## 24, 0, NAME ## 26, 0,                                                 \
462
NAME ## 28, 0, NAME ## 30, 0,                                                 \
463
};                                                                            \
464
static inline void func(int n)                                                \
465
{                                                                             \
466
    NAME ## _table[n]();                                                      \
467
}
466
FGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
467
FGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
468

  
469
FGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
470
FGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
468 471

  
469
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
470
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
472
FGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
473
FGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
471 474

  
472
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
473
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
475
FGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
476
FGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
474 477

  
475
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
476
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
478
FGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
479
FGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
477 480

  
478
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
479
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
481
FGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
482
FGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
480 483

  
481
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
482
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
484
FGEN32(gen_op_load_fpr_WTH0,  gen_op_load_fpr_WTH0_fpr);
485
FGEN32(gen_op_store_fpr_WTH0, gen_op_store_fpr_WTH0_fpr);
483 486

  
484
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
485
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
487
FGEN32(gen_op_load_fpr_WTH1,  gen_op_load_fpr_WTH1_fpr);
488
FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr);
489

  
490
FGEN32(gen_op_load_fpr_WTH2,  gen_op_load_fpr_WTH2_fpr);
491
FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr);
486 492

  
487 493
#define FOP_CONDS(fmt) \
488
static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
494
static GenOpFunc1 * cond_ ## fmt ## _table[16] = {                      \
489 495
    gen_op_cmp_ ## fmt ## _f,                                           \
490 496
    gen_op_cmp_ ## fmt ## _un,                                          \
491 497
    gen_op_cmp_ ## fmt ## _eq,                                          \
......
503 509
    gen_op_cmp_ ## fmt ## _le,                                          \
504 510
    gen_op_cmp_ ## fmt ## _ngt,                                         \
505 511
};                                                                      \
506
static inline void gen_cmp_ ## fmt(int n)                               \
512
static inline void gen_cmp_ ## fmt(int n, long cc)                      \
507 513
{                                                                       \
508
    cond_ ## fmt ## _table[n]();                                        \
514
    cond_ ## fmt ## _table[n](cc);                                      \
509 515
}
510 516

  
511 517
FOP_CONDS(d)
512 518
FOP_CONDS(s)
519
FOP_CONDS(ps)
513 520

  
514 521
typedef struct DisasContext {
515 522
    struct TranslationBlock *tb;
516 523
    target_ulong pc, saved_pc;
517 524
    uint32_t opcode;
525
    uint32_t fp_status, saved_fp_status;
518 526
    /* Routine used to access memory */
519 527
    int mem_idx;
520 528
    uint32_t hflags, saved_hflags;
......
600 608
    if (ctx->hflags != ctx->saved_hflags) {
601 609
        gen_op_save_state(ctx->hflags);
602 610
        ctx->saved_hflags = ctx->hflags;
603
        if (ctx->hflags & MIPS_HFLAG_BR) {
611
        switch (ctx->hflags & MIPS_HFLAG_BMASK) {
612
        case MIPS_HFLAG_BR:
604 613
            gen_op_save_breg_target();
605
        } else if (ctx->hflags & MIPS_HFLAG_B) {
606
            gen_op_save_btarget(ctx->btarget);
607
        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
614
            break;
615
        case MIPS_HFLAG_BC:
608 616
            gen_op_save_bcond();
617
            /* fall through */
618
        case MIPS_HFLAG_BL:
619
            /* bcond was already saved by the BL insn */
620
            /* fall through */
621
        case MIPS_HFLAG_B:
609 622
            gen_op_save_btarget(ctx->btarget);
623
            break;
610 624
        }
611 625
    }
612 626
}
613 627

  
628
static inline void save_fpu_state (DisasContext *ctx)
629
{
630
    if (ctx->fp_status != ctx->saved_fp_status) {
631
        gen_op_save_fp_status(ctx->fp_status);
632
        ctx->saved_fp_status = ctx->fp_status;
633
    }
634
}
635

  
614 636
static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
615 637
{
616 638
#if defined MIPS_DEBUG_DISAS
......
677 699
OP_ST_TABLE(wc1);
678 700
OP_LD_TABLE(dc1);
679 701
OP_ST_TABLE(dc1);
702
OP_LD_TABLE(wxc1);
703
OP_ST_TABLE(wxc1);
704
OP_LD_TABLE(dxc1);
705
OP_ST_TABLE(dxc1);
706
OP_LD_TABLE(uxc1);
707
OP_ST_TABLE(uxc1);
680 708

  
681 709
/* Load and store */
682 710
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
......
1472 1500
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
1473 1501
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1474 1502
            fprintf(logfile,
1475
                    "undefined branch in delay slot at PC " TARGET_FMT_lx "\n",
1503
                    "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
1476 1504
                    ctx->pc);
1477 1505
	}
1478 1506
        MIPS_INVAL("branch/jump in bdelay slot");
......
1672 1700
            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1673 1701
        not_likely:
1674 1702
            ctx->hflags |= MIPS_HFLAG_BC;
1703
            gen_op_set_bcond();
1675 1704
            break;
1676 1705
        case OPC_BLTZALL:
1677 1706
            gen_op_ltz();
......
1679 1708
            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1680 1709
        likely:
1681 1710
            ctx->hflags |= MIPS_HFLAG_BL;
1711
            gen_op_set_bcond();
1712
            gen_op_save_bcond();
1682 1713
            break;
1683 1714
        default:
1684 1715
            MIPS_INVAL("conditional branch/jump");
1685 1716
            generate_exception(ctx, EXCP_RI);
1686 1717
            return;
1687 1718
        }
1688
        gen_op_set_bcond();
1689 1719
    }
1690 1720
    MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1691 1721
               blink, ctx->hflags, btarget);
......
4220 4250

  
4221 4251
/* CP1 Branches (before delay slot) */
4222 4252
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4223
                                 int32_t offset)
4253
                                 int32_t cc, int32_t offset)
4224 4254
{
4225 4255
    target_ulong btarget;
4226 4256

  
......
4228 4258

  
4229 4259
    switch (op) {
4230 4260
    case OPC_BC1F:
4231
        gen_op_bc1f();
4261
        gen_op_bc1f(cc);
4232 4262
        MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
4233 4263
        goto not_likely;
4234 4264
    case OPC_BC1FL:
4235
        gen_op_bc1f();
4265
        gen_op_bc1f(cc);
4236 4266
        MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
4237 4267
        goto likely;
4238 4268
    case OPC_BC1T:
4239
        gen_op_bc1t();
4269
        gen_op_bc1t(cc);
4240 4270
        MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
4241
    not_likely:
4242
        ctx->hflags |= MIPS_HFLAG_BC;
4243
        break;
4271
        goto not_likely;
4244 4272
    case OPC_BC1TL:
4245
        gen_op_bc1t();
4273
        gen_op_bc1t(cc);
4246 4274
        MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
4247 4275
    likely:
4248 4276
        ctx->hflags |= MIPS_HFLAG_BL;
4277
        gen_op_set_bcond();
4278
        gen_op_save_bcond();
4249 4279
        break;
4250
    default:    
4251
        MIPS_INVAL("cp1 branch/jump");
4280
    case OPC_BC1FANY2:
4281
        gen_op_bc1fany2(cc);
4282
        MIPS_DEBUG("bc1fany2 " TARGET_FMT_lx, btarget);
4283
        goto not_likely;
4284
    case OPC_BC1TANY2:
4285
        gen_op_bc1tany2(cc);
4286
        MIPS_DEBUG("bc1tany2 " TARGET_FMT_lx, btarget);
4287
        goto not_likely;
4288
    case OPC_BC1FANY4:
4289
        gen_op_bc1fany4(cc);
4290
        MIPS_DEBUG("bc1fany4 " TARGET_FMT_lx, btarget);
4291
        goto not_likely;
4292
    case OPC_BC1TANY4:
4293
        gen_op_bc1tany4(cc);
4294
        MIPS_DEBUG("bc1tany4 " TARGET_FMT_lx, btarget);
4295
    not_likely:
4296
        ctx->hflags |= MIPS_HFLAG_BC;
4297
        gen_op_set_bcond();
4298
        break;
4299
    default:
4300
        MIPS_INVAL("cp1 branch");
4252 4301
        generate_exception (ctx, EXCP_RI);
4253 4302
        return;
4254 4303
    }
4255
    gen_op_set_bcond();
4256 4304

  
4257 4305
    MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4258 4306
               ctx->hflags, btarget);
......
4262 4310
}
4263 4311

  
4264 4312
/* Coprocessor 1 (FPU) */
4313

  
4314
/* verify if floating point register is valid; an operation is not defined
4315
 * if bit 0 of any register specification is set and the FR bit in the
4316
 * Status register equals zero, since the register numbers specify an
4317
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
4318
 * in the Status register equals one, both even and odd register numbers
4319
 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
4320
 * 
4321
 * Multiple 64 bit wide registers can be checked by calling
4322
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4323
 * 
4324
 * FIXME: This is broken for R2, it needs to be checked at runtime, not
4325
 * at translation time.
4326
 */
4327
#define CHECK_FR(ctx, freg) do { \
4328
        if (!((ctx)->CP0_Status & (1 << CP0St_FR)) && ((freg) & 1)) { \
4329
            generate_exception (ctx, EXCP_RI); \
4330
            return; \
4331
        } \
4332
    } while(0)
4333

  
4334
#define FOP(func, fmt) (((fmt) << 21) | (func))
4335

  
4265 4336
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4266 4337
{
4267 4338
    const char *opn = "unk";
......
4280 4351
        opn = "mtc1";
4281 4352
        break;
4282 4353
    case OPC_CFC1:
4283
        if (fs != 0 && fs != 31) {
4284
            MIPS_INVAL("cfc1 freg");
4285
            generate_exception (ctx, EXCP_RI);
4286
            return;
4287
        }
4288 4354
        GEN_LOAD_IMM_TN(T1, fs);
4289 4355
        gen_op_cfc1();
4290 4356
        GEN_STORE_TN_REG(rt, T0);
4291 4357
        opn = "cfc1";
4292 4358
        break;
4293 4359
    case OPC_CTC1:
4294
         if (fs != 0 && fs != 31) {
4295
            MIPS_INVAL("ctc1 freg");
4296
            generate_exception (ctx, EXCP_RI);
4297
            return;
4298
        }
4299 4360
        GEN_LOAD_IMM_TN(T1, fs);
4300 4361
        GEN_LOAD_REG_TN(T0, rt);
4301 4362
        gen_op_ctc1();
4302 4363
        opn = "ctc1";
4303 4364
        break;
4304 4365
    case OPC_DMFC1:
4366
        GEN_LOAD_FREG_FTN(DT0, fs);
4367
        gen_op_dmfc1();
4368
        GEN_STORE_TN_REG(rt, T0);
4369
        opn = "dmfc1";
4370
        break;
4305 4371
    case OPC_DMTC1:
4306
        /* Not implemented, fallthrough. */
4372
        GEN_LOAD_REG_TN(T0, rt);
4373
        gen_op_dmtc1();
4374
        GEN_STORE_FTN_FREG(fs, DT0);
4375
        opn = "dmtc1";
4376
        break;
4377
    case OPC_MFHC1:
4378
        CHECK_FR(ctx, fs);
4379
        GEN_LOAD_FREG_FTN(WTH0, fs);
4380
        gen_op_mfhc1();
4381
        GEN_STORE_TN_REG(rt, T0);
4382
        opn = "mfhc1";
4383
        break;
4384
    case OPC_MTHC1:
4385
        CHECK_FR(ctx, fs);
4386
        GEN_LOAD_REG_TN(T0, rt);
4387
        gen_op_mthc1();
4388
        GEN_STORE_FTN_FREG(fs, WTH0);
4389
        opn = "mthc1";
4390
        break;
4307 4391
    default:
4308 4392
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4309 4393
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
......
4316 4400
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4317 4401
}
4318 4402

  
4319
/* verify if floating point register is valid; an operation is not defined
4320
 * if bit 0 of any register specification is set and the FR bit in the
4321
 * Status register equals zero, since the register numbers specify an
4322
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
4323
 * in the Status register equals one, both even and odd register numbers
4324
 * are valid. This limitation exists only for 64 bit wide (d,l) registers.
4325
 * 
4326
 * Multiple 64 bit wide registers can be checked by calling
4327
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4328
 */
4329
#define CHECK_FR(ctx, freg) do { \
4330
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
4331
            generate_exception (ctx, EXCP_RI); \
4332
            return; \
4333
        } \
4334
    } while(0)
4403
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4404
{
4405
    uint32_t ccbit;
4335 4406

  
4336
#define FOP(func, fmt) (((fmt) << 21) | (func))
4407
    GEN_LOAD_REG_TN(T0, rd);
4408
    GEN_LOAD_REG_TN(T1, rs);
4409
    if (cc)
4410
        ccbit = 1 << (24 + cc);
4411
    else
4412
        ccbit = 1 << 23;
4413
    if (!tf)
4414
        gen_op_movf(ccbit);
4415
    else
4416
        gen_op_movt(ccbit);
4417
    GEN_STORE_TN_REG(rd, T0);
4418
}
4419

  
4420
#define GEN_MOVCF(fmt)                                                \
4421
static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
4422
{                                                                     \
4423
    uint32_t ccbit;                                                   \
4424
                                                                      \
4425
    if (cc)                                                           \
4426
        ccbit = 1 << (24 + cc);                                       \
4427
    else                                                              \
4428
        ccbit = 1 << 23;                                              \
4429
    if (!tf)                                                          \
4430
        glue(gen_op_float_movf_, fmt)(ccbit);                         \
4431
    else                                                              \
4432
        glue(gen_op_float_movt_, fmt)(ccbit);                         \
4433
}
4434
GEN_MOVCF(d);
4435
GEN_MOVCF(s);
4436
GEN_MOVCF(ps);
4437
#undef GEN_MOVCF
4337 4438

  
4338
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4439
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4440
                        int fs, int fd, int cc)
4339 4441
{
4340 4442
    const char *opn = "unk";
4341 4443
    const char *condnames[] = {
......
4360 4462
    uint32_t func = ctx->opcode & 0x3f;
4361 4463

  
4362 4464
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
4465
    case FOP(0, 16):
4466
        GEN_LOAD_FREG_FTN(WT0, fs);
4467
        GEN_LOAD_FREG_FTN(WT1, ft);
4468
        gen_op_float_add_s();
4469
        GEN_STORE_FTN_FREG(fd, WT2);
4470
        opn = "add.s";
4471
        binary = 1;
4472
        break;
4473
    case FOP(1, 16):
4474
        GEN_LOAD_FREG_FTN(WT0, fs);
4475
        GEN_LOAD_FREG_FTN(WT1, ft);
4476
        gen_op_float_sub_s();
4477
        GEN_STORE_FTN_FREG(fd, WT2);
4478
        opn = "sub.s";
4479
        binary = 1;
4480
        break;
4481
    case FOP(2, 16):
4482
        GEN_LOAD_FREG_FTN(WT0, fs);
4483
        GEN_LOAD_FREG_FTN(WT1, ft);
4484
        gen_op_float_mul_s();
4485
        GEN_STORE_FTN_FREG(fd, WT2);
4486
        opn = "mul.s";
4487
        binary = 1;
4488
        break;
4489
    case FOP(3, 16):
4490
        GEN_LOAD_FREG_FTN(WT0, fs);
4491
        GEN_LOAD_FREG_FTN(WT1, ft);
4492
        gen_op_float_div_s();
4493
        GEN_STORE_FTN_FREG(fd, WT2);
4494
        opn = "div.s";
4495
        binary = 1;
4496
        break;
4497
    case FOP(4, 16):
4498
        GEN_LOAD_FREG_FTN(WT0, fs);
4499
        gen_op_float_sqrt_s();
4500
        GEN_STORE_FTN_FREG(fd, WT2);
4501
        opn = "sqrt.s";
4502
        break;
4503
    case FOP(5, 16):
4504
        GEN_LOAD_FREG_FTN(WT0, fs);
4505
        gen_op_float_abs_s();
4506
        GEN_STORE_FTN_FREG(fd, WT2);
4507
        opn = "abs.s";
4508
        break;
4509
    case FOP(6, 16):
4510
        GEN_LOAD_FREG_FTN(WT0, fs);
4511
        gen_op_float_mov_s();
4512
        GEN_STORE_FTN_FREG(fd, WT2);
4513
        opn = "mov.s";
4514
        break;
4515
    case FOP(7, 16):
4516
        GEN_LOAD_FREG_FTN(WT0, fs);
4517
        gen_op_float_chs_s();
4518
        GEN_STORE_FTN_FREG(fd, WT2);
4519
        opn = "neg.s";
4520
        break;
4521
    case FOP(8, 16):
4522
        CHECK_FR(ctx, fs);
4523
        GEN_LOAD_FREG_FTN(WT0, fs);
4524
        gen_op_float_roundl_s();
4525
        GEN_STORE_FTN_FREG(fd, DT2);
4526
        opn = "round.l.s";
4527
        break;
4528
    case FOP(9, 16):
4529
        CHECK_FR(ctx, fs);
4530
        GEN_LOAD_FREG_FTN(WT0, fs);
4531
        gen_op_float_truncl_s();
4532
        GEN_STORE_FTN_FREG(fd, DT2);
4533
        opn = "trunc.l.s";
4534
        break;
4535
    case FOP(10, 16):
4536
        CHECK_FR(ctx, fs);
4537
        GEN_LOAD_FREG_FTN(WT0, fs);
4538
        gen_op_float_ceill_s();
4539
        GEN_STORE_FTN_FREG(fd, DT2);
4540
        opn = "ceil.l.s";
4541
        break;
4542
    case FOP(11, 16):
4543
        CHECK_FR(ctx, fs);
4544
        GEN_LOAD_FREG_FTN(WT0, fs);
4545
        gen_op_float_floorl_s();
4546
        GEN_STORE_FTN_FREG(fd, DT2);
4547
        opn = "floor.l.s";
4548
        break;
4549
    case FOP(12, 16):
4550
        GEN_LOAD_FREG_FTN(WT0, fs);
4551
        gen_op_float_roundw_s();
4552
        GEN_STORE_FTN_FREG(fd, WT2);
4553
        opn = "round.w.s";
4554
        break;
4555
    case FOP(13, 16):
4556
        GEN_LOAD_FREG_FTN(WT0, fs);
4557
        gen_op_float_truncw_s();
4558
        GEN_STORE_FTN_FREG(fd, WT2);
4559
        opn = "trunc.w.s";
4560
        break;
4561
    case FOP(14, 16):
4562
        GEN_LOAD_FREG_FTN(WT0, fs);
4563
        gen_op_float_ceilw_s();
4564
        GEN_STORE_FTN_FREG(fd, WT2);
4565
        opn = "ceil.w.s";
4566
        break;
4567
    case FOP(15, 16):
4568
        GEN_LOAD_FREG_FTN(WT0, fs);
4569
        gen_op_float_floorw_s();
4570
        GEN_STORE_FTN_FREG(fd, WT2);
4571
        opn = "floor.w.s";
4572
        break;
4573
    case FOP(17, 16):
4574
        GEN_LOAD_REG_TN(T0, ft);
4575
        GEN_LOAD_FREG_FTN(WT0, fs);
4576
        GEN_LOAD_FREG_FTN(WT2, fd);
4577
        gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
4578
        GEN_STORE_FTN_FREG(fd, WT2);
4579
        opn = "movcf.s";
4580
        break;
4581
    case FOP(18, 16):
4582
        GEN_LOAD_REG_TN(T0, ft);
4583
        GEN_LOAD_FREG_FTN(WT0, fs);
4584
        GEN_LOAD_FREG_FTN(WT2, fd);
4585
        gen_op_float_movz_s();
4586
        GEN_STORE_FTN_FREG(fd, WT2);
4587
        opn = "movz.s";
4588
        break;
4589
    case FOP(19, 16):
4590
        GEN_LOAD_REG_TN(T0, ft);
4591
        GEN_LOAD_FREG_FTN(WT0, fs);
4592
        GEN_LOAD_FREG_FTN(WT2, fd);
4593
        gen_op_float_movn_s();
4594
        GEN_STORE_FTN_FREG(fd, WT2);
4595
        opn = "movn.s";
4596
        break;
4597
    case FOP(33, 16):
4598
        CHECK_FR(ctx, fd);
4599
        GEN_LOAD_FREG_FTN(WT0, fs);
4600
        gen_op_float_cvtd_s();
4601
        GEN_STORE_FTN_FREG(fd, DT2);
4602
        opn = "cvt.d.s";
4603
        break;
4604
    case FOP(36, 16):
4605
        GEN_LOAD_FREG_FTN(WT0, fs);
4606
        gen_op_float_cvtw_s();
4607
        GEN_STORE_FTN_FREG(fd, WT2);
4608
        opn = "cvt.w.s";
4609
        break;
4610
    case FOP(37, 16):
4611
        CHECK_FR(ctx, fs | fd);
4612
        GEN_LOAD_FREG_FTN(WT0, fs);
4613
        gen_op_float_cvtl_s();
4614
        GEN_STORE_FTN_FREG(fd, DT2);
4615
        opn = "cvt.l.s";
4616
        break;
4617
    case FOP(38, 16):
4618
        CHECK_FR(ctx, fs | ft | fd);
4619
        GEN_LOAD_FREG_FTN(WT1, fs);
4620
        GEN_LOAD_FREG_FTN(WT0, ft);
4621
        gen_op_float_cvtps_s();
4622
        GEN_STORE_FTN_FREG(fd, DT2);
4623
        opn = "cvt.ps.s";
4624
        break;
4625
    case FOP(48, 16):
4626
    case FOP(49, 16):
4627
    case FOP(50, 16):
4628
    case FOP(51, 16):
4629
    case FOP(52, 16):
4630
    case FOP(53, 16):
4631
    case FOP(54, 16):
4632
    case FOP(55, 16):
4633
    case FOP(56, 16):
4634
    case FOP(57, 16):
4635
    case FOP(58, 16):
4636
    case FOP(59, 16):
4637
    case FOP(60, 16):
4638
    case FOP(61, 16):
4639
    case FOP(62, 16):
4640
    case FOP(63, 16):
4641
        GEN_LOAD_FREG_FTN(WT0, fs);
4642
        GEN_LOAD_FREG_FTN(WT1, ft);
4643
        gen_cmp_s(func-48, cc);
4644
        opn = condnames[func-48];
4645
        break;
4363 4646
    case FOP(0, 17):
4364 4647
        CHECK_FR(ctx, fs | ft | fd);
4365 4648
        GEN_LOAD_FREG_FTN(DT0, fs);
......
4424 4707
        GEN_STORE_FTN_FREG(fd, DT2);
4425 4708
        opn = "neg.d";
4426 4709
        break;
4427
    /*  8 - round.l */
4428
    /*  9 - trunc.l */
4429
    /* 10 - ceil.l  */
4430
    /* 11 - floor.l */
4710
    case FOP(8, 17):
4711
        CHECK_FR(ctx, fs);
4712
        GEN_LOAD_FREG_FTN(DT0, fs);
4713
        gen_op_float_roundl_d();
4714
        GEN_STORE_FTN_FREG(fd, DT2);
4715
        opn = "round.l.d";
4716
        break;
4717
    case FOP(9, 17):
4718
        CHECK_FR(ctx, fs);
4719
        GEN_LOAD_FREG_FTN(DT0, fs);
4720
        gen_op_float_truncl_d();
4721
        GEN_STORE_FTN_FREG(fd, DT2);
4722
        opn = "trunc.l.d";
4723
        break;
4724
    case FOP(10, 17):
4725
        CHECK_FR(ctx, fs);
4726
        GEN_LOAD_FREG_FTN(DT0, fs);
4727
        gen_op_float_ceill_d();
4728
        GEN_STORE_FTN_FREG(fd, DT2);
4729
        opn = "ceil.l.d";
4730
        break;
4731
    case FOP(11, 17):
4732
        CHECK_FR(ctx, fs);
4733
        GEN_LOAD_FREG_FTN(DT0, fs);
4734
        gen_op_float_floorl_d();
4735
        GEN_STORE_FTN_FREG(fd, DT2);
4736
        opn = "floor.l.d";
4737
        break;
4431 4738
    case FOP(12, 17):
4432 4739
        CHECK_FR(ctx, fs);
4433 4740
        GEN_LOAD_FREG_FTN(DT0, fs);
......
4456 4763
        GEN_STORE_FTN_FREG(fd, WT2);
4457 4764
        opn = "floor.w.d";
4458 4765
        break;
4459
    case FOP(33, 16):
4460
        CHECK_FR(ctx, fd);
4461
        GEN_LOAD_FREG_FTN(WT0, fs);
4462
        gen_op_float_cvtd_s();
4766
    case FOP(17, 17):
4767
        GEN_LOAD_REG_TN(T0, ft);
4768
        GEN_LOAD_FREG_FTN(DT0, fs);
4769
        GEN_LOAD_FREG_FTN(DT2, fd);
4770
        gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
4463 4771
        GEN_STORE_FTN_FREG(fd, DT2);
4464
        opn = "cvt.d.s";
4772
        opn = "movcf.d";
4465 4773
        break;
4466
    case FOP(33, 20):
4467
        CHECK_FR(ctx, fd);
4468
        GEN_LOAD_FREG_FTN(WT0, fs);
4469
        gen_op_float_cvtd_w();
4774
    case FOP(18, 17):
4775
        GEN_LOAD_REG_TN(T0, ft);
4776
        GEN_LOAD_FREG_FTN(DT0, fs);
4777
        GEN_LOAD_FREG_FTN(DT2, fd);
4778
        gen_op_float_movz_d();
4470 4779
        GEN_STORE_FTN_FREG(fd, DT2);
4471
        opn = "cvt.d.w";
4780
        opn = "movz.d";
4781
        break;
4782
    case FOP(19, 17):
4783
        GEN_LOAD_REG_TN(T0, ft);
4784
        GEN_LOAD_FREG_FTN(DT0, fs);
4785
        GEN_LOAD_FREG_FTN(DT2, fd);
4786
        gen_op_float_movn_d();
4787
        GEN_STORE_FTN_FREG(fd, DT2);
4788
        opn = "movn.d";
4472 4789
        break;
4473 4790
    case FOP(48, 17):
4474 4791
    case FOP(49, 17):
......
4489 4806
        CHECK_FR(ctx, fs | ft);
4490 4807
        GEN_LOAD_FREG_FTN(DT0, fs);
4491 4808
        GEN_LOAD_FREG_FTN(DT1, ft);
4492
        gen_cmp_d(func-48);
4809
        gen_cmp_d(func-48, cc);
4493 4810
        opn = condnames[func-48];
4494 4811
        break;
4495
    case FOP(0, 16):
4812
    case FOP(32, 17):
4813
        CHECK_FR(ctx, fs);
4814
        GEN_LOAD_FREG_FTN(DT0, fs);
4815
        gen_op_float_cvts_d();
4816
        GEN_STORE_FTN_FREG(fd, WT2);
4817
        opn = "cvt.s.d";
4818
        break;
4819
    case FOP(36, 17):
4820
        CHECK_FR(ctx, fs);
4821
        GEN_LOAD_FREG_FTN(DT0, fs);
4822
        gen_op_float_cvtw_d();
4823
        GEN_STORE_FTN_FREG(fd, WT2);
4824
        opn = "cvt.w.d";
4825
        break;
4826
    case FOP(37, 17):
4827
        CHECK_FR(ctx, fs | fd);
4828
        GEN_LOAD_FREG_FTN(DT0, fs);
4829
        gen_op_float_cvtl_d();
4830
        GEN_STORE_FTN_FREG(fd, DT2);
4831
        opn = "cvt.l.d";
4832
        break;
4833
    case FOP(32, 20):
4496 4834
        GEN_LOAD_FREG_FTN(WT0, fs);
4497
        GEN_LOAD_FREG_FTN(WT1, ft);
4498
        gen_op_float_add_s();
4835
        gen_op_float_cvts_w();
4499 4836
        GEN_STORE_FTN_FREG(fd, WT2);
4500
        opn = "add.s";
4501
        binary = 1;
4837
        opn = "cvt.s.w";
4502 4838
        break;
4503
    case FOP(1, 16):
4839
    case FOP(33, 20):
4840
        CHECK_FR(ctx, fd);
4504 4841
        GEN_LOAD_FREG_FTN(WT0, fs);
4842
        gen_op_float_cvtd_w();
4843
        GEN_STORE_FTN_FREG(fd, DT2);
4844
        opn = "cvt.d.w";
4845
        break;
4846
    case FOP(32, 21):
4847
        CHECK_FR(ctx, fs);
4848
        GEN_LOAD_FREG_FTN(DT0, fs);
4849
        gen_op_float_cvts_l();
4850
        GEN_STORE_FTN_FREG(fd, WT2);
4851
        opn = "cvt.s.l";
4852
        break;
4853
    case FOP(33, 21):
4854
        CHECK_FR(ctx, fs | fd);
4855
        GEN_LOAD_FREG_FTN(DT0, fs);
4856
        gen_op_float_cvtd_l();
4857
        GEN_STORE_FTN_FREG(fd, DT2);
4858
        opn = "cvt.d.l";
4859
        break;
4860
    case FOP(38, 20):
4861
    case FOP(38, 21):
4862
        CHECK_FR(ctx, fs | fd);
4863
        GEN_LOAD_FREG_FTN(WT0, fs);
4864
        GEN_LOAD_FREG_FTN(WTH0, fs);
4865
        gen_op_float_cvtps_pw();
4866
        GEN_STORE_FTN_FREG(fd, WT2);
4867
        GEN_STORE_FTN_FREG(fd, WTH2);
4868
        opn = "cvt.ps.pw";
4869
        break;
4870
    case FOP(0, 22):
4871
        CHECK_FR(ctx, fs | ft | fd);
4872
        GEN_LOAD_FREG_FTN(WT0, fs);
4873
        GEN_LOAD_FREG_FTN(WTH0, fs);
4505 4874
        GEN_LOAD_FREG_FTN(WT1, ft);
4506
        gen_op_float_sub_s();
4875
        GEN_LOAD_FREG_FTN(WTH1, ft);
4876
        gen_op_float_add_ps();
4507 4877
        GEN_STORE_FTN_FREG(fd, WT2);
4508
        opn = "sub.s";
4509
        binary = 1;
4878
        GEN_STORE_FTN_FREG(fd, WTH2);
4879
        opn = "add.ps";
4510 4880
        break;
4511
    case FOP(2, 16):
4881
    case FOP(1, 22):
4882
        CHECK_FR(ctx, fs | ft | fd);
4512 4883
        GEN_LOAD_FREG_FTN(WT0, fs);
4884
        GEN_LOAD_FREG_FTN(WTH0, fs);
4513 4885
        GEN_LOAD_FREG_FTN(WT1, ft);
4514
        gen_op_float_mul_s();
4886
        GEN_LOAD_FREG_FTN(WTH1, ft);
4887
        gen_op_float_sub_ps();
4515 4888
        GEN_STORE_FTN_FREG(fd, WT2);
4516
        opn = "mul.s";
4517
        binary = 1;
4889
        GEN_STORE_FTN_FREG(fd, WTH2);
4890
        opn = "sub.ps";
4518 4891
        break;
4519
    case FOP(3, 16):
4892
    case FOP(2, 22):
4893
        CHECK_FR(ctx, fs | ft | fd);
4520 4894
        GEN_LOAD_FREG_FTN(WT0, fs);
4895
        GEN_LOAD_FREG_FTN(WTH0, fs);
4521 4896
        GEN_LOAD_FREG_FTN(WT1, ft);
4522
        gen_op_float_div_s();
4897
        GEN_LOAD_FREG_FTN(WTH1, ft);
4898
        gen_op_float_mul_ps();
4523 4899
        GEN_STORE_FTN_FREG(fd, WT2);
4524
        opn = "div.s";
4525
        binary = 1;
4900
        GEN_STORE_FTN_FREG(fd, WTH2);
4901
        opn = "mul.ps";
4526 4902
        break;
4527
    case FOP(4, 16):
4903
    case FOP(5, 22):
4904
        CHECK_FR(ctx, fs | fd);
4528 4905
        GEN_LOAD_FREG_FTN(WT0, fs);
4529
        gen_op_float_sqrt_s();
4906
        GEN_LOAD_FREG_FTN(WTH0, fs);
4907
        gen_op_float_abs_ps();
4530 4908
        GEN_STORE_FTN_FREG(fd, WT2);
4531
        opn = "sqrt.s";
4909
        GEN_STORE_FTN_FREG(fd, WTH2);
4910
        opn = "abs.ps";
4532 4911
        break;
4533
    case FOP(5, 16):
4912
    case FOP(6, 22):
4913
        CHECK_FR(ctx, fs | fd);
4534 4914
        GEN_LOAD_FREG_FTN(WT0, fs);
4535
        gen_op_float_abs_s();
4915
        GEN_LOAD_FREG_FTN(WTH0, fs);
4916
        gen_op_float_mov_ps();
4536 4917
        GEN_STORE_FTN_FREG(fd, WT2);
4537
        opn = "abs.s";
4918
        GEN_STORE_FTN_FREG(fd, WTH2);
4919
        opn = "mov.ps";
4538 4920
        break;
4539
    case FOP(6, 16):
4921
    case FOP(7, 22):
4922
        CHECK_FR(ctx, fs | fd);
4540 4923
        GEN_LOAD_FREG_FTN(WT0, fs);
4541
        gen_op_float_mov_s();
4924
        GEN_LOAD_FREG_FTN(WTH0, fs);
4925
        gen_op_float_chs_ps();
4542 4926
        GEN_STORE_FTN_FREG(fd, WT2);
4543
        opn = "mov.s";
4927
        GEN_STORE_FTN_FREG(fd, WTH2);
4928
        opn = "neg.ps";
4544 4929
        break;
4545
    case FOP(7, 16):
4930
    case FOP(17, 22):
4931
        GEN_LOAD_REG_TN(T0, ft);
4546 4932
        GEN_LOAD_FREG_FTN(WT0, fs);
4547
        gen_op_float_chs_s();
4933
        GEN_LOAD_FREG_FTN(WTH0, fs);
4934
        GEN_LOAD_FREG_FTN(WT2, fd);
4935
        GEN_LOAD_FREG_FTN(WTH2, fd);
4936
        gen_movcf_ps(ctx, (ft >> 2) & 0x7, ft & 0x1);
4548 4937
        GEN_STORE_FTN_FREG(fd, WT2);
4549
        opn = "neg.s";
4938
        GEN_STORE_FTN_FREG(fd, WTH2);
4939
        opn = "movcf.ps";
4550 4940
        break;
4551
    case FOP(12, 16):
4941
    case FOP(18, 22):
4942
        GEN_LOAD_REG_TN(T0, ft);
4552 4943
        GEN_LOAD_FREG_FTN(WT0, fs);
4553
        gen_op_float_roundw_s();
4944
        GEN_LOAD_FREG_FTN(WTH0, fs);
4945
        GEN_LOAD_FREG_FTN(WT2, fd);
4946
        GEN_LOAD_FREG_FTN(WTH2, fd);
4947
        gen_op_float_movz_ps();
4554 4948
        GEN_STORE_FTN_FREG(fd, WT2);
4555
        opn = "round.w.s";
4949
        GEN_STORE_FTN_FREG(fd, WTH2);
4950
        opn = "movz.ps";
4556 4951
        break;
4557
    case FOP(13, 16):
4952
    case FOP(19, 22):
4953
        GEN_LOAD_REG_TN(T0, ft);
4558 4954
        GEN_LOAD_FREG_FTN(WT0, fs);
4559
        gen_op_float_truncw_s();
4955
        GEN_LOAD_FREG_FTN(WTH0, fs);
4956
        GEN_LOAD_FREG_FTN(WT2, fd);
4957
        GEN_LOAD_FREG_FTN(WTH2, fd);
4958
        gen_op_float_movn_ps();
4560 4959
        GEN_STORE_FTN_FREG(fd, WT2);
4561
        opn = "trunc.w.s";
4960
        GEN_STORE_FTN_FREG(fd, WTH2);
4961
        opn = "movn.ps";
4562 4962
        break;
4563
    case FOP(32, 17):
4963
    case FOP(32, 22):
4564 4964
        CHECK_FR(ctx, fs);
4565
        GEN_LOAD_FREG_FTN(DT0, fs);
4566
        gen_op_float_cvts_d();
4965
        GEN_LOAD_FREG_FTN(WTH0, fs);
4966
        gen_op_float_cvts_pu();
4567 4967
        GEN_STORE_FTN_FREG(fd, WT2);
4568
        opn = "cvt.s.d";
4968
        opn = "cvt.s.pu";
4569 4969
        break;
4570
    case FOP(32, 20):
4970
    case FOP(36, 22):
4971
        CHECK_FR(ctx, fs | fd);
4571 4972
        GEN_LOAD_FREG_FTN(WT0, fs);
4572
        gen_op_float_cvts_w();
4973
        GEN_LOAD_FREG_FTN(WTH0, fs);
4974
        gen_op_float_cvtpw_ps();
4573 4975
        GEN_STORE_FTN_FREG(fd, WT2);
4574
        opn = "cvt.s.w";
4976
        GEN_STORE_FTN_FREG(fd, WTH2);
4977
        opn = "cvt.pw.ps";
4575 4978
        break;
4576
    case FOP(36, 16):
4979
    case FOP(40, 22):
4980
        CHECK_FR(ctx, fs);
4577 4981
        GEN_LOAD_FREG_FTN(WT0, fs);
4578
        gen_op_float_cvtw_s();
4982
        gen_op_float_cvts_pl();
4579 4983
        GEN_STORE_FTN_FREG(fd, WT2);
4580
        opn = "cvt.w.s";
4984
        opn = "cvt.s.pl";
4581 4985
        break;
4582
    case FOP(36, 17):
4583
        CHECK_FR(ctx, fs);
4584
        GEN_LOAD_FREG_FTN(DT0, fs);
4585
        gen_op_float_cvtw_d();
4586
        GEN_STORE_FTN_FREG(fd, WT2);
4587
        opn = "cvt.w.d";
4986
    case FOP(44, 22):
4987
        CHECK_FR(ctx, fs | ft | fd);
4988
        GEN_LOAD_FREG_FTN(WT0, fs);
4989
        GEN_LOAD_FREG_FTN(WT1, ft);
4990
        gen_op_float_pll_ps();
4991
        GEN_STORE_FTN_FREG(fd, DT2);
4992
        opn = "pll.ps";
4588 4993
        break;
4589
    case FOP(48, 16):
4590
    case FOP(49, 16):
4591
    case FOP(50, 16):
4592
    case FOP(51, 16):
4593
    case FOP(52, 16):
4594
    case FOP(53, 16):
4595
    case FOP(54, 16):
4596
    case FOP(55, 16):
4597
    case FOP(56, 16):
4598
    case FOP(57, 16):
4599
    case FOP(58, 16):
4600
    case FOP(59, 16):
4601
    case FOP(60, 16):
4602
    case FOP(61, 16):
4603
    case FOP(62, 16):
4604
    case FOP(63, 16):
4994
    case FOP(45, 22):
4995
        CHECK_FR(ctx, fs | ft | fd);
4605 4996
        GEN_LOAD_FREG_FTN(WT0, fs);
4997
        GEN_LOAD_FREG_FTN(WTH1, ft);
4998
        gen_op_float_plu_ps();
4999
        GEN_STORE_FTN_FREG(fd, DT2);
5000
        opn = "plu.ps";
5001
        break;
5002
    case FOP(46, 22):
5003
        CHECK_FR(ctx, fs | ft | fd);
5004
        GEN_LOAD_FREG_FTN(WTH0, fs);
4606 5005
        GEN_LOAD_FREG_FTN(WT1, ft);
4607
        gen_cmp_s(func-48);
5006
        gen_op_float_pul_ps();
5007
        GEN_STORE_FTN_FREG(fd, DT2);
5008
        opn = "pul.ps";
5009
        break;
5010
    case FOP(47, 22):
5011
        CHECK_FR(ctx, fs | ft | fd);
5012
        GEN_LOAD_FREG_FTN(WTH0, fs);
5013
        GEN_LOAD_FREG_FTN(WTH1, ft);
5014
        gen_op_float_puu_ps();
5015
        GEN_STORE_FTN_FREG(fd, DT2);
5016
        opn = "puu.ps";
5017
        break;
5018
    case FOP(48, 22):
5019
    case FOP(49, 22):
5020
    case FOP(50, 22):
5021
    case FOP(51, 22):
5022
    case FOP(52, 22):
5023
    case FOP(53, 22):
5024
    case FOP(54, 22):
5025
    case FOP(55, 22):
5026
    case FOP(56, 22):
5027
    case FOP(57, 22):
5028
    case FOP(58, 22):
5029
    case FOP(59, 22):
5030
    case FOP(60, 22):
5031
    case FOP(61, 22):
5032
    case FOP(62, 22):
5033
    case FOP(63, 22):
5034
        CHECK_FR(ctx, fs | ft);
5035
        GEN_LOAD_FREG_FTN(WT0, fs);
5036
        GEN_LOAD_FREG_FTN(WTH0, fs);
5037
        GEN_LOAD_FREG_FTN(WT1, ft);
5038
        GEN_LOAD_FREG_FTN(WTH1, ft);
5039
        gen_cmp_ps(func-48, cc);
4608 5040
        opn = condnames[func-48];
4609 5041
        break;
4610
    default:    
5042
    default:
4611 5043
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4612 5044
            fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
4613 5045
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
......
4622 5054
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
4623 5055
}
4624 5056

  
4625
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5057
/* Coprocessor 3 (FPU) */
5058
static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd,
5059
                           int base, int index)
4626 5060
{
4627
    uint32_t ccbit;
5061
    const char *opn = "unk";
4628 5062

  
4629
    if (cc)
4630
        ccbit = 1 << (24 + cc);
4631
    else
4632
        ccbit = 1 << 23;
4633
    if (!tf)
4634
        gen_op_movf(ccbit, rd, rs);
4635
    else
4636
       gen_op_movt(ccbit, rd, rs);
5063
    GEN_LOAD_REG_TN(T0, base);
5064
    GEN_LOAD_REG_TN(T1, index);
5065
    /* Don't do NOP if destination is zero: we must perform the actual
5066
     * memory access
5067
     */
5068
    switch (opc) {
5069
    case OPC_LWXC1:
5070
        op_ldst(lwxc1);
5071
        GEN_STORE_FTN_FREG(fd, WT0);
5072
        opn = "lwxc1";
5073
        break;
5074
    case OPC_LDXC1:
5075
        op_ldst(ldxc1);
5076
        GEN_STORE_FTN_FREG(fd, DT0);
5077
        opn = "ldxc1";
5078
        break;
5079
    case OPC_LUXC1:
5080
        op_ldst(luxc1);
5081
        GEN_STORE_FTN_FREG(fd, DT0);
5082
        opn = "luxc1";
5083
        break;
5084
    case OPC_SWXC1:
5085
        GEN_LOAD_FREG_FTN(WT0, fd);
5086
        op_ldst(swxc1);
5087
        opn = "swxc1";
5088
        break;
5089
    case OPC_SDXC1:
5090
        GEN_LOAD_FREG_FTN(DT0, fd);
5091
        op_ldst(sdxc1);
5092
        opn = "sdxc1";
5093
        break;
5094
    case OPC_SUXC1:
5095
        GEN_LOAD_FREG_FTN(DT0, fd);
5096
        op_ldst(suxc1);
5097
        opn = "suxc1";
5098
        break;
5099
    default:
5100
        MIPS_INVAL("extended float load/store");
5101
        generate_exception(ctx, EXCP_RI);
5102
        return;
5103
    }
5104
    MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[fd],regnames[index], regnames[base]);
5105
}
5106

  
5107
static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
5108
                            int fr, int fs, int ft)
5109
{
5110
    const char *opn = "unk";
5111

  
5112
    /* All of those work only on 64bit FPUs. */
5113
    CHECK_FR(ctx, fd | fr | fs | ft);
5114
    switch (opc) {
5115
    case OPC_ALNV_PS:
5116
        GEN_LOAD_REG_TN(T0, fr);
5117
        GEN_LOAD_FREG_FTN(DT0, fs);
5118
        GEN_LOAD_FREG_FTN(DT1, ft);
5119
        gen_op_float_alnv_ps();
5120
        GEN_STORE_FTN_FREG(fd, DT2);
5121
        opn = "alnv.ps";
5122
        break;
5123
    case OPC_MADD_S:
5124
        GEN_LOAD_FREG_FTN(WT0, fs);
5125
        GEN_LOAD_FREG_FTN(WT1, ft);
5126
        GEN_LOAD_FREG_FTN(WT2, fr);
5127
        gen_op_float_muladd_s();
5128
        GEN_STORE_FTN_FREG(fd, WT2);
5129
        opn = "madd.s";
5130
        break;
5131
    case OPC_MADD_D:
5132
        generate_exception (ctx, EXCP_RI);
5133
        opn = "madd.d";
5134
        break;
5135
    case OPC_MADD_PS:
5136
        generate_exception (ctx, EXCP_RI);
5137
        opn = "madd.ps";
5138
        break;
5139
    case OPC_MSUB_S:
5140
        generate_exception (ctx, EXCP_RI);
5141
        opn = "msub.s";
5142
        break;
5143
    case OPC_MSUB_D:
5144
        generate_exception (ctx, EXCP_RI);
5145
        opn = "msub.d";
5146
        break;
5147
    case OPC_MSUB_PS:
5148
        generate_exception (ctx, EXCP_RI);
5149
        opn = "msub.ps";
5150
        break;
5151
    case OPC_NMADD_S:
5152
        generate_exception (ctx, EXCP_RI);
5153
        opn = "nmadd.s";
5154
        break;
5155
    case OPC_NMADD_D:
5156
        generate_exception (ctx, EXCP_RI);
5157
        opn = "nmadd.d";
5158
        break;
5159
    case OPC_NMADD_PS:
5160
        generate_exception (ctx, EXCP_RI);
5161
        opn = "nmadd.ps";
5162
        break;
5163
    case OPC_NMSUB_S:
5164
        generate_exception (ctx, EXCP_RI);
5165
        opn = "nmsub.s";
5166
        break;
5167
    case OPC_NMSUB_D:
5168
        generate_exception (ctx, EXCP_RI);
5169
        opn = "nmsub.d";
5170
        break;
5171
    case OPC_NMSUB_PS:
5172
        generate_exception (ctx, EXCP_RI);
5173
        opn = "nmsub.ps";
5174
        break;
5175
    default:    
5176
        if (loglevel & CPU_LOG_TB_IN_ASM) {
5177
            fprintf(logfile, "Invalid extended FP arith function: %08x %03x %03x\n",
5178
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F);
5179
        }
5180
        generate_exception (ctx, EXCP_RI);
5181
        return;
5182
    }
5183
    MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
5184
               fregnames[fs], fregnames[ft]);
4637 5185
}
4638 5186

  
4639 5187
/* ISA extensions (ASEs) */
......
4641 5189
/* SmartMIPS extension to MIPS32 */
4642 5190

  
4643 5191
#ifdef TARGET_MIPS64
4644
/* Coprocessor 3 (FPU) */
4645 5192

  
4646 5193
/* MDMX extension to MIPS64 */
4647 5194
/* MIPS-3D extension to MIPS64 */
4648 5195

  
4649 5196
#endif
4650 5197

  
4651
static void gen_blikely(DisasContext *ctx)
4652
{
4653
    int l1;
4654
    l1 = gen_new_label();
4655
    gen_op_jnz_T2(l1);
4656
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
4657
    gen_goto_tb(ctx, 1, ctx->pc + 4);
4658
    gen_set_label(l1);
4659
}
4660

  
4661 5198
static void decode_opc (CPUState *env, DisasContext *ctx)
4662 5199
{
4663 5200
    int32_t offset;
......
4673 5210
    }
4674 5211

  
4675 5212
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
5213
        int l1;
4676 5214
        /* Handle blikely not taken case */
4677 5215
        MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
4678
        gen_blikely(ctx);
5216
        l1 = gen_new_label();
5217
        gen_op_jnz_T2(l1);
5218
        gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
5219
        gen_goto_tb(ctx, 1, ctx->pc + 4);
5220
        gen_set_label(l1);
4679 5221
    }
4680 5222
    op = MASK_OP_MAJOR(ctx->opcode);
4681 5223
    rs = (ctx->opcode >> 21) & 0x1f;
......
5024 5566
            case OPC_DMFC1:
5025 5567
            case OPC_DMTC1:
5026 5568
#endif
5569
            case OPC_MFHC1:
5570
            case OPC_MTHC1:
5027 5571
                gen_cp1(ctx, op1, rt, rd);
5028 5572
                break;
5029 5573
            case OPC_BC1:
5030
                gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
5574
                gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5575
                                    (rt >> 2) & 0x7, imm << 2);
5031 5576
                return;
5032 5577
            case OPC_S_FMT:
5033 5578
            case OPC_D_FMT:
5034 5579
            case OPC_W_FMT:
5035 5580
            case OPC_L_FMT:
5036
                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
5581
            case OPC_PS_FMT:
5582
                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
5583
                           (imm >> 8) & 0x7);
5037 5584
                break;
5038 5585
            default:
5039 5586
                generate_exception (ctx, EXCP_RI);
......
5060 5607
            gen_op_cp1_enabled();
5061 5608
            op1 = MASK_CP3(ctx->opcode);
5062 5609
            switch (op1) {
5610
            case OPC_LWXC1:
5611
            case OPC_LDXC1:
5612
            case OPC_LUXC1:
5613
            case OPC_SWXC1:
5614
            case OPC_SDXC1:
5615
            case OPC_SUXC1:
5616
                gen_flt3_ldst(ctx, op1, sa, rs, rt);
5617
                break;
5063 5618
            case OPC_PREFX:
5064 5619
                /* treat as noop */
5065 5620
                break;
5066
            /* Not implemented */
5621
            case OPC_ALNV_PS:
5622
            case OPC_MADD_S:
5623
            case OPC_MADD_D:
5624
            case OPC_MADD_PS:
5625
            case OPC_MSUB_S:
5626
            case OPC_MSUB_D:
5627
            case OPC_MSUB_PS:
5628
            case OPC_NMADD_S:
5629
            case OPC_NMADD_D:
5630
            case OPC_NMADD_PS:
5631
            case OPC_NMSUB_S:
5632
            case OPC_NMSUB_D:
5633
            case OPC_NMSUB_PS:
5634
                gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
5635
                break;
5067 5636
            default:
5068 5637
                generate_exception (ctx, EXCP_RI);
5069 5638
                break;
......
5107 5676
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
5108 5677
        ctx->bstate = BS_BRANCH;
5109 5678
        save_cpu_state(ctx, 0);
5110
        switch (hflags & MIPS_HFLAG_BMASK) {
5679
        switch (hflags) {
5111 5680
        case MIPS_HFLAG_B:
5112 5681
            /* unconditional branch */
5113 5682
            MIPS_DEBUG("unconditional branch");
......
5134 5703
            /* unconditional branch to register */
5135 5704
            MIPS_DEBUG("branch to register");
5136 5705
            gen_op_breg();
5706
            gen_op_reset_T0();
5707
            gen_op_exit_tb();
5137 5708
            break;
5138 5709
        default:
5139 5710
            MIPS_DEBUG("unknown branch");
......
5166 5737
    /* Restore delay slot state from the tb context.  */
5167 5738
    ctx.hflags = tb->flags;
5168 5739
    ctx.saved_hflags = ctx.hflags;
5169
    if (ctx.hflags & MIPS_HFLAG_BR) {
5740
    switch (ctx.hflags & MIPS_HFLAG_BMASK) {
5741
    case MIPS_HFLAG_BR:
5170 5742
        gen_op_restore_breg_target();
5171
    } else if (ctx.hflags & MIPS_HFLAG_B) {
5743
        break;
5744
    case MIPS_HFLAG_B:
5172 5745
        ctx.btarget = env->btarget;
5173
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
5174
        /* If we are in the delay slot of a conditional branch,
5175
         * restore the branch condition from env->bcond to T2
5176
         */
5746
        break;
5747
    case MIPS_HFLAG_BC:
5748
    case MIPS_HFLAG_BL:
5177 5749
        ctx.btarget = env->btarget;
5178 5750
        gen_op_restore_bcond();
5751
        break;
5179 5752
    }
5180 5753
#if defined(CONFIG_USER_ONLY)
5181 5754
    ctx.mem_idx = 0;
......
5237 5810
        gen_op_debug();
5238 5811
    } else {
5239 5812
	switch (ctx.bstate) {
5240
        case BS_EXCP:
5241
            gen_op_interrupt_restart();
5242
            gen_op_reset_T0();
5243
            /* Generate the return instruction. */
5244
            gen_op_exit_tb();
5245
            break;
5246 5813
        case BS_STOP:
5247 5814
            gen_op_interrupt_restart();
5248 5815
            /* Fall through. */
......
5250 5817
            save_cpu_state(ctxp, 0);
5251 5818
            gen_goto_tb(&ctx, 0, ctx.pc);
5252 5819
            break;
5253
        case BS_BRANCH:
5254
        default:
5820
        case BS_EXCP:
5821
            gen_op_interrupt_restart();
5255 5822
            gen_op_reset_T0();
5256
            /* Generate the return instruction. */
5257 5823
            gen_op_exit_tb();
5258 5824
            break;
5825
        case BS_BRANCH:
5826
        default:
5827
            break;
5259 5828
	}
5260 5829
    }
5261 5830
done_generating:
......
5307 5876
                    int flags)
5308 5877
{
5309 5878
    int i;
5310

  
5311
#   define printfpr(fp) do { \
5312
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
5313
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
5879
    int is_fpu64 = !!(env->CP0_Status & (1 << CP0St_FR));
5880

  
5881
#define printfpr(fp)                                                        \
5882
    do {                                                                    \
5883
        if (is_fpu64)                                                       \
5884
            fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n",   \
5885
                        (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd,          \
5886
                        (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
5887
        else {                                                              \
5888
            fpr_t tmp;                                                      \
5889
            tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX];                  \
5890
            tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX];           \
5891
            fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n",    \
5892
                        tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd,                \
5893
                        tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]);     \
5894
        }                                                                   \
5314 5895
    } while(0)
5315 5896

  
5316
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
5317
                env->fcr0, env->fcr31,
5318
                (env->CP0_Status & (1 << CP0St_FR)) != 0);
5897

  
5898
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d  fp_status 0x%08x(0x%02x)\n",
5899
                env->fcr0, env->fcr31, is_fpu64, env->fp_status, get_float_exception_flags(&env->fp_status));
5319 5900
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5320 5901
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5321 5902
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
5322
    for(i = 0; i < 32; i += 2) {
5323
        fpu_fprintf(f, "%s: ", fregnames[i]);
5324
        printfpr(FPR(env, i));
5903
    for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
5904
        fpu_fprintf(f, "%3s: ", fregnames[i]);
5905
        printfpr(&env->fpr[i]);
5325 5906
    }
5326 5907

  
5327 5908
#undef printfpr

Also available in: Unified diff