xref: /freebsd-src/contrib/opencsd/decoder/source/trc_ret_stack.cpp (revision c120c5646da1a1d2c4d90fd069a7e2a8d559eb46)
1*c120c564SAndrew Turner /*
2*c120c564SAndrew Turner * \file       trc_ret_stack.cpp
3*c120c564SAndrew Turner * \brief      OpenCSD : trace decoder return stack feature.
4*c120c564SAndrew Turner *
5*c120c564SAndrew Turner * \copyright  Copyright (c) 2017, ARM Limited. All Rights Reserved.
6*c120c564SAndrew Turner */
7*c120c564SAndrew Turner 
8*c120c564SAndrew Turner /*
9*c120c564SAndrew Turner * Redistribution and use in source and binary forms, with or without modification,
10*c120c564SAndrew Turner * are permitted provided that the following conditions are met:
11*c120c564SAndrew Turner *
12*c120c564SAndrew Turner * 1. Redistributions of source code must retain the above copyright notice,
13*c120c564SAndrew Turner * this list of conditions and the following disclaimer.
14*c120c564SAndrew Turner *
15*c120c564SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright notice,
16*c120c564SAndrew Turner * this list of conditions and the following disclaimer in the documentation
17*c120c564SAndrew Turner * and/or other materials provided with the distribution.
18*c120c564SAndrew Turner *
19*c120c564SAndrew Turner * 3. Neither the name of the copyright holder nor the names of its contributors
20*c120c564SAndrew Turner * may be used to endorse or promote products derived from this software without
21*c120c564SAndrew Turner * specific prior written permission.
22*c120c564SAndrew Turner *
23*c120c564SAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24*c120c564SAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25*c120c564SAndrew Turner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26*c120c564SAndrew Turner * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27*c120c564SAndrew Turner * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28*c120c564SAndrew Turner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29*c120c564SAndrew Turner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30*c120c564SAndrew Turner * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31*c120c564SAndrew Turner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32*c120c564SAndrew Turner * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*c120c564SAndrew Turner */
34*c120c564SAndrew Turner #include "common/trc_ret_stack.h"
35*c120c564SAndrew Turner 
36*c120c564SAndrew Turner #ifdef TRC_RET_STACK_DEBUG
37*c120c564SAndrew Turner #include <sstream>
38*c120c564SAndrew Turner #include <iostream>
39*c120c564SAndrew Turner #include "common/trc_component.h"
40*c120c564SAndrew Turner 
41*c120c564SAndrew Turner #define LOG_POP(A,O,I) LogOp("Pop",A,O,I)
42*c120c564SAndrew Turner #define LOG_PUSH(A,O,I) LogOp("Push",A,O,I)
43*c120c564SAndrew Turner #define LOG_FLUSH() LogOp("Flush",0,-1000,(const ocsd_isa)0)
44*c120c564SAndrew Turner 
45*c120c564SAndrew Turner // uncomment for forced std::cout log, bypassing normal library debug logger.
46*c120c564SAndrew Turner // useful perhaps when perf is decoding w/o printing.
47*c120c564SAndrew Turner // #define FORCE_STD_COUT
48*c120c564SAndrew Turner 
49*c120c564SAndrew Turner #else
50*c120c564SAndrew Turner #define LOG_POP(A,O,I)
51*c120c564SAndrew Turner #define LOG_PUSH(A,O,I)
52*c120c564SAndrew Turner #define LOG_FLUSH()
53*c120c564SAndrew Turner #endif
54*c120c564SAndrew Turner 
TrcAddrReturnStack()55*c120c564SAndrew Turner TrcAddrReturnStack::TrcAddrReturnStack() :
56*c120c564SAndrew Turner     m_active(false),
57*c120c564SAndrew Turner     m_pop_pending(false),
58*c120c564SAndrew Turner     head_idx(0),
59*c120c564SAndrew Turner     num_entries(0)
60*c120c564SAndrew Turner {
61*c120c564SAndrew Turner #ifdef TRC_RET_STACK_DEBUG
62*c120c564SAndrew Turner     m_p_debug_logger = 0;
63*c120c564SAndrew Turner #endif
64*c120c564SAndrew Turner }
65*c120c564SAndrew Turner 
push(const ocsd_vaddr_t addr,const ocsd_isa isa)66*c120c564SAndrew Turner void TrcAddrReturnStack::push(const ocsd_vaddr_t addr, const ocsd_isa isa)
67*c120c564SAndrew Turner {
68*c120c564SAndrew Turner     if (is_active())
69*c120c564SAndrew Turner     {
70*c120c564SAndrew Turner         head_idx++;
71*c120c564SAndrew Turner         head_idx &= 0xF;
72*c120c564SAndrew Turner         m_stack[head_idx].ret_addr = addr;
73*c120c564SAndrew Turner         m_stack[head_idx].ret_isa = isa;
74*c120c564SAndrew Turner         num_entries++;
75*c120c564SAndrew Turner         if (num_entries > 16)
76*c120c564SAndrew Turner             num_entries = 16;
77*c120c564SAndrew Turner         LOG_PUSH(addr,0,isa);
78*c120c564SAndrew Turner         m_pop_pending = false;
79*c120c564SAndrew Turner     }
80*c120c564SAndrew Turner }
81*c120c564SAndrew Turner 
pop(ocsd_isa & isa)82*c120c564SAndrew Turner ocsd_vaddr_t TrcAddrReturnStack::pop(ocsd_isa &isa)
83*c120c564SAndrew Turner {
84*c120c564SAndrew Turner     ocsd_vaddr_t addr = (ocsd_vaddr_t)-1;
85*c120c564SAndrew Turner     if (is_active())
86*c120c564SAndrew Turner     {
87*c120c564SAndrew Turner         if (num_entries > 0)
88*c120c564SAndrew Turner         {
89*c120c564SAndrew Turner             addr = m_stack[head_idx].ret_addr;
90*c120c564SAndrew Turner             isa = m_stack[head_idx].ret_isa;
91*c120c564SAndrew Turner             head_idx--;
92*c120c564SAndrew Turner             head_idx &= 0xF;
93*c120c564SAndrew Turner         }
94*c120c564SAndrew Turner         num_entries--;
95*c120c564SAndrew Turner         LOG_POP(addr,1,isa);
96*c120c564SAndrew Turner         m_pop_pending = false;
97*c120c564SAndrew Turner     }
98*c120c564SAndrew Turner     return addr;
99*c120c564SAndrew Turner }
100*c120c564SAndrew Turner 
101*c120c564SAndrew Turner 
flush()102*c120c564SAndrew Turner void  TrcAddrReturnStack::flush()
103*c120c564SAndrew Turner {
104*c120c564SAndrew Turner     num_entries = 0;
105*c120c564SAndrew Turner     m_pop_pending = false;
106*c120c564SAndrew Turner     LOG_FLUSH();
107*c120c564SAndrew Turner }
108*c120c564SAndrew Turner 
109*c120c564SAndrew Turner #ifdef TRC_RET_STACK_DEBUG
LogOp(const char * pszOpString,ocsd_vaddr_t addr,int head_off,ocsd_isa isa)110*c120c564SAndrew Turner void TrcAddrReturnStack::LogOp(const char * pszOpString, ocsd_vaddr_t addr, int head_off, ocsd_isa isa)
111*c120c564SAndrew Turner {
112*c120c564SAndrew Turner     static const char *isa_names[] =
113*c120c564SAndrew Turner     {
114*c120c564SAndrew Turner         "A32",      /**< V7 ARM 32, V8 AArch32 */
115*c120c564SAndrew Turner         "T32",      /**< Thumb2 -> 16/32 bit instructions */
116*c120c564SAndrew Turner         "A64",      /**< V8 AArch64 */
117*c120c564SAndrew Turner         "TEE",      /**< Thumb EE - unsupported */
118*c120c564SAndrew Turner         "JZL",      /**< Jazelle - unsupported in trace */
119*c120c564SAndrew Turner         "custom",       /**< Instruction set - custom arch decoder */
120*c120c564SAndrew Turner         "unknown"       /**< ISA not yet known */
121*c120c564SAndrew Turner     };
122*c120c564SAndrew Turner 
123*c120c564SAndrew Turner     if (m_p_debug_logger)
124*c120c564SAndrew Turner     {
125*c120c564SAndrew Turner         std::ostringstream oss;
126*c120c564SAndrew Turner         if(head_off == -1000)
127*c120c564SAndrew Turner         {
128*c120c564SAndrew Turner             oss << "Return stack " << pszOpString << "\n";
129*c120c564SAndrew Turner         }
130*c120c564SAndrew Turner         else
131*c120c564SAndrew Turner         {
132*c120c564SAndrew Turner             int name_idx = (int)isa;
133*c120c564SAndrew Turner             if (name_idx > 6)
134*c120c564SAndrew Turner                 name_idx = 6;
135*c120c564SAndrew Turner             oss << "Return stack " << pszOpString << "[" << std::dec << (head_idx+head_off) << "](0x" << std::hex << addr << "), " << isa_names[name_idx] << ";";
136*c120c564SAndrew Turner             oss << "current entries = " << std::dec << num_entries << ";";
137*c120c564SAndrew Turner             oss << "new head idx = " << head_idx << ";";
138*c120c564SAndrew Turner             oss << "pop pend (pre op) = " << (m_pop_pending ? "true\n" : "false\n");
139*c120c564SAndrew Turner         }
140*c120c564SAndrew Turner #ifdef FORCE_STD_COUT
141*c120c564SAndrew Turner         std::cout << oss.str();
142*c120c564SAndrew Turner         std::cout.flush();
143*c120c564SAndrew Turner #endif
144*c120c564SAndrew Turner         m_p_debug_logger->LogDefMessage(oss.str());
145*c120c564SAndrew Turner     }
146*c120c564SAndrew Turner }
147*c120c564SAndrew Turner #endif
148*c120c564SAndrew Turner 
149*c120c564SAndrew Turner /* End of File trc_ret_stack.cpp */
150