xref: /src/contrib/opencsd/decoder/include/common/ocsd_code_follower.h (revision c120c5646da1a1d2c4d90fd069a7e2a8d559eb46)
1a6157d81SRuslan Bukin /*
2a6157d81SRuslan Bukin  * \file       ocsd_code_follower.h
3a6157d81SRuslan Bukin  * \brief      OpenCSD : Code follower for instruction trace decode
4a6157d81SRuslan Bukin  *
5a6157d81SRuslan Bukin  * \copyright  Copyright (c) 2016, ARM Limited. All Rights Reserved.
6a6157d81SRuslan Bukin  */
7a6157d81SRuslan Bukin 
8a6157d81SRuslan Bukin /*
9a6157d81SRuslan Bukin  * Redistribution and use in source and binary forms, with or without modification,
10a6157d81SRuslan Bukin  * are permitted provided that the following conditions are met:
11a6157d81SRuslan Bukin  *
12a6157d81SRuslan Bukin  * 1. Redistributions of source code must retain the above copyright notice,
13a6157d81SRuslan Bukin  * this list of conditions and the following disclaimer.
14a6157d81SRuslan Bukin  *
15a6157d81SRuslan Bukin  * 2. Redistributions in binary form must reproduce the above copyright notice,
16a6157d81SRuslan Bukin  * this list of conditions and the following disclaimer in the documentation
17a6157d81SRuslan Bukin  * and/or other materials provided with the distribution.
18a6157d81SRuslan Bukin  *
19a6157d81SRuslan Bukin  * 3. Neither the name of the copyright holder nor the names of its contributors
20a6157d81SRuslan Bukin  * may be used to endorse or promote products derived from this software without
21a6157d81SRuslan Bukin  * specific prior written permission.
22a6157d81SRuslan Bukin  *
23a6157d81SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24a6157d81SRuslan Bukin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25a6157d81SRuslan Bukin  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26a6157d81SRuslan Bukin  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27a6157d81SRuslan Bukin  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28a6157d81SRuslan Bukin  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29a6157d81SRuslan Bukin  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30a6157d81SRuslan Bukin  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31a6157d81SRuslan Bukin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32a6157d81SRuslan Bukin  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33a6157d81SRuslan Bukin  */
34a6157d81SRuslan Bukin 
35a6157d81SRuslan Bukin #ifndef ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
36a6157d81SRuslan Bukin #define ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
37a6157d81SRuslan Bukin 
38a6157d81SRuslan Bukin #include "opencsd/ocsd_if_types.h"
39a6157d81SRuslan Bukin #include "opencsd/trc_pkt_types.h"
40a6157d81SRuslan Bukin #include "comp_attach_pt_t.h"
41a6157d81SRuslan Bukin #include "interfaces/trc_tgt_mem_access_i.h"
42a6157d81SRuslan Bukin #include "interfaces/trc_instr_decode_i.h"
43a6157d81SRuslan Bukin 
44a6157d81SRuslan Bukin /*!
45a6157d81SRuslan Bukin  * @class OcsdCodeFollower
46a6157d81SRuslan Bukin  * @brief The code follower looks for waypoints or addresses.
47a6157d81SRuslan Bukin  *
48a6157d81SRuslan Bukin  *  Code follower used to determine the trace ranges for Atom or other waypoint
49a6157d81SRuslan Bukin  *  elements. Uses memory accessor and I decoder to follow the code path.
50a6157d81SRuslan Bukin  *
51a6157d81SRuslan Bukin  */
52a6157d81SRuslan Bukin class OcsdCodeFollower
53a6157d81SRuslan Bukin {
54a6157d81SRuslan Bukin public:
55a6157d81SRuslan Bukin     OcsdCodeFollower();
56a6157d81SRuslan Bukin     ~OcsdCodeFollower();
57a6157d81SRuslan Bukin 
58a6157d81SRuslan Bukin //*********** setup API
59a6157d81SRuslan Bukin     void initInterfaces(componentAttachPt<ITargetMemAccess> *pMemAccess, componentAttachPt<IInstrDecode> *pIDecode);
60a6157d81SRuslan Bukin 
61a6157d81SRuslan Bukin // set information for decode operation - static or occasionally changing settings
62a6157d81SRuslan Bukin // per decode values are passed as parameters into the decode API calls.
63a6157d81SRuslan Bukin     void setArchProfile(const ocsd_arch_profile_t profile);             //!< core profile
64a6157d81SRuslan Bukin     void setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule);    //!< memory space to use for access (filtered by S/NS, EL etc).
65a6157d81SRuslan Bukin     void setMemSpaceCSID(const uint8_t csid);                           //!< memory spaces might be partitioned by CSID
66a6157d81SRuslan Bukin     void setISA(const ocsd_isa isa);    //!< set the ISA for the decode.
67a6157d81SRuslan Bukin     void setDSBDMBasWP();   //!< DSB and DMB can be treated as WP in some archs.
68a6157d81SRuslan Bukin 
69a6157d81SRuslan Bukin //********** code following API
70a6157d81SRuslan Bukin 
71a6157d81SRuslan Bukin     // standard WP search - for program flow trace
72a6157d81SRuslan Bukin     //ocsd_err_t followToAtomWP(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A);
73a6157d81SRuslan Bukin 
74a6157d81SRuslan Bukin     // PTM exception code may require follow to an address
75a6157d81SRuslan Bukin     //ocsd_err_t followToAddress(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A, const ocsd_vaddr_t addrMatch);
76a6157d81SRuslan Bukin 
77a6157d81SRuslan Bukin     // single instruction atom format such as ETMv3
78a6157d81SRuslan Bukin     ocsd_err_t followSingleAtom(const ocsd_vaddr_t addrStart, const ocsd_atm_val A);
79a6157d81SRuslan Bukin 
80a6157d81SRuslan Bukin     // follow N instructions
81a6157d81SRuslan Bukin     // ocsd_err_t followNInstructions(idec_res_t &op_result) // ETMv4 Q elements
82a6157d81SRuslan Bukin 
83a6157d81SRuslan Bukin //*********************** results API
84a6157d81SRuslan Bukin     const ocsd_vaddr_t getRangeSt() const;  //!< inclusive start address of decoded range (value passed in)
85a6157d81SRuslan Bukin     const ocsd_vaddr_t getRangeEn() const;  //!< exclusive end address of decoded range (first instruction _not_ executed / potential next instruction).
86a6157d81SRuslan Bukin     const bool hasRange() const;            //!< we have a valid range executed (may be false if nacc).
87a6157d81SRuslan Bukin 
88a6157d81SRuslan Bukin     const bool hasNextAddr() const;         //!< we have calulated the next address - otherwise this is needed from trace packets.
89a6157d81SRuslan Bukin     const ocsd_vaddr_t getNextAddr() const; //!< next address - valid if hasNextAddr() true.
90a6157d81SRuslan Bukin 
91a6157d81SRuslan Bukin     // information on last instruction executed in range.
92a6157d81SRuslan Bukin     const ocsd_instr_type getInstrType() const;         //!< last instruction type
93a6157d81SRuslan Bukin     const ocsd_instr_subtype getInstrSubType() const;   //!< last instruction sub-type
94a6157d81SRuslan Bukin     const bool isCondInstr() const;                     //!< is a conditional instruction
95a6157d81SRuslan Bukin     const bool isLink() const;                          //!< is a link (branch with link etc)
96a6157d81SRuslan Bukin     const bool ISAChanged() const;                      //!< next ISA different from input ISA.
97a6157d81SRuslan Bukin     const ocsd_isa nextISA() const;                     //!< ISA for next instruction
98cf98ba14SRuslan Bukin     const uint8_t getInstrSize() const;                 //!< Get the last instruction size.
99a6157d81SRuslan Bukin 
100a6157d81SRuslan Bukin     // information on error conditions
101a6157d81SRuslan Bukin     const bool isNacc() const;                  //!< true if Memory Not Accessible (nacc) error occurred
102a6157d81SRuslan Bukin     void clearNacc();                           //!< clear the nacc error flag
103a6157d81SRuslan Bukin     const ocsd_vaddr_t getNaccAddr() const;     //!< get the nacc error address.
104a6157d81SRuslan Bukin 
105a6157d81SRuslan Bukin private:
106a6157d81SRuslan Bukin     bool initFollowerState();       //!< clear all the o/p data and flags, check init valid.
107a6157d81SRuslan Bukin 
108a6157d81SRuslan Bukin     ocsd_err_t decodeSingleOpCode();      //!< decode single opcode address from current m_inst_info packet
109a6157d81SRuslan Bukin 
110a6157d81SRuslan Bukin     ocsd_instr_info m_instr_info;
111a6157d81SRuslan Bukin 
112a6157d81SRuslan Bukin     ocsd_vaddr_t m_st_range_addr;   //!< start of excuted range - inclusive address.
113a6157d81SRuslan Bukin     ocsd_vaddr_t m_en_range_addr;   //!< end of executed range - exclusive address.
114a6157d81SRuslan Bukin     ocsd_vaddr_t m_next_addr;       //!< calcuated next address (could be eo range of branch address, not set for indirect branches)
115a6157d81SRuslan Bukin     bool m_b_next_valid;            //!< true if next address valid, false if need address from trace packets.
116a6157d81SRuslan Bukin 
117a6157d81SRuslan Bukin     //! memory space rule to use when accessing memory.
118a6157d81SRuslan Bukin     ocsd_mem_space_acc_t m_mem_acc_rule;
119a6157d81SRuslan Bukin     //! memory space csid to use when accessing memory.
120a6157d81SRuslan Bukin     uint8_t              m_mem_space_csid;
121a6157d81SRuslan Bukin 
122a6157d81SRuslan Bukin     ocsd_vaddr_t m_nacc_address;    //!< memory address that was inaccessible - failed read @ start, or during follow operation
123a6157d81SRuslan Bukin     bool m_b_nacc_err;              //!< memory NACC error - required address was unavailable.
124a6157d81SRuslan Bukin 
125a6157d81SRuslan Bukin     //! pointers to the memory access and i decode interfaces.
126a6157d81SRuslan Bukin     componentAttachPt<ITargetMemAccess> *m_pMemAccess;
127a6157d81SRuslan Bukin     componentAttachPt<IInstrDecode> *m_pIDecode;
128a6157d81SRuslan Bukin 
129a6157d81SRuslan Bukin };
130a6157d81SRuslan Bukin 
131a6157d81SRuslan Bukin #endif // ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
132a6157d81SRuslan Bukin 
133a6157d81SRuslan Bukin //*********** setup API
setArchProfile(const ocsd_arch_profile_t profile)134a6157d81SRuslan Bukin inline void OcsdCodeFollower::setArchProfile(const ocsd_arch_profile_t profile)
135a6157d81SRuslan Bukin {
136a6157d81SRuslan Bukin     m_instr_info.pe_type = profile;
137a6157d81SRuslan Bukin }
138a6157d81SRuslan Bukin 
setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule)139a6157d81SRuslan Bukin inline void OcsdCodeFollower::setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule)
140a6157d81SRuslan Bukin {
141a6157d81SRuslan Bukin     m_mem_acc_rule = mem_acc_rule;
142a6157d81SRuslan Bukin }
143a6157d81SRuslan Bukin 
setMemSpaceCSID(const uint8_t csid)144a6157d81SRuslan Bukin inline void  OcsdCodeFollower::setMemSpaceCSID(const uint8_t csid)
145a6157d81SRuslan Bukin {
146a6157d81SRuslan Bukin     m_mem_space_csid = csid;
147a6157d81SRuslan Bukin }
148a6157d81SRuslan Bukin 
setISA(const ocsd_isa isa)149a6157d81SRuslan Bukin inline void OcsdCodeFollower::setISA(const ocsd_isa isa)
150a6157d81SRuslan Bukin {
151a6157d81SRuslan Bukin     m_instr_info.isa = isa;
152a6157d81SRuslan Bukin }
153a6157d81SRuslan Bukin 
setDSBDMBasWP()154a6157d81SRuslan Bukin inline void OcsdCodeFollower::setDSBDMBasWP()
155a6157d81SRuslan Bukin {
156a6157d81SRuslan Bukin     m_instr_info.dsb_dmb_waypoints = 1;
157a6157d81SRuslan Bukin }
158a6157d81SRuslan Bukin 
159a6157d81SRuslan Bukin //**************************************** results API
getRangeSt()160a6157d81SRuslan Bukin inline const ocsd_vaddr_t OcsdCodeFollower::getRangeSt() const
161a6157d81SRuslan Bukin {
162a6157d81SRuslan Bukin     return m_st_range_addr;
163a6157d81SRuslan Bukin }
164a6157d81SRuslan Bukin 
getRangeEn()165a6157d81SRuslan Bukin inline const ocsd_vaddr_t OcsdCodeFollower::getRangeEn() const
166a6157d81SRuslan Bukin {
167a6157d81SRuslan Bukin     return m_en_range_addr;
168a6157d81SRuslan Bukin }
169a6157d81SRuslan Bukin 
hasRange()170a6157d81SRuslan Bukin inline const bool OcsdCodeFollower::hasRange() const
171a6157d81SRuslan Bukin {
172a6157d81SRuslan Bukin     return m_st_range_addr < m_en_range_addr;
173a6157d81SRuslan Bukin }
174a6157d81SRuslan Bukin 
hasNextAddr()175a6157d81SRuslan Bukin inline const bool OcsdCodeFollower::hasNextAddr() const
176a6157d81SRuslan Bukin {
177a6157d81SRuslan Bukin     return m_b_next_valid;
178a6157d81SRuslan Bukin }
179a6157d81SRuslan Bukin 
getNextAddr()180a6157d81SRuslan Bukin inline const ocsd_vaddr_t OcsdCodeFollower::getNextAddr() const
181a6157d81SRuslan Bukin {
182a6157d81SRuslan Bukin     return m_next_addr;
183a6157d81SRuslan Bukin }
184a6157d81SRuslan Bukin 
185a6157d81SRuslan Bukin // information on last instruction executed in range.
getInstrType()186a6157d81SRuslan Bukin inline const ocsd_instr_type OcsdCodeFollower::getInstrType() const
187a6157d81SRuslan Bukin {
188a6157d81SRuslan Bukin     return m_instr_info.type;
189a6157d81SRuslan Bukin }
190a6157d81SRuslan Bukin 
getInstrSubType()191a6157d81SRuslan Bukin inline const ocsd_instr_subtype OcsdCodeFollower::getInstrSubType() const
192a6157d81SRuslan Bukin {
193a6157d81SRuslan Bukin     return m_instr_info.sub_type;
194a6157d81SRuslan Bukin }
195a6157d81SRuslan Bukin 
getInstrSize()196cf98ba14SRuslan Bukin inline const uint8_t  OcsdCodeFollower::getInstrSize() const
197cf98ba14SRuslan Bukin {
198cf98ba14SRuslan Bukin     return m_instr_info.instr_size;
199cf98ba14SRuslan Bukin }
200cf98ba14SRuslan Bukin 
isCondInstr()201a6157d81SRuslan Bukin inline const bool OcsdCodeFollower::isCondInstr() const
202a6157d81SRuslan Bukin {
203a6157d81SRuslan Bukin     return (bool)(m_instr_info.is_conditional == 1);
204a6157d81SRuslan Bukin }
205a6157d81SRuslan Bukin 
isLink()206a6157d81SRuslan Bukin inline const bool OcsdCodeFollower::isLink() const
207a6157d81SRuslan Bukin {
208a6157d81SRuslan Bukin     return (bool)(m_instr_info.is_link == 1);
209a6157d81SRuslan Bukin }
210a6157d81SRuslan Bukin 
ISAChanged()211a6157d81SRuslan Bukin inline const bool OcsdCodeFollower::ISAChanged() const
212a6157d81SRuslan Bukin {
213a6157d81SRuslan Bukin     return (bool)(m_instr_info.isa != m_instr_info.next_isa);
214a6157d81SRuslan Bukin }
215a6157d81SRuslan Bukin 
nextISA()216a6157d81SRuslan Bukin inline const ocsd_isa OcsdCodeFollower::nextISA() const
217a6157d81SRuslan Bukin {
218a6157d81SRuslan Bukin     return m_instr_info.next_isa;
219a6157d81SRuslan Bukin }
220a6157d81SRuslan Bukin 
221a6157d81SRuslan Bukin // information on error conditions
isNacc()222a6157d81SRuslan Bukin inline const bool OcsdCodeFollower::isNacc() const
223a6157d81SRuslan Bukin {
224a6157d81SRuslan Bukin     return m_b_nacc_err;
225a6157d81SRuslan Bukin }
226a6157d81SRuslan Bukin 
clearNacc()227a6157d81SRuslan Bukin inline void OcsdCodeFollower::clearNacc()
228a6157d81SRuslan Bukin {
229a6157d81SRuslan Bukin     m_b_nacc_err = false;
230a6157d81SRuslan Bukin }
231a6157d81SRuslan Bukin 
getNaccAddr()232a6157d81SRuslan Bukin inline const ocsd_vaddr_t OcsdCodeFollower::getNaccAddr() const
233a6157d81SRuslan Bukin {
234a6157d81SRuslan Bukin     return m_nacc_address;
235a6157d81SRuslan Bukin }
236a6157d81SRuslan Bukin 
237a6157d81SRuslan Bukin /* End of File ocsd_code_follower.h */
238