From a0356398e54984d292f4e6812cd67a9874b62f0d Mon Sep 17 00:00:00 2001 From: James Marshall Date: Tue, 16 Jan 2018 21:08:16 -0500 Subject: [PATCH] target/arm: Add PLD command to ARM disassembler. Updates the ARM disassembler to handle PLD (PreLoad Data) commands. Previously handled by printing a TODO message. There are three forms of the command: literal, register, and immediate. Simply decode based off of the A1 encoding for the instructions in the ARM ARM. Also fixes mask to handle PLDW commands. Change-Id: I63bf97f16af254e838462c7cfac80f6c4681c556 Signed-off-by: James Marshall Reviewed-on: http://openocd.zylin.com/4348 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/target/arm_disassembler.c | 75 ++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index 17948d6da..8eb819446 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -118,15 +118,78 @@ static int evaluate_pld(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { /* PLD */ - if ((opcode & 0x0d70f000) == 0x0550f000) { + if ((opcode & 0x0d30f000) == 0x0510f000) { + uint8_t Rn; + uint8_t U; + unsigned offset; + instruction->type = ARM_PLD; + Rn = (opcode & 0xf0000) >> 16; + U = (opcode & 0x00800000) >> 23; + if (Rn == 0xf) { + /* literal */ + offset = opcode & 0x0fff; + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD %s%d", + address, opcode, U ? "" : "-", offset); + } else { + uint8_t I, R; - snprintf(instruction->text, - 128, - "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", - address, - opcode); + I = (opcode & 0x02000000) >> 25; + R = (opcode & 0x00400000) >> 22; + if (I) { + /* register PLD{W} [,+/-{, }] */ + offset = (opcode & 0x0F80) >> 7; + uint8_t Rm; + Rm = opcode & 0xf; + + if (offset == 0) { + /* No shift */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d]", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm); + + } else { + uint8_t shift; + shift = (opcode & 0x60) >> 5; + + if (shift == 0x0) { + /* LSL */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSL #0x%x)", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset); + } else if (shift == 0x1) { + /* LSR */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSR #0x%x)", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset); + } else if (shift == 0x2) { + /* ASR */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ASR #0x%x)", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset); + } else if (shift == 0x3) { + /* ROR */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ROR #0x%x)", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset); + } + } + } else { + /* immediate PLD{W} [, #+/-] */ + offset = opcode & 0x0fff; + if (offset == 0) { + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d]", + address, opcode, R ? "" : "W", Rn); + } else { + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, #%s%d]", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", offset); + } + } + } return ERROR_OK; } /* DSB */