@@ -657,8 +657,12 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
{ .name = "MVA_prefetch",
.cp = 15, .crn = 7, .crm = 13, .opc1 = 0, .opc2 = 1,
.access = PL1_W, .type = ARM_CP_NOP },
+ /* We need to break the TB after ISB to execute self-modifying code
+ * correctly and also to take any pending interrupts immediately.
+ * So use arm_cp_write_ignore() function instead of ARM_CP_NOP flag.
+ */
{ .name = "ISB", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 4,
- .access = PL0_W, .type = ARM_CP_NOP },
+ .access = PL0_W, .type = ARM_CP_NO_RAW, .writefn = arm_cp_write_ignore },
{ .name = "DSB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
.access = PL0_W, .type = ARM_CP_NOP },
{ .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
@@ -1230,9 +1230,15 @@ static void handle_sync(DisasContext *s, uint32_t insn,
return;
case 4: /* DSB */
case 5: /* DMB */
- case 6: /* ISB */
/* We don't emulate caches so barriers are no-ops */
return;
+ case 6: /* ISB */
+ /* We need to break the TB after this insn to execute
+ * a self-modified code correctly and also to take
+ * any pending interrupts immediately.
+ */
+ s->is_jmp = DISAS_UPDATE;
+ return;
default:
unallocated_encoding(s);
return;
@@ -7720,10 +7720,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
return;
case 4: /* dsb */
case 5: /* dmb */
- case 6: /* isb */
ARCH(7);
/* We don't emulate caches so these are a no-op. */
return;
+ case 6: /* isb */
+ /* We need to break the TB after this insn to execute
+ * self-modifying code correctly and also to take
+ * any pending interrupts immediately.
+ */
+ gen_lookup_tb(s);
+ return;
default:
goto illegal_op;
}
@@ -10030,9 +10036,16 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
break;
case 4: /* dsb */
case 5: /* dmb */
- case 6: /* isb */
/* These execute as NOPs. */
break;
+ case 6: /* isb */
+ /* We need to break the TB after this insn
+ * to execute self-modifying code correctly
+ * and also to take any pending interrupts
+ * immediately.
+ */
+ gen_lookup_tb(s);
+ break;
default:
goto illegal_op;
}