Thumb prefetch abort fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1805 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
cdbdb648b7
commit
358bf29e80
|
@ -2295,8 +2295,21 @@ static void disas_thumb_insn(DisasContext *s)
|
||||||
|
|
||||||
case 14:
|
case 14:
|
||||||
/* unconditional branch */
|
/* unconditional branch */
|
||||||
if (insn & (1 << 11))
|
if (insn & (1 << 11)) {
|
||||||
goto undef; /* Second half of a blx */
|
/* Second half of blx. */
|
||||||
|
offset = ((insn & 0x7ff) << 1);
|
||||||
|
gen_movl_T0_reg(s, 14);
|
||||||
|
gen_op_movl_T1_im(offset);
|
||||||
|
gen_op_addl_T0_T1();
|
||||||
|
gen_op_movl_T1_im(0xfffffffc);
|
||||||
|
gen_op_andl_T0_T1();
|
||||||
|
|
||||||
|
val = (uint32_t)s->pc;
|
||||||
|
gen_op_movl_T1_im(val | 1);
|
||||||
|
gen_movl_reg_T1(s, 14);
|
||||||
|
gen_bx(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
val = (uint32_t)s->pc;
|
val = (uint32_t)s->pc;
|
||||||
offset = ((int32_t)insn << 21) >> 21;
|
offset = ((int32_t)insn << 21) >> 21;
|
||||||
val += (offset << 1) + 2;
|
val += (offset << 1) + 2;
|
||||||
|
@ -2305,6 +2318,29 @@ static void disas_thumb_insn(DisasContext *s)
|
||||||
|
|
||||||
case 15:
|
case 15:
|
||||||
/* branch and link [and switch to arm] */
|
/* branch and link [and switch to arm] */
|
||||||
|
if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
|
||||||
|
/* Instruction spans a page boundary. Implement it as two
|
||||||
|
16-bit instructions in case the second half causes an
|
||||||
|
prefetch abort. */
|
||||||
|
offset = ((int32_t)insn << 21) >> 9;
|
||||||
|
val = s->pc + 2 + offset;
|
||||||
|
gen_op_movl_T0_im(val);
|
||||||
|
gen_movl_reg_T0(s, 14);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (insn & (1 << 11)) {
|
||||||
|
/* Second half of bl. */
|
||||||
|
offset = ((insn & 0x7ff) << 1) | 1;
|
||||||
|
gen_movl_T0_reg(s, 14);
|
||||||
|
gen_op_movl_T1_im(offset);
|
||||||
|
gen_op_addl_T0_T1();
|
||||||
|
|
||||||
|
val = (uint32_t)s->pc;
|
||||||
|
gen_op_movl_T1_im(val | 1);
|
||||||
|
gen_movl_reg_T1(s, 14);
|
||||||
|
gen_bx(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
offset = ((int32_t)insn << 21) >> 10;
|
offset = ((int32_t)insn << 21) >> 10;
|
||||||
insn = lduw_code(s->pc);
|
insn = lduw_code(s->pc);
|
||||||
offset |= insn & 0x7ff;
|
offset |= insn & 0x7ff;
|
||||||
|
|
Loading…
Reference in a new issue