[RFC v5 23/57] objtool: arm64: Decode logical data processing instructions

Julien Thierry jthierry at redhat.com
Thu Jan 9 08:02:26 PST 2020


Decode instructions performing logical operations with immediate values.
Create a stack operation for and operation targeting the stack pointer.

Since OP_SRC_AND assumes the source and destination register are the same,
add a register assignment operation when the source operand of the logical
instruction is not the stack pointer.

Suggested-by: Raphael Gault <raphael.gault at arm.com>
Signed-off-by: Julien Thierry <jthierry at redhat.com>
---
 tools/objtool/arch/arm64/decode.c             | 58 +++++++++++++++++++
 .../objtool/arch/arm64/include/insn_decode.h  |  3 +
 2 files changed, 61 insertions(+)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index d240f29a2390..a30c3294cc21 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -160,6 +160,7 @@ static arm_decode_class aarch64_insn_dp_imm_decode_table[NR_DP_IMM_SUBCLASS] = {
 	[0 ... INSN_PCREL]	= arm_decode_pcrel,
 	[INSN_ADD_SUB]		= arm_decode_add_sub,
 	[INSN_ADD_TAG]		= arm_decode_add_sub_tags,
+	[INSN_LOGICAL]		= arm_decode_logical,
 	[INSN_MOVE_WIDE]	= arm_decode_move_wide,
 	[INSN_BITFIELD]		= arm_decode_bitfield,
 	[INSN_EXTRACT]		= arm_decode_extract,
@@ -273,6 +274,63 @@ int arm_decode_add_sub_tags(u32 instr, enum insn_type *type,
 	return 0;
 }
 
+int arm_decode_logical(u32 instr, enum insn_type *type,
+		       unsigned long *immediate, struct list_head *ops_list)
+{
+	unsigned char sf = 0, opc = 0, N = 0;
+	unsigned char imms = 0, immr = 0, rn = 0, rd = 0;
+	struct stack_op *op;
+
+	rd = instr & ONES(5);
+	rn = (instr >> 5) & ONES(5);
+
+	imms = (instr >> 10) & ONES(6);
+	immr = (instr >> 16) & ONES(6);
+
+	N = EXTRACT_BIT(instr, 22);
+	opc = (instr >> 29) & ONES(2);
+	sf = EXTRACT_BIT(instr, 31);
+
+	if (N == 1 && sf == 0)
+		return arm_decode_unknown(instr, type, immediate, ops_list);
+
+	*type = INSN_OTHER;
+	*immediate = (decode_bit_masks(N, imms, immr, true) >> 64);
+
+	if (opc & 1)
+		return 0;
+
+	if (rd != CFI_SP)
+		return 0;
+
+	*type = INSN_STACK;
+
+	if (rn != CFI_SP) {
+		op = calloc(1, sizeof(*op));
+		list_add_tail(&op->list, ops_list);
+
+		op->dest.type = OP_DEST_REG;
+		op->dest.offset = 0;
+		op->dest.reg = rd;
+		op->src.type = OP_SRC_REG;
+		op->src.offset = 0;
+		op->src.reg = rn;
+	}
+
+	op = calloc(1, sizeof(*op));
+	list_add_tail(&op->list, ops_list);
+
+	op->dest.type = OP_DEST_REG;
+	op->dest.offset = 0;
+	op->dest.reg = rd;
+
+	op->src.type = OP_SRC_AND;
+	op->src.offset = 0;
+	op->src.reg = rd;
+
+	return 0;
+}
+
 int arm_decode_move_wide(u32 instr, enum insn_type *type,
 			 unsigned long *immediate, struct list_head *ops_list)
 {
diff --git a/tools/objtool/arch/arm64/include/insn_decode.h b/tools/objtool/arch/arm64/include/insn_decode.h
index 65e60b293a07..6f68e8887cdb 100644
--- a/tools/objtool/arch/arm64/include/insn_decode.h
+++ b/tools/objtool/arch/arm64/include/insn_decode.h
@@ -16,6 +16,7 @@
 #define INSN_PCREL	0b001	//0b00x
 #define INSN_ADD_SUB	0b010
 #define INSN_ADD_TAG	0b011
+#define INSN_LOGICAL	0b100
 #define INSN_MOVE_WIDE	0b101
 #define INSN_BITFIELD	0b110
 #define INSN_EXTRACT	0b111
@@ -38,6 +39,8 @@ int arm_decode_add_sub(u32 instr, enum insn_type *type,
 int arm_decode_add_sub_tags(u32 instr, enum insn_type *type,
 			    unsigned long *immediate,
 			    struct list_head *ops_list);
+int arm_decode_logical(u32 instr, enum insn_type *type,
+		       unsigned long *immediate, struct list_head *ops_list);
 int arm_decode_move_wide(u32 instr, enum insn_type *type,
 			 unsigned long *immediate, struct list_head *ops_list);
 int arm_decode_bitfield(u32 instr, enum insn_type *type,
-- 
2.21.0




More information about the linux-arm-kernel mailing list