diff options
author | zwelch <zwelch@b42882b7-edfa-0310-969c-e2dbd0fdcd60> | 2009-07-15 23:48:43 +0000 |
---|---|---|
committer | zwelch <zwelch@b42882b7-edfa-0310-969c-e2dbd0fdcd60> | 2009-07-15 23:48:43 +0000 |
commit | 421b8e133aa4dfc01dba53ac769afbcec00ab3c3 (patch) | |
tree | f3e0b575f9f085064f6ef4a4d4be51103e2d66ae /src/target | |
parent | 889bd3e7163864e78ab73ed0d340b5fd1e0493e4 (diff) | |
download | openocd+libswd-421b8e133aa4dfc01dba53ac769afbcec00ab3c3.tar.gz openocd+libswd-421b8e133aa4dfc01dba53ac769afbcec00ab3c3.tar.bz2 openocd+libswd-421b8e133aa4dfc01dba53ac769afbcec00ab3c3.tar.xz openocd+libswd-421b8e133aa4dfc01dba53ac769afbcec00ab3c3.zip |
David Brownell <david-b@pacbell.net>:
More instructions decoded:
A5.3.14 Multiply, and multiply accumulate
A5.3.15 Long multiply, long multiply accumulate, divide
The EABI requires *adjacent* register pairs, but the long multiply
ops can use any pair of registers; interesting.
git-svn-id: svn://svn.berlios.de/openocd/trunk@2538 b42882b7-edfa-0310-969c-e2dbd0fdcd60
Diffstat (limited to 'src/target')
-rw-r--r-- | src/target/arm_disassembler.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index 0c278b23..63166932 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -2875,6 +2875,71 @@ imm8: return ERROR_OK; } +static int t2ev_mul32(uint32_t opcode, uint32_t address, + arm_instruction_t *instruction, char *cp) +{ + int ra = (opcode >> 12) & 0xf; + + + switch (opcode & 0x007000f0) { + case 0: + if (ra == 0xf) + sprintf(cp, "MUL\tr%d, r%d, r%d", + (opcode >> 8) & 0xf, (opcode >> 16) & 0xf, + (opcode >> 0) & 0xf); + else + sprintf(cp, "MLA\tr%d, r%d, r%d, r%d", + (opcode >> 8) & 0xf, (opcode >> 16) & 0xf, + (opcode >> 0) & 0xf, ra); + break; + case 0x10: + sprintf(cp, "MLS\tr%d, r%d, r%d, r%d", + (opcode >> 8) & 0xf, (opcode >> 16) & 0xf, + (opcode >> 0) & 0xf, ra); + break; + default: + return ERROR_INVALID_ARGUMENTS; + } + return ERROR_OK; +} + +static int t2ev_mul64_div(uint32_t opcode, uint32_t address, + arm_instruction_t *instruction, char *cp) +{ + int op = (opcode >> 4) & 0xf; + char *infix = "MUL"; + + op += (opcode >> 16) & 0x70; + switch (op) { + case 0x40: + case 0x60: + infix = "MLA"; + /* FALLTHROUGH */ + case 0: + case 0x20: + sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d", + (op & 0x20) ? 'U' : 'S', + infix, + (opcode >> 12) & 0xf, + (opcode >> 8) & 0xf, + (opcode >> 16) & 0xf, + (opcode >> 0) & 0xf); + break; + case 0x1f: + case 0x3f: + sprintf(cp, "%cDIV\tr%d, r%d, r%d", + (op & 0x20) ? 'U' : 'S', + (opcode >> 8) & 0xf, + (opcode >> 16) & 0xf, + (opcode >> 0) & 0xf); + break; + default: + return ERROR_INVALID_ARGUMENTS; + } + + return ERROR_OK; +} + /* * REVISIT for Thumb2 instructions, instruction->type and friends aren't * always set. That means eventual arm_simulate_step() support for Thumb2 @@ -2938,6 +3003,14 @@ int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruc else if ((opcode & 0x1f100000) == 0x18000000) retval = t2ev_store_single(opcode, address, instruction, cp); + /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */ + else if ((opcode & 0x1f800000) == 0x1b000000) + retval = t2ev_mul32(opcode, address, instruction, cp); + + /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */ + else if ((opcode & 0x1f800000) == 0x1b800000) + retval = t2ev_mul64_div(opcode, address, instruction, cp); + /* FIXME decode more 32-bit instructions */ if (retval == ERROR_OK) |