summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzwelch <zwelch@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2009-07-15 23:48:21 +0000
committerzwelch <zwelch@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2009-07-15 23:48:21 +0000
commitf163d0009d99736c423b41db99ec015edf9814e5 (patch)
tree1053afc751823a0ecbd2cfbd9ab85752633d7044 /src
parent0165ae44053f3eb7a94ab88dee2e01b412bf5517 (diff)
downloadopenocd+libswd-f163d0009d99736c423b41db99ec015edf9814e5.tar.gz
openocd+libswd-f163d0009d99736c423b41db99ec015edf9814e5.tar.bz2
openocd+libswd-f163d0009d99736c423b41db99ec015edf9814e5.tar.xz
openocd+libswd-f163d0009d99736c423b41db99ec015edf9814e5.zip
David Brownell <david-b@pacbell.net>:
Make the Thumb2 disassembler handle more 32-bit instructions: A5.3.3 Data processing (plain binary immediate) These use mostly twelve bit literals, but there are also bitfield and saturated add primitives. git-svn-id: svn://svn.berlios.de/openocd/trunk@2534 b42882b7-edfa-0310-969c-e2dbd0fdcd60
Diffstat (limited to 'src')
-rw-r--r--src/target/arm_disassembler.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c
index 25b27378..a3b61b58 100644
--- a/src/target/arm_disassembler.c
+++ b/src/target/arm_disassembler.c
@@ -2671,6 +2671,101 @@ static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
return ERROR_OK;
}
+static int t2ev_data_immed(uint32_t opcode, uint32_t address,
+ arm_instruction_t *instruction, char *cp)
+{
+ char *mnemonic = NULL;
+ int rn = (opcode >> 16) & 0xf;
+ int rd = (opcode >> 8) & 0xf;
+ unsigned immed;
+ bool add = false;
+ bool is_signed = false;
+
+ immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 12);
+ if (opcode & (1 << 27))
+ immed |= (1 << 11);
+
+ switch ((opcode >> 20) & 0x1f) {
+ case 0:
+ if (rn == 0xf) {
+ add = true;
+ goto do_adr;
+ }
+ mnemonic = "ADD.W";
+ break;
+ case 4:
+ mnemonic = "MOV.W";
+ break;
+ case 0x0a:
+ if (rn == 0xf)
+ goto do_adr;
+ mnemonic = "SUB.W";
+ break;
+ case 0x0c:
+ /* move constant to top 16 bits of register */
+ immed |= (opcode >> 4) & 0xf000;
+ sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
+ return ERROR_OK;
+ case 0x10:
+ case 0x12:
+ is_signed = true;
+ case 0x18:
+ case 0x1a:
+ /* signed/unsigned saturated add */
+ immed = (opcode >> 6) & 0x03;
+ immed |= (opcode >> 10) & 0x1c;
+ sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
+ is_signed ? "S" : "U",
+ rd, (opcode & 0x1f) + 1, rn,
+ (opcode & (1 << 21)) ? "ASR" : "LSL",
+ immed ? immed : 32);
+ return ERROR_OK;
+ case 0x14:
+ is_signed = true;
+ /* FALLTHROUGH */
+ case 0x1c:
+ /* signed/unsigned bitfield extract */
+ immed = (opcode >> 6) & 0x03;
+ immed |= (opcode >> 10) & 0x1c;
+ sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
+ is_signed ? "S" : "U",
+ rd, rn, immed,
+ (opcode & 0x1f) + 1);
+ return ERROR_OK;
+ case 0x16:
+ immed = (opcode >> 6) & 0x03;
+ immed |= (opcode >> 10) & 0x1c;
+ if (rn == 0xf) /* bitfield clear */
+ sprintf(cp, "BFC\tr%d, #%d, #%d\t",
+ rd, immed,
+ (opcode & 0x1f) + 1 - immed);
+ else /* bitfield insert */
+ sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
+ rd, rn, immed,
+ (opcode & 0x1f) + 1 - immed);
+ return ERROR_OK;
+ default:
+ return ERROR_INVALID_ARGUMENTS;
+ }
+
+ sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
+ rd, rn, immed, immed);
+ return ERROR_OK;
+
+do_adr:
+ address &= ~0x03;
+ address += 4;
+ if (add)
+ address += immed;
+ else
+ address -= immed;
+ /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
+ * not hiding the pc-relative stuff will sometimes be useful.
+ */
+ sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
+ return ERROR_OK;
+}
+
/*
* REVISIT for Thumb2 instructions, instruction->type and friends aren't
* always set. That means eventual arm_simulate_step() support for Thumb2
@@ -2722,6 +2817,10 @@ int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruc
if ((opcode & 0x1a008000) == 0x10000000)
retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
+ /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
+ else if ((opcode & 0x1a008000) == 0x12000000)
+ retval = t2ev_data_immed(opcode, address, instruction, cp);
+
/* ARMv7-M: A5.3.4 Branches and miscellaneous control */
else if ((opcode & 0x18008000) == 0x10008000)
retval = t2ev_b_misc(opcode, address, instruction, cp);