Now that we have a working branch map update the branch bit in sync messages by checking if the sync address is a branch address that was taken (or not).
Signed-off-by: Daniel Henrique Barboza <[email protected]> --- hw/riscv/rv-trace-messages.c | 6 +++--- hw/riscv/rv-trace-messages.h | 3 ++- hw/riscv/trace-encoder.c | 30 ++++++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/hw/riscv/rv-trace-messages.c b/hw/riscv/rv-trace-messages.c index a93b0adfc6..a0a0cbb6ce 100644 --- a/hw/riscv/rv-trace-messages.c +++ b/hw/riscv/rv-trace-messages.c @@ -115,11 +115,12 @@ static void rv_etrace_write_header(uint8_t *buf, RVTraceMessageHeader header) } size_t rv_etrace_gen_encoded_sync_msg(uint8_t *buf, uint64_t pc, - TracePrivLevel priv_level) + TracePrivLevel priv_level, + bool pc_is_branch) { RVTraceSyncPayload payload = {.format = 0b11, .subformat = 0b00, - .branch = 1, + .branch = pc_is_branch, .privilege = priv_level}; RVTraceMessageHeader header = {.flow = 0, .extend = 0, .length = SYNC_PAYLOAD_SIZE_64BITS}; @@ -158,7 +159,6 @@ size_t rv_etrace_gen_encoded_trap_msg(uint8_t *buf, uint64_t trap_addr, { RVTraceTrapPayload payload = {.format = 0b11, .subformat = 0b01, - .branch = 1, .privilege = priv_level, .ecause = ecause}; RVTraceMessageHeader header = {.flow = 0, .extend = 0, diff --git a/hw/riscv/rv-trace-messages.h b/hw/riscv/rv-trace-messages.h index 2b371641a4..fd4bb10860 100644 --- a/hw/riscv/rv-trace-messages.h +++ b/hw/riscv/rv-trace-messages.h @@ -20,7 +20,8 @@ typedef enum { } TracePrivLevel; size_t rv_etrace_gen_encoded_sync_msg(uint8_t *buf, uint64_t pc, - TracePrivLevel priv_level); + TracePrivLevel priv_level, + bool pc_is_branch); size_t rv_etrace_gen_encoded_trap_msg(uint8_t *buf, uint64_t trap_addr, TracePrivLevel priv_level, uint8_t ecause, diff --git a/hw/riscv/trace-encoder.c b/hw/riscv/trace-encoder.c index 5b8f773b11..39ed8c8d54 100644 --- a/hw/riscv/trace-encoder.c +++ b/hw/riscv/trace-encoder.c @@ -394,15 +394,38 @@ static void trencoder_send_message_smem(TraceEncoder *trencoder, trencoder_update_ramsink_writep(trencoder, dest, wrapped); } +static bool trencoder_addr_is_branch_taken(TraceEncoder *te, uint64_t addr) +{ + uint8_t last_branch; + + if (te->branches == 0) { + return false; + } + + if (te->last_branch_pc == addr) { + last_branch = extract32(te->branches, te->branches - 1, 1); + + /* 0: branch taken, 1: not taken*/ + if (last_branch == 0) { + return true; + } + } + + return false; +} + static void trencoder_send_sync_msg(Object *trencoder_obj, uint64_t pc) { TraceEncoder *trencoder = TRACE_ENCODER(trencoder_obj); TracePrivLevel priv = trencoder_get_curr_priv_level(trencoder); g_autofree uint8_t *msg = g_malloc0(TRACE_MSG_MAX_SIZE); uint8_t msg_size; + bool is_branch_taken; trencoder->first_pc = pc; - msg_size = rv_etrace_gen_encoded_sync_msg(msg, pc, priv); + is_branch_taken = trencoder_addr_is_branch_taken(trencoder, pc); + msg_size = rv_etrace_gen_encoded_sync_msg(msg, pc, priv, + is_branch_taken); trencoder_send_message_smem(trencoder, msg, msg_size); } @@ -440,6 +463,7 @@ void trencoder_set_first_trace_insn(Object *trencoder_obj, uint64_t pc) TracePrivLevel priv = trencoder_get_curr_priv_level(trencoder); g_autofree uint8_t *msg = g_malloc0(TRACE_MSG_MAX_SIZE); uint8_t msg_size; + bool is_branch_taken; if (trencoder->updiscon_pending) { trencoder_send_updiscon(trencoder, pc); @@ -447,7 +471,9 @@ void trencoder_set_first_trace_insn(Object *trencoder_obj, uint64_t pc) trencoder->first_pc = pc; trace_trencoder_first_trace_insn(pc); - msg_size = rv_etrace_gen_encoded_sync_msg(msg, pc, priv); + is_branch_taken = trencoder_addr_is_branch_taken(trencoder, pc); + msg_size = rv_etrace_gen_encoded_sync_msg(msg, pc, priv, + is_branch_taken); trencoder_send_message_smem(trencoder, msg, msg_size); } -- 2.51.1
