diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
commit | 070852d8604cece0c31f28ff3eb8d21d9ba415fb (patch) | |
tree | 9097175a6a5b8b7e37af9a96269ac0b61a0189cd /decoder/source/ptm/trc_pkt_decode_ptm.cpp | |
parent | Initial commit. (diff) | |
download | libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.tar.xz libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.zip |
Adding upstream version 1.3.3.upstream/1.3.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'decoder/source/ptm/trc_pkt_decode_ptm.cpp')
-rw-r--r-- | decoder/source/ptm/trc_pkt_decode_ptm.cpp | 671 |
1 files changed, 671 insertions, 0 deletions
diff --git a/decoder/source/ptm/trc_pkt_decode_ptm.cpp b/decoder/source/ptm/trc_pkt_decode_ptm.cpp new file mode 100644 index 0000000..7abee84 --- /dev/null +++ b/decoder/source/ptm/trc_pkt_decode_ptm.cpp @@ -0,0 +1,671 @@ +/* + * \file trc_pkt_decode_ptm.cpp + * \brief OpenCSD : PTM packet decoder. + * + * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sstream> +#include "opencsd/ptm/trc_pkt_decode_ptm.h" + +#define DCD_NAME "DCD_PTM" + +TrcPktDecodePtm::TrcPktDecodePtm() + : TrcPktDecodeBase(DCD_NAME) +{ + initDecoder(); +} + +TrcPktDecodePtm::TrcPktDecodePtm(int instIDNum) + : TrcPktDecodeBase(DCD_NAME,instIDNum) +{ + initDecoder(); +} + +TrcPktDecodePtm::~TrcPktDecodePtm() +{ +} + +/*********************** implementation packet decoding interface */ + +ocsd_datapath_resp_t TrcPktDecodePtm::processPacket() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + bool bPktDone = false; + + while(!bPktDone) + { + switch(m_curr_state) + { + case NO_SYNC: + // no sync - output a no sync packet then transition to wait sync. + m_output_elem.elem_type = OCSD_GEN_TRC_ELEM_NO_SYNC; + m_output_elem.unsync_eot_info = m_unsync_info; + resp = outputTraceElement(m_output_elem); + m_curr_state = (m_curr_packet_in->getType() == PTM_PKT_A_SYNC) ? WAIT_ISYNC : WAIT_SYNC; + bPktDone = true; + break; + + case WAIT_SYNC: + if(m_curr_packet_in->getType() == PTM_PKT_A_SYNC) + m_curr_state = WAIT_ISYNC; + bPktDone = true; + break; + + case WAIT_ISYNC: + if(m_curr_packet_in->getType() == PTM_PKT_I_SYNC) + m_curr_state = DECODE_PKTS; + else + bPktDone = true; + break; + + case DECODE_PKTS: + resp = decodePacket(); + bPktDone = true; + break; + + default: + // should only see these after a _WAIT resp - in flush handler + case CONT_ISYNC: + case CONT_ATOM: + bPktDone = true; + // throw a decoder error + break; + } + } + return resp; +} + +ocsd_datapath_resp_t TrcPktDecodePtm::onEOT() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + // shouldn't be any packets left to be processed - flush shoudl have done this. + // just output the end of trace marker + m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE); + m_output_elem.setUnSyncEOTReason(UNSYNC_EOT); + resp = outputTraceElement(m_output_elem); + return resp; +} + +ocsd_datapath_resp_t TrcPktDecodePtm::onReset() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + m_unsync_info = UNSYNC_RESET_DECODER; + resetDecoder(); + return resp; +} + +ocsd_datapath_resp_t TrcPktDecodePtm::onFlush() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + resp = contProcess(); + return resp; +} + +// atom and isync packets can have multiple ouput packets that can be _WAITed mid stream. +ocsd_datapath_resp_t TrcPktDecodePtm::contProcess() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + switch(m_curr_state) + { + case CONT_ISYNC: + resp = processIsync(); + break; + + case CONT_ATOM: + resp = processAtom(); + break; + + case CONT_WPUP: + resp = processWPUpdate(); + break; + + case CONT_BRANCH: + resp = processBranch(); + break; + + default: break; // not a state that requires further processing + } + + if(OCSD_DATA_RESP_IS_CONT(resp) && processStateIsCont()) + m_curr_state = DECODE_PKTS; // continue packet processing - assuming we have not degraded into an unsynced state. + + return resp; +} + +ocsd_err_t TrcPktDecodePtm::onProtocolConfig() +{ + ocsd_err_t err = OCSD_OK; + if(m_config == 0) + return OCSD_ERR_NOT_INIT; + + // static config - copy of CSID for easy reference + m_CSID = m_config->getTraceID(); + + // handle return stack implementation + if (m_config->hasRetStack()) + { + m_return_stack.set_active(m_config->enaRetStack()); +#ifdef TRC_RET_STACK_DEBUG + m_return_stack.set_dbg_logger(this); +#endif + } + + // config options affecting decode + m_instr_info.pe_type.profile = m_config->coreProfile(); + m_instr_info.pe_type.arch = m_config->archVersion(); + m_instr_info.dsb_dmb_waypoints = m_config->dmsbWayPt() ? 1 : 0; + m_instr_info.wfi_wfe_branch = 0; + return err; +} + +/****************** local decoder routines */ + +void TrcPktDecodePtm::initDecoder() +{ + m_CSID = 0; + m_instr_info.pe_type.profile = profile_Unknown; + m_instr_info.pe_type.arch = ARCH_UNKNOWN; + m_instr_info.dsb_dmb_waypoints = 0; + m_unsync_info = UNSYNC_INIT_DECODER; + resetDecoder(); +} + +void TrcPktDecodePtm::resetDecoder() +{ + m_curr_state = NO_SYNC; + m_need_isync = true; // need context to start. + + m_instr_info.isa = ocsd_isa_unknown; + m_mem_nacc_pending = false; + + m_pe_context.ctxt_id_valid = 0; + m_pe_context.bits64 = 0; + m_pe_context.vmid_valid = 0; + m_pe_context.exception_level = ocsd_EL_unknown; + m_pe_context.security_level = ocsd_sec_secure; + m_pe_context.el_valid = 0; + + m_curr_pe_state.instr_addr = 0x0; + m_curr_pe_state.isa = ocsd_isa_unknown; + m_curr_pe_state.valid = false; + + m_atoms.clearAll(); + m_output_elem.init(); +} + +ocsd_datapath_resp_t TrcPktDecodePtm::decodePacket() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + switch(m_curr_packet_in->getType()) + { + // ignore these from trace o/p point of veiw + case PTM_PKT_NOTSYNC: + case PTM_PKT_INCOMPLETE_EOT: + case PTM_PKT_NOERROR: + break; + + // bad / reserved packet - need to wait for next sync point + case PTM_PKT_BAD_SEQUENCE: + case PTM_PKT_RESERVED: + m_curr_state = WAIT_SYNC; + m_need_isync = true; // need context to re-start. + m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); + resp = outputTraceElement(m_output_elem); + break; + + // packets we can ignore if in sync + case PTM_PKT_A_SYNC: + case PTM_PKT_IGNORE: + break; + + // + case PTM_PKT_I_SYNC: + resp = processIsync(); + break; + + case PTM_PKT_BRANCH_ADDRESS: + resp = processBranch(); + break; + + case PTM_PKT_TRIGGER: + m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT); + m_output_elem.setEvent(EVENT_TRIGGER, 0); + resp = outputTraceElement(m_output_elem); + break; + + case PTM_PKT_WPOINT_UPDATE: + resp = processWPUpdate(); + break; + + case PTM_PKT_CONTEXT_ID: + { + bool bUpdate = true; + // see if this is a change + if((m_pe_context.ctxt_id_valid) && (m_pe_context.context_id == m_curr_packet_in->context.ctxtID)) + bUpdate = false; + if(bUpdate) + { + m_pe_context.context_id = m_curr_packet_in->context.ctxtID; + m_pe_context.ctxt_id_valid = 1; + m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + m_output_elem.setContext(m_pe_context); + resp = outputTraceElement(m_output_elem); + } + } + break; + + case PTM_PKT_VMID: + { + bool bUpdate = true; + // see if this is a change + if((m_pe_context.vmid_valid) && (m_pe_context.vmid == m_curr_packet_in->context.VMID)) + bUpdate = false; + if(bUpdate) + { + m_pe_context.vmid = m_curr_packet_in->context.VMID; + m_pe_context.vmid_valid = 1; + m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + m_output_elem.setContext(m_pe_context); + resp = outputTraceElement(m_output_elem); + } + } + break; + + case PTM_PKT_ATOM: + if(m_curr_pe_state.valid) + { + m_atoms.initAtomPkt(m_curr_packet_in->getAtom(),m_index_curr_pkt); + resp = processAtom(); + } + break; + + case PTM_PKT_TIMESTAMP: + m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP); + m_output_elem.timestamp = m_curr_packet_in->timestamp; + if(m_curr_packet_in->cc_valid) + m_output_elem.setCycleCount(m_curr_packet_in->cycle_count); + resp = outputTraceElement(m_output_elem); + break; + + case PTM_PKT_EXCEPTION_RET: + m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET); + resp = outputTraceElement(m_output_elem); + break; + + } + return resp; +} + +ocsd_datapath_resp_t TrcPktDecodePtm::processIsync() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + // extract the I-Sync data if not re-entering after a _WAIT + if(m_curr_state == DECODE_PKTS) + { + m_curr_pe_state.instr_addr = m_curr_packet_in->getAddrVal(); + m_curr_pe_state.isa = m_curr_packet_in->getISA(); + m_curr_pe_state.valid = true; + + m_i_sync_pe_ctxt = m_curr_packet_in->ISAChanged(); + if(m_curr_packet_in->CtxtIDUpdated()) + { + m_pe_context.context_id = m_curr_packet_in->getCtxtID(); + m_pe_context.ctxt_id_valid = 1; + m_i_sync_pe_ctxt = true; + } + + if(m_curr_packet_in->VMIDUpdated()) + { + m_pe_context.vmid = m_curr_packet_in->getVMID(); + m_pe_context.vmid_valid = 1; + m_i_sync_pe_ctxt = true; + } + m_pe_context.security_level = m_curr_packet_in->getNS() ? ocsd_sec_nonsecure : ocsd_sec_secure; + + if(m_need_isync || (m_curr_packet_in->iSyncReason() != iSync_Periodic)) + { + m_output_elem.setType(OCSD_GEN_TRC_ELEM_TRACE_ON); + m_output_elem.trace_on_reason = TRACE_ON_NORMAL; + if(m_curr_packet_in->iSyncReason() == iSync_TraceRestartAfterOverflow) + m_output_elem.trace_on_reason = TRACE_ON_OVERFLOW; + else if(m_curr_packet_in->iSyncReason() == iSync_DebugExit) + m_output_elem.trace_on_reason = TRACE_ON_EX_DEBUG; + if(m_curr_packet_in->hasCC()) + m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); + resp = outputTraceElement(m_output_elem); + } + else + { + // periodic - no output + m_i_sync_pe_ctxt = false; + } + m_need_isync = false; // got 1st Isync - can continue to process data. + m_return_stack.flush(); + } + + if(m_i_sync_pe_ctxt && OCSD_DATA_RESP_IS_CONT(resp)) + { + m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + m_output_elem.setContext(m_pe_context); + m_output_elem.setISA(m_curr_pe_state.isa); + resp = outputTraceElement(m_output_elem); + m_i_sync_pe_ctxt = false; + } + + // if wait and still stuff to process.... + if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_i_sync_pe_ctxt)) + m_curr_state = CONT_ISYNC; + + return resp; +} + +// change of address and/or exception in program flow. +// implies E atom before the branch if none exception. +ocsd_datapath_resp_t TrcPktDecodePtm::processBranch() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + // initial pass - decoding packet. + if(m_curr_state == DECODE_PKTS) + { + // specific behviour if this is an exception packet. + if(m_curr_packet_in->isBranchExcepPacket()) + { + // exception - record address and output exception packet. + m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION); + m_output_elem.exception_number = m_curr_packet_in->excepNum(); + m_output_elem.excep_ret_addr = 0; + if(m_curr_pe_state.valid) + { + m_output_elem.excep_ret_addr = 1; + m_output_elem.en_addr = m_curr_pe_state.instr_addr; + } + // could be an associated cycle count + if(m_curr_packet_in->hasCC()) + m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); + + // output the element + resp = outputTraceElement(m_output_elem); + } + else + { + // branch address only - implies E atom - need to output a range element based on the atom. + if(m_curr_pe_state.valid) + resp = processAtomRange(ATOM_E,"BranchAddr"); + } + + // now set the branch address for the next time. + m_curr_pe_state.isa = m_curr_packet_in->getISA(); + m_curr_pe_state.instr_addr = m_curr_packet_in->getAddrVal(); + m_curr_pe_state.valid = true; + } + + // atom range may return with NACC pending + checkPendingNacc(resp); + + // if wait and still stuff to process.... + if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending)) + m_curr_state = CONT_BRANCH; + + return resp; +} + +// effectively completes a range prior to exception or after many bytes of trace (>4096) +// +ocsd_datapath_resp_t TrcPktDecodePtm::processWPUpdate() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + // if we need an address to run from then the WPUpdate will not form a range as + // we do not have a start point - still waiting for branch or other address packet + if(m_curr_pe_state.valid) + { + // WP update implies atom - use E, we cannot be sure if the instruction passed its condition codes + // - though it doesn't really matter as it is not a branch so cannot change flow. + resp = processAtomRange(ATOM_E,"WP update",TRACE_TO_ADDR_INCL,m_curr_packet_in->getAddrVal()); + } + + // atom range may return with NACC pending + checkPendingNacc(resp); + + // if wait and still stuff to process.... + if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending)) + m_curr_state = CONT_WPUP; + + return resp; +} + +// a single atom packet can result in multiple range outputs...need to be re-entrant in case we get a wait response. +// also need to handle nacc response from instruction walking routine +// +ocsd_datapath_resp_t TrcPktDecodePtm::processAtom() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + // loop to process all the atoms in the packet + while(m_atoms.numAtoms() && m_curr_pe_state.valid && OCSD_DATA_RESP_IS_CONT(resp)) + { + resp = processAtomRange(m_atoms.getCurrAtomVal(),"atom"); + if(!m_curr_pe_state.valid) + m_atoms.clearAll(); + else + m_atoms.clearAtom(); + } + + // bad address may mean a nacc needs sending + checkPendingNacc(resp); + + // if wait and still stuff to process.... + if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending || m_atoms.numAtoms())) + m_curr_state = CONT_ATOM; + + return resp; +} + + void TrcPktDecodePtm::checkPendingNacc(ocsd_datapath_resp_t &resp) + { + if(m_mem_nacc_pending && 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_index_curr_pkt,m_output_elem); + m_mem_nacc_pending = false; + } + } + +// given an atom element - walk the code and output a range or mark nacc. +ocsd_datapath_resp_t TrcPktDecodePtm::processAtomRange(const ocsd_atm_val A, const char *pkt_msg, const waypoint_trace_t traceWPOp /*= TRACE_WAYPOINT*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + bool bWPFound = false; + std::ostringstream oss; + ocsd_err_t err = OCSD_OK; + + m_instr_info.instr_addr = m_curr_pe_state.instr_addr; + m_instr_info.isa = m_curr_pe_state.isa; + + // set type (which resets out-elem) before traceInstrToWP modifies out-elem values + m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); + + err = traceInstrToWP(bWPFound,traceWPOp,nextAddrMatch); + if(err != OCSD_OK) + { + if(err == OCSD_ERR_UNSUPPORTED_ISA) + { + m_curr_pe_state.valid = false; // need a new address packet + oss << "Warning: unsupported instruction set processing " << pkt_msg << " packet."; + LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_index_curr_pkt,m_CSID,oss.str())); + // wait for next address + return OCSD_RESP_WARN_CONT; + } + else + { + resp = OCSD_RESP_FATAL_INVALID_DATA; + oss << "Error processing " << pkt_msg << " packet."; + LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,m_index_curr_pkt,m_CSID,oss.str())); + return resp; + } + } + + if(bWPFound) + { + // save recorded next instuction address + ocsd_vaddr_t nextAddr = m_instr_info.instr_addr; + + // action according to waypoint type and atom value + switch(m_instr_info.type) + { + case OCSD_INSTR_BR: + if (A == ATOM_E) + { + m_instr_info.instr_addr = m_instr_info.branch_addr; + if (m_instr_info.is_link) + m_return_stack.push(nextAddr,m_instr_info.isa); + } + break; + + // For PTM -> branch addresses imply E atom, N atom does not need address (return stack will require this) + case OCSD_INSTR_BR_INDIRECT: + if (A == ATOM_E) + { + // atom on indirect branch - either implied E from a branch address packet, or return stack if active. + + // indirect branch taken - need new address -if the current packet is a branch address packet this will be sorted. + m_curr_pe_state.valid = false; + + // if return stack and the incoming packet is an atom. + if (m_return_stack.is_active() && (m_curr_packet_in->getType() == PTM_PKT_ATOM)) + { + // we have an E atom packet and return stack value - set address from return stack + m_instr_info.instr_addr = m_return_stack.pop(m_instr_info.next_isa); + + if (m_return_stack.overflow()) + { + resp = OCSD_RESP_FATAL_INVALID_DATA; + oss << "Return stack error processing " << pkt_msg << " packet."; + LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_RET_STACK_OVERFLOW, m_index_curr_pkt, m_CSID, oss.str())); + return resp; + } + else + m_curr_pe_state.valid = true; + } + if(m_instr_info.is_link) + m_return_stack.push(nextAddr, m_instr_info.isa); + } + break; + } + + m_output_elem.setLastInstrInfo((A == ATOM_E),m_instr_info.type, m_instr_info.sub_type,m_instr_info.instr_size); + m_output_elem.setISA(m_curr_pe_state.isa); + if(m_curr_packet_in->hasCC()) + m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); + m_output_elem.setLastInstrCond(m_instr_info.is_conditional); + resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); + + m_curr_pe_state.instr_addr = m_instr_info.instr_addr; + m_curr_pe_state.isa = m_instr_info.next_isa; + } + else + { + // no waypoint - likely inaccessible memory range. + m_curr_pe_state.valid = false; // need an address update + + if(m_output_elem.st_addr != m_output_elem.en_addr) + { + // some trace before we were out of memory access range + m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type,m_instr_info.instr_size); + m_output_elem.setISA(m_curr_pe_state.isa); + m_output_elem.setLastInstrCond(m_instr_info.is_conditional); + resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); + } + } + return resp; +} + +ocsd_err_t TrcPktDecodePtm::traceInstrToWP(bool &bWPFound, const waypoint_trace_t traceWPOp /*= TRACE_WAYPOINT*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) +{ + uint32_t opcode; + uint32_t bytesReq; + ocsd_err_t err = OCSD_OK; + ocsd_vaddr_t curr_op_address; + + ocsd_mem_space_acc_t mem_space = (m_pe_context.security_level == ocsd_sec_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; + + while(!bWPFound && !m_mem_nacc_pending) + { + // start off by reading next opcode; + bytesReq = 4; + curr_op_address = m_instr_info.instr_addr; // save the start address for the current opcode + err = accessMemory(m_instr_info.instr_addr,mem_space,&bytesReq,(uint8_t *)&opcode); + if(err != OCSD_OK) break; + + if(bytesReq == 4) // got data back + { + m_instr_info.opcode = opcode; + err = instrDecode(&m_instr_info); + if(err != OCSD_OK) break; + + // increment address - may be adjusted by direct branch value later + m_instr_info.instr_addr += m_instr_info.instr_size; + + // 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++; + + m_output_elem.last_i_type = m_instr_info.type; + // either walking to match the next instruction address or a real waypoint + if(traceWPOp != TRACE_WAYPOINT) + { + if(traceWPOp == TRACE_TO_ADDR_EXCL) + bWPFound = (m_output_elem.en_addr == nextAddrMatch); + else + bWPFound = (curr_op_address == nextAddrMatch); + } + else + bWPFound = (m_instr_info.type != OCSD_INSTR_OTHER); + } + else + { + // not enough memory accessible. + m_mem_nacc_pending = true; + m_nacc_addr = m_instr_info.instr_addr; + } + } + return err; +} + +/* End of File trc_pkt_decode_ptm.cpp */ |