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 <dbarboza@ventanamicro.com>
---
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