38 |
int condlabel; |
int condlabel; |
39 |
struct TranslationBlock *tb; |
struct TranslationBlock *tb; |
40 |
int singlestep_enabled; |
int singlestep_enabled; |
41 |
|
int thumb; |
42 |
} DisasContext; |
} DisasContext; |
43 |
|
|
44 |
#define DISAS_JUMP_NEXT 4 |
#define DISAS_JUMP_NEXT 4 |
269 |
int val; |
int val; |
270 |
|
|
271 |
if (reg == 15) { |
if (reg == 15) { |
272 |
/* normaly, since we updated PC, we need only to add 4 */ |
/* normaly, since we updated PC, we need only to add one insn */ |
273 |
val = (long)s->pc + 4; |
if (s->thumb) |
274 |
|
val = (long)s->pc + 2; |
275 |
|
else |
276 |
|
val = (long)s->pc + 4; |
277 |
gen_op_movl_TN_im[t](val); |
gen_op_movl_TN_im[t](val); |
278 |
} else { |
} else { |
279 |
gen_op_movl_TN_reg[t][reg](); |
gen_op_movl_TN_reg[t][reg](); |
901 |
{ |
{ |
902 |
if (__builtin_expect(s->singlestep_enabled, 0)) { |
if (__builtin_expect(s->singlestep_enabled, 0)) { |
903 |
/* An indirect jump so that we still trigger the debug exception. */ |
/* An indirect jump so that we still trigger the debug exception. */ |
904 |
|
if (s->thumb) |
905 |
|
dest |= 1; |
906 |
gen_op_movl_T0_im(dest); |
gen_op_movl_T0_im(dest); |
907 |
gen_bx(s); |
gen_bx(s); |
908 |
} else { |
} else { |
1558 |
gen_movl_T1_reg(s, rm); |
gen_movl_T1_reg(s, rm); |
1559 |
} |
} |
1560 |
if (insn & (1 << 9)) |
if (insn & (1 << 9)) |
1561 |
gen_op_addl_T0_T1_cc(); |
gen_op_subl_T0_T1_cc(); |
1562 |
else |
else |
1563 |
gen_op_addl_T0_T1_cc(); |
gen_op_addl_T0_T1_cc(); |
1564 |
gen_movl_reg_T0(s, rd); |
gen_movl_reg_T0(s, rd); |
1601 |
case 4: |
case 4: |
1602 |
if (insn & (1 << 11)) { |
if (insn & (1 << 11)) { |
1603 |
rd = (insn >> 8) & 7; |
rd = (insn >> 8) & 7; |
1604 |
/* load pc-relative */ |
/* load pc-relative. Bit 1 of PC is ignored. */ |
1605 |
val = (insn & 0xff) * 4; |
val = s->pc + 2 + ((insn & 0xff) * 4); |
1606 |
|
val &= ~(uint32_t)2; |
1607 |
gen_op_movl_T1_im(val); |
gen_op_movl_T1_im(val); |
|
gen_movl_T2_reg(s, 15); |
|
|
gen_op_addl_T1_T2(); |
|
1608 |
gen_op_ldl_T0_T1(); |
gen_op_ldl_T0_T1(); |
1609 |
gen_movl_reg_T0(s, rd); |
gen_movl_reg_T0(s, rd); |
1610 |
break; |
break; |
1663 |
gen_movl_T0_reg(s, rd); |
gen_movl_T0_reg(s, rd); |
1664 |
|
|
1665 |
gen_movl_T1_reg(s, rm); |
gen_movl_T1_reg(s, rm); |
1666 |
switch (insn >> 6) { |
switch (op) { |
1667 |
case 0x0: /* and */ |
case 0x0: /* and */ |
1668 |
gen_op_andl_T0_T1(); |
gen_op_andl_T0_T1(); |
1669 |
gen_op_logic_T0_cc(); |
gen_op_logic_T0_cc(); |
1694 |
gen_op_andl_T0_T1(); |
gen_op_andl_T0_T1(); |
1695 |
gen_op_logic_T0_cc(); |
gen_op_logic_T0_cc(); |
1696 |
rd = 16; |
rd = 16; |
1697 |
|
break; |
1698 |
case 0x9: /* neg */ |
case 0x9: /* neg */ |
1699 |
gen_op_rsbl_T0_T1_cc(); |
gen_op_subl_T0_T1_cc(); |
1700 |
break; |
break; |
1701 |
case 0xa: /* cmp */ |
case 0xa: /* cmp */ |
1702 |
gen_op_subl_T0_T1_cc(); |
gen_op_subl_T0_T1_cc(); |
1722 |
gen_op_notl_T1(); |
gen_op_notl_T1(); |
1723 |
gen_op_logic_T1_cc(); |
gen_op_logic_T1_cc(); |
1724 |
val = 1; |
val = 1; |
1725 |
|
rm = rd; |
1726 |
break; |
break; |
1727 |
} |
} |
1728 |
if (rd != 16) { |
if (rd != 16) { |
1729 |
if (val) |
if (val) |
1730 |
gen_movl_reg_T1(s, rd); |
gen_movl_reg_T1(s, rm); |
1731 |
else |
else |
1732 |
gen_movl_reg_T0(s, rd); |
gen_movl_reg_T0(s, rd); |
1733 |
} |
} |
1763 |
gen_op_ldl_T0_T1(); |
gen_op_ldl_T0_T1(); |
1764 |
break; |
break; |
1765 |
case 5: /* ldrh */ |
case 5: /* ldrh */ |
1766 |
gen_op_ldsw_T0_T1(); |
gen_op_lduw_T0_T1(); |
1767 |
break; |
break; |
1768 |
case 6: /* ldrb */ |
case 6: /* ldrb */ |
1769 |
gen_op_ldub_T0_T1(); |
gen_op_ldub_T0_T1(); |
1858 |
case 10: |
case 10: |
1859 |
/* add to high reg */ |
/* add to high reg */ |
1860 |
rd = (insn >> 8) & 7; |
rd = (insn >> 8) & 7; |
1861 |
if (insn & (1 << 11)) |
if (insn & (1 << 11)) { |
1862 |
rm = 13; /* sp */ |
/* SP */ |
1863 |
else |
gen_movl_T0_reg(s, 13); |
1864 |
rm = 15; /* pc */ |
} else { |
1865 |
gen_movl_T0_reg(s, rm); |
/* PC. bit 1 is ignored. */ |
1866 |
|
gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2); |
1867 |
|
} |
1868 |
val = (insn & 0xff) * 4; |
val = (insn & 0xff) * 4; |
1869 |
gen_op_movl_T1_im(val); |
gen_op_movl_T1_im(val); |
1870 |
gen_op_addl_T0_T1(); |
gen_op_addl_T0_T1(); |
1889 |
case 4: case 5: case 0xc: case 0xd: |
case 4: case 5: case 0xc: case 0xd: |
1890 |
/* push/pop */ |
/* push/pop */ |
1891 |
gen_movl_T1_reg(s, 13); |
gen_movl_T1_reg(s, 13); |
1892 |
if (insn & (1 << 11)) |
if (insn & (1 << 8)) |
1893 |
val = 4; |
offset = 4; |
1894 |
else |
else |
1895 |
val = -4; |
offset = 0; |
1896 |
gen_op_movl_T2_im(val); |
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); |
1905 |
for (i = 0; i < 8; i++) { |
for (i = 0; i < 8; i++) { |
1906 |
if (insn & (1 << i)) { |
if (insn & (1 << i)) { |
1907 |
if (insn & (1 << 11)) { |
if (insn & (1 << 11)) { |
1913 |
gen_movl_T0_reg(s, i); |
gen_movl_T0_reg(s, i); |
1914 |
gen_op_stl_T0_T1(); |
gen_op_stl_T0_T1(); |
1915 |
} |
} |
1916 |
/* move to the next address */ |
/* advance to the next address. */ |
1917 |
gen_op_addl_T1_T2(); |
gen_op_addl_T1_T2(); |
1918 |
} |
} |
1919 |
} |
} |
1930 |
} |
} |
1931 |
gen_op_addl_T1_T2(); |
gen_op_addl_T1_T2(); |
1932 |
} |
} |
1933 |
|
if ((insn & (1 << 11)) == 0) { |
1934 |
|
gen_op_movl_T2_im(-offset); |
1935 |
|
gen_op_addl_T1_T2(); |
1936 |
|
} |
1937 |
/* write back the new stack pointer */ |
/* write back the new stack pointer */ |
1938 |
gen_movl_reg_T1(s, 13); |
gen_movl_reg_T1(s, 13); |
1939 |
/* set the new PC value */ |
/* set the new PC value */ |
1951 |
rn = (insn >> 8) & 0x7; |
rn = (insn >> 8) & 0x7; |
1952 |
gen_movl_T1_reg(s, rn); |
gen_movl_T1_reg(s, rn); |
1953 |
gen_op_movl_T2_im(4); |
gen_op_movl_T2_im(4); |
|
val = 0; |
|
1954 |
for (i = 0; i < 8; i++) { |
for (i = 0; i < 8; i++) { |
1955 |
if (insn & (1 << i)) { |
if (insn & (1 << i)) { |
|
/* advance to the next address */ |
|
|
if (val) |
|
|
gen_op_addl_T1_T2(); |
|
|
else |
|
|
val = 1; |
|
1956 |
if (insn & (1 << 11)) { |
if (insn & (1 << 11)) { |
1957 |
/* load */ |
/* load */ |
1958 |
gen_op_ldl_T0_T1(); |
gen_op_ldl_T0_T1(); |
1962 |
gen_movl_T0_reg(s, i); |
gen_movl_T0_reg(s, i); |
1963 |
gen_op_stl_T0_T1(); |
gen_op_stl_T0_T1(); |
1964 |
} |
} |
1965 |
|
/* advance to the next address */ |
1966 |
|
gen_op_addl_T1_T2(); |
1967 |
} |
} |
1968 |
} |
} |
1969 |
|
/* Base register writeback. */ |
1970 |
|
gen_movl_reg_T1(s, rn); |
1971 |
break; |
break; |
1972 |
|
|
1973 |
case 13: |
case 13: |
1994 |
gen_movl_T1_reg(s, 15); |
gen_movl_T1_reg(s, 15); |
1995 |
|
|
1996 |
/* jump to the offset */ |
/* jump to the offset */ |
1997 |
val = (uint32_t)s->pc; |
val = (uint32_t)s->pc + 2; |
1998 |
offset = ((int32_t)insn << 24) >> 24; |
offset = ((int32_t)insn << 24) >> 24; |
1999 |
val += (offset << 1) + 2; |
val += offset << 1; |
2000 |
gen_jmp(s, val); |
gen_jmp(s, val); |
2001 |
break; |
break; |
2002 |
|
|
2020 |
gen_op_movl_T1_im(val | 1); |
gen_op_movl_T1_im(val | 1); |
2021 |
gen_movl_reg_T1(s, 14); |
gen_movl_reg_T1(s, 14); |
2022 |
|
|
2023 |
val += offset; |
val += offset << 1; |
2024 |
if (insn & (1 << 11)) { |
if (insn & (1 << 11)) { |
2025 |
/* bl */ |
/* bl */ |
2026 |
gen_jmp(s, val); |
gen_jmp(s, val); |
2027 |
} else { |
} else { |
2028 |
/* blx */ |
/* blx */ |
2029 |
|
val &= ~(uint32_t)2; |
2030 |
gen_op_movl_T0_im(val); |
gen_op_movl_T0_im(val); |
2031 |
gen_bx(s); |
gen_bx(s); |
2032 |
} |
} |
2033 |
} |
} |
2034 |
return; |
return; |
2035 |
undef: |
undef: |
2036 |
gen_op_movl_T0_im((long)s->pc - 4); |
gen_op_movl_T0_im((long)s->pc - 2); |
2037 |
gen_op_movl_reg_TN[0][15](); |
gen_op_movl_reg_TN[0][15](); |
2038 |
gen_op_undef_insn(); |
gen_op_undef_insn(); |
2039 |
s->is_jmp = DISAS_JUMP; |
s->is_jmp = DISAS_JUMP; |
2064 |
dc->pc = pc_start; |
dc->pc = pc_start; |
2065 |
dc->singlestep_enabled = env->singlestep_enabled; |
dc->singlestep_enabled = env->singlestep_enabled; |
2066 |
dc->condjmp = 0; |
dc->condjmp = 0; |
2067 |
|
dc->thumb = env->thumb; |
2068 |
nb_gen_labels = 0; |
nb_gen_labels = 0; |
2069 |
lj = -1; |
lj = -1; |
2070 |
do { |
do { |
2148 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
2149 |
fprintf(logfile, "----------------\n"); |
fprintf(logfile, "----------------\n"); |
2150 |
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
2151 |
target_disas(logfile, pc_start, dc->pc - pc_start, 0); |
target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb); |
2152 |
fprintf(logfile, "\n"); |
fprintf(logfile, "\n"); |
2153 |
if (loglevel & (CPU_LOG_TB_OP)) { |
if (loglevel & (CPU_LOG_TB_OP)) { |
2154 |
fprintf(logfile, "OP:\n"); |
fprintf(logfile, "OP:\n"); |