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