1 /* 2 * \file trc_pkt_decode_ptm.cpp 3 * \brief OpenCSD : PTM packet decoder. 4 * 5 * \copyright Copyright (c) 2016, 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 <sstream> 36 #include "opencsd/ptm/trc_pkt_decode_ptm.h" 37 38 #define DCD_NAME "DCD_PTM" 39 40 TrcPktDecodePtm::TrcPktDecodePtm() 41 : TrcPktDecodeBase(DCD_NAME) 42 { 43 initDecoder(); 44 } 45 46 TrcPktDecodePtm::TrcPktDecodePtm(int instIDNum) 47 : TrcPktDecodeBase(DCD_NAME,instIDNum) 48 { 49 initDecoder(); 50 } 51 52 TrcPktDecodePtm::~TrcPktDecodePtm() 53 { 54 } 55 56 /*********************** implementation packet decoding interface */ 57 58 ocsd_datapath_resp_t TrcPktDecodePtm::processPacket() 59 { 60 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 61 bool bPktDone = false; 62 63 while(!bPktDone) 64 { 65 switch(m_curr_state) 66 { 67 case NO_SYNC: 68 // no sync - output a no sync packet then transition to wait sync. 69 m_output_elem.elem_type = OCSD_GEN_TRC_ELEM_NO_SYNC; 70 resp = outputTraceElement(m_output_elem); 71 m_curr_state = (m_curr_packet_in->getType() == PTM_PKT_A_SYNC) ? WAIT_ISYNC : WAIT_SYNC; 72 bPktDone = true; 73 break; 74 75 case WAIT_SYNC: 76 if(m_curr_packet_in->getType() == PTM_PKT_A_SYNC) 77 m_curr_state = WAIT_ISYNC; 78 bPktDone = true; 79 break; 80 81 case WAIT_ISYNC: 82 if(m_curr_packet_in->getType() == PTM_PKT_I_SYNC) 83 m_curr_state = DECODE_PKTS; 84 else 85 bPktDone = true; 86 break; 87 88 case DECODE_PKTS: 89 resp = decodePacket(); 90 bPktDone = true; 91 break; 92 93 default: 94 // should only see these after a _WAIT resp - in flush handler 95 case CONT_ISYNC: 96 case CONT_ATOM: 97 bPktDone = true; 98 // throw a decoder error 99 break; 100 } 101 } 102 return resp; 103 } 104 105 ocsd_datapath_resp_t TrcPktDecodePtm::onEOT() 106 { 107 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 108 // shouldn't be any packets left to be processed - flush shoudl have done this. 109 // just output the end of trace marker 110 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE); 111 resp = outputTraceElement(m_output_elem); 112 return resp; 113 } 114 115 ocsd_datapath_resp_t TrcPktDecodePtm::onReset() 116 { 117 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 118 resetDecoder(); 119 return resp; 120 } 121 122 ocsd_datapath_resp_t TrcPktDecodePtm::onFlush() 123 { 124 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 125 resp = contProcess(); 126 return resp; 127 } 128 129 // atom and isync packets can have multiple ouput packets that can be _WAITed mid stream. 130 ocsd_datapath_resp_t TrcPktDecodePtm::contProcess() 131 { 132 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 133 switch(m_curr_state) 134 { 135 case CONT_ISYNC: 136 resp = processIsync(); 137 break; 138 139 case CONT_ATOM: 140 resp = processAtom(); 141 break; 142 143 case CONT_WPUP: 144 resp = processWPUpdate(); 145 break; 146 147 case CONT_BRANCH: 148 resp = processBranch(); 149 break; 150 151 default: break; // not a state that requires further processing 152 } 153 154 if(OCSD_DATA_RESP_IS_CONT(resp) && processStateIsCont()) 155 m_curr_state = DECODE_PKTS; // continue packet processing - assuming we have not degraded into an unsynced state. 156 157 return resp; 158 } 159 160 ocsd_err_t TrcPktDecodePtm::onProtocolConfig() 161 { 162 ocsd_err_t err = OCSD_OK; 163 if(m_config == 0) 164 return OCSD_ERR_NOT_INIT; 165 166 // static config - copy of CSID for easy reference 167 m_CSID = m_config->getTraceID(); 168 169 // handle return stack implementation 170 if (m_config->hasRetStack()) 171 { 172 m_return_stack.set_active(m_config->enaRetStack()); 173 #ifdef TRC_RET_STACK_DEBUG 174 m_return_stack.set_dbg_logger(this); 175 #endif 176 } 177 178 // config options affecting decode 179 m_instr_info.pe_type.profile = m_config->coreProfile(); 180 m_instr_info.pe_type.arch = m_config->archVersion(); 181 m_instr_info.dsb_dmb_waypoints = m_config->dmsbWayPt() ? 1 : 0; 182 m_instr_info.wfi_wfe_branch = 0; 183 return err; 184 } 185 186 /****************** local decoder routines */ 187 188 void TrcPktDecodePtm::initDecoder() 189 { 190 m_CSID = 0; 191 m_instr_info.pe_type.profile = profile_Unknown; 192 m_instr_info.pe_type.arch = ARCH_UNKNOWN; 193 m_instr_info.dsb_dmb_waypoints = 0; 194 resetDecoder(); 195 } 196 197 void TrcPktDecodePtm::resetDecoder() 198 { 199 m_curr_state = NO_SYNC; 200 m_need_isync = true; // need context to start. 201 202 m_instr_info.isa = ocsd_isa_unknown; 203 m_mem_nacc_pending = false; 204 205 m_pe_context.ctxt_id_valid = 0; 206 m_pe_context.bits64 = 0; 207 m_pe_context.vmid_valid = 0; 208 m_pe_context.exception_level = ocsd_EL_unknown; 209 m_pe_context.security_level = ocsd_sec_secure; 210 m_pe_context.el_valid = 0; 211 212 m_curr_pe_state.instr_addr = 0x0; 213 m_curr_pe_state.isa = ocsd_isa_unknown; 214 m_curr_pe_state.valid = false; 215 216 m_atoms.clearAll(); 217 m_output_elem.init(); 218 } 219 220 ocsd_datapath_resp_t TrcPktDecodePtm::decodePacket() 221 { 222 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 223 switch(m_curr_packet_in->getType()) 224 { 225 // ignore these from trace o/p point of veiw 226 case PTM_PKT_NOTSYNC: 227 case PTM_PKT_INCOMPLETE_EOT: 228 case PTM_PKT_NOERROR: 229 break; 230 231 // bad / reserved packet - need to wait for next sync point 232 case PTM_PKT_BAD_SEQUENCE: 233 case PTM_PKT_RESERVED: 234 m_curr_state = WAIT_SYNC; 235 m_need_isync = true; // need context to re-start. 236 m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); 237 resp = outputTraceElement(m_output_elem); 238 break; 239 240 // packets we can ignore if in sync 241 case PTM_PKT_A_SYNC: 242 case PTM_PKT_IGNORE: 243 break; 244 245 // 246 case PTM_PKT_I_SYNC: 247 resp = processIsync(); 248 break; 249 250 case PTM_PKT_BRANCH_ADDRESS: 251 resp = processBranch(); 252 break; 253 254 case PTM_PKT_TRIGGER: 255 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT); 256 m_output_elem.setEvent(EVENT_TRIGGER, 0); 257 resp = outputTraceElement(m_output_elem); 258 break; 259 260 case PTM_PKT_WPOINT_UPDATE: 261 resp = processWPUpdate(); 262 break; 263 264 case PTM_PKT_CONTEXT_ID: 265 { 266 bool bUpdate = true; 267 // see if this is a change 268 if((m_pe_context.ctxt_id_valid) && (m_pe_context.context_id == m_curr_packet_in->context.ctxtID)) 269 bUpdate = false; 270 if(bUpdate) 271 { 272 m_pe_context.context_id = m_curr_packet_in->context.ctxtID; 273 m_pe_context.ctxt_id_valid = 1; 274 m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 275 m_output_elem.setContext(m_pe_context); 276 resp = outputTraceElement(m_output_elem); 277 } 278 } 279 break; 280 281 case PTM_PKT_VMID: 282 { 283 bool bUpdate = true; 284 // see if this is a change 285 if((m_pe_context.vmid_valid) && (m_pe_context.vmid == m_curr_packet_in->context.VMID)) 286 bUpdate = false; 287 if(bUpdate) 288 { 289 m_pe_context.vmid = m_curr_packet_in->context.VMID; 290 m_pe_context.vmid_valid = 1; 291 m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 292 m_output_elem.setContext(m_pe_context); 293 resp = outputTraceElement(m_output_elem); 294 } 295 } 296 break; 297 298 case PTM_PKT_ATOM: 299 if(m_curr_pe_state.valid) 300 { 301 m_atoms.initAtomPkt(m_curr_packet_in->getAtom(),m_index_curr_pkt); 302 resp = processAtom(); 303 } 304 break; 305 306 case PTM_PKT_TIMESTAMP: 307 m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP); 308 m_output_elem.timestamp = m_curr_packet_in->timestamp; 309 if(m_curr_packet_in->cc_valid) 310 m_output_elem.setCycleCount(m_curr_packet_in->cycle_count); 311 resp = outputTraceElement(m_output_elem); 312 break; 313 314 case PTM_PKT_EXCEPTION_RET: 315 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET); 316 resp = outputTraceElement(m_output_elem); 317 break; 318 319 } 320 return resp; 321 } 322 323 ocsd_datapath_resp_t TrcPktDecodePtm::processIsync() 324 { 325 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 326 327 // extract the I-Sync data if not re-entering after a _WAIT 328 if(m_curr_state == DECODE_PKTS) 329 { 330 m_curr_pe_state.instr_addr = m_curr_packet_in->getAddrVal(); 331 m_curr_pe_state.isa = m_curr_packet_in->getISA(); 332 m_curr_pe_state.valid = true; 333 334 m_i_sync_pe_ctxt = m_curr_packet_in->ISAChanged(); 335 if(m_curr_packet_in->CtxtIDUpdated()) 336 { 337 m_pe_context.context_id = m_curr_packet_in->getCtxtID(); 338 m_pe_context.ctxt_id_valid = 1; 339 m_i_sync_pe_ctxt = true; 340 } 341 342 if(m_curr_packet_in->VMIDUpdated()) 343 { 344 m_pe_context.vmid = m_curr_packet_in->getVMID(); 345 m_pe_context.vmid_valid = 1; 346 m_i_sync_pe_ctxt = true; 347 } 348 m_pe_context.security_level = m_curr_packet_in->getNS() ? ocsd_sec_nonsecure : ocsd_sec_secure; 349 350 if(m_need_isync || (m_curr_packet_in->iSyncReason() != iSync_Periodic)) 351 { 352 m_output_elem.setType(OCSD_GEN_TRC_ELEM_TRACE_ON); 353 m_output_elem.trace_on_reason = TRACE_ON_NORMAL; 354 if(m_curr_packet_in->iSyncReason() == iSync_TraceRestartAfterOverflow) 355 m_output_elem.trace_on_reason = TRACE_ON_OVERFLOW; 356 else if(m_curr_packet_in->iSyncReason() == iSync_DebugExit) 357 m_output_elem.trace_on_reason = TRACE_ON_EX_DEBUG; 358 if(m_curr_packet_in->hasCC()) 359 m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); 360 resp = outputTraceElement(m_output_elem); 361 } 362 else 363 { 364 // periodic - no output 365 m_i_sync_pe_ctxt = false; 366 } 367 m_need_isync = false; // got 1st Isync - can continue to process data. 368 m_return_stack.flush(); 369 } 370 371 if(m_i_sync_pe_ctxt && OCSD_DATA_RESP_IS_CONT(resp)) 372 { 373 m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 374 m_output_elem.setContext(m_pe_context); 375 m_output_elem.setISA(m_curr_pe_state.isa); 376 resp = outputTraceElement(m_output_elem); 377 m_i_sync_pe_ctxt = false; 378 } 379 380 // if wait and still stuff to process.... 381 if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_i_sync_pe_ctxt)) 382 m_curr_state = CONT_ISYNC; 383 384 return resp; 385 } 386 387 // change of address and/or exception in program flow. 388 // implies E atom before the branch if none exception. 389 ocsd_datapath_resp_t TrcPktDecodePtm::processBranch() 390 { 391 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 392 393 // initial pass - decoding packet. 394 if(m_curr_state == DECODE_PKTS) 395 { 396 // specific behviour if this is an exception packet. 397 if(m_curr_packet_in->isBranchExcepPacket()) 398 { 399 // exception - record address and output exception packet. 400 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION); 401 m_output_elem.exception_number = m_curr_packet_in->excepNum(); 402 m_output_elem.excep_ret_addr = 0; 403 if(m_curr_pe_state.valid) 404 { 405 m_output_elem.excep_ret_addr = 1; 406 m_output_elem.en_addr = m_curr_pe_state.instr_addr; 407 } 408 // could be an associated cycle count 409 if(m_curr_packet_in->hasCC()) 410 m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); 411 412 // output the element 413 resp = outputTraceElement(m_output_elem); 414 } 415 else 416 { 417 // branch address only - implies E atom - need to output a range element based on the atom. 418 if(m_curr_pe_state.valid) 419 resp = processAtomRange(ATOM_E,"BranchAddr"); 420 } 421 422 // now set the branch address for the next time. 423 m_curr_pe_state.isa = m_curr_packet_in->getISA(); 424 m_curr_pe_state.instr_addr = m_curr_packet_in->getAddrVal(); 425 m_curr_pe_state.valid = true; 426 } 427 428 // atom range may return with NACC pending 429 checkPendingNacc(resp); 430 431 // if wait and still stuff to process.... 432 if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending)) 433 m_curr_state = CONT_BRANCH; 434 435 return resp; 436 } 437 438 // effectively completes a range prior to exception or after many bytes of trace (>4096) 439 // 440 ocsd_datapath_resp_t TrcPktDecodePtm::processWPUpdate() 441 { 442 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 443 444 // if we need an address to run from then the WPUpdate will not form a range as 445 // we do not have a start point - still waiting for branch or other address packet 446 if(m_curr_pe_state.valid) 447 { 448 // WP update implies atom - use E, we cannot be sure if the instruction passed its condition codes 449 // - though it doesn't really matter as it is not a branch so cannot change flow. 450 resp = processAtomRange(ATOM_E,"WP update",TRACE_TO_ADDR_INCL,m_curr_packet_in->getAddrVal()); 451 } 452 453 // atom range may return with NACC pending 454 checkPendingNacc(resp); 455 456 // if wait and still stuff to process.... 457 if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending)) 458 m_curr_state = CONT_WPUP; 459 460 return resp; 461 } 462 463 // a single atom packet can result in multiple range outputs...need to be re-entrant in case we get a wait response. 464 // also need to handle nacc response from instruction walking routine 465 // 466 ocsd_datapath_resp_t TrcPktDecodePtm::processAtom() 467 { 468 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 469 470 // loop to process all the atoms in the packet 471 while(m_atoms.numAtoms() && m_curr_pe_state.valid && OCSD_DATA_RESP_IS_CONT(resp)) 472 { 473 resp = processAtomRange(m_atoms.getCurrAtomVal(),"atom"); 474 if(!m_curr_pe_state.valid) 475 m_atoms.clearAll(); 476 else 477 m_atoms.clearAtom(); 478 } 479 480 // bad address may mean a nacc needs sending 481 checkPendingNacc(resp); 482 483 // if wait and still stuff to process.... 484 if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending || m_atoms.numAtoms())) 485 m_curr_state = CONT_ATOM; 486 487 return resp; 488 } 489 490 void TrcPktDecodePtm::checkPendingNacc(ocsd_datapath_resp_t &resp) 491 { 492 if(m_mem_nacc_pending && OCSD_DATA_RESP_IS_CONT(resp)) 493 { 494 m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); 495 m_output_elem.st_addr = m_nacc_addr; 496 resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); 497 m_mem_nacc_pending = false; 498 } 499 } 500 501 // given an atom element - walk the code and output a range or mark nacc. 502 ocsd_datapath_resp_t TrcPktDecodePtm::processAtomRange(const ocsd_atm_val A, const char *pkt_msg, const waypoint_trace_t traceWPOp /*= TRACE_WAYPOINT*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) 503 { 504 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 505 bool bWPFound = false; 506 std::ostringstream oss; 507 508 m_instr_info.instr_addr = m_curr_pe_state.instr_addr; 509 m_instr_info.isa = m_curr_pe_state.isa; 510 511 ocsd_err_t err = traceInstrToWP(bWPFound,traceWPOp,nextAddrMatch); 512 if(err != OCSD_OK) 513 { 514 if(err == OCSD_ERR_UNSUPPORTED_ISA) 515 { 516 m_curr_pe_state.valid = false; // need a new address packet 517 oss << "Warning: unsupported instruction set processing " << pkt_msg << " packet."; 518 LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_index_curr_pkt,m_CSID,oss.str())); 519 // wait for next address 520 return OCSD_RESP_WARN_CONT; 521 } 522 else 523 { 524 resp = OCSD_RESP_FATAL_INVALID_DATA; 525 oss << "Error processing " << pkt_msg << " packet."; 526 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,m_index_curr_pkt,m_CSID,oss.str())); 527 return resp; 528 } 529 } 530 531 if(bWPFound) 532 { 533 // save recorded next instuction address 534 ocsd_vaddr_t nextAddr = m_instr_info.instr_addr; 535 536 // action according to waypoint type and atom value 537 switch(m_instr_info.type) 538 { 539 case OCSD_INSTR_BR: 540 if (A == ATOM_E) 541 { 542 m_instr_info.instr_addr = m_instr_info.branch_addr; 543 if (m_instr_info.is_link) 544 m_return_stack.push(nextAddr,m_instr_info.isa); 545 } 546 break; 547 548 // For PTM -> branch addresses imply E atom, N atom does not need address (return stack will require this) 549 case OCSD_INSTR_BR_INDIRECT: 550 if (A == ATOM_E) 551 { 552 // atom on indirect branch - either implied E from a branch address packet, or return stack if active. 553 554 // indirect branch taken - need new address -if the current packet is a branch address packet this will be sorted. 555 m_curr_pe_state.valid = false; 556 557 // if return stack and the incoming packet is an atom. 558 if (m_return_stack.is_active() && (m_curr_packet_in->getType() == PTM_PKT_ATOM)) 559 { 560 // we have an E atom packet and return stack value - set address from return stack 561 m_instr_info.instr_addr = m_return_stack.pop(m_instr_info.next_isa); 562 563 if (m_return_stack.overflow()) 564 { 565 resp = OCSD_RESP_FATAL_INVALID_DATA; 566 oss << "Return stack error processing " << pkt_msg << " packet."; 567 LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_RET_STACK_OVERFLOW, m_index_curr_pkt, m_CSID, oss.str())); 568 return resp; 569 } 570 else 571 m_curr_pe_state.valid = true; 572 } 573 if(m_instr_info.is_link) 574 m_return_stack.push(nextAddr, m_instr_info.isa); 575 } 576 break; 577 } 578 579 m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); 580 m_output_elem.setLastInstrInfo((A == ATOM_E),m_instr_info.type, m_instr_info.sub_type,m_instr_info.instr_size); 581 m_output_elem.setISA(m_curr_pe_state.isa); 582 if(m_curr_packet_in->hasCC()) 583 m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); 584 m_output_elem.setLastInstrCond(m_instr_info.is_conditional); 585 resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); 586 587 m_curr_pe_state.instr_addr = m_instr_info.instr_addr; 588 m_curr_pe_state.isa = m_instr_info.next_isa; 589 } 590 else 591 { 592 // no waypoint - likely inaccessible memory range. 593 m_curr_pe_state.valid = false; // need an address update 594 595 if(m_output_elem.st_addr != m_output_elem.en_addr) 596 { 597 // some trace before we were out of memory access range 598 m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); 599 m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type,m_instr_info.instr_size); 600 m_output_elem.setISA(m_curr_pe_state.isa); 601 m_output_elem.setLastInstrCond(m_instr_info.is_conditional); 602 resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); 603 } 604 } 605 return resp; 606 } 607 608 ocsd_err_t TrcPktDecodePtm::traceInstrToWP(bool &bWPFound, const waypoint_trace_t traceWPOp /*= TRACE_WAYPOINT*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) 609 { 610 uint32_t opcode; 611 uint32_t bytesReq; 612 ocsd_err_t err = OCSD_OK; 613 ocsd_vaddr_t curr_op_address; 614 615 ocsd_mem_space_acc_t mem_space = (m_pe_context.security_level == ocsd_sec_secure) ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N; 616 617 m_output_elem.st_addr = m_output_elem.en_addr = m_instr_info.instr_addr; 618 m_output_elem.num_instr_range = 0; 619 620 bWPFound = false; 621 622 while(!bWPFound && !m_mem_nacc_pending) 623 { 624 // start off by reading next opcode; 625 bytesReq = 4; 626 curr_op_address = m_instr_info.instr_addr; // save the start address for the current opcode 627 err = accessMemory(m_instr_info.instr_addr,mem_space,&bytesReq,(uint8_t *)&opcode); 628 if(err != OCSD_OK) break; 629 630 if(bytesReq == 4) // got data back 631 { 632 m_instr_info.opcode = opcode; 633 err = instrDecode(&m_instr_info); 634 if(err != OCSD_OK) break; 635 636 // increment address - may be adjusted by direct branch value later 637 m_instr_info.instr_addr += m_instr_info.instr_size; 638 639 // update the range decoded address in the output packet. 640 m_output_elem.en_addr = m_instr_info.instr_addr; 641 m_output_elem.num_instr_range++; 642 643 m_output_elem.last_i_type = m_instr_info.type; 644 // either walking to match the next instruction address or a real waypoint 645 if(traceWPOp != TRACE_WAYPOINT) 646 { 647 if(traceWPOp == TRACE_TO_ADDR_EXCL) 648 bWPFound = (m_output_elem.en_addr == nextAddrMatch); 649 else 650 bWPFound = (curr_op_address == nextAddrMatch); 651 } 652 else 653 bWPFound = (m_instr_info.type != OCSD_INSTR_OTHER); 654 } 655 else 656 { 657 // not enough memory accessible. 658 m_mem_nacc_pending = true; 659 m_nacc_addr = m_instr_info.instr_addr; 660 } 661 } 662 return err; 663 } 664 665 /* End of File trc_pkt_decode_ptm.cpp */ 666