diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index d1a6cbc..0e50c52 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -303,6 +303,7 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
 	decoder->packet_buffer[et].instr_count = 0;
 	decoder->packet_buffer[et].last_instr_taken_branch = false;
 	decoder->packet_buffer[et].last_instr_size = 0;
+	decoder->packet_buffer[et].flags = 0;
 
 	if (decoder->packet_count == MAX_BUFFER - 1)
 		return OCSD_RESP_WAIT;
@@ -437,6 +438,171 @@ cs_etm_decoder__buffer_exception_ret(struct cs_etm_decoder *decoder,
 					     CS_ETM_EXCEPTION_RET);
 }
 
+static void cs_etm_decoder__set_sample_flags(
+				const void *context,
+				const ocsd_generic_trace_elem *elem)
+{
+	struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
+	struct cs_etm_packet *packet;
+	u32 exc_num;
+
+	packet = &decoder->packet_buffer[decoder->tail];
+
+	switch (elem->elem_type) {
+	case OCSD_GEN_TRC_ELEM_TRACE_ON:
+		packet->flags = PERF_IP_FLAG_BRANCH |
+				PERF_IP_FLAG_TRACE_BEGIN;
+		break;
+
+	case OCSD_GEN_TRC_ELEM_NO_SYNC:
+	case OCSD_GEN_TRC_ELEM_EO_TRACE:
+		packet->flags = PERF_IP_FLAG_BRANCH |
+				PERF_IP_FLAG_TRACE_END;
+		break;
+
+	case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
+		/*
+		 * Immediate branch instruction without neither link nor
+		 * return flag, it's normal branch instruction within
+		 * the function.
+		 */
+		if (elem->last_i_type == OCSD_INSTR_BR &&
+		    elem->last_i_subtype == OCSD_S_INSTR_NONE) {
+			packet->flags = PERF_IP_FLAG_BRANCH;
+
+			if (elem->last_instr_cond)
+				packet->flags |= PERF_IP_FLAG_CONDITIONAL;
+		}
+
+		/*
+		 * Immediate branch instruction with link (e.g. BL), this is
+		 * branch instruction for function call.
+		 */
+		if (elem->last_i_type == OCSD_INSTR_BR &&
+		    elem->last_i_subtype == OCSD_S_INSTR_BR_LINK)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_CALL;
+
+		/*
+		 * Indirect branch instruction with subtype of
+		 * OCSD_S_INSTR_V7_IMPLIED_RET, this is explicit hint for
+		 * function return for A32/T32.
+		 */
+		if (elem->last_i_type == OCSD_INSTR_BR_INDIRECT &&
+		    elem->last_i_subtype == OCSD_S_INSTR_V7_IMPLIED_RET)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_RETURN;
+
+		/*
+		 * Indirect branch instruction without link (e.g. BR), usually
+		 * this is used for function return, especially for functions
+		 * within dynamic link lib.
+		 */
+		if (elem->last_i_type == OCSD_INSTR_BR_INDIRECT &&
+		    elem->last_i_subtype == OCSD_S_INSTR_NONE)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_RETURN;
+
+		/*
+		 * Indirect branch instruction with link (e.g. BLR), this is
+		 * branch instruction for function call.
+		 */
+		if (elem->last_i_type == OCSD_INSTR_BR_INDIRECT &&
+		    elem->last_i_subtype == OCSD_S_INSTR_BR_LINK)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_CALL;
+
+		/* Return instruction for function return. */
+		if (elem->last_i_type == OCSD_INSTR_BR_INDIRECT &&
+		    elem->last_i_subtype == OCSD_S_INSTR_V8_RET)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_RETURN;
+
+		break;
+
+	case OCSD_GEN_TRC_ELEM_EXCEPTION:
+
+#define OCSD_EXC_RESET			0
+#define OCSD_EXC_DEBUG_HALT		1
+#define OCSD_EXC_CALL			2
+#define OCSD_EXC_TRAP			3
+#define OCSD_EXC_SYSTEM_ERROR		4
+#define OCSD_EXC_INST_DEBUG		6
+#define OCSD_EXC_DATA_DEBUG		7
+#define OCSD_EXC_ALIGNMENT		10
+#define OCSD_EXC_INST_FAULT		11
+#define OCSD_EXC_DATA_FAULT		12
+#define OCSD_EXC_IRQ			14
+#define OCSD_EXC_FIQ			15
+
+		exc_num = decoder->exc_num[packet->cpu];
+
+		/*
+		 * The exceptions are triggered by external signals
+		 * from bus, interrupt controller, debug module,
+		 * PE reset or halt.
+		 */
+		if (exc_num == OCSD_EXC_RESET ||
+		    exc_num == OCSD_EXC_DEBUG_HALT ||
+		    exc_num == OCSD_EXC_SYSTEM_ERROR ||
+		    exc_num == OCSD_EXC_INST_DEBUG ||
+		    exc_num == OCSD_EXC_DATA_DEBUG ||
+		    exc_num == OCSD_EXC_IRQ ||
+		    exc_num == OCSD_EXC_FIQ)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_CALL |
+					PERF_IP_FLAG_ASYNC |
+					PERF_IP_FLAG_INTERRUPT;
+
+		/* The exception is for system call. */
+		if (exc_num == OCSD_EXC_CALL)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_CALL |
+					PERF_IP_FLAG_SYSCALLRET;
+
+		/*
+		 * The exception is introduced by trap, instruction &
+		 * data fault or alignment errors.
+		 */
+		if (exc_num == OCSD_EXC_TRAP ||
+		    exc_num == OCSD_EXC_ALIGNMENT ||
+		    exc_num == OCSD_EXC_INST_FAULT ||
+		    exc_num == OCSD_EXC_DATA_FAULT)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_CALL |
+					PERF_IP_FLAG_INTERRUPT;
+
+		break;
+
+	case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
+
+		exc_num = decoder->exc_num[packet->cpu];
+
+		if (exc_num == OCSD_EXC_CALL)
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_RETURN |
+					PERF_IP_FLAG_SYSCALLRET;
+		else
+			packet->flags = PERF_IP_FLAG_BRANCH |
+					PERF_IP_FLAG_RETURN |
+					PERF_IP_FLAG_INTERRUPT;
+
+		break;
+
+	case OCSD_GEN_TRC_ELEM_UNKNOWN:
+	case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
+	case OCSD_GEN_TRC_ELEM_ADDR_NACC:
+	case OCSD_GEN_TRC_ELEM_TIMESTAMP:
+	case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
+	case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
+	case OCSD_GEN_TRC_ELEM_EVENT:
+	case OCSD_GEN_TRC_ELEM_SWTRACE:
+	case OCSD_GEN_TRC_ELEM_CUSTOM:
+	default:
+		break;
+	}
+}
+
 static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
 				const void *context,
 				const ocsd_trc_index_t indx __maybe_unused,
@@ -484,6 +650,8 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
 		break;
 	}
 
+	cs_etm_decoder__set_sample_flags(context, elem);
+
 	return resp;
 }
 
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
index 0d1c18d..71df908 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
@@ -47,6 +47,7 @@ struct cs_etm_packet {
 	u8 last_instr_taken_branch;
 	u8 last_instr_size;
 	int cpu;
+	u32 flags;
 };
 
 struct cs_etm_queue;
