1*c120c564SAndrew Turner /*
2*c120c564SAndrew Turner * \file ocsd_code_follower.h
3*c120c564SAndrew Turner * \brief OpenCSD : Code follower for instruction trace decode
4*c120c564SAndrew Turner *
5*c120c564SAndrew Turner * \copyright Copyright (c) 2016, 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
35*c120c564SAndrew Turner #ifndef ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
36*c120c564SAndrew Turner #define ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
37*c120c564SAndrew Turner
38*c120c564SAndrew Turner #include "opencsd/ocsd_if_types.h"
39*c120c564SAndrew Turner #include "opencsd/trc_pkt_types.h"
40*c120c564SAndrew Turner #include "comp_attach_pt_t.h"
41*c120c564SAndrew Turner #include "interfaces/trc_tgt_mem_access_i.h"
42*c120c564SAndrew Turner #include "interfaces/trc_instr_decode_i.h"
43*c120c564SAndrew Turner
44*c120c564SAndrew Turner /*!
45*c120c564SAndrew Turner * @class OcsdCodeFollower
46*c120c564SAndrew Turner * @brief The code follower looks for waypoints or addresses.
47*c120c564SAndrew Turner *
48*c120c564SAndrew Turner * Code follower used to determine the trace ranges for Atom or other waypoint
49*c120c564SAndrew Turner * elements. Uses memory accessor and I decoder to follow the code path.
50*c120c564SAndrew Turner *
51*c120c564SAndrew Turner */
52*c120c564SAndrew Turner class OcsdCodeFollower
53*c120c564SAndrew Turner {
54*c120c564SAndrew Turner public:
55*c120c564SAndrew Turner OcsdCodeFollower();
56*c120c564SAndrew Turner ~OcsdCodeFollower();
57*c120c564SAndrew Turner
58*c120c564SAndrew Turner //*********** setup API
59*c120c564SAndrew Turner void initInterfaces(componentAttachPt<ITargetMemAccess> *pMemAccess, componentAttachPt<IInstrDecode> *pIDecode);
60*c120c564SAndrew Turner
61*c120c564SAndrew Turner // set information for decode operation - static or occasionally changing settings
62*c120c564SAndrew Turner // per decode values are passed as parameters into the decode API calls.
63*c120c564SAndrew Turner void setArchProfile(const ocsd_arch_profile_t profile); //!< core profile
64*c120c564SAndrew Turner void setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule); //!< memory space to use for access (filtered by S/NS, EL etc).
65*c120c564SAndrew Turner void setMemSpaceCSID(const uint8_t csid); //!< memory spaces might be partitioned by CSID
66*c120c564SAndrew Turner void setISA(const ocsd_isa isa); //!< set the ISA for the decode.
67*c120c564SAndrew Turner void setDSBDMBasWP(); //!< DSB and DMB can be treated as WP in some archs.
68*c120c564SAndrew Turner
69*c120c564SAndrew Turner //********** code following API
70*c120c564SAndrew Turner
71*c120c564SAndrew Turner // standard WP search - for program flow trace
72*c120c564SAndrew Turner //ocsd_err_t followToAtomWP(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A);
73*c120c564SAndrew Turner
74*c120c564SAndrew Turner // PTM exception code may require follow to an address
75*c120c564SAndrew Turner //ocsd_err_t followToAddress(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A, const ocsd_vaddr_t addrMatch);
76*c120c564SAndrew Turner
77*c120c564SAndrew Turner // single instruction atom format such as ETMv3
78*c120c564SAndrew Turner ocsd_err_t followSingleAtom(const ocsd_vaddr_t addrStart, const ocsd_atm_val A);
79*c120c564SAndrew Turner
80*c120c564SAndrew Turner // follow N instructions
81*c120c564SAndrew Turner // ocsd_err_t followNInstructions(idec_res_t &op_result) // ETMv4 Q elements
82*c120c564SAndrew Turner
83*c120c564SAndrew Turner //*********************** results API
84*c120c564SAndrew Turner const ocsd_vaddr_t getRangeSt() const; //!< inclusive start address of decoded range (value passed in)
85*c120c564SAndrew Turner const ocsd_vaddr_t getRangeEn() const; //!< exclusive end address of decoded range (first instruction _not_ executed / potential next instruction).
86*c120c564SAndrew Turner const bool hasRange() const; //!< we have a valid range executed (may be false if nacc).
87*c120c564SAndrew Turner
88*c120c564SAndrew Turner const bool hasNextAddr() const; //!< we have calulated the next address - otherwise this is needed from trace packets.
89*c120c564SAndrew Turner const ocsd_vaddr_t getNextAddr() const; //!< next address - valid if hasNextAddr() true.
90*c120c564SAndrew Turner
91*c120c564SAndrew Turner // information on last instruction executed in range.
92*c120c564SAndrew Turner const ocsd_instr_type getInstrType() const; //!< last instruction type
93*c120c564SAndrew Turner const ocsd_instr_subtype getInstrSubType() const; //!< last instruction sub-type
94*c120c564SAndrew Turner const bool isCondInstr() const; //!< is a conditional instruction
95*c120c564SAndrew Turner const bool isLink() const; //!< is a link (branch with link etc)
96*c120c564SAndrew Turner const bool ISAChanged() const; //!< next ISA different from input ISA.
97*c120c564SAndrew Turner const ocsd_isa nextISA() const; //!< ISA for next instruction
98*c120c564SAndrew Turner const uint8_t getInstrSize() const; //!< Get the last instruction size.
99*c120c564SAndrew Turner
100*c120c564SAndrew Turner // information on error conditions
101*c120c564SAndrew Turner const bool isNacc() const; //!< true if Memory Not Accessible (nacc) error occurred
102*c120c564SAndrew Turner void clearNacc(); //!< clear the nacc error flag
103*c120c564SAndrew Turner const ocsd_vaddr_t getNaccAddr() const; //!< get the nacc error address.
104*c120c564SAndrew Turner
105*c120c564SAndrew Turner private:
106*c120c564SAndrew Turner bool initFollowerState(); //!< clear all the o/p data and flags, check init valid.
107*c120c564SAndrew Turner
108*c120c564SAndrew Turner ocsd_err_t decodeSingleOpCode(); //!< decode single opcode address from current m_inst_info packet
109*c120c564SAndrew Turner
110*c120c564SAndrew Turner ocsd_instr_info m_instr_info;
111*c120c564SAndrew Turner
112*c120c564SAndrew Turner ocsd_vaddr_t m_st_range_addr; //!< start of excuted range - inclusive address.
113*c120c564SAndrew Turner ocsd_vaddr_t m_en_range_addr; //!< end of executed range - exclusive address.
114*c120c564SAndrew Turner ocsd_vaddr_t m_next_addr; //!< calcuated next address (could be eo range of branch address, not set for indirect branches)
115*c120c564SAndrew Turner bool m_b_next_valid; //!< true if next address valid, false if need address from trace packets.
116*c120c564SAndrew Turner
117*c120c564SAndrew Turner //! memory space rule to use when accessing memory.
118*c120c564SAndrew Turner ocsd_mem_space_acc_t m_mem_acc_rule;
119*c120c564SAndrew Turner //! memory space csid to use when accessing memory.
120*c120c564SAndrew Turner uint8_t m_mem_space_csid;
121*c120c564SAndrew Turner
122*c120c564SAndrew Turner ocsd_vaddr_t m_nacc_address; //!< memory address that was inaccessible - failed read @ start, or during follow operation
123*c120c564SAndrew Turner bool m_b_nacc_err; //!< memory NACC error - required address was unavailable.
124*c120c564SAndrew Turner
125*c120c564SAndrew Turner //! pointers to the memory access and i decode interfaces.
126*c120c564SAndrew Turner componentAttachPt<ITargetMemAccess> *m_pMemAccess;
127*c120c564SAndrew Turner componentAttachPt<IInstrDecode> *m_pIDecode;
128*c120c564SAndrew Turner
129*c120c564SAndrew Turner };
130*c120c564SAndrew Turner
131*c120c564SAndrew Turner #endif // ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
132*c120c564SAndrew Turner
133*c120c564SAndrew Turner //*********** setup API
setArchProfile(const ocsd_arch_profile_t profile)134*c120c564SAndrew Turner inline void OcsdCodeFollower::setArchProfile(const ocsd_arch_profile_t profile)
135*c120c564SAndrew Turner {
136*c120c564SAndrew Turner m_instr_info.pe_type = profile;
137*c120c564SAndrew Turner }
138*c120c564SAndrew Turner
setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule)139*c120c564SAndrew Turner inline void OcsdCodeFollower::setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule)
140*c120c564SAndrew Turner {
141*c120c564SAndrew Turner m_mem_acc_rule = mem_acc_rule;
142*c120c564SAndrew Turner }
143*c120c564SAndrew Turner
setMemSpaceCSID(const uint8_t csid)144*c120c564SAndrew Turner inline void OcsdCodeFollower::setMemSpaceCSID(const uint8_t csid)
145*c120c564SAndrew Turner {
146*c120c564SAndrew Turner m_mem_space_csid = csid;
147*c120c564SAndrew Turner }
148*c120c564SAndrew Turner
setISA(const ocsd_isa isa)149*c120c564SAndrew Turner inline void OcsdCodeFollower::setISA(const ocsd_isa isa)
150*c120c564SAndrew Turner {
151*c120c564SAndrew Turner m_instr_info.isa = isa;
152*c120c564SAndrew Turner }
153*c120c564SAndrew Turner
setDSBDMBasWP()154*c120c564SAndrew Turner inline void OcsdCodeFollower::setDSBDMBasWP()
155*c120c564SAndrew Turner {
156*c120c564SAndrew Turner m_instr_info.dsb_dmb_waypoints = 1;
157*c120c564SAndrew Turner }
158*c120c564SAndrew Turner
159*c120c564SAndrew Turner //**************************************** results API
getRangeSt()160*c120c564SAndrew Turner inline const ocsd_vaddr_t OcsdCodeFollower::getRangeSt() const
161*c120c564SAndrew Turner {
162*c120c564SAndrew Turner return m_st_range_addr;
163*c120c564SAndrew Turner }
164*c120c564SAndrew Turner
getRangeEn()165*c120c564SAndrew Turner inline const ocsd_vaddr_t OcsdCodeFollower::getRangeEn() const
166*c120c564SAndrew Turner {
167*c120c564SAndrew Turner return m_en_range_addr;
168*c120c564SAndrew Turner }
169*c120c564SAndrew Turner
hasRange()170*c120c564SAndrew Turner inline const bool OcsdCodeFollower::hasRange() const
171*c120c564SAndrew Turner {
172*c120c564SAndrew Turner return m_st_range_addr < m_en_range_addr;
173*c120c564SAndrew Turner }
174*c120c564SAndrew Turner
hasNextAddr()175*c120c564SAndrew Turner inline const bool OcsdCodeFollower::hasNextAddr() const
176*c120c564SAndrew Turner {
177*c120c564SAndrew Turner return m_b_next_valid;
178*c120c564SAndrew Turner }
179*c120c564SAndrew Turner
getNextAddr()180*c120c564SAndrew Turner inline const ocsd_vaddr_t OcsdCodeFollower::getNextAddr() const
181*c120c564SAndrew Turner {
182*c120c564SAndrew Turner return m_next_addr;
183*c120c564SAndrew Turner }
184*c120c564SAndrew Turner
185*c120c564SAndrew Turner // information on last instruction executed in range.
getInstrType()186*c120c564SAndrew Turner inline const ocsd_instr_type OcsdCodeFollower::getInstrType() const
187*c120c564SAndrew Turner {
188*c120c564SAndrew Turner return m_instr_info.type;
189*c120c564SAndrew Turner }
190*c120c564SAndrew Turner
getInstrSubType()191*c120c564SAndrew Turner inline const ocsd_instr_subtype OcsdCodeFollower::getInstrSubType() const
192*c120c564SAndrew Turner {
193*c120c564SAndrew Turner return m_instr_info.sub_type;
194*c120c564SAndrew Turner }
195*c120c564SAndrew Turner
getInstrSize()196*c120c564SAndrew Turner inline const uint8_t OcsdCodeFollower::getInstrSize() const
197*c120c564SAndrew Turner {
198*c120c564SAndrew Turner return m_instr_info.instr_size;
199*c120c564SAndrew Turner }
200*c120c564SAndrew Turner
isCondInstr()201*c120c564SAndrew Turner inline const bool OcsdCodeFollower::isCondInstr() const
202*c120c564SAndrew Turner {
203*c120c564SAndrew Turner return (bool)(m_instr_info.is_conditional == 1);
204*c120c564SAndrew Turner }
205*c120c564SAndrew Turner
isLink()206*c120c564SAndrew Turner inline const bool OcsdCodeFollower::isLink() const
207*c120c564SAndrew Turner {
208*c120c564SAndrew Turner return (bool)(m_instr_info.is_link == 1);
209*c120c564SAndrew Turner }
210*c120c564SAndrew Turner
ISAChanged()211*c120c564SAndrew Turner inline const bool OcsdCodeFollower::ISAChanged() const
212*c120c564SAndrew Turner {
213*c120c564SAndrew Turner return (bool)(m_instr_info.isa != m_instr_info.next_isa);
214*c120c564SAndrew Turner }
215*c120c564SAndrew Turner
nextISA()216*c120c564SAndrew Turner inline const ocsd_isa OcsdCodeFollower::nextISA() const
217*c120c564SAndrew Turner {
218*c120c564SAndrew Turner return m_instr_info.next_isa;
219*c120c564SAndrew Turner }
220*c120c564SAndrew Turner
221*c120c564SAndrew Turner // information on error conditions
isNacc()222*c120c564SAndrew Turner inline const bool OcsdCodeFollower::isNacc() const
223*c120c564SAndrew Turner {
224*c120c564SAndrew Turner return m_b_nacc_err;
225*c120c564SAndrew Turner }
226*c120c564SAndrew Turner
clearNacc()227*c120c564SAndrew Turner inline void OcsdCodeFollower::clearNacc()
228*c120c564SAndrew Turner {
229*c120c564SAndrew Turner m_b_nacc_err = false;
230*c120c564SAndrew Turner }
231*c120c564SAndrew Turner
getNaccAddr()232*c120c564SAndrew Turner inline const ocsd_vaddr_t OcsdCodeFollower::getNaccAddr() const
233*c120c564SAndrew Turner {
234*c120c564SAndrew Turner return m_nacc_address;
235*c120c564SAndrew Turner }
236*c120c564SAndrew Turner
237*c120c564SAndrew Turner /* End of File ocsd_code_follower.h */
238