summaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2018-02-01 15:51:01 +0000
committerYao Qi <yao.qi@linaro.org>2018-02-01 15:51:01 +0000
commit2d9e6acbdbc528563a9df5445584a8a150a86527 (patch)
tree388f01d6bc4abec9e934b69009e83eb092a0a337 /gdb/arm-tdep.c
parentdf95a9cf09867c237ddf9b4eb65a990e86de1e17 (diff)
downloadbinutils-gdb-2d9e6acbdbc528563a9df5445584a8a150a86527.tar.gz
Rewrite arm_record_coproc_data_proc and arm_record_data_proc_misc_ld_str
When I triage some reverse debugging test fails on arm-linux, I find arm_record_coproc_data_proc and arm_record_data_proc_misc_ld_str is not friendly to instruction encoding on ARM ARM. This patch rewrites them, in a way match more closely to the manual. gdb: 2018-02-01 Yao Qi <yao.qi@linaro.org> * arm-tdep.c (arm_record_data_proc_misc_ld_str): Rewrite it. (arm_record_coproc_data_proc): Likewise.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c501
1 files changed, 329 insertions, 172 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index d991e7ea4ff..8be0d4d063f 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -10238,75 +10238,101 @@ arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
- /* Data processing insn /multiply insn. */
- if (9 == arm_insn_r->decode
- && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
- || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ if (!((opcode1 & 0x19) == 0x10))
{
- /* Handle multiply instructions. */
- /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
- if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
- {
- /* Handle MLA and MUL. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
- record_buf[1] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 2;
- }
- else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
- {
- /* Handle SMLAL, SMULL, UMLAL, UMULL. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
- record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
- record_buf[2] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 3;
- }
+ /* Data-processing (register) and Data-processing (register-shifted
+ register */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
}
- else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
- && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ else if ((arm_insn_r->decode < 8) && ((opcode1 & 0x19) == 0x10))
{
- /* Handle misc load insns, as 20th bit (L = 1). */
- /* LDR insn has a capability to do branching, if
- MOV LR, PC is precceded by LDR insn having Rn as R15
- in that case, it emulates branch and link insn, and hence we
- need to save CSPR and PC as well. I am not sure this is right
- place; as opcode = 010 LDR insn make this happen, if R15 was
- used. */
- reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
- if (15 != reg_dest)
- {
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- arm_insn_r->reg_rec_count = 1;
- }
- else
- {
- record_buf[0] = reg_dest;
- record_buf[1] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 2;
- }
+ /* Miscellaneous instructions */
+
+ if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+
+ /* Save SPSR also; how? */
+ return -1;
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0))
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
}
- else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
- && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
- && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
- && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ else if (9 == arm_insn_r->decode && opcode1 < 0x10)
{
- /* Handle MSR insn. */
- if (9 == arm_insn_r->opcode)
- {
- /* CSPR is going to be changed. */
- record_buf[0] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 1;
- }
- else
- {
- /* SPSR is going to be changed. */
- /* How to read SPSR value? */
- return -1;
- }
+ /* Multiply and multiply-accumulate */
+
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
}
- else if (9 == arm_insn_r->decode
- && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
- && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ else if (9 == arm_insn_r->decode && opcode1 > 0x10)
{
+ /* Synchronization primitives */
+
/* Handling SWP, SWPB. */
/* These insn, changes register and memory as well. */
/* SWP or SWPB insn. */
@@ -10315,91 +10341,169 @@ arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
/* SWP insn ?, swaps word. */
if (8 == arm_insn_r->opcode)
- {
- record_buf_mem[0] = 4;
- }
- else
- {
- /* SWPB insn, swaps only byte. */
- record_buf_mem[0] = 1;
- }
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
record_buf_mem[1] = u_regval[0];
arm_insn_r->mem_rec_count = 1;
record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
arm_insn_r->reg_rec_count = 1;
}
- else if (3 == arm_insn_r->decode && 0x12 == opcode1
- && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ else if (11 == arm_insn_r->decode || 13 == arm_insn_r->decode
+ || 15 == arm_insn_r->decode)
{
- /* Handle BLX, branch and link/exchange. */
- if (9 == arm_insn_r->opcode)
- {
- /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
- and R14 stores the return address. */
- record_buf[0] = ARM_PS_REGNUM;
- record_buf[1] = ARM_LR_REGNUM;
- arm_insn_r->reg_rec_count = 2;
- }
- }
- else if (7 == arm_insn_r->decode && 0x12 == opcode1)
- {
- /* Handle enhanced software breakpoint insn, BKPT. */
- /* CPSR is changed to be executed in ARM state, disabling normal
- interrupts, entering abort mode. */
- /* According to high vector configuration PC is set. */
- /* user hit breakpoint and type reverse, in
- that case, we need to go back with previous CPSR and
- Program Counter. */
- record_buf[0] = ARM_PS_REGNUM;
- record_buf[1] = ARM_LR_REGNUM;
- arm_insn_r->reg_rec_count = 2;
+ if ((opcode1 & 0x12) == 2)
+ {
+ /* Extra load/store (unprivileged) */
+ return -1;
+ }
+ else
+ {
+ /* Extra load/store */
+ switch (bits (arm_insn_r->arm_insn, 5, 6))
+ {
+ case 1:
+ if ((opcode1 & 0x05) == 0x0 || (opcode1 & 0x05) == 0x4)
+ {
+ /* STRH (register), STRH (immediate) */
+ arm_record_strx (arm_insn_r, &record_buf[0],
+ &record_buf_mem[0], ARM_RECORD_STRH);
+ }
+ else if ((opcode1 & 0x05) == 0x1)
+ {
+ /* LDRH (register) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
- /* Save SPSR also; how? */
- return -1;
- }
- else if (11 == arm_insn_r->decode
- && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
- {
- /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else if ((opcode1 & 0x05) == 0x5)
+ {
+ /* LDRH (immediate), LDRH (literal) */
+ int rn = bits (arm_insn_r->arm_insn, 16, 19);
- /* Handle str(x) insn */
- arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
- ARM_RECORD_STRH);
- }
- else if (1 == arm_insn_r->decode && 0x12 == opcode1
- && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
- {
- /* Handle BX, branch and link/exchange. */
- /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
- record_buf[0] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 1;
- }
- else if (1 == arm_insn_r->decode && 0x16 == opcode1
- && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
- && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
- {
- /* Count leading zeros: CLZ. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- arm_insn_r->reg_rec_count = 1;
- }
- else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
- && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
- && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
- && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
- )
- {
- /* Handle MRS insn. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- arm_insn_r->reg_rec_count = 1;
- }
- else if (arm_insn_r->opcode <= 15)
- {
- /* Normal data processing insns. */
- /* Out of 11 shifter operands mode, all the insn modifies destination
- register, which is specified by 13-16 decode. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- record_buf[1] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 2;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (rn != 15)
+ {
+ /*LDRH (immediate) */
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++] = rn;
+ }
+ }
+ }
+ else
+ return -1;
+ break;
+ case 2:
+ if ((opcode1 & 0x05) == 0x0)
+ {
+ /* LDRD (register) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else if ((opcode1 & 0x05) == 0x1)
+ {
+ /* LDRSB (register) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else if ((opcode1 & 0x05) == 0x4 || (opcode1 & 0x05) == 0x5)
+ {
+ /* LDRD (immediate), LDRD (literal), LDRSB (immediate),
+ LDRSB (literal) */
+ int rn = bits (arm_insn_r->arm_insn, 16, 19);
+
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (rn != 15)
+ {
+ /*LDRD (immediate), LDRSB (immediate) */
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++] = rn;
+ }
+ }
+ }
+ else
+ return -1;
+ break;
+ case 3:
+ if ((opcode1 & 0x05) == 0x0)
+ {
+ /* STRD (register) */
+ arm_record_strx (arm_insn_r, &record_buf[0],
+ &record_buf_mem[0], ARM_RECORD_STRD);
+ }
+ else if ((opcode1 & 0x05) == 0x1)
+ {
+ /* LDRSH (register) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else if ((opcode1 & 0x05) == 0x4)
+ {
+ /* STRD (immediate) */
+ arm_record_strx (arm_insn_r, &record_buf[0],
+ &record_buf_mem[0], ARM_RECORD_STRD);
+ }
+ else if ((opcode1 & 0x05) == 0x5)
+ {
+ /* LDRSH (immediate), LDRSH (literal) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ }
}
else
{
@@ -11579,18 +11683,18 @@ arm_record_asimd_vfp_coproc (insn_decode_record *arm_insn_r)
static int
arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
{
- uint32_t op, op1_sbit, op1_ebit, coproc;
+ uint32_t op, op1_ebit, coproc, bits_24_25;
struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
struct regcache *reg_cache = arm_insn_r->regcache;
arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
coproc = bits (arm_insn_r->arm_insn, 8, 11);
- op1_sbit = bit (arm_insn_r->arm_insn, 24);
op1_ebit = bit (arm_insn_r->arm_insn, 20);
op = bit (arm_insn_r->arm_insn, 4);
+ bits_24_25 = bits (arm_insn_r->arm_insn, 24, 25);
/* Handle arm SWI/SVC system call instructions. */
- if (op1_sbit)
+ if (bits_24_25 == 0x3)
{
if (tdep->arm_syscall_record != NULL)
{
@@ -11611,44 +11715,97 @@ arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
return -1;
}
}
-
- if ((coproc & 0x0e) == 0x0a)
+ else if (bits_24_25 == 0x02)
{
- /* VFP data-processing instructions. */
- if (!op1_sbit && !op)
- return arm_record_vfp_data_proc_insn (arm_insn_r);
+ if (op)
+ {
+ if ((coproc & 0x0e) == 0x0a)
+ {
+ /* 8, 16, and 32-bit transfer */
+ return arm_record_vdata_transfer_insn (arm_insn_r);
+ }
+ else
+ {
+ if (op1_ebit)
+ {
+ /* MRC, MRC2 */
+ uint32_t record_buf[1];
+
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ if (record_buf[0] == 15)
+ record_buf[0] = ARM_PS_REGNUM;
- /* Advanced SIMD, VFP instructions. */
- if (!op1_sbit && op)
- return arm_record_vdata_transfer_insn (arm_insn_r);
+ arm_insn_r->reg_rec_count = 1;
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count,
+ record_buf);
+ return 0;
+ }
+ else
+ {
+ /* MCR, MCR2 */
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ if ((coproc & 0x0e) == 0x0a)
+ {
+ /* VFP data-processing instructions. */
+ return arm_record_vfp_data_proc_insn (arm_insn_r);
+ }
+ else
+ {
+ /* CDP, CDP2 */
+ return -1;
+ }
+ }
}
else
{
- /* Coprocessor data operations. */
- if (!op1_sbit && !op)
- return arm_record_unsupported_insn (arm_insn_r);
-
- /* Move to Coprocessor from ARM core register. */
- if (!op1_sbit && !op1_ebit && op)
- return arm_record_unsupported_insn (arm_insn_r);
-
- /* Move to arm core register from coprocessor. */
- if (!op1_sbit && op1_ebit && op)
- {
- uint32_t record_buf[1];
-
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- if (record_buf[0] == 15)
- record_buf[0] = ARM_PS_REGNUM;
+ unsigned int op1 = bits (arm_insn_r->arm_insn, 20, 25);
- arm_insn_r->reg_rec_count = 1;
- REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count,
- record_buf);
- return 0;
- }
+ if (op1 == 5)
+ {
+ if ((coproc & 0x0e) != 0x0a)
+ {
+ /* MRRC, MRRC2 */
+ return -1;
+ }
+ }
+ else if (op1 == 4 || op1 == 5)
+ {
+ if ((coproc & 0x0e) == 0x0a)
+ {
+ /* 64-bit transfers between ARM core and extension */
+ return -1;
+ }
+ else if (op1 == 4)
+ {
+ /* MCRR, MCRR2 */
+ return -1;
+ }
+ }
+ else if (op1 == 0 || op1 == 1)
+ {
+ /* UNDEFINED */
+ return -1;
+ }
+ else
+ {
+ if ((coproc & 0x0e) == 0x0a)
+ {
+ /* Extension register load/store */
+ }
+ else
+ {
+ /* STC, STC2, LDC, LDC2 */
+ }
+ return -1;
+ }
}
- return arm_record_unsupported_insn (arm_insn_r);
+ return -1;
}
/* Handling opcode 000 insns. */