[PATCH v6 2/8] perf cs-etm: Refactor instruction size handling

James Clark james.clark at linaro.org
Thu Jun 4 07:11:12 PDT 2026



On 26/05/2026 5:59 pm, Leo Yan wrote:
> From: Leo Yan <leo.yan at linaro.org>
> 
> This patch introduces a new function cs_etm__instr_size() to calculate
> the instruction size based on ISA type and instruction address.
> 
> Given the trace data can be MB and most likely that will be A64/A32 on
> a lot of platforms, cs_etm__instr_addr() keeps a single ISA type check
> for A64/A32 and executes an optimized calculation (addr + offset * 4).
> 
> Signed-off-by: Leo Yan <leo.yan at linaro.org>
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
>   tools/perf/util/cs-etm.c | 44 +++++++++++++++++++++++---------------------
>   1 file changed, 23 insertions(+), 21 deletions(-)
> 
> diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> index ab79d08f5a6095448470e2c3ec85ff3db2fb5634..5bff8811d61e423463b7bd4e20d599d5b5307a1a 100644
> --- a/tools/perf/util/cs-etm.c
> +++ b/tools/perf/util/cs-etm.c
> @@ -1347,6 +1347,17 @@ static inline int cs_etm__t32_instr_size(struct cs_etm_queue *etmq,
>   	return ((instrBytes[1] & 0xF8) >= 0xE8) ? 4 : 2;
>   }
>   
> +static inline int cs_etm__instr_size(struct cs_etm_queue *etmq,
> +				     u8 trace_chan_id,
> +				     enum cs_etm_isa isa, u64 addr)
> +{
> +	if (isa == CS_ETM_ISA_T32)
> +		return cs_etm__t32_instr_size(etmq, trace_chan_id, addr);
> +
> +	/* Otherwise, 4-byte instruction size for A32/A64 */
> +	return 4;
> +}
> +
>   static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet)
>   {
>   	/*
> @@ -1375,19 +1386,18 @@ static inline u64 cs_etm__instr_addr(struct cs_etm_queue *etmq,
>   				     const struct cs_etm_packet *packet,
>   				     u64 offset)
>   {
> -	if (packet->isa == CS_ETM_ISA_T32) {
> -		u64 addr = packet->start_addr;
> +	u64 addr = packet->start_addr;
>   
> -		while (offset) {
> -			addr += cs_etm__t32_instr_size(etmq,
> -						       trace_chan_id, addr);
> -			offset--;
> -		}
> -		return addr;
> -	}
> +	/* 4-byte instruction size for A32/A64 */
> +	if (packet->isa == CS_ETM_ISA_A64 || packet->isa == CS_ETM_ISA_A32)
> +		return addr + offset * 4;
>   
> -	/* Assume a 4 byte instruction size (A32/A64) */
> -	return packet->start_addr + offset * 4;
> +	while (offset) {
> +		addr += cs_etm__instr_size(etmq, trace_chan_id,
> +					   packet->isa, addr);
> +		offset--;
> +	}
> +	return addr;
>   }
>   
>   static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq,
> @@ -1540,16 +1550,8 @@ static void cs_etm__copy_insn(struct cs_etm_queue *etmq,
>   		return;
>   	}
>   
> -	/*
> -	 * T32 instruction size might be 32-bit or 16-bit, decide by calling
> -	 * cs_etm__t32_instr_size().
> -	 */
> -	if (packet->isa == CS_ETM_ISA_T32)
> -		sample->insn_len = cs_etm__t32_instr_size(etmq, trace_chan_id,
> -							  sample->ip);
> -	/* Otherwise, A64 and A32 instruction size are always 32-bit. */
> -	else
> -		sample->insn_len = 4;
> +	sample->insn_len = cs_etm__instr_size(etmq, trace_chan_id,
> +					      packet->isa, sample->ip);
>   
>   	cs_etm__mem_access(etmq, trace_chan_id, sample->ip, sample->insn_len,
>   			   (void *)sample->insn, 0);
> 

Reviewed-by: James Clark <james.clark at linaro.org>




More information about the linux-arm-kernel mailing list