1 /*
2  * \file       trc_pkt_decode_etmv4i.cpp
3  * \brief      OpenCSD : ETMv4 decoder
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/etmv4/trc_pkt_decode_etmv4i.h"
36 
37 #include "common/trc_gen_elem.h"
38 
39 
40 #define DCD_NAME "DCD_ETMV4"
41 
42 static const uint32_t ETMV4_SUPPORTED_DECODE_OP_FLAGS = OCSD_OPFLG_PKTDEC_COMMON;
43 
44 TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I()
45     : TrcPktDecodeBase(DCD_NAME)
46 {
47     initDecoder();
48 }
49 
50 TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I(int instIDNum)
51     : TrcPktDecodeBase(DCD_NAME,instIDNum)
52 {
53     initDecoder();
54 }
55 
56 TrcPktDecodeEtmV4I::~TrcPktDecodeEtmV4I()
57 {
58 }
59 
60 /*********************** implementation packet decoding interface */
61 
62 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()
63 {
64     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
65     ocsd_err_t err = OCSD_OK;
66     bool bPktDone = false;
67 
68     while(!bPktDone)
69     {
70         switch (m_curr_state)
71         {
72         case NO_SYNC:
73             // output the initial not synced packet to the sink
74             err = m_out_elem.resetElemStack();
75             if (!err)
76                 err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_NO_SYNC);
77             if (!err)
78             {
79                 outElem().setUnSyncEOTReason(m_unsync_eot_info);
80                 resp = m_out_elem.sendElements();
81                 m_curr_state = WAIT_SYNC;
82             }
83             else
84                 resp = OCSD_RESP_FATAL_SYS_ERR;
85 
86             // fall through to check if the current packet is the async we are waiting for.
87             break;
88 
89         case WAIT_SYNC:
90             if(m_curr_packet_in->getType() == ETM4_PKT_I_ASYNC)
91                 m_curr_state = WAIT_TINFO;
92             bPktDone = true;
93             break;
94 
95         case WAIT_TINFO:
96             m_need_ctxt = true;
97             m_need_addr = true;
98             if(m_curr_packet_in->getType() == ETM4_PKT_I_TRACE_INFO)
99             {
100                 doTraceInfoPacket();
101                 m_curr_state = DECODE_PKTS;
102                 m_return_stack.flush();
103             }
104             bPktDone = true;
105             break;
106 
107         case DECODE_PKTS:
108             // this may change the state to RESOLVE_ELEM if required;
109             err = decodePacket();
110             if (err)
111             {
112 #ifdef OCSD_WARN_UNSUPPORTED
113                 if (err == OCSD_ERR_UNSUPP_DECODE_PKT)
114                     resp = OCSD_RESP_WARN_CONT;
115                 else
116 #else
117                 resp = OCSD_RESP_FATAL_INVALID_DATA;
118 #endif
119 
120                 bPktDone = true;
121             }
122             else if (m_curr_state != RESOLVE_ELEM)
123                 bPktDone = true;
124             break;
125 
126         case RESOLVE_ELEM:
127             // this will change the state to DECODE_PKTS once required elem resolved &
128             // needed generic packets output
129             resp = resolveElements();
130             if ((m_curr_state == DECODE_PKTS) || (!OCSD_DATA_RESP_IS_CONT(resp)))
131                 bPktDone = true;
132             break;
133         }
134     }
135     return resp;
136 }
137 
138 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onEOT()
139 {
140     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
141     ocsd_err_t err;
142     if ((err = commitElemOnEOT()) != OCSD_OK)
143     {
144         resp = OCSD_RESP_FATAL_INVALID_DATA;
145         LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Error flushing element stack at end of trace data."));
146     }
147     else
148         resp = m_out_elem.sendElements();
149     return resp;
150 }
151 
152 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onReset()
153 {
154     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
155     m_unsync_eot_info = UNSYNC_RESET_DECODER;
156     resetDecoder();
157     return resp;
158 }
159 
160 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onFlush()
161 {
162     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
163 
164     if (m_curr_state == RESOLVE_ELEM)
165         resp = resolveElements();
166     else
167         resp = m_out_elem.sendElements();
168     return resp;
169 }
170 
171 ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig()
172 {
173     ocsd_err_t err = OCSD_OK;
174 
175     // set some static config elements
176     m_CSID = m_config->getTraceID();
177     m_max_spec_depth = m_config->MaxSpecDepth();
178 
179     // elements associated with data trace
180 #ifdef DATA_TRACE_SUPPORTED
181     m_p0_key_max = m_config->P0_Key_Max();
182     m_cond_key_max_incr = m_config->CondKeyMaxIncr();
183 #endif
184 
185     m_out_elem.initCSID(m_CSID);
186 
187     // set up static trace instruction decode elements
188     m_instr_info.dsb_dmb_waypoints = 0;
189     m_instr_info.wfi_wfe_branch = m_config->wfiwfeBranch() ? 1 : 0;
190     m_instr_info.pe_type.arch = m_config->archVersion();
191     m_instr_info.pe_type.profile = m_config->coreProfile();
192 
193     m_IASize64 = (m_config->iaSizeMax() == 64);
194 
195     if (m_config->enabledRetStack())
196     {
197         m_return_stack.set_active(true);
198 #ifdef TRC_RET_STACK_DEBUG
199         m_return_stack.set_dbg_logger(this);
200 #endif
201     }
202 
203     // check config compatible with current decoder support level.
204     // at present no data trace, no spec depth, no return stack, no QE
205     // Remove these checks as support is added.
206     if(m_config->enabledDataTrace())
207     {
208         err = OCSD_ERR_HW_CFG_UNSUPP;
209         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Data trace elements not supported"));
210     }
211     else if(m_config->enabledLSP0Trace())
212     {
213         err = OCSD_ERR_HW_CFG_UNSUPP;
214         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : LSP0 elements not supported."));
215     }
216     else if(m_config->enabledCondITrace() != EtmV4Config::COND_TR_DIS)
217     {
218         err = OCSD_ERR_HW_CFG_UNSUPP;
219         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace on conditional non-branch elements not supported."));
220     }
221     return err;
222 }
223 
224 /************* local decode methods */
225 void TrcPktDecodeEtmV4I::initDecoder()
226 {
227     // set the operational modes supported.
228     m_supported_op_flags = ETMV4_SUPPORTED_DECODE_OP_FLAGS;
229 
230     /* init elements that get set by config */
231     m_max_spec_depth = 0;
232     m_CSID = 0;
233     m_IASize64 = false;
234 
235     // elements associated with data trace
236 #ifdef DATA_TRACE_SUPPORTED
237     m_p0_key_max = 0;
238     m_cond_key_max_incr = 0;
239 #endif
240 
241     // reset decoder state to unsynced
242     m_unsync_eot_info = UNSYNC_INIT_DECODER;
243     resetDecoder();
244 }
245 
246 void TrcPktDecodeEtmV4I::resetDecoder()
247 {
248     m_curr_state = NO_SYNC;
249     m_timestamp = 0;
250     m_context_id = 0;
251     m_vmid_id = 0;
252     m_is_secure = true;
253     m_is_64bit = false;
254     m_cc_threshold = 0;
255     m_curr_spec_depth = 0;
256     m_need_ctxt = true;
257     m_need_addr = true;
258     m_elem_pending_addr = false;
259     m_prev_overflow = false;
260     m_P0_stack.delete_all();
261     m_out_elem.resetElemStack();
262     m_last_IS = 0;
263     clearElemRes();
264 
265     // elements associated with data trace
266 #ifdef DATA_TRACE_SUPPORTED
267     m_p0_key = 0;
268     m_cond_c_key = 0;
269     m_cond_r_key = 0;
270 #endif
271 }
272 
273 void TrcPktDecodeEtmV4I::onFirstInitOK()
274 {
275     // once init, set the output element interface to the out elem list.
276     m_out_elem.initSendIf(this->getTraceElemOutAttachPt());
277 }
278 
279 // Changes a packet into stack of trace elements - these will be resolved and output later
280 ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()
281 {
282     ocsd_err_t err = OCSD_OK;
283     bool bAllocErr = false;
284     bool is_addr = false;
285 
286     switch(m_curr_packet_in->getType())
287     {
288     case ETM4_PKT_I_ASYNC: // nothing to do with this packet.
289     case ETM4_PKT_I_IGNORE: // or this one.
290         break;
291 
292     case ETM4_PKT_I_TRACE_INFO:
293         // skip subsequent TInfo packets.
294         m_return_stack.flush();
295         break;
296 
297     case ETM4_PKT_I_TRACE_ON:
298         {
299             if (m_P0_stack.createParamElemNoParam(P0_TRC_ON, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
300                 bAllocErr = true;
301         }
302         break;
303 
304     case ETM4_PKT_I_ATOM_F1:
305     case ETM4_PKT_I_ATOM_F2:
306     case ETM4_PKT_I_ATOM_F3:
307     case ETM4_PKT_I_ATOM_F4:
308     case ETM4_PKT_I_ATOM_F5:
309     case ETM4_PKT_I_ATOM_F6:
310         {
311             if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0)
312                 bAllocErr = true;
313             else
314                 m_curr_spec_depth += m_curr_packet_in->getAtom().num;
315         }
316         break;
317 
318     case ETM4_PKT_I_CTXT:
319         {
320             if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)
321                 bAllocErr = true;
322         }
323         break;
324 
325     case ETM4_PKT_I_ADDR_MATCH:
326         {
327             etmv4_addr_val_t addr;
328 
329             addr.val = m_curr_packet_in->getAddrVal();
330             addr.isa = m_last_IS = m_curr_packet_in->getAddrIS();
331 
332             if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
333                 bAllocErr = true;
334             is_addr = true;
335         }
336         break;
337 
338     case ETM4_PKT_I_ADDR_CTXT_L_64IS0:
339     case ETM4_PKT_I_ADDR_CTXT_L_64IS1:
340     case ETM4_PKT_I_ADDR_CTXT_L_32IS0:
341     case ETM4_PKT_I_ADDR_CTXT_L_32IS1:
342         {
343             m_last_IS = m_curr_packet_in->getAddrIS();
344             if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)
345                 bAllocErr = true;
346         }
347     case ETM4_PKT_I_ADDR_L_32IS0:
348     case ETM4_PKT_I_ADDR_L_32IS1:
349     case ETM4_PKT_I_ADDR_L_64IS0:
350     case ETM4_PKT_I_ADDR_L_64IS1:
351     case ETM4_PKT_I_ADDR_S_IS0:
352     case ETM4_PKT_I_ADDR_S_IS1:
353         {
354             etmv4_addr_val_t addr;
355 
356             addr.val = m_curr_packet_in->getAddrVal();
357             addr.isa = m_last_IS = m_curr_packet_in->getAddrIS();
358 
359             if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
360                 bAllocErr = true;
361             is_addr = true;
362         }
363         break;
364 
365     // Exceptions
366     case ETM4_PKT_I_EXCEPT:
367          {
368             if (m_P0_stack.createExceptElem(m_curr_packet_in->getType(), m_index_curr_pkt,
369                                             (m_curr_packet_in->exception_info.addr_interp == 0x2),
370                                             m_curr_packet_in->exception_info.exceptionType) == 0)
371                 bAllocErr = true;
372             else
373                 m_elem_pending_addr = true;  // wait for following packets before marking for commit.
374         }
375         break;
376 
377     case ETM4_PKT_I_EXCEPT_RTN:
378         {
379             // P0 element if V7M profile.
380             bool bV7MProfile = (m_config->archVersion() == ARCH_V7) && (m_config->coreProfile() == profile_CortexM);
381             if (m_P0_stack.createParamElemNoParam(P0_EXCEP_RET, bV7MProfile, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
382                 bAllocErr = true;
383             else if (bV7MProfile)
384                 m_curr_spec_depth++;
385         }
386         break;
387 
388     case ETM4_PKT_I_FUNC_RET:
389         {
390             // P0 element iff V8M profile, otherwise ignore
391             if (OCSD_IS_V8_ARCH(m_config->archVersion()) && (m_config->coreProfile() == profile_CortexM))
392             {
393                 if (m_P0_stack.createParamElemNoParam(P0_FUNC_RET, true, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
394                     bAllocErr = true;
395                 else
396                     m_curr_spec_depth++;
397             }
398         }
399         break;
400 
401     // event trace
402     case ETM4_PKT_I_EVENT:
403         {
404             std::vector<uint32_t> params = { 0 };
405             params[0] = (uint32_t)m_curr_packet_in->event_val;
406             if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
407                 bAllocErr = true;
408 
409         }
410         break;
411 
412     /* cycle count packets */
413     case ETM4_PKT_I_CCNT_F1:
414     case ETM4_PKT_I_CCNT_F2:
415     case ETM4_PKT_I_CCNT_F3:
416         {
417             std::vector<uint32_t> params = { 0 };
418             params[0] = m_curr_packet_in->getCC();
419             if (m_P0_stack.createParamElem(P0_CC, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
420                 bAllocErr = true;
421 
422         }
423         break;
424 
425     // timestamp
426     case ETM4_PKT_I_TIMESTAMP:
427         {
428             bool bTSwithCC = m_config->enabledCCI();
429             uint64_t ts = m_curr_packet_in->getTS();
430             std::vector<uint32_t> params = { 0, 0, 0 };
431             params[0] = (uint32_t)(ts & 0xFFFFFFFF);
432             params[1] = (uint32_t)((ts >> 32) & 0xFFFFFFFF);
433             if (bTSwithCC)
434                 params[2] = m_curr_packet_in->getCC();
435             if (m_P0_stack.createParamElem(bTSwithCC ? P0_TS_CC : P0_TS, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
436                 bAllocErr = true;
437 
438         }
439         break;
440 
441     case ETM4_PKT_I_BAD_SEQUENCE:
442         err = handleBadPacket("Bad byte sequence in packet.");
443         break;
444 
445     case ETM4_PKT_I_BAD_TRACEMODE:
446         err = handleBadPacket("Invalid packet type for trace mode.");
447         break;
448 
449     case ETM4_PKT_I_RESERVED:
450         err = handleBadPacket("Reserved packet header");
451         break;
452 
453     // speculation
454     case ETM4_PKT_I_MISPREDICT:
455     case ETM4_PKT_I_CANCEL_F1_MISPRED:
456     case ETM4_PKT_I_CANCEL_F2:
457     case ETM4_PKT_I_CANCEL_F3:
458         m_elem_res.mispredict = true;
459         if (m_curr_packet_in->getNumAtoms())
460         {
461             if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0)
462                 bAllocErr = true;
463             else
464                 m_curr_spec_depth += m_curr_packet_in->getNumAtoms();
465         }
466 
467     case ETM4_PKT_I_CANCEL_F1:
468         m_elem_res.P0_cancel = m_curr_packet_in->getCancelElem();
469         break;
470 
471     case ETM4_PKT_I_COMMIT:
472         m_elem_res.P0_commit = m_curr_packet_in->getCommitElem();
473         break;
474 
475     case ETM4_PKT_I_OVERFLOW:
476         m_prev_overflow = true;
477     case ETM4_PKT_I_DISCARD:
478         m_curr_spec_depth = 0;
479         m_elem_res.discard = true;
480         break;
481 
482         /* Q packets */
483     case ETM4_PKT_I_Q:
484         {
485             TrcStackQElem *pQElem = m_P0_stack.createQElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->Q_pkt.q_count);
486             if (pQElem)
487             {
488                 if (m_curr_packet_in->Q_pkt.addr_present)
489                 {
490                     etmv4_addr_val_t addr;
491 
492                     addr.val = m_curr_packet_in->getAddrVal();
493                     addr.isa = m_curr_packet_in->getAddrIS();
494                     pQElem->setAddr(addr);
495                     m_curr_spec_depth++;
496                 }
497                 else
498                     m_elem_pending_addr = true;
499             }
500             else
501                 bAllocErr = true;
502         }
503         break;
504 
505     /*** presently unsupported packets ***/
506     /* conditional instruction tracing */
507     case ETM4_PKT_I_COND_FLUSH:
508     case ETM4_PKT_I_COND_I_F1:
509     case ETM4_PKT_I_COND_I_F2:
510     case ETM4_PKT_I_COND_I_F3:
511     case ETM4_PKT_I_COND_RES_F1:
512     case ETM4_PKT_I_COND_RES_F2:
513     case ETM4_PKT_I_COND_RES_F3:
514     case ETM4_PKT_I_COND_RES_F4:
515     // data synchronisation markers
516     case ETM4_PKT_I_NUM_DS_MKR:
517     case ETM4_PKT_I_UNNUM_DS_MKR:
518         // all currently unsupported
519         {
520         ocsd_err_severity_t sev = OCSD_ERR_SEV_ERROR;
521 #ifdef OCSD_WARN_UNSUPPORTED
522         sev = OCSD_ERR_SEV_WARN;
523         //resp = OCSD_RESP_WARN_CONT;
524 #else
525         //resp = OCSD_RESP_FATAL_INVALID_DATA;
526 #endif
527         err = OCSD_ERR_UNSUPP_DECODE_PKT;
528         LogError(ocsdError(sev, err, "Data trace releated, unsupported packet type."));
529         }
530         break;
531 
532     default:
533         // any other packet - bad packet error
534         err = OCSD_ERR_BAD_DECODE_PKT;
535         LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Unknown packet type."));
536         break;
537     }
538 
539     // we need to wait for following address after certain packets
540     // - work out if we have seen enough here...
541     if (is_addr && m_elem_pending_addr)
542     {
543         m_curr_spec_depth++;  // increase spec depth for element waiting on address.
544         m_elem_pending_addr = false;  // can't be waiting on both
545     }
546 
547     if(bAllocErr)
548     {
549         err = OCSD_ERR_MEM;
550         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error."));
551     }
552     else if(m_curr_spec_depth > m_max_spec_depth)
553     {
554         // auto commit anything above max spec depth
555         // (this will auto commit anything if spec depth not supported!)
556         m_elem_res.P0_commit = m_curr_spec_depth - m_max_spec_depth;
557     }
558 
559     if (!err && isElemForRes())
560         m_curr_state = RESOLVE_ELEM;
561     return err;
562 }
563 
564 void TrcPktDecodeEtmV4I::doTraceInfoPacket()
565 {
566     m_trace_info = m_curr_packet_in->getTraceInfo();
567     m_cc_threshold = m_curr_packet_in->getCCThreshold();
568     m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth();
569 
570     // elements associated with data trace
571 #ifdef DATA_TRACE_SUPPORTED
572     m_p0_key = m_curr_packet_in->getP0Key();
573 #endif
574 }
575 
576 /* Element resolution
577  * Commit or cancel elements as required
578  * Send any buffered output packets.
579  */
580 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements()
581 {
582     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
583     bool Complete = false;
584 
585     while (!Complete)
586     {
587         if (m_out_elem.numElemToSend())
588             resp = m_out_elem.sendElements();
589         else if (isElemForRes())
590         {
591             ocsd_err_t err = OCSD_OK;
592             if (m_elem_res.P0_commit)
593                 err = commitElements();
594 
595             if (!err && m_elem_res.P0_cancel)
596                 err = cancelElements();
597 
598             if (!err && m_elem_res.mispredict)
599                 err = mispredictAtom();
600 
601             if (!err && m_elem_res.discard)
602                 err = discardElements();
603 
604             if (err != OCSD_OK)
605                 resp = OCSD_RESP_FATAL_INVALID_DATA;
606         }
607 
608         // break out on error or wait request.
609         if (!OCSD_DATA_RESP_IS_CONT(resp))
610             break;
611 
612         // completion is nothing to send and nothing to commit
613         Complete = !m_out_elem.numElemToSend() && !isElemForRes();
614 
615         // done all elements - need more packets.
616         if (Complete) {
617             // if we are still in resolve, the goto decode.
618             if (m_curr_state == RESOLVE_ELEM)
619                 m_curr_state = DECODE_PKTS;
620         }
621     }
622     return resp;
623 }
624 
625 /*
626  * Walks through the element stack, processing from oldest element to the newest,
627    according to the number of P0 elements that need committing.
628    Build a stack of output elements in the process.
629  */
630 ocsd_err_t TrcPktDecodeEtmV4I::commitElements()
631 {
632     ocsd_err_t err = OCSD_OK;
633     bool bPopElem = true;       // do we remove the element from the stack (multi atom elements may need to stay!)
634     int num_commit_req = m_elem_res.P0_commit;
635     ocsd_trc_index_t err_idx = 0;
636     TrcStackElem *pElem = 0;    // stacked element pointer
637 
638     err = m_out_elem.resetElemStack();
639 
640     while(m_elem_res.P0_commit && !err)
641     {
642         if (m_P0_stack.size() > 0)
643         {
644             pElem = m_P0_stack.back();  // get oldest element
645             err_idx = pElem->getRootIndex(); // save index in case of error.
646 
647             switch (pElem->getP0Type())
648             {
649             // indicates a trace restart - beginning of trace or discontinuiuty
650             case P0_TRC_ON:
651                 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON);
652                 if (!err)
653                 {
654                     m_out_elem.getCurrElem().trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL;
655                     m_prev_overflow = false;
656                     m_return_stack.flush();
657                 }
658                 break;
659 
660             case P0_ADDR:
661                 {
662                 TrcStackElemAddr *pAddrElem = dynamic_cast<TrcStackElemAddr *>(pElem);
663                 m_return_stack.clear_pop_pending(); // address removes the need to pop the indirect address target from the stack
664                 if(pAddrElem)
665                 {
666                     SetInstrInfoInAddrISA(pAddrElem->getAddr().val, pAddrElem->getAddr().isa);
667                     m_need_addr = false;
668                 }
669                 }
670                 break;
671 
672             case P0_CTXT:
673                 {
674                 TrcStackElemCtxt *pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
675                 if(pCtxtElem)
676                 {
677                     etmv4_context_t ctxt = pCtxtElem->getContext();
678                     // check this is an updated context
679                     if(ctxt.updated)
680                     {
681                         err = m_out_elem.addElem(pElem->getRootIndex());
682                         if (!err)
683                             updateContext(pCtxtElem, outElem());
684                     }
685                 }
686                 }
687                 break;
688 
689             case P0_EVENT:
690             case P0_TS:
691             case P0_CC:
692             case P0_TS_CC:
693                 err = processTS_CC_EventElem(pElem);
694                 break;
695 
696             case P0_ATOM:
697                 {
698                 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
699 
700                 if(pAtomElem)
701                 {
702                     while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err)
703                     {
704                         ocsd_atm_val atom = pAtomElem->commitOldest();
705 
706                         // check if prev atom left us an indirect address target on the return stack
707                         if ((err = returnStackPop()) != OCSD_OK)
708                             break;
709 
710                         // if address and context do instruction trace follower.
711                         // otherwise skip atom and reduce committed elements
712                         if(!m_need_ctxt && !m_need_addr)
713                         {
714                             err = processAtom(atom);
715                         }
716                         m_elem_res.P0_commit--; // mark committed
717                     }
718                     if(!pAtomElem->isEmpty())
719                         bPopElem = false;   // don't remove if still atoms to process.
720                 }
721                 }
722                 break;
723 
724             case P0_EXCEP:
725                 // check if prev atom left us an indirect address target on the return stack
726                 if ((err = returnStackPop()) != OCSD_OK)
727                     break;
728 
729                 err = processException();  // output trace + exception elements.
730                 m_elem_res.P0_commit--;
731                 break;
732 
733             case P0_EXCEP_RET:
734                 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
735                 if (!err)
736                 {
737                     if (pElem->isP0()) // are we on a core that counts ERET as P0?
738                         m_elem_res.P0_commit--;
739                 }
740                 break;
741 
742             case P0_FUNC_RET:
743                 // func ret is V8M - data trace only - hint that data has been popped off the stack.
744                 // at this point nothing to do till the decoder starts handling data trace.
745                 if (pElem->isP0())
746                     m_elem_res.P0_commit--;
747                 break;
748 
749             case P0_Q:
750                 err = processQElement();
751                 m_elem_res.P0_commit--;
752                 break;
753             }
754 
755             if(bPopElem)
756                 m_P0_stack.delete_back();  // remove element from stack;
757         }
758         else
759         {
760             // too few elements for commit operation - decode error.
761             err = OCSD_ERR_COMMIT_PKT_OVERRUN;
762             LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_COMMIT_PKT_OVERRUN,err_idx,m_CSID,"Not enough elements to commit"));
763         }
764     }
765 
766     // reduce the spec depth by number of comitted elements
767     m_curr_spec_depth -= (num_commit_req-m_elem_res.P0_commit);
768     return err;
769 }
770 
771 ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop()
772 {
773     ocsd_err_t err = OCSD_OK;
774     ocsd_isa nextISA;
775 
776     if (m_return_stack.pop_pending())
777     {
778         ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA);
779         if (m_return_stack.overflow())
780         {
781             err = OCSD_ERR_RET_STACK_OVERFLOW;
782             LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Trace Return Stack Overflow."));
783         }
784         else
785         {
786             m_instr_info.instr_addr = popAddr;
787             m_instr_info.isa = nextISA;
788             m_need_addr = false;
789         }
790     }
791     return err;
792 }
793 
794 ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT()
795 {
796     ocsd_err_t err = OCSD_OK;
797     TrcStackElem *pElem = 0;
798 
799     // nothing outstanding - reset the stack before we add more
800     if (!m_out_elem.numElemToSend())
801         m_out_elem.resetElemStack();
802 
803     while((m_P0_stack.size() > 0) && !err)
804     {
805         // scan for outstanding events, TS and CC, that appear before any outstanding
806         // uncommited P0 element.
807         pElem = m_P0_stack.back();
808 
809             switch(pElem->getP0Type())
810             {
811                 // clear stack and stop
812             case P0_UNKNOWN:
813             case P0_ATOM:
814             case P0_TRC_ON:
815             case P0_EXCEP:
816             case P0_EXCEP_RET:
817             case P0_OVERFLOW:
818             case P0_Q:
819                 m_P0_stack.delete_all();
820                 break;
821 
822             //skip
823         case P0_ADDR:
824         case P0_CTXT:
825             break;
826 
827             // output
828         case P0_EVENT:
829         case P0_TS:
830         case P0_CC:
831         case P0_TS_CC:
832             err = processTS_CC_EventElem(pElem);
833             break;
834         }
835         m_P0_stack.delete_back();
836     }
837 
838     if(!err)
839     {
840         err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_EO_TRACE);
841         outElem().setUnSyncEOTReason(m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_EOT);
842     }
843     return err;
844 }
845 
846 // cancel elements. These not output
847 ocsd_err_t TrcPktDecodeEtmV4I::cancelElements()
848 {
849     ocsd_err_t err = OCSD_OK;
850     bool P0StackDone = false;  // checked all P0 elements on the stack
851     TrcStackElem *pElem = 0;   // stacked element pointer
852     EtmV4P0Stack temp;
853     int num_cancel_req = m_elem_res.P0_cancel;
854 
855     while (m_elem_res.P0_cancel)
856     {
857         //search the stack for the newest elements
858         if (!P0StackDone)
859         {
860             if (m_P0_stack.size() == 0)
861                 P0StackDone = true;
862             else
863             {
864                 // get the newest element
865                 pElem = m_P0_stack.front();
866                 if (pElem->isP0()) {
867                     if (pElem->getP0Type() == P0_ATOM)
868                     {
869                         TrcStackElemAtom *pAtomElem = (TrcStackElemAtom *)pElem;
870                         // atom - cancel N atoms
871                         m_elem_res.P0_cancel -= pAtomElem->cancelNewest(m_elem_res.P0_cancel);
872                         if (pAtomElem->isEmpty())
873                             m_P0_stack.delete_front();  // remove the element
874                     }
875                     else
876                     {
877                         m_elem_res.P0_cancel--;
878                         m_P0_stack.delete_front();  // remove the element
879                     }
880                 } else {
881                 // not P0, make a keep / remove decision
882                     switch (pElem->getP0Type())
883                     {
884                     // keep these
885                     case P0_EVENT:
886                     case P0_TS:
887                     case P0_CC:
888                     case P0_TS_CC:
889                         m_P0_stack.pop_front(false);
890                         temp.push_back(pElem);
891                         break;
892 
893                     default:
894                         m_P0_stack.delete_front();
895                         break;
896                     }
897                 }
898             }
899         }
900         // may have some unseen elements
901         else if (m_unseen_spec_elem)
902         {
903             m_unseen_spec_elem--;
904             m_elem_res.P0_cancel--;
905         }
906         // otherwise we have some sort of overrun
907         else
908         {
909             // too few elements for commit operation - decode error.
910             err = OCSD_ERR_COMMIT_PKT_OVERRUN;
911             LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not enough elements to cancel"));
912             m_elem_res.P0_cancel = 0;
913             break;
914         }
915 
916         if (temp.size())
917         {
918             while (temp.size())
919             {
920                 pElem = temp.back();
921                 m_P0_stack.push_front(pElem);
922                 temp.pop_back(false);
923             }
924         }
925     }
926     m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel;
927     return err;
928 }
929 
930 // mispredict an atom
931 ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom()
932 {
933     ocsd_err_t err = OCSD_OK;
934     bool bFoundAtom = false, bDone = false;
935     TrcStackElem *pElem = 0;
936 
937     m_P0_stack.from_front_init();   // init iterator at front.
938     while (!bDone)
939     {
940         pElem = m_P0_stack.from_front_next();
941         if (pElem)
942         {
943             if (pElem->getP0Type() == P0_ATOM)
944             {
945                 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
946                 if (pAtomElem)
947                 {
948                     pAtomElem->mispredictNewest();
949                     bFoundAtom = true;
950                 }
951                 bDone = true;
952             }
953             else if (pElem->getP0Type() == P0_ADDR)
954             {
955                 // need to disregard any addresses that appear between mispredict and the atom in question
956                 m_P0_stack.erase_curr_from_front();
957             }
958         }
959         else
960             bDone = true;
961     }
962 
963     // if missed atom then either overrun error or mispredict on unseen element
964     if (!bFoundAtom && !m_unseen_spec_elem)
965     {
966         err = OCSD_ERR_COMMIT_PKT_OVERRUN;
967         LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom"));
968     }
969     m_elem_res.mispredict = false;
970     return err;
971 }
972 
973 // discard elements and flush
974 ocsd_err_t TrcPktDecodeEtmV4I::discardElements()
975 {
976     ocsd_err_t err = OCSD_OK;
977     TrcStackElem *pElem = 0;   // stacked element pointer
978 
979     // dump P0, elemnts - output remaining CC / TS
980     while ((m_P0_stack.size() > 0) && !err)
981     {
982         pElem = m_P0_stack.back();
983         err = processTS_CC_EventElem(pElem);
984         m_P0_stack.delete_back();
985     }
986 
987     // clear all speculation info
988     clearElemRes();
989     m_curr_spec_depth = 0;
990 
991     // set decode state
992     m_curr_state = NO_SYNC;
993     m_unsync_eot_info = m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_DISCARD;
994 
995     // unsync so need context & address.
996     m_need_ctxt = true;
997     m_need_addr = true;
998     m_elem_pending_addr = false;
999     return err;
1000 }
1001 
1002 ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)
1003 {
1004     ocsd_err_t err = OCSD_OK;
1005 
1006     switch (pElem->getP0Type())
1007     {
1008         case P0_EVENT:
1009         {
1010             TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1011             if (pParamElem)
1012                 err = addElemEvent(pParamElem);
1013         }
1014         break;
1015 
1016         case P0_TS:
1017         {
1018             TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1019             if (pParamElem)
1020                 err = addElemTS(pParamElem, false);
1021         }
1022         break;
1023 
1024         case P0_CC:
1025         {
1026             TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1027             if (pParamElem)
1028                 err = addElemCC(pParamElem);
1029         }
1030         break;
1031 
1032         case P0_TS_CC:
1033         {
1034             TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1035             if (pParamElem)
1036                 err = addElemTS(pParamElem, true);
1037         }
1038         break;
1039     }
1040     return err;
1041 
1042 }
1043 
1044 ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem)
1045 {
1046     ocsd_err_t err = OCSD_OK;
1047 
1048     err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
1049     if (!err)
1050         outElem().setCycleCount(pParamElem->getParam(0));
1051     return err;
1052 }
1053 
1054 ocsd_err_t TrcPktDecodeEtmV4I::addElemTS(TrcStackElemParam *pParamElem, bool withCC)
1055 {
1056     ocsd_err_t err = OCSD_OK;
1057 
1058     err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TIMESTAMP);
1059     if (!err)
1060     {
1061         outElem().timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32);
1062         if (withCC)
1063             outElem().setCycleCount(pParamElem->getParam(2));
1064     }
1065     return err;
1066 }
1067 
1068 ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem)
1069 {
1070     ocsd_err_t err = OCSD_OK;
1071 
1072     err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EVENT);
1073     if (!err)
1074     {
1075         outElem().trace_event.ev_type = EVENT_NUMBERED;
1076         outElem().trace_event.ev_number = pParamElem->getParam(0);
1077     }
1078     return err;
1079 }
1080 
1081 void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range,
1082                                            const bool executed, ocsd_trc_index_t index)
1083 {
1084     elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
1085     elemIn.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size);
1086     elemIn.setISA(m_instr_info.isa);
1087     elemIn.setLastInstrCond(m_instr_info.is_conditional);
1088     elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
1089     if (executed)
1090         m_instr_info.isa = m_instr_info.next_isa;
1091 }
1092 
1093 ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)
1094 {
1095     ocsd_err_t err;
1096     TrcStackElem *pElem = m_P0_stack.back();  // get the atom element
1097     WP_res_t WPRes;
1098     instr_range_t addr_range;
1099 
1100     // new element for this processed atom
1101     if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK)
1102         return err;
1103 
1104     err = traceInstrToWP(addr_range, WPRes);
1105     if(err != OCSD_OK)
1106     {
1107         if(err == OCSD_ERR_UNSUPPORTED_ISA)
1108         {
1109              m_need_addr = true;
1110              m_need_ctxt = true;
1111              LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet."));
1112              // wait for next context
1113              return OCSD_OK;
1114         }
1115         else
1116         {
1117             LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));
1118             return err;
1119         }
1120     }
1121 
1122     if(WPFound(WPRes))
1123     {
1124         //  save recorded next instuction address
1125         ocsd_vaddr_t nextAddr = m_instr_info.instr_addr;
1126 
1127         // action according to waypoint type and atom value
1128         switch(m_instr_info.type)
1129         {
1130         case OCSD_INSTR_BR:
1131             if (atom == ATOM_E)
1132             {
1133                 m_instr_info.instr_addr = m_instr_info.branch_addr;
1134                 if (m_instr_info.is_link)
1135                     m_return_stack.push(nextAddr, m_instr_info.isa);
1136 
1137             }
1138             break;
1139 
1140         case OCSD_INSTR_BR_INDIRECT:
1141             if (atom == ATOM_E)
1142             {
1143                 m_need_addr = true; // indirect branch taken - need new address.
1144                 if (m_instr_info.is_link)
1145                     m_return_stack.push(nextAddr,m_instr_info.isa);
1146                 m_return_stack.set_pop_pending();  // need to know next packet before we know what is to happen
1147             }
1148             break;
1149         }
1150         setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex());
1151     }
1152     else
1153     {
1154         // no waypoint - likely inaccessible memory range.
1155         m_need_addr = true; // need an address update
1156 
1157         if(addr_range.st_addr != addr_range.en_addr)
1158         {
1159             // some trace before we were out of memory access range
1160             setElemTraceRange(outElem(), addr_range, true, pElem->getRootIndex());
1161 
1162             // another element for the nacc...
1163             if (WPNacc(WPRes))
1164                 err = m_out_elem.addElem(pElem->getRootIndex());
1165         }
1166 
1167         if(WPNacc(WPRes) && !err)
1168         {
1169             outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1170             outElem().st_addr = m_instr_info.instr_addr;
1171         }
1172     }
1173     return err;
1174 }
1175 
1176 // Exception processor
1177 ocsd_err_t TrcPktDecodeEtmV4I::processException()
1178 {
1179     ocsd_err_t err;
1180     TrcStackElem *pElem = 0;
1181     TrcStackElemExcept *pExceptElem = 0;
1182     TrcStackElemAddr *pAddressElem = 0;
1183     TrcStackElemCtxt *pCtxtElem = 0;
1184     bool branch_target = false;    // exception address implies prior branch target address
1185     ocsd_vaddr_t excep_ret_addr;
1186     ocsd_trc_index_t excep_pkt_index;
1187     WP_res_t WPRes = WP_NOT_FOUND;
1188 
1189     // grab the exception element off the stack
1190     pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back());  // get the exception element
1191     excep_pkt_index = pExceptElem->getRootIndex();
1192     branch_target = pExceptElem->getPrevSame();
1193     m_P0_stack.pop_back(); // remove the exception element
1194 
1195     pElem = m_P0_stack.back();  // look at next element.
1196     if(pElem->getP0Type() == P0_CTXT)
1197     {
1198         pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
1199         m_P0_stack.pop_back(); // remove the context element
1200         pElem = m_P0_stack.back();  // next one should be an address element
1201     }
1202 
1203    if(pElem->getP0Type() != P0_ADDR)
1204    {
1205        // no following address element - indicate processing error.
1206        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index,m_CSID,"Address missing in exception packet."));
1207        return OCSD_ERR_BAD_PACKET_SEQ;
1208    }
1209    else
1210    {
1211         // extract address
1212         pAddressElem = static_cast<TrcStackElemAddr *>(pElem);
1213         excep_ret_addr = pAddressElem->getAddr().val;
1214 
1215         // see if there is an address + optional context element implied
1216         // prior to the exception.
1217         if (branch_target)
1218         {
1219             // this was a branch target address - update current setting
1220             bool b64bit = m_instr_info.isa == ocsd_isa_aarch64;
1221             if (pCtxtElem) {
1222                 b64bit = pCtxtElem->getContext().SF;
1223             }
1224 
1225             // as the exception address was also a branch target address then update the
1226             // current maintained address value. This also means that there is no range to
1227             // output before the exception packet.
1228             m_instr_info.instr_addr = excep_ret_addr;
1229             m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ?
1230                     (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2;
1231             m_need_addr = false;
1232         }
1233     }
1234 
1235     // need to output something - set up an element
1236     if ((err = m_out_elem.addElem(excep_pkt_index)))
1237         return err;
1238 
1239     // output a context element if present
1240     if (pCtxtElem)
1241     {
1242         updateContext(pCtxtElem, outElem());
1243 
1244         // used the element - need another for later stages
1245         if ((err = m_out_elem.addElem(excep_pkt_index)))
1246             return err;
1247     }
1248 
1249     // if the preferred return address is not the end of the last output range...
1250     if (m_instr_info.instr_addr != excep_ret_addr)
1251     {
1252         bool range_out = false;
1253         instr_range_t addr_range;
1254 
1255         // look for match to return address.
1256         err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr);
1257 
1258         if(err != OCSD_OK)
1259         {
1260             if(err == OCSD_ERR_UNSUPPORTED_ISA)
1261             {
1262                 m_need_addr = true;
1263                 m_need_ctxt = true;
1264                 LogError(ocsdError(OCSD_ERR_SEV_WARN,err, excep_pkt_index,m_CSID,"Warning: unsupported instruction set processing exception packet."));
1265             }
1266             else
1267             {
1268                 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err, excep_pkt_index,m_CSID,"Error processing exception packet."));
1269             }
1270             return err;
1271         }
1272 
1273         if(WPFound(WPRes))
1274         {
1275             // waypoint address found - output range
1276             setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
1277             range_out = true;
1278         }
1279         else
1280         {
1281             // no waypoint - likely inaccessible memory range.
1282             m_need_addr = true; // need an address update
1283 
1284             if(addr_range.st_addr != addr_range.en_addr)
1285             {
1286                 // some trace before we were out of memory access range
1287                 setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
1288                 range_out = true;
1289             }
1290         }
1291 
1292         // used the element need another for NACC or EXCEP.
1293         if (range_out)
1294         {
1295             if ((err = m_out_elem.addElem(excep_pkt_index)))
1296                 return err;
1297         }
1298     }
1299 
1300     // watchpoint walk resulted in inaccessible memory call...
1301     if (WPNacc(WPRes))
1302     {
1303 
1304         outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1305         outElem().st_addr = m_instr_info.instr_addr;
1306 
1307         // used the element - need another for the final exception packet.
1308         if ((err = m_out_elem.addElem(excep_pkt_index)))
1309             return err;
1310     }
1311 
1312     // output exception element.
1313     outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
1314 
1315     // add end address as preferred return address to end addr in element
1316     outElem().en_addr = excep_ret_addr;
1317     outElem().excep_ret_addr = 1;
1318     outElem().excep_ret_addr_br_tgt = branch_target;
1319     outElem().exception_number = pExceptElem->getExcepNum();
1320 
1321     m_P0_stack.delete_popped();     // clear the used elements from the stack
1322     return err;
1323 }
1324 
1325 ocsd_err_t TrcPktDecodeEtmV4I::processQElement()
1326 {
1327     ocsd_err_t err = OCSD_OK;
1328     TrcStackQElem *pQElem;
1329     etmv4_addr_val_t QAddr; // address where trace restarts
1330     int iCount = 0;
1331 
1332     pQElem = dynamic_cast<TrcStackQElem *>(m_P0_stack.back());  // get the exception element
1333     m_P0_stack.pop_back(); // remove the Q element.
1334 
1335     if (!pQElem->hasAddr())  // no address - it must be next on the stack....
1336     {
1337         TrcStackElemAddr *pAddressElem = 0;
1338         TrcStackElemCtxt *pCtxtElem = 0;
1339         TrcStackElem *pElem = 0;
1340 
1341         pElem = m_P0_stack.back();  // look at next element.
1342         if (pElem->getP0Type() == P0_CTXT)
1343         {
1344             pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
1345             m_P0_stack.pop_back(); // remove the context element
1346             pElem = m_P0_stack.back();  // next one should be an address element
1347         }
1348 
1349         if (pElem->getP0Type() != P0_ADDR)
1350         {
1351             // no following address element - indicate processing error.
1352             err = OCSD_ERR_BAD_PACKET_SEQ;
1353             LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Address missing in Q packet."));
1354             m_P0_stack.delete_popped();
1355             return err;
1356         }
1357         pAddressElem = dynamic_cast<TrcStackElemAddr *>(pElem);
1358         QAddr = pAddressElem->getAddr();
1359         m_P0_stack.pop_back();  // remove the address element
1360         m_P0_stack.delete_popped(); // clear used elements
1361 
1362         // return the context element for processing next time.
1363         if (pCtxtElem)
1364         {
1365             // need a new copy at the back - old one will be deleted as popped.
1366             m_P0_stack.createContextElem(pCtxtElem->getRootPkt(), pCtxtElem->getRootIndex(), pCtxtElem->getContext(),true);
1367         }
1368     }
1369     else
1370         QAddr = pQElem->getAddr();
1371 
1372     // process the Q element with address.
1373     iCount = pQElem->getInstrCount();
1374 
1375     bool isBranch = false;
1376 
1377     // need to output something - set up an element
1378     if ((err = m_out_elem.addElem(pQElem->getRootIndex())))
1379         return err;
1380 
1381     instr_range_t addr_range;
1382     addr_range.st_addr = addr_range.en_addr = m_instr_info.instr_addr;
1383     addr_range.num_instr = 0;
1384 
1385     // walk iCount instructions
1386     for (int i = 0; i < iCount; i++)
1387     {
1388         uint32_t opcode;
1389         uint32_t bytesReq = 4;
1390 
1391         err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1392         if (err != OCSD_OK) break;
1393 
1394         if (bytesReq == 4) // got data back
1395         {
1396             m_instr_info.opcode = opcode;
1397             err = instrDecode(&m_instr_info);
1398             if (err != OCSD_OK) break;
1399 
1400             // increment address - may be adjusted by direct branch value later
1401             m_instr_info.instr_addr += m_instr_info.instr_size;
1402             addr_range.num_instr++;
1403 
1404             isBranch = (m_instr_info.type == OCSD_INSTR_BR) ||
1405                 (m_instr_info.type == OCSD_INSTR_BR_INDIRECT);
1406 
1407             // on a branch no way of knowing if taken - bail out
1408             if (isBranch)
1409                 break;
1410         }
1411         else
1412             break;  // missing memory
1413 
1414     }
1415 
1416     if (err == OCSD_OK)
1417     {
1418         bool inCompleteRange = true;
1419         if (iCount && (addr_range.num_instr == (unsigned)iCount))
1420         {
1421             if ((m_instr_info.instr_addr == QAddr.val) ||    // complete range
1422                 (isBranch)) // or ends on branch - only way we know if branch taken.
1423             {
1424                 // output a range and continue
1425                 inCompleteRange = false;
1426                 // update the range decoded address in the output packet.
1427                 addr_range.en_addr = m_instr_info.instr_addr;
1428                 setElemTraceRange(outElem(), addr_range, true, pQElem->getRootIndex());
1429             }
1430         }
1431 
1432         if (inCompleteRange)
1433         {
1434             // unknown instructions executed.
1435             addr_range.en_addr = QAddr.val;
1436             addr_range.num_instr = iCount;
1437 
1438             outElem().setType(OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH);
1439             outElem().setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
1440             outElem().setISA(calcISA(m_is_64bit, QAddr.isa));
1441         }
1442 
1443         // after the Q element, tracing resumes at the address supplied
1444         SetInstrInfoInAddrISA(QAddr.val, QAddr.isa);
1445         m_need_addr = false;
1446     }
1447     else
1448     {
1449         // output error and halt decode.
1450         LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Error processing Q packet"));
1451     }
1452     m_P0_stack.delete_popped();
1453     return err;
1454 }
1455 
1456 void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa)
1457 {
1458     m_instr_info.instr_addr = addr_val;
1459     m_instr_info.isa = calcISA(m_is_64bit, isa);
1460 }
1461 
1462 // trace an instruction range to a waypoint - and set next address to restart from.
1463 ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WPRes, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/)
1464 {
1465     uint32_t opcode;
1466     uint32_t bytesReq;
1467     ocsd_err_t err = OCSD_OK;
1468 
1469     range.st_addr = range.en_addr = m_instr_info.instr_addr;
1470     range.num_instr = 0;
1471 
1472     WPRes = WP_NOT_FOUND;
1473 
1474     while(WPRes == WP_NOT_FOUND)
1475     {
1476         // start off by reading next opcode;
1477         bytesReq = 4;
1478         err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode);
1479         if(err != OCSD_OK) break;
1480 
1481         if(bytesReq == 4) // got data back
1482         {
1483             m_instr_info.opcode = opcode;
1484             err = instrDecode(&m_instr_info);
1485             if(err != OCSD_OK) break;
1486 
1487             // increment address - may be adjusted by direct branch value later
1488             m_instr_info.instr_addr += m_instr_info.instr_size;
1489             range.num_instr++;
1490 
1491             // either walking to match the next instruction address or a real watchpoint
1492             if (traceToAddrNext)
1493             {
1494                 if (m_instr_info.instr_addr == nextAddrMatch)
1495                     WPRes = WP_FOUND;
1496             }
1497             else if (m_instr_info.type != OCSD_INSTR_OTHER)
1498                 WPRes = WP_FOUND;
1499         }
1500         else
1501         {
1502             // not enough memory accessible.
1503             WPRes = WP_NACC;
1504         }
1505     }
1506     // update the range decoded address in the output packet.
1507     range.en_addr = m_instr_info.instr_addr;
1508     return err;
1509 }
1510 
1511 void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem)
1512 {
1513     etmv4_context_t ctxt = pCtxtElem->getContext();
1514 
1515     elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
1516 
1517     // map to output element and local saved state.
1518     m_is_64bit = (ctxt.SF != 0);
1519     elem.context.bits64 = ctxt.SF;
1520     m_is_secure = (ctxt.NS == 0);
1521     elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure;
1522     elem.context.exception_level = (ocsd_ex_level)ctxt.EL;
1523     elem.context.el_valid = 1;
1524     if(ctxt.updated_c)
1525     {
1526         elem.context.ctxt_id_valid = 1;
1527         m_context_id = elem.context.context_id = ctxt.ctxtID;
1528     }
1529     if(ctxt.updated_v)
1530     {
1531         elem.context.vmid_valid = 1;
1532         m_vmid_id = elem.context.vmid = ctxt.VMID;
1533     }
1534 
1535     // need to update ISA in case context follows address.
1536     elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS());
1537     m_need_ctxt = false;
1538 }
1539 
1540 ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason)
1541 {
1542     ocsd_err_t err = OCSD_OK;
1543 
1544     if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
1545     {
1546         // error out - stop decoding
1547         err = OCSD_ERR_BAD_DECODE_PKT;
1548         LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,reason));
1549     }
1550     else
1551     {
1552         LogError(ocsdError(OCSD_ERR_SEV_WARN, OCSD_ERR_BAD_DECODE_PKT, reason));
1553         // switch to unsync - clear decode state
1554         resetDecoder();
1555         m_curr_state = NO_SYNC;
1556         m_unsync_eot_info = UNSYNC_BAD_PACKET;
1557     }
1558     return err;
1559 }
1560 
1561 inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace()
1562 {
1563     static ocsd_mem_space_acc_t SMemSpace[] = {
1564         OCSD_MEM_SPACE_EL1S,
1565         OCSD_MEM_SPACE_EL1S,
1566         OCSD_MEM_SPACE_EL2S,
1567         OCSD_MEM_SPACE_EL3
1568     };
1569 
1570     static ocsd_mem_space_acc_t NSMemSpace[] = {
1571         OCSD_MEM_SPACE_EL1N,
1572         OCSD_MEM_SPACE_EL1N,
1573         OCSD_MEM_SPACE_EL2,
1574         OCSD_MEM_SPACE_EL3
1575     };
1576 
1577     /* if no valid EL value - just use S/NS */
1578     if (!outElem().context.el_valid)
1579         return  m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N;
1580 
1581     /* mem space according to EL + S/NS */
1582     int el = (int)(outElem().context.exception_level) & 0x3;
1583     return m_is_secure ? SMemSpace[el] : NSMemSpace[el];
1584 }
1585 /* End of File trc_pkt_decode_etmv4i.cpp */
1586