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
TrcPktDecodeEtmV3()39 TrcPktDecodeEtmV3::TrcPktDecodeEtmV3() :
40 TrcPktDecodeBase(DCD_NAME)
41 {
42 initDecoder();
43 }
44
TrcPktDecodeEtmV3(int instIDNum)45 TrcPktDecodeEtmV3::TrcPktDecodeEtmV3(int instIDNum) :
46 TrcPktDecodeBase(DCD_NAME, instIDNum)
47 {
48 initDecoder();
49 }
50
~TrcPktDecodeEtmV3()51 TrcPktDecodeEtmV3::~TrcPktDecodeEtmV3()
52 {
53 }
54
55
56 /* implementation packet decoding interface */
processPacket()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
onEOT()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
onReset()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
onFlush()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
onProtocolConfig()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
initDecoder()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.
resetDecoder()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
GetNextOpElem(ocsd_datapath_resp_t & resp)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
preISyncValid(ocsd_etmv3_pkt_type pkt_type)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.
decodePacket(bool & pktDone)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
sendUnsyncPacket()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
setNeedAddr(bool bNeedAddr)395 void TrcPktDecodeEtmV3::setNeedAddr(bool bNeedAddr)
396 {
397 m_bNeedAddr = bNeedAddr;
398 m_bSentUnknown = false;
399 }
400
processISync(const bool withCC,const bool firstSync)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
processBranchAddr()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
processPHdr()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.
pendExceptionReturn()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