1 /*! 2 * \file trc_pkt_decode_etmv3.cpp 3 * \brief OpenCSD : ETMv3 trace packet decode. 4 * 5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. 6 */ 7 8 /* 9 * Redistribution and use in source and binary forms, with or without modification, 10 * are permitted provided that the following conditions are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the copyright holder nor the names of its contributors 20 * may be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "opencsd/etmv3/trc_pkt_decode_etmv3.h" 36 37 #define DCD_NAME "DCD_ETMV3" 38 39 TrcPktDecodeEtmV3::TrcPktDecodeEtmV3() : 40 TrcPktDecodeBase(DCD_NAME) 41 { 42 initDecoder(); 43 } 44 45 TrcPktDecodeEtmV3::TrcPktDecodeEtmV3(int instIDNum) : 46 TrcPktDecodeBase(DCD_NAME, instIDNum) 47 { 48 initDecoder(); 49 } 50 51 TrcPktDecodeEtmV3::~TrcPktDecodeEtmV3() 52 { 53 } 54 55 56 /* implementation packet decoding interface */ 57 ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPacket() 58 { 59 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 60 bool bPktDone = false; 61 62 if(!m_config) 63 return OCSD_RESP_FATAL_NOT_INIT; 64 65 // iterate round the state machine, waiting for sync, then decoding packets. 66 while(!bPktDone) 67 { 68 switch(m_curr_state) 69 { 70 case NO_SYNC: 71 // output the initial not synced packet to the sink 72 resp = sendUnsyncPacket(); 73 m_curr_state = WAIT_ASYNC; // immediate wait for ASync and actually check out the packet 74 break; 75 76 case WAIT_ASYNC: 77 // if async, wait for ISync, but this packet done. 78 if(m_curr_packet_in->getType() == ETM3_PKT_A_SYNC) 79 m_curr_state = WAIT_ISYNC; 80 bPktDone = true; 81 break; 82 83 case WAIT_ISYNC: 84 m_bWaitISync = true; // we are waiting for ISync 85 if((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC) || 86 (m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE)) 87 { 88 // process the ISync immediately as the first ISync seen. 89 resp = processISync((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE),true); 90 m_curr_state = SEND_PKTS; 91 m_bWaitISync = false; 92 } 93 // something like TS, CC, PHDR+CC, which after ASYNC may be valid prior to ISync 94 else if(preISyncValid(m_curr_packet_in->getType())) 95 { 96 // decode anything that might be valid - send will be set automatically 97 resp = decodePacket(bPktDone); 98 } 99 else 100 bPktDone = true; 101 break; 102 103 case DECODE_PKTS: 104 resp = decodePacket(bPktDone); 105 break; 106 107 case SEND_PKTS: 108 resp = m_outputElemList.sendElements(); 109 if(OCSD_DATA_RESP_IS_CONT(resp)) 110 m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS; 111 bPktDone = true; 112 break; 113 114 default: 115 bPktDone = true; 116 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,"Unknown Decoder State")); 117 resetDecoder(); // mark decoder as unsynced - dump any current state. 118 resp = OCSD_RESP_FATAL_SYS_ERR; 119 break; 120 } 121 } 122 123 return resp; 124 } 125 126 ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT() 127 { 128 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 129 OcsdTraceElement *pElem = 0; 130 try { 131 pElem = GetNextOpElem(resp); 132 pElem->setType(OCSD_GEN_TRC_ELEM_EO_TRACE); 133 pElem->setUnSyncEOTReason(UNSYNC_EOT); 134 m_outputElemList.commitAllPendElem(); 135 m_curr_state = SEND_PKTS; 136 resp = m_outputElemList.sendElements(); 137 if(OCSD_DATA_RESP_IS_CONT(resp)) 138 m_curr_state = DECODE_PKTS; 139 } 140 catch(ocsdError &err) 141 { 142 LogError(err); 143 resetDecoder(); // mark decoder as unsynced - dump any current state. 144 } 145 return resp; 146 } 147 148 ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset() 149 { 150 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 151 m_unsync_info = UNSYNC_RESET_DECODER; 152 resetDecoder(); 153 return resp; 154 } 155 156 ocsd_datapath_resp_t TrcPktDecodeEtmV3::onFlush() 157 { 158 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 159 if(m_curr_state == SEND_PKTS) 160 { 161 resp = m_outputElemList.sendElements(); 162 if(OCSD_DATA_RESP_IS_CONT(resp)) 163 m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS; 164 } 165 return resp; 166 } 167 168 ocsd_err_t TrcPktDecodeEtmV3::onProtocolConfig() 169 { 170 ocsd_err_t err = OCSD_OK; 171 if(m_config) 172 { 173 // set some static config elements 174 m_CSID = m_config->getTraceID(); 175 176 // check config compatible with current decoder support level. 177 // at present no data trace; 178 if(m_config->GetTraceMode() != EtmV3Config::TM_INSTR_ONLY) 179 { 180 err = OCSD_ERR_HW_CFG_UNSUPP; 181 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv3 trace decoder : data trace decode not yet supported")); 182 } 183 184 // need to set up core profile info in follower 185 ocsd_arch_profile_t arch_profile; 186 arch_profile.arch = m_config->getArchVersion(); 187 arch_profile.profile = m_config->getCoreProfile(); 188 m_code_follower.setArchProfile(arch_profile); 189 m_code_follower.setMemSpaceCSID(m_CSID); 190 m_outputElemList.initCSID(m_CSID); 191 } 192 else 193 err = OCSD_ERR_NOT_INIT; 194 return err; 195 } 196 197 /* local decode methods */ 198 199 // initialise on creation 200 void TrcPktDecodeEtmV3::initDecoder() 201 { 202 m_CSID = 0; 203 resetDecoder(); 204 m_unsync_info = UNSYNC_INIT_DECODER; 205 m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt()); 206 m_outputElemList.initSendIf(getTraceElemOutAttachPt()); 207 } 208 209 // reset for first use / re-use. 210 void TrcPktDecodeEtmV3::resetDecoder() 211 { 212 m_curr_state = NO_SYNC; // mark as not synced 213 m_bNeedAddr = true; 214 m_bSentUnknown = false; 215 m_bWaitISync = false; 216 m_outputElemList.reset(); 217 } 218 219 OcsdTraceElement *TrcPktDecodeEtmV3::GetNextOpElem(ocsd_datapath_resp_t &resp) 220 { 221 OcsdTraceElement *pElem = m_outputElemList.getNextElem(m_index_curr_pkt); 222 if(pElem == 0) 223 { 224 resp = OCSD_RESP_FATAL_NOT_INIT; 225 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_MEM,m_index_curr_pkt,m_CSID,"Memory Allocation Error - fatal"); 226 } 227 return pElem; 228 } 229 230 bool TrcPktDecodeEtmV3::preISyncValid(ocsd_etmv3_pkt_type pkt_type) 231 { 232 bool bValid = false; 233 // its a timestamp 234 if((pkt_type == ETM3_PKT_TIMESTAMP) || 235 // or we are cycleacc and its a packet that can have CC in it 236 (m_config->isCycleAcc() && ((pkt_type == ETM3_PKT_CYCLE_COUNT) || (pkt_type == ETM3_PKT_P_HDR))) 237 ) 238 bValid = true; 239 return bValid; 240 } 241 242 // simple packet transforms handled here, more complex processing passed on to specific routines. 243 ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone) 244 { 245 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 246 bool bISyncHasCC = false; 247 OcsdTraceElement *pElem = 0; 248 pktDone = false; 249 250 // there may be pended packets that can now be committed. 251 // only the branch address with exception and cancel element can cancel 252 // if not one of those, commit immediately, otherwise defer to branch address handler. 253 if(m_curr_packet_in->getType() != ETM3_PKT_BRANCH_ADDRESS) 254 m_outputElemList.commitAllPendElem(); 255 256 try { 257 258 switch(m_curr_packet_in->getType()) 259 { 260 261 case ETM3_PKT_NOTSYNC: 262 // mark as not synced - must have lost sync in the packet processor somehow 263 throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Trace Packet Synchronisation Lost"); 264 break; 265 266 // no action for these packets - ignore and continue 267 case ETM3_PKT_INCOMPLETE_EOT: 268 case ETM3_PKT_A_SYNC: 269 case ETM3_PKT_IGNORE: 270 break; 271 272 // markers for valid packets 273 case ETM3_PKT_CYCLE_COUNT: 274 pElem = GetNextOpElem(resp); 275 pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); 276 pElem->setCycleCount(m_curr_packet_in->getCycleCount()); 277 break; 278 279 case ETM3_PKT_TRIGGER: 280 pElem = GetNextOpElem(resp); 281 pElem->setType(OCSD_GEN_TRC_ELEM_EVENT); 282 pElem->setEvent(EVENT_TRIGGER,0); 283 break; 284 285 case ETM3_PKT_BRANCH_ADDRESS: 286 resp = processBranchAddr(); 287 break; 288 289 case ETM3_PKT_I_SYNC_CYCLE: 290 bISyncHasCC = true; 291 case ETM3_PKT_I_SYNC: 292 resp = processISync(bISyncHasCC); 293 break; 294 295 case ETM3_PKT_P_HDR: 296 resp = processPHdr(); 297 break; 298 299 case ETM3_PKT_CONTEXT_ID: 300 pElem = GetNextOpElem(resp); 301 pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 302 m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID()); 303 pElem->setContext(m_PeContext); 304 break; 305 306 case ETM3_PKT_VMID: 307 pElem = GetNextOpElem(resp); 308 pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 309 m_PeContext.setVMID(m_curr_packet_in->getVMID()); 310 pElem->setContext(m_PeContext); 311 break; 312 313 case ETM3_PKT_EXCEPTION_ENTRY: 314 pElem = GetNextOpElem(resp); 315 pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION); 316 pElem->setExcepMarker(); // exception entries are always v7M data markers in ETMv3 trace. 317 break; 318 319 case ETM3_PKT_EXCEPTION_EXIT: 320 pElem = GetNextOpElem(resp); 321 pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET); 322 pendExceptionReturn(); 323 break; 324 325 case ETM3_PKT_TIMESTAMP: 326 pElem = GetNextOpElem(resp); 327 pElem->setType(OCSD_GEN_TRC_ELEM_TIMESTAMP); 328 pElem->setTS(m_curr_packet_in->getTS()); 329 break; 330 331 // data packets - data trace not supported at present 332 case ETM3_PKT_STORE_FAIL: 333 case ETM3_PKT_OOO_DATA: 334 case ETM3_PKT_OOO_ADDR_PLC: 335 case ETM3_PKT_NORM_DATA: 336 case ETM3_PKT_DATA_SUPPRESSED: 337 case ETM3_PKT_VAL_NOT_TRACED: 338 case ETM3_PKT_BAD_TRACEMODE: 339 resp = OCSD_RESP_FATAL_INVALID_DATA; 340 throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,m_index_curr_pkt,m_CSID,"Invalid packet type : Data Tracing decode not supported."); 341 break; 342 343 // packet errors 344 case ETM3_PKT_BAD_SEQUENCE: 345 resp = OCSD_RESP_FATAL_INVALID_DATA; 346 throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Bad Packet sequence."); 347 break; 348 349 default: 350 case ETM3_PKT_RESERVED: 351 resp = OCSD_RESP_FATAL_INVALID_DATA; 352 throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Reserved or unknown packet ID."); 353 break; 354 } 355 m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS; 356 pktDone = !m_outputElemList.elemToSend(); 357 } 358 catch(ocsdError &err) 359 { 360 LogError(err); 361 m_unsync_info = UNSYNC_BAD_PACKET; 362 resetDecoder(); // mark decoder as unsynced - dump any current state. 363 pktDone = true; 364 } 365 catch(...) 366 { 367 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,m_CSID,"Bad Packet sequence.")); 368 resp = OCSD_RESP_FATAL_SYS_ERR; 369 m_unsync_info = UNSYNC_BAD_PACKET; 370 resetDecoder(); // mark decoder as unsynced - dump any current state. 371 pktDone = true; 372 } 373 return resp; 374 } 375 376 ocsd_datapath_resp_t TrcPktDecodeEtmV3::sendUnsyncPacket() 377 { 378 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 379 OcsdTraceElement *pElem = 0; 380 try { 381 pElem = GetNextOpElem(resp); 382 pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC); 383 pElem->setUnSyncEOTReason(m_unsync_info); 384 resp = m_outputElemList.sendElements(); 385 } 386 catch(ocsdError &err) 387 { 388 LogError(err); 389 m_unsync_info = UNSYNC_BAD_PACKET; 390 resetDecoder(); // mark decoder as unsynced - dump any current state. 391 } 392 return resp; 393 } 394 395 void TrcPktDecodeEtmV3::setNeedAddr(bool bNeedAddr) 396 { 397 m_bNeedAddr = bNeedAddr; 398 m_bSentUnknown = false; 399 } 400 401 ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC, const bool firstSync /* = false */) 402 { 403 // map ISync reason to generic reason codes. 404 static trace_on_reason_t on_map[] = { TRACE_ON_NORMAL, TRACE_ON_NORMAL, 405 TRACE_ON_OVERFLOW, TRACE_ON_EX_DEBUG }; 406 407 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 408 bool ctxtUpdate = m_curr_packet_in->isCtxtUpdated(); 409 OcsdTraceElement *pElem = 0; 410 411 try { 412 413 pElem = GetNextOpElem(resp); 414 415 if(firstSync || (m_curr_packet_in->getISyncReason() != iSync_Periodic)) 416 { 417 pElem->setType(OCSD_GEN_TRC_ELEM_TRACE_ON); 418 pElem->setTraceOnReason(on_map[(int)m_curr_packet_in->getISyncReason()]); 419 pElem = GetNextOpElem(resp); 420 } 421 422 // look for context changes.... 423 if(ctxtUpdate || firstSync) 424 { 425 // if not first time out, read existing context in output element, 426 // otherwise we are setting it new. 427 if(firstSync) 428 m_PeContext.resetCtxt(); 429 430 if(m_curr_packet_in->isCtxtIDUpdated()) 431 m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID()); 432 if(m_curr_packet_in->isVMIDUpdated()) 433 m_PeContext.setVMID(m_curr_packet_in->getVMID()); 434 if(m_curr_packet_in->isCtxtFlagsUpdated()) 435 { 436 m_PeContext.setEL(m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown); 437 m_PeContext.setSecLevel(m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure); 438 } 439 440 // prepare the context packet 441 pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 442 pElem->setContext(m_PeContext); 443 pElem->setISA(m_curr_packet_in->ISA()); 444 445 // with cycle count... 446 if(m_curr_packet_in->getISyncHasCC()) 447 pElem->setCycleCount(m_curr_packet_in->getCycleCount()); 448 449 } 450 451 // set ISync address - if it is a valid I address 452 if(!m_curr_packet_in->getISyncNoAddr()) 453 { 454 if(m_curr_packet_in->getISyncIsLSiPAddr()) 455 { 456 // TBD: handle extra data processing instruction for data trace 457 // need to output E atom relating to the data instruction 458 // rare - on start-up case. 459 460 // main instruction address saved in data address for this packet type. 461 m_IAddr = m_curr_packet_in->getDataAddr(); 462 } 463 else 464 { 465 m_IAddr = m_curr_packet_in->getAddr(); 466 } 467 setNeedAddr(false); // ready to process atoms. 468 } 469 m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS; 470 } 471 catch(ocsdError &err) 472 { 473 LogError(err); 474 m_unsync_info = UNSYNC_BAD_PACKET; 475 resetDecoder(); // mark decoder as unsynced - dump any current state. 476 } 477 return resp; 478 } 479 480 ocsd_datapath_resp_t TrcPktDecodeEtmV3::processBranchAddr() 481 { 482 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 483 OcsdTraceElement *pElem = 0; 484 bool bUpdatePEContext = false; 485 486 // might need to cancel something ... if the last output was an instruction range or excep return 487 if(m_curr_packet_in->isExcepCancel()) 488 m_outputElemList.cancelPendElem(); 489 else 490 m_outputElemList.commitAllPendElem(); // otherwise commit any pending elements. 491 492 // record the address 493 m_IAddr = m_curr_packet_in->getAddr(); 494 setNeedAddr(false); // no longer need an address. 495 496 // exception packet - may need additional output 497 if(m_curr_packet_in->isExcepPkt()) 498 { 499 // exeception packet may have exception, context change, or both. 500 // check for context change 501 if(m_curr_packet_in->isCtxtUpdated()) 502 { 503 504 ocsd_sec_level sec = m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure; 505 if(sec != m_PeContext.getSecLevel()) 506 { 507 m_PeContext.setSecLevel(sec); 508 bUpdatePEContext = true; 509 } 510 ocsd_ex_level pkt_el = m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown; 511 if(pkt_el != m_PeContext.getEL()) 512 { 513 m_PeContext.setEL(pkt_el); 514 bUpdatePEContext = true; 515 } 516 } 517 518 // now decide if we need to send any packets out. 519 try { 520 521 if(bUpdatePEContext) 522 { 523 pElem = GetNextOpElem(resp); 524 pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 525 pElem->setContext(m_PeContext); 526 } 527 528 // check for exception 529 if(m_curr_packet_in->excepNum() != 0) 530 { 531 pElem = GetNextOpElem(resp); 532 pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION); 533 pElem->setExceptionNum(m_curr_packet_in->excepNum()); 534 } 535 536 // finally - do we have anything to send yet? 537 m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS; 538 } 539 catch(ocsdError &err) 540 { 541 LogError(err); 542 m_unsync_info = UNSYNC_BAD_PACKET; 543 resetDecoder(); // mark decoder as unsynced - dump any current state. 544 } 545 } 546 return resp; 547 } 548 549 550 ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPHdr() 551 { 552 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 553 OcsdTraceElement *pElem = 0; 554 ocsd_isa isa; 555 Etmv3Atoms atoms(m_config->isCycleAcc()); 556 557 atoms.initAtomPkt(m_curr_packet_in,m_index_curr_pkt); 558 isa = m_curr_packet_in->ISA(); 559 m_code_follower.setMemSpaceAccess((m_PeContext.getSecLevel() == ocsd_sec_secure) ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N); 560 561 try 562 { 563 do 564 { 565 // if we do not have a valid address then send any cycle count elements 566 // and stop processing 567 if(m_bNeedAddr) 568 { 569 // output unknown address packet or a cycle count packet 570 if(!m_bSentUnknown || m_config->isCycleAcc()) 571 { 572 pElem = GetNextOpElem(resp); 573 if(m_bSentUnknown || !atoms.numAtoms()) 574 pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); 575 else 576 pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN); 577 if(m_config->isCycleAcc()) 578 pElem->setCycleCount(atoms.getRemainCC()); 579 m_bSentUnknown = true; 580 } 581 atoms.clearAll(); // skip remaining atoms 582 } 583 else // have an address, can process atoms 584 { 585 pElem = GetNextOpElem(resp); 586 pElem->setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); 587 588 // cycle accurate may have a cycle count to use 589 if(m_config->isCycleAcc()) 590 { 591 // note: it is possible to have a CC only atom packet. 592 if(!atoms.numAtoms()) // override type if CC only 593 pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); 594 // set cycle count 595 pElem->setCycleCount(atoms.getAtomCC()); 596 } 597 598 // now process the atom 599 if(atoms.numAtoms()) 600 { 601 m_code_follower.setISA(isa); 602 m_code_follower.followSingleAtom(m_IAddr,atoms.getCurrAtomVal()); 603 604 // valid code range 605 if(m_code_follower.hasRange()) 606 { 607 pElem->setAddrRange(m_IAddr,m_code_follower.getRangeEn()); 608 pElem->setLastInstrInfo(atoms.getCurrAtomVal() == ATOM_E, 609 m_code_follower.getInstrType(), 610 m_code_follower.getInstrSubType(),m_code_follower.getInstrSize()); 611 pElem->setLastInstrCond(m_code_follower.isCondInstr()); 612 pElem->setISA(isa); 613 if(m_code_follower.hasNextAddr()) 614 m_IAddr = m_code_follower.getNextAddr(); 615 else 616 setNeedAddr(true); 617 } 618 619 // next address has new ISA? 620 if(m_code_follower.ISAChanged()) 621 isa = m_code_follower.nextISA(); 622 623 // there is a nacc 624 if(m_code_follower.isNacc()) 625 { 626 if(m_code_follower.hasRange()) 627 { 628 pElem = GetNextOpElem(resp); 629 pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); 630 } 631 else 632 pElem->updateType(OCSD_GEN_TRC_ELEM_ADDR_NACC); 633 pElem->setAddrStart(m_code_follower.getNaccAddr()); 634 setNeedAddr(true); 635 m_code_follower.clearNacc(); // we have generated some code for the nacc. 636 } 637 } 638 639 atoms.clearAtom(); // next atom 640 } 641 } 642 while(atoms.numAtoms()); 643 644 // is tha last element an atom? 645 int numElem = m_outputElemList.getNumElem(); 646 if(numElem >= 1) 647 { 648 // if the last thing is an instruction range, pend it - could be cancelled later. 649 if(m_outputElemList.getElemType(numElem-1) == OCSD_GEN_TRC_ELEM_INSTR_RANGE) 650 m_outputElemList.pendLastNElem(1); 651 } 652 653 // finally - do we have anything to send yet? 654 m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS; 655 } 656 catch(ocsdError &err) 657 { 658 LogError(err); 659 m_unsync_info = UNSYNC_BAD_PACKET; 660 resetDecoder(); // mark decoder as unsynced - dump any current state. 661 } 662 return resp; 663 } 664 665 // if v7M -> pend only ERET, if V7A/R pend ERET and prev instr. 666 void TrcPktDecodeEtmV3::pendExceptionReturn() 667 { 668 int pendElem = 1; 669 if(m_config->getCoreProfile() != profile_CortexM) 670 { 671 int nElem = m_outputElemList.getNumElem(); 672 if(nElem > 1) 673 { 674 if(m_outputElemList.getElemType(nElem - 2) == OCSD_GEN_TRC_ELEM_INSTR_RANGE) 675 pendElem = 2; // need to pend instr+eret for A/R 676 } 677 } 678 m_outputElemList.pendLastNElem(pendElem); 679 } 680 681 /* End of File trc_pkt_decode_etmv3.cpp */ 682