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.
---
 src/target/arm_disassembler.c |  101 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 101 insertions(+)

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.
---
 src/target/arm_disassembler.c |  101 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 101 insertions(+)

--- a/src/target/arm_disassembler.c
+++ b/src/target/arm_disassembler.c
@@ -2654,6 +2654,103 @@ static int t2ev_data_mod_immed(uint32_t 
 	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 = "ADDW";
+		break;
+	case 4:
+		mnemonic = "MOVW";
+		break;
+	case 0x0a:
+		if (rn == 0xf)
+			goto do_adr;
+		mnemonic = "SUBW";
+		break;
+	case 0x0c:
+		/* move constant to top 16 bits of register */
+		immed |= (opcode >> 4) & 0xf000;
+		sprintf(cp, "MOVT\tr%d, #%d\t;0x%x", 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:
+		goto undef;
+	}
+
+	sprintf(cp, "%s\tr%d, r%d, #%d\t;0x%x", mnemonic,
+			rd, rn, immed, immed);
+	return ERROR_OK;
+
+do_adr:
+	address &= ~0x03;
+	address += 4;
+	if (add)
+		address += immed;
+	else
+		address -= immed;
+	sprintf(cp, "ADR.W\tr%d, %8.8" PRIx32, rd, address);
+	return ERROR_OK;
+
+undef:
+	instruction->type = ARM_UNDEFINED_INSTRUCTION;
+	strcpy(cp, "UNDEFINED OPCODE");
+	return ERROR_OK;
+}
+
 /*
  * REVISIT for Thumb2 instructions, instruction->type isn't always being
  * set.  That means eventual arm_simulate_step() support for Thumb2 will
@@ -2708,6 +2805,10 @@ int thumb2_opcode(target_t *target, uint
 	if ((opcode & 0x1a008000) == 0x10000000)
 		return t2ev_data_mod_immed(opcode, address, instruction, cp);
 
+	/* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
+	if ((opcode & 0x1a008000) == 0x12000000)
+		return t2ev_data_immed(opcode, address, instruction, cp);
+
 	/* FIXME decode more 32-bit instructions */
 
 	LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to