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