diff options
Diffstat (limited to 'decoder/source')
20 files changed, 1497 insertions, 1217 deletions
| diff --git a/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp b/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp index 0a15a33c42fb..e68a73fd9e0d 100644 --- a/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp +++ b/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp @@ -130,6 +130,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT()      try {          pElem = GetNextOpElem(resp);          pElem->setType(OCSD_GEN_TRC_ELEM_EO_TRACE); +        pElem->setUnSyncEOTReason(UNSYNC_EOT);          m_outputElemList.commitAllPendElem();          m_curr_state = SEND_PKTS;          resp = m_outputElemList.sendElements(); @@ -147,6 +148,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT()  ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    m_unsync_info = UNSYNC_RESET_DECODER;      resetDecoder();      return resp;  } @@ -199,6 +201,7 @@ void TrcPktDecodeEtmV3::initDecoder()  {      m_CSID = 0;      resetDecoder(); +    m_unsync_info = UNSYNC_INIT_DECODER;      m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt());      m_outputElemList.initSendIf(getTraceElemOutAttachPt());  } @@ -355,6 +358,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone)      catch(ocsdError &err)      {          LogError(err); +        m_unsync_info = UNSYNC_BAD_PACKET;          resetDecoder(); // mark decoder as unsynced - dump any current state.          pktDone = true;      } @@ -362,6 +366,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone)      {          LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,m_CSID,"Bad Packet sequence."));          resp = OCSD_RESP_FATAL_SYS_ERR; +        m_unsync_info = UNSYNC_BAD_PACKET;          resetDecoder(); // mark decoder as unsynced - dump any current state.          pktDone = true;      } @@ -375,11 +380,13 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::sendUnsyncPacket()      try {          pElem = GetNextOpElem(resp);          pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC); +        pElem->setUnSyncEOTReason(m_unsync_info);          resp = m_outputElemList.sendElements();      }      catch(ocsdError &err)      {          LogError(err); +        m_unsync_info = UNSYNC_BAD_PACKET;          resetDecoder(); // mark decoder as unsynced - dump any current state.      }      return resp; @@ -464,6 +471,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC, const bo      catch(ocsdError &err)      {          LogError(err); +        m_unsync_info = UNSYNC_BAD_PACKET;          resetDecoder(); // mark decoder as unsynced - dump any current state.      }      return resp; @@ -531,6 +539,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processBranchAddr()          catch(ocsdError &err)          {              LogError(err); +            m_unsync_info = UNSYNC_BAD_PACKET;              resetDecoder(); // mark decoder as unsynced - dump any current state.          }      }        @@ -647,6 +656,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPHdr()      catch(ocsdError &err)      {          LogError(err); +        m_unsync_info = UNSYNC_BAD_PACKET;          resetDecoder(); // mark decoder as unsynced - dump any current state.      }      return resp; diff --git a/decoder/source/etmv4/trc_etmv4_stack_elem.cpp b/decoder/source/etmv4/trc_etmv4_stack_elem.cpp index 8916c7dc350d..8e9ba9ac43ca 100644 --- a/decoder/source/etmv4/trc_etmv4_stack_elem.cpp +++ b/decoder/source/etmv4/trc_etmv4_stack_elem.cpp @@ -90,13 +90,17 @@ TrcStackElemExcept *EtmV4P0Stack::createExceptElem(const ocsd_etmv4_i_pkt_type r      return pElem;  } -TrcStackElemCtxt *EtmV4P0Stack::createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context) +TrcStackElemCtxt *EtmV4P0Stack::createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context, const uint8_t IS, const bool back /*= false*/)  {      TrcStackElemCtxt *pElem = new (std::nothrow) TrcStackElemCtxt(root_pkt, root_index);      if (pElem)      {          pElem->setContext(context); -        push_front(pElem); +        pElem->setIS(IS); +        if (back) +            push_back(pElem); +        else +            push_front(pElem);      }      return pElem; @@ -113,4 +117,40 @@ TrcStackElemAddr *EtmV4P0Stack::createAddrElem(const ocsd_etmv4_i_pkt_type root_      return pElem;  } +TrcStackQElem *EtmV4P0Stack::createQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const int count) +{ +    TrcStackQElem *pElem = new (std::nothrow) TrcStackQElem(root_pkt, root_index); +    if (pElem) +    { +        pElem->setInstrCount(count); +        push_front(pElem); +    } +    return pElem; +} + +// iteration functions +void EtmV4P0Stack::from_front_init() +{ +    m_iter = m_P0_stack.begin(); +} + +TrcStackElem *EtmV4P0Stack::from_front_next() +{ +    TrcStackElem *pElem = 0; +    if (m_iter != m_P0_stack.end()) +    { +        pElem = *m_iter++; +    } +    return pElem; +} + +void EtmV4P0Stack::erase_curr_from_front() +{ +    std::deque<TrcStackElem *>::iterator erase_iter; +    erase_iter = m_iter; +    erase_iter--; +    m_P0_stack.erase(erase_iter); +} + +  /* End of file trc_etmv4_stack_elem.cpp */ diff --git a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp index 2eb6cbc3f5bf..393046ba23d1 100644 --- a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp +++ b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp @@ -5,7 +5,6 @@   * \copyright  Copyright (c) 2015, 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: @@ -63,6 +62,7 @@ TrcPktDecodeEtmV4I::~TrcPktDecodeEtmV4I()  ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    ocsd_err_t err = OCSD_OK;      bool bPktDone = false;      while(!bPktDone) @@ -71,9 +71,18 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()          {          case NO_SYNC:              // output the initial not synced packet to the sink -            m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); -            resp = outputTraceElement(m_output_elem); -            m_curr_state = WAIT_SYNC; +            err = m_out_elem.resetElemStack(); +            if (!err) +                err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_NO_SYNC); +            if (!err) +            { +                outElem().setUnSyncEOTReason(m_unsync_eot_info); +                resp = m_out_elem.sendElements(); +                m_curr_state = WAIT_SYNC; +            } +            else +                resp = OCSD_RESP_FATAL_SYS_ERR; +              // fall through to check if the current packet is the async we are waiting for.              break; @@ -96,13 +105,31 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()              break;          case DECODE_PKTS: -            resp = decodePacket(bPktDone);  // this may change the state to commit elem; -            break; +            // this may change the state to RESOLVE_ELEM if required; +            err = decodePacket(); +            if (err) +            { +#ifdef OCSD_WARN_UNSUPPORTED +                if (err == OCSD_ERR_UNSUPP_DECODE_PKT) +                    resp = OCSD_RESP_WARN_CONT; +                else +#else +                resp = OCSD_RESP_FATAL_INVALID_DATA; +#endif -        case COMMIT_ELEM: -            resp = commitElements(bPktDone); // this will change the state to DECODE_PKTS once all elem committed. +                bPktDone = true; +            } +            else if (m_curr_state != RESOLVE_ELEM) +                bPktDone = true;              break; +        case RESOLVE_ELEM: +            // this will change the state to DECODE_PKTS once required elem resolved &  +            // needed generic packets output +            resp = resolveElements();  +            if ((m_curr_state == DECODE_PKTS) || (!OCSD_DATA_RESP_IS_CONT(resp))) +                bPktDone = true; +            break;          }      }      return resp; @@ -111,14 +138,21 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()  ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onEOT()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; -    m_flush_EOT = true; -    resp = flushEOT(); +    ocsd_err_t err; +    if ((err = commitElemOnEOT()) != OCSD_OK) +    { +        resp = OCSD_RESP_FATAL_INVALID_DATA; +        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Error flushing element stack at end of trace data.")); +    } +    else +        resp = m_out_elem.sendElements();      return resp;  }  ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onReset()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    m_unsync_eot_info = UNSYNC_RESET_DECODER;      resetDecoder();      return resp;  } @@ -127,15 +161,10 @@ 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_info.proc != EXCEP_POP) -        resp = processException(); -    // continue ongoing output operations on comitted elements. -    else if(m_curr_state == COMMIT_ELEM) -        resp = processPacket();  -    // continue flushing at end of trace -    else if(m_flush_EOT) -        resp = flushEOT(); +    if (m_curr_state == RESOLVE_ELEM) +        resp = resolveElements(); +    else +        resp = m_out_elem.sendElements();      return resp;  } @@ -146,8 +175,14 @@ ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig()      // set some static config elements      m_CSID = m_config->getTraceID();      m_max_spec_depth = m_config->MaxSpecDepth(); + +    // elements associated with data trace +#ifdef DATA_TRACE_SUPPORTED      m_p0_key_max = m_config->P0_Key_Max();      m_cond_key_max_incr = m_config->CondKeyMaxIncr(); +#endif + +    m_out_elem.initCSID(m_CSID);      // set up static trace instruction decode elements      m_instr_info.dsb_dmb_waypoints = 0; @@ -168,12 +203,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig()      // check config compatible with current decoder support level.      // at present no data trace, no spec depth, no return stack, no QE      // Remove these checks as support is added. -    if(m_max_spec_depth != 0) -    { -        err = OCSD_ERR_HW_CFG_UNSUPP; -        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : None-zero speculation depth not supported")); -    } -    else if(m_config->enabledDataTrace()) +    if(m_config->enabledDataTrace())      {          err = OCSD_ERR_HW_CFG_UNSUPP;          LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Data trace elements not supported")); @@ -188,15 +218,9 @@ ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig()          err = OCSD_ERR_HW_CFG_UNSUPP;          LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace on conditional non-branch elements not supported."));      } -    else if(m_config->enabledQE()) -    { -        err = OCSD_ERR_HW_CFG_UNSUPP; -        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace using Q elements not supported.")); -    }      return err;  } -  /************* local decode methods */  void TrcPktDecodeEtmV4I::initDecoder()  { @@ -205,12 +229,17 @@ void TrcPktDecodeEtmV4I::initDecoder()      /* init elements that get set by config */      m_max_spec_depth = 0; -    m_p0_key_max = 0;      m_CSID = 0; -    m_cond_key_max_incr = 0;      m_IASize64 = false; +    // elements associated with data trace +#ifdef DATA_TRACE_SUPPORTED +    m_p0_key_max = 0; +    m_cond_key_max_incr = 0; +#endif +      // reset decoder state to unsynced +    m_unsync_eot_info = UNSYNC_INIT_DECODER;      resetDecoder();  } @@ -224,30 +253,36 @@ void TrcPktDecodeEtmV4I::resetDecoder()      m_is_64bit = false;      m_cc_threshold = 0;      m_curr_spec_depth = 0; -    m_p0_key = 0; -    m_cond_c_key = 0; -    m_cond_r_key = 0;      m_need_ctxt = true;      m_need_addr = true; -    m_except_pending_addr = false; -    m_mem_nacc_pending = false; +    m_elem_pending_addr = false;      m_prev_overflow = false;      m_P0_stack.delete_all(); -    m_output_elem.init(); -    m_excep_info.proc = EXCEP_POP; -    m_flush_EOT = false; +    m_out_elem.resetElemStack(); +    m_last_IS = 0; +    clearElemRes(); + +    // elements associated with data trace +#ifdef DATA_TRACE_SUPPORTED +    m_p0_key = 0; +    m_cond_c_key = 0; +    m_cond_r_key = 0; +#endif +} + +void TrcPktDecodeEtmV4I::onFirstInitOK() +{ +    // once init, set the output element interface to the out elem list. +    m_out_elem.initSendIf(this->getTraceElemOutAttachPt());  } -// this function can output an immediate generic element if this covers the complete packet decode,  -// or stack P0 and other elements for later processing on commit or cancel. -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) +// Changes a packet into stack of trace elements - these will be resolved and output later +ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()  { +    ocsd_err_t err = OCSD_OK;      bool bAllocErr = false; -    ocsd_datapath_resp_t resp = OCSD_RESP_CONT; -    Complete = true;      bool is_addr = false; -    bool is_except = false; -     +      switch(m_curr_packet_in->getType())      {      case ETM4_PKT_I_ASYNC: // nothing to do with this packet. @@ -266,13 +301,6 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)          }          break; -    case ETM4_PKT_I_OVERFLOW: -        { -            if (m_P0_stack.createParamElemNoParam(P0_OVERFLOW, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) -                bAllocErr = true; -        } -        break; -      case ETM4_PKT_I_ATOM_F1:      case ETM4_PKT_I_ATOM_F2:      case ETM4_PKT_I_ATOM_F3: @@ -289,7 +317,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)      case ETM4_PKT_I_CTXT:          { -            if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext()) == 0) +            if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)                  bAllocErr = true;          }          break; @@ -299,7 +327,8 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)              etmv4_addr_val_t addr;              addr.val = m_curr_packet_in->getAddrVal(); -            addr.isa = m_curr_packet_in->getAddrIS(); +            addr.isa = m_last_IS = m_curr_packet_in->getAddrIS(); +              if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)                  bAllocErr = true;              is_addr = true; @@ -311,7 +340,8 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)      case ETM4_PKT_I_ADDR_CTXT_L_32IS0:      case ETM4_PKT_I_ADDR_CTXT_L_32IS1:              { -            if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext()) == 0) +            m_last_IS = m_curr_packet_in->getAddrIS(); +            if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)                  bAllocErr = true;          }      case ETM4_PKT_I_ADDR_L_32IS0: @@ -324,7 +354,8 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)              etmv4_addr_val_t addr;              addr.val = m_curr_packet_in->getAddrVal(); -            addr.isa = m_curr_packet_in->getAddrIS(); +            addr.isa = m_last_IS = m_curr_packet_in->getAddrIS(); +              if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)                  bAllocErr = true;              is_addr = true; @@ -339,10 +370,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)                                              m_curr_packet_in->exception_info.exceptionType) == 0)                  bAllocErr = true;              else -            { -                m_except_pending_addr = true;  // wait for following packets before marking for commit. -                is_except = true; -            } +                m_elem_pending_addr = true;  // wait for following packets before marking for commit.          }          break; @@ -411,15 +439,67 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)          break;      case ETM4_PKT_I_BAD_SEQUENCE: -        resp = handleBadPacket("Bad byte sequence in packet."); +        err = handleBadPacket("Bad byte sequence in packet.");          break;      case ETM4_PKT_I_BAD_TRACEMODE: -        resp = handleBadPacket("Invalid packet type for trace mode."); +        err = handleBadPacket("Invalid packet type for trace mode.");          break;      case ETM4_PKT_I_RESERVED: -        resp = handleBadPacket("Reserved packet header"); +        err = handleBadPacket("Reserved packet header"); +        break; + +    // speculation  +    case ETM4_PKT_I_MISPREDICT: +    case ETM4_PKT_I_CANCEL_F1_MISPRED: +    case ETM4_PKT_I_CANCEL_F2: +    case ETM4_PKT_I_CANCEL_F3: +        m_elem_res.mispredict = true; +        if (m_curr_packet_in->getNumAtoms()) +        { +            if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0) +                bAllocErr = true; +            else +                m_curr_spec_depth += m_curr_packet_in->getNumAtoms(); +        } + +    case ETM4_PKT_I_CANCEL_F1: +        m_elem_res.P0_cancel = m_curr_packet_in->getCancelElem(); +        break; +                                 +    case ETM4_PKT_I_COMMIT: +        m_elem_res.P0_commit = m_curr_packet_in->getCommitElem(); +        break; + +    case ETM4_PKT_I_OVERFLOW: +        m_prev_overflow = true; +    case ETM4_PKT_I_DISCARD: +        m_curr_spec_depth = 0; +        m_elem_res.discard = true; +        break; + +        /* Q packets */ +    case ETM4_PKT_I_Q: +        { +            TrcStackQElem *pQElem = m_P0_stack.createQElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->Q_pkt.q_count); +            if (pQElem) +            { +                if (m_curr_packet_in->Q_pkt.addr_present) +                { +                    etmv4_addr_val_t addr; + +                    addr.val = m_curr_packet_in->getAddrVal(); +                    addr.isa = m_curr_packet_in->getAddrIS(); +                    pQElem->setAddr(addr); +                    m_curr_spec_depth++; +                } +                else +                    m_elem_pending_addr = true; +            } +            else +                bAllocErr = true; +        }          break;      /*** presently unsupported packets ***/ @@ -432,90 +512,134 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)      case ETM4_PKT_I_COND_RES_F2:      case ETM4_PKT_I_COND_RES_F3:      case ETM4_PKT_I_COND_RES_F4: -    // speculation  -    case ETM4_PKT_I_CANCEL_F1: -    case ETM4_PKT_I_CANCEL_F2: -    case ETM4_PKT_I_CANCEL_F3: -    case ETM4_PKT_I_COMMIT: -    case ETM4_PKT_I_MISPREDICT: -    case ETM4_PKT_I_DISCARD:      // data synchronisation markers      case ETM4_PKT_I_NUM_DS_MKR:      case ETM4_PKT_I_UNNUM_DS_MKR: -    /* Q packets */ -    case ETM4_PKT_I_Q: -        resp = OCSD_RESP_FATAL_INVALID_DATA; -        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Unsupported packet type.")); +        // all currently unsupported +        { +        ocsd_err_severity_t sev = OCSD_ERR_SEV_ERROR; +#ifdef OCSD_WARN_UNSUPPORTED +        sev = OCSD_ERR_SEV_WARN; +        //resp = OCSD_RESP_WARN_CONT; +#else +        //resp = OCSD_RESP_FATAL_INVALID_DATA; +#endif +        err = OCSD_ERR_UNSUPP_DECODE_PKT; +        LogError(ocsdError(sev, err, "Data trace releated, unsupported packet type.")); +        }          break;      default:          // any other packet - bad packet error -        resp = OCSD_RESP_FATAL_INVALID_DATA; -        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Unknown packet type.")); +        err = OCSD_ERR_BAD_DECODE_PKT; +        LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Unknown packet type."));          break; -      } -    // we need to wait for following address after exception  +    // we need to wait for following address after certain packets      // - work out if we have seen enough here... -    if(m_except_pending_addr && !is_except) +    if (is_addr && m_elem_pending_addr)      { -        m_except_pending_addr = false;  //next packet has to be an address -        // exception packet sequence complete -        if(is_addr) -        { -            m_curr_spec_depth++;   // exceptions are P0 elements so up the spec depth to commit if needed. -        } -        else -        { -            resp = OCSD_RESP_FATAL_INVALID_DATA; -            LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Expected Address packet to follow exception packet.")); -        } +        m_curr_spec_depth++;  // increase spec depth for element waiting on address. +        m_elem_pending_addr = false;  // can't be waiting on both      }      if(bAllocErr)      { -        resp = OCSD_RESP_FATAL_SYS_ERR; +        err = OCSD_ERR_MEM;          LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error."));             }      else if(m_curr_spec_depth > m_max_spec_depth)      {          // auto commit anything above max spec depth           // (this will auto commit anything if spec depth not supported!) -        m_P0_commit = m_curr_spec_depth - m_max_spec_depth; -        m_curr_state = COMMIT_ELEM; -        Complete = false;   // force the processing of the commit elements.         +        m_elem_res.P0_commit = m_curr_spec_depth - m_max_spec_depth;      } -    return resp; + +    if (!err && isElemForRes()) +        m_curr_state = RESOLVE_ELEM; +    return err;  }  void TrcPktDecodeEtmV4I::doTraceInfoPacket()  {      m_trace_info = m_curr_packet_in->getTraceInfo();      m_cc_threshold = m_curr_packet_in->getCCThreshold(); -    m_p0_key = m_curr_packet_in->getP0Key();      m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth(); + +    // elements associated with data trace +#ifdef DATA_TRACE_SUPPORTED +    m_p0_key = m_curr_packet_in->getP0Key(); +#endif +} + +/* Element resolution + * Commit or cancel elements as required + * Send any buffered output packets. + */ +ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements() +{ +    ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    bool Complete = false; + +    while (!Complete) +    { +        if (m_out_elem.numElemToSend()) +            resp = m_out_elem.sendElements(); +        else if (isElemForRes()) +        { +            ocsd_err_t err = OCSD_OK; +            if (m_elem_res.P0_commit) +                err = commitElements(); + +            if (!err && m_elem_res.P0_cancel) +                err = cancelElements(); + +            if (!err && m_elem_res.mispredict) +                err = mispredictAtom(); +             +            if (!err && m_elem_res.discard) +                err = discardElements(); + +            if (err != OCSD_OK) +                resp = OCSD_RESP_FATAL_INVALID_DATA; +        } +         +        // break out on error or wait request. +        if (!OCSD_DATA_RESP_IS_CONT(resp)) +            break; + +        // completion is nothing to send and nothing to commit +        Complete = !m_out_elem.numElemToSend() && !isElemForRes(); + +        // done all elements - need more packets. +        if (Complete) { +            // if we are still in resolve, the goto decode. +            if (m_curr_state == RESOLVE_ELEM) +                m_curr_state = DECODE_PKTS; +        }         +    } +    return resp;  }  /*   * Walks through the element stack, processing from oldest element to the newest,      according to the number of P0 elements that need committing. +   Build a stack of output elements in the process.   */ -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete) +ocsd_err_t TrcPktDecodeEtmV4I::commitElements()  { -    ocsd_datapath_resp_t resp = OCSD_RESP_CONT; -    bool bPause = false;    // pause commit operation  +    ocsd_err_t err = OCSD_OK;      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; +    int num_commit_req = m_elem_res.P0_commit;      ocsd_trc_index_t err_idx = 0; - -    Complete = true; // assume we exit due to completion of commit operation -      TrcStackElem *pElem = 0;    // stacked element pointer -    while(m_P0_commit && !bPause) +    err = m_out_elem.resetElemStack(); + +    while(m_elem_res.P0_commit && !err)      { -        if(m_P0_stack.size() > 0) +        if (m_P0_stack.size() > 0)          {              pElem = m_P0_stack.back();  // get oldest element              err_idx = pElem->getRootIndex(); // save index in case of error. @@ -524,11 +648,13 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)              {              // indicates a trace restart - beginning of trace or discontinuiuty              case P0_TRC_ON: -                m_output_elem.setType(OCSD_GEN_TRC_ELEM_TRACE_ON); -                m_output_elem.trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL; -                m_prev_overflow = false; -                resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem); -                m_return_stack.flush(); +                err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON); +                if (!err) +                { +                    m_out_elem.getCurrElem().trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL; +                    m_prev_overflow = false; +                    m_return_stack.flush(); +                }                  break;              case P0_ADDR: @@ -551,50 +677,20 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)                      etmv4_context_t ctxt = pCtxtElem->getContext();                      // check this is an updated context                      if(ctxt.updated) -                    { -                        updateContext(pCtxtElem); - -                        m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); -                        resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem); +                    {                         +                        err = m_out_elem.addElem(pElem->getRootIndex()); +                        if (!err) +                            updateContext(pCtxtElem, outElem());                      }                  }                  }                  break;              case P0_EVENT: -                { -                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -                if(pParamElem) -                    resp = this->outputEvent(pParamElem); -                } -                break; -              case P0_TS: -                { -                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -                if(pParamElem) -                    resp = outputTS(pParamElem,false); -                } -                break; -              case P0_CC: -                { -                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -                if(pParamElem) -                    resp = outputCC(pParamElem); -                } -                break; -              case P0_TS_CC: -                { -                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -                if(pParamElem) -                    resp = outputTS(pParamElem,true); -                } -                break; - -            case P0_OVERFLOW: -                m_prev_overflow = true; +                err = processTS_CC_EventElem(pElem);                  break;              case P0_ATOM: @@ -603,22 +699,21 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)                  if(pAtomElem)                  { -                    bool bContProcess = true; -                    while(!pAtomElem->isEmpty() && m_P0_commit && bContProcess) +                    while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err)                      {                          ocsd_atm_val atom = pAtomElem->commitOldest();                          // check if prev atom left us an indirect address target on the return stack -                        if ((resp = returnStackPop()) != OCSD_RESP_CONT) +                        if ((err = returnStackPop()) != OCSD_OK)                              break;                          // if address and context do instruction trace follower.                          // otherwise skip atom and reduce committed elements                          if(!m_need_ctxt && !m_need_addr)                          { -                            resp = processAtom(atom,bContProcess); +                            err = processAtom(atom);                          } -                        m_P0_commit--; // mark committed  +                        m_elem_res.P0_commit--; // mark committed                       }                      if(!pAtomElem->isEmpty())                             bPopElem = false;   // don't remove if still atoms to process. @@ -628,68 +723,63 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)              case P0_EXCEP:                  // check if prev atom left us an indirect address target on the return stack -                if ((resp = returnStackPop()) != OCSD_RESP_CONT) +                if ((err = returnStackPop()) != OCSD_OK)                      break; -                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--; +                err = processException();  // output trace + exception elements. +                m_elem_res.P0_commit--;                  break;              case P0_EXCEP_RET: -                m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET); -                resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem); -                if(pElem->isP0()) // are we on a core that counts ERET as P0? -                    m_P0_commit--; +                err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET); +                if (!err) +                { +                    if (pElem->isP0()) // are we on a core that counts ERET as P0? +                        m_elem_res.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--; +                    m_elem_res.P0_commit--; +                break; + +            case P0_Q: +                err = processQElement(); +                m_elem_res.P0_commit--;                  break;              }              if(bPopElem)                  m_P0_stack.delete_back();  // remove element from stack; - -            // if response not continue, then break out of the loop. -            if(!OCSD_DATA_RESP_IS_CONT(resp)) -            { -                bPause = true; -            }          }          else          {              // too few elements for commit operation - decode error. -            resp = OCSD_RESP_FATAL_INVALID_DATA; +            err = OCSD_ERR_COMMIT_PKT_OVERRUN;              LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_COMMIT_PKT_OVERRUN,err_idx,m_CSID,"Not enough elements to commit")); -            bPause = true;          }      } -    // done all elements - need more packets. -    if(m_P0_commit == 0)     -        m_curr_state = DECODE_PKTS; -      // reduce the spec depth by number of comitted elements -    m_curr_spec_depth -= (num_commit_req-m_P0_commit); -    return resp; +    m_curr_spec_depth -= (num_commit_req-m_elem_res.P0_commit); +    return err;  } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::returnStackPop() +ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop()  { -    ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    ocsd_err_t err = OCSD_OK;      ocsd_isa nextISA; -     +             if (m_return_stack.pop_pending())      {          ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA);          if (m_return_stack.overflow())          { -            resp = OCSD_RESP_FATAL_INVALID_DATA; -            LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_RET_STACK_OVERFLOW, "Trace Return Stack Overflow.")); +            err = OCSD_ERR_RET_STACK_OVERFLOW; +            LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Trace Return Stack Overflow."));          }          else          { @@ -698,20 +788,23 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::returnStackPop()              m_need_addr = false;          }      } -    return resp; +    return err;  } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::flushEOT() +ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT()  { -    ocsd_datapath_resp_t resp = OCSD_RESP_CONT; -    if(m_flush_EOT) +    ocsd_err_t err = OCSD_OK; +    TrcStackElem *pElem = 0; + +    // nothing outstanding - reset the stack before we add more +    if (!m_out_elem.numElemToSend()) +        m_out_elem.resetElemStack(); + +    while((m_P0_stack.size() > 0) && !err)      { -        TrcStackElem *pElem = 0; -        while(OCSD_DATA_RESP_IS_CONT(resp) && (m_P0_stack.size() > 0)) -        { -            // scan for outstanding events, TS and CC, before any outstanding -            // P0 commit elements. -            pElem = m_P0_stack.back(); +        // scan for outstanding events, TS and CC, that appear before any outstanding +        // uncommited P0 element. +        pElem = m_P0_stack.back();              switch(pElem->getP0Type())              { @@ -722,104 +815,293 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::flushEOT()              case P0_EXCEP:              case P0_EXCEP_RET:              case P0_OVERFLOW: +            case P0_Q:                  m_P0_stack.delete_all();                  break; -                //skip -            case P0_ADDR: -            case P0_CTXT: -                break; +            //skip +        case P0_ADDR: +        case P0_CTXT: +            break; -                // output -            case P0_EVENT: -                { -                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -                if(pParamElem) -                    resp = this->outputEvent(pParamElem); -                } -                break; +            // output +        case P0_EVENT: +        case P0_TS: +        case P0_CC: +        case P0_TS_CC: +            err = processTS_CC_EventElem(pElem); +            break; +        } +        m_P0_stack.delete_back(); +    } -            case P0_TS: -                { -                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -                if(pParamElem) -                    resp = outputTS(pParamElem,false); -                } -                break; +    if(!err) +    { +        err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_EO_TRACE); +        outElem().setUnSyncEOTReason(m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_EOT); +    } +    return err; +} -            case P0_CC: -                { -                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -                if(pParamElem) -                    resp = outputCC(pParamElem); +// cancel elements. These not output   +ocsd_err_t TrcPktDecodeEtmV4I::cancelElements() +{ +    ocsd_err_t err = OCSD_OK; +    bool P0StackDone = false;  // checked all P0 elements on the stack +    TrcStackElem *pElem = 0;   // stacked element pointer +    EtmV4P0Stack temp; +    int num_cancel_req = m_elem_res.P0_cancel; +     +    while (m_elem_res.P0_cancel) +    { +        //search the stack for the newest elements  +        if (!P0StackDone) +        { +            if (m_P0_stack.size() == 0) +                P0StackDone = true; +            else +            { +                // get the newest element +                pElem = m_P0_stack.front(); +                if (pElem->isP0()) { +                    if (pElem->getP0Type() == P0_ATOM) +                    {  +                        TrcStackElemAtom *pAtomElem = (TrcStackElemAtom *)pElem; +                        // atom - cancel N atoms +                        m_elem_res.P0_cancel -= pAtomElem->cancelNewest(m_elem_res.P0_cancel); +                        if (pAtomElem->isEmpty()) +                            m_P0_stack.delete_front();  // remove the element +                    } +                    else +                    { +                        m_elem_res.P0_cancel--; +                        m_P0_stack.delete_front();  // remove the element +                    } +                } else { +                // not P0, make a keep / remove decision +                    switch (pElem->getP0Type()) +                    { +                    // keep these  +                    case P0_EVENT: +                    case P0_TS: +                    case P0_CC: +                    case P0_TS_CC: +                        m_P0_stack.pop_front(false); +                        temp.push_back(pElem); +                        break; + +                    default: +                        m_P0_stack.delete_front(); +                        break; +                    }                  } -                break; +            } +        } +        // may have some unseen elements +        else if (m_unseen_spec_elem) +        { +            m_unseen_spec_elem--; +            m_elem_res.P0_cancel--; +        } +        // otherwise we have some sort of overrun +        else +        { +            // too few elements for commit operation - decode error. +            err = OCSD_ERR_COMMIT_PKT_OVERRUN; +            LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not enough elements to cancel")); +            m_elem_res.P0_cancel = 0; +            break; +        } +        +        if (temp.size()) +        { +            while (temp.size()) +            { +                pElem = temp.back(); +                m_P0_stack.push_front(pElem); +                temp.pop_back(false); +            } +        } +    } +    m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel; +    return err; +} -            case P0_TS_CC: +// mispredict an atom +ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom() +{ +    ocsd_err_t err = OCSD_OK; +    bool bFoundAtom = false, bDone = false; +    TrcStackElem *pElem = 0; +        +    m_P0_stack.from_front_init();   // init iterator at front. +    while (!bDone) +    { +        pElem = m_P0_stack.from_front_next(); +        if (pElem) +        { +            if (pElem->getP0Type() == P0_ATOM) +            { +                TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem); +                if (pAtomElem)                  { -                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -                if(pParamElem) -                    resp = outputTS(pParamElem,true); +                    pAtomElem->mispredictNewest(); +                    bFoundAtom = true;                  } -                break; +                bDone = true; +            } +            else if (pElem->getP0Type() == P0_ADDR) +            { +                // need to disregard any addresses that appear between mispredict and the atom in question +                m_P0_stack.erase_curr_from_front();              } -            m_P0_stack.delete_back();          } +        else +            bDone = true; +    } +    +    // if missed atom then either overrun error or mispredict on unseen element +    if (!bFoundAtom && !m_unseen_spec_elem) +    { +        err = OCSD_ERR_COMMIT_PKT_OVERRUN; +        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom")); +    } +    m_elem_res.mispredict = false; +    return err; +} + +// discard elements and flush +ocsd_err_t TrcPktDecodeEtmV4I::discardElements() +{ +    ocsd_err_t err = OCSD_OK; +    TrcStackElem *pElem = 0;   // stacked element pointer + +    // dump P0, elemnts - output remaining CC / TS +    while ((m_P0_stack.size() > 0) && !err) +    { +        pElem = m_P0_stack.back(); +        err = processTS_CC_EventElem(pElem); +        m_P0_stack.delete_back(); +    } + +    // clear all speculation info +    clearElemRes();  +    m_curr_spec_depth = 0; + +    // set decode state +    m_curr_state = NO_SYNC; +    m_unsync_eot_info = m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_DISCARD; + +    // unsync so need context & address. +    m_need_ctxt = true; +    m_need_addr = true; +    m_elem_pending_addr = false; +    return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem) +{ +    ocsd_err_t err = OCSD_OK; -        if(OCSD_DATA_RESP_IS_CONT(resp) && (m_P0_stack.size() == 0)) +    switch (pElem->getP0Type()) +    { +        case P0_EVENT: +        { +            TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); +            if (pParamElem) +                err = addElemEvent(pParamElem); +        } +        break; + +        case P0_TS: +        { +            TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); +            if (pParamElem) +                err = addElemTS(pParamElem, false); +        } +        break; + +        case P0_CC:          { -            m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE); -            resp = outputTraceElement(m_output_elem); -            m_flush_EOT = false; +            TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); +            if (pParamElem) +                err = addElemCC(pParamElem);          } +        break; + +        case P0_TS_CC: +        { +            TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); +            if (pParamElem) +                err = addElemTS(pParamElem, true); +        } +        break;      } -    return resp; +    return err; +  } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputCC(TrcStackElemParam *pParamElem) +ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem)  { -    m_output_elem.setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); -    m_output_elem.setCycleCount(pParamElem->getParam(0)); -    return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem); +    ocsd_err_t err = OCSD_OK; + +    err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_CYCLE_COUNT); +    if (!err) +        outElem().setCycleCount(pParamElem->getParam(0)); +    return err;  } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputTS(TrcStackElemParam *pParamElem, bool withCC) +ocsd_err_t TrcPktDecodeEtmV4I::addElemTS(TrcStackElemParam *pParamElem, bool withCC)  { -    m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP); -    m_output_elem.timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32); -    if(withCC) -        m_output_elem.setCycleCount(pParamElem->getParam(2)); -    return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem); +    ocsd_err_t err = OCSD_OK; + +    err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TIMESTAMP); +    if (!err) +    { +        outElem().timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32); +        if (withCC) +            outElem().setCycleCount(pParamElem->getParam(2)); +    } +    return err;  } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputEvent(TrcStackElemParam *pParamElem) +ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem)  { -    m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT); -    m_output_elem.trace_event.ev_type = EVENT_NUMBERED; -    m_output_elem.trace_event.ev_number = pParamElem->getParam(0); -    return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem); +    ocsd_err_t err = OCSD_OK; + +    err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EVENT); +    if (!err) +    { +        outElem().trace_event.ev_type = EVENT_NUMBERED; +        outElem().trace_event.ev_number = pParamElem->getParam(0); +    } +    return err;  } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputTraceRange(const bool executed, ocsd_trc_index_t index) +void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range,  +                                           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); +    elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); +    elemIn.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size); +    elemIn.setISA(m_instr_info.isa); +    elemIn.setLastInstrCond(m_instr_info.is_conditional); +    elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);      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_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)  { -    ocsd_datapath_resp_t resp = OCSD_RESP_CONT; -    TrcStackElem *pElem = m_P0_stack.back();  // get the atom element -    bool bWPFound = false;      ocsd_err_t err; -    bCont = true; +    TrcStackElem *pElem = m_P0_stack.back();  // get the atom element +    WP_res_t WPRes; +    instr_range_t addr_range; + +    // new element for this processed atom +    if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK) +        return err; -    err = traceInstrToWP(bWPFound); +    err = traceInstrToWP(addr_range, WPRes);      if(err != OCSD_OK)      {          if(err == OCSD_ERR_UNSUPPORTED_ISA) @@ -828,18 +1110,16 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bo               m_need_ctxt = true;               LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet."));                 // wait for next context -             return resp; +             return OCSD_OK;          }          else          { -            bCont = false; -            resp = OCSD_RESP_FATAL_INVALID_DATA;              LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));   -            return resp; +            return err;          }      } -    if(bWPFound) +    if(WPFound(WPRes))      {          //  save recorded next instuction address          ocsd_vaddr_t nextAddr = m_instr_info.instr_addr; @@ -867,125 +1147,113 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bo              }              break;          } -        resp = outputTraceRange((atom == ATOM_E), pElem->getRootIndex()); - +        setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex());      }      else      {          // no waypoint - likely inaccessible memory range.          m_need_addr = true; // need an address update  -        if(m_output_elem.st_addr != m_output_elem.en_addr) +        if(addr_range.st_addr != addr_range.en_addr)          {              // some trace before we were out of memory access range -            resp = outputTraceRange(true, pElem->getRootIndex()); +            setElemTraceRange(outElem(), addr_range, true, pElem->getRootIndex()); + +            // another element for the nacc... +            if (WPNacc(WPRes)) +                err = m_out_elem.addElem(pElem->getRootIndex());          } -        if(m_mem_nacc_pending && OCSD_DATA_RESP_IS_CONT(resp)) +        if(WPNacc(WPRes) && !err)          { -            m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); -            m_output_elem.st_addr = m_nacc_addr; -            resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem); -            m_mem_nacc_pending = false; +            outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); +            outElem().st_addr = m_instr_info.instr_addr;          }      } - -    if(!OCSD_DATA_RESP_IS_CONT(resp)) -        bCont = false; - -    return resp; +    return err;  }  // Exception processor -ocsd_datapath_resp_t  TrcPktDecodeEtmV4I::processException() +ocsd_err_t TrcPktDecodeEtmV4I::processException()  { -    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;  -    TrcStackElemExcept *pExceptElem; - -    m_excep_info.addr_b_tgt = false; -     -    if(m_excep_info.proc == EXCEP_POP) +    ocsd_err_t err; +    TrcStackElem *pElem = 0; +    TrcStackElemExcept *pExceptElem = 0; +    TrcStackElemAddr *pAddressElem = 0; +    TrcStackElemCtxt *pCtxtElem = 0; +    bool branch_target = false;    // exception address implies prior branch target address +    ocsd_vaddr_t excep_ret_addr; +    ocsd_trc_index_t excep_pkt_index; +    WP_res_t WPRes = WP_NOT_FOUND; + +    // grab the exception element off the stack +    pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back());  // get the exception element +    excep_pkt_index = pExceptElem->getRootIndex(); +    branch_target = pExceptElem->getPrevSame(); +    m_P0_stack.pop_back(); // remove the exception element + +    pElem = m_P0_stack.back();  // look at next element. +    if(pElem->getP0Type() == P0_CTXT)      { -        pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back());  // get the exception element -        TrcStackElemAddr *pAddressElem = 0; -        TrcStackElemCtxt *pCtxtElem = 0; -        TrcStackElem *pElem = 0; -     -        m_P0_stack.pop_back(); // remove the exception element -        pElem = m_P0_stack.back();  // look at next element. -        if(pElem->getP0Type() == P0_CTXT) -        { -            pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); -            m_P0_stack.pop_back(); // remove the context element -            pElem = m_P0_stack.back();  // next one should be an address element -        } +        pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); +        m_P0_stack.pop_back(); // remove the context element +        pElem = m_P0_stack.back();  // next one should be an address element +    } -        if(pElem->getP0Type() != P0_ADDR) +   if(pElem->getP0Type() != P0_ADDR) +   { +       // no following address element - indicate processing error.       +       LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index,m_CSID,"Address missing in exception packet.")); +       return OCSD_ERR_BAD_PACKET_SEQ; +   } +   else +   { +        // extract address +        pAddressElem = static_cast<TrcStackElemAddr *>(pElem); +        excep_ret_addr = pAddressElem->getAddr().val; + +        // see if there is an address + optional context element implied  +        // prior to the exception. +        if (branch_target)          { -            // no following address element - indicate processing error. -            resp = OCSD_RESP_FATAL_INVALID_DATA; -            LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,pExceptElem->getRootIndex(),m_CSID,"Address missing in exception packet."));   -        } -        else -        { -            // extract address -            pAddressElem = static_cast<TrcStackElemAddr *>(pElem); - -            // 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(); - -            // 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 +            // this was a branch target address - update current setting +            bool b64bit = m_instr_info.isa == ocsd_isa_aarch64;              if (pCtxtElem) { -                m_excep_info.proc = EXCEP_CTXT; -                updateContext(pCtxtElem); +                b64bit = pCtxtElem->getContext().SF;              } -            else if(m_excep_info.addr.val == m_instr_info.instr_addr) -                m_excep_info.proc = EXCEP_EXCEP; -            else -                m_excep_info.proc = EXCEP_RANGE; + +            // as the exception address was also a branch target address then update the  +            // current maintained address value. This also means that there is no range to +            // output before the exception packet. +            m_instr_info.instr_addr = excep_ret_addr;  +            m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ? +                    (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2; +            m_need_addr = false;          } -        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; -    } +    // need to output something - set up an element +    if ((err = m_out_elem.addElem(excep_pkt_index))) +        return err;   -    // output a range element -    if(m_excep_info.proc == EXCEP_RANGE)  +    // output a context element if present +    if (pCtxtElem)      { -        bool bWPFound = false; -        ocsd_err_t err; +        updateContext(pCtxtElem, outElem()); -        // last instr_info address is the start address -        m_output_elem.st_addr = m_instr_info.instr_addr; +        // used the element - need another for later stages +        if ((err = m_out_elem.addElem(excep_pkt_index))) +            return err; +    } + +    // if the preferred return address is not the end of the last output range... +    if (m_instr_info.instr_addr != excep_ret_addr) +    {         +        bool range_out = false; +        instr_range_t addr_range;          // look for match to return address. -        err = traceInstrToWP(bWPFound,true,m_excep_info.addr.val); +        err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr);          if(err != OCSD_OK)          { @@ -993,90 +1261,221 @@ ocsd_datapath_resp_t  TrcPktDecodeEtmV4I::processException()              {                  m_need_addr = true;                  m_need_ctxt = true; -                LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_excep_info.index,m_CSID,"Warning: unsupported instruction set processing exception packet."));   +                LogError(ocsdError(OCSD_ERR_SEV_WARN,err, excep_pkt_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_info.index,m_CSID,"Error processing exception packet."));   -                m_excep_info.proc = EXCEP_POP;  // nothing more to do, reset to start of exception handling +                LogError(ocsdError(OCSD_ERR_SEV_ERROR,err, excep_pkt_index,m_CSID,"Error processing exception packet."));              } +            return err;          } -        if(bWPFound) +        if(WPFound(WPRes))          {              // waypoint address found - output range -            resp = outputTraceRange(true, m_excep_info.index); -            m_excep_info.proc = EXCEP_EXCEP; +            setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); +            range_out = true;          }          else          {              // no waypoint - likely inaccessible memory range.              m_need_addr = true; // need an address update  -            if(m_output_elem.st_addr != m_output_elem.en_addr) +            if(addr_range.st_addr != addr_range.en_addr)              {                  // some trace before we were out of memory access range -                resp = outputTraceRange(true, m_excep_info.index); +                setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); +                range_out = true;              } +        } -            m_excep_info.proc = m_mem_nacc_pending ? EXCEP_NACC : EXCEP_EXCEP; +        // used the element need another for NACC or EXCEP. +        if (range_out) +        { +            if ((err = m_out_elem.addElem(excep_pkt_index))) +                return err;          } -    }   -     -    if((m_excep_info.proc == EXCEP_NACC) && OCSD_DATA_RESP_IS_CONT(resp)) +    } +    +    // watchpoint walk resulted in inaccessible memory call... +    if (WPNacc(WPRes))      { -        m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); -        m_output_elem.st_addr = m_nacc_addr; -        resp = outputTraceElementIdx(m_excep_info.index,m_output_elem); -        m_excep_info.proc = EXCEP_EXCEP; -        m_mem_nacc_pending = false; +         +        outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); +        outElem().st_addr = m_instr_info.instr_addr; + +        // used the element - need another for the final exception packet. +        if ((err = m_out_elem.addElem(excep_pkt_index))) +            return err;      } -    if((m_excep_info.proc == EXCEP_EXCEP) && OCSD_DATA_RESP_IS_CONT(resp)) +    // output exception element. +    outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION); + +    // add end address as preferred return address to end addr in element +    outElem().en_addr = excep_ret_addr; +    outElem().excep_ret_addr = 1; +    outElem().excep_ret_addr_br_tgt = branch_target; +    outElem().exception_number = pExceptElem->getExcepNum(); + +    m_P0_stack.delete_popped();     // clear the used elements from the stack +    return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::processQElement() +{ +    ocsd_err_t err = OCSD_OK; +    TrcStackQElem *pQElem; +    etmv4_addr_val_t QAddr; // address where trace restarts  +    int iCount = 0; + +    pQElem = dynamic_cast<TrcStackQElem *>(m_P0_stack.back());  // get the exception element +    m_P0_stack.pop_back(); // remove the Q element. + +    if (!pQElem->hasAddr())  // no address - it must be next on the stack....      { -        // 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_info.addr.val; -        m_output_elem.excep_ret_addr = 1; -        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; +        TrcStackElemAddr *pAddressElem = 0; +        TrcStackElemCtxt *pCtxtElem = 0; +        TrcStackElem *pElem = 0; + +        pElem = m_P0_stack.back();  // look at next element. +        if (pElem->getP0Type() == P0_CTXT) +        { +            pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); +            m_P0_stack.pop_back(); // remove the context element +            pElem = m_P0_stack.back();  // next one should be an address element +        } + +        if (pElem->getP0Type() != P0_ADDR) +        { +            // no following address element - indicate processing error. +            err = OCSD_ERR_BAD_PACKET_SEQ; +            LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Address missing in Q packet.")); +            m_P0_stack.delete_popped(); +            return err; +        } +        pAddressElem = dynamic_cast<TrcStackElemAddr *>(pElem); +        QAddr = pAddressElem->getAddr(); +        m_P0_stack.pop_back();  // remove the address element +        m_P0_stack.delete_popped(); // clear used elements + +        // return the context element for processing next time. +        if (pCtxtElem) +        { +            // need a new copy at the back - old one will be deleted as popped. +            m_P0_stack.createContextElem(pCtxtElem->getRootPkt(), pCtxtElem->getRootIndex(), pCtxtElem->getContext(),true); +        } +    } +    else +        QAddr = pQElem->getAddr(); + +    // process the Q element with address.  +    iCount = pQElem->getInstrCount(); + +    bool isBranch = false; + +    // need to output something - set up an element +    if ((err = m_out_elem.addElem(pQElem->getRootIndex()))) +        return err; + +    instr_range_t addr_range; +    addr_range.st_addr = addr_range.en_addr = m_instr_info.instr_addr; +    addr_range.num_instr = 0; + +    // walk iCount instructions +    for (int i = 0; i < iCount; i++) +    { +        uint32_t opcode; +        uint32_t bytesReq = 4; + +        err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(), &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; +            addr_range.num_instr++; + +            isBranch = (m_instr_info.type == OCSD_INSTR_BR) || +                (m_instr_info.type == OCSD_INSTR_BR_INDIRECT); + +            // on a branch no way of knowing if taken - bail out +            if (isBranch) +                break; +        } +        else +            break;  // missing memory + +    } + +    if (err == OCSD_OK) +    { +        bool inCompleteRange = true; +        if (iCount && (addr_range.num_instr == (unsigned)iCount)) +        { +            if ((m_instr_info.instr_addr == QAddr.val) ||    // complete range +                (isBranch)) // or ends on branch - only way we know if branch taken. +            { +                // output a range and continue +                inCompleteRange = false; +                // update the range decoded address in the output packet. +                addr_range.en_addr = m_instr_info.instr_addr; +                setElemTraceRange(outElem(), addr_range, true, pQElem->getRootIndex()); +            } +        } + +        if (inCompleteRange) +        {    +            // unknown instructions executed. +            addr_range.en_addr = QAddr.val; +            addr_range.num_instr = iCount; + +            outElem().setType(OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH); +            outElem().setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr); +            outElem().setISA(calcISA(m_is_64bit, QAddr.isa)); +        } + +        // after the Q element, tracing resumes at the address supplied +        SetInstrInfoInAddrISA(QAddr.val, QAddr.isa); +        m_need_addr = false; +    } +    else +    { +        // output error and halt decode. +        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Error processing Q packet")); +    } +    m_P0_stack.delete_popped(); +    return err;  }  void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa)  {      m_instr_info.instr_addr = addr_val; -    if(m_is_64bit) -        m_instr_info.isa = ocsd_isa_aarch64; -    else -        m_instr_info.isa = (isa == 0) ? ocsd_isa_arm : ocsd_isa_thumb2; +    m_instr_info.isa = calcISA(m_is_64bit, isa);  }  // trace an instruction range to a waypoint - and set next address to restart from. -ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) +ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WPRes, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/)  {      uint32_t opcode;      uint32_t bytesReq;      ocsd_err_t err = OCSD_OK; -    // TBD?: update mem space to allow for EL as well. -    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; +    range.st_addr = range.en_addr = m_instr_info.instr_addr; +    range.num_instr = 0; -    bWPFound = false; +    WPRes = WP_NOT_FOUND; -    while(!bWPFound && !m_mem_nacc_pending) +    while(WPRes == WP_NOT_FOUND)      {          // start off by reading next opcode;          bytesReq = 4; -        err = accessMemory(m_instr_info.instr_addr,mem_space,&bytesReq,(uint8_t *)&opcode); +        err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode);          if(err != OCSD_OK) break;          if(bytesReq == 4) // got data back @@ -1087,69 +1486,100 @@ ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceTo              // 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++; +            range.num_instr++;              // either walking to match the next instruction address or a real watchpoint -            if(traceToAddrNext) -                bWPFound = (m_output_elem.en_addr == nextAddrMatch); -            else -                bWPFound = (m_instr_info.type != OCSD_INSTR_OTHER); +            if (traceToAddrNext) +            { +                if (m_instr_info.instr_addr == nextAddrMatch)  +                    WPRes = WP_FOUND; +            } +            else if (m_instr_info.type != OCSD_INSTR_OTHER) +                WPRes = WP_FOUND;          }          else          {              // not enough memory accessible. -            m_mem_nacc_pending = true; -            m_nacc_addr = m_instr_info.instr_addr;            +            WPRes = WP_NACC;          }      } +    // update the range decoded address in the output packet. +    range.en_addr = m_instr_info.instr_addr;      return err;  } -void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem) +void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem)  {      etmv4_context_t ctxt = pCtxtElem->getContext(); -    // map to output element  and local saved state. +     +    elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + +    // map to output element and local saved state.      m_is_64bit = (ctxt.SF != 0); -    m_output_elem.context.bits64 = ctxt.SF; +    elem.context.bits64 = ctxt.SF;      m_is_secure = (ctxt.NS == 0); -    m_output_elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure; -    m_output_elem.context.exception_level = (ocsd_ex_level)ctxt.EL; -    m_output_elem.context.el_valid = 1; +    elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure; +    elem.context.exception_level = (ocsd_ex_level)ctxt.EL; +    elem.context.el_valid = 1;      if(ctxt.updated_c)      { -        m_output_elem.context.ctxt_id_valid = 1; -        m_context_id = m_output_elem.context.context_id = ctxt.ctxtID; +        elem.context.ctxt_id_valid = 1; +        m_context_id = elem.context.context_id = ctxt.ctxtID;      }      if(ctxt.updated_v)      { -        m_output_elem.context.vmid_valid = 1; -        m_vmid_id = m_output_elem.context.vmid = ctxt.VMID; +        elem.context.vmid_valid = 1; +        m_vmid_id = elem.context.vmid = ctxt.VMID;      } + +    // need to update ISA in case context follows address. +    elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS());      m_need_ctxt = false;  } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason) +ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason)  { -    ocsd_datapath_resp_t resp  = OCSD_RESP_CONT;    +    ocsd_err_t err = OCSD_OK; -    if(getComponentOpMode() && OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) +    if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)      {          // error out - stop decoding -        resp = OCSD_RESP_FATAL_INVALID_DATA; -        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,reason)); +        err = OCSD_ERR_BAD_DECODE_PKT; +        LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,reason));      }      else      { +        LogError(ocsdError(OCSD_ERR_SEV_WARN, OCSD_ERR_BAD_DECODE_PKT, reason));          // switch to unsync - clear decode state -        m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); -        resp = outputTraceElement(m_output_elem);          resetDecoder(); -        m_curr_state = WAIT_SYNC; +        m_curr_state = NO_SYNC; +        m_unsync_eot_info = UNSYNC_BAD_PACKET;      } -    return resp; +    return err;  } +inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace() +{ +    static ocsd_mem_space_acc_t SMemSpace[] = { +        OCSD_MEM_SPACE_EL1S, +        OCSD_MEM_SPACE_EL1S, +        OCSD_MEM_SPACE_EL2S, +        OCSD_MEM_SPACE_EL3 +    }; + +    static ocsd_mem_space_acc_t NSMemSpace[] = { +        OCSD_MEM_SPACE_EL1N, +        OCSD_MEM_SPACE_EL1N, +        OCSD_MEM_SPACE_EL2, +        OCSD_MEM_SPACE_EL3 +    }; + +    /* if no valid EL value - just use S/NS */ +    if (!outElem().context.el_valid) +        return  m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N; +     +    /* mem space according to EL + S/NS */ +    int el = (int)(outElem().context.exception_level) & 0x3; +    return m_is_secure ? SMemSpace[el] : NSMemSpace[el]; +}  /* End of File trc_pkt_decode_etmv4i.cpp */ diff --git a/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp b/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp deleted file mode 100644 index 58343b4117bf..000000000000 --- a/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * \file       trc_pkt_elem_etmv4d.cpp - * \brief      OpenCSD :  - *  - * \copyright  Copyright (c) 2015, 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 "opencsd/etmv4/trc_pkt_elem_etmv4d.h" - -EtmV4DTrcPacket::EtmV4DTrcPacket() -{ -} - -EtmV4DTrcPacket::~EtmV4DTrcPacket() -{ -} - -    // printing -void EtmV4DTrcPacket::toString(std::string &str) const -{ -} - -void EtmV4DTrcPacket::toStringFmt(const uint32_t fmtFlags, std::string &str) const -{ -} - - - -/* End of File trc_pkt_elem_etmv4d.cpp */ diff --git a/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp index 3f9d534db82c..853fde499a1b 100644 --- a/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp +++ b/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp @@ -161,6 +161,7 @@ void EtmV4ITrcPacket::toString(std::string &str) const          {              std::ostringstream oss;              oss << "; INFO=" << std::hex << "0x" << trace_info.val; +            oss << " { CC." << std::dec << trace_info.bits.cc_enabled << " }";              if (trace_info.bits.cc_enabled)                  oss << "; CC_THRESHOLD=" << std::hex << "0x" << cc_threshold;              str += oss.str(); @@ -176,8 +177,96 @@ void EtmV4ITrcPacket::toString(std::string &str) const              str += oss.str();          }          break; + +    case ETM4_PKT_I_CANCEL_F1: +        { +            std::ostringstream oss; +            oss << "; Cancel(" << std::dec << cancel_elements << ")"; +            str += oss.str(); +        } +        break; + +    case ETM4_PKT_I_CANCEL_F1_MISPRED: +        { +            std::ostringstream oss; +            oss << "; Cancel(" << std::dec << cancel_elements << "), Mispredict"; +            str += oss.str(); +        } +        break; + +    case ETM4_PKT_I_MISPREDICT: +        { +            std::ostringstream oss; +            oss << "; "; +            if (atom.num) { +                atomSeq(valStr); +                oss << "Atom: " << valStr << ", "; +            } +            oss << "Mispredict"; +            str += oss.str(); +        } +        break; + +    case ETM4_PKT_I_CANCEL_F2: +        { +            std::ostringstream oss; +            oss << "; "; +            if (atom.num) { +                atomSeq(valStr); +                oss << "Atom: " << valStr << ", "; +            } +            oss << "Cancel(1), Mispredict"; +            str += oss.str(); +        } +        break; + +    case ETM4_PKT_I_CANCEL_F3: +        { +            std::ostringstream oss; +            oss << "; "; +            if (atom.num) { +                oss << "Atom: E, "; +            } +            oss << "Cancel(" << std::dec << cancel_elements << "), Mispredict"; +            str += oss.str(); +        } +        break; + +    case ETM4_PKT_I_COMMIT: +        { +            std::ostringstream oss; +            oss << "; Commit(" << std::dec << commit_elements << ")"; +            str += oss.str(); +        } +        break; + +    case ETM4_PKT_I_Q: +        { +            std::ostringstream oss; +            if (Q_pkt.count_present) +            { +                oss << "; Count(" << std::dec << Q_pkt.q_count << ")"; +                str += oss.str(); +            } +            else +                str += "; Count(Unknown)"; + +            if (Q_pkt.addr_match)  +            { +                addrMatchIdx(valStr); +                str += "; " + valStr; +            } + +            if (Q_pkt.addr_present || Q_pkt.addr_match) +            { +                trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, (v_addr.pkt_bits < 64) ? v_addr.pkt_bits : 0); +                str += "; Addr=" + valStr; +            } +        } +        break;      } -} + +}     void EtmV4ITrcPacket::toStringFmt(const uint32_t fmtFlags, std::string &str) const  { @@ -296,6 +385,12 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co          pDesc = "Cancel Format 1.";          break; +    case ETM4_PKT_I_CANCEL_F1_MISPRED: +        pName = "I_CANCEL_F1_MISPRED"; +        pDesc = "Cancel Format 1 + Mispredict."; +        break; + +      case ETM4_PKT_I_MISPREDICT:          pName = "I_MISPREDICT";          pDesc = "Mispredict."; diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp b/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp deleted file mode 100644 index b8c4f819c2d3..000000000000 --- a/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * \file       trc_pkt_proc_etmv4.cpp - * \brief      OpenCSD :  - *  - * \copyright  Copyright (c) 2015, 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 "opencsd/etmv4/trc_pkt_proc_etmv4.h" -#include "trc_pkt_proc_etmv4i_impl.h" -#include "common/ocsd_error.h" - -#ifdef __GNUC__ -// G++ doesn't like the ## pasting -#define ETMV4I_PKTS_NAME "PKTP_ETMV4I" -#else -// VC++ is fine -#define ETMV4I_PKTS_NAME OCSD_CMPNAME_PREFIX_PKTPROC##"_ETMV4I" -#endif - -static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON; - -/***************************************************************************/ -/*******************ETM V4 INSTRUCTION *************************************/ -/***************************************************************************/ - -TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME),  -    m_pProcessor(0) -{ -    m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS; -} - -TrcPktProcEtmV4I::TrcPktProcEtmV4I(int instIDNum) : TrcPktProcBase(ETMV4I_PKTS_NAME, instIDNum), -    m_pProcessor(0) -{ -    m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS; -} - -TrcPktProcEtmV4I::~TrcPktProcEtmV4I() -{ -    if(m_pProcessor) -        delete m_pProcessor; -    m_pProcessor = 0; -} - -ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig() -{ -    if(m_pProcessor == 0) -    { -        m_pProcessor = new (std::nothrow) EtmV4IPktProcImpl(); -        if(m_pProcessor == 0) -        {            -            LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM)); -            return OCSD_ERR_MEM; -        } -        m_pProcessor->Initialise(this); -    } -    return m_pProcessor->Configure(m_config); -} - -ocsd_datapath_resp_t TrcPktProcEtmV4I::processData(  const ocsd_trc_index_t index, -                                                const uint32_t dataBlockSize, -                                                const uint8_t *pDataBlock, -                                                uint32_t *numBytesProcessed) -{ -    if(m_pProcessor) -        return m_pProcessor->processData(index,dataBlockSize,pDataBlock,numBytesProcessed); -    return OCSD_RESP_FATAL_NOT_INIT; -} - -ocsd_datapath_resp_t TrcPktProcEtmV4I::onEOT() -{ -    if(m_pProcessor) -        return m_pProcessor->onEOT(); -    return OCSD_RESP_FATAL_NOT_INIT; -} - -ocsd_datapath_resp_t TrcPktProcEtmV4I::onReset() -{ -    if(m_pProcessor) -        return m_pProcessor->onReset(); -    return OCSD_RESP_FATAL_NOT_INIT; -} - -ocsd_datapath_resp_t TrcPktProcEtmV4I::onFlush() -{ -    if(m_pProcessor) -        return m_pProcessor->onFlush(); -    return OCSD_RESP_FATAL_NOT_INIT; -} - -const bool TrcPktProcEtmV4I::isBadPacket() const -{ -    if(m_pProcessor) -        return m_pProcessor->isBadPacket(); -    return false; -} - -/* End of File trc_pkt_proc_etmv4.cpp */ diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h b/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h deleted file mode 100644 index 3be35bd12b55..000000000000 --- a/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * \file       trc_pkt_proc_etmv4d_impl.h - * \brief      OpenCSD :  - *  - * \copyright  Copyright (c) 2015, 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.  - */  - -#ifndef ARM_TRC_PKT_PROC_ETMV4D_IMPL_H_INCLUDED -#define ARM_TRC_PKT_PROC_ETMV4D_IMPL_H_INCLUDED - -#include "etmv4/trc_pkt_proc_etmv4.h" -#include "etmv4/trc_cmp_cfg_etmv4.h" - -class EtmV4DPktProcImpl -{ -public: -    EtmV4DPktProcImpl(); -    ~EtmV4DPktProcImpl(); - -    void Initialise(TrcPktProcEtmV4D *p_interface); - -    ocsd_err_t Configure(const EtmV4Config *p_config); - - -    ocsd_datapath_resp_t processData(  const ocsd_trc_index_t index, -                                        const uint32_t dataBlockSize, -                                        const uint8_t *pDataBlock, -                                        uint32_t *numBytesProcessed); -    ocsd_datapath_resp_t onEOT(); -    ocsd_datapath_resp_t onReset(); -    ocsd_datapath_resp_t onFlush(); - -protected: - -    bool m_isInit; -    TrcPktProcEtmV4D *m_interface;       /**< The interface to the other decode components */ -     -    EtmV4Config m_config; -}; - - -#endif // ARM_TRC_PKT_PROC_ETMV4D_IMPL_H_INCLUDED - -/* End of File trc_pkt_proc_etmv4d_impl.h */ diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp b/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp index 0607c192f879..d8c7d84667d1 100644 --- a/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp +++ b/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp @@ -1,8 +1,8 @@  /* - * \file       trc_pkt_proc_etmv4i_impl.cpp - * \brief      OpenCSD :  + * \file       trc_pkt_proc_etmv4i.cpp + * \brief      OpenCSD : Packet processor for ETMv4   *  - * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved. + * \copyright  Copyright (c) 2015, 2019, ARM Limited. All Rights Reserved.   */  /*  @@ -32,87 +32,58 @@   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.    */  -#include "trc_pkt_proc_etmv4i_impl.h" +#include "opencsd/etmv4/trc_pkt_proc_etmv4.h" +#include "common/ocsd_error.h" -/* Trace raw input buffer class */ -TraceRawBuffer::TraceRawBuffer() -{ -    m_bufSize = 0; -    m_bufProcessed = 0; -    m_pBuffer = 0; -    pkt = 0; -} +#ifdef __GNUC__ + // G++ doesn't like the ## pasting +#define ETMV4I_PKTS_NAME "PKTP_ETMV4I" +#else + // VC++ is fine +#define ETMV4I_PKTS_NAME OCSD_CMPNAME_PREFIX_PKTPROC##"_ETMV4I" +#endif -// init the buffer -void TraceRawBuffer::init(const uint32_t size, const uint8_t *rawtrace, std::vector<uint8_t> *out_packet) -{ -    m_bufSize = size; -    m_bufProcessed = 0; -    m_pBuffer = rawtrace; -    pkt = out_packet; -} - -void TraceRawBuffer::copyByteToPkt() -{ -    if (!empty()) { -        pkt->push_back(m_pBuffer[m_bufProcessed]); -        m_bufProcessed++; -    } -} -uint8_t TraceRawBuffer::peekNextByte() -{ -    uint8_t val = 0; -    if (!empty()) -        val = m_pBuffer[m_bufProcessed]; -    return val; -} +static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON;  /* trace etmv4 packet processing class */ -EtmV4IPktProcImpl::EtmV4IPktProcImpl() : +TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME),      m_isInit(false), -    m_interface(0),      m_first_trace_info(false)  { -     +    m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS;  } -EtmV4IPktProcImpl::~EtmV4IPktProcImpl() +TrcPktProcEtmV4I::TrcPktProcEtmV4I(int instIDNum) : TrcPktProcBase(ETMV4I_PKTS_NAME, instIDNum), +    m_isInit(false), +    m_first_trace_info(false)  { +    m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS;  } -void EtmV4IPktProcImpl::Initialise(TrcPktProcEtmV4I *p_interface) + +TrcPktProcEtmV4I::~TrcPktProcEtmV4I()  { -     if(p_interface) -     { -         m_interface = p_interface; -         m_isInit = true; -     } -     InitProcessorState();  } -ocsd_err_t EtmV4IPktProcImpl::Configure(const EtmV4Config *p_config) +ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig()  { -    ocsd_err_t err = OCSD_OK; -    if(p_config != 0) -    { -        m_config = *p_config; -        BuildIPacketTable();    // packet table based on config -    } -    else -    { -        err = OCSD_ERR_INVALID_PARAM_VAL; -        if(m_isInit) -            m_interface->LogError(ocsdError(OCSD_ERR_SEV_ERROR,err)); -    } -    return err; +    InitProcessorState(); +    m_config = *TrcPktProcBase::getProtocolConfig(); +    BuildIPacketTable();    // packet table based on config +    m_isInit = true; +    return OCSD_OK;  } -ocsd_datapath_resp_t EtmV4IPktProcImpl::processData(  const ocsd_trc_index_t index, +ocsd_datapath_resp_t TrcPktProcEtmV4I::processData(  const ocsd_trc_index_t index,                                      const uint32_t dataBlockSize,                                      const uint8_t *pDataBlock,                                      uint32_t *numBytesProcessed)  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + +    if (!m_isInit) +        return OCSD_RESP_FATAL_NOT_INIT; +      m_trcIn.init(dataBlockSize, pDataBlock, &m_currPacketData);      m_blockIndex = index;      bool done = false; @@ -122,9 +93,6 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData(  const ocsd_trc_index_t ind      {          try           { -           /* while (((m_blockBytesProcessed < dataBlockSize) || -                ((m_blockBytesProcessed == dataBlockSize) && (m_process_state == SEND_PKT))) && -                OCSD_DATA_RESP_IS_CONT(resp))*/              while ( (!m_trcIn.empty() || (m_process_state == SEND_PKT)) &&                      OCSD_DATA_RESP_IS_CONT(resp)                  ) @@ -142,7 +110,7 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData(  const ocsd_trc_index_t ind                      else                      {                          // unsynced - process data until we see a sync point -                        m_pIPktFn = &EtmV4IPktProcImpl::iNotSync; +                        m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;                          m_curr_packet.type = ETM4_PKT_I_NOTSYNC;                      }                      m_process_state = PROC_DATA; @@ -153,8 +121,6 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData(  const ocsd_trc_index_t ind                      {                          nextByte = m_trcIn.peekNextByte();                          m_trcIn.copyByteToPkt();  // move next byte into the packet -    //                    m_currPacketData.push_back(pDataBlock[m_blockBytesProcessed]); -    //                    m_blockBytesProcessed++;                          (this->*m_pIPktFn)(nextByte);                      }                      break; @@ -181,7 +147,7 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData(  const ocsd_trc_index_t ind          catch(ocsdError &err)          {              done = true; -            m_interface->LogError(err); +            LogError(err);              if( (err.getErrorCode() == OCSD_ERR_BAD_PACKET_SEQ) ||                  (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR))              { @@ -201,7 +167,7 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData(  const ocsd_trc_index_t ind              /// vv bad at this point.              resp = OCSD_RESP_FATAL_SYS_ERR;              const ocsdError &fatal = ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_packet_index,m_config.getTraceID(),"Unknown System Error decoding trace."); -            m_interface->LogError(fatal); +           LogError(fatal);          }      } while (!done); @@ -209,9 +175,12 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData(  const ocsd_trc_index_t ind      return resp;  } -ocsd_datapath_resp_t EtmV4IPktProcImpl::onEOT() +ocsd_datapath_resp_t TrcPktProcEtmV4I::onEOT()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    if (!m_isInit) +        return OCSD_RESP_FATAL_NOT_INIT; +      // if we have a partial packet then send to attached sinks      if(m_currPacketData.size() != 0)      { @@ -222,31 +191,37 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::onEOT()      return resp;  } -ocsd_datapath_resp_t EtmV4IPktProcImpl::onReset() +ocsd_datapath_resp_t TrcPktProcEtmV4I::onReset()  { +    if (!m_isInit) +        return OCSD_RESP_FATAL_NOT_INIT; +      // prepare for new decoding session      InitProcessorState();      return OCSD_RESP_CONT;  } -ocsd_datapath_resp_t EtmV4IPktProcImpl::onFlush() +ocsd_datapath_resp_t TrcPktProcEtmV4I::onFlush()  { +    if (!m_isInit) +        return OCSD_RESP_FATAL_NOT_INIT; +      // packet processor never holds on to flushable data (may have partial packet,       // but any full packets are immediately sent)      return OCSD_RESP_CONT;  } -void EtmV4IPktProcImpl::InitPacketState() +void TrcPktProcEtmV4I::InitPacketState()  {      m_currPacketData.clear();      m_curr_packet.initNextPacket(); // clear for next packet.      m_update_on_unsync_packet_index = 0;  } -void EtmV4IPktProcImpl::InitProcessorState() +void TrcPktProcEtmV4I::InitProcessorState()  {      InitPacketState(); -    m_pIPktFn = &EtmV4IPktProcImpl::iNotSync; +    m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;      m_packet_index = 0;      m_is_sync = false;      m_first_trace_info = false; @@ -255,23 +230,23 @@ void EtmV4IPktProcImpl::InitProcessorState()      m_curr_packet.initStartState();  } -ocsd_datapath_resp_t EtmV4IPktProcImpl::outputPacket() +ocsd_datapath_resp_t TrcPktProcEtmV4I::outputPacket()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; -    resp = m_interface->outputOnAllInterfaces(m_packet_index,&m_curr_packet,&m_curr_packet.type,m_currPacketData); +    resp = outputOnAllInterfaces(m_packet_index,&m_curr_packet,&m_curr_packet.type,m_currPacketData);      return resp;  } -ocsd_datapath_resp_t EtmV4IPktProcImpl::outputUnsyncedRawPacket() +ocsd_datapath_resp_t TrcPktProcEtmV4I::outputUnsyncedRawPacket()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; -    m_interface->outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]); +   outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]);      if(!m_sent_notsync_packet)      {         -        resp = m_interface->outputDecodedPacket(m_packet_index,&m_curr_packet); +        resp = outputDecodedPacket(m_packet_index,&m_curr_packet);          m_sent_notsync_packet = true;      } @@ -283,7 +258,7 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::outputUnsyncedRawPacket()      return resp;  } -void EtmV4IPktProcImpl::iNotSync(const uint8_t lastByte) +void TrcPktProcEtmV4I::iNotSync(const uint8_t lastByte)  {      // is it an extension byte?       if (lastByte == 0x00) // TBD : add check for forced sync in here? @@ -309,7 +284,7 @@ void EtmV4IPktProcImpl::iNotSync(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktNoPayload(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte)  {      // some expansion may be required...      switch(m_curr_packet.type) @@ -338,26 +313,26 @@ void EtmV4IPktProcImpl::iPktNoPayload(const uint8_t lastByte)      m_process_state = SEND_PKT; // now just send it....  } -void EtmV4IPktProcImpl::iPktReserved(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktReserved(const uint8_t lastByte)  {      m_curr_packet.updateErrType(ETM4_PKT_I_RESERVED, lastByte);   // swap type for err type      throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PCKT_HDR,m_packet_index,m_config.getTraceID());  } -void EtmV4IPktProcImpl::iPktInvalidCfg(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktInvalidCfg(const uint8_t lastByte)  {      m_curr_packet.updateErrType(ETM4_PKT_I_RESERVED_CFG, lastByte);   // swap type for err type      throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PCKT_HDR, m_packet_index, m_config.getTraceID());  } -void EtmV4IPktProcImpl::iPktExtension(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktExtension(const uint8_t lastByte)  {      if(m_currPacketData.size() == 2)      {          // not sync and not next by 0x00 - not sync sequence          if(!m_is_sync && (lastByte != 0x00))          { -            m_pIPktFn = &EtmV4IPktProcImpl::iNotSync; +            m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;              m_curr_packet.type = ETM4_PKT_I_NOTSYNC;              return;          } @@ -376,7 +351,7 @@ void EtmV4IPktProcImpl::iPktExtension(const uint8_t lastByte)          case 0x00:              m_curr_packet.type = ETM4_PKT_I_ASYNC; -            m_pIPktFn = &EtmV4IPktProcImpl::iPktASync;  // handle subsequent bytes as async +            m_pIPktFn = &TrcPktProcEtmV4I::iPktASync;  // handle subsequent bytes as async              break;          default: @@ -388,14 +363,14 @@ void EtmV4IPktProcImpl::iPktExtension(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktASync(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktASync(const uint8_t lastByte)  {      if(lastByte != 0x00)      {          // not sync and not next by 0x00 - not sync sequence if < 12          if(!m_is_sync && m_currPacketData.size() != 12)          { -            m_pIPktFn = &EtmV4IPktProcImpl::iNotSync; +            m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;              m_curr_packet.type = ETM4_PKT_I_NOTSYNC;              return;          } @@ -428,7 +403,7 @@ void EtmV4IPktProcImpl::iPktASync(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktTraceInfo(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte)  {      if(m_currPacketData.size() == 1)    // header      { @@ -500,7 +475,7 @@ void EtmV4IPktProcImpl::iPktTraceInfo(const uint8_t lastByte)  } -void EtmV4IPktProcImpl::iPktTimestamp(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktTimestamp(const uint8_t lastByte)  {      // process the header byte      if(m_currPacketData.size() == 1) @@ -550,7 +525,7 @@ void EtmV4IPktProcImpl::iPktTimestamp(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktException(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte)  {      uint16_t excep_type = 0; @@ -582,7 +557,7 @@ void EtmV4IPktProcImpl::iPktException(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktCycleCntF123(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktCycleCntF123(const uint8_t lastByte)  {      ocsd_etmv4_i_pkt_type format = m_curr_packet.type; @@ -657,7 +632,7 @@ void EtmV4IPktProcImpl::iPktCycleCntF123(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktSpeclRes(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktSpeclRes(const uint8_t lastByte)  {          if(m_currPacketData.size() == 1)      { @@ -671,8 +646,10 @@ void EtmV4IPktProcImpl::iPktSpeclRes(const uint8_t lastByte)              case 0x2: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x3, 2); break; // EE              case 0x3: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x0, 1); break; // N              } -            if(m_curr_packet.getType() == ETM4_PKT_I_CANCEL_F2) +            if (m_curr_packet.getType() == ETM4_PKT_I_CANCEL_F2)                  m_curr_packet.setCancelElements(1); +            else +                m_curr_packet.setCancelElements(0);              m_process_state = SEND_PKT;              break; @@ -694,13 +671,12 @@ void EtmV4IPktProcImpl::iPktSpeclRes(const uint8_t lastByte)                  m_curr_packet.setCommitElements(field_val);              else                  m_curr_packet.setCancelElements(field_val); -            // TBD: sanity check with max spec depth here?              m_process_state = SEND_PKT;          }      }  } -void EtmV4IPktProcImpl::iPktCondInstr(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktCondInstr(const uint8_t lastByte)  {      bool bF1Done = false; @@ -740,7 +716,7 @@ void EtmV4IPktProcImpl::iPktCondInstr(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktCondResult(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktCondResult(const uint8_t lastByte)  {      if(m_currPacketData.size() == 1)          { @@ -810,7 +786,7 @@ void EtmV4IPktProcImpl::iPktCondResult(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktContext(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktContext(const uint8_t lastByte)  {      bool bSendPacket = false; @@ -852,7 +828,7 @@ void EtmV4IPktProcImpl::iPktContext(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::extractAndSetContextInfo(const std::vector<uint8_t> &buffer, const int st_idx) +void TrcPktProcEtmV4I::extractAndSetContextInfo(const std::vector<uint8_t> &buffer, const int st_idx)  {      // on input, buffer index points at the info byte - always present      uint8_t infoByte = m_currPacketData[st_idx]; @@ -887,7 +863,7 @@ void EtmV4IPktProcImpl::extractAndSetContextInfo(const std::vector<uint8_t> &buf      }  } -void EtmV4IPktProcImpl::iPktAddrCtxt(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktAddrCtxt(const uint8_t lastByte)  {      if( m_currPacketData.size() == 1)          {         @@ -955,7 +931,7 @@ void EtmV4IPktProcImpl::iPktAddrCtxt(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktShortAddr(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktShortAddr(const uint8_t lastByte)  {      if (m_currPacketData.size() == 1)      { @@ -980,7 +956,7 @@ void EtmV4IPktProcImpl::iPktShortAddr(const uint8_t lastByte)      }  } -int EtmV4IPktProcImpl::extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits) +int TrcPktProcEtmV4I::extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits)  {      int IS_shift = (IS == 0) ? 2 : 1;      int idx = 0; @@ -1000,7 +976,7 @@ int EtmV4IPktProcImpl::extractShortAddr(const std::vector<uint8_t> &buffer, cons      return idx;  } -void EtmV4IPktProcImpl::iPktLongAddr(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktLongAddr(const uint8_t lastByte)  {      if(m_currPacketData.size() == 1)          { @@ -1044,7 +1020,7 @@ void EtmV4IPktProcImpl::iPktLongAddr(const uint8_t lastByte)      }  } -void EtmV4IPktProcImpl::iPktQ(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktQ(const uint8_t lastByte)  {      if(m_currPacketData.size() == 1)      { @@ -1096,7 +1072,7 @@ void EtmV4IPktProcImpl::iPktQ(const uint8_t lastByte)          default:              m_curr_packet.err_type =  m_curr_packet.type;              m_curr_packet.type = ETM4_PKT_I_BAD_SEQUENCE; -            //SendBadIPacket( PKT_BAD_SEQUENCE, "ERROR: Bad Q packet type", PKT_Q ); +            m_process_state = SEND_PKT;              break;          }      } @@ -1156,7 +1132,7 @@ void EtmV4IPktProcImpl::iPktQ(const uint8_t lastByte)  } -void EtmV4IPktProcImpl::iAtom(const uint8_t lastByte) +void TrcPktProcEtmV4I::iAtom(const uint8_t lastByte)  {      // patterns lsbit = oldest atom, ms bit = newest.      static const uint32_t f4_patterns[] = { @@ -1228,32 +1204,32 @@ void EtmV4IPktProcImpl::iAtom(const uint8_t lastByte)  }  // header byte processing is table driven. -void EtmV4IPktProcImpl::BuildIPacketTable()    +void TrcPktProcEtmV4I::BuildIPacketTable()     {      // initialise everything as reserved.      for(int i = 0; i < 256; i++)      {          m_i_table[i].pkt_type = ETM4_PKT_I_RESERVED; -        m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iPktReserved; +        m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iPktReserved;      }      // 0x00 - extension       m_i_table[0x00].pkt_type = ETM4_PKT_I_EXTENSION; -    m_i_table[0x00].pptkFn   = &EtmV4IPktProcImpl::iPktExtension; +    m_i_table[0x00].pptkFn   = &TrcPktProcEtmV4I::iPktExtension;      // 0x01 - Trace info      m_i_table[0x01].pkt_type = ETM4_PKT_I_TRACE_INFO; -    m_i_table[0x01].pptkFn   = &EtmV4IPktProcImpl::iPktTraceInfo; +    m_i_table[0x01].pptkFn   = &TrcPktProcEtmV4I::iPktTraceInfo;      // b0000001x - timestamp      m_i_table[0x02].pkt_type = ETM4_PKT_I_TIMESTAMP; -    m_i_table[0x02].pptkFn   = &EtmV4IPktProcImpl::iPktTimestamp; +    m_i_table[0x02].pptkFn   = &TrcPktProcEtmV4I::iPktTimestamp;      m_i_table[0x03].pkt_type = ETM4_PKT_I_TIMESTAMP; -    m_i_table[0x03].pptkFn   = &EtmV4IPktProcImpl::iPktTimestamp; +    m_i_table[0x03].pptkFn   = &TrcPktProcEtmV4I::iPktTimestamp;      // b0000 0100 - trace on      m_i_table[0x04].pkt_type = ETM4_PKT_I_TRACE_ON; -    m_i_table[0x04].pptkFn   = &EtmV4IPktProcImpl::iPktNoPayload; +    m_i_table[0x04].pptkFn   = &TrcPktProcEtmV4I::iPktNoPayload;      // b0000 0101 - Funct ret V8M @@ -1262,30 +1238,30 @@ void EtmV4IPktProcImpl::BuildIPacketTable()          (OCSD_IS_V8_ARCH(m_config.archVersion())) &&          (m_config.FullVersion() >= 0x42))      {         -        m_i_table[0x05].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; +        m_i_table[0x05].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;      }      // b0000 0110 - exception       m_i_table[0x06].pkt_type = ETM4_PKT_I_EXCEPT; -    m_i_table[0x06].pptkFn   = &EtmV4IPktProcImpl::iPktException; +    m_i_table[0x06].pptkFn   = &TrcPktProcEtmV4I::iPktException;      // b0000 0111 - exception return       m_i_table[0x07].pkt_type = ETM4_PKT_I_EXCEPT_RTN; -    m_i_table[0x07].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; +    m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;      // b0000 110x - cycle count f2      // b0000 111x - cycle count f1      for(int i = 0; i < 4; i++)      {          m_i_table[0x0C+i].pkt_type = (i >= 2) ? ETM4_PKT_I_CCNT_F1 : ETM4_PKT_I_CCNT_F2; -        m_i_table[0x0C+i].pptkFn   = &EtmV4IPktProcImpl::iPktCycleCntF123; +        m_i_table[0x0C+i].pptkFn   = &TrcPktProcEtmV4I::iPktCycleCntF123;      }      // b0001 xxxx - cycle count f3      for(int i = 0; i < 16; i++)      {          m_i_table[0x10+i].pkt_type = ETM4_PKT_I_CCNT_F3; -        m_i_table[0x10+i].pptkFn   = &EtmV4IPktProcImpl::iPktCycleCntF123; +        m_i_table[0x10+i].pptkFn   = &TrcPktProcEtmV4I::iPktCycleCntF123;      }      // b0010 0xxx - NDSM @@ -1293,9 +1269,9 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      {          m_i_table[0x20 + i].pkt_type = ETM4_PKT_I_NUM_DS_MKR;          if (m_config.enabledDataTrace()) -            m_i_table[0x20+i].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; +            m_i_table[0x20+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;          else -            m_i_table[0x20+i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[0x20+i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      // b0010 10xx, b0010 1100 - UDSM @@ -1303,43 +1279,40 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      {          m_i_table[0x28+i].pkt_type = ETM4_PKT_I_UNNUM_DS_MKR;          if (m_config.enabledDataTrace()) -            m_i_table[0x28+i].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; +            m_i_table[0x28+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;          else -            m_i_table[0x28+i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[0x28+i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      // b0010 1101 - commit      m_i_table[0x2D].pkt_type = ETM4_PKT_I_COMMIT; -    m_i_table[0x2D].pptkFn   = &EtmV4IPktProcImpl::iPktSpeclRes; +    m_i_table[0x2D].pptkFn   = &TrcPktProcEtmV4I::iPktSpeclRes; -    // b0010 111x - cancel f1 -    for(int i = 0; i < 2; i++) -    { -        // G++ doesn't understand [0x2E+i] so... -        int idx = i + 0x2E; -        m_i_table[idx].pkt_type = ETM4_PKT_I_CANCEL_F1; -        m_i_table[idx].pptkFn   = &EtmV4IPktProcImpl::iPktSpeclRes; -    } +    // b0010 111x - cancel f1 (mis pred) +    m_i_table[0x2E].pkt_type = ETM4_PKT_I_CANCEL_F1; +    m_i_table[0x2E].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes; +    m_i_table[0x2F].pkt_type = ETM4_PKT_I_CANCEL_F1_MISPRED; +    m_i_table[0x2F].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;      // b0011 00xx - mis predict      for(int i = 0; i < 4; i++)      {          m_i_table[0x30+i].pkt_type = ETM4_PKT_I_MISPREDICT; -        m_i_table[0x30+i].pptkFn   =  &EtmV4IPktProcImpl::iPktSpeclRes; +        m_i_table[0x30+i].pptkFn   =  &TrcPktProcEtmV4I::iPktSpeclRes;      }      // b0011 01xx - cancel f2      for(int i = 0; i < 4; i++)      {          m_i_table[0x34+i].pkt_type = ETM4_PKT_I_CANCEL_F2; -        m_i_table[0x34+i].pptkFn   =  &EtmV4IPktProcImpl::iPktSpeclRes; +        m_i_table[0x34+i].pptkFn   =  &TrcPktProcEtmV4I::iPktSpeclRes;      }      // b0011 1xxx - cancel f3      for(int i = 0; i < 8; i++)      {          m_i_table[0x38+i].pkt_type = ETM4_PKT_I_CANCEL_F3; -        m_i_table[0x38+i].pptkFn   =  &EtmV4IPktProcImpl::iPktSpeclRes; +        m_i_table[0x38+i].pptkFn   =  &TrcPktProcEtmV4I::iPktSpeclRes;      }      bool bCondValid = m_config.hasCondTrace() && m_config.enabledCondITrace(); @@ -1349,26 +1322,26 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      {          m_i_table[0x40 + i].pkt_type = ETM4_PKT_I_COND_I_F2;          if (bCondValid) -            m_i_table[0x40 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr; +            m_i_table[0x40 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;          else -            m_i_table[0x40 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[0x40 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      // b0100 0011 - cond flush      m_i_table[0x43].pkt_type = ETM4_PKT_I_COND_FLUSH;      if (bCondValid) -        m_i_table[0x43].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; +        m_i_table[0x43].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;      else -        m_i_table[0x43].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +        m_i_table[0x43].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      // b0100 010x, b0100 0110 - cond res f4      for (int i = 0; i < 3; i++)      {          m_i_table[0x44 + i].pkt_type = ETM4_PKT_I_COND_RES_F4;          if (bCondValid) -            m_i_table[0x44 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; +            m_i_table[0x44 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;          else -            m_i_table[0x44 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[0x44 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      // b0100 100x, b0100 0110 - cond res f2 @@ -1377,17 +1350,17 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      {          m_i_table[0x48 + i].pkt_type = ETM4_PKT_I_COND_RES_F2;          if (bCondValid) -            m_i_table[0x48 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; +            m_i_table[0x48 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;          else -            m_i_table[0x48 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[0x48 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      for (int i = 0; i < 3; i++)      {          m_i_table[0x4C + i].pkt_type = ETM4_PKT_I_COND_RES_F2;          if (bCondValid) -            m_i_table[0x4C + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; +            m_i_table[0x4C + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;          else -            m_i_table[0x4C + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[0x4C + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      // b0101xxxx - cond res f3 @@ -1395,9 +1368,9 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      {          m_i_table[0x50 + i].pkt_type = ETM4_PKT_I_COND_RES_F3;          if (bCondValid) -            m_i_table[0x50 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; +            m_i_table[0x50 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;          else -            m_i_table[0x50 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[0x50 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      // b011010xx - cond res f1 @@ -1405,24 +1378,24 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      {          m_i_table[0x68 + i].pkt_type = ETM4_PKT_I_COND_RES_F1;          if (bCondValid) -            m_i_table[0x68 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; +            m_i_table[0x68 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;          else -            m_i_table[0x68 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[0x68 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      // b0110 1100 - cond instr f1      m_i_table[0x6C].pkt_type = ETM4_PKT_I_COND_I_F1;      if (bCondValid) -        m_i_table[0x6C].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr; +        m_i_table[0x6C].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;      else -        m_i_table[0x6C].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +        m_i_table[0x6C].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      // b0110 1101 - cond instr f3      m_i_table[0x6D].pkt_type = ETM4_PKT_I_COND_I_F3;      if (bCondValid) -        m_i_table[0x6D].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr; +        m_i_table[0x6D].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;      else -        m_i_table[0x6D].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +        m_i_table[0x6D].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      // b0110111x - cond res f1      for (int i = 0; i < 2; i++) @@ -1430,30 +1403,30 @@ void EtmV4IPktProcImpl::BuildIPacketTable()          // G++ cannot understand [0x6E+i] so change these round          m_i_table[i + 0x6E].pkt_type = ETM4_PKT_I_COND_RES_F1;          if (bCondValid) -            m_i_table[i + 0x6E].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; +            m_i_table[i + 0x6E].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;          else -            m_i_table[i + 0x6E].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; +            m_i_table[i + 0x6E].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;      }      // ETM 4.3 introduces ignore packets      if (m_config.FullVersion() >= 0x43)      {          m_i_table[0x70].pkt_type = ETM4_PKT_I_IGNORE; -        m_i_table[0x70].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; +        m_i_table[0x70].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;      }      // b01110001 - b01111111 - event trace      for(int i = 0; i < 15; i++)      {          m_i_table[0x71+i].pkt_type = ETM4_PKT_I_EVENT; -        m_i_table[0x71+i].pptkFn   = &EtmV4IPktProcImpl::iPktNoPayload; +        m_i_table[0x71+i].pptkFn   = &TrcPktProcEtmV4I::iPktNoPayload;      }      // 0b1000 000x - context       for(int i = 0; i < 2; i++)      {          m_i_table[0x80+i].pkt_type = ETM4_PKT_I_CTXT; -        m_i_table[0x80+i].pptkFn   = &EtmV4IPktProcImpl::iPktContext; +        m_i_table[0x80+i].pptkFn   = &TrcPktProcEtmV4I::iPktContext;      }      // 0b1000 0010 to b1000 0011 - addr with ctxt @@ -1461,27 +1434,27 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      for(int i = 0; i < 2; i++)      {          m_i_table[0x82+i].pkt_type =  (i == 0) ? ETM4_PKT_I_ADDR_CTXT_L_32IS0 : ETM4_PKT_I_ADDR_CTXT_L_32IS1; -        m_i_table[0x82+i].pptkFn   = &EtmV4IPktProcImpl::iPktAddrCtxt; +        m_i_table[0x82+i].pptkFn   = &TrcPktProcEtmV4I::iPktAddrCtxt;      }      for(int i = 0; i < 2; i++)      {          m_i_table[0x85+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_CTXT_L_64IS0 : ETM4_PKT_I_ADDR_CTXT_L_64IS1; -        m_i_table[0x85+i].pptkFn   = &EtmV4IPktProcImpl::iPktAddrCtxt; +        m_i_table[0x85+i].pptkFn   = &TrcPktProcEtmV4I::iPktAddrCtxt;      }      // 0b1001 0000 to b1001 0010 - exact match addr      for(int i = 0; i < 3; i++)      {          m_i_table[0x90+i].pkt_type = ETM4_PKT_I_ADDR_MATCH; -        m_i_table[0x90+i].pptkFn   = &EtmV4IPktProcImpl::iPktNoPayload; +        m_i_table[0x90+i].pptkFn   = &TrcPktProcEtmV4I::iPktNoPayload;      }      // b1001 0101 - b1001 0110 - addr short address      for(int i = 0; i < 2; i++)      {          m_i_table[0x95+i].pkt_type =  (i == 0) ? ETM4_PKT_I_ADDR_S_IS0 : ETM4_PKT_I_ADDR_S_IS1; -        m_i_table[0x95+i].pptkFn   = &EtmV4IPktProcImpl::iPktShortAddr; +        m_i_table[0x95+i].pptkFn   = &TrcPktProcEtmV4I::iPktShortAddr;      }      // b10011010 - b10011011 - addr long address  @@ -1489,12 +1462,12 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      for(int i = 0; i < 2; i++)      {          m_i_table[0x9A+i].pkt_type =  (i == 0) ? ETM4_PKT_I_ADDR_L_32IS0 : ETM4_PKT_I_ADDR_L_32IS1; -        m_i_table[0x9A+i].pptkFn   = &EtmV4IPktProcImpl::iPktLongAddr; +        m_i_table[0x9A+i].pptkFn   = &TrcPktProcEtmV4I::iPktLongAddr;      }      for(int i = 0; i < 2; i++)      {          m_i_table[0x9D+i].pkt_type =  (i == 0) ? ETM4_PKT_I_ADDR_L_64IS0 : ETM4_PKT_I_ADDR_L_64IS1; -        m_i_table[0x9D+i].pptkFn   = &EtmV4IPktProcImpl::iPktLongAddr; +        m_i_table[0x9D+i].pptkFn   = &TrcPktProcEtmV4I::iPktLongAddr;      }      // b1010xxxx - Q packet @@ -1515,7 +1488,7 @@ void EtmV4IPktProcImpl::BuildIPacketTable()          default:              // if this config supports Q elem - otherwise reserved again.              if (m_config.hasQElem()) -                m_i_table[0xA0 + i].pptkFn = &EtmV4IPktProcImpl::iPktQ; +                m_i_table[0xA0 + i].pptkFn = &TrcPktProcEtmV4I::iPktQ;          }      } @@ -1523,46 +1496,46 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      for(int i = 0xC0; i <= 0xD4; i++)   // atom f6      {          m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F6; -        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom; +        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;      }      for(int i = 0xD5; i <= 0xD7; i++)  // atom f5      {          m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F5; -        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom; +        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;      }      for(int i = 0xD8; i <= 0xDB; i++)  // atom f2      {          m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F2; -        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom; +        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;      }      for(int i = 0xDC; i <= 0xDF; i++)  // atom f4      {          m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F4; -        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom; +        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;      }      for(int i = 0xE0; i <= 0xF4; i++)  // atom f6      {          m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F6; -        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom; +        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;      }      // atom f5      m_i_table[0xF5].pkt_type = ETM4_PKT_I_ATOM_F5; -    m_i_table[0xF5].pptkFn   = &EtmV4IPktProcImpl::iAtom; +    m_i_table[0xF5].pptkFn   = &TrcPktProcEtmV4I::iAtom;      for(int i = 0xF6; i <= 0xF7; i++)  // atom f1      {          m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F1; -        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom; +        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;      }      for(int i = 0xF8; i <= 0xFF; i++)  // atom f3      {          m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F3; -        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom; +        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;      }  } - unsigned EtmV4IPktProcImpl::extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit /*= 5*/) + unsigned TrcPktProcEtmV4I::extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit /*= 5*/)  {      unsigned idx = 0;      bool lastByte = false; @@ -1586,7 +1559,7 @@ void EtmV4IPktProcImpl::BuildIPacketTable()      return idx;  } -unsigned EtmV4IPktProcImpl::extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/) +unsigned TrcPktProcEtmV4I::extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/)  {      unsigned idx = 0;      bool lastByte = false; @@ -1610,7 +1583,7 @@ unsigned EtmV4IPktProcImpl::extractContField64(const std::vector<uint8_t> &buffe      return idx;  } - unsigned EtmV4IPktProcImpl::extractCondResult(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result) + unsigned TrcPktProcEtmV4I::extractCondResult(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result)  {      unsigned idx = 0;      bool lastByte = false; @@ -1644,7 +1617,7 @@ unsigned EtmV4IPktProcImpl::extractContField64(const std::vector<uint8_t> &buffe      return idx;  } -int EtmV4IPktProcImpl::extract64BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint64_t &value) +int TrcPktProcEtmV4I::extract64BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint64_t &value)  {      value = 0;      if(IS == 0) @@ -1666,7 +1639,7 @@ int EtmV4IPktProcImpl::extract64BitLongAddr(const std::vector<uint8_t> &buffer,      return 8;      } -int EtmV4IPktProcImpl::extract32BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value) +int TrcPktProcEtmV4I::extract32BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value)  {      value = 0;      if(IS == 0) @@ -1684,11 +1657,11 @@ int EtmV4IPktProcImpl::extract32BitLongAddr(const std::vector<uint8_t> &buffer,      return 4;  } -void EtmV4IPktProcImpl::throwBadSequenceError(const char *pszExtMsg) +void TrcPktProcEtmV4I::throwBadSequenceError(const char *pszExtMsg)  {      m_curr_packet.updateErrType(ETM4_PKT_I_BAD_SEQUENCE);   // swap type for err type      throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ,m_packet_index,m_config.getTraceID(),pszExtMsg);  } -/* End of File trc_pkt_proc_etmv4i_impl.cpp */ +/* End of File trc_pkt_proc_etmv4i.cpp */ diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h b/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h deleted file mode 100644 index 429f32711f3e..000000000000 --- a/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * \file       trc_pkt_proc_etmv4i_impl.h - * \brief      OpenCSD : Implementation of ETMv4 packet processing - *  - * \copyright  Copyright (c) 2015, 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.  - */  - -#ifndef ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED -#define ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED - -#include "opencsd/etmv4/trc_pkt_proc_etmv4.h" -#include "opencsd/etmv4/trc_cmp_cfg_etmv4.h" -#include "opencsd/etmv4/trc_pkt_elem_etmv4i.h" - -class TraceRawBuffer -{ -public: -    TraceRawBuffer(); -    ~TraceRawBuffer() {}; - -    // init the buffer -    void init(const uint32_t size, const uint8_t *rawtrace, std::vector<uint8_t> *out_packet); -    void copyByteToPkt();   // move a byte to the packet buffer      -    uint8_t peekNextByte(); // value of next byte in buffer. - -    bool empty() { return m_bufProcessed == m_bufSize; }; -    // bytes processed. -    uint32_t processed() { return m_bufProcessed; };  -    // buffer size; -    uint32_t size() { return m_bufSize; }  - -private: -    uint32_t m_bufSize; -    uint32_t m_bufProcessed; -    const uint8_t *m_pBuffer; -    std::vector<uint8_t> *pkt; - -}; - -class EtmV4IPktProcImpl -{ -public: -    EtmV4IPktProcImpl(); -    ~EtmV4IPktProcImpl(); - -    void Initialise(TrcPktProcEtmV4I *p_interface); - -    ocsd_err_t Configure(const EtmV4Config *p_config); - - -    ocsd_datapath_resp_t processData(  const ocsd_trc_index_t index, -                                        const uint32_t dataBlockSize, -                                        const uint8_t *pDataBlock, -                                        uint32_t *numBytesProcessed); -    ocsd_datapath_resp_t onEOT(); -    ocsd_datapath_resp_t onReset(); -    ocsd_datapath_resp_t onFlush(); -    const bool isBadPacket() const; - -protected: -    typedef enum _process_state { -        PROC_HDR, -        PROC_DATA, -        SEND_PKT, -        SEND_UNSYNCED, -        PROC_ERR, -    } process_state; -     -    process_state m_process_state; - -    void InitPacketState();      // clear current packet state. -    void InitProcessorState();   // clear all previous process state - -    /** packet processor configuration **/ -    bool m_isInit; -    TrcPktProcEtmV4I *m_interface;       /**< The interface to the other decode components */ - -    // etmv4 hardware configuration -    EtmV4Config m_config; - -    /** packet data **/ -    TraceRawBuffer m_trcIn;    // trace data in buffer -    std::vector<uint8_t> m_currPacketData;  // raw data packet -    int m_currPktIdx;   // index into raw packet when expanding -    EtmV4ITrcPacket m_curr_packet;  // expanded packet -    ocsd_trc_index_t m_packet_index;   // index of the start of the current packet -//    uint32_t m_blockBytesProcessed;     // number of bytes processed in the current data block -    ocsd_trc_index_t m_blockIndex;     // index at the start of the current data block being processed - -    // searching for sync -    bool m_is_sync;             //!< seen first sync packet -    bool m_first_trace_info;    //!< seen first trace info packet after sync -    bool m_sent_notsync_packet; //!< send one not sync packet if we see any unsynced data on the channel  -    unsigned m_dump_unsynced_bytes;  //!< number of unsynced bytes to send -    ocsd_trc_index_t m_update_on_unsync_packet_index; - - -private: -    // current processing state data - counts and flags to determine if a packet is complete. - -    // TraceInfo Packet -    // flags to indicate processing progress for these sections is complete. -    struct _t_info_pkt_prog { -        uint8_t sectFlags; -        uint8_t ctrlBytes;                  -    }  m_tinfo_sections; - -    #define TINFO_INFO_SECT 0x01 -    #define TINFO_KEY_SECT  0x02  -    #define TINFO_SPEC_SECT 0x04 -    #define TINFO_CYCT_SECT 0x08 -    #define TINFO_CTRL      0x20 -    #define TINFO_ALL_SECT  0x1F -    #define TINFO_ALL       0x3F - - -    // address and context packets  -    int m_addrBytes; -    uint8_t m_addrIS; -    bool m_bAddr64bit; -    int m_vmidBytes;    // bytes still to find -    int m_ctxtidBytes;  // bytes still to find -    bool m_bCtxtInfoDone; -    bool m_addr_done; - -    // timestamp -    bool m_ccount_done; // done or not needed  -    bool m_ts_done; -    int m_ts_bytes; - -    // exception -    int m_excep_size; - -    // cycle count -    bool m_has_count; -    bool m_count_done; -    bool m_commit_done; - -    // cond result -    bool m_F1P1_done;  // F1 payload 1 done -    bool m_F1P2_done;  // F1 payload 2 done -    bool m_F1has_P2;   // F1 has a payload 2 - -    // Q packets (use some from above too) -    bool m_has_addr; -    bool m_addr_short; -    bool m_addr_match; -    uint8_t m_Q_type; -    uint8_t m_QE; - -    ocsd_datapath_resp_t outputPacket(); -    ocsd_datapath_resp_t outputUnsyncedRawPacket();  - -    void iNotSync(const uint8_t lastByte);      // not synced yet -    void iPktNoPayload(const uint8_t lastByte); // process a single byte packet -    void iPktReserved(const uint8_t lastByte);  // deal with reserved header value -    void iPktExtension(const uint8_t lastByte); -    void iPktASync(const uint8_t lastByte); -    void iPktTraceInfo(const uint8_t lastByte); -    void iPktTimestamp(const uint8_t lastByte); -    void iPktException(const uint8_t lastByte); -    void iPktCycleCntF123(const uint8_t lastByte); -    void iPktSpeclRes(const uint8_t lastByte); -    void iPktCondInstr(const uint8_t lastByte); -    void iPktCondResult(const uint8_t lastByte); -    void iPktContext(const uint8_t lastByte); -    void iPktAddrCtxt(const uint8_t lastByte); -    void iPktShortAddr(const uint8_t lastByte); -    void iPktLongAddr(const uint8_t lastByte); -    void iPktQ(const uint8_t lastByte); -    void iAtom(const uint8_t lastByte); -    void iPktInvalidCfg(const uint8_t lastByte);  // packet invalid in current config. - -    unsigned extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit = 5); -    unsigned extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit = 9); -    unsigned extractCondResult(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result); -    void extractAndSetContextInfo(const std::vector<uint8_t> &buffer, const int st_idx); -    int extract64BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint64_t &value); -    int extract32BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value); -    int extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits); - -    // packet processing is table driven.     -    typedef void (EtmV4IPktProcImpl::*PPKTFN)(uint8_t); -    PPKTFN m_pIPktFn; - -    struct _pkt_i_table_t { -        ocsd_etmv4_i_pkt_type pkt_type; -        PPKTFN pptkFn; -    } m_i_table[256]; - -    void BuildIPacketTable(); - -    void throwBadSequenceError(const char *pszExtMsg); -}; - - -inline const bool EtmV4IPktProcImpl::isBadPacket() const -{ -    return m_curr_packet.isBadPacket(); -} - -#endif // ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED - -/* End of File trc_pkt_proc_etmv4i_impl.h */ diff --git a/decoder/source/i_dec/trc_i_decode.cpp b/decoder/source/i_dec/trc_i_decode.cpp index ab93284848bb..614fc1d8b45c 100644 --- a/decoder/source/i_dec/trc_i_decode.cpp +++ b/decoder/source/i_dec/trc_i_decode.cpp @@ -39,21 +39,23 @@  ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info)  {      ocsd_err_t err = OCSD_OK; -    clear_instr_subtype(); -    SetArchVersion(instr_info); +    struct decode_info info; + +    info.instr_sub_type = OCSD_S_INSTR_NONE; +    info.arch_version = (uint16_t)(instr_info->pe_type.arch);      switch(instr_info->isa)      {      case ocsd_isa_arm: -        err = DecodeA32(instr_info); +        err = DecodeA32(instr_info, &info);          break;      case ocsd_isa_thumb2: -        err = DecodeT32(instr_info); +        err = DecodeT32(instr_info, &info);          break;      case ocsd_isa_aarch64: -        err = DecodeA64(instr_info); +        err = DecodeA64(instr_info, &info);          break;      case ocsd_isa_tee:     @@ -63,27 +65,11 @@ ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info)          err = OCSD_ERR_UNSUPPORTED_ISA;          break;      } -    instr_info->sub_type = get_instr_subtype(); +    instr_info->sub_type = info.instr_sub_type;      return err;  } -void TrcIDecode::SetArchVersion(ocsd_instr_info *instr_info) -{ -    uint16_t arch = 0x0700; - -    switch (instr_info->pe_type.arch) -    { -    case ARCH_V8: arch = 0x0800; break; -    case ARCH_V8r3: arch = 0x0803; break; -    case ARCH_V7: -    default: -        break; -    } -    set_arch_version(arch); -} - - -ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info, struct decode_info *info)  {      uint32_t branchAddr = 0;      arm_barrier_t barrier; @@ -93,10 +79,10 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info)      instr_info->next_isa = instr_info->isa; // assume same ISA       instr_info->is_link = 0; -    if(inst_ARM_is_indirect_branch(instr_info->opcode)) +    if(inst_ARM_is_indirect_branch(instr_info->opcode, info))      {          instr_info->type = OCSD_INSTR_BR_INDIRECT; -        instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode); +        instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode, info);      }      else if(inst_ARM_is_direct_branch(instr_info->opcode))      { @@ -108,7 +94,7 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info)              branchAddr &= ~0x1;          }          instr_info->branch_addr = (ocsd_vaddr_t)branchAddr; -        instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode); +        instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode, info);      }      else if((barrier = inst_ARM_barrier(instr_info->opcode)) != ARM_BARRIER_NONE)      { @@ -137,7 +123,7 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info)      return OCSD_OK;  } -ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info *info)  {      uint64_t branchAddr = 0;      arm_barrier_t barrier; @@ -147,12 +133,12 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info)      instr_info->next_isa = instr_info->isa; // assume same ISA       instr_info->is_link = 0; -    if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link)) +    if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info))      {          instr_info->type = OCSD_INSTR_BR_INDIRECT;  //        instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode);      } -    else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link)) +    else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link, info))      {          inst_A64_branch_destination(instr_info->instr_addr,instr_info->opcode,&branchAddr);          instr_info->type = OCSD_INSTR_BR; @@ -187,7 +173,7 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info)      return OCSD_OK;  } -ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info, struct decode_info *info)  {      uint32_t branchAddr = 0;      arm_barrier_t barrier; @@ -206,7 +192,7 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info)      instr_info->is_conditional = 0; -    if(inst_Thumb_is_direct_branch_link(instr_info->opcode,&instr_info->is_link, &instr_info->is_conditional)) +    if(inst_Thumb_is_direct_branch_link(instr_info->opcode,&instr_info->is_link, &instr_info->is_conditional, info))      {          inst_Thumb_branch_destination((uint32_t)instr_info->instr_addr,instr_info->opcode,&branchAddr);          instr_info->type = OCSD_INSTR_BR; @@ -214,7 +200,7 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info)          if((branchAddr & 0x1) == 0)              instr_info->next_isa = ocsd_isa_arm;      } -    else if (inst_Thumb_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link)) +    else if (inst_Thumb_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info))      {          instr_info->type = OCSD_INSTR_BR_INDIRECT;      } @@ -246,5 +232,4 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info)      return OCSD_OK;  } -  /* End of File trc_i_decode.cpp */ diff --git a/decoder/source/i_dec/trc_idec_arminst.cpp b/decoder/source/i_dec/trc_idec_arminst.cpp index 09964a15e7b3..3652e84921f3 100644 --- a/decoder/source/i_dec/trc_idec_arminst.cpp +++ b/decoder/source/i_dec/trc_idec_arminst.cpp @@ -42,27 +42,6 @@ block identification and trace decode.  #include <stddef.h>  /* for NULL */  #include <assert.h> - -static ocsd_instr_subtype instr_sub_type = OCSD_S_INSTR_NONE; - -/* need to spot the architecture version for certain instructions */ -static uint16_t arch_version = 0x70; - -ocsd_instr_subtype get_instr_subtype() -{ -    return instr_sub_type; -} - -void clear_instr_subtype() -{ -    instr_sub_type = OCSD_S_INSTR_NONE; -} - -void set_arch_version(uint16_t version) -{ -    arch_version = version; -} -  int inst_ARM_is_direct_branch(uint32_t inst)  {      int is_direct_branch = 1; @@ -91,7 +70,7 @@ int inst_ARM_wfiwfe(uint32_t inst)      return 0;  } -int inst_ARM_is_indirect_branch(uint32_t inst) +int inst_ARM_is_indirect_branch(uint32_t inst, struct decode_info *info)  {      int is_indirect_branch = 1;      if ((inst & 0xf0000000) == 0xf0000000) { @@ -104,23 +83,23 @@ int inst_ARM_is_indirect_branch(uint32_t inst)      } else if ((inst & 0x0ff000d0) == 0x01200010) {          /* BLX (register), BX */          if ((inst & 0xFF) == 0x1E) -            instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ +            info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */      } else if ((inst & 0x0ff000f0) == 0x01200020) {          /* BXJ: in v8 this behaves like BX */      } else if ((inst & 0x0e108000) == 0x08108000) {          /* POP {...,pc} or LDMxx {...,pc} */          if ((inst & 0x0FFFA000) == 0x08BD8000) /* LDMIA SP!,{...,pc} */ -            instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; +            info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET;      } else if ((inst & 0x0e50f000) == 0x0410f000) {          /* LDR PC,imm... inc. POP {PC} */          if ( (inst & 0x01ff0000) == 0x009D0000) -            instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm */ +            info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm */      } else if ((inst & 0x0e50f010) == 0x0610f000) {          /* LDR PC,reg */      } else if ((inst & 0x0fe0f000) == 0x01a0f000) {          /* MOV PC,rx */          if ((inst & 0x00100FFF) == 0x00E) /* ensure the S=0, LSL #0 variant - i.e plain MOV */ -            instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC, R14 */ +            info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC, R14 */      } else if ((inst & 0x0f900080) == 0x01000000) {          /* "Miscellaneous instructions" - in DP space */          is_indirect_branch = 0; @@ -144,13 +123,13 @@ int inst_ARM_is_indirect_branch(uint32_t inst)      return is_indirect_branch;  } -int inst_Thumb_is_direct_branch(uint32_t inst) +int inst_Thumb_is_direct_branch(uint32_t inst, struct decode_info *info)  {      uint8_t link, cond; -    return inst_Thumb_is_direct_branch_link(inst, &link, &cond); +    return inst_Thumb_is_direct_branch_link(inst, &link, &cond, info);  } -int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond) +int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond, struct decode_info *info)  {      int is_direct_branch = 1; @@ -166,12 +145,12 @@ int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *i          /* B (encoding T4); BL (encoding T1) */          if (inst & 0x00004000) {              *is_link = 1; -            instr_sub_type = OCSD_S_INSTR_BR_LINK; +            info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          }      } else if ((inst & 0xf800d001) == 0xf000c000) {          /* BLX (imm) (encoding T2) */          *is_link = 1; -        instr_sub_type = OCSD_S_INSTR_BR_LINK; +        info->instr_sub_type = OCSD_S_INSTR_BR_LINK;      } else if ((inst & 0xf5000000) == 0xb1000000) {          /* CB(NZ) */          *is_cond = 1; @@ -197,13 +176,13 @@ int inst_Thumb_wfiwfe(uint32_t inst)      return is_wfiwfe;  } -int inst_Thumb_is_indirect_branch(uint32_t inst) +int inst_Thumb_is_indirect_branch(uint32_t inst, struct decode_info *info)  {      uint8_t link; -    return inst_Thumb_is_indirect_branch_link(inst, &link); +    return inst_Thumb_is_indirect_branch_link(inst, &link, info);  } -int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) +int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info)  {      /* See e.g. PFT Table 2-3 and Table 2-5 */      int is_branch = 1; @@ -212,20 +191,20 @@ int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link)          /* BX, BLX (reg) [v8M includes BXNS, BLXNS] */          if (inst & 0x00800000) {              *is_link = 1; -            instr_sub_type = OCSD_S_INSTR_BR_LINK; +            info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          }          else if ((inst & 0x00780000) == 0x00700000) { -            instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET;  /* BX LR */ +            info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET;  /* BX LR */          }      } else if ((inst & 0xfff0d000) == 0xf3c08000) {          /* BXJ: in v8 this behaves like BX */      } else if ((inst & 0xff000000) == 0xbd000000) {          /* POP {pc} */ -        instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; +        info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET;      } else if ((inst & 0xfd870000) == 0x44870000) {          /* MOV PC,reg or ADD PC,reg */ -        if ((inst & 0xffff0000) == 0x46f700000) -            instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC,LR */ +        if ((inst & 0xffff0000) == 0x46f70000) +            info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC,LR */      } else if ((inst & 0xfff0ffe0) == 0xe8d0f000) {          /* TBB/TBH */      } else if ((inst & 0xffd00000) == 0xe8100000) { @@ -241,26 +220,26 @@ int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link)      } else if ((inst & 0xfff0f800) == 0xf850f800) {          /* LDR PC,imm (T4) */          if((inst & 0x000f0f00) == 0x000d0b00) -            instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm*/ +            info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm*/      } else if ((inst & 0xfff0ffc0) == 0xf850f000) {          /* LDR PC,reg (T2) */      } else if ((inst & 0xfe508000) == 0xe8108000) {          /* LDM PC */          if ((inst & 0x0FFF0000) == 0x08BD0000) /* LDMIA [SP]!, */ -            instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* POP {...,pc} */ +            info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* POP {...,pc} */      } else {          is_branch = 0;      }      return is_branch;  } -int inst_A64_is_direct_branch(uint32_t inst) +int inst_A64_is_direct_branch(uint32_t inst, struct decode_info *info)  {      uint8_t link = 0; -    return inst_A64_is_direct_branch_link(inst, &link); +    return inst_A64_is_direct_branch_link(inst, &link, info);  } -int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link) +int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info)  {      int is_direct_branch = 1;      if ((inst & 0x7c000000) == 0x34000000) { @@ -271,7 +250,7 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link)          /* B, BL imm */          if (inst & 0x80000000) {              *is_link = 1; -            instr_sub_type = OCSD_S_INSTR_BR_LINK; +            info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          }      } else {          is_direct_branch = 0; @@ -287,13 +266,13 @@ int inst_A64_wfiwfe(uint32_t inst)      return 0;  } -int inst_A64_is_indirect_branch(uint32_t inst) +int inst_A64_is_indirect_branch(uint32_t inst, struct decode_info *info)  {      uint8_t link = 0; -    return inst_A64_is_indirect_branch_link(inst, &link); +    return inst_A64_is_indirect_branch_link(inst, &link, info);  } -int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) +int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info)  {      int is_indirect_branch = 1; @@ -301,34 +280,34 @@ int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link)          /* BR, BLR */          if (inst & 0x00200000) {              *is_link = 1; -            instr_sub_type = OCSD_S_INSTR_BR_LINK; +            info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          }      } else if ((inst & 0xfffffc1f) == 0xd65f0000) { -        instr_sub_type = OCSD_S_INSTR_V8_RET; +        info->instr_sub_type = OCSD_S_INSTR_V8_RET;          /* RET */      } else if ((inst & 0xffffffff) == 0xd69f03e0) {          /* ERET */ -        instr_sub_type = OCSD_S_INSTR_V8_ERET; -    } else if (arch_version >= 0x0803) { +        info->instr_sub_type = OCSD_S_INSTR_V8_ERET; +    } else if (info->arch_version >= 0x0803) {          /* new pointer auth instr for v8.3 arch */    -        if ((inst & 0xffdff800) == 0xd61f0800) { +        if ((inst & 0xffdff800) == 0xd71f0800) {              /* BRAA, BRAB, BLRAA, BLRBB */              if (inst & 0x00200000) {                  *is_link = 1; -                instr_sub_type = OCSD_S_INSTR_BR_LINK; +                info->instr_sub_type = OCSD_S_INSTR_BR_LINK;              } -        } else if ((inst & 0xffdff81F) == 0xd71f081F) { +        } else if ((inst & 0xffdff81F) == 0xd61f081F) {              /* BRAAZ, BRABZ, BLRAAZ, BLRBBZ */              if (inst & 0x00200000) {                  *is_link = 1; -                instr_sub_type = OCSD_S_INSTR_BR_LINK; +                info->instr_sub_type = OCSD_S_INSTR_BR_LINK;              }          } else if ((inst & 0xfffffbff) == 0xd69f0bff) {              /* ERETAA, ERETAB */ -            instr_sub_type = OCSD_S_INSTR_V8_ERET; +            info->instr_sub_type = OCSD_S_INSTR_V8_ERET;          } else if ((inst & 0xfffffbff) == 0xd65f0bff) {              /* RETAA, RETAB */ -            instr_sub_type = OCSD_S_INSTR_V8_RET; +            info->instr_sub_type = OCSD_S_INSTR_V8_RET;          } else {              is_indirect_branch = 0;          } @@ -441,39 +420,39 @@ int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc)      return is_direct_branch;  } -int inst_ARM_is_branch(uint32_t inst) +int inst_ARM_is_branch(uint32_t inst, struct decode_info *info)  { -    return inst_ARM_is_indirect_branch(inst) || +    return inst_ARM_is_indirect_branch(inst, info) ||             inst_ARM_is_direct_branch(inst);  } -int inst_Thumb_is_branch(uint32_t inst) +int inst_Thumb_is_branch(uint32_t inst, struct decode_info *info)  { -    return inst_Thumb_is_indirect_branch(inst) || -           inst_Thumb_is_direct_branch(inst); +    return inst_Thumb_is_indirect_branch(inst, info) || +           inst_Thumb_is_direct_branch(inst, info);  } -int inst_A64_is_branch(uint32_t inst) +int inst_A64_is_branch(uint32_t inst, struct decode_info *info)  { -    return inst_A64_is_indirect_branch(inst) || -           inst_A64_is_direct_branch(inst); +    return inst_A64_is_indirect_branch(inst, info) || +           inst_A64_is_direct_branch(inst, info);  } -int inst_ARM_is_branch_and_link(uint32_t inst) +int inst_ARM_is_branch_and_link(uint32_t inst, struct decode_info *info)  {      int is_branch = 1;      if ((inst & 0xf0000000) == 0xf0000000) {          if ((inst & 0xfe000000) == 0xfa000000){ -            instr_sub_type = OCSD_S_INSTR_BR_LINK; +            info->instr_sub_type = OCSD_S_INSTR_BR_LINK;              /* BLX (imm) */          } else {              is_branch = 0;          }      } else if ((inst & 0x0f000000) == 0x0b000000) { -        instr_sub_type = OCSD_S_INSTR_BR_LINK; +        info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          /* BL */      } else if ((inst & 0x0ff000f0) == 0x01200030) { -        instr_sub_type = OCSD_S_INSTR_BR_LINK; +        info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          /* BLX (reg) */      } else {          is_branch = 0; @@ -481,14 +460,14 @@ int inst_ARM_is_branch_and_link(uint32_t inst)      return is_branch;  } -int inst_Thumb_is_branch_and_link(uint32_t inst) +int inst_Thumb_is_branch_and_link(uint32_t inst, struct decode_info *info)  {      int is_branch = 1;      if ((inst & 0xff800000) == 0x47800000) { -        instr_sub_type = OCSD_S_INSTR_BR_LINK; +        info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          /* BLX (reg) */      } else if ((inst & 0xf800c000) == 0xf000c000) { -        instr_sub_type = OCSD_S_INSTR_BR_LINK; +        info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          /* BL, BLX (imm) */      } else {          is_branch = 0; @@ -496,23 +475,23 @@ int inst_Thumb_is_branch_and_link(uint32_t inst)      return is_branch;  } -int inst_A64_is_branch_and_link(uint32_t inst) +int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info)  {      int is_branch = 1;      if ((inst & 0xfffffc1f) == 0xd63f0000) {          /* BLR */ -        instr_sub_type = OCSD_S_INSTR_BR_LINK; +        info->instr_sub_type = OCSD_S_INSTR_BR_LINK;      } else if ((inst & 0xfc000000) == 0x94000000) {          /* BL */ -        instr_sub_type = OCSD_S_INSTR_BR_LINK; -    }  else if (arch_version >= 0x0803) { +        info->instr_sub_type = OCSD_S_INSTR_BR_LINK; +    }  else if (info->arch_version >= 0x0803) {          /* new pointer auth instr for v8.3 arch */          if ((inst & 0xfffff800) == 0xd73f0800) {              /* BLRAA, BLRBB */ -            instr_sub_type = OCSD_S_INSTR_BR_LINK; +            info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          } else if ((inst & 0xfffff81F) == 0xd63f081F) {              /* BLRAAZ, BLRBBZ */ -            instr_sub_type = OCSD_S_INSTR_BR_LINK; +            info->instr_sub_type = OCSD_S_INSTR_BR_LINK;          } else {              is_branch = 0;          } diff --git a/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp b/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp index 25c736387c0b..7ecd3b018dab 100644 --- a/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp +++ b/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp @@ -37,8 +37,7 @@  TrcMemAccBufPtr::TrcMemAccBufPtr(const ocsd_vaddr_t s_address, const uint8_t *p_buffer, const uint32_t size) :       TrcMemAccessorBase(MEMACC_BUFPTR, s_address, s_address+size-1), -    m_p_buffer(p_buffer), -    m_size(size) +    m_p_buffer(p_buffer)  {  } diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp index cf75e569d72a..be15e36e9cb3 100644 --- a/decoder/source/ocsd_dcd_tree.cpp +++ b/decoder/source/ocsd_dcd_tree.cpp @@ -111,6 +111,7 @@ DecodeTree::~DecodeTree()          destroyDecodeElement(i);      }      PktPrinterFact::destroyAllPrinters(m_printer_list); +    delete m_frame_deformatter_root;  } diff --git a/decoder/source/ocsd_error.cpp b/decoder/source/ocsd_error.cpp index 251964b7a4b0..74e9e4977f60 100644 --- a/decoder/source/ocsd_error.cpp +++ b/decoder/source/ocsd_error.cpp @@ -207,7 +207,7 @@ const std::string ocsdError::getErrorString(const ocsdError &error)  void ocsdError::appendErrorDetails(std::string &errStr, const ocsdError &error)  { -    int numerrstr = ((sizeof(s_errorCodeDescs) / sizeof(const char *)) / 2); +    int numerrstr = sizeof(s_errorCodeDescs) / sizeof(s_errorCodeDescs[0]);      int code = (int)error.getErrorCode();      ocsd_trc_index_t idx = error.getErrorIndex();      uint8_t chan_ID = error.getErrorChanID(); diff --git a/decoder/source/ocsd_gen_elem_stack.cpp b/decoder/source/ocsd_gen_elem_stack.cpp new file mode 100644 index 000000000000..bb758427a9b8 --- /dev/null +++ b/decoder/source/ocsd_gen_elem_stack.cpp @@ -0,0 +1,196 @@ +/* +* \file       ocsd_gen_elem_stack.cpp +* \brief      OpenCSD : List of Generic trace elements for output. +* +* \copyright  Copyright (c) 2020, 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 "common/ocsd_gen_elem_stack.h" + +OcsdGenElemStack::OcsdGenElemStack() : +    m_pElemArray(0), +    m_elemArraySize(0), +    m_elem_to_send(0), +    m_curr_elem_idx(0), +    m_send_elem_idx(0), +    m_CSID(0), +    m_is_init(false) +{ + +} + +OcsdGenElemStack::~OcsdGenElemStack() +{ +    for (int i = 0; i<m_elemArraySize; i++) +    { +        delete m_pElemArray[i].pElem; +    } +    delete [] m_pElemArray; +    m_pElemArray = 0; +} + +ocsd_err_t OcsdGenElemStack::addElem(const ocsd_trc_index_t trc_pkt_idx) +{ +    ocsd_err_t err = OCSD_OK; + +    if (((m_curr_elem_idx + 1) == m_elemArraySize) || !m_pElemArray) +    { +        err = growArray(); +        if (err) +            return err; +    } + +    // if there is a least one element then copy and increment +    // otherwise we are at base of stack. +    if (m_elem_to_send) +    { +        copyPersistentData(m_curr_elem_idx, m_curr_elem_idx + 1); +        m_curr_elem_idx++; +    } +    m_pElemArray[m_curr_elem_idx].trc_pkt_idx = trc_pkt_idx; +    m_elem_to_send++; +    return err; +} + +ocsd_err_t OcsdGenElemStack::addElemType(const ocsd_trc_index_t trc_pkt_idx, ocsd_gen_trc_elem_t elem_type) +{ +    ocsd_err_t err = addElem(trc_pkt_idx); +    if (!err) +        getCurrElem().setType(elem_type); +    return err; +} + +ocsd_err_t OcsdGenElemStack::resetElemStack() +{ +    ocsd_err_t err = OCSD_OK; +    if (!m_pElemArray) +    { +        err = growArray(); +        if (err) +            return err; +    } + +    if (!isInit()) +        return OCSD_ERR_NOT_INIT; + +    resetIndexes(); +    return err; +} + +void OcsdGenElemStack::resetIndexes() +{ +    // last time there was more than one element on stack +    if (m_curr_elem_idx > 0) +        copyPersistentData(m_curr_elem_idx, 0); + +    // indexes to bottom of stack, nothing in use at present +    m_curr_elem_idx = 0; +    m_send_elem_idx = 0; +    m_elem_to_send = 0; +} + +ocsd_datapath_resp_t OcsdGenElemStack::sendElements() +{ +    ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    if (!isInit()) +        return OCSD_RESP_FATAL_NOT_INIT; + +    while (m_elem_to_send && OCSD_DATA_RESP_IS_CONT(resp)) +    { +        resp = m_sendIf->first()->TraceElemIn(m_pElemArray[m_send_elem_idx].trc_pkt_idx, m_CSID, *(m_pElemArray[m_send_elem_idx].pElem)); +        m_send_elem_idx++; +        m_elem_to_send--; +    } + +    // clear the indexes if we are done. +    if (!m_elem_to_send) +        resetIndexes(); +    return resp; +} + +ocsd_err_t OcsdGenElemStack::growArray() +{ +    elemPtr_t *p_new_array = 0; +    const int increment = 4; +     +    p_new_array = new (std::nothrow) elemPtr_t[m_elemArraySize + increment]; + +    if (p_new_array != 0) +    { +        OcsdTraceElement *pElem = 0; + +        // fill the last increment elements with new objects +        for (int i = 0; i < increment; i++) +        { +            pElem = new (std::nothrow) OcsdTraceElement(); +            if (!pElem) +                return OCSD_ERR_MEM; +            pElem->init(); +            p_new_array[m_elemArraySize + i].pElem = pElem; +        } + +        // copy the existing objects from the old array to the start of the new one +        if (m_elemArraySize > 0) +        {             +            for (int i = 0; i < m_elemArraySize; i++) +            { +                p_new_array[i].pElem = m_pElemArray[i].pElem; +                p_new_array[i].trc_pkt_idx = m_pElemArray[i].trc_pkt_idx; +            } +        } + +        // delete the old pointer array. +        delete[] m_pElemArray; +        m_elemArraySize += increment; +        m_pElemArray = p_new_array; +    } +    else +        return OCSD_ERR_MEM; + +    return OCSD_OK; +} + +void OcsdGenElemStack::copyPersistentData(int src, int dst) +{ +    m_pElemArray[dst].pElem->copyPersistentData(*(m_pElemArray[src].pElem)); +} + +const bool OcsdGenElemStack::isInit() +{ +    if (!m_is_init) { +        if (m_elemArraySize && m_pElemArray && m_sendIf) +            m_is_init = true; +    } +    return m_is_init; +} + + +/* End of File ocsd_gen_elem_stack.cpp */ diff --git a/decoder/source/ptm/trc_pkt_decode_ptm.cpp b/decoder/source/ptm/trc_pkt_decode_ptm.cpp index 94ed5acc243a..7abee8499f46 100644 --- a/decoder/source/ptm/trc_pkt_decode_ptm.cpp +++ b/decoder/source/ptm/trc_pkt_decode_ptm.cpp @@ -67,6 +67,7 @@ ocsd_datapath_resp_t TrcPktDecodePtm::processPacket()          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; @@ -108,6 +109,7 @@ ocsd_datapath_resp_t TrcPktDecodePtm::onEOT()      // 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;  } @@ -115,6 +117,7 @@ ocsd_datapath_resp_t TrcPktDecodePtm::onEOT()  ocsd_datapath_resp_t TrcPktDecodePtm::onReset()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    m_unsync_info = UNSYNC_RESET_DECODER;      resetDecoder();      return resp;  } @@ -191,6 +194,7 @@ void TrcPktDecodePtm::initDecoder()      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();  } @@ -504,11 +508,15 @@ ocsd_datapath_resp_t TrcPktDecodePtm::processAtomRange(const ocsd_atm_val A, con      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; -    ocsd_err_t err = traceInstrToWP(bWPFound,traceWPOp,nextAddrMatch); +    // 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) @@ -576,7 +584,6 @@ ocsd_datapath_resp_t TrcPktDecodePtm::processAtomRange(const ocsd_atm_val A, con              break;          } -        m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);          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()) @@ -595,7 +602,6 @@ ocsd_datapath_resp_t TrcPktDecodePtm::processAtomRange(const ocsd_atm_val A, con          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_instr_info.instr_size);              m_output_elem.setISA(m_curr_pe_state.isa);              m_output_elem.setLastInstrCond(m_instr_info.is_conditional); diff --git a/decoder/source/stm/trc_pkt_decode_stm.cpp b/decoder/source/stm/trc_pkt_decode_stm.cpp index a47e96312546..1bb8d7346be0 100644 --- a/decoder/source/stm/trc_pkt_decode_stm.cpp +++ b/decoder/source/stm/trc_pkt_decode_stm.cpp @@ -68,6 +68,7 @@ ocsd_datapath_resp_t TrcPktDecodeStm::processPacket()          {          case NO_SYNC:              m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); +            m_output_elem.setUnSyncEOTReason(m_unsync_info);              resp = outputTraceElement(m_output_elem);              m_curr_state = WAIT_SYNC;              break; @@ -90,6 +91,7 @@ ocsd_datapath_resp_t TrcPktDecodeStm::onEOT()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT;      m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE); +    m_output_elem.setUnSyncEOTReason(UNSYNC_EOT);      resp = outputTraceElement(m_output_elem);      return resp;  } @@ -97,6 +99,7 @@ ocsd_datapath_resp_t TrcPktDecodeStm::onEOT()  ocsd_datapath_resp_t TrcPktDecodeStm::onReset()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; +    m_unsync_info = UNSYNC_RESET_DECODER;      resetDecoder();      return resp;  } @@ -127,7 +130,7 @@ void TrcPktDecodeStm::initDecoder()      // base decoder state - STM requires no memory and instruction decode.      setUsesMemAccess(false);      setUsesIDecode(false); - +    m_unsync_info = UNSYNC_INIT_DECODER;      resetDecoder();  } @@ -166,6 +169,7 @@ ocsd_datapath_resp_t TrcPktDecodeStm::decodePacket(bool &bPktDone)      case STM_PKT_BAD_SEQUENCE:   /**< Incorrect protocol sequence */      case STM_PKT_RESERVED:          resp = OCSD_RESP_FATAL_INVALID_DATA; +        m_unsync_info = UNSYNC_BAD_PACKET;      case STM_PKT_NOTSYNC:          resetDecoder();          break; diff --git a/decoder/source/trc_component.cpp b/decoder/source/trc_component.cpp index 47200a1ead67..dae92d4213de 100644 --- a/decoder/source/trc_component.cpp +++ b/decoder/source/trc_component.cpp @@ -41,7 +41,13 @@ public:      {          m_pComp = 0;      }; -    virtual ~ errLogAttachMonitor() {}; +    virtual ~ errLogAttachMonitor() +    { +        if (m_pComp) +            m_pComp->getErrorLogAttachPt()->set_notifier(0); +        m_pComp = 0; +         +    };      virtual void attachNotify(const int num_attached)      {          if(m_pComp) @@ -73,6 +79,8 @@ TraceComponent::TraceComponent(const std::string &name, int instIDNum)  TraceComponent::~TraceComponent()  { +    if (m_pErrAttachMon) +        delete m_pErrAttachMon;  }  void TraceComponent::Init(const std::string &name) @@ -140,9 +148,7 @@ void TraceComponent::updateErrorLogLevel()  ocsd_err_t TraceComponent::setComponentOpMode(uint32_t op_flags)  { -    if( (~m_supported_op_flags & op_flags) != 0) -        return OCSD_ERR_INVALID_PARAM_VAL; -    m_op_flags = op_flags; +    m_op_flags = op_flags & m_supported_op_flags;      return OCSD_OK;  } diff --git a/decoder/source/trc_core_arch_map.cpp b/decoder/source/trc_core_arch_map.cpp index 70a25eef0359..a26f79db996e 100644 --- a/decoder/source/trc_core_arch_map.cpp +++ b/decoder/source/trc_core_arch_map.cpp @@ -34,10 +34,12 @@  #include "common/trc_core_arch_map.h" -static struct _ap_map_elements { +typedef struct _ap_map_elements {      const char *name;      ocsd_arch_profile_t ap; -} ap_map_array[] =  +} ap_map_elem_t; + +static ap_map_elem_t ap_map_array[] =   {      { "Cortex-A77", { ARCH_V8r3, profile_CortexA } },      { "Cortex-A76", { ARCH_V8r3, profile_CortexA } }, @@ -70,12 +72,28 @@ static struct _ap_map_elements {      { "Cortex-M4", { ARCH_V7, profile_CortexM } }  };    +static ap_map_elem_t arch_map_array[] =  +{ +    { "ARMv7-A", { ARCH_V7, profile_CortexA } }, +    { "ARMv7-R", { ARCH_V7, profile_CortexR } }, +    { "ARMv7-M", { ARCH_V7, profile_CortexM } }, +    { "ARMv8-A", { ARCH_V8, profile_CortexA } }, +    { "ARMv8.3-A", { ARCH_V8r3, profile_CortexA } }, +    { "ARMv8-R", { ARCH_V8, profile_CortexR } }, +    { "ARMv8-M", { ARCH_V8, profile_CortexM } }, +}; +  CoreArchProfileMap::CoreArchProfileMap()  { -    for(unsigned i = 0; i < sizeof(ap_map_array)/sizeof(_ap_map_elements); i++) +    unsigned i; +    for (i = 0; i < sizeof(ap_map_array) / sizeof(_ap_map_elements); i++)      {          core_profiles[ap_map_array[i].name] = ap_map_array[i].ap;      } +    for (i = 0; i < sizeof(arch_map_array) / sizeof(_ap_map_elements); i++) +    { +        arch_profiles[arch_map_array[i].name] = arch_map_array[i].ap; +    }  }  /* End of File trc_core_arch_map.cpp */ diff --git a/decoder/source/trc_gen_elem.cpp b/decoder/source/trc_gen_elem.cpp index b3ec75f059d4..e1774203ebc5 100644 --- a/decoder/source/trc_gen_elem.cpp +++ b/decoder/source/trc_gen_elem.cpp @@ -46,6 +46,7 @@ static const char *s_elem_descs[][2] =      {"OCSD_GEN_TRC_ELEM_EO_TRACE","End of the available trace in the buffer."},      {"OCSD_GEN_TRC_ELEM_PE_CONTEXT","PE status update / change (arch, ctxtid, vmid etc)."},      {"OCSD_GEN_TRC_ELEM_INSTR_RANGE","Traced N consecutive instructions from addr (no intervening events or data elements), may have data assoc key"}, +    {"OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH","Traced N instructions in a range, but incomplete information as to program execution path from start to end of range"},      {"OCSD_GEN_TRC_ELEM_ADDR_NACC","Tracing in inaccessible memory area."},      {"OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN","Tracing unknown address area."},      {"OCSD_GEN_TRC_ELEM_EXCEPTION","Exception"}, @@ -62,7 +63,8 @@ static const char *instr_type[] = {      "BR  ",      "iBR ",      "ISB ", -    "DSB.DMB" +    "DSB.DMB", +    "WFI.WFE"  };  #define T_SIZE (sizeof(instr_type) / sizeof(const char *)) @@ -94,10 +96,20 @@ static const char *s_isa_str[] = {     "Unk"       /**< ISA not yet known */  }; +static const char *s_unsync_reason[] = { +    "undefined",            // UNSYNC_UNKNOWN - unknown /undefined +    "init-decoder",         // UNSYNC_INIT_DECODER - decoder intialisation - start of trace. +    "reset-decoder",        // UNSYNC_RESET_DECODER - decoder reset. +    "overflow",             // UNSYNC_OVERFLOW - overflow packet - need to re-sync +    "discard",              // UNSYNC_DISCARD - specl trace discard - need to re-sync +    "bad-packet",           // UNSYNC_BAD_PACKET - bad packet at input - resync to restart. +    "end-of-trace",         // UNSYNC_EOT - end of trace info. +}; +  void OcsdTraceElement::toString(std::string &str) const  {      std::ostringstream oss; -    int num_str = ((sizeof(s_elem_descs) / sizeof(const char *)) / 2); +    int num_str = sizeof(s_elem_descs) / sizeof(s_elem_descs[0]);      int typeIdx = (int)this->elem_type;      if(typeIdx < num_str)      { @@ -122,6 +134,11 @@ void OcsdTraceElement::toString(std::string &str) const              oss << " 0x" << std::hex << st_addr << " ";              break; +        case OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH: +            oss << "first 0x" << std::hex << st_addr << ":[next 0x" << en_addr << "] "; +            oss << "num_i(" << std::dec << num_instr_range << ") "; +            break; +          case OCSD_GEN_TRC_ELEM_EXCEPTION:              if (excep_ret_addr == 1)              { @@ -167,6 +184,12 @@ void OcsdTraceElement::toString(std::string &str) const                  oss << " Numbered:" << std::dec << trace_event.ev_number << "; ";              break; +        case OCSD_GEN_TRC_ELEM_EO_TRACE: +        case OCSD_GEN_TRC_ELEM_NO_SYNC: +            if (unsync_eot_info <= UNSYNC_EOT) +                oss << " [" << s_unsync_reason[unsync_eot_info] << "]"; +            break; +          default: break;          }          if(has_cc) | 
