117f65170SRuslan Bukin /* 217f65170SRuslan Bukin * \file ocsd_code_follower.cpp 317f65170SRuslan Bukin * \brief OpenCSD : Instruction Code path follower. 417f65170SRuslan Bukin * 517f65170SRuslan Bukin * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. 617f65170SRuslan Bukin */ 717f65170SRuslan Bukin 817f65170SRuslan Bukin 917f65170SRuslan Bukin /* 1017f65170SRuslan Bukin * Redistribution and use in source and binary forms, with or without modification, 1117f65170SRuslan Bukin * are permitted provided that the following conditions are met: 1217f65170SRuslan Bukin * 1317f65170SRuslan Bukin * 1. Redistributions of source code must retain the above copyright notice, 1417f65170SRuslan Bukin * this list of conditions and the following disclaimer. 1517f65170SRuslan Bukin * 1617f65170SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright notice, 1717f65170SRuslan Bukin * this list of conditions and the following disclaimer in the documentation 1817f65170SRuslan Bukin * and/or other materials provided with the distribution. 1917f65170SRuslan Bukin * 2017f65170SRuslan Bukin * 3. Neither the name of the copyright holder nor the names of its contributors 2117f65170SRuslan Bukin * may be used to endorse or promote products derived from this software without 2217f65170SRuslan Bukin * specific prior written permission. 2317f65170SRuslan Bukin * 2417f65170SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 2517f65170SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2617f65170SRuslan Bukin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2717f65170SRuslan Bukin * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 2817f65170SRuslan Bukin * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2917f65170SRuslan Bukin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 3017f65170SRuslan Bukin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 3117f65170SRuslan Bukin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3217f65170SRuslan Bukin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317f65170SRuslan Bukin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3417f65170SRuslan Bukin */ 3517f65170SRuslan Bukin 3617f65170SRuslan Bukin #include "common/ocsd_code_follower.h" 3717f65170SRuslan Bukin 3817f65170SRuslan Bukin OcsdCodeFollower::OcsdCodeFollower() 3917f65170SRuslan Bukin { 4017f65170SRuslan Bukin m_instr_info.pe_type.arch = ARCH_UNKNOWN; 4117f65170SRuslan Bukin m_instr_info.pe_type.profile = profile_Unknown; 4217f65170SRuslan Bukin m_instr_info.isa = ocsd_isa_unknown; 4317f65170SRuslan Bukin m_instr_info.dsb_dmb_waypoints = 0; 4417f65170SRuslan Bukin m_instr_info.instr_addr = 0; 4517f65170SRuslan Bukin m_instr_info.opcode = 0; 4617f65170SRuslan Bukin m_pMemAccess = 0; 4717f65170SRuslan Bukin m_pIDecode = 0; 4817f65170SRuslan Bukin m_mem_space_csid = 0; 4917f65170SRuslan Bukin m_st_range_addr = m_en_range_addr = m_next_addr = 0; 5017f65170SRuslan Bukin m_b_next_valid = false; 5117f65170SRuslan Bukin m_b_nacc_err = false; 5217f65170SRuslan Bukin } 5317f65170SRuslan Bukin 5417f65170SRuslan Bukin OcsdCodeFollower::~OcsdCodeFollower() 5517f65170SRuslan Bukin { 5617f65170SRuslan Bukin } 5717f65170SRuslan Bukin 5817f65170SRuslan Bukin void OcsdCodeFollower::initInterfaces(componentAttachPt<ITargetMemAccess> *pMemAccess, componentAttachPt<IInstrDecode> *pIDecode) 5917f65170SRuslan Bukin { 6017f65170SRuslan Bukin m_pMemAccess = pMemAccess; 6117f65170SRuslan Bukin m_pIDecode = pIDecode; 6217f65170SRuslan Bukin } 6317f65170SRuslan Bukin 6417f65170SRuslan Bukin bool OcsdCodeFollower::initFollowerState() 6517f65170SRuslan Bukin { 6617f65170SRuslan Bukin bool initDone = false; 6717f65170SRuslan Bukin 6817f65170SRuslan Bukin // reset per follow flags 6917f65170SRuslan Bukin m_b_next_valid = false; 7017f65170SRuslan Bukin m_b_nacc_err = false; 7117f65170SRuslan Bukin 7217f65170SRuslan Bukin // set range addresses 7317f65170SRuslan Bukin m_en_range_addr = m_next_addr = m_st_range_addr; 7417f65170SRuslan Bukin 7517f65170SRuslan Bukin // check initialisation is valid. 7617f65170SRuslan Bukin 7717f65170SRuslan Bukin // must have attached memory access and i-decode objects 7817f65170SRuslan Bukin if(m_pMemAccess && m_pIDecode) 7917f65170SRuslan Bukin { 8017f65170SRuslan Bukin initDone = (m_pMemAccess->hasAttachedAndEnabled() && m_pIDecode->hasAttachedAndEnabled()); 8117f65170SRuslan Bukin } 8217f65170SRuslan Bukin return initDone; 8317f65170SRuslan Bukin } 8417f65170SRuslan Bukin 8517f65170SRuslan Bukin /*! 8617f65170SRuslan Bukin * Decodes an instruction at a single location, calculates the next address 8717f65170SRuslan Bukin * if possible according to the instruction type and atom. 8817f65170SRuslan Bukin * 8917f65170SRuslan Bukin * @param addrStart : Address of the instruction 9017f65170SRuslan Bukin * @param A : Atom value - E or N 9117f65170SRuslan Bukin * 9217f65170SRuslan Bukin * @return ocsd_err_t : OCSD_OK - decode correct, check flags for next address 9317f65170SRuslan Bukin * : OCSD_ERR_MEM_NACC - unable to access memory area @ address - need new address in trace packet stream. 9417f65170SRuslan Bukin * : OCSD_ERR_NOT_INIT - not initialised - fatal. 9517f65170SRuslan Bukin * : OCSD_<other> - other error occured - fatal. 9617f65170SRuslan Bukin */ 9717f65170SRuslan Bukin ocsd_err_t OcsdCodeFollower::followSingleAtom(const ocsd_vaddr_t addrStart, const ocsd_atm_val A) 9817f65170SRuslan Bukin { 9917f65170SRuslan Bukin ocsd_err_t err = OCSD_ERR_NOT_INIT; 10017f65170SRuslan Bukin 10117f65170SRuslan Bukin if(!initFollowerState()) 10217f65170SRuslan Bukin return err; 10317f65170SRuslan Bukin 10417f65170SRuslan Bukin m_en_range_addr = m_st_range_addr = m_instr_info.instr_addr = addrStart; 10517f65170SRuslan Bukin err = decodeSingleOpCode(); 10617f65170SRuslan Bukin 10717f65170SRuslan Bukin if(err != OCSD_OK) 10817f65170SRuslan Bukin return err; 10917f65170SRuslan Bukin 11017f65170SRuslan Bukin // set end range - always after the instruction executed. 11117f65170SRuslan Bukin m_en_range_addr = m_instr_info.instr_addr + m_instr_info.instr_size; 11217f65170SRuslan Bukin 11317f65170SRuslan Bukin // assume next addr is the instruction after 11417f65170SRuslan Bukin m_next_addr = m_en_range_addr; 11517f65170SRuslan Bukin m_b_next_valid = true; 11617f65170SRuslan Bukin 11717f65170SRuslan Bukin // case when next address is different 11817f65170SRuslan Bukin switch(m_instr_info.type) 11917f65170SRuslan Bukin { 12017f65170SRuslan Bukin case OCSD_INSTR_BR: 12117f65170SRuslan Bukin if(A == ATOM_E) // executed the direct branch 12217f65170SRuslan Bukin m_next_addr = m_instr_info.branch_addr; 12317f65170SRuslan Bukin break; 12417f65170SRuslan Bukin 12517f65170SRuslan Bukin case OCSD_INSTR_BR_INDIRECT: 12617f65170SRuslan Bukin if(A == ATOM_E) // executed indirect branch 12717f65170SRuslan Bukin m_b_next_valid = false; 12817f65170SRuslan Bukin break; 12917f65170SRuslan Bukin } 13017f65170SRuslan Bukin return err; 13117f65170SRuslan Bukin } 13217f65170SRuslan Bukin 13317f65170SRuslan Bukin ocsd_err_t OcsdCodeFollower::decodeSingleOpCode() 13417f65170SRuslan Bukin { 13517f65170SRuslan Bukin ocsd_err_t err = OCSD_OK; 13617f65170SRuslan Bukin // request 4 bytes for the opcode - even for Thumb which may be T32 13717f65170SRuslan Bukin uint32_t bytesReq = 4; 13817f65170SRuslan Bukin uint32_t opcode; // buffer for opcode 13917f65170SRuslan Bukin 14017f65170SRuslan Bukin // read memory location for opcode 14117f65170SRuslan Bukin err = m_pMemAccess->first()->ReadTargetMemory(m_instr_info.instr_addr,m_mem_space_csid,m_mem_acc_rule,&bytesReq,(uint8_t *)&opcode); 14217f65170SRuslan Bukin 14317f65170SRuslan Bukin // operational error (not access problem - that is indicated by 0 bytes returned) 14417f65170SRuslan Bukin if(err != OCSD_OK) 14517f65170SRuslan Bukin return err; 14617f65170SRuslan Bukin 14717f65170SRuslan Bukin if(bytesReq == 4) // check that we got all memory requested. 14817f65170SRuslan Bukin { 14917f65170SRuslan Bukin m_instr_info.opcode = opcode; 15017f65170SRuslan Bukin err = m_pIDecode->first()->DecodeInstruction(&m_instr_info); 15117f65170SRuslan Bukin } 15217f65170SRuslan Bukin else // otherwise memory unavailable. 15317f65170SRuslan Bukin { 15417f65170SRuslan Bukin m_b_nacc_err = true; 15517f65170SRuslan Bukin m_nacc_address = m_instr_info.instr_addr; 15617f65170SRuslan Bukin err = OCSD_ERR_MEM_NACC; 15717f65170SRuslan Bukin } 15817f65170SRuslan Bukin return err; 15917f65170SRuslan Bukin } 16017f65170SRuslan Bukin 16117f65170SRuslan Bukin /* End of File ocsd_code_follower.cpp */ 162