xref: /aosp_15_r20/external/OpenCSD/decoder/source/ocsd_code_follower.cpp (revision 02ca8ccacfba7e0df68f3332a95f3180334d6649)
1*02ca8ccaSAndroid Build Coastguard Worker /*
2*02ca8ccaSAndroid Build Coastguard Worker  * \file       ocsd_code_follower.cpp
3*02ca8ccaSAndroid Build Coastguard Worker  * \brief      OpenCSD : Instruction Code path follower.
4*02ca8ccaSAndroid Build Coastguard Worker  *
5*02ca8ccaSAndroid Build Coastguard Worker  * \copyright  Copyright (c) 2016, ARM Limited. All Rights Reserved.
6*02ca8ccaSAndroid Build Coastguard Worker  */
7*02ca8ccaSAndroid Build Coastguard Worker 
8*02ca8ccaSAndroid Build Coastguard Worker 
9*02ca8ccaSAndroid Build Coastguard Worker /*
10*02ca8ccaSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without modification,
11*02ca8ccaSAndroid Build Coastguard Worker  * are permitted provided that the following conditions are met:
12*02ca8ccaSAndroid Build Coastguard Worker  *
13*02ca8ccaSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright notice,
14*02ca8ccaSAndroid Build Coastguard Worker  * this list of conditions and the following disclaimer.
15*02ca8ccaSAndroid Build Coastguard Worker  *
16*02ca8ccaSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright notice,
17*02ca8ccaSAndroid Build Coastguard Worker  * this list of conditions and the following disclaimer in the documentation
18*02ca8ccaSAndroid Build Coastguard Worker  * and/or other materials provided with the distribution.
19*02ca8ccaSAndroid Build Coastguard Worker  *
20*02ca8ccaSAndroid Build Coastguard Worker  * 3. Neither the name of the copyright holder nor the names of its contributors
21*02ca8ccaSAndroid Build Coastguard Worker  * may be used to endorse or promote products derived from this software without
22*02ca8ccaSAndroid Build Coastguard Worker  * specific prior written permission.
23*02ca8ccaSAndroid Build Coastguard Worker  *
24*02ca8ccaSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
25*02ca8ccaSAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26*02ca8ccaSAndroid Build Coastguard Worker  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27*02ca8ccaSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28*02ca8ccaSAndroid Build Coastguard Worker  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*02ca8ccaSAndroid Build Coastguard Worker  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*02ca8ccaSAndroid Build Coastguard Worker  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31*02ca8ccaSAndroid Build Coastguard Worker  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*02ca8ccaSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*02ca8ccaSAndroid Build Coastguard Worker  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*02ca8ccaSAndroid Build Coastguard Worker  */
35*02ca8ccaSAndroid Build Coastguard Worker 
36*02ca8ccaSAndroid Build Coastguard Worker #include "common/ocsd_code_follower.h"
37*02ca8ccaSAndroid Build Coastguard Worker 
OcsdCodeFollower()38*02ca8ccaSAndroid Build Coastguard Worker OcsdCodeFollower::OcsdCodeFollower()
39*02ca8ccaSAndroid Build Coastguard Worker {
40*02ca8ccaSAndroid Build Coastguard Worker     m_instr_info.pe_type.arch = ARCH_UNKNOWN;
41*02ca8ccaSAndroid Build Coastguard Worker     m_instr_info.pe_type.profile = profile_Unknown;
42*02ca8ccaSAndroid Build Coastguard Worker     m_instr_info.isa = ocsd_isa_unknown;
43*02ca8ccaSAndroid Build Coastguard Worker     m_instr_info.dsb_dmb_waypoints = 0;
44*02ca8ccaSAndroid Build Coastguard Worker     m_instr_info.wfi_wfe_branch = 0;
45*02ca8ccaSAndroid Build Coastguard Worker     m_instr_info.instr_addr = 0;
46*02ca8ccaSAndroid Build Coastguard Worker     m_instr_info.opcode = 0;
47*02ca8ccaSAndroid Build Coastguard Worker     m_pMemAccess = 0;
48*02ca8ccaSAndroid Build Coastguard Worker     m_pIDecode = 0;
49*02ca8ccaSAndroid Build Coastguard Worker     m_mem_space_csid = 0;
50*02ca8ccaSAndroid Build Coastguard Worker     m_st_range_addr =  m_en_range_addr = m_next_addr = 0;
51*02ca8ccaSAndroid Build Coastguard Worker     m_b_next_valid = false;
52*02ca8ccaSAndroid Build Coastguard Worker     m_b_nacc_err = false;
53*02ca8ccaSAndroid Build Coastguard Worker }
54*02ca8ccaSAndroid Build Coastguard Worker 
~OcsdCodeFollower()55*02ca8ccaSAndroid Build Coastguard Worker OcsdCodeFollower::~OcsdCodeFollower()
56*02ca8ccaSAndroid Build Coastguard Worker {
57*02ca8ccaSAndroid Build Coastguard Worker }
58*02ca8ccaSAndroid Build Coastguard Worker 
initInterfaces(componentAttachPt<ITargetMemAccess> * pMemAccess,componentAttachPt<IInstrDecode> * pIDecode)59*02ca8ccaSAndroid Build Coastguard Worker void OcsdCodeFollower::initInterfaces(componentAttachPt<ITargetMemAccess> *pMemAccess, componentAttachPt<IInstrDecode> *pIDecode)
60*02ca8ccaSAndroid Build Coastguard Worker {
61*02ca8ccaSAndroid Build Coastguard Worker     m_pMemAccess = pMemAccess;
62*02ca8ccaSAndroid Build Coastguard Worker     m_pIDecode = pIDecode;
63*02ca8ccaSAndroid Build Coastguard Worker }
64*02ca8ccaSAndroid Build Coastguard Worker 
initFollowerState()65*02ca8ccaSAndroid Build Coastguard Worker bool OcsdCodeFollower::initFollowerState()
66*02ca8ccaSAndroid Build Coastguard Worker {
67*02ca8ccaSAndroid Build Coastguard Worker     bool initDone = false;
68*02ca8ccaSAndroid Build Coastguard Worker 
69*02ca8ccaSAndroid Build Coastguard Worker     // reset per follow flags
70*02ca8ccaSAndroid Build Coastguard Worker     m_b_next_valid = false;
71*02ca8ccaSAndroid Build Coastguard Worker     m_b_nacc_err = false;
72*02ca8ccaSAndroid Build Coastguard Worker 
73*02ca8ccaSAndroid Build Coastguard Worker     // set range addresses
74*02ca8ccaSAndroid Build Coastguard Worker     m_en_range_addr = m_next_addr = m_st_range_addr;
75*02ca8ccaSAndroid Build Coastguard Worker 
76*02ca8ccaSAndroid Build Coastguard Worker // check initialisation is valid.
77*02ca8ccaSAndroid Build Coastguard Worker 
78*02ca8ccaSAndroid Build Coastguard Worker     // must have attached memory access and i-decode objects
79*02ca8ccaSAndroid Build Coastguard Worker     if(m_pMemAccess && m_pIDecode)
80*02ca8ccaSAndroid Build Coastguard Worker     {
81*02ca8ccaSAndroid Build Coastguard Worker         initDone = (m_pMemAccess->hasAttachedAndEnabled() && m_pIDecode->hasAttachedAndEnabled());
82*02ca8ccaSAndroid Build Coastguard Worker     }
83*02ca8ccaSAndroid Build Coastguard Worker     return initDone;
84*02ca8ccaSAndroid Build Coastguard Worker }
85*02ca8ccaSAndroid Build Coastguard Worker 
86*02ca8ccaSAndroid Build Coastguard Worker /*!
87*02ca8ccaSAndroid Build Coastguard Worker  * Decodes an instruction at a single location, calculates the next address
88*02ca8ccaSAndroid Build Coastguard Worker  * if possible according to the instruction type and atom.
89*02ca8ccaSAndroid Build Coastguard Worker  *
90*02ca8ccaSAndroid Build Coastguard Worker  * @param addrStart : Address of the instruction
91*02ca8ccaSAndroid Build Coastguard Worker  * @param A :  Atom value - E or N
92*02ca8ccaSAndroid Build Coastguard Worker  *
93*02ca8ccaSAndroid Build Coastguard Worker  * @return ocsd_err_t : OCSD_OK - decode correct, check flags for next address
94*02ca8ccaSAndroid Build Coastguard Worker  *                    : OCSD_ERR_MEM_NACC - unable to access memory area @ address - need new address in trace packet stream.
95*02ca8ccaSAndroid Build Coastguard Worker  *                    : OCSD_ERR_NOT_INIT - not initialised - fatal.
96*02ca8ccaSAndroid Build Coastguard Worker  *                    : OCSD_<other>  - other error occured - fatal.
97*02ca8ccaSAndroid Build Coastguard Worker  */
followSingleAtom(const ocsd_vaddr_t addrStart,const ocsd_atm_val A)98*02ca8ccaSAndroid Build Coastguard Worker ocsd_err_t OcsdCodeFollower::followSingleAtom(const ocsd_vaddr_t addrStart, const ocsd_atm_val A)
99*02ca8ccaSAndroid Build Coastguard Worker {
100*02ca8ccaSAndroid Build Coastguard Worker     ocsd_err_t err = OCSD_ERR_NOT_INIT;
101*02ca8ccaSAndroid Build Coastguard Worker 
102*02ca8ccaSAndroid Build Coastguard Worker     if(!initFollowerState())
103*02ca8ccaSAndroid Build Coastguard Worker         return err;
104*02ca8ccaSAndroid Build Coastguard Worker 
105*02ca8ccaSAndroid Build Coastguard Worker     m_en_range_addr = m_st_range_addr = m_instr_info.instr_addr = addrStart;
106*02ca8ccaSAndroid Build Coastguard Worker     err = decodeSingleOpCode();
107*02ca8ccaSAndroid Build Coastguard Worker 
108*02ca8ccaSAndroid Build Coastguard Worker     if(err != OCSD_OK)
109*02ca8ccaSAndroid Build Coastguard Worker         return err;
110*02ca8ccaSAndroid Build Coastguard Worker 
111*02ca8ccaSAndroid Build Coastguard Worker     // set end range - always after the instruction executed.
112*02ca8ccaSAndroid Build Coastguard Worker     m_en_range_addr = m_instr_info.instr_addr + m_instr_info.instr_size;
113*02ca8ccaSAndroid Build Coastguard Worker 
114*02ca8ccaSAndroid Build Coastguard Worker     // assume next addr is the instruction after
115*02ca8ccaSAndroid Build Coastguard Worker     m_next_addr = m_en_range_addr;
116*02ca8ccaSAndroid Build Coastguard Worker     m_b_next_valid = true;
117*02ca8ccaSAndroid Build Coastguard Worker 
118*02ca8ccaSAndroid Build Coastguard Worker     // case when next address is different
119*02ca8ccaSAndroid Build Coastguard Worker     switch(m_instr_info.type)
120*02ca8ccaSAndroid Build Coastguard Worker     {
121*02ca8ccaSAndroid Build Coastguard Worker     case OCSD_INSTR_BR:
122*02ca8ccaSAndroid Build Coastguard Worker         if(A == ATOM_E) // executed the direct branch
123*02ca8ccaSAndroid Build Coastguard Worker             m_next_addr = m_instr_info.branch_addr;
124*02ca8ccaSAndroid Build Coastguard Worker         break;
125*02ca8ccaSAndroid Build Coastguard Worker 
126*02ca8ccaSAndroid Build Coastguard Worker     case OCSD_INSTR_BR_INDIRECT:
127*02ca8ccaSAndroid Build Coastguard Worker         if(A == ATOM_E) // executed indirect branch
128*02ca8ccaSAndroid Build Coastguard Worker             m_b_next_valid = false;
129*02ca8ccaSAndroid Build Coastguard Worker         break;
130*02ca8ccaSAndroid Build Coastguard Worker     }
131*02ca8ccaSAndroid Build Coastguard Worker     return err;
132*02ca8ccaSAndroid Build Coastguard Worker }
133*02ca8ccaSAndroid Build Coastguard Worker 
decodeSingleOpCode()134*02ca8ccaSAndroid Build Coastguard Worker ocsd_err_t OcsdCodeFollower::decodeSingleOpCode()
135*02ca8ccaSAndroid Build Coastguard Worker {
136*02ca8ccaSAndroid Build Coastguard Worker     ocsd_err_t err = OCSD_OK;
137*02ca8ccaSAndroid Build Coastguard Worker     // request 4 bytes for the opcode - even for Thumb which may be T32
138*02ca8ccaSAndroid Build Coastguard Worker     uint32_t bytesReq = 4;
139*02ca8ccaSAndroid Build Coastguard Worker     uint32_t opcode;    // buffer for opcode
140*02ca8ccaSAndroid Build Coastguard Worker 
141*02ca8ccaSAndroid Build Coastguard Worker     // read memory location for opcode
142*02ca8ccaSAndroid Build Coastguard Worker     err = m_pMemAccess->first()->ReadTargetMemory(m_instr_info.instr_addr,m_mem_space_csid,m_mem_acc_rule,&bytesReq,(uint8_t *)&opcode);
143*02ca8ccaSAndroid Build Coastguard Worker 
144*02ca8ccaSAndroid Build Coastguard Worker     // operational error (not access problem - that is indicated by 0 bytes returned)
145*02ca8ccaSAndroid Build Coastguard Worker     if(err != OCSD_OK)
146*02ca8ccaSAndroid Build Coastguard Worker         return err;
147*02ca8ccaSAndroid Build Coastguard Worker 
148*02ca8ccaSAndroid Build Coastguard Worker     if(bytesReq == 4)       // check that we got all memory requested.
149*02ca8ccaSAndroid Build Coastguard Worker     {
150*02ca8ccaSAndroid Build Coastguard Worker         m_instr_info.opcode = opcode;
151*02ca8ccaSAndroid Build Coastguard Worker         err = m_pIDecode->first()->DecodeInstruction(&m_instr_info);
152*02ca8ccaSAndroid Build Coastguard Worker     }
153*02ca8ccaSAndroid Build Coastguard Worker     else       // otherwise memory unavailable.
154*02ca8ccaSAndroid Build Coastguard Worker     {
155*02ca8ccaSAndroid Build Coastguard Worker         m_b_nacc_err = true;
156*02ca8ccaSAndroid Build Coastguard Worker         m_nacc_address = m_instr_info.instr_addr;
157*02ca8ccaSAndroid Build Coastguard Worker         err = OCSD_ERR_MEM_NACC;
158*02ca8ccaSAndroid Build Coastguard Worker     }
159*02ca8ccaSAndroid Build Coastguard Worker     return err;
160*02ca8ccaSAndroid Build Coastguard Worker }
161*02ca8ccaSAndroid Build Coastguard Worker 
162*02ca8ccaSAndroid Build Coastguard Worker /* End of File ocsd_code_follower.cpp */
163