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 return err; 183 } 184 185 /****************** local decoder routines */ 186 187 void TrcPktDecodePtm::initDecoder() 188 { 189 m_CSID = 0; 190 m_instr_info.pe_type.profile = profile_Unknown; 191 m_instr_info.pe_type.arch = ARCH_UNKNOWN; 192 m_instr_info.dsb_dmb_waypoints = 0; 193 resetDecoder(); 194 } 195 196 void TrcPktDecodePtm::resetDecoder() 197 { 198 m_curr_state = NO_SYNC; 199 m_need_isync = true; // need context to start. 200 201 m_instr_info.isa = ocsd_isa_unknown; 202 m_mem_nacc_pending = false; 203 204 m_pe_context.ctxt_id_valid = 0; 205 m_pe_context.bits64 = 0; 206 m_pe_context.vmid_valid = 0; 207 m_pe_context.exception_level = ocsd_EL_unknown; 208 m_pe_context.security_level = ocsd_sec_secure; 209 m_pe_context.el_valid = 0; 210 211 m_curr_pe_state.instr_addr = 0x0; 212 m_curr_pe_state.isa = ocsd_isa_unknown; 213 m_curr_pe_state.valid = false; 214 215 m_atoms.clearAll(); 216 m_output_elem.init(); 217 } 218 219 ocsd_datapath_resp_t TrcPktDecodePtm::decodePacket() 220 { 221 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 222 switch(m_curr_packet_in->getType()) 223 { 224 // ignore these from trace o/p point of veiw 225 case PTM_PKT_NOTSYNC: 226 case PTM_PKT_INCOMPLETE_EOT: 227 case PTM_PKT_NOERROR: 228 break; 229 230 // bad / reserved packet - need to wait for next sync point 231 case PTM_PKT_BAD_SEQUENCE: 232 case PTM_PKT_RESERVED: 233 m_curr_state = WAIT_SYNC; 234 m_need_isync = true; // need context to re-start. 235 m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); 236 resp = outputTraceElement(m_output_elem); 237 break; 238 239 // packets we can ignore if in sync 240 case PTM_PKT_A_SYNC: 241 case PTM_PKT_IGNORE: 242 break; 243 244 // 245 case PTM_PKT_I_SYNC: 246 resp = processIsync(); 247 break; 248 249 case PTM_PKT_BRANCH_ADDRESS: 250 resp = processBranch(); 251 break; 252 253 case PTM_PKT_TRIGGER: 254 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT); 255 m_output_elem.setEvent(EVENT_TRIGGER, 0); 256 resp = outputTraceElement(m_output_elem); 257 break; 258 259 case PTM_PKT_WPOINT_UPDATE: 260 resp = processWPUpdate(); 261 break; 262 263 case PTM_PKT_CONTEXT_ID: 264 { 265 bool bUpdate = true; 266 // see if this is a change 267 if((m_pe_context.ctxt_id_valid) && (m_pe_context.context_id == m_curr_packet_in->context.ctxtID)) 268 bUpdate = false; 269 if(bUpdate) 270 { 271 m_pe_context.context_id = m_curr_packet_in->context.ctxtID; 272 m_pe_context.ctxt_id_valid = 1; 273 m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 274 m_output_elem.setContext(m_pe_context); 275 resp = outputTraceElement(m_output_elem); 276 } 277 } 278 break; 279 280 case PTM_PKT_VMID: 281 { 282 bool bUpdate = true; 283 // see if this is a change 284 if((m_pe_context.vmid_valid) && (m_pe_context.vmid == m_curr_packet_in->context.VMID)) 285 bUpdate = false; 286 if(bUpdate) 287 { 288 m_pe_context.vmid = m_curr_packet_in->context.VMID; 289 m_pe_context.vmid_valid = 1; 290 m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 291 m_output_elem.setContext(m_pe_context); 292 resp = outputTraceElement(m_output_elem); 293 } 294 } 295 break; 296 297 case PTM_PKT_ATOM: 298 if(m_curr_pe_state.valid) 299 { 300 m_atoms.initAtomPkt(m_curr_packet_in->getAtom(),m_index_curr_pkt); 301 resp = processAtom(); 302 } 303 break; 304 305 case PTM_PKT_TIMESTAMP: 306 m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP); 307 m_output_elem.timestamp = m_curr_packet_in->timestamp; 308 if(m_curr_packet_in->cc_valid) 309 m_output_elem.setCycleCount(m_curr_packet_in->cycle_count); 310 resp = outputTraceElement(m_output_elem); 311 break; 312 313 case PTM_PKT_EXCEPTION_RET: 314 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET); 315 resp = outputTraceElement(m_output_elem); 316 break; 317 318 } 319 return resp; 320 } 321 322 ocsd_datapath_resp_t TrcPktDecodePtm::processIsync() 323 { 324 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 325 326 // extract the I-Sync data if not re-entering after a _WAIT 327 if(m_curr_state == DECODE_PKTS) 328 { 329 m_curr_pe_state.instr_addr = m_curr_packet_in->getAddrVal(); 330 m_curr_pe_state.isa = m_curr_packet_in->getISA(); 331 m_curr_pe_state.valid = true; 332 333 m_i_sync_pe_ctxt = m_curr_packet_in->ISAChanged(); 334 if(m_curr_packet_in->CtxtIDUpdated()) 335 { 336 m_pe_context.context_id = m_curr_packet_in->getCtxtID(); 337 m_pe_context.ctxt_id_valid = 1; 338 m_i_sync_pe_ctxt = true; 339 } 340 341 if(m_curr_packet_in->VMIDUpdated()) 342 { 343 m_pe_context.vmid = m_curr_packet_in->getVMID(); 344 m_pe_context.vmid_valid = 1; 345 m_i_sync_pe_ctxt = true; 346 } 347 m_pe_context.security_level = m_curr_packet_in->getNS() ? ocsd_sec_nonsecure : ocsd_sec_secure; 348 349 if(m_need_isync || (m_curr_packet_in->iSyncReason() != iSync_Periodic)) 350 { 351 m_output_elem.setType(OCSD_GEN_TRC_ELEM_TRACE_ON); 352 m_output_elem.trace_on_reason = TRACE_ON_NORMAL; 353 if(m_curr_packet_in->iSyncReason() == iSync_TraceRestartAfterOverflow) 354 m_output_elem.trace_on_reason = TRACE_ON_OVERFLOW; 355 else if(m_curr_packet_in->iSyncReason() == iSync_DebugExit) 356 m_output_elem.trace_on_reason = TRACE_ON_EX_DEBUG; 357 if(m_curr_packet_in->hasCC()) 358 m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); 359 resp = outputTraceElement(m_output_elem); 360 } 361 else 362 { 363 // periodic - no output 364 m_i_sync_pe_ctxt = false; 365 } 366 m_need_isync = false; // got 1st Isync - can continue to process data. 367 m_return_stack.flush(); 368 } 369 370 if(m_i_sync_pe_ctxt && OCSD_DATA_RESP_IS_CONT(resp)) 371 { 372 m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 373 m_output_elem.setContext(m_pe_context); 374 m_output_elem.setISA(m_curr_pe_state.isa); 375 resp = outputTraceElement(m_output_elem); 376 m_i_sync_pe_ctxt = false; 377 } 378 379 // if wait and still stuff to process.... 380 if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_i_sync_pe_ctxt)) 381 m_curr_state = CONT_ISYNC; 382 383 return resp; 384 } 385 386 // change of address and/or exception in program flow. 387 // implies E atom before the branch if none exception. 388 ocsd_datapath_resp_t TrcPktDecodePtm::processBranch() 389 { 390 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 391 392 // initial pass - decoding packet. 393 if(m_curr_state == DECODE_PKTS) 394 { 395 // specific behviour if this is an exception packet. 396 if(m_curr_packet_in->isBranchExcepPacket()) 397 { 398 // exception - record address and output exception packet. 399 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION); 400 m_output_elem.exception_number = m_curr_packet_in->excepNum(); 401 m_output_elem.excep_ret_addr = 0; 402 if(m_curr_pe_state.valid) 403 { 404 m_output_elem.excep_ret_addr = 1; 405 m_output_elem.en_addr = m_curr_pe_state.instr_addr; 406 } 407 // could be an associated cycle count 408 if(m_curr_packet_in->hasCC()) 409 m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); 410 411 // output the element 412 resp = outputTraceElement(m_output_elem); 413 } 414 else 415 { 416 // branch address only - implies E atom - need to output a range element based on the atom. 417 if(m_curr_pe_state.valid) 418 resp = processAtomRange(ATOM_E,"BranchAddr"); 419 } 420 421 // now set the branch address for the next time. 422 m_curr_pe_state.isa = m_curr_packet_in->getISA(); 423 m_curr_pe_state.instr_addr = m_curr_packet_in->getAddrVal(); 424 m_curr_pe_state.valid = true; 425 } 426 427 // atom range may return with NACC pending 428 checkPendingNacc(resp); 429 430 // if wait and still stuff to process.... 431 if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending)) 432 m_curr_state = CONT_BRANCH; 433 434 return resp; 435 } 436 437 // effectively completes a range prior to exception or after many bytes of trace (>4096) 438 // 439 ocsd_datapath_resp_t TrcPktDecodePtm::processWPUpdate() 440 { 441 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 442 443 // if we need an address to run from then the WPUpdate will not form a range as 444 // we do not have a start point - still waiting for branch or other address packet 445 if(m_curr_pe_state.valid) 446 { 447 // WP update implies atom - use E, we cannot be sure if the instruction passed its condition codes 448 // - though it doesn't really matter as it is not a branch so cannot change flow. 449 resp = processAtomRange(ATOM_E,"WP update",TRACE_TO_ADDR_INCL,m_curr_packet_in->getAddrVal()); 450 } 451 452 // atom range may return with NACC pending 453 checkPendingNacc(resp); 454 455 // if wait and still stuff to process.... 456 if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending)) 457 m_curr_state = CONT_WPUP; 458 459 return resp; 460 } 461 462 // a single atom packet can result in multiple range outputs...need to be re-entrant in case we get a wait response. 463 // also need to handle nacc response from instruction walking routine 464 // 465 ocsd_datapath_resp_t TrcPktDecodePtm::processAtom() 466 { 467 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 468 469 // loop to process all the atoms in the packet 470 while(m_atoms.numAtoms() && m_curr_pe_state.valid && OCSD_DATA_RESP_IS_CONT(resp)) 471 { 472 resp = processAtomRange(m_atoms.getCurrAtomVal(),"atom"); 473 if(!m_curr_pe_state.valid) 474 m_atoms.clearAll(); 475 else 476 m_atoms.clearAtom(); 477 } 478 479 // bad address may mean a nacc needs sending 480 checkPendingNacc(resp); 481 482 // if wait and still stuff to process.... 483 if(OCSD_DATA_RESP_IS_WAIT(resp) && ( m_mem_nacc_pending || m_atoms.numAtoms())) 484 m_curr_state = CONT_ATOM; 485 486 return resp; 487 } 488 489 void TrcPktDecodePtm::checkPendingNacc(ocsd_datapath_resp_t &resp) 490 { 491 if(m_mem_nacc_pending && OCSD_DATA_RESP_IS_CONT(resp)) 492 { 493 m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); 494 m_output_elem.st_addr = m_nacc_addr; 495 resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); 496 m_mem_nacc_pending = false; 497 } 498 } 499 500 // given an atom element - walk the code and output a range or mark nacc. 501 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*/) 502 { 503 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 504 bool bWPFound = false; 505 std::ostringstream oss; 506 507 m_instr_info.instr_addr = m_curr_pe_state.instr_addr; 508 m_instr_info.isa = m_curr_pe_state.isa; 509 510 ocsd_err_t err = traceInstrToWP(bWPFound,traceWPOp,nextAddrMatch); 511 if(err != OCSD_OK) 512 { 513 if(err == OCSD_ERR_UNSUPPORTED_ISA) 514 { 515 m_curr_pe_state.valid = false; // need a new address packet 516 oss << "Warning: unsupported instruction set processing " << pkt_msg << " packet."; 517 LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_index_curr_pkt,m_CSID,oss.str())); 518 // wait for next address 519 return OCSD_RESP_WARN_CONT; 520 } 521 else 522 { 523 resp = OCSD_RESP_FATAL_INVALID_DATA; 524 oss << "Error processing " << pkt_msg << " packet."; 525 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,m_index_curr_pkt,m_CSID,oss.str())); 526 return resp; 527 } 528 } 529 530 if(bWPFound) 531 { 532 // save recorded next instuction address 533 ocsd_vaddr_t nextAddr = m_instr_info.instr_addr; 534 535 // action according to waypoint type and atom value 536 switch(m_instr_info.type) 537 { 538 case OCSD_INSTR_BR: 539 if (A == ATOM_E) 540 { 541 m_instr_info.instr_addr = m_instr_info.branch_addr; 542 if (m_instr_info.is_link) 543 m_return_stack.push(nextAddr,m_instr_info.isa); 544 } 545 break; 546 547 // For PTM -> branch addresses imply E atom, N atom does not need address (return stack will require this) 548 case OCSD_INSTR_BR_INDIRECT: 549 if (A == ATOM_E) 550 { 551 // atom on indirect branch - either implied E from a branch address packet, or return stack if active. 552 553 // indirect branch taken - need new address -if the current packet is a branch address packet this will be sorted. 554 m_curr_pe_state.valid = false; 555 556 // if return stack and the incoming packet is an atom. 557 if (m_return_stack.is_active() && (m_curr_packet_in->getType() == PTM_PKT_ATOM)) 558 { 559 // we have an E atom packet and return stack value - set address from return stack 560 m_instr_info.instr_addr = m_return_stack.pop(m_instr_info.next_isa); 561 562 if (m_return_stack.overflow()) 563 { 564 resp = OCSD_RESP_FATAL_INVALID_DATA; 565 oss << "Return stack error processing " << pkt_msg << " packet."; 566 LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_RET_STACK_OVERFLOW, m_index_curr_pkt, m_CSID, oss.str())); 567 return resp; 568 } 569 else 570 m_curr_pe_state.valid = true; 571 } 572 if(m_instr_info.is_link) 573 m_return_stack.push(nextAddr, m_instr_info.isa); 574 } 575 break; 576 } 577 578 m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); 579 m_output_elem.setLastInstrInfo((A == ATOM_E),m_instr_info.type, m_instr_info.sub_type); 580 m_output_elem.setISA(m_curr_pe_state.isa); 581 if(m_curr_packet_in->hasCC()) 582 m_output_elem.setCycleCount(m_curr_packet_in->getCCVal()); 583 resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); 584 585 m_curr_pe_state.instr_addr = m_instr_info.instr_addr; 586 m_curr_pe_state.isa = m_instr_info.next_isa; 587 } 588 else 589 { 590 // no waypoint - likely inaccessible memory range. 591 m_curr_pe_state.valid = false; // need an address update 592 593 if(m_output_elem.st_addr != m_output_elem.en_addr) 594 { 595 // some trace before we were out of memory access range 596 m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); 597 m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type); 598 m_output_elem.setISA(m_curr_pe_state.isa); 599 resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); 600 } 601 } 602 return resp; 603 } 604 605 ocsd_err_t TrcPktDecodePtm::traceInstrToWP(bool &bWPFound, const waypoint_trace_t traceWPOp /*= TRACE_WAYPOINT*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) 606 { 607 uint32_t opcode; 608 uint32_t bytesReq; 609 ocsd_err_t err = OCSD_OK; 610 ocsd_vaddr_t curr_op_address; 611 612 ocsd_mem_space_acc_t mem_space = (m_pe_context.security_level == ocsd_sec_secure) ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N; 613 614 m_output_elem.st_addr = m_output_elem.en_addr = m_instr_info.instr_addr; 615 616 bWPFound = false; 617 618 while(!bWPFound && !m_mem_nacc_pending) 619 { 620 // start off by reading next opcode; 621 bytesReq = 4; 622 curr_op_address = m_instr_info.instr_addr; // save the start address for the current opcode 623 err = accessMemory(m_instr_info.instr_addr,mem_space,&bytesReq,(uint8_t *)&opcode); 624 if(err != OCSD_OK) break; 625 626 if(bytesReq == 4) // got data back 627 { 628 m_instr_info.opcode = opcode; 629 err = instrDecode(&m_instr_info); 630 if(err != OCSD_OK) break; 631 632 // increment address - may be adjusted by direct branch value later 633 m_instr_info.instr_addr += m_instr_info.instr_size; 634 635 // update the range decoded address in the output packet. 636 m_output_elem.en_addr = m_instr_info.instr_addr; 637 638 m_output_elem.last_i_type = m_instr_info.type; 639 // either walking to match the next instruction address or a real waypoint 640 if(traceWPOp != TRACE_WAYPOINT) 641 { 642 if(traceWPOp == TRACE_TO_ADDR_EXCL) 643 bWPFound = (m_output_elem.en_addr == nextAddrMatch); 644 else 645 bWPFound = (curr_op_address == nextAddrMatch); 646 } 647 else 648 bWPFound = (m_instr_info.type != OCSD_INSTR_OTHER); 649 } 650 else 651 { 652 // not enough memory accessible. 653 m_mem_nacc_pending = true; 654 m_nacc_addr = m_instr_info.instr_addr; 655 } 656 } 657 return err; 658 } 659 660 /* End of File trc_pkt_decode_ptm.cpp */ 661