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
This commit is contained in:
parent
889bd3e716
commit
421b8e133a
|
@ -2875,6 +2875,71 @@ imm8:
|
||||||
return ERROR_OK;
|
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
|
* REVISIT for Thumb2 instructions, instruction->type and friends aren't
|
||||||
* always set. That means eventual arm_simulate_step() support for Thumb2
|
* 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)
|
else if ((opcode & 0x1f100000) == 0x18000000)
|
||||||
retval = t2ev_store_single(opcode, address, instruction, cp);
|
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 */
|
/* FIXME decode more 32-bit instructions */
|
||||||
|
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
|
|
Loading…
Reference in New Issue