提交 5899f386 编写于 作者: B bellard

ARM thumb fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1418 c046a42c-6fe2-441c-8c8c-71466251a162
上级 6a0f9e82
...@@ -824,12 +824,13 @@ void OPPROTO op_shrl_T0_im_thumb(void) ...@@ -824,12 +824,13 @@ void OPPROTO op_shrl_T0_im_thumb(void)
shift = PARAM1; shift = PARAM1;
if (shift == 0) { if (shift == 0) {
env->CF = 0; env->CF = ((uint32_t)shift) >> 31;
T0 = 0; T0 = 0;
} else { } else {
env->CF = (T0 >> (shift - 1)) & 1; env->CF = (T0 >> (shift - 1)) & 1;
T0 = T0 >> shift; T0 = T0 >> shift;
} }
env->NZF = T0;
FORCE_RET(); FORCE_RET();
} }
......
...@@ -38,6 +38,7 @@ typedef struct DisasContext { ...@@ -38,6 +38,7 @@ typedef struct DisasContext {
int condlabel; int condlabel;
struct TranslationBlock *tb; struct TranslationBlock *tb;
int singlestep_enabled; int singlestep_enabled;
int thumb;
} DisasContext; } DisasContext;
#define DISAS_JUMP_NEXT 4 #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)
int val; int val;
if (reg == 15) { if (reg == 15) {
/* normaly, since we updated PC, we need only to add 4 */ /* normaly, since we updated PC, we need only to add one insn */
val = (long)s->pc + 4; if (s->thumb)
val = (long)s->pc + 2;
else
val = (long)s->pc + 4;
gen_op_movl_TN_im[t](val); gen_op_movl_TN_im[t](val);
} else { } else {
gen_op_movl_TN_reg[t][reg](); 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)
{ {
if (__builtin_expect(s->singlestep_enabled, 0)) { if (__builtin_expect(s->singlestep_enabled, 0)) {
/* An indirect jump so that we still trigger the debug exception. */ /* An indirect jump so that we still trigger the debug exception. */
if (s->thumb)
dest |= 1;
gen_op_movl_T0_im(dest); gen_op_movl_T0_im(dest);
gen_bx(s); gen_bx(s);
} else { } else {
...@@ -1552,7 +1558,7 @@ static void disas_thumb_insn(DisasContext *s) ...@@ -1552,7 +1558,7 @@ static void disas_thumb_insn(DisasContext *s)
gen_movl_T1_reg(s, rm); gen_movl_T1_reg(s, rm);
} }
if (insn & (1 << 9)) if (insn & (1 << 9))
gen_op_addl_T0_T1_cc(); gen_op_subl_T0_T1_cc();
else else
gen_op_addl_T0_T1_cc(); gen_op_addl_T0_T1_cc();
gen_movl_reg_T0(s, rd); 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)
case 4: case 4:
if (insn & (1 << 11)) { if (insn & (1 << 11)) {
rd = (insn >> 8) & 7; rd = (insn >> 8) & 7;
/* load pc-relative */ /* load pc-relative. Bit 1 of PC is ignored. */
val = (insn & 0xff) * 4; val = s->pc + 2 + ((insn & 0xff) * 4);
val &= ~(uint32_t)2;
gen_op_movl_T1_im(val); gen_op_movl_T1_im(val);
gen_movl_T2_reg(s, 15);
gen_op_addl_T1_T2();
gen_op_ldl_T0_T1(); gen_op_ldl_T0_T1();
gen_movl_reg_T0(s, rd); gen_movl_reg_T0(s, rd);
break; break;
...@@ -1658,7 +1663,7 @@ static void disas_thumb_insn(DisasContext *s) ...@@ -1658,7 +1663,7 @@ static void disas_thumb_insn(DisasContext *s)
gen_movl_T0_reg(s, rd); gen_movl_T0_reg(s, rd);
gen_movl_T1_reg(s, rm); gen_movl_T1_reg(s, rm);
switch (insn >> 6) { switch (op) {
case 0x0: /* and */ case 0x0: /* and */
gen_op_andl_T0_T1(); gen_op_andl_T0_T1();
gen_op_logic_T0_cc(); 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)
gen_op_andl_T0_T1(); gen_op_andl_T0_T1();
gen_op_logic_T0_cc(); gen_op_logic_T0_cc();
rd = 16; rd = 16;
break;
case 0x9: /* neg */ case 0x9: /* neg */
gen_op_rsbl_T0_T1_cc(); gen_op_subl_T0_T1_cc();
break; break;
case 0xa: /* cmp */ case 0xa: /* cmp */
gen_op_subl_T0_T1_cc(); 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)
gen_op_notl_T1(); gen_op_notl_T1();
gen_op_logic_T1_cc(); gen_op_logic_T1_cc();
val = 1; val = 1;
rm = rd;
break; break;
} }
if (rd != 16) { if (rd != 16) {
if (val) if (val)
gen_movl_reg_T1(s, rd); gen_movl_reg_T1(s, rm);
else else
gen_movl_reg_T0(s, rd); gen_movl_reg_T0(s, rd);
} }
...@@ -1756,7 +1763,7 @@ static void disas_thumb_insn(DisasContext *s) ...@@ -1756,7 +1763,7 @@ static void disas_thumb_insn(DisasContext *s)
gen_op_ldl_T0_T1(); gen_op_ldl_T0_T1();
break; break;
case 5: /* ldrh */ case 5: /* ldrh */
gen_op_ldsw_T0_T1(); gen_op_lduw_T0_T1();
break; break;
case 6: /* ldrb */ case 6: /* ldrb */
gen_op_ldub_T0_T1(); 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)
case 10: case 10:
/* add to high reg */ /* add to high reg */
rd = (insn >> 8) & 7; rd = (insn >> 8) & 7;
if (insn & (1 << 11)) if (insn & (1 << 11)) {
rm = 13; /* sp */ /* SP */
else gen_movl_T0_reg(s, 13);
rm = 15; /* pc */ } else {
gen_movl_T0_reg(s, rm); /* PC. bit 1 is ignored. */
gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
}
val = (insn & 0xff) * 4; val = (insn & 0xff) * 4;
gen_op_movl_T1_im(val); gen_op_movl_T1_im(val);
gen_op_addl_T0_T1(); 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)
case 4: case 5: case 0xc: case 0xd: case 4: case 5: case 0xc: case 0xd:
/* push/pop */ /* push/pop */
gen_movl_T1_reg(s, 13); gen_movl_T1_reg(s, 13);
if (insn & (1 << 11)) if (insn & (1 << 8))
val = 4; offset = 4;
else else
val = -4; offset = 0;
gen_op_movl_T2_im(val); for (i = 0; i < 8; i++) {
if (insn & (1 << i))
offset += 4;
}
if ((insn & (1 << 11)) == 0) {
gen_op_movl_T2_im(-offset);
gen_op_addl_T1_T2();
}
gen_op_movl_T2_im(4);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (insn & (1 << i)) { if (insn & (1 << i)) {
if (insn & (1 << 11)) { 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)
gen_movl_T0_reg(s, i); gen_movl_T0_reg(s, i);
gen_op_stl_T0_T1(); gen_op_stl_T0_T1();
} }
/* move to the next address */ /* advance to the next address. */
gen_op_addl_T1_T2(); gen_op_addl_T1_T2();
} }
} }
...@@ -1913,7 +1930,10 @@ static void disas_thumb_insn(DisasContext *s) ...@@ -1913,7 +1930,10 @@ static void disas_thumb_insn(DisasContext *s)
} }
gen_op_addl_T1_T2(); gen_op_addl_T1_T2();
} }
if ((insn & (1 << 11)) == 0) {
gen_op_movl_T2_im(-offset);
gen_op_addl_T1_T2();
}
/* write back the new stack pointer */ /* write back the new stack pointer */
gen_movl_reg_T1(s, 13); gen_movl_reg_T1(s, 13);
/* set the new PC value */ /* 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)
rn = (insn >> 8) & 0x7; rn = (insn >> 8) & 0x7;
gen_movl_T1_reg(s, rn); gen_movl_T1_reg(s, rn);
gen_op_movl_T2_im(4); gen_op_movl_T2_im(4);
val = 0;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (insn & (1 << i)) { if (insn & (1 << i)) {
/* advance to the next address */
if (val)
gen_op_addl_T1_T2();
else
val = 1;
if (insn & (1 << 11)) { if (insn & (1 << 11)) {
/* load */ /* load */
gen_op_ldl_T0_T1(); 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)
gen_movl_T0_reg(s, i); gen_movl_T0_reg(s, i);
gen_op_stl_T0_T1(); gen_op_stl_T0_T1();
} }
/* advance to the next address */
gen_op_addl_T1_T2();
} }
} }
/* Base register writeback. */
gen_movl_reg_T1(s, rn);
break; break;
case 13: case 13:
...@@ -1976,9 +1994,9 @@ static void disas_thumb_insn(DisasContext *s) ...@@ -1976,9 +1994,9 @@ static void disas_thumb_insn(DisasContext *s)
gen_movl_T1_reg(s, 15); gen_movl_T1_reg(s, 15);
/* jump to the offset */ /* jump to the offset */
val = (uint32_t)s->pc; val = (uint32_t)s->pc + 2;
offset = ((int32_t)insn << 24) >> 24; offset = ((int32_t)insn << 24) >> 24;
val += (offset << 1) + 2; val += offset << 1;
gen_jmp(s, val); gen_jmp(s, val);
break; break;
...@@ -2002,19 +2020,20 @@ static void disas_thumb_insn(DisasContext *s) ...@@ -2002,19 +2020,20 @@ static void disas_thumb_insn(DisasContext *s)
gen_op_movl_T1_im(val | 1); gen_op_movl_T1_im(val | 1);
gen_movl_reg_T1(s, 14); gen_movl_reg_T1(s, 14);
val += offset; val += offset << 1;
if (insn & (1 << 11)) { if (insn & (1 << 11)) {
/* bl */ /* bl */
gen_jmp(s, val); gen_jmp(s, val);
} else { } else {
/* blx */ /* blx */
val &= ~(uint32_t)2;
gen_op_movl_T0_im(val); gen_op_movl_T0_im(val);
gen_bx(s); gen_bx(s);
} }
} }
return; return;
undef: undef:
gen_op_movl_T0_im((long)s->pc - 4); gen_op_movl_T0_im((long)s->pc - 2);
gen_op_movl_reg_TN[0][15](); gen_op_movl_reg_TN[0][15]();
gen_op_undef_insn(); gen_op_undef_insn();
s->is_jmp = DISAS_JUMP; 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,
dc->pc = pc_start; dc->pc = pc_start;
dc->singlestep_enabled = env->singlestep_enabled; dc->singlestep_enabled = env->singlestep_enabled;
dc->condjmp = 0; dc->condjmp = 0;
dc->thumb = env->thumb;
nb_gen_labels = 0; nb_gen_labels = 0;
lj = -1; lj = -1;
do { 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,
if (loglevel & CPU_LOG_TB_IN_ASM) { if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "----------------\n"); fprintf(logfile, "----------------\n");
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
target_disas(logfile, pc_start, dc->pc - pc_start, 0); target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
if (loglevel & (CPU_LOG_TB_OP)) { if (loglevel & (CPU_LOG_TB_OP)) {
fprintf(logfile, "OP:\n"); fprintf(logfile, "OP:\n");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册