]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/opencsd/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp
Re-add opencsd as a vendor import from the dist directory
[FreeBSD/FreeBSD.git] / contrib / opencsd / decoder / source / etmv3 / trc_pkt_decode_etmv3.cpp
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         m_outputElemList.commitAllPendElem();
134         m_curr_state = SEND_PKTS;
135         resp = m_outputElemList.sendElements();
136         if(OCSD_DATA_RESP_IS_CONT(resp))
137             m_curr_state = DECODE_PKTS;
138     }
139     catch(ocsdError &err)
140     {
141         LogError(err);
142         resetDecoder(); // mark decoder as unsynced - dump any current state.
143     }    
144     return resp;
145 }
146
147 ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset()
148 {
149     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
150     resetDecoder();
151     return resp;
152 }
153
154 ocsd_datapath_resp_t TrcPktDecodeEtmV3::onFlush()
155 {
156     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
157     if(m_curr_state == SEND_PKTS)
158     {
159         resp = m_outputElemList.sendElements();
160         if(OCSD_DATA_RESP_IS_CONT(resp))
161             m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS;
162     }
163     return resp;
164 }
165
166 ocsd_err_t TrcPktDecodeEtmV3::onProtocolConfig()
167 {
168     ocsd_err_t err = OCSD_OK;
169     if(m_config)
170     {
171         // set some static config elements
172         m_CSID = m_config->getTraceID();
173
174         // check config compatible with current decoder support level.
175         // at present no data trace;
176         if(m_config->GetTraceMode() != EtmV3Config::TM_INSTR_ONLY)
177         {
178             err = OCSD_ERR_HW_CFG_UNSUPP;
179             LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv3 trace decoder : data trace decode not yet supported"));
180         }
181
182         // need to set up core profile info in follower
183         ocsd_arch_profile_t arch_profile;
184         arch_profile.arch = m_config->getArchVersion();
185         arch_profile.profile = m_config->getCoreProfile();
186         m_code_follower.setArchProfile(arch_profile);
187         m_code_follower.setMemSpaceCSID(m_CSID);
188         m_outputElemList.initCSID(m_CSID);
189     }
190     else
191         err = OCSD_ERR_NOT_INIT;
192     return err;
193 }
194
195 /* local decode methods */
196
197 // initialise on creation
198 void TrcPktDecodeEtmV3::initDecoder()
199 {
200     m_CSID = 0;
201     resetDecoder();
202     m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt());
203     m_outputElemList.initSendIf(getTraceElemOutAttachPt());
204 }
205
206 // reset for first use / re-use.
207 void TrcPktDecodeEtmV3::resetDecoder()
208 {
209     m_curr_state = NO_SYNC; // mark as not synced
210     m_bNeedAddr = true;
211     m_bSentUnknown = false;
212     m_bWaitISync = false;
213     m_outputElemList.reset();
214 }
215
216 OcsdTraceElement *TrcPktDecodeEtmV3::GetNextOpElem(ocsd_datapath_resp_t &resp)
217 {
218     OcsdTraceElement *pElem = m_outputElemList.getNextElem(m_index_curr_pkt);
219     if(pElem == 0)
220     {
221         resp = OCSD_RESP_FATAL_NOT_INIT;
222         throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_MEM,m_index_curr_pkt,m_CSID,"Memory Allocation Error - fatal");
223     }
224     return pElem;
225 }
226
227 bool TrcPktDecodeEtmV3::preISyncValid(ocsd_etmv3_pkt_type pkt_type)
228 {
229     bool bValid = false;
230     // its a timestamp
231     if((pkt_type == ETM3_PKT_TIMESTAMP) || 
232         // or we are cycleacc and its a packet that can have CC in it
233         (m_config->isCycleAcc() && ((pkt_type == ETM3_PKT_CYCLE_COUNT) || (pkt_type == ETM3_PKT_P_HDR)))
234         )
235         bValid = true;
236     return bValid;
237 }
238
239 // simple packet transforms handled here, more complex processing passed on to specific routines.
240 ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone)
241 {
242     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
243     bool bISyncHasCC = false;
244     OcsdTraceElement *pElem = 0;
245     pktDone = false;
246
247     // there may be pended packets that can now be committed.
248     // only the branch address with exception and cancel element can cancel
249     // if not one of those, commit immediately, otherwise defer to branch address handler.
250     if(m_curr_packet_in->getType() != ETM3_PKT_BRANCH_ADDRESS)
251         m_outputElemList.commitAllPendElem();
252
253     try {
254
255         switch(m_curr_packet_in->getType())
256         {
257
258         case ETM3_PKT_NOTSYNC:
259             // mark as not synced - must have lost sync in the packet processor somehow
260             throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Trace Packet Synchronisation Lost");
261             break;
262
263             // no action for these packets - ignore and continue
264         case ETM3_PKT_INCOMPLETE_EOT:
265         case ETM3_PKT_A_SYNC:
266         case ETM3_PKT_IGNORE:
267             break;
268
269     // markers for valid packets
270         case ETM3_PKT_CYCLE_COUNT:
271             pElem = GetNextOpElem(resp);
272             pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
273             pElem->setCycleCount(m_curr_packet_in->getCycleCount());
274             break;
275
276         case ETM3_PKT_TRIGGER:
277             pElem = GetNextOpElem(resp);
278             pElem->setType(OCSD_GEN_TRC_ELEM_EVENT);
279             pElem->setEvent(EVENT_TRIGGER,0);
280             break;
281
282         case ETM3_PKT_BRANCH_ADDRESS:
283             resp = processBranchAddr();
284             break;
285
286         case ETM3_PKT_I_SYNC_CYCLE:
287             bISyncHasCC = true;
288         case ETM3_PKT_I_SYNC:
289             resp = processISync(bISyncHasCC);
290             break;
291
292         case ETM3_PKT_P_HDR:
293             resp = processPHdr();
294             break;
295
296         case ETM3_PKT_CONTEXT_ID:
297             pElem = GetNextOpElem(resp);
298             pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
299             m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID());
300             pElem->setContext(m_PeContext);
301             break;
302
303         case ETM3_PKT_VMID:
304             pElem = GetNextOpElem(resp);
305             pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
306             m_PeContext.setVMID(m_curr_packet_in->getVMID());
307             pElem->setContext(m_PeContext);
308             break;
309
310         case ETM3_PKT_EXCEPTION_ENTRY:
311             pElem = GetNextOpElem(resp);
312             pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
313             pElem->setExcepMarker(); // exception entries are always v7M data markers in ETMv3 trace.
314             break;
315
316         case ETM3_PKT_EXCEPTION_EXIT:
317             pElem = GetNextOpElem(resp);
318             pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
319             pendExceptionReturn();
320             break;
321         
322         case ETM3_PKT_TIMESTAMP:
323             pElem = GetNextOpElem(resp);
324             pElem->setType(OCSD_GEN_TRC_ELEM_TIMESTAMP);
325             pElem->setTS(m_curr_packet_in->getTS());
326             break;
327
328             // data packets - data trace not supported at present
329         case ETM3_PKT_STORE_FAIL:
330         case ETM3_PKT_OOO_DATA:
331         case ETM3_PKT_OOO_ADDR_PLC:
332         case ETM3_PKT_NORM_DATA:
333         case ETM3_PKT_DATA_SUPPRESSED:
334         case ETM3_PKT_VAL_NOT_TRACED:
335         case ETM3_PKT_BAD_TRACEMODE:
336             resp = OCSD_RESP_FATAL_INVALID_DATA;        
337             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.");
338             break;
339
340     // packet errors 
341         case ETM3_PKT_BAD_SEQUENCE:
342             resp = OCSD_RESP_FATAL_INVALID_DATA;
343             throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Bad Packet sequence.");
344             break;
345
346         default:
347         case ETM3_PKT_RESERVED:
348             resp = OCSD_RESP_FATAL_INVALID_DATA;
349             throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Reserved or unknown packet ID.");
350             break;
351         }    
352         m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
353         pktDone = !m_outputElemList.elemToSend();
354     }
355     catch(ocsdError &err)
356     {
357         LogError(err);
358         resetDecoder(); // mark decoder as unsynced - dump any current state.
359         pktDone = true;
360     }
361     catch(...)
362     {
363         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,m_CSID,"Bad Packet sequence."));
364         resp = OCSD_RESP_FATAL_SYS_ERR;
365         resetDecoder(); // mark decoder as unsynced - dump any current state.
366         pktDone = true;
367     }
368     return resp;
369 }
370    
371 ocsd_datapath_resp_t TrcPktDecodeEtmV3::sendUnsyncPacket()
372 {
373     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
374     OcsdTraceElement *pElem = 0;
375     try {
376         pElem = GetNextOpElem(resp);
377         pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
378         resp = m_outputElemList.sendElements();
379     }
380     catch(ocsdError &err)
381     {
382         LogError(err);
383         resetDecoder(); // mark decoder as unsynced - dump any current state.
384     }
385     return resp;
386 }
387
388 void TrcPktDecodeEtmV3::setNeedAddr(bool bNeedAddr)
389 {
390     m_bNeedAddr = bNeedAddr;
391     m_bSentUnknown = false;    
392 }
393
394 ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC, const bool firstSync /* = false */)
395 {
396     // map ISync reason to generic reason codes.
397     static trace_on_reason_t on_map[] = { TRACE_ON_NORMAL, TRACE_ON_NORMAL,
398         TRACE_ON_OVERFLOW, TRACE_ON_EX_DEBUG };
399
400     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
401     bool ctxtUpdate = m_curr_packet_in->isCtxtUpdated();   
402     OcsdTraceElement *pElem = 0;
403
404     try {
405
406         pElem = GetNextOpElem(resp);
407
408         if(firstSync || (m_curr_packet_in->getISyncReason() != iSync_Periodic))
409         {
410             pElem->setType(OCSD_GEN_TRC_ELEM_TRACE_ON);
411             pElem->setTraceOnReason(on_map[(int)m_curr_packet_in->getISyncReason()]);
412             pElem =  GetNextOpElem(resp);           
413         }
414
415         // look for context changes....
416         if(ctxtUpdate || firstSync)
417         {
418             // if not first time out, read existing context in output element,
419             // otherwise we are setting it new.
420             if(firstSync)  
421                 m_PeContext.resetCtxt();
422
423             if(m_curr_packet_in->isCtxtIDUpdated())
424                 m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID());
425             if(m_curr_packet_in->isVMIDUpdated())
426                 m_PeContext.setVMID(m_curr_packet_in->getVMID());
427             if(m_curr_packet_in->isCtxtFlagsUpdated())
428             {
429                 m_PeContext.setEL(m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown);
430                 m_PeContext.setSecLevel(m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure);
431             }
432
433             // prepare the context packet
434             pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
435             pElem->setContext(m_PeContext);
436             pElem->setISA(m_curr_packet_in->ISA());
437
438             // with cycle count...
439             if(m_curr_packet_in->getISyncHasCC())
440                 pElem->setCycleCount(m_curr_packet_in->getCycleCount());
441
442         }
443
444         // set ISync address - if it is a valid I address
445         if(!m_curr_packet_in->getISyncNoAddr())
446         {
447             if(m_curr_packet_in->getISyncIsLSiPAddr())
448             {
449                 // TBD: handle extra data processing instruction for data trace
450                 // need to output E atom relating to the data instruction
451                 // rare - on start-up case.
452
453                 // main instruction address saved in data address for this packet type.
454                 m_IAddr = m_curr_packet_in->getDataAddr();
455             }
456             else
457             {
458                 m_IAddr = m_curr_packet_in->getAddr();
459             }
460             setNeedAddr(false);    // ready to process atoms.
461         }
462         m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
463     }
464     catch(ocsdError &err)
465     {
466         LogError(err);
467         resetDecoder(); // mark decoder as unsynced - dump any current state.
468     }
469     return resp;
470 }
471
472 ocsd_datapath_resp_t TrcPktDecodeEtmV3::processBranchAddr()
473 {
474     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
475     OcsdTraceElement *pElem = 0;
476     bool bUpdatePEContext = false;
477
478     // might need to cancel something ... if the last output was an instruction range or excep return
479     if(m_curr_packet_in->isExcepCancel())
480         m_outputElemList.cancelPendElem();
481     else         
482         m_outputElemList.commitAllPendElem(); // otherwise commit any pending elements.
483
484     // record the address
485     m_IAddr = m_curr_packet_in->getAddr();
486     setNeedAddr(false);    // no longer need an address.
487    
488     // exception packet - may need additional output
489     if(m_curr_packet_in->isExcepPkt())
490     {
491         // exeception packet may have exception, context change, or both.
492         // check for context change
493         if(m_curr_packet_in->isCtxtUpdated())
494         {
495             
496             ocsd_sec_level sec = m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure;
497             if(sec != m_PeContext.getSecLevel())
498             {
499                 m_PeContext.setSecLevel(sec);
500                 bUpdatePEContext = true;
501             }
502             ocsd_ex_level pkt_el = m_curr_packet_in->isHyp() ?  ocsd_EL2 : ocsd_EL_unknown;
503             if(pkt_el != m_PeContext.getEL())
504             {
505                 m_PeContext.setEL(pkt_el);
506                 bUpdatePEContext = true;
507             }
508         }
509
510         // now decide if we need to send any packets out.
511         try {
512
513             if(bUpdatePEContext)
514             {
515                 pElem = GetNextOpElem(resp);
516                 pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
517                 pElem->setContext(m_PeContext);
518             }
519
520             // check for exception
521             if(m_curr_packet_in->excepNum() != 0)
522             {
523                 pElem = GetNextOpElem(resp);
524                 pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
525                 pElem->setExceptionNum(m_curr_packet_in->excepNum());                        
526             }
527
528             // finally - do we have anything to send yet?
529             m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
530         }
531         catch(ocsdError &err)
532         {
533             LogError(err);
534             resetDecoder(); // mark decoder as unsynced - dump any current state.
535         }
536     }       
537     return resp;
538 }
539
540
541 ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPHdr()
542 {
543     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
544     OcsdTraceElement *pElem = 0;
545     ocsd_isa isa;
546     Etmv3Atoms atoms(m_config->isCycleAcc());
547
548     atoms.initAtomPkt(m_curr_packet_in,m_index_curr_pkt);
549     isa = m_curr_packet_in->ISA();
550     m_code_follower.setMemSpaceAccess((m_PeContext.getSecLevel() ==  ocsd_sec_secure) ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N);
551
552     try
553     {
554         do 
555         {
556             // if we do not have a valid address then send any cycle count elements 
557             // and stop processing
558             if(m_bNeedAddr)
559             {
560                 // output unknown address packet or a cycle count packet
561                 if(!m_bSentUnknown || m_config->isCycleAcc())
562                 {
563                     pElem = GetNextOpElem(resp);
564                     if(m_bSentUnknown || !atoms.numAtoms())
565                         pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
566                     else
567                         pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN);
568                     if(m_config->isCycleAcc())
569                         pElem->setCycleCount(atoms.getRemainCC());
570                     m_bSentUnknown = true;
571                 }
572                 atoms.clearAll();   // skip remaining atoms
573             }
574             else    // have an address, can process atoms
575             {
576                 pElem = GetNextOpElem(resp);
577                 pElem->setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
578     
579                 // cycle accurate may have a cycle count to use
580                 if(m_config->isCycleAcc())
581                 {
582                     // note: it is possible to have a CC only atom packet.
583                     if(!atoms.numAtoms())   // override type if CC only
584                          pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
585                     // set cycle count
586                     pElem->setCycleCount(atoms.getAtomCC());
587                 }
588
589                 // now process the atom 
590                 if(atoms.numAtoms())
591                 {
592                     m_code_follower.setISA(isa);
593                     m_code_follower.followSingleAtom(m_IAddr,atoms.getCurrAtomVal());
594
595                     // valid code range
596                     if(m_code_follower.hasRange())
597                     {
598                         pElem->setAddrRange(m_IAddr,m_code_follower.getRangeEn());
599                         pElem->setLastInstrInfo(atoms.getCurrAtomVal() == ATOM_E, 
600                                     m_code_follower.getInstrType(),
601                                     m_code_follower.getInstrSubType(),m_code_follower.getInstrSize());
602                         pElem->setLastInstrCond(m_code_follower.isCondInstr());
603                         pElem->setISA(isa);
604                         if(m_code_follower.hasNextAddr())
605                             m_IAddr = m_code_follower.getNextAddr();
606                         else
607                             setNeedAddr(true);
608                     }
609
610                     // next address has new ISA?
611                     if(m_code_follower.ISAChanged())
612                         isa = m_code_follower.nextISA();
613                     
614                     // there is a nacc
615                     if(m_code_follower.isNacc())
616                     {
617                         if(m_code_follower.hasRange())
618                         {
619                             pElem = GetNextOpElem(resp);
620                             pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
621                         }
622                         else
623                             pElem->updateType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
624                         pElem->setAddrStart(m_code_follower.getNaccAddr());
625                         setNeedAddr(true);
626                         m_code_follower.clearNacc(); // we have generated some code for the nacc.
627                     }
628                 }
629
630                 atoms.clearAtom();  // next atom
631             }
632         }
633         while(atoms.numAtoms());
634
635         // is tha last element an atom?
636         int numElem = m_outputElemList.getNumElem();
637         if(numElem >= 1)
638         {
639             // if the last thing is an instruction range, pend it - could be cancelled later.
640             if(m_outputElemList.getElemType(numElem-1) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
641                 m_outputElemList.pendLastNElem(1);
642         }
643
644         // finally - do we have anything to send yet?
645         m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
646     }
647     catch(ocsdError &err)
648     {
649         LogError(err);
650         resetDecoder(); // mark decoder as unsynced - dump any current state.
651     }
652     return resp;
653 }
654
655 // if v7M -> pend only ERET, if V7A/R pend ERET and prev instr.
656 void TrcPktDecodeEtmV3::pendExceptionReturn()
657 {
658     int pendElem = 1;
659     if(m_config->getCoreProfile() != profile_CortexM)
660     {
661         int nElem = m_outputElemList.getNumElem();
662         if(nElem > 1)
663         {
664            if(m_outputElemList.getElemType(nElem - 2) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
665                pendElem = 2;    // need to pend instr+eret for A/R
666         }
667     }
668     m_outputElemList.pendLastNElem(pendElem);
669 }
670
671 /* End of File trc_pkt_decode_etmv3.cpp */