Revision 9ee6e8bb target-arm/translate.c

b/target-arm/translate.c
2 2
 *  ARM translation
3 3
 *
4 4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005 CodeSourcery, LLC
5
 *  Copyright (c) 2005-2007 CodeSourcery
6 6
 *  Copyright (c) 2007 OpenedHand, Ltd.
7 7
 *
8 8
 * This library is free software; you can redistribute it and/or
......
29 29
#include "exec-all.h"
30 30
#include "disas.h"
31 31

  
32
#define ENABLE_ARCH_5J  0
33
#define ENABLE_ARCH_6   1
34
#define ENABLE_ARCH_6T2 1
32
#define ENABLE_ARCH_5J    0
33
#define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
34
#define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
35
#define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
36
#define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
35 37

  
36 38
#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
37 39

  
......
43 45
    int condjmp;
44 46
    /* The label that will be jumped to when the instruction is skipped.  */
45 47
    int condlabel;
48
    /* Thumb-2 condtional execution bits.  */
49
    int condexec_mask;
50
    int condexec_cond;
46 51
    struct TranslationBlock *tb;
47 52
    int singlestep_enabled;
48 53
    int thumb;
......
58 63
#define IS_USER(s) (s->user)
59 64
#endif
60 65

  
61
#define DISAS_JUMP_NEXT 4
66
/* These instructions trap after executing, so defer them until after the
67
   conditional executions state has been updated.  */
68
#define DISAS_WFI 4
69
#define DISAS_SWI 5
62 70

  
63 71
#ifdef USE_DIRECT_JUMP
64 72
#define TBPARAM(x)
......
81 89

  
82 90
#include "gen-op.h"
83 91

  
92
#define PAS_OP(pfx) {  \
93
    gen_op_ ## pfx ## add16_T0_T1, \
94
    gen_op_ ## pfx ## addsubx_T0_T1, \
95
    gen_op_ ## pfx ## subaddx_T0_T1, \
96
    gen_op_ ## pfx ## sub16_T0_T1, \
97
    gen_op_ ## pfx ## add8_T0_T1, \
98
    NULL, \
99
    NULL, \
100
    gen_op_ ## pfx ## sub8_T0_T1 }
101

  
102
static GenOpFunc *gen_arm_parallel_addsub[8][8] = {
103
    {},
104
    PAS_OP(s),
105
    PAS_OP(q),
106
    PAS_OP(sh),
107
    {},
108
    PAS_OP(u),
109
    PAS_OP(uq),
110
    PAS_OP(uh),
111
};
112
#undef PAS_OP
113

  
114
/* For unknown reasons Arm and Thumb-2 use arbitrarily diffenet encodings.  */
115
#define PAS_OP(pfx) {  \
116
    gen_op_ ## pfx ## add8_T0_T1, \
117
    gen_op_ ## pfx ## add16_T0_T1, \
118
    gen_op_ ## pfx ## addsubx_T0_T1, \
119
    NULL, \
120
    gen_op_ ## pfx ## sub8_T0_T1, \
121
    gen_op_ ## pfx ## sub16_T0_T1, \
122
    gen_op_ ## pfx ## subaddx_T0_T1, \
123
    NULL }
124

  
125
static GenOpFunc *gen_thumb2_parallel_addsub[8][8] = {
126
    PAS_OP(s),
127
    PAS_OP(q),
128
    PAS_OP(sh),
129
    {},
130
    PAS_OP(u),
131
    PAS_OP(uq),
132
    PAS_OP(uh),
133
    {}
134
};
135
#undef PAS_OP
136

  
84 137
static GenOpFunc1 *gen_test_cc[14] = {
85 138
    gen_op_test_eq,
86 139
    gen_op_test_ne,
......
275 328
    gen_op_movl_T2_im,
276 329
};
277 330

  
331
static GenOpFunc1 *gen_shift_T0_im_thumb_cc[3] = {
332
    gen_op_shll_T0_im_thumb_cc,
333
    gen_op_shrl_T0_im_thumb_cc,
334
    gen_op_sarl_T0_im_thumb_cc,
335
};
336

  
278 337
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
279 338
    gen_op_shll_T0_im_thumb,
280 339
    gen_op_shrl_T0_im_thumb,
......
421 480
        gen_op_vfp_##name##s();           \
422 481
}
423 482

  
483
#define VFP_OP1(name)                               \
484
static inline void gen_vfp_##name(int dp, int arg)  \
485
{                                                   \
486
    if (dp)                                         \
487
        gen_op_vfp_##name##d(arg);                  \
488
    else                                            \
489
        gen_op_vfp_##name##s(arg);                  \
490
}
491

  
424 492
VFP_OP(add)
425 493
VFP_OP(sub)
426 494
VFP_OP(mul)
......
437 505
VFP_OP(touiz)
438 506
VFP_OP(tosi)
439 507
VFP_OP(tosiz)
508
VFP_OP1(tosh)
509
VFP_OP1(tosl)
510
VFP_OP1(touh)
511
VFP_OP1(toul)
512
VFP_OP1(shto)
513
VFP_OP1(slto)
514
VFP_OP1(uhto)
515
VFP_OP1(ulto)
440 516

  
441 517
#undef VFP_OP
442 518

  
519
static inline void gen_vfp_fconst(int dp, uint32_t val)
520
{
521
    if (dp)
522
        gen_op_vfp_fconstd(val);
523
    else
524
        gen_op_vfp_fconsts(val);
525
}
526

  
443 527
static inline void gen_vfp_ld(DisasContext *s, int dp)
444 528
{
445 529
    if (dp)
......
469 553
          + offsetof(CPU_DoubleU, l.lower);
470 554
    }
471 555
}
556

  
557
/* Return the offset of a 32-bit piece of a NEON register.
558
   zero is the least significant end of the register.  */
559
static inline long
560
neon_reg_offset (int reg, int n)
561
{
562
    int sreg;
563
    sreg = reg * 2 + n;
564
    return vfp_reg_offset(0, sreg);
565
}
566

  
567
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
568
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
569

  
472 570
static inline void gen_mov_F0_vreg(int dp, int reg)
473 571
{
474 572
    if (dp)
......
1582 1680
    return 0;
1583 1681
}
1584 1682

  
1683
static int cp15_user_ok(uint32_t insn)
1684
{
1685
    int cpn = (insn >> 16) & 0xf;
1686
    int cpm = insn & 0xf;
1687
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
1688

  
1689
    if (cpn == 13 && cpm == 0) {
1690
        /* TLS register.  */
1691
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
1692
            return 1;
1693
    }
1694
    if (cpn == 7) {
1695
        /* ISB, DSB, DMB.  */
1696
        if ((cpm == 5 && op == 4)
1697
                || (cpm == 10 && (op == 4 || op == 5)))
1698
            return 1;
1699
    }
1700
    return 0;
1701
}
1702

  
1585 1703
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
1586 1704
   instruction is not defined.  */
1587 1705
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
1588 1706
{
1589 1707
    uint32_t rd;
1590 1708

  
1591
    /* ??? Some cp15 registers are accessible from userspace.  */
1592
    if (IS_USER(s)) {
1709
    /* M profile cores use memory mapped registers instead of cp15.  */
1710
    if (arm_feature(env, ARM_FEATURE_M))
1711
	return 1;
1712

  
1713
    if ((insn & (1 << 25)) == 0) {
1714
        if (insn & (1 << 20)) {
1715
            /* mrrc */
1716
            return 1;
1717
        }
1718
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
1719
        return 0;
1720
    }
1721
    if ((insn & (1 << 4)) == 0) {
1722
        /* cdp */
1723
        return 1;
1724
    }
1725
    if (IS_USER(s) && !cp15_user_ok(insn)) {
1593 1726
        return 1;
1594 1727
    }
1595 1728
    if ((insn & 0x0fff0fff) == 0x0e070f90
......
1597 1730
        /* Wait for interrupt.  */
1598 1731
        gen_op_movl_T0_im((long)s->pc);
1599 1732
        gen_op_movl_reg_TN[0][15]();
1600
        gen_op_wfi();
1601
        s->is_jmp = DISAS_JUMP;
1733
        s->is_jmp = DISAS_WFI;
1602 1734
        return 0;
1603 1735
    }
1604 1736
    rd = (insn >> 12) & 0xf;
......
1620 1752
    return 0;
1621 1753
}
1622 1754

  
1755
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
1756
#define VFP_SREG(insn, bigbit, smallbit) \
1757
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
1758
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
1759
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
1760
        reg = (((insn) >> (bigbit)) & 0x0f) \
1761
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
1762
    } else { \
1763
        if (insn & (1 << (smallbit))) \
1764
            return 1; \
1765
        reg = ((insn) >> (bigbit)) & 0x0f; \
1766
    }} while (0)
1767

  
1768
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
1769
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
1770
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
1771
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
1772
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
1773
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
1774

  
1775
static inline int
1776
vfp_enabled(CPUState * env)
1777
{
1778
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
1779
}
1780

  
1623 1781
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
1624 1782
   (ie. an undefined instruction).  */
1625 1783
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
......
1630 1788
    if (!arm_feature(env, ARM_FEATURE_VFP))
1631 1789
        return 1;
1632 1790

  
1633
    if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) {
1634
        /* VFP disabled.  Only allow fmxr/fmrx to/from fpexc and fpsid.  */
1791
    if (!vfp_enabled(env)) {
1792
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
1635 1793
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
1636 1794
            return 1;
1637 1795
        rn = (insn >> 16) & 0xf;
1638
        if (rn != 0 && rn != 8)
1796
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
1797
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
1639 1798
            return 1;
1640 1799
    }
1641 1800
    dp = ((insn & 0xf00) == 0xb00);
......
1643 1802
    case 0xe:
1644 1803
        if (insn & (1 << 4)) {
1645 1804
            /* single register transfer */
1646
            if ((insn & 0x6f) != 0x00)
1647
                return 1;
1648 1805
            rd = (insn >> 12) & 0xf;
1649 1806
            if (dp) {
1650
                if (insn & 0x80)
1807
                int size;
1808
                int pass;
1809

  
1810
                VFP_DREG_N(rn, insn);
1811
                if (insn & 0xf)
1651 1812
                    return 1;
1652
                rn = (insn >> 16) & 0xf;
1653
                /* Get the existing value even for arm->vfp moves because
1654
                   we only set half the register.  */
1655
                gen_mov_F0_vreg(1, rn);
1656
                gen_op_vfp_mrrd();
1813
                if (insn & 0x00c00060
1814
                    && !arm_feature(env, ARM_FEATURE_NEON))
1815
                    return 1;
1816

  
1817
                pass = (insn >> 21) & 1;
1818
                if (insn & (1 << 22)) {
1819
                    size = 0;
1820
                    offset = ((insn >> 5) & 3) * 8;
1821
                } else if (insn & (1 << 5)) {
1822
                    size = 1;
1823
                    offset = (insn & (1 << 6)) ? 16 : 0;
1824
                } else {
1825
                    size = 2;
1826
                    offset = 0;
1827
                }
1657 1828
                if (insn & ARM_CP_RW_BIT) {
1658 1829
                    /* vfp->arm */
1659
                    if (insn & (1 << 21))
1660
                        gen_movl_reg_T1(s, rd);
1661
                    else
1662
                        gen_movl_reg_T0(s, rd);
1830
                    switch (size) {
1831
                    case 0:
1832
                        NEON_GET_REG(T1, rn, pass);
1833
                        if (offset)
1834
                            gen_op_shrl_T1_im(offset);
1835
                        if (insn & (1 << 23))
1836
                            gen_op_uxtb_T1();
1837
                        else
1838
                            gen_op_sxtb_T1();
1839
                        break;
1840
                    case 1:
1841
                        NEON_GET_REG(T1, rn, pass);
1842
                        if (insn & (1 << 23)) {
1843
                            if (offset) {
1844
                                gen_op_shrl_T1_im(16);
1845
                            } else {
1846
                                gen_op_uxth_T1();
1847
                            }
1848
                        } else {
1849
                            if (offset) {
1850
                                gen_op_sarl_T1_im(16);
1851
                            } else {
1852
                                gen_op_sxth_T1();
1853
                            }
1854
                        }
1855
                        break;
1856
                    case 2:
1857
                        NEON_GET_REG(T1, rn, pass);
1858
                        break;
1859
                    }
1860
                    gen_movl_reg_T1(s, rd);
1663 1861
                } else {
1664 1862
                    /* arm->vfp */
1665
                    if (insn & (1 << 21))
1666
                        gen_movl_T1_reg(s, rd);
1667
                    else
1668
                        gen_movl_T0_reg(s, rd);
1669
                    gen_op_vfp_mdrr();
1670
                    gen_mov_vreg_F0(dp, rn);
1863
                    gen_movl_T0_reg(s, rd);
1864
                    if (insn & (1 << 23)) {
1865
                        /* VDUP */
1866
                        if (size == 0) {
1867
                            gen_op_neon_dup_u8(0);
1868
                        } else if (size == 1) {
1869
                            gen_op_neon_dup_low16();
1870
                        }
1871
                        NEON_SET_REG(T0, rn, 0);
1872
                        NEON_SET_REG(T0, rn, 1);
1873
                    } else {
1874
                        /* VMOV */
1875
                        switch (size) {
1876
                        case 0:
1877
                            NEON_GET_REG(T2, rn, pass);
1878
                            gen_op_movl_T1_im(0xff);
1879
                            gen_op_andl_T0_T1();
1880
                            gen_op_neon_insert_elt(offset, ~(0xff << offset));
1881
                            NEON_SET_REG(T2, rn, pass);
1882
                            break;
1883
                        case 1:
1884
                            NEON_GET_REG(T2, rn, pass);
1885
                            gen_op_movl_T1_im(0xffff);
1886
                            gen_op_andl_T0_T1();
1887
                            bank_mask = offset ? 0xffff : 0xffff0000;
1888
                            gen_op_neon_insert_elt(offset, bank_mask);
1889
                            NEON_SET_REG(T2, rn, pass);
1890
                            break;
1891
                        case 2:
1892
                            NEON_SET_REG(T0, rn, pass);
1893
                            break;
1894
                        }
1895
                    }
1671 1896
                }
1672
            } else {
1673
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
1897
            } else { /* !dp */
1898
                if ((insn & 0x6f) != 0x00)
1899
                    return 1;
1900
                rn = VFP_SREG_N(insn);
1674 1901
                if (insn & ARM_CP_RW_BIT) {
1675 1902
                    /* vfp->arm */
1676 1903
                    if (insn & (1 << 21)) {
1677 1904
                        /* system register */
1678 1905
                        rn >>= 1;
1906

  
1679 1907
                        switch (rn) {
1680 1908
                        case ARM_VFP_FPSID:
1909
                            /* VFP2 allows access for FSID from userspace.
1910
                               VFP3 restricts all id registers to privileged
1911
                               accesses.  */
1912
                            if (IS_USER(s)
1913
                                && arm_feature(env, ARM_FEATURE_VFP3))
1914
                                return 1;
1915
                            gen_op_vfp_movl_T0_xreg(rn);
1916
                            break;
1681 1917
                        case ARM_VFP_FPEXC:
1918
                            if (IS_USER(s))
1919
                                return 1;
1920
                            gen_op_vfp_movl_T0_xreg(rn);
1921
                            break;
1682 1922
                        case ARM_VFP_FPINST:
1683 1923
                        case ARM_VFP_FPINST2:
1924
                            /* Not present in VFP3.  */
1925
                            if (IS_USER(s)
1926
                                || arm_feature(env, ARM_FEATURE_VFP3))
1927
                                return 1;
1684 1928
                            gen_op_vfp_movl_T0_xreg(rn);
1685 1929
                            break;
1686 1930
                        case ARM_VFP_FPSCR:
......
1689 1933
			    else
1690 1934
				gen_op_vfp_movl_T0_fpscr();
1691 1935
                            break;
1936
                        case ARM_VFP_MVFR0:
1937
                        case ARM_VFP_MVFR1:
1938
                            if (IS_USER(s)
1939
                                || !arm_feature(env, ARM_FEATURE_VFP3))
1940
                                return 1;
1941
                            gen_op_vfp_movl_T0_xreg(rn);
1942
                            break;
1692 1943
                        default:
1693 1944
                            return 1;
1694 1945
                        }
......
1709 1960
                        /* system register */
1710 1961
                        switch (rn) {
1711 1962
                        case ARM_VFP_FPSID:
1963
                        case ARM_VFP_MVFR0:
1964
                        case ARM_VFP_MVFR1:
1712 1965
                            /* Writes are ignored.  */
1713 1966
                            break;
1714 1967
                        case ARM_VFP_FPSCR:
......
1716 1969
                            gen_lookup_tb(s);
1717 1970
                            break;
1718 1971
                        case ARM_VFP_FPEXC:
1972
                            if (IS_USER(s))
1973
                                return 1;
1719 1974
                            gen_op_vfp_movl_xreg_T0(rn);
1720 1975
                            gen_lookup_tb(s);
1721 1976
                            break;
......
1742 1997
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
1743 1998
                } else {
1744 1999
                    /* rn is register number */
1745
                    if (insn & (1 << 7))
1746
                        return 1;
1747
                    rn = (insn >> 16) & 0xf;
2000
                    VFP_DREG_N(rn, insn);
1748 2001
                }
1749 2002

  
1750 2003
                if (op == 15 && (rn == 15 || rn > 17)) {
1751 2004
                    /* Integer or single precision destination.  */
1752
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
2005
                    rd = VFP_SREG_D(insn);
1753 2006
                } else {
1754
                    if (insn & (1 << 22))
1755
                        return 1;
1756
                    rd = (insn >> 12) & 0xf;
2007
                    VFP_DREG_D(rd, insn);
1757 2008
                }
1758 2009

  
1759 2010
                if (op == 15 && (rn == 16 || rn == 17)) {
1760 2011
                    /* Integer source.  */
1761 2012
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
1762 2013
                } else {
1763
                    if (insn & (1 << 5))
1764
                        return 1;
1765
                    rm = insn & 0xf;
2014
                    VFP_DREG_M(rm, insn);
1766 2015
                }
1767 2016
            } else {
1768
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2017
                rn = VFP_SREG_N(insn);
1769 2018
                if (op == 15 && rn == 15) {
1770 2019
                    /* Double precision destination.  */
1771
                    if (insn & (1 << 22))
1772
                        return 1;
1773
                    rd = (insn >> 12) & 0xf;
1774
                } else
1775
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
1776
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2020
                    VFP_DREG_D(rd, insn);
2021
                } else {
2022
                    rd = VFP_SREG_D(insn);
2023
                }
2024
                rm = VFP_SREG_M(insn);
1777 2025
            }
1778 2026

  
1779 2027
            veclen = env->vfp.vec_len;
......
1831 2079
                    gen_mov_F0_vreg(dp, rd);
1832 2080
                    gen_vfp_F1_ld0(dp);
1833 2081
                    break;
2082
                case 20:
2083
                case 21:
2084
                case 22:
2085
                case 23:
2086
                    /* Source and destination the same.  */
2087
                    gen_mov_F0_vreg(dp, rd);
2088
                    break;
1834 2089
                default:
1835 2090
                    /* One source operand.  */
1836 2091
                    gen_mov_F0_vreg(dp, rm);
2092
                    break;
1837 2093
                }
1838 2094
            } else {
1839 2095
                /* Two source operands.  */
......
1882 2138
                case 8: /* div: fn / fm */
1883 2139
                    gen_vfp_div(dp);
1884 2140
                    break;
2141
                case 14: /* fconst */
2142
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2143
                      return 1;
2144

  
2145
                    n = (insn << 12) & 0x80000000;
2146
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
2147
                    if (dp) {
2148
                        if (i & 0x40)
2149
                            i |= 0x3f80;
2150
                        else
2151
                            i |= 0x4000;
2152
                        n |= i << 16;
2153
                    } else {
2154
                        if (i & 0x40)
2155
                            i |= 0x780;
2156
                        else
2157
                            i |= 0x800;
2158
                        n |= i << 19;
2159
                    }
2160
                    gen_vfp_fconst(dp, n);
2161
                    break;
1885 2162
                case 15: /* extension space */
1886 2163
                    switch (rn) {
1887 2164
                    case 0: /* cpy */
......
1921 2198
                    case 17: /* fsito */
1922 2199
                        gen_vfp_sito(dp);
1923 2200
                        break;
2201
                    case 20: /* fshto */
2202
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2203
                          return 1;
2204
                        gen_vfp_shto(dp, rm);
2205
                        break;
2206
                    case 21: /* fslto */
2207
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2208
                          return 1;
2209
                        gen_vfp_slto(dp, rm);
2210
                        break;
2211
                    case 22: /* fuhto */
2212
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2213
                          return 1;
2214
                        gen_vfp_uhto(dp, rm);
2215
                        break;
2216
                    case 23: /* fulto */
2217
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2218
                          return 1;
2219
                        gen_vfp_ulto(dp, rm);
2220
                        break;
1924 2221
                    case 24: /* ftoui */
1925 2222
                        gen_vfp_toui(dp);
1926 2223
                        break;
......
1933 2230
                    case 27: /* ftosiz */
1934 2231
                        gen_vfp_tosiz(dp);
1935 2232
                        break;
2233
                    case 28: /* ftosh */
2234
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2235
                          return 1;
2236
                        gen_vfp_tosh(dp, rm);
2237
                        break;
2238
                    case 29: /* ftosl */
2239
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2240
                          return 1;
2241
                        gen_vfp_tosl(dp, rm);
2242
                        break;
2243
                    case 30: /* ftouh */
2244
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2245
                          return 1;
2246
                        gen_vfp_touh(dp, rm);
2247
                        break;
2248
                    case 31: /* ftoul */
2249
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2250
                          return 1;
2251
                        gen_vfp_toul(dp, rm);
2252
                        break;
1936 2253
                    default: /* undefined */
1937 2254
                        printf ("rn:%d\n", rn);
1938 2255
                        return 1;
......
1994 2311
        break;
1995 2312
    case 0xc:
1996 2313
    case 0xd:
1997
        if (dp && (insn & (1 << 22))) {
2314
        if (dp && (insn & 0x03e00000) == 0x00400000) {
1998 2315
            /* two-register transfer */
1999 2316
            rn = (insn >> 16) & 0xf;
2000 2317
            rd = (insn >> 12) & 0xf;
2001 2318
            if (dp) {
2002
                if (insn & (1 << 5))
2003
                    return 1;
2004
                rm = insn & 0xf;
2005
            } else
2006
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2319
                VFP_DREG_M(rm, insn);
2320
            } else {
2321
                rm = VFP_SREG_M(insn);
2322
            }
2007 2323

  
2008 2324
            if (insn & ARM_CP_RW_BIT) {
2009 2325
                /* vfp->arm */
......
2040 2356
            /* Load/store */
2041 2357
            rn = (insn >> 16) & 0xf;
2042 2358
            if (dp)
2043
                rd = (insn >> 12) & 0xf;
2359
                VFP_DREG_D(rd, insn);
2044 2360
            else
2045
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
2046
            gen_movl_T1_reg(s, rn);
2361
                rd = VFP_SREG_D(insn);
2362
            if (s->thumb && rn == 15) {
2363
                gen_op_movl_T1_im(s->pc & ~2);
2364
            } else {
2365
                gen_movl_T1_reg(s, rn);
2366
            }
2047 2367
            if ((insn & 0x01200000) == 0x01000000) {
2048 2368
                /* Single load/store */
2049 2369
                offset = (insn & 0xff) << 2;
......
2156 2476
}
2157 2477

  
2158 2478
/* Return the mask of PSR bits set by a MSR instruction.  */
2159
static uint32_t msr_mask(DisasContext *s, int flags, int spsr) {
2479
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
2160 2480
    uint32_t mask;
2481
    uint32_t reserved;
2161 2482

  
2162 2483
    mask = 0;
2163 2484
    if (flags & (1 << 0))
......
2168 2489
        mask |= 0xff0000;
2169 2490
    if (flags & (1 << 3))
2170 2491
        mask |= 0xff000000;
2492

  
2171 2493
    /* Mask out undefined bits.  */
2172
    mask &= 0xf90f03ff;
2173
    /* Mask out state bits.  */
2494
    mask &= ~CPSR_RESERVED;
2495
    if (!arm_feature(env, ARM_FEATURE_V6))
2496
        reserved &= ~(CPSR_E | CPSR_GE);
2497
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
2498
        reserved &= ~CPSR_IT;
2499
    /* Mask out execution state bits.  */
2174 2500
    if (!spsr)
2175
        mask &= ~0x01000020;
2501
        reserved &= ~CPSR_EXEC;
2176 2502
    /* Mask out privileged bits.  */
2177 2503
    if (IS_USER(s))
2178
        mask &= 0xf80f0200;
2504
        mask &= CPSR_USER;
2179 2505
    return mask;
2180 2506
}
2181 2507

  
......
2194 2520
    return 0;
2195 2521
}
2196 2522

  
2523
/* Generate an old-style exception return.  */
2197 2524
static void gen_exception_return(DisasContext *s)
2198 2525
{
2199 2526
    gen_op_movl_reg_TN[0][15]();
......
2202 2529
    s->is_jmp = DISAS_UPDATE;
2203 2530
}
2204 2531

  
2205
static void disas_arm_insn(CPUState * env, DisasContext *s)
2532
/* Generate a v6 exception return.  */
2533
static void gen_rfe(DisasContext *s)
2206 2534
{
2207
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
2535
    gen_op_movl_cpsr_T0(0xffffffff);
2536
    gen_op_movl_T0_T2();
2537
    gen_op_movl_reg_TN[0][15]();
2538
    s->is_jmp = DISAS_UPDATE;
2539
}
2208 2540

  
2209
    insn = ldl_code(s->pc);
2210
    s->pc += 4;
2541
static inline void
2542
gen_set_condexec (DisasContext *s)
2543
{
2544
    if (s->condexec_mask) {
2545
        gen_op_set_condexec((s->condexec_cond << 4) | (s->condexec_mask >> 1));
2546
    }
2547
}
2211 2548

  
2212
    cond = insn >> 28;
2213
    if (cond == 0xf){
2214
        /* Unconditional instructions.  */
2215
        if ((insn & 0x0d70f000) == 0x0550f000)
2216
            return; /* PLD */
2217
        else if ((insn & 0x0e000000) == 0x0a000000) {
2218
            /* branch link and change to thumb (blx <offset>) */
2219
            int32_t offset;
2549
static void gen_nop_hint(DisasContext *s, int val)
2550
{
2551
    switch (val) {
2552
    case 3: /* wfi */
2553
        gen_op_movl_T0_im((long)s->pc);
2554
        gen_op_movl_reg_TN[0][15]();
2555
        s->is_jmp = DISAS_WFI;
2556
        break;
2557
    case 2: /* wfe */
2558
    case 4: /* sev */
2559
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
2560
    default: /* nop */
2561
        break;
2562
    }
2563
}
2220 2564

  
2221
            val = (uint32_t)s->pc;
2222
            gen_op_movl_T0_im(val);
2223
            gen_movl_reg_T0(s, 14);
2224
            /* Sign-extend the 24-bit offset */
2225
            offset = (((int32_t)insn) << 8) >> 8;
2226
            /* offset * 4 + bit24 * 2 + (thumb bit) */
2227
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
2228
            /* pipeline offset */
2229
            val += 4;
2230
            gen_op_movl_T0_im(val);
2231
            gen_bx(s);
2232
            return;
2233
        } else if ((insn & 0x0e000f00) == 0x0c000100) {
2234
            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2235
                /* iWMMXt register transfer.  */
2236
                if (env->cp15.c15_cpar & (1 << 1))
2237
                    if (!disas_iwmmxt_insn(env, s, insn))
2238
                        return;
2239
            }
2240
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
2241
            /* Coprocessor double register transfer.  */
2242
        } else if ((insn & 0x0f000010) == 0x0e000010) {
2243
            /* Additional coprocessor register transfer.  */
2244
        } else if ((insn & 0x0ff10010) == 0x01000000) {
2245
            /* cps (privileged) */
2246
        } else if ((insn & 0x0ffffdff) == 0x01010000) {
2247
            /* setend */
2248
            if (insn & (1 << 9)) {
2249
                /* BE8 mode not implemented.  */
2250
                goto illegal_op;
2251
            }
2252
            return;
2253
        }
2254
        goto illegal_op;
2565
/* Neon shift by constant.  The actual ops are the same as used for variable
2566
   shifts.  [OP][U][SIZE]  */
2567
static GenOpFunc *gen_neon_shift_im[8][2][4] = {
2568
    { /* 0 */ /* VSHR */
2569
      {
2570
        gen_op_neon_shl_u8,
2571
        gen_op_neon_shl_u16,
2572
        gen_op_neon_shl_u32,
2573
        gen_op_neon_shl_u64
2574
      }, {
2575
        gen_op_neon_shl_s8,
2576
        gen_op_neon_shl_s16,
2577
        gen_op_neon_shl_s32,
2578
        gen_op_neon_shl_s64
2579
      }
2580
    }, { /* 1 */ /* VSRA */
2581
      {
2582
        gen_op_neon_shl_u8,
2583
        gen_op_neon_shl_u16,
2584
        gen_op_neon_shl_u32,
2585
        gen_op_neon_shl_u64
2586
      }, {
2587
        gen_op_neon_shl_s8,
2588
        gen_op_neon_shl_s16,
2589
        gen_op_neon_shl_s32,
2590
        gen_op_neon_shl_s64
2591
      }
2592
    }, { /* 2 */ /* VRSHR */
2593
      {
2594
        gen_op_neon_rshl_u8,
2595
        gen_op_neon_rshl_u16,
2596
        gen_op_neon_rshl_u32,
2597
        gen_op_neon_rshl_u64
2598
      }, {
2599
        gen_op_neon_rshl_s8,
2600
        gen_op_neon_rshl_s16,
2601
        gen_op_neon_rshl_s32,
2602
        gen_op_neon_rshl_s64
2603
      }
2604
    }, { /* 3 */ /* VRSRA */
2605
      {
2606
        gen_op_neon_rshl_u8,
2607
        gen_op_neon_rshl_u16,
2608
        gen_op_neon_rshl_u32,
2609
        gen_op_neon_rshl_u64
2610
      }, {
2611
        gen_op_neon_rshl_s8,
2612
        gen_op_neon_rshl_s16,
2613
        gen_op_neon_rshl_s32,
2614
        gen_op_neon_rshl_s64
2615
      }
2616
    }, { /* 4 */
2617
      {
2618
        NULL, NULL, NULL, NULL
2619
      }, { /* VSRI */
2620
        gen_op_neon_shl_u8,
2621
        gen_op_neon_shl_u16,
2622
        gen_op_neon_shl_u32,
2623
        gen_op_neon_shl_u64,
2624
      }
2625
    }, { /* 5 */
2626
      { /* VSHL */
2627
        gen_op_neon_shl_u8,
2628
        gen_op_neon_shl_u16,
2629
        gen_op_neon_shl_u32,
2630
        gen_op_neon_shl_u64,
2631
      }, { /* VSLI */
2632
        gen_op_neon_shl_u8,
2633
        gen_op_neon_shl_u16,
2634
        gen_op_neon_shl_u32,
2635
        gen_op_neon_shl_u64,
2636
      }
2637
    }, { /* 6 */ /* VQSHL */
2638
      {
2639
        gen_op_neon_qshl_u8,
2640
        gen_op_neon_qshl_u16,
2641
        gen_op_neon_qshl_u32,
2642
        gen_op_neon_qshl_u64
2643
      }, {
2644
        gen_op_neon_qshl_s8,
2645
        gen_op_neon_qshl_s16,
2646
        gen_op_neon_qshl_s32,
2647
        gen_op_neon_qshl_s64
2648
      }
2649
    }, { /* 7 */ /* VQSHLU */
2650
      {
2651
        gen_op_neon_qshl_u8,
2652
        gen_op_neon_qshl_u16,
2653
        gen_op_neon_qshl_u32,
2654
        gen_op_neon_qshl_u64
2655
      }, {
2656
        gen_op_neon_qshl_u8,
2657
        gen_op_neon_qshl_u16,
2658
        gen_op_neon_qshl_u32,
2659
        gen_op_neon_qshl_u64
2660
      }
2255 2661
    }
2256
    if (cond != 0xe) {
2257
        /* if not always execute, we generate a conditional jump to
2258
           next instruction */
2259
        s->condlabel = gen_new_label();
2260
        gen_test_cc[cond ^ 1](s->condlabel);
2261
        s->condjmp = 1;
2262
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
2263
        //s->is_jmp = DISAS_JUMP_NEXT;
2662
};
2663

  
2664
/* [R][U][size - 1] */
2665
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
2666
    {
2667
      {
2668
        gen_op_neon_shl_u16,
2669
        gen_op_neon_shl_u32,
2670
        gen_op_neon_shl_u64
2671
      }, {
2672
        gen_op_neon_shl_s16,
2673
        gen_op_neon_shl_s32,
2674
        gen_op_neon_shl_s64
2675
      }
2676
    }, {
2677
      {
2678
        gen_op_neon_rshl_u16,
2679
        gen_op_neon_rshl_u32,
2680
        gen_op_neon_rshl_u64
2681
      }, {
2682
        gen_op_neon_rshl_s16,
2683
        gen_op_neon_rshl_s32,
2684
        gen_op_neon_rshl_s64
2685
      }
2264 2686
    }
2265
    if ((insn & 0x0f900000) == 0x03000000) {
2266
        if ((insn & 0x0fb0f000) != 0x0320f000)
2267
            goto illegal_op;
2268
        /* CPSR = immediate */
2269
        val = insn & 0xff;
2270
        shift = ((insn >> 8) & 0xf) * 2;
2271
        if (shift)
2272
            val = (val >> shift) | (val << (32 - shift));
2273
        gen_op_movl_T0_im(val);
2274
        i = ((insn & (1 << 22)) != 0);
2275
        if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
2276
            goto illegal_op;
2277
    } else if ((insn & 0x0f900000) == 0x01000000
2278
               && (insn & 0x00000090) != 0x00000090) {
2279
        /* miscellaneous instructions */
2280
        op1 = (insn >> 21) & 3;
2281
        sh = (insn >> 4) & 0xf;
2282
        rm = insn & 0xf;
2283
        switch (sh) {
2284
        case 0x0: /* move program status register */
2285
            if (op1 & 1) {
2286
                /* PSR = reg */
2287
                gen_movl_T0_reg(s, rm);
2288
                i = ((op1 & 2) != 0);
2289
                if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
2290
                    goto illegal_op;
2291
            } else {
2292
                /* reg = PSR */
2293
                rd = (insn >> 12) & 0xf;
2294
                if (op1 & 2) {
2295
                    if (IS_USER(s))
2296
                        goto illegal_op;
2297
                    gen_op_movl_T0_spsr();
2298
                } else {
2299
                    gen_op_movl_T0_cpsr();
2300
                }
2301
                gen_movl_reg_T0(s, rd);
2302
            }
2303
            break;
2304
        case 0x1:
2305
            if (op1 == 1) {
2306
                /* branch/exchange thumb (bx).  */
2307
                gen_movl_T0_reg(s, rm);
2308
                gen_bx(s);
2309
            } else if (op1 == 3) {
2310
                /* clz */
2311
                rd = (insn >> 12) & 0xf;
2312
                gen_movl_T0_reg(s, rm);
2313
                gen_op_clz_T0();
2314
                gen_movl_reg_T0(s, rd);
2315
            } else {
2316
                goto illegal_op;
2317
            }
2318
            break;
2319
        case 0x2:
2320
            if (op1 == 1) {
2321
                ARCH(5J); /* bxj */
2322
                /* Trivial implementation equivalent to bx.  */
2323
                gen_movl_T0_reg(s, rm);
2324
                gen_bx(s);
2325
            } else {
2326
                goto illegal_op;
2327
            }
2328
            break;
2329
        case 0x3:
2330
            if (op1 != 1)
2331
              goto illegal_op;
2687
};
2332 2688

  
2333
            /* branch link/exchange thumb (blx) */
2334
            val = (uint32_t)s->pc;
2335
            gen_op_movl_T1_im(val);
2336
            gen_movl_T0_reg(s, rm);
2337
            gen_movl_reg_T1(s, 14);
2338
            gen_bx(s);
2339
            break;
2340
        case 0x5: /* saturating add/subtract */
2341
            rd = (insn >> 12) & 0xf;
2342
            rn = (insn >> 16) & 0xf;
2343
            gen_movl_T0_reg(s, rm);
2689
static inline void
2690
gen_op_neon_narrow_u32 ()
2691
{
2692
    /* No-op.  */
2693
}
2694

  
2695
static GenOpFunc *gen_neon_narrow[3] = {
2696
    gen_op_neon_narrow_u8,
2697
    gen_op_neon_narrow_u16,
2698
    gen_op_neon_narrow_u32
2699
};
2700

  
2701
static GenOpFunc *gen_neon_narrow_satu[3] = {
2702
    gen_op_neon_narrow_sat_u8,
2703
    gen_op_neon_narrow_sat_u16,
2704
    gen_op_neon_narrow_sat_u32
2705
};
2706

  
2707
static GenOpFunc *gen_neon_narrow_sats[3] = {
2708
    gen_op_neon_narrow_sat_s8,
2709
    gen_op_neon_narrow_sat_s16,
2710
    gen_op_neon_narrow_sat_s32
2711
};
2712

  
2713
static inline int gen_neon_add(int size)
2714
{
2715
    switch (size) {
2716
    case 0: gen_op_neon_add_u8(); break;
2717
    case 1: gen_op_neon_add_u16(); break;
2718
    case 2: gen_op_addl_T0_T1(); break;
2719
    default: return 1;
2720
    }
2721
    return 0;
2722
}
2723

  
2724
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
2725
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
2726
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
2727
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
2728
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
2729

  
2730
#define GEN_NEON_INTEGER_OP(name) do { \
2731
    switch ((size << 1) | u) { \
2732
    case 0: gen_op_neon_##name##_s8(); break; \
2733
    case 1: gen_op_neon_##name##_u8(); break; \
2734
    case 2: gen_op_neon_##name##_s16(); break; \
2735
    case 3: gen_op_neon_##name##_u16(); break; \
2736
    case 4: gen_op_neon_##name##_s32(); break; \
2737
    case 5: gen_op_neon_##name##_u32(); break; \
2738
    default: return 1; \
2739
    }} while (0)
2740

  
2741
static inline void
2742
gen_neon_movl_scratch_T0(int scratch)
2743
{
2744
  uint32_t offset;
2745

  
2746
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2747
  gen_op_neon_setreg_T0(offset);
2748
}
2749

  
2750
static inline void
2751
gen_neon_movl_scratch_T1(int scratch)
2752
{
2753
  uint32_t offset;
2754

  
2755
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2756
  gen_op_neon_setreg_T1(offset);
2757
}
2758

  
2759
static inline void
2760
gen_neon_movl_T0_scratch(int scratch)
2761
{
2762
  uint32_t offset;
2763

  
2764
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2765
  gen_op_neon_getreg_T0(offset);
2766
}
2767

  
2768
static inline void
2769
gen_neon_movl_T1_scratch(int scratch)
2770
{
2771
  uint32_t offset;
2772

  
2773
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2774
  gen_op_neon_getreg_T1(offset);
2775
}
2776

  
2777
static inline void gen_op_neon_widen_u32(void)
2778
{
2779
    gen_op_movl_T1_im(0);
2780
}
2781

  
2782
static inline void gen_neon_get_scalar(int size, int reg)
2783
{
2784
    if (size == 1) {
2785
        NEON_GET_REG(T0, reg >> 1, reg & 1);
2786
    } else {
2787
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
2788
        if (reg & 1)
2789
            gen_op_neon_dup_low16();
2790
        else
2791
            gen_op_neon_dup_high16();
2792
    }
2793
}
2794

  
2795
static void gen_neon_unzip(int reg, int q, int tmp, int size)
2796
{
2797
    int n;
2798

  
2799
    for (n = 0; n < q + 1; n += 2) {
2800
        NEON_GET_REG(T0, reg, n);
2801
        NEON_GET_REG(T0, reg, n + n);
2802
        switch (size) {
2803
        case 0: gen_op_neon_unzip_u8(); break;
2804
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
2805
        case 2: /* no-op */; break;
2806
        default: abort();
2807
        }
2808
        gen_neon_movl_scratch_T0(tmp + n);
2809
        gen_neon_movl_scratch_T1(tmp + n + 1);
2810
    }
2811
}
2812

  
2813
static struct {
2814
    int nregs;
2815
    int interleave;
2816
    int spacing;
2817
} neon_ls_element_type[11] = {
2818
    {4, 4, 1},
2819
    {4, 4, 2},
2820
    {4, 1, 1},
2821
    {4, 2, 1},
2822
    {3, 3, 1},
2823
    {3, 3, 2},
2824
    {3, 1, 1},
2825
    {1, 1, 1},
2826
    {2, 2, 1},
2827
    {2, 2, 2},
2828
    {2, 1, 1}
2829
};
2830

  
2831
/* Translate a NEON load/store element instruction.  Return nonzero if the
2832
   instruction is invalid.  */
2833
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
2834
{
2835
    int rd, rn, rm;
2836
    int op;
2837
    int nregs;
2838
    int interleave;
2839
    int stride;
2840
    int size;
2841
    int reg;
2842
    int pass;
2843
    int load;
2844
    int shift;
2845
    uint32_t mask;
2846
    int n;
2847

  
2848
    if (!vfp_enabled(env))
2849
      return 1;
2850
    VFP_DREG_D(rd, insn);
2851
    rn = (insn >> 16) & 0xf;
2852
    rm = insn & 0xf;
2853
    load = (insn & (1 << 21)) != 0;
2854
    if ((insn & (1 << 23)) == 0) {
2855
        /* Load store all elements.  */
2856
        op = (insn >> 8) & 0xf;
2857
        size = (insn >> 6) & 3;
2858
        if (op > 10 || size == 3)
2859
            return 1;
2860
        nregs = neon_ls_element_type[op].nregs;
2861
        interleave = neon_ls_element_type[op].interleave;
2862
        gen_movl_T1_reg(s, rn);
2863
        stride = (1 << size) * interleave;
2864
        for (reg = 0; reg < nregs; reg++) {
2865
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
2866
                gen_movl_T1_reg(s, rn);
2867
                gen_op_addl_T1_im((1 << size) * reg);
2868
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
2869
                gen_movl_T1_reg(s, rn);
2870
                gen_op_addl_T1_im(1 << size);
2871
            }
2872
            for (pass = 0; pass < 2; pass++) {
2873
                if (size == 2) {
2874
                    if (load) {
2875
                        gen_ldst(ldl, s);
2876
                        NEON_SET_REG(T0, rd, pass);
2877
                    } else {
2878
                        NEON_GET_REG(T0, rd, pass);
2879
                        gen_ldst(stl, s);
2880
                    }
2881
                    gen_op_addl_T1_im(stride);
2882
                } else if (size == 1) {
2883
                    if (load) {
2884
                        gen_ldst(lduw, s);
2885
                        gen_op_addl_T1_im(stride);
2886
                        gen_op_movl_T2_T0();
2887
                        gen_ldst(lduw, s);
2888
                        gen_op_addl_T1_im(stride);
2889
                        gen_op_neon_insert_elt(16, 0xffff);
2890
                        NEON_SET_REG(T2, rd, pass);
2891
                    } else {
2892
                        NEON_GET_REG(T2, rd, pass);
2893
                        gen_op_movl_T0_T2();
2894
                        gen_ldst(stw, s);
2895
                        gen_op_addl_T1_im(stride);
2896
                        gen_op_neon_extract_elt(16, 0xffff0000);
2897
                        gen_ldst(stw, s);
2898
                        gen_op_addl_T1_im(stride);
2899
                    }
2900
                } else /* size == 0 */ {
2901
                    if (load) {
2902
                        mask = 0xff;
2903
                        for (n = 0; n < 4; n++) {
2904
                            gen_ldst(ldub, s);
2905
                            gen_op_addl_T1_im(stride);
2906
                            if (n == 0) {
2907
                                gen_op_movl_T2_T0();
2908
                            } else {
2909
                                gen_op_neon_insert_elt(n * 8, ~mask);
2910
                            }
2911
                            mask <<= 8;
2912
                        }
2913
                        NEON_SET_REG(T2, rd, pass);
2914
                    } else {
2915
                        NEON_GET_REG(T2, rd, pass);
2916
                        mask = 0xff;
2917
                        for (n = 0; n < 4; n++) {
2918
                            if (n == 0) {
2919
                                gen_op_movl_T0_T2();
2920
                            } else {
2921
                                gen_op_neon_extract_elt(n * 8, mask);
2922
                            }
2923
                            gen_ldst(stb, s);
2924
                            gen_op_addl_T1_im(stride);
2925
                            mask <<= 8;
2926
                        }
2927
                    }
2928
                }
2929
            }
2930
            rd += neon_ls_element_type[op].spacing;
2931
        }
2932
        stride = nregs * 8;
2933
    } else {
2934
        size = (insn >> 10) & 3;
2935
        if (size == 3) {
2936
            /* Load single element to all lanes.  */
2937
            if (!load)
2938
                return 1;
2939
            size = (insn >> 6) & 3;
2940
            nregs = ((insn >> 8) & 3) + 1;
2941
            stride = (insn & (1 << 5)) ? 2 : 1;
2344 2942
            gen_movl_T1_reg(s, rn);
2345
            if (op1 & 2)
2346
                gen_op_double_T1_saturate();
2347
            if (op1 & 1)
2348
                gen_op_subl_T0_T1_saturate();
2349
            else
2350
                gen_op_addl_T0_T1_saturate();
2351
            gen_movl_reg_T0(s, rd);
2352
            break;
2353
        case 7: /* bkpt */
2354
            gen_op_movl_T0_im((long)s->pc - 4);
2355
            gen_op_movl_reg_TN[0][15]();
2356
            gen_op_bkpt();
2357
            s->is_jmp = DISAS_JUMP;
2358
            break;
2359
        case 0x8: /* signed multiply */
2360
        case 0xa:
2361
        case 0xc:
2362
        case 0xe:
2363
            rs = (insn >> 8) & 0xf;
2364
            rn = (insn >> 12) & 0xf;
2365
            rd = (insn >> 16) & 0xf;
2366
            if (op1 == 1) {
2367
                /* (32 * 16) >> 16 */
2368
                gen_movl_T0_reg(s, rm);
2369
                gen_movl_T1_reg(s, rs);
2370
                if (sh & 4)
2371
                    gen_op_sarl_T1_im(16);
2372
                else
2373
                    gen_op_sxth_T1();
2374
                gen_op_imulw_T0_T1();
2375
                if ((sh & 2) == 0) {
2376
                    gen_movl_T1_reg(s, rn);
2377
                    gen_op_addl_T0_T1_setq();
2943
            for (reg = 0; reg < nregs; reg++) {
2944
                switch (size) {
2945
                case 0:
2946
                    gen_ldst(ldub, s);
2947
                    gen_op_neon_dup_u8(0);
2948
                    break;
2949
                case 1:
2950
                    gen_ldst(lduw, s);
2951
                    gen_op_neon_dup_low16();
2952
                    break;
2953
                case 2:
2954
                    gen_ldst(ldl, s);
2955
                    break;
2956
                case 3:
2957
                    return 1;
2378 2958
                }
2379
                gen_movl_reg_T0(s, rd);
2380
            } else {
2381
                /* 16 * 16 */
2382
                gen_movl_T0_reg(s, rm);
2383
                gen_movl_T1_reg(s, rs);
2384
                gen_mulxy(sh & 2, sh & 4);
2385
                if (op1 == 2) {
2386
                    gen_op_signbit_T1_T0();
2387
                    gen_op_addq_T0_T1(rn, rd);
2388
                    gen_movl_reg_T0(s, rn);
2389
                    gen_movl_reg_T1(s, rd);
2390
                } else {
2391
                    if (op1 == 0) {
2392
                        gen_movl_T1_reg(s, rn);
2393
                        gen_op_addl_T0_T1_setq();
2959
                gen_op_addl_T1_im(1 << size);
2960
                NEON_SET_REG(T0, rd, 0);
2961
                NEON_SET_REG(T0, rd, 1);
2962
                rd += stride;
2963
            }
2964
            stride = (1 << size) * nregs;
2965
        } else {
2966
            /* Single element.  */
2967
            pass = (insn >> 7) & 1;
2968
            switch (size) {
2969
            case 0:
2970
                shift = ((insn >> 5) & 3) * 8;
2971
                mask = 0xff << shift;
2972
                stride = 1;
2973
                break;
2974
            case 1:
2975
                shift = ((insn >> 6) & 1) * 16;
2976
                mask = shift ? 0xffff0000 : 0xffff;
2977
                stride = (insn & (1 << 5)) ? 2 : 1;
2978
                break;
2979
            case 2:
2980
                shift = 0;
2981
                mask = 0xffffffff;
2982
                stride = (insn & (1 << 6)) ? 2 : 1;
2983
                break;
2984
            default:
2985
                abort();
2986
            }
2987
            nregs = ((insn >> 8) & 3) + 1;
2988
            gen_movl_T1_reg(s, rn);
2989
            for (reg = 0; reg < nregs; reg++) {
2990
                if (load) {
2991
                    if (size != 2) {
2992
                        NEON_GET_REG(T2, rd, pass);
2993
                    }
2994
                    switch (size) {
2995
                    case 0:
2996
                        gen_ldst(ldub, s);
2997
                        break;
2998
                    case 1:
2999
                        gen_ldst(lduw, s);
3000
                        break;
3001
                    case 2:
3002
                        gen_ldst(ldl, s);
3003
                        NEON_SET_REG(T0, rd, pass);
3004
                        break;
3005
                    }
3006
                    if (size != 2) {
3007
                        gen_op_neon_insert_elt(shift, ~mask);
3008
                        NEON_SET_REG(T0, rd, pass);
3009
                    }
3010
                } else { /* Store */
3011
                    if (size == 2) {
3012
                        NEON_GET_REG(T0, rd, pass);
3013
                    } else {
3014
                        NEON_GET_REG(T2, rd, pass);
3015
                        gen_op_neon_extract_elt(shift, mask);
3016
                    }
3017
                    switch (size) {
3018
                    case 0:
3019
                        gen_ldst(stb, s);
3020
                        break;
3021
                    case 1:
3022
                        gen_ldst(stw, s);
3023
                        break;
3024
                    case 2:
3025
                        gen_ldst(stl, s);
3026
                        break;
2394 3027
                    }
2395
                    gen_movl_reg_T0(s, rd);
2396 3028
                }
3029
                rd += stride;
3030
                gen_op_addl_T1_im(1 << size);
2397 3031
            }
2398
            break;
2399
        default:
2400
            goto illegal_op;
3032
            stride = nregs * (1 << size);
2401 3033
        }
2402
    } else if (((insn & 0x0e000000) == 0 &&
2403
                (insn & 0x00000090) != 0x90) ||
2404
               ((insn & 0x0e000000) == (1 << 25))) {
2405
        int set_cc, logic_cc, shiftop;
3034
    }
3035
    if (rm != 15) {
3036
        gen_movl_T1_reg(s, rn);
3037
        if (rm == 13) {
3038
            gen_op_addl_T1_im(stride);
3039
        } else {
3040
            gen_movl_T2_reg(s, rm);
3041
            gen_op_addl_T1_T2();
3042
        }
3043
        gen_movl_reg_T1(s, rn);
3044
    }
3045
    return 0;
3046
}
2406 3047

  
2407
        op1 = (insn >> 21) & 0xf;
2408
        set_cc = (insn >> 20) & 1;
2409
        logic_cc = table_logic_cc[op1] & set_cc;
3048
/* Translate a NEON data processing instruction.  Return nonzero if the
3049
   instruction is invalid.
3050
   In general we process vectors in 32-bit chunks.  This means we can reuse
3051
   some of the scalar ops, and hopefully the code generated for 32-bit
3052
   hosts won't be too awful.  The downside is that the few 64-bit operations
3053
   (mainly shifts) get complicated.  */
2410 3054

  
2411
        /* data processing instruction */
2412
        if (insn & (1 << 25)) {
2413
            /* immediate operand */
2414
            val = insn & 0xff;
2415
            shift = ((insn >> 8) & 0xf) * 2;
2416
            if (shift)
2417
                val = (val >> shift) | (val << (32 - shift));
2418
            gen_op_movl_T1_im(val);
2419
            if (logic_cc && shift)
2420
                gen_op_mov_CF_T1();
2421
        } else {
2422
            /* register */
2423
            rm = (insn) & 0xf;
2424
            gen_movl_T1_reg(s, rm);
2425
            shiftop = (insn >> 5) & 3;
2426
            if (!(insn & (1 << 4))) {
2427
                shift = (insn >> 7) & 0x1f;
2428
                if (shift != 0) {
2429
                    if (logic_cc) {
2430
                        gen_shift_T1_im_cc[shiftop](shift);
3055
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3056
{
3057
    int op;
3058
    int q;
3059
    int rd, rn, rm;
3060
    int size;
3061
    int shift;
3062
    int pass;
3063
    int count;
3064
    int pairwise;
3065
    int u;
3066
    int n;
3067
    uint32_t imm;
3068

  
3069
    if (!vfp_enabled(env))
3070
      return 1;
3071
    q = (insn & (1 << 6)) != 0;
3072
    u = (insn >> 24) & 1;
3073
    VFP_DREG_D(rd, insn);
3074
    VFP_DREG_N(rn, insn);
3075
    VFP_DREG_M(rm, insn);
3076
    size = (insn >> 20) & 3;
3077
    if ((insn & (1 << 23)) == 0) {
3078
        /* Three register same length.  */
3079
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3080
        if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3081
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
3082
                NEON_GET_REG(T0, rm, pass * 2);
3083
                NEON_GET_REG(T1, rm, pass * 2 + 1);
3084
                gen_neon_movl_scratch_T0(0);
3085
                gen_neon_movl_scratch_T1(1);
3086
                NEON_GET_REG(T0, rn, pass * 2);
3087
                NEON_GET_REG(T1, rn, pass * 2 + 1);
3088
                switch (op) {
3089
                case 1: /* VQADD */
3090
                    if (u) {
3091
                        gen_op_neon_addl_saturate_u64();
2431 3092
                    } else {
2432
                        gen_shift_T1_im[shiftop](shift);
3093
                        gen_op_neon_addl_saturate_s64();
2433 3094
                    }
2434
                } else if (shiftop != 0) {
2435
                    if (logic_cc) {
2436
                        gen_shift_T1_0_cc[shiftop]();
3095
                    break;
3096
                case 5: /* VQSUB */
3097
                    if (u) {
3098
                        gen_op_neon_subl_saturate_u64();
2437 3099
                    } else {
2438
                        gen_shift_T1_0[shiftop]();
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff