summaryrefslogtreecommitdiff
path: root/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp')
-rw-r--r--decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp188
1 files changed, 111 insertions, 77 deletions
diff --git a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp
index 865aacbdb2a5..2eb6cbc3f5bf 100644
--- a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp
+++ b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp
@@ -128,7 +128,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onFlush()
ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
// continue exception processing (can't go through processPacket as elements no longer on stack)
- if(m_excep_proc != EXCEP_POP)
+ if(m_excep_info.proc != EXCEP_POP)
resp = processException();
// continue ongoing output operations on comitted elements.
else if(m_curr_state == COMMIT_ELEM)
@@ -151,6 +151,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig()
// set up static trace instruction decode elements
m_instr_info.dsb_dmb_waypoints = 0;
+ m_instr_info.wfi_wfe_branch = m_config->wfiwfeBranch() ? 1 : 0;
m_instr_info.pe_type.arch = m_config->archVersion();
m_instr_info.pe_type.profile = m_config->coreProfile();
@@ -233,7 +234,7 @@ void TrcPktDecodeEtmV4I::resetDecoder()
m_prev_overflow = false;
m_P0_stack.delete_all();
m_output_elem.init();
- m_excep_proc = EXCEP_POP;
+ m_excep_info.proc = EXCEP_POP;
m_flush_EOT = false;
}
@@ -250,6 +251,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)
switch(m_curr_packet_in->getType())
{
case ETM4_PKT_I_ASYNC: // nothing to do with this packet.
+ case ETM4_PKT_I_IGNORE: // or this one.
break;
case ETM4_PKT_I_TRACE_INFO:
@@ -350,6 +352,21 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)
bool bV7MProfile = (m_config->archVersion() == ARCH_V7) && (m_config->coreProfile() == profile_CortexM);
if (m_P0_stack.createParamElemNoParam(P0_EXCEP_RET, bV7MProfile, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
bAllocErr = true;
+ else if (bV7MProfile)
+ m_curr_spec_depth++;
+ }
+ break;
+
+ case ETM4_PKT_I_FUNC_RET:
+ {
+ // P0 element iff V8M profile, otherwise ignore
+ if (OCSD_IS_V8_ARCH(m_config->archVersion()) && (m_config->coreProfile() == profile_CortexM))
+ {
+ if (m_P0_stack.createParamElemNoParam(P0_FUNC_RET, true, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
+ bAllocErr = true;
+ else
+ m_curr_spec_depth++;
+ }
}
break;
@@ -371,7 +388,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)
{
std::vector<uint32_t> params = { 0 };
params[0] = m_curr_packet_in->getCC();
- if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
+ if (m_P0_stack.createParamElem(P0_CC, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
bAllocErr = true;
}
@@ -387,7 +404,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)
params[1] = (uint32_t)((ts >> 32) & 0xFFFFFFFF);
if (bTSwithCC)
params[2] = m_curr_packet_in->getCC();
- if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
+ if (m_P0_stack.createParamElem(bTSwithCC ? P0_TS_CC : P0_TS, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
bAllocErr = true;
}
@@ -490,6 +507,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)
bool bPause = false; // pause commit operation
bool bPopElem = true; // do we remove the element from the stack (multi atom elements may need to stay!)
int num_commit_req = m_P0_commit;
+ ocsd_trc_index_t err_idx = 0;
Complete = true; // assume we exit due to completion of commit operation
@@ -500,8 +518,9 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)
if(m_P0_stack.size() > 0)
{
pElem = m_P0_stack.back(); // get oldest element
-
- switch(pElem->getP0Type())
+ err_idx = pElem->getRootIndex(); // save index in case of error.
+
+ switch (pElem->getP0Type())
{
// indicates a trace restart - beginning of trace or discontinuiuty
case P0_TRC_ON:
@@ -612,7 +631,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)
if ((resp = returnStackPop()) != OCSD_RESP_CONT)
break;
- m_excep_proc = EXCEP_POP; // set state in case we need to stop part way through
+ m_excep_info.proc = EXCEP_POP; // set state in case we need to stop part way through
resp = processException(); // output trace + exception elements.
m_P0_commit--;
break;
@@ -623,6 +642,13 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)
if(pElem->isP0()) // are we on a core that counts ERET as P0?
m_P0_commit--;
break;
+
+ case P0_FUNC_RET:
+ // func ret is V8M - data trace only - hint that data has been popped off the stack.
+ // at this point nothing to do till the decoder starts handling data trace.
+ if (pElem->isP0())
+ m_P0_commit--;
+ break;
}
if(bPopElem)
@@ -637,10 +663,6 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)
else
{
// too few elements for commit operation - decode error.
- ocsd_trc_index_t err_idx = 0;
- if(pElem)
- err_idx = pElem->getRootIndex();
-
resp = OCSD_RESP_FATAL_INVALID_DATA;
LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_COMMIT_PKT_OVERRUN,err_idx,m_CSID,"Not enough elements to commit"));
bPause = true;
@@ -757,7 +779,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::flushEOT()
ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputCC(TrcStackElemParam *pParamElem)
{
m_output_elem.setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
- m_output_elem.cycle_count = pParamElem->getParam(0);
+ m_output_elem.setCycleCount(pParamElem->getParam(0));
return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem);
}
@@ -778,6 +800,17 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputEvent(TrcStackElemParam *pParamEl
return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem);
}
+ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputTraceRange(const bool executed, ocsd_trc_index_t index)
+{
+ m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
+ m_output_elem.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size);
+ m_output_elem.setISA(m_instr_info.isa);
+ m_output_elem.setLastInstrCond(m_instr_info.is_conditional);
+ if (executed)
+ m_instr_info.isa = m_instr_info.next_isa;
+ return outputTraceElementIdx(index, m_output_elem);
+}
+
ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bool &bCont)
{
ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
@@ -834,10 +867,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bo
}
break;
}
- m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
- m_output_elem.setLastInstrInfo((atom == ATOM_E),m_instr_info.type, m_instr_info.sub_type);
- m_output_elem.setISA(m_instr_info.isa);
- resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
+ resp = outputTraceRange((atom == ATOM_E), pElem->getRootIndex());
}
else
@@ -848,10 +878,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bo
if(m_output_elem.st_addr != m_output_elem.en_addr)
{
// some trace before we were out of memory access range
- m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
- m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type);
- m_output_elem.setISA(m_instr_info.isa);
- resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
+ resp = outputTraceRange(true, pElem->getRootIndex());
}
if(m_mem_nacc_pending && OCSD_DATA_RESP_IS_CONT(resp))
@@ -873,11 +900,13 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bo
ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processException()
{
ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
- bool excep_implied_P0 = false; //!< exception implies P0
+ TrcStackElemExcept *pExceptElem;
- if(m_excep_proc == EXCEP_POP)
+ m_excep_info.addr_b_tgt = false;
+
+ if(m_excep_info.proc == EXCEP_POP)
{
- TrcStackElemExcept *pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back()); // get the exception element
+ pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back()); // get the exception element
TrcStackElemAddr *pAddressElem = 0;
TrcStackElemCtxt *pCtxtElem = 0;
TrcStackElem *pElem = 0;
@@ -902,32 +931,52 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processException()
// extract address
pAddressElem = static_cast<TrcStackElemAddr *>(pElem);
- m_excep_addr = pAddressElem->getAddr();
+ // fill in exception info for use later
+ m_excep_info.addr = pAddressElem->getAddr();
+ m_excep_info.number = pExceptElem->getExcepNum();
+ m_excep_info.index = pExceptElem->getRootIndex();
+ m_excep_info.addr_b_tgt = pExceptElem->getPrevSame();
- // if we have context, get that.
- if(pCtxtElem)
- updateContext(pCtxtElem);
-
- // record the exception number
- m_output_elem.exception_number = pExceptElem->getExcepNum();
-
- // see if there is an implied P0 element on the exception.
- excep_implied_P0 = pExceptElem->getPrevSame();
-
- // save the trace index.
- m_excep_index = pExceptElem->getRootIndex();
+ // see if there is an address + optional context element implied
+ // prior to the exception.
+ if (m_excep_info.addr_b_tgt)
+ {
+ // this was a branch target address - update current setting
+ bool b64bit = m_instr_info.isa == ocsd_isa_aarch64;
+ if (pCtxtElem) {
+ b64bit = pCtxtElem->getContext().SF;
+ }
+ m_instr_info.instr_addr = m_excep_info.addr.val;
+ m_instr_info.isa = (m_excep_info.addr.isa == 0) ?
+ (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2;
+ m_need_addr = false;
+ }
// figure out next move
- if(m_excep_addr.val == m_instr_info.instr_addr)
- m_excep_proc = EXCEP_EXCEP;
+ if (pCtxtElem) {
+ m_excep_info.proc = EXCEP_CTXT;
+ updateContext(pCtxtElem);
+ }
+ else if(m_excep_info.addr.val == m_instr_info.instr_addr)
+ m_excep_info.proc = EXCEP_EXCEP;
else
- m_excep_proc = EXCEP_RANGE;
+ m_excep_info.proc = EXCEP_RANGE;
}
m_P0_stack.delete_popped();
}
+ // output a context element
+ if (m_excep_info.proc == EXCEP_CTXT)
+ {
+ m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
+ resp = outputTraceElementIdx(m_excep_info.index, m_output_elem);
+ m_excep_info.proc = EXCEP_EXCEP;
+ if (!OCSD_DATA_RESP_IS_CONT(resp))
+ return resp;
+ }
+
// output a range element
- if(m_excep_proc == EXCEP_RANGE)
+ if(m_excep_info.proc == EXCEP_RANGE)
{
bool bWPFound = false;
ocsd_err_t err;
@@ -935,8 +984,8 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processException()
// last instr_info address is the start address
m_output_elem.st_addr = m_instr_info.instr_addr;
- // look for either a WP or match to return address.
- err = traceInstrToWP(bWPFound,!excep_implied_P0,m_excep_addr.val);
+ // look for match to return address.
+ err = traceInstrToWP(bWPFound,true,m_excep_info.addr.val);
if(err != OCSD_OK)
{
@@ -944,37 +993,21 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processException()
{
m_need_addr = true;
m_need_ctxt = true;
- LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_excep_index,m_CSID,"Warning: unsupported instruction set processing exception packet."));
+ LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_excep_info.index,m_CSID,"Warning: unsupported instruction set processing exception packet."));
}
else
{
resp = OCSD_RESP_FATAL_INVALID_DATA;
- LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,m_excep_index,m_CSID,"Error processing exception packet."));
- m_excep_proc = EXCEP_POP; // nothing more to do, reset to start of exception handling
+ LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,m_excep_info.index,m_CSID,"Error processing exception packet."));
+ m_excep_info.proc = EXCEP_POP; // nothing more to do, reset to start of exception handling
}
}
if(bWPFound)
{
- // action according to waypoint type and atom value
- if(excep_implied_P0)
- {
- switch(m_instr_info.type)
- {
- case OCSD_INSTR_BR:
- m_instr_info.instr_addr = m_instr_info.branch_addr;
- break;
-
- case OCSD_INSTR_BR_INDIRECT:
- m_instr_info.instr_addr = m_excep_addr.val;
- break;
- }
- }
- m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
- m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type);
- m_output_elem.setISA(m_instr_info.isa);
- resp = outputTraceElementIdx(m_excep_index, m_output_elem);
- m_excep_proc = EXCEP_EXCEP;
+ // waypoint address found - output range
+ resp = outputTraceRange(true, m_excep_info.index);
+ m_excep_info.proc = EXCEP_EXCEP;
}
else
{
@@ -984,34 +1017,33 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processException()
if(m_output_elem.st_addr != m_output_elem.en_addr)
{
// some trace before we were out of memory access range
- m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
- m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type);
- m_output_elem.setISA(m_instr_info.isa);
- resp = outputTraceElementIdx(m_excep_index,m_output_elem);
+ resp = outputTraceRange(true, m_excep_info.index);
}
- m_excep_proc = m_mem_nacc_pending ? EXCEP_NACC : EXCEP_EXCEP;
+ m_excep_info.proc = m_mem_nacc_pending ? EXCEP_NACC : EXCEP_EXCEP;
}
}
- if((m_excep_proc == EXCEP_NACC) && OCSD_DATA_RESP_IS_CONT(resp))
+ if((m_excep_info.proc == EXCEP_NACC) && OCSD_DATA_RESP_IS_CONT(resp))
{
m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
m_output_elem.st_addr = m_nacc_addr;
- resp = outputTraceElementIdx(m_excep_index,m_output_elem);
- m_excep_proc = EXCEP_EXCEP;
+ resp = outputTraceElementIdx(m_excep_info.index,m_output_elem);
+ m_excep_info.proc = EXCEP_EXCEP;
m_mem_nacc_pending = false;
}
- if((m_excep_proc == EXCEP_EXCEP) && OCSD_DATA_RESP_IS_CONT(resp))
+ if((m_excep_info.proc == EXCEP_EXCEP) && OCSD_DATA_RESP_IS_CONT(resp))
{
// output element.
m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
// add end address as preferred return address to end addr in element
- m_output_elem.en_addr = m_excep_addr.val;
+ m_output_elem.en_addr = m_excep_info.addr.val;
m_output_elem.excep_ret_addr = 1;
- resp = outputTraceElementIdx(m_excep_index,m_output_elem);
- m_excep_proc = EXCEP_POP;
+ m_output_elem.excep_ret_addr_br_tgt = m_excep_info.addr_b_tgt;
+ m_output_elem.exception_number = m_excep_info.number;
+ resp = outputTraceElementIdx(m_excep_info.index,m_output_elem);
+ m_excep_info.proc = EXCEP_POP;
}
return resp;
}
@@ -1036,6 +1068,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceTo
ocsd_mem_space_acc_t mem_space = m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N;
m_output_elem.st_addr = m_output_elem.en_addr = m_instr_info.instr_addr;
+ m_output_elem.num_instr_range = 0;
bWPFound = false;
@@ -1057,6 +1090,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceTo
// update the range decoded address in the output packet.
m_output_elem.en_addr = m_instr_info.instr_addr;
+ m_output_elem.num_instr_range++;
// either walking to match the next instruction address or a real watchpoint
if(traceToAddrNext)
@@ -1068,7 +1102,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceTo
{
// not enough memory accessible.
m_mem_nacc_pending = true;
- m_nacc_addr = m_instr_info.instr_addr;
+ m_nacc_addr = m_instr_info.instr_addr;
}
}
return err;