abort();
case 4:
if (insn & (1 << 22)) {
- /* Other load/store, table branch. */
+ /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
+ * - load/store doubleword, load/store exclusive, ldacq/strel,
+ * table branch.
+ */
if (insn & 0x01200000) {
- /* Load/store doubleword. */
+ /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
+ * - load/store dual (post-indexed)
+ * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
+ * - load/store dual (literal and immediate)
+ * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
+ * - load/store dual (pre-indexed)
+ */
if (rn == 15) {
+ if (insn & (1 << 21)) {
+ /* UNPREDICTABLE */
+ goto illegal_op;
+ }
addr = tcg_temp_new_i32();
tcg_gen_movi_i32(addr, s->pc & ~3);
} else {
}
if (insn & (1 << 21)) {
/* Base writeback. */
- if (rn == 15)
- goto illegal_op;
tcg_gen_addi_i32(addr, addr, offset - 4);
store_reg(s, rn, addr);
} else {
tcg_temp_free_i32(addr);
}
} else if ((insn & (1 << 23)) == 0) {
- /* Load/store exclusive word. */
+ /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
+ * - load/store exclusive word
+ */
+ if (rs == 15) {
+ goto illegal_op;
+ }
addr = tcg_temp_local_new_i32();
load_reg_var(s, addr, rn);
tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
break;
}
if (insn & (1 << 10)) {
- /* data processing extended or blx */
+ /* 0b0100_01xx_xxxx_xxxx
+ * - data processing extended, branch and exchange
+ */
rd = (insn & 7) | ((insn >> 4) & 8);
rm = (insn >> 3) & 0xf;
op = (insn >> 8) & 3;
tmp = load_reg(s, rm);
store_reg(s, rd, tmp);
break;
- case 3:/* branch [and link] exchange thumb register */
- tmp = load_reg(s, rm);
- if (insn & (1 << 7)) {
+ case 3:
+ {
+ /* 0b0100_0111_xxxx_xxxx
+ * - branch [and link] exchange thumb register
+ */
+ bool link = insn & (1 << 7);
+
+ if (insn & 7) {
+ goto undef;
+ }
+ if (link) {
ARCH(5);
+ }
+ tmp = load_reg(s, rm);
+ if (link) {
val = (uint32_t)s->pc | 1;
tmp2 = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp2, val);
}
break;
}
+ }
break;
}