Commit 5899f386ba9474d0bb0c055f9276d8923845cbd3

Authored by bellard
1 parent 6a0f9e82

ARM thumb fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1418 c046a42c-6fe2-441c-8c8c-71466251a162
target-arm/op.c
... ... @@ -824,12 +824,13 @@ void OPPROTO op_shrl_T0_im_thumb(void)
824 824  
825 825 shift = PARAM1;
826 826 if (shift == 0) {
827   - env->CF = 0;
  827 + env->CF = ((uint32_t)shift) >> 31;
828 828 T0 = 0;
829 829 } else {
830 830 env->CF = (T0 >> (shift - 1)) & 1;
831 831 T0 = T0 >> shift;
832 832 }
  833 + env->NZF = T0;
833 834 FORCE_RET();
834 835 }
835 836  
... ...
target-arm/translate.c
... ... @@ -38,6 +38,7 @@ typedef struct DisasContext {
38 38 int condlabel;
39 39 struct TranslationBlock *tb;
40 40 int singlestep_enabled;
  41 + int thumb;
41 42 } DisasContext;
42 43  
43 44 #define DISAS_JUMP_NEXT 4
... ... @@ -268,8 +269,11 @@ static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
268 269 int val;
269 270  
270 271 if (reg == 15) {
271   - /* normaly, since we updated PC, we need only to add 4 */
272   - val = (long)s->pc + 4;
  272 + /* normaly, since we updated PC, we need only to add one insn */
  273 + if (s->thumb)
  274 + val = (long)s->pc + 2;
  275 + else
  276 + val = (long)s->pc + 4;
273 277 gen_op_movl_TN_im[t](val);
274 278 } else {
275 279 gen_op_movl_TN_reg[t][reg]();
... ... @@ -897,6 +901,8 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest)
897 901 {
898 902 if (__builtin_expect(s->singlestep_enabled, 0)) {
899 903 /* An indirect jump so that we still trigger the debug exception. */
  904 + if (s->thumb)
  905 + dest |= 1;
900 906 gen_op_movl_T0_im(dest);
901 907 gen_bx(s);
902 908 } else {
... ... @@ -1552,7 +1558,7 @@ static void disas_thumb_insn(DisasContext *s)
1552 1558 gen_movl_T1_reg(s, rm);
1553 1559 }
1554 1560 if (insn & (1 << 9))
1555   - gen_op_addl_T0_T1_cc();
  1561 + gen_op_subl_T0_T1_cc();
1556 1562 else
1557 1563 gen_op_addl_T0_T1_cc();
1558 1564 gen_movl_reg_T0(s, rd);
... ... @@ -1595,11 +1601,10 @@ static void disas_thumb_insn(DisasContext *s)
1595 1601 case 4:
1596 1602 if (insn & (1 << 11)) {
1597 1603 rd = (insn >> 8) & 7;
1598   - /* load pc-relative */
1599   - val = (insn & 0xff) * 4;
  1604 + /* load pc-relative. Bit 1 of PC is ignored. */
  1605 + val = s->pc + 2 + ((insn & 0xff) * 4);
  1606 + val &= ~(uint32_t)2;
1600 1607 gen_op_movl_T1_im(val);
1601   - gen_movl_T2_reg(s, 15);
1602   - gen_op_addl_T1_T2();
1603 1608 gen_op_ldl_T0_T1();
1604 1609 gen_movl_reg_T0(s, rd);
1605 1610 break;
... ... @@ -1658,7 +1663,7 @@ static void disas_thumb_insn(DisasContext *s)
1658 1663 gen_movl_T0_reg(s, rd);
1659 1664  
1660 1665 gen_movl_T1_reg(s, rm);
1661   - switch (insn >> 6) {
  1666 + switch (op) {
1662 1667 case 0x0: /* and */
1663 1668 gen_op_andl_T0_T1();
1664 1669 gen_op_logic_T0_cc();
... ... @@ -1689,8 +1694,9 @@ static void disas_thumb_insn(DisasContext *s)
1689 1694 gen_op_andl_T0_T1();
1690 1695 gen_op_logic_T0_cc();
1691 1696 rd = 16;
  1697 + break;
1692 1698 case 0x9: /* neg */
1693   - gen_op_rsbl_T0_T1_cc();
  1699 + gen_op_subl_T0_T1_cc();
1694 1700 break;
1695 1701 case 0xa: /* cmp */
1696 1702 gen_op_subl_T0_T1_cc();
... ... @@ -1716,11 +1722,12 @@ static void disas_thumb_insn(DisasContext *s)
1716 1722 gen_op_notl_T1();
1717 1723 gen_op_logic_T1_cc();
1718 1724 val = 1;
  1725 + rm = rd;
1719 1726 break;
1720 1727 }
1721 1728 if (rd != 16) {
1722 1729 if (val)
1723   - gen_movl_reg_T1(s, rd);
  1730 + gen_movl_reg_T1(s, rm);
1724 1731 else
1725 1732 gen_movl_reg_T0(s, rd);
1726 1733 }
... ... @@ -1756,7 +1763,7 @@ static void disas_thumb_insn(DisasContext *s)
1756 1763 gen_op_ldl_T0_T1();
1757 1764 break;
1758 1765 case 5: /* ldrh */
1759   - gen_op_ldsw_T0_T1();
  1766 + gen_op_lduw_T0_T1();
1760 1767 break;
1761 1768 case 6: /* ldrb */
1762 1769 gen_op_ldub_T0_T1();
... ... @@ -1851,11 +1858,13 @@ static void disas_thumb_insn(DisasContext *s)
1851 1858 case 10:
1852 1859 /* add to high reg */
1853 1860 rd = (insn >> 8) & 7;
1854   - if (insn & (1 << 11))
1855   - rm = 13; /* sp */
1856   - else
1857   - rm = 15; /* pc */
1858   - gen_movl_T0_reg(s, rm);
  1861 + if (insn & (1 << 11)) {
  1862 + /* SP */
  1863 + gen_movl_T0_reg(s, 13);
  1864 + } else {
  1865 + /* PC. bit 1 is ignored. */
  1866 + gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
  1867 + }
1859 1868 val = (insn & 0xff) * 4;
1860 1869 gen_op_movl_T1_im(val);
1861 1870 gen_op_addl_T0_T1();
... ... @@ -1880,11 +1889,19 @@ static void disas_thumb_insn(DisasContext *s)
1880 1889 case 4: case 5: case 0xc: case 0xd:
1881 1890 /* push/pop */
1882 1891 gen_movl_T1_reg(s, 13);
1883   - if (insn & (1 << 11))
1884   - val = 4;
  1892 + if (insn & (1 << 8))
  1893 + offset = 4;
1885 1894 else
1886   - val = -4;
1887   - gen_op_movl_T2_im(val);
  1895 + offset = 0;
  1896 + for (i = 0; i < 8; i++) {
  1897 + if (insn & (1 << i))
  1898 + offset += 4;
  1899 + }
  1900 + if ((insn & (1 << 11)) == 0) {
  1901 + gen_op_movl_T2_im(-offset);
  1902 + gen_op_addl_T1_T2();
  1903 + }
  1904 + gen_op_movl_T2_im(4);
1888 1905 for (i = 0; i < 8; i++) {
1889 1906 if (insn & (1 << i)) {
1890 1907 if (insn & (1 << 11)) {
... ... @@ -1896,7 +1913,7 @@ static void disas_thumb_insn(DisasContext *s)
1896 1913 gen_movl_T0_reg(s, i);
1897 1914 gen_op_stl_T0_T1();
1898 1915 }
1899   - /* move to the next address */
  1916 + /* advance to the next address. */
1900 1917 gen_op_addl_T1_T2();
1901 1918 }
1902 1919 }
... ... @@ -1913,7 +1930,10 @@ static void disas_thumb_insn(DisasContext *s)
1913 1930 }
1914 1931 gen_op_addl_T1_T2();
1915 1932 }
1916   -
  1933 + if ((insn & (1 << 11)) == 0) {
  1934 + gen_op_movl_T2_im(-offset);
  1935 + gen_op_addl_T1_T2();
  1936 + }
1917 1937 /* write back the new stack pointer */
1918 1938 gen_movl_reg_T1(s, 13);
1919 1939 /* set the new PC value */
... ... @@ -1931,14 +1951,8 @@ static void disas_thumb_insn(DisasContext *s)
1931 1951 rn = (insn >> 8) & 0x7;
1932 1952 gen_movl_T1_reg(s, rn);
1933 1953 gen_op_movl_T2_im(4);
1934   - val = 0;
1935 1954 for (i = 0; i < 8; i++) {
1936 1955 if (insn & (1 << i)) {
1937   - /* advance to the next address */
1938   - if (val)
1939   - gen_op_addl_T1_T2();
1940   - else
1941   - val = 1;
1942 1956 if (insn & (1 << 11)) {
1943 1957 /* load */
1944 1958 gen_op_ldl_T0_T1();
... ... @@ -1948,8 +1962,12 @@ static void disas_thumb_insn(DisasContext *s)
1948 1962 gen_movl_T0_reg(s, i);
1949 1963 gen_op_stl_T0_T1();
1950 1964 }
  1965 + /* advance to the next address */
  1966 + gen_op_addl_T1_T2();
1951 1967 }
1952 1968 }
  1969 + /* Base register writeback. */
  1970 + gen_movl_reg_T1(s, rn);
1953 1971 break;
1954 1972  
1955 1973 case 13:
... ... @@ -1976,9 +1994,9 @@ static void disas_thumb_insn(DisasContext *s)
1976 1994 gen_movl_T1_reg(s, 15);
1977 1995  
1978 1996 /* jump to the offset */
1979   - val = (uint32_t)s->pc;
  1997 + val = (uint32_t)s->pc + 2;
1980 1998 offset = ((int32_t)insn << 24) >> 24;
1981   - val += (offset << 1) + 2;
  1999 + val += offset << 1;
1982 2000 gen_jmp(s, val);
1983 2001 break;
1984 2002  
... ... @@ -2002,19 +2020,20 @@ static void disas_thumb_insn(DisasContext *s)
2002 2020 gen_op_movl_T1_im(val | 1);
2003 2021 gen_movl_reg_T1(s, 14);
2004 2022  
2005   - val += offset;
  2023 + val += offset << 1;
2006 2024 if (insn & (1 << 11)) {
2007 2025 /* bl */
2008 2026 gen_jmp(s, val);
2009 2027 } else {
2010 2028 /* blx */
  2029 + val &= ~(uint32_t)2;
2011 2030 gen_op_movl_T0_im(val);
2012 2031 gen_bx(s);
2013 2032 }
2014 2033 }
2015 2034 return;
2016 2035 undef:
2017   - gen_op_movl_T0_im((long)s->pc - 4);
  2036 + gen_op_movl_T0_im((long)s->pc - 2);
2018 2037 gen_op_movl_reg_TN[0][15]();
2019 2038 gen_op_undef_insn();
2020 2039 s->is_jmp = DISAS_JUMP;
... ... @@ -2045,6 +2064,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2045 2064 dc->pc = pc_start;
2046 2065 dc->singlestep_enabled = env->singlestep_enabled;
2047 2066 dc->condjmp = 0;
  2067 + dc->thumb = env->thumb;
2048 2068 nb_gen_labels = 0;
2049 2069 lj = -1;
2050 2070 do {
... ... @@ -2128,7 +2148,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2128 2148 if (loglevel & CPU_LOG_TB_IN_ASM) {
2129 2149 fprintf(logfile, "----------------\n");
2130 2150 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2131   - target_disas(logfile, pc_start, dc->pc - pc_start, 0);
  2151 + target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
2132 2152 fprintf(logfile, "\n");
2133 2153 if (loglevel & (CPU_LOG_TB_OP)) {
2134 2154 fprintf(logfile, "OP:\n");
... ...