gdb/ * arm-tdep.c (thumb_copy_b): Extract correct offset. (thumb_copy_16bit_ldr_literal): Extract correct value for rt and imm8. Set pc 4-byte aligned. Set branch dest address correctly. --- gdb/arm-tdep.c | 26 +++++++++++++++----------- 1 files changed, 15 insertions(+), 11 deletions(-) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 8f13b72..7df9958 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -5767,13 +5767,14 @@ thumb_copy_b (struct gdbarch *gdbarch, unsigned short insn, if (bit_12_15 == 0xd) { - offset = sbits (insn, 0, 7); + /* offset = SignExtend (imm8:0, 32) */ + offset = sbits ((insn << 1), 0, 8); cond = bits (insn, 8, 11); } else if (bit_12_15 == 0xe) /* Encoding T2 */ { offset = sbits ((insn << 1), 0, 11); - cond = INST_AL; + cond = INST_AL; } if (debug_displaced) @@ -7648,29 +7649,32 @@ thumb_copy_16bit_ldr_literal (struct gdbarch *gdbarch, unsigned short insn1, struct regcache *regs, struct displaced_step_closure *dsc) { - unsigned int rt = bits (insn1, 8, 7); + unsigned int rt = bits (insn1, 8, 10); unsigned int pc; - int imm8 = sbits (insn1, 0, 7); + int imm8 = (bits (insn1, 0, 7) << 2); CORE_ADDR from = dsc->insn_addr; /* LDR Rd, #imm8 Rwrite as: - Preparation: tmp2 <- R2, tmp3 <- R3, R2 <- PC, R3 <- #imm8; - if (Rd is not R0) tmp0 <- R0; + Preparation: tmp0 <- R0, tmp2 <- R2, tmp3 <- R3, R2 <- PC, R3 <- #imm8; + Insn: LDR R0, [R2, R3]; - Cleanup: R2 <- tmp2, R3 <- tmp3, - if (Rd is not R0) Rd <- R0, R0 <- tmp0 */ + Cleanup: R2 <- tmp2, R3 <- tmp3, Rd <- R0, R0 <- tmp0 */ if (debug_displaced) - fprintf_unfiltered (gdb_stdlog, "displaced: copying thumb ldr literal " - "insn %.4x\n", insn1); + fprintf_unfiltered (gdb_stdlog, + "displaced: copying thumb ldr r%d [pc #%d]\n" + , rt, imm8); dsc->tmp[0] = displaced_read_reg (regs, dsc, 0); dsc->tmp[2] = displaced_read_reg (regs, dsc, 2); dsc->tmp[3] = displaced_read_reg (regs, dsc, 3); pc = displaced_read_reg (regs, dsc, ARM_PC_REGNUM); + /* The assembler calculates the required value of the offset from the + Align(PC,4) value of this instruction to the label. */ + pc = pc & 0xfffffffc; displaced_write_reg (regs, dsc, 2, pc, CANNOT_WRITE_PC); displaced_write_reg (regs, dsc, 3, imm8, CANNOT_WRITE_PC); @@ -7712,7 +7716,7 @@ thumb_copy_cbnz_cbz (struct gdbarch *gdbarch, uint16_t insn1, dsc->u.branch.link = 0; dsc->u.branch.exchange = 0; - dsc->u.branch.dest = from + 2 + imm5; + dsc->u.branch.dest = from + 4 + imm5; if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: copying %s [r%d = 0x%x]" -- 1.7.0.4