Revision 6ea83fed target-mips/translate.c

b/target-mips/translate.c
2 2
 *  MIPS32 emulation for qemu: main translation routines.
3 3
 * 
4 4
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5
 *  Copyright (c) 2006 Marius Groeger (FPU operations)
5 6
 *
6 7
 * This library is free software; you can redistribute it and/or
7 8
 * modify it under the terms of the GNU Lesser General Public
......
217 218
    OPC_WAIT     = 0x20 | EXT_CP0,
218 219
};
219 220

  
221
#ifdef MIPS_USES_FPU
222
enum {
223
    /* Coprocessor 1 (FPU) */
224
    OPC_MFC1     = 0x00 | EXT_CP1,
225
    OPC_MTC1     = 0x04 | EXT_CP1,
226
    OPC_CFC1     = 0x02 | EXT_CP1,
227
    OPC_CTC1     = 0x06 | EXT_CP1,
228
};
229
#endif
230

  
220 231
const unsigned char *regnames[] =
221 232
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
222 233
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
......
248 259
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
249 260
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
250 261

  
262
#ifdef MIPS_USES_FPU
263
const unsigned char *fregnames[] =
264
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
265
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
266
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
267
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
268

  
269
# define SFGEN32(func, NAME) \
270
static GenOpFunc *NAME ## _table [32] = {                                     \
271
NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
272
NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
273
NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
274
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
275
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
276
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
277
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
278
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
279
};                                                                            \
280
static inline void func(int n)                                                \
281
{                                                                             \
282
    NAME ## _table[n]();                                                      \
283
}
284

  
285
# define DFGEN32(func, NAME) \
286
static GenOpFunc *NAME ## _table [32] = {                                     \
287
NAME ## 0,  0, NAME ## 2,  0,                                                 \
288
NAME ## 4,  0, NAME ## 6,  0,                                                 \
289
NAME ## 8,  0, NAME ## 10, 0,                                                 \
290
NAME ## 12, 0, NAME ## 14, 0,                                                 \
291
NAME ## 16, 0, NAME ## 18, 0,                                                 \
292
NAME ## 20, 0, NAME ## 22, 0,                                                 \
293
NAME ## 24, 0, NAME ## 26, 0,                                                 \
294
NAME ## 28, 0, NAME ## 30, 0,                                                 \
295
};                                                                            \
296
static inline void func(int n)                                                \
297
{                                                                             \
298
    NAME ## _table[n]();                                                      \
299
}
300

  
301
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
302
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
303

  
304
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
305
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
306

  
307
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
308
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
309

  
310
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
311
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
312

  
313
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
314
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
315

  
316
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
317
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
318

  
319
#define FOP_CONDS(fmt) \
320
static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
321
    gen_op_cmp_ ## fmt ## _f,                                           \
322
    gen_op_cmp_ ## fmt ## _un,                                          \
323
    gen_op_cmp_ ## fmt ## _eq,                                          \
324
    gen_op_cmp_ ## fmt ## _ueq,                                         \
325
    gen_op_cmp_ ## fmt ## _olt,                                         \
326
    gen_op_cmp_ ## fmt ## _ult,                                         \
327
    gen_op_cmp_ ## fmt ## _ole,                                         \
328
    gen_op_cmp_ ## fmt ## _ule,                                         \
329
    gen_op_cmp_ ## fmt ## _sf,                                          \
330
    gen_op_cmp_ ## fmt ## _ngle,                                        \
331
    gen_op_cmp_ ## fmt ## _seq,                                         \
332
    gen_op_cmp_ ## fmt ## _ngl,                                         \
333
    gen_op_cmp_ ## fmt ## _lt,                                          \
334
    gen_op_cmp_ ## fmt ## _nge,                                         \
335
    gen_op_cmp_ ## fmt ## _le,                                          \
336
    gen_op_cmp_ ## fmt ## _ngt,                                         \
337
};                                                                      \
338
static inline void gen_cmp_ ## fmt(int n)                               \
339
{                                                                       \
340
    cond_ ## fmt ## _table[n]();                                        \
341
}
342

  
343
FOP_CONDS(d)
344
FOP_CONDS(s)
345

  
346
#endif
347

  
251 348
typedef struct DisasContext {
252 349
    struct TranslationBlock *tb;
253 350
    target_ulong pc, saved_pc;
......
312 409
    }                                                                         \
313 410
} while (0)
314 411

  
412
#ifdef MIPS_USES_FPU
413

  
414
# define GEN_LOAD_FREG_FTN(FTn, Fn)                                           \
415
do {                                                                          \
416
    glue(gen_op_load_fpr_, FTn)(Fn);                                          \
417
} while (0)
418

  
419
#define GEN_STORE_FTN_FREG(Fn, FTn)                                           \
420
do {                                                                          \
421
    glue(gen_op_store_fpr_, FTn)(Fn);                                         \
422
} while (0)
423

  
424
#endif
425

  
315 426
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
316 427
{
317 428
#if defined MIPS_DEBUG_DISAS
......
397 508
OP_ST_TABLE(b);
398 509
OP_LD_TABLE(l);
399 510
OP_ST_TABLE(c);
511
#ifdef MIPS_USES_FPU
512
OP_LD_TABLE(wc1);
513
OP_ST_TABLE(wc1);
514
OP_LD_TABLE(dc1);
515
OP_ST_TABLE(dc1);
516
#endif
400 517

  
401 518
/* Load and store */
402 519
static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt,
......
551 668
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
552 669
}
553 670

  
671
#ifdef MIPS_USES_FPU
672

  
673
/* Load and store */
674
static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft,
675
                      int base, int16_t offset)
676
{
677
    const unsigned char *opn = "unk";
678

  
679
    if (base == 0) {
680
        GEN_LOAD_IMM_TN(T0, offset);
681
    } else if (offset == 0) {
682
        gen_op_load_gpr_T0(base);
683
    } else {
684
        gen_op_load_gpr_T0(base);
685
        gen_op_set_T1(offset);
686
        gen_op_add();
687
    }
688
    /* Don't do NOP if destination is zero: we must perform the actual
689
     * memory access
690
     */
691
    switch (opc) {
692
    case OPC_LWC1:
693
        op_ldst(lwc1);
694
        GEN_STORE_FTN_FREG(ft, WT0);
695
        opn = "lwc1";
696
        break;
697
    case OPC_SWC1:
698
        GEN_LOAD_FREG_FTN(WT0, ft);
699
        op_ldst(swc1);
700
        opn = "swc1";
701
        break;
702
    case OPC_LDC1:
703
        op_ldst(ldc1);
704
        GEN_STORE_FTN_FREG(ft, DT0);
705
        opn = "ldc1";
706
        break;
707
    case OPC_SDC1:
708
        GEN_LOAD_FREG_FTN(DT0, ft);
709
        op_ldst(sdc1);
710
        opn = "sdc1";
711
        break;
712
    default:
713
        MIPS_INVAL("float load/store");
714
        generate_exception(ctx, EXCP_CpU);
715
        return;
716
    }
717
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
718
}
719
#endif
720

  
554 721
/* Arithmetic with immediate operand */
555 722
static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt,
556 723
                           int rs, int16_t imm)
......
1265 1432
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
1266 1433
}
1267 1434

  
1435
#ifdef MIPS_USES_FPU
1436
/* CP1 Branches (before delay slot) */
1437
static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond,
1438
                                 int32_t offset)
1439
{
1440
    target_ulong btarget;
1441

  
1442
    btarget = ctx->pc + 4 + offset;
1443

  
1444
    switch (cond) {
1445
    case 0x0000: /* bc1f */
1446
        gen_op_bc1f();
1447
        MIPS_DEBUG("bc1f %08x", btarget);
1448
        goto not_likely;
1449
    case 0x0002: /* bc1fl */
1450
        gen_op_bc1f();
1451
        MIPS_DEBUG("bc1fl %08x", btarget);
1452
        goto likely;
1453
    case 0x0001: /* bc1t */
1454
        gen_op_bc1t();
1455
        MIPS_DEBUG("bc1t %08x", btarget);
1456
    not_likely:
1457
        ctx->hflags |= MIPS_HFLAG_BC;
1458
        break;
1459
    case 0x0003: /* bc1tl */
1460
        gen_op_bc1t();
1461
        MIPS_DEBUG("bc1tl %08x", btarget);
1462
    likely:
1463
        ctx->hflags |= MIPS_HFLAG_BL;
1464
        break;
1465
    default:    
1466
        MIPS_INVAL("cp1 branch/jump");
1467
        generate_exception(ctx, EXCP_RI);
1468
        return;
1469
    }
1470
    gen_op_set_bcond();
1471

  
1472
    MIPS_DEBUG("enter ds: cond %02x target %08x",
1473
               ctx->hflags, btarget);
1474
    ctx->btarget = btarget;
1475

  
1476
    return;
1477
}
1478

  
1268 1479
/* Coprocessor 1 (FPU) */
1480
static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs)
1481
{
1482
    const unsigned char *opn = "unk";
1483

  
1484
    switch (opc) {
1485
    case OPC_MFC1:
1486
        GEN_LOAD_FREG_FTN(WT0, fs);
1487
        gen_op_mfc1();
1488
        GEN_STORE_TN_REG(rt, T0);
1489
        opn = "mfc1";
1490
        break;
1491
    case OPC_MTC1:
1492
        GEN_LOAD_REG_TN(T0, rt);
1493
        gen_op_mtc1();
1494
        GEN_STORE_FTN_FREG(fs, WT0);
1495
        opn = "mtc1";
1496
        break;
1497
    case OPC_CFC1:
1498
        if (fs != 0 && fs != 31) {
1499
            MIPS_INVAL("cfc1 freg");
1500
            generate_exception(ctx, EXCP_RI);
1501
            return;
1502
        }
1503
        GEN_LOAD_IMM_TN(T1, fs);
1504
        gen_op_cfc1();
1505
        GEN_STORE_TN_REG(rt, T0);
1506
        opn = "cfc1";
1507
        break;
1508
    case OPC_CTC1:
1509
        if (fs != 0 && fs != 31) {
1510
            MIPS_INVAL("ctc1 freg");
1511
            generate_exception(ctx, EXCP_RI);
1512
            return;
1513
        }
1514
        GEN_LOAD_IMM_TN(T1, fs);
1515
        GEN_LOAD_REG_TN(T0, rt);
1516
        gen_op_ctc1();
1517
        opn = "ctc1";
1518
        break;
1519
    default:
1520
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1521
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
1522
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1523
                    ((ctx->opcode >> 16) & 0x1F));
1524
        }
1525
        generate_exception(ctx, EXCP_RI);
1526
        return;
1527
    }
1528
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1529
}
1530

  
1531
/* verify if floating point register is valid; an operation is not defined
1532
 * if bit 0 of any register specification is set and the FR bit in the
1533
 * Status register equals zero, since the register numbers specify an
1534
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1535
 * in the Status register equals one, both even and odd register numbers
1536
 * are valid.
1537
 * 
1538
 * Multiple float registers can be checked by calling
1539
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
1540
 */
1541
#define CHECK_FR(ctx, freg) do { \
1542
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
1543
            generate_exception(ctx, EXCP_RI); \
1544
            return; \
1545
        } \
1546
    } while(0)
1547

  
1548
#define FOP(func, fmt) (((fmt) << 21) | (func))
1549

  
1550
static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int func)
1551
{
1552
    const unsigned char *opn = "unk";
1553
    const char *condnames[] = {
1554
            "c.f",
1555
            "c.un",
1556
            "c.eq",
1557
            "c.ueq",
1558
            "c.olt",
1559
            "c.ult",
1560
            "c.ole",
1561
            "c.ule",
1562
            "c.sf",
1563
            "c.ngle",
1564
            "c.seq",
1565
            "c.ngl",
1566
            "c.lt",
1567
            "c.nge",
1568
            "c.le",
1569
            "c.ngt",
1570
    };
1571
    int binary = 0;
1572
    
1573
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
1574
    case FOP(0, 17):
1575
        CHECK_FR(ctx, fs | ft | fd);
1576
        GEN_LOAD_FREG_FTN(DT0, fs);
1577
        GEN_LOAD_FREG_FTN(DT1, ft);
1578
        gen_op_float_add_d();
1579
        GEN_STORE_FTN_FREG(fd, DT2);
1580
        opn = "add.d";
1581
        binary = 1;
1582
        break;
1583
    case FOP(1, 17):
1584
        CHECK_FR(ctx, fs | ft | fd);
1585
        GEN_LOAD_FREG_FTN(DT0, fs);
1586
        GEN_LOAD_FREG_FTN(DT1, ft);
1587
        gen_op_float_sub_d();
1588
        GEN_STORE_FTN_FREG(fd, DT2);
1589
        opn = "sub.d";
1590
        binary = 1;
1591
        break;
1592
    case FOP(2, 17):
1593
        CHECK_FR(ctx, fs | ft | fd);
1594
        GEN_LOAD_FREG_FTN(DT0, fs);
1595
        GEN_LOAD_FREG_FTN(DT1, ft);
1596
        gen_op_float_mul_d();
1597
        GEN_STORE_FTN_FREG(fd, DT2);
1598
        opn = "mul.d";
1599
        binary = 1;
1600
        break;
1601
    case FOP(3, 17):
1602
        CHECK_FR(ctx, fs | ft | fd);
1603
        GEN_LOAD_FREG_FTN(DT0, fs);
1604
        GEN_LOAD_FREG_FTN(DT1, ft);
1605
        gen_op_float_div_d();
1606
        GEN_STORE_FTN_FREG(fd, DT2);
1607
        opn = "div.d";
1608
        binary = 1;
1609
        break;
1610
    case FOP(4, 17):
1611
        CHECK_FR(ctx, fs | fd);
1612
        GEN_LOAD_FREG_FTN(DT0, fs);
1613
        gen_op_float_sqrt_d();
1614
        GEN_STORE_FTN_FREG(fd, DT2);
1615
        opn = "sqrt.d";
1616
        break;
1617
    case FOP(5, 17):
1618
        CHECK_FR(ctx, fs | fd);
1619
        GEN_LOAD_FREG_FTN(DT0, fs);
1620
        gen_op_float_abs_d();
1621
        GEN_STORE_FTN_FREG(fd, DT2);
1622
        opn = "abs.d";
1623
        break;
1624
    case FOP(6, 17):
1625
        CHECK_FR(ctx, fs | fd);
1626
        GEN_LOAD_FREG_FTN(DT0, fs);
1627
        gen_op_float_mov_d();
1628
        GEN_STORE_FTN_FREG(fd, DT2);
1629
        opn = "mov.d";
1630
        break;
1631
    case FOP(7, 17):
1632
        CHECK_FR(ctx, fs | fd);
1633
        GEN_LOAD_FREG_FTN(DT0, fs);
1634
        gen_op_float_chs_d();
1635
        GEN_STORE_FTN_FREG(fd, DT2);
1636
        opn = "neg.d";
1637
        break;
1638
    /*  8 - round.l */
1639
    /*  9 - trunc.l */
1640
    /* 10 - ceil.l  */
1641
    /* 11 - floor.l */
1642
    case FOP(12, 17):
1643
        CHECK_FR(ctx, fs | fd);
1644
        GEN_LOAD_FREG_FTN(DT0, fs);
1645
        gen_op_float_roundw_d();
1646
        GEN_STORE_FTN_FREG(fd, WT2);
1647
        opn = "round.w.d";
1648
        break;
1649
    case FOP(13, 17):
1650
        CHECK_FR(ctx, fs | fd);
1651
        GEN_LOAD_FREG_FTN(DT0, fs);
1652
        gen_op_float_truncw_d();
1653
        GEN_STORE_FTN_FREG(fd, WT2);
1654
        opn = "trunc.w.d";
1655
        break;
1656
    case FOP(14, 17):
1657
        CHECK_FR(ctx, fs | fd);
1658
        GEN_LOAD_FREG_FTN(DT0, fs);
1659
        gen_op_float_ceilw_d();
1660
        GEN_STORE_FTN_FREG(fd, WT2);
1661
        opn = "ceil.w.d";
1662
        break;
1663
    case FOP(15, 17):
1664
        CHECK_FR(ctx, fs | fd);
1665
        GEN_LOAD_FREG_FTN(DT0, fs);
1666
        gen_op_float_floorw_d();
1667
        GEN_STORE_FTN_FREG(fd, WT2);
1668
        opn = "ceil.w.d";
1669
        break;
1670
    case FOP(33, 20): /* cvt.d.w */
1671
        CHECK_FR(ctx, fs | fd);
1672
        GEN_LOAD_FREG_FTN(WT0, fs);
1673
        gen_op_float_cvtd_w();
1674
        GEN_STORE_FTN_FREG(fd, DT2);
1675
        opn = "cvt.d.w";
1676
        break;
1677
    case FOP(48, 17):
1678
    case FOP(49, 17):
1679
    case FOP(50, 17):
1680
    case FOP(51, 17):
1681
    case FOP(52, 17):
1682
    case FOP(53, 17):
1683
    case FOP(54, 17):
1684
    case FOP(55, 17):
1685
    case FOP(56, 17):
1686
    case FOP(57, 17):
1687
    case FOP(58, 17):
1688
    case FOP(59, 17):
1689
    case FOP(60, 17):
1690
    case FOP(61, 17):
1691
    case FOP(62, 17):
1692
    case FOP(63, 17):
1693
        CHECK_FR(ctx, fs | ft);
1694
        GEN_LOAD_FREG_FTN(DT0, fs);
1695
        GEN_LOAD_FREG_FTN(DT1, ft);
1696
        gen_cmp_d(func-48);
1697
        opn = condnames[func-48];
1698
        break;
1699
    case FOP(0, 16):
1700
        CHECK_FR(ctx, fs | ft | fd);
1701
        GEN_LOAD_FREG_FTN(WT0, fs);
1702
        GEN_LOAD_FREG_FTN(WT1, ft);
1703
        gen_op_float_add_s();
1704
        GEN_STORE_FTN_FREG(fd, WT2);
1705
        opn = "add.s";
1706
        binary = 1;
1707
        break;
1708
    case FOP(1, 16):
1709
        CHECK_FR(ctx, fs | ft | fd);
1710
        GEN_LOAD_FREG_FTN(WT0, fs);
1711
        GEN_LOAD_FREG_FTN(WT1, ft);
1712
        gen_op_float_sub_s();
1713
        GEN_STORE_FTN_FREG(fd, WT2);
1714
        opn = "sub.s";
1715
        binary = 1;
1716
        break;
1717
    case FOP(2, 16):
1718
        CHECK_FR(ctx, fs | ft | fd);
1719
        GEN_LOAD_FREG_FTN(WT0, fs);
1720
        GEN_LOAD_FREG_FTN(WT1, ft);
1721
        gen_op_float_mul_s();
1722
        GEN_STORE_FTN_FREG(fd, WT2);
1723
        opn = "mul.s";
1724
        binary = 1;
1725
        break;
1726
    case FOP(3, 16):
1727
        CHECK_FR(ctx, fs | ft | fd);
1728
        GEN_LOAD_FREG_FTN(WT0, fs);
1729
        GEN_LOAD_FREG_FTN(WT1, ft);
1730
        gen_op_float_div_s();
1731
        GEN_STORE_FTN_FREG(fd, WT2);
1732
        opn = "div.s";
1733
        binary = 1;
1734
        break;
1735
    case FOP(4, 16):
1736
        CHECK_FR(ctx, fs | fd);
1737
        GEN_LOAD_FREG_FTN(WT0, fs);
1738
        gen_op_float_sqrt_s();
1739
        GEN_STORE_FTN_FREG(fd, WT2);
1740
        opn = "sqrt.s";
1741
        break;
1742
    case FOP(5, 16):
1743
        CHECK_FR(ctx, fs | fd);
1744
        GEN_LOAD_FREG_FTN(WT0, fs);
1745
        gen_op_float_abs_s();
1746
        GEN_STORE_FTN_FREG(fd, WT2);
1747
        opn = "abs.s";
1748
        break;
1749
    case FOP(6, 16):
1750
        CHECK_FR(ctx, fs | fd);
1751
        GEN_LOAD_FREG_FTN(WT0, fs);
1752
        gen_op_float_mov_s();
1753
        GEN_STORE_FTN_FREG(fd, WT2);
1754
        opn = "mov.s";
1755
        break;
1756
    case FOP(7, 16):
1757
        CHECK_FR(ctx, fs | fd);
1758
        GEN_LOAD_FREG_FTN(WT0, fs);
1759
        gen_op_float_chs_s();
1760
        GEN_STORE_FTN_FREG(fd, WT2);
1761
        opn = "neg.s";
1762
        break;
1763
    case FOP(12, 16):
1764
        CHECK_FR(ctx, fs | fd);
1765
        GEN_LOAD_FREG_FTN(WT0, fs);
1766
        gen_op_float_roundw_s();
1767
        GEN_STORE_FTN_FREG(fd, WT2);
1768
        opn = "round.w.s";
1769
        break;
1770
    case FOP(13, 16):
1771
        CHECK_FR(ctx, fs | fd);
1772
        GEN_LOAD_FREG_FTN(WT0, fs);
1773
        gen_op_float_truncw_s();
1774
        GEN_STORE_FTN_FREG(fd, WT2);
1775
        opn = "trunc.w.s";
1776
        break;
1777
    case FOP(32, 20): /* cvt.s.w */
1778
        CHECK_FR(ctx, fs | fd);
1779
        GEN_LOAD_FREG_FTN(WT0, fs);
1780
        gen_op_float_cvts_w();
1781
        GEN_STORE_FTN_FREG(fd, WT2);
1782
        opn = "cvt.s.w";
1783
        break;
1784
    case FOP(36, 16): /* cvt.w.s */
1785
        CHECK_FR(ctx, fs | fd);
1786
        GEN_LOAD_FREG_FTN(WT0, fs);
1787
        gen_op_float_cvtw_s();
1788
        GEN_STORE_FTN_FREG(fd, WT2);
1789
        opn = "cvt.w.s";
1790
        break;
1791
    case FOP(36, 17): /* cvt.w.d */
1792
        CHECK_FR(ctx, fs | fd);
1793
        GEN_LOAD_FREG_FTN(WT0, fs);
1794
        gen_op_float_cvtw_d();
1795
        GEN_STORE_FTN_FREG(fd, WT2);
1796
        opn = "cvt.w.d";
1797
        break;
1798
    case FOP(48, 16):
1799
    case FOP(49, 16):
1800
    case FOP(50, 16):
1801
    case FOP(51, 16):
1802
    case FOP(52, 16):
1803
    case FOP(53, 16):
1804
    case FOP(54, 16):
1805
    case FOP(55, 16):
1806
    case FOP(56, 16):
1807
    case FOP(57, 16):
1808
    case FOP(58, 16):
1809
    case FOP(59, 16):
1810
    case FOP(60, 16):
1811
    case FOP(61, 16):
1812
    case FOP(62, 16):
1813
    case FOP(63, 16):
1814
        CHECK_FR(ctx, fs | ft);
1815
        GEN_LOAD_FREG_FTN(WT0, fs);
1816
        GEN_LOAD_FREG_FTN(WT1, ft);
1817
        gen_cmp_s(func-48);
1818
        opn = condnames[func-48];
1819
        break;
1820
    default:    
1821
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1822
            fprintf(logfile, "Invalid arith function: %08x %03x %03x %03x\n",
1823
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1824
                    ((ctx->opcode >> 16) & 0x1F));
1825
        }
1826
        generate_exception(ctx, EXCP_RI);
1827
        return;
1828
    }
1829
    if (binary)
1830
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
1831
    else
1832
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
1833
}
1834
#endif
1269 1835

  
1270 1836
/* ISA extensions */
1271 1837
/* MIPS16 extension to MIPS32 */
......
1495 2061
    case 0x35: /* LDC1 */
1496 2062
    case 0x39: /* SWC1 */
1497 2063
    case 0x3D: /* SDC1 */
2064
#if defined(MIPS_USES_FPU)
2065
        gen_op_cp1_enabled();
2066
        gen_flt_ldst(ctx, op, rt, rs, imm);
2067
#else
2068
        generate_exception_err(ctx, EXCP_CpU, 1);
2069
#endif
2070
        break;
2071

  
1498 2072
    case 0x11:          /* CP1 opcode */
1499 2073
#if defined(MIPS_USES_FPU)
1500
        /* XXX: not correct */
2074
        gen_op_cp1_enabled();
2075
        op1 = ((ctx->opcode >> 21) & 0x1F);
2076
        switch (op1) {
2077
        case 0x00: /* mfc1 */
2078
        case 0x02: /* cfc1 */
2079
        case 0x04: /* mtc1 */
2080
        case 0x06: /* ctc1 */
2081
            gen_cp1(ctx, op1 | EXT_CP1, rt, rd);
2082
            break;
2083
        case 0x08: /* bc */
2084
            gen_compute_branch1(ctx, rt, imm << 2);
2085
            return;
2086
        case 0x10: /* 16: fmt=single fp */
2087
        case 0x11: /* 17: fmt=double fp */
2088
        case 0x14: /* 20: fmt=32bit fixed */
2089
        case 0x15: /* 21: fmt=64bit fixed */
2090
            gen_farith(ctx, op1, rt, rd, sa, ctx->opcode & 0x3f);
2091
            break;
2092
        default:
2093
            generate_exception_err(ctx, EXCP_RI, 1);
2094
            break;
2095
        }
2096
        break;
1501 2097
#else
1502 2098
        generate_exception_err(ctx, EXCP_CpU, 1);
1503 2099
#endif
......
1586 2182
    int j, lj = -1;
1587 2183

  
1588 2184
    if (search_pc && loglevel)
1589
	fprintf (logfile, "search pc %d\n", search_pc);
2185
        fprintf (logfile, "search pc %d\n", search_pc);
1590 2186

  
1591 2187
    pc_start = tb->pc;
1592 2188
    gen_opc_ptr = gen_opc_buf;
......
1696 2292
#endif
1697 2293
    if (loglevel & CPU_LOG_TB_IN_ASM) {
1698 2294
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1699
	target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
2295
    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1700 2296
        fprintf(logfile, "\n");
1701 2297
    }
1702 2298
    if (loglevel & CPU_LOG_TB_OP) {
......
1722 2318
    return gen_intermediate_code_internal(env, tb, 1);
1723 2319
}
1724 2320

  
2321
#ifdef MIPS_USES_FPU
2322
void fpu_dump_state(CPUState *env, FILE *f, 
2323
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
2324
                    int flags)
2325
{
2326
    int i;
2327

  
2328
#   define printfpr(fp) do { \
2329
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
2330
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
2331
    } while(0)
2332

  
2333
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
2334
                env->fcr0, env->fcr31,
2335
                (env->CP0_Status & (1<<CP0St_FR)) != 0);
2336
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
2337
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
2338
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
2339
    for(i=0; i < 32; i+=2) {
2340
        fpu_fprintf(f, "f%02d: ", i);
2341
        printfpr(FPR(env, i));
2342
    }
2343

  
2344
#undef printfpr
2345
}
2346

  
2347
void dump_fpu(CPUState *env)
2348
{
2349
    if (loglevel) { 
2350
       fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
2351
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
2352
       fpu_dump_state(env, logfile, fprintf, 0);
2353
    }
2354
}
2355
#endif /* MIPS_USES_FPU */
2356

  
1725 2357
void cpu_dump_state (CPUState *env, FILE *f, 
1726 2358
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1727 2359
                     int flags)
......
1751 2383
                c0_status, env->CP0_Cause, env->CP0_EPC);
1752 2384
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
1753 2385
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
2386
#ifdef MIPS_USES_FPU
2387
    fpu_dump_state(env, f, cpu_fprintf, flags);
2388
#endif
1754 2389
}
1755 2390

  
1756 2391
CPUMIPSState *cpu_mips_init (void)
......
1788 2423
#if defined(CONFIG_USER_ONLY)
1789 2424
    env->hflags |= MIPS_HFLAG_UM;
1790 2425
#endif
2426
#ifdef MIPS_USES_FPU
2427
    env->fcr0 = MIPS_FCR0;	
2428
#endif
1791 2429
    return env;
1792 2430
}

Also available in: Unified diff