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