1 /* 2 * \file trc_i_decode.cpp 3 * \brief OpenCSD : 4 * 5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. 6 */ 7 8 /* 9 * Redistribution and use in source and binary forms, with or without modification, 10 * are permitted provided that the following conditions are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the copyright holder nor the names of its contributors 20 * may be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "opencsd/ocsd_if_types.h" 36 #include "i_dec/trc_i_decode.h" 37 #include "i_dec/trc_idec_arminst.h" 38 39 ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info) 40 { 41 ocsd_err_t err = OCSD_OK; 42 clear_instr_subtype(); 43 SetArchVersion(instr_info); 44 45 switch(instr_info->isa) 46 { 47 case ocsd_isa_arm: 48 err = DecodeA32(instr_info); 49 break; 50 51 case ocsd_isa_thumb2: 52 err = DecodeT32(instr_info); 53 break; 54 55 case ocsd_isa_aarch64: 56 err = DecodeA64(instr_info); 57 break; 58 59 case ocsd_isa_tee: 60 case ocsd_isa_jazelle: 61 default: 62 // unsupported ISA 63 err = OCSD_ERR_UNSUPPORTED_ISA; 64 break; 65 } 66 instr_info->sub_type = get_instr_subtype(); 67 return err; 68 } 69 70 void TrcIDecode::SetArchVersion(ocsd_instr_info *instr_info) 71 { 72 uint16_t arch = 0x0700; 73 74 switch (instr_info->pe_type.arch) 75 { 76 case ARCH_V8: arch = 0x0800; break; 77 case ARCH_V8r3: arch = 0x0803; break; 78 case ARCH_V7: 79 default: 80 break; 81 } 82 set_arch_version(arch); 83 } 84 85 86 ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) 87 { 88 uint32_t branchAddr = 0; 89 arm_barrier_t barrier; 90 91 instr_info->instr_size = 4; // instruction size A32 92 instr_info->type = OCSD_INSTR_OTHER; // default type 93 instr_info->next_isa = instr_info->isa; // assume same ISA 94 instr_info->is_link = 0; 95 96 if(inst_ARM_is_indirect_branch(instr_info->opcode)) 97 { 98 instr_info->type = OCSD_INSTR_BR_INDIRECT; 99 instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode); 100 } 101 else if(inst_ARM_is_direct_branch(instr_info->opcode)) 102 { 103 inst_ARM_branch_destination((uint32_t)instr_info->instr_addr,instr_info->opcode,&branchAddr); 104 instr_info->type = OCSD_INSTR_BR; 105 if (branchAddr & 0x1) 106 { 107 instr_info->next_isa = ocsd_isa_thumb2; 108 branchAddr &= ~0x1; 109 } 110 instr_info->branch_addr = (ocsd_vaddr_t)branchAddr; 111 instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode); 112 } 113 else if((barrier = inst_ARM_barrier(instr_info->opcode)) != ARM_BARRIER_NONE) 114 { 115 switch(barrier) 116 { 117 case ARM_BARRIER_ISB: 118 instr_info->type = OCSD_INSTR_ISB; 119 break; 120 121 case ARM_BARRIER_DSB: 122 case ARM_BARRIER_DMB: 123 if(instr_info->dsb_dmb_waypoints) 124 instr_info->type = OCSD_INSTR_DSB_DMB; 125 break; 126 } 127 } 128 else if (instr_info->wfi_wfe_branch) 129 { 130 if (inst_ARM_wfiwfe(instr_info->opcode)) 131 { 132 instr_info->type = OCSD_INSTR_WFI_WFE; 133 } 134 } 135 instr_info->is_conditional = inst_ARM_is_conditional(instr_info->opcode); 136 137 return OCSD_OK; 138 } 139 140 ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info) 141 { 142 uint64_t branchAddr = 0; 143 arm_barrier_t barrier; 144 145 instr_info->instr_size = 4; // default address update 146 instr_info->type = OCSD_INSTR_OTHER; // default type 147 instr_info->next_isa = instr_info->isa; // assume same ISA 148 instr_info->is_link = 0; 149 150 if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link)) 151 { 152 instr_info->type = OCSD_INSTR_BR_INDIRECT; 153 // instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode); 154 } 155 else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link)) 156 { 157 inst_A64_branch_destination(instr_info->instr_addr,instr_info->opcode,&branchAddr); 158 instr_info->type = OCSD_INSTR_BR; 159 instr_info->branch_addr = (ocsd_vaddr_t)branchAddr; 160 // instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode); 161 } 162 else if((barrier = inst_A64_barrier(instr_info->opcode)) != ARM_BARRIER_NONE) 163 { 164 switch(barrier) 165 { 166 case ARM_BARRIER_ISB: 167 instr_info->type = OCSD_INSTR_ISB; 168 break; 169 170 case ARM_BARRIER_DSB: 171 case ARM_BARRIER_DMB: 172 if(instr_info->dsb_dmb_waypoints) 173 instr_info->type = OCSD_INSTR_DSB_DMB; 174 break; 175 } 176 } 177 else if (instr_info->wfi_wfe_branch) 178 { 179 if (inst_A64_wfiwfe(instr_info->opcode)) 180 { 181 instr_info->type = OCSD_INSTR_WFI_WFE; 182 } 183 } 184 185 instr_info->is_conditional = inst_A64_is_conditional(instr_info->opcode); 186 187 return OCSD_OK; 188 } 189 190 ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) 191 { 192 uint32_t branchAddr = 0; 193 arm_barrier_t barrier; 194 195 // need to align the 32 bit opcode as 2 16 bit, with LS 16 as in top 16 bit of 196 // 32 bit word - T2 routines assume 16 bit in top 16 bit of 32 bit opcode. 197 uint32_t op_temp = (instr_info->opcode >> 16) & 0xFFFF; 198 op_temp |= ((instr_info->opcode & 0xFFFF) << 16); 199 instr_info->opcode = op_temp; 200 201 202 instr_info->instr_size = is_wide_thumb((uint16_t)(instr_info->opcode >> 16)) ? 4 : 2; 203 instr_info->type = OCSD_INSTR_OTHER; // default type 204 instr_info->next_isa = instr_info->isa; // assume same ISA 205 instr_info->is_link = 0; 206 instr_info->is_conditional = 0; 207 208 209 if(inst_Thumb_is_direct_branch_link(instr_info->opcode,&instr_info->is_link, &instr_info->is_conditional)) 210 { 211 inst_Thumb_branch_destination((uint32_t)instr_info->instr_addr,instr_info->opcode,&branchAddr); 212 instr_info->type = OCSD_INSTR_BR; 213 instr_info->branch_addr = (ocsd_vaddr_t)(branchAddr & ~0x1); 214 if((branchAddr & 0x1) == 0) 215 instr_info->next_isa = ocsd_isa_arm; 216 } 217 else if (inst_Thumb_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link)) 218 { 219 instr_info->type = OCSD_INSTR_BR_INDIRECT; 220 } 221 else if((barrier = inst_Thumb_barrier(instr_info->opcode)) != ARM_BARRIER_NONE) 222 { 223 switch(barrier) 224 { 225 case ARM_BARRIER_ISB: 226 instr_info->type = OCSD_INSTR_ISB; 227 break; 228 229 case ARM_BARRIER_DSB: 230 case ARM_BARRIER_DMB: 231 if(instr_info->dsb_dmb_waypoints) 232 instr_info->type = OCSD_INSTR_DSB_DMB; 233 break; 234 } 235 } 236 else if (instr_info->wfi_wfe_branch) 237 { 238 if (inst_Thumb_wfiwfe(instr_info->opcode)) 239 { 240 instr_info->type = OCSD_INSTR_WFI_WFE; 241 } 242 } 243 instr_info->is_conditional = inst_Thumb_is_conditional(instr_info->opcode); 244 instr_info->thumb_it_conditions = inst_Thumb_is_IT(instr_info->opcode); 245 246 return OCSD_OK; 247 } 248 249 250 /* End of File trc_i_decode.cpp */ 251