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
39TrcPktDecodeEtmV3::TrcPktDecodeEtmV3() :
40    TrcPktDecodeBase(DCD_NAME)
41{
42    initDecoder();
43}
44
45TrcPktDecodeEtmV3::TrcPktDecodeEtmV3(int instIDNum) :
46    TrcPktDecodeBase(DCD_NAME, instIDNum)
47{
48    initDecoder();
49}
50
51TrcPktDecodeEtmV3::~TrcPktDecodeEtmV3()
52{
53}
54
55
56/* implementation packet decoding interface */
57ocsd_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
126ocsd_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
147ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset()
148{
149    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
150    resetDecoder();
151    return resp;
152}
153
154ocsd_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
166ocsd_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
198void 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.
207void 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
216OcsdTraceElement *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
227bool 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.
240ocsd_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
371ocsd_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
388void TrcPktDecodeEtmV3::setNeedAddr(bool bNeedAddr)
389{
390    m_bNeedAddr = bNeedAddr;
391    m_bSentUnknown = false;
392}
393
394ocsd_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
472ocsd_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
541ocsd_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());
602                        pElem->setISA(isa);
603                        if(m_code_follower.hasNextAddr())
604                            m_IAddr = m_code_follower.getNextAddr();
605                        else
606                            setNeedAddr(true);
607                    }
608
609                    // next address has new ISA?
610                    if(m_code_follower.ISAChanged())
611                        isa = m_code_follower.nextISA();
612
613                    // there is a nacc
614                    if(m_code_follower.isNacc())
615                    {
616                        if(m_code_follower.hasRange())
617                        {
618                            pElem = GetNextOpElem(resp);
619                            pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
620                        }
621                        else
622                            pElem->updateType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
623                        pElem->setAddrStart(m_code_follower.getNaccAddr());
624                        setNeedAddr(true);
625                        m_code_follower.clearNacc(); // we have generated some code for the nacc.
626                    }
627                }
628
629                atoms.clearAtom();  // next atom
630            }
631        }
632        while(atoms.numAtoms());
633
634        // is tha last element an atom?
635        int numElem = m_outputElemList.getNumElem();
636        if(numElem >= 1)
637        {
638            // if the last thing is an instruction range, pend it - could be cancelled later.
639            if(m_outputElemList.getElemType(numElem-1) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
640                m_outputElemList.pendLastNElem(1);
641        }
642
643        // finally - do we have anything to send yet?
644        m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
645    }
646    catch(ocsdError &err)
647    {
648        LogError(err);
649        resetDecoder(); // mark decoder as unsynced - dump any current state.
650    }
651    return resp;
652}
653
654// if v7M -> pend only ERET, if V7A/R pend ERET and prev instr.
655void TrcPktDecodeEtmV3::pendExceptionReturn()
656{
657    int pendElem = 1;
658    if(m_config->getCoreProfile() != profile_CortexM)
659    {
660        int nElem = m_outputElemList.getNumElem();
661        if(nElem > 1)
662        {
663           if(m_outputElemList.getElemType(nElem - 2) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
664               pendElem = 2;    // need to pend instr+eret for A/R
665        }
666    }
667    m_outputElemList.pendLastNElem(pendElem);
668}
669
670/* End of File trc_pkt_decode_etmv3.cpp */
671