1 /* 2 * \file trc_idec_arminst.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 /* 36 Basic ARM/Thumb/A64 instruction decode, suitable for e.g. basic 37 block identification and trace decode. 38 */ 39 40 #include "i_dec/trc_idec_arminst.h" 41 42 #include <stddef.h> /* for NULL */ 43 #include <assert.h> 44 45 int inst_ARM_is_direct_branch(uint32_t inst) 46 { 47 int is_direct_branch = 1; 48 if ((inst & 0xf0000000) == 0xf0000000) { 49 /* NV space */ 50 if ((inst & 0xfe000000) == 0xfa000000){ 51 /* BLX (imm) */ 52 } else { 53 is_direct_branch = 0; 54 } 55 } else if ((inst & 0x0e000000) == 0x0a000000) { 56 /* B, BL */ 57 } else { 58 is_direct_branch = 0; 59 } 60 return is_direct_branch; 61 } 62 63 int inst_ARM_wfiwfe(uint32_t inst) 64 { 65 if ( ((inst & 0xf0000000) != 0xf0000000) && 66 ((inst & 0x0ffffffe) == 0x0320f002) 67 ) 68 /* WFI & WFE may be traced as branches in etm4.3 ++ */ 69 return 1; 70 return 0; 71 } 72 73 int inst_ARM_is_indirect_branch(uint32_t inst, struct decode_info *info) 74 { 75 int is_indirect_branch = 1; 76 if ((inst & 0xf0000000) == 0xf0000000) { 77 /* NV space */ 78 if ((inst & 0xfe500000) == 0xf8100000) { 79 /* RFE */ 80 } else { 81 is_indirect_branch = 0; 82 } 83 } else if ((inst & 0x0ff000d0) == 0x01200010) { 84 /* BLX (register), BX */ 85 if ((inst & 0xFF) == 0x1E) 86 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ 87 } else if ((inst & 0x0ff000f0) == 0x01200020) { 88 /* BXJ: in v8 this behaves like BX */ 89 } else if ((inst & 0x0e108000) == 0x08108000) { 90 /* POP {...,pc} or LDMxx {...,pc} */ 91 if ((inst & 0x0FFFA000) == 0x08BD8000) /* LDMIA SP!,{...,pc} */ 92 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; 93 } else if ((inst & 0x0e50f000) == 0x0410f000) { 94 /* LDR PC,imm... inc. POP {PC} */ 95 if ( (inst & 0x01ff0000) == 0x009D0000) 96 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm */ 97 } else if ((inst & 0x0e50f010) == 0x0610f000) { 98 /* LDR PC,reg */ 99 } else if ((inst & 0x0fe0f000) == 0x01a0f000) { 100 /* MOV PC,rx */ 101 if ((inst & 0x00100FFF) == 0x00E) /* ensure the S=0, LSL #0 variant - i.e plain MOV */ 102 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC, R14 */ 103 } else if ((inst & 0x0f900080) == 0x01000000) { 104 /* "Miscellaneous instructions" - in DP space */ 105 is_indirect_branch = 0; 106 } else if ((inst & 0x0f9000f0) == 0x01800090) { 107 /* Some extended loads and stores */ 108 is_indirect_branch = 0; 109 } else if ((inst & 0x0fb0f000) == 0x0320f000) { 110 /* MSR #imm */ 111 is_indirect_branch = 0; 112 } else if ((inst & 0x0e00f000) == 0x0200f000) { 113 /* DP PC,imm shift */ 114 if ((inst & 0x0f90f000) == 0x0310f000) { 115 /* TST/CMP */ 116 is_indirect_branch = 0; 117 } 118 } else if ((inst & 0x0e00f000) == 0x0000f000) { 119 /* DP PC,reg */ 120 } else { 121 is_indirect_branch = 0; 122 } 123 return is_indirect_branch; 124 } 125 126 int inst_Thumb_is_direct_branch(uint32_t inst, struct decode_info *info) 127 { 128 uint8_t link, cond; 129 return inst_Thumb_is_direct_branch_link(inst, &link, &cond, info); 130 } 131 132 int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond, struct decode_info *info) 133 { 134 int is_direct_branch = 1; 135 136 if ((inst & 0xf0000000) == 0xd0000000 && (inst & 0x0e000000) != 0x0e000000) { 137 /* B<c> (encoding T1) */ 138 *is_cond = 1; 139 } else if ((inst & 0xf8000000) == 0xe0000000) { 140 /* B (encoding T2) */ 141 } else if ((inst & 0xf800d000) == 0xf0008000 && (inst & 0x03800000) != 0x03800000) { 142 /* B (encoding T3) */ 143 *is_cond = 1; 144 } else if ((inst & 0xf8009000) == 0xf0009000) { 145 /* B (encoding T4); BL (encoding T1) */ 146 if (inst & 0x00004000) { 147 *is_link = 1; 148 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 149 } 150 } else if ((inst & 0xf800d001) == 0xf000c000) { 151 /* BLX (imm) (encoding T2) */ 152 *is_link = 1; 153 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 154 } else if ((inst & 0xf5000000) == 0xb1000000) { 155 /* CB(NZ) */ 156 *is_cond = 1; 157 } else { 158 is_direct_branch = 0; 159 } 160 return is_direct_branch; 161 } 162 163 int inst_Thumb_wfiwfe(uint32_t inst) 164 { 165 int is_wfiwfe = 1; 166 /* WFI, WFE may be branches in etm4.3++ */ 167 if ((inst & 0xfffffffe) == 0xf3af8002) { 168 /* WFI & WFE (encoding T2) */ 169 } 170 else if ((inst & 0xffef0000) == 0xbf200000) { 171 /* WFI & WFE (encoding T1) */ 172 } 173 else { 174 is_wfiwfe = 0; 175 } 176 return is_wfiwfe; 177 } 178 179 int inst_Thumb_is_indirect_branch(uint32_t inst, struct decode_info *info) 180 { 181 uint8_t link; 182 return inst_Thumb_is_indirect_branch_link(inst, &link, info); 183 } 184 185 int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) 186 { 187 /* See e.g. PFT Table 2-3 and Table 2-5 */ 188 int is_branch = 1; 189 190 if ((inst & 0xff000000) == 0x47000000) { 191 /* BX, BLX (reg) [v8M includes BXNS, BLXNS] */ 192 if (inst & 0x00800000) { 193 *is_link = 1; 194 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 195 } 196 else if ((inst & 0x00780000) == 0x00700000) { 197 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ 198 } 199 } else if ((inst & 0xfff0d000) == 0xf3c08000) { 200 /* BXJ: in v8 this behaves like BX */ 201 } else if ((inst & 0xff000000) == 0xbd000000) { 202 /* POP {pc} */ 203 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; 204 } else if ((inst & 0xfd870000) == 0x44870000) { 205 /* MOV PC,reg or ADD PC,reg */ 206 if ((inst & 0xffff0000) == 0x46f70000) 207 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC,LR */ 208 } else if ((inst & 0xfff0ffe0) == 0xe8d0f000) { 209 /* TBB/TBH */ 210 } else if ((inst & 0xffd00000) == 0xe8100000) { 211 /* RFE (T1) */ 212 } else if ((inst & 0xffd00000) == 0xe9900000) { 213 /* RFE (T2) */ 214 } else if ((inst & 0xfff0d000) == 0xf3d08000) { 215 /* SUBS PC,LR,#imm inc.ERET */ 216 } else if ((inst & 0xfff0f000) == 0xf8d0f000) { 217 /* LDR PC,imm (T3) */ 218 } else if ((inst & 0xff7ff000) == 0xf85ff000) { 219 /* LDR PC,literal (T2) */ 220 } else if ((inst & 0xfff0f800) == 0xf850f800) { 221 /* LDR PC,imm (T4) */ 222 if((inst & 0x000f0f00) == 0x000d0b00) 223 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm*/ 224 } else if ((inst & 0xfff0ffc0) == 0xf850f000) { 225 /* LDR PC,reg (T2) */ 226 } else if ((inst & 0xfe508000) == 0xe8108000) { 227 /* LDM PC */ 228 if ((inst & 0x0FFF0000) == 0x08BD0000) /* LDMIA [SP]!, */ 229 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* POP {...,pc} */ 230 } else { 231 is_branch = 0; 232 } 233 return is_branch; 234 } 235 236 int inst_A64_is_direct_branch(uint32_t inst, struct decode_info *info) 237 { 238 uint8_t link = 0; 239 return inst_A64_is_direct_branch_link(inst, &link, info); 240 } 241 242 int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) 243 { 244 int is_direct_branch = 1; 245 if ((inst & 0x7c000000) == 0x34000000) { 246 /* CB, TB */ 247 } else if ((inst & 0xff000010) == 0x54000000) { 248 /* B<cond> */ 249 } else if ((inst & 0x7c000000) == 0x14000000) { 250 /* B, BL imm */ 251 if (inst & 0x80000000) { 252 *is_link = 1; 253 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 254 } 255 } else { 256 is_direct_branch = 0; 257 } 258 return is_direct_branch; 259 } 260 261 int inst_A64_wfiwfe(uint32_t inst) 262 { 263 /* WFI, WFE may be traced as branches in etm 4.3++ */ 264 if ((inst & 0xffffffdf) == 0xd503205f) 265 return 1; 266 return 0; 267 } 268 269 int inst_A64_is_indirect_branch(uint32_t inst, struct decode_info *info) 270 { 271 uint8_t link = 0; 272 return inst_A64_is_indirect_branch_link(inst, &link, info); 273 } 274 275 int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) 276 { 277 int is_indirect_branch = 1; 278 279 if ((inst & 0xffdffc1f) == 0xd61f0000) { 280 /* BR, BLR */ 281 if (inst & 0x00200000) { 282 *is_link = 1; 283 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 284 } 285 } else if ((inst & 0xfffffc1f) == 0xd65f0000) { 286 info->instr_sub_type = OCSD_S_INSTR_V8_RET; 287 /* RET */ 288 } else if ((inst & 0xffffffff) == 0xd69f03e0) { 289 /* ERET */ 290 info->instr_sub_type = OCSD_S_INSTR_V8_ERET; 291 } else if (info->arch_version >= 0x0803) { 292 /* new pointer auth instr for v8.3 arch */ 293 if ((inst & 0xffdff800) == 0xd71f0800) { 294 /* BRAA, BRAB, BLRAA, BLRBB */ 295 if (inst & 0x00200000) { 296 *is_link = 1; 297 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 298 } 299 } else if ((inst & 0xffdff81F) == 0xd61f081F) { 300 /* BRAAZ, BRABZ, BLRAAZ, BLRBBZ */ 301 if (inst & 0x00200000) { 302 *is_link = 1; 303 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 304 } 305 } else if ((inst & 0xfffffbff) == 0xd69f0bff) { 306 /* ERETAA, ERETAB */ 307 info->instr_sub_type = OCSD_S_INSTR_V8_ERET; 308 } else if ((inst & 0xfffffbff) == 0xd65f0bff) { 309 /* RETAA, RETAB */ 310 info->instr_sub_type = OCSD_S_INSTR_V8_RET; 311 } else { 312 is_indirect_branch = 0; 313 } 314 } else { 315 is_indirect_branch = 0; 316 } 317 return is_indirect_branch; 318 } 319 320 int inst_ARM_branch_destination(uint32_t addr, uint32_t inst, uint32_t *pnpc) 321 { 322 uint32_t npc; 323 int is_direct_branch = 1; 324 if ((inst & 0x0e000000) == 0x0a000000) { 325 /* 326 B: cccc:1010:imm24 327 BL: cccc:1011:imm24 328 BLX: 1111:101H:imm24 329 */ 330 npc = addr + 8 + ((int32_t)((inst & 0xffffff) << 8) >> 6); 331 if ((inst & 0xf0000000) == 0xf0000000) { 332 npc |= 1; /* indicate ISA is now Thumb */ 333 npc |= ((inst >> 23) & 2); /* apply the H bit */ 334 } 335 } else { 336 is_direct_branch = 0; 337 } 338 if (is_direct_branch && pnpc != NULL) { 339 *pnpc = npc; 340 } 341 return is_direct_branch; 342 } 343 344 int inst_Thumb_branch_destination(uint32_t addr, uint32_t inst, uint32_t *pnpc) 345 { 346 uint32_t npc; 347 int is_direct_branch = 1; 348 if ((inst & 0xf0000000) == 0xd0000000 && (inst & 0x0e000000) != 0x0e000000) { 349 /* B<c> (encoding T1) */ 350 npc = addr + 4 + ((int32_t)((inst & 0x00ff0000) << 8) >> 23); 351 npc |= 1; 352 } else if ((inst & 0xf8000000) == 0xe0000000) { 353 /* B (encoding T2) */ 354 npc = addr + 4 + ((int32_t)((inst & 0x07ff0000) << 5) >> 20); 355 npc |= 1; 356 } else if ((inst & 0xf800d000) == 0xf0008000 && (inst & 0x03800000) != 0x03800000) { 357 /* B (encoding T3) */ 358 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) | 359 ((inst & 0x0800) << 19) | 360 ((inst & 0x2000) << 16) | 361 ((inst & 0x003f0000) << 7) | 362 ((inst & 0x000007ff) << 12)) >> 11); 363 npc |= 1; 364 } else if ((inst & 0xf8009000) == 0xf0009000) { 365 /* B (encoding T4); BL (encoding T1) */ 366 uint32_t S = ((inst & 0x04000000) >> 26)-1; /* ffffffff or 0 according to S bit */ 367 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) | 368 (((inst^S) & 0x2000) << 17) | 369 (((inst^S) & 0x0800) << 18) | 370 ((inst & 0x03ff0000) << 3) | 371 ((inst & 0x000007ff) << 8)) >> 7); 372 npc |= 1; 373 } else if ((inst & 0xf800d001) == 0xf000c000) { 374 /* BLX (encoding T2) */ 375 uint32_t S = ((inst & 0x04000000) >> 26)-1; /* ffffffff or 0 according to S bit */ 376 addr &= 0xfffffffc; /* Align(PC,4) */ 377 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) | 378 (((inst^S) & 0x2000) << 17) | 379 (((inst^S) & 0x0800) << 18) | 380 ((inst & 0x03ff0000) << 3) | 381 ((inst & 0x000007fe) << 8)) >> 7); 382 /* don't set the Thumb bit, as we're transferring to ARM */ 383 } else if ((inst & 0xf5000000) == 0xb1000000) { 384 /* CB(NZ) */ 385 /* Note that it's zero-extended - always a forward branch */ 386 npc = addr + 4 + ((((inst & 0x02000000) << 6) | 387 ((inst & 0x00f80000) << 7)) >> 25); 388 npc |= 1; 389 } else { 390 is_direct_branch = 0; 391 } 392 if (is_direct_branch && pnpc != NULL) { 393 *pnpc = npc; 394 } 395 return is_direct_branch; 396 } 397 398 int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc) 399 { 400 uint64_t npc; 401 int is_direct_branch = 1; 402 if ((inst & 0xff000010) == 0x54000000) { 403 /* B<cond> */ 404 npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11); 405 } else if ((inst & 0x7c000000) == 0x14000000) { 406 /* B, BL imm */ 407 npc = addr + ((int32_t)((inst & 0x03ffffff) << 6) >> 4); 408 } else if ((inst & 0x7e000000) == 0x34000000) { 409 /* CB */ 410 npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11); 411 } else if ((inst & 0x7e000000) == 0x36000000) { 412 /* TB */ 413 npc = addr + ((int32_t)((inst & 0x0007ffe0) << 13) >> 16); 414 } else { 415 is_direct_branch = 0; 416 } 417 if (is_direct_branch && pnpc != NULL) { 418 *pnpc = npc; 419 } 420 return is_direct_branch; 421 } 422 423 int inst_ARM_is_branch(uint32_t inst, struct decode_info *info) 424 { 425 return inst_ARM_is_indirect_branch(inst, info) || 426 inst_ARM_is_direct_branch(inst); 427 } 428 429 int inst_Thumb_is_branch(uint32_t inst, struct decode_info *info) 430 { 431 return inst_Thumb_is_indirect_branch(inst, info) || 432 inst_Thumb_is_direct_branch(inst, info); 433 } 434 435 int inst_A64_is_branch(uint32_t inst, struct decode_info *info) 436 { 437 return inst_A64_is_indirect_branch(inst, info) || 438 inst_A64_is_direct_branch(inst, info); 439 } 440 441 int inst_ARM_is_branch_and_link(uint32_t inst, struct decode_info *info) 442 { 443 int is_branch = 1; 444 if ((inst & 0xf0000000) == 0xf0000000) { 445 if ((inst & 0xfe000000) == 0xfa000000){ 446 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 447 /* BLX (imm) */ 448 } else { 449 is_branch = 0; 450 } 451 } else if ((inst & 0x0f000000) == 0x0b000000) { 452 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 453 /* BL */ 454 } else if ((inst & 0x0ff000f0) == 0x01200030) { 455 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 456 /* BLX (reg) */ 457 } else { 458 is_branch = 0; 459 } 460 return is_branch; 461 } 462 463 int inst_Thumb_is_branch_and_link(uint32_t inst, struct decode_info *info) 464 { 465 int is_branch = 1; 466 if ((inst & 0xff800000) == 0x47800000) { 467 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 468 /* BLX (reg) */ 469 } else if ((inst & 0xf800c000) == 0xf000c000) { 470 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 471 /* BL, BLX (imm) */ 472 } else { 473 is_branch = 0; 474 } 475 return is_branch; 476 } 477 478 int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info) 479 { 480 int is_branch = 1; 481 if ((inst & 0xfffffc1f) == 0xd63f0000) { 482 /* BLR */ 483 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 484 } else if ((inst & 0xfc000000) == 0x94000000) { 485 /* BL */ 486 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 487 } else if (info->arch_version >= 0x0803) { 488 /* new pointer auth instr for v8.3 arch */ 489 if ((inst & 0xfffff800) == 0xd73f0800) { 490 /* BLRAA, BLRBB */ 491 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 492 } else if ((inst & 0xfffff81F) == 0xd63f081F) { 493 /* BLRAAZ, BLRBBZ */ 494 info->instr_sub_type = OCSD_S_INSTR_BR_LINK; 495 } else { 496 is_branch = 0; 497 } 498 } else { 499 is_branch = 0; 500 } 501 return is_branch; 502 } 503 504 int inst_ARM_is_conditional(uint32_t inst) 505 { 506 return (inst & 0xe0000000) != 0xe0000000; 507 } 508 509 int inst_Thumb_is_conditional(uint32_t inst) 510 { 511 if ((inst & 0xf0000000) == 0xd0000000 && (inst & 0x0e000000) != 0x0e000000) { 512 /* B<c> (encoding T1) */ 513 return 1; 514 } else if ((inst & 0xf800d000) == 0xf0008000 && (inst & 0x03800000) != 0x03800000) { 515 /* B<c> (encoding T3) */ 516 return 1; 517 } else if ((inst & 0xf5000000) == 0xb1000000) { 518 /* CB(N)Z */ 519 return 1; 520 } 521 return 0; 522 } 523 524 unsigned int inst_Thumb_is_IT(uint32_t inst) 525 { 526 if ((inst & 0xff000000) == 0xbf000000 && 527 (inst & 0x000f0000) != 0x00000000) { 528 if (inst & 0x00010000) { 529 return 4; 530 } else if (inst & 0x00020000) { 531 return 3; 532 } else if (inst & 0x00040000) { 533 return 2; 534 } else { 535 assert(inst & 0x00080000); 536 return 1; 537 } 538 } else { 539 return 0; 540 } 541 } 542 543 /* 544 Test whether an A64 instruction is conditional. 545 546 Instructions like CSEL, CSINV, CCMP are not classed as conditional. 547 They use the condition code but do one of two things with it, 548 neither a NOP. The "intruction categories" section of ETMv4 549 lists no (non branch) conditional instructions for A64. 550 */ 551 int inst_A64_is_conditional(uint32_t inst) 552 { 553 if ((inst & 0x7c000000) == 0x34000000) { 554 /* CB, TB */ 555 return 1; 556 } else if ((inst & 0xff000010) == 0x54000000) { 557 /* B.cond */ 558 return 1; 559 } 560 return 0; 561 } 562 563 arm_barrier_t inst_ARM_barrier(uint32_t inst) 564 { 565 if ((inst & 0xfff00000) == 0xf5700000) { 566 switch (inst & 0xf0) { 567 case 0x40: 568 return ARM_BARRIER_DSB; 569 case 0x50: 570 return ARM_BARRIER_DMB; 571 case 0x60: 572 return ARM_BARRIER_ISB; 573 default: 574 return ARM_BARRIER_NONE; 575 } 576 } else if ((inst & 0x0fff0f00) == 0x0e070f00) { 577 switch (inst & 0xff) { 578 case 0x9a: 579 return ARM_BARRIER_DSB; /* mcr p15,0,Rt,c7,c10,4 */ 580 case 0xba: 581 return ARM_BARRIER_DMB; /* mcr p15,0,Rt,c7,c10,5 */ 582 case 0x95: 583 return ARM_BARRIER_ISB; /* mcr p15,0,Rt,c7,c5,4 */ 584 default: 585 return ARM_BARRIER_NONE; 586 } 587 } else { 588 return ARM_BARRIER_NONE; 589 } 590 } 591 592 arm_barrier_t inst_Thumb_barrier(uint32_t inst) 593 { 594 if ((inst & 0xffffff00) == 0xf3bf8f00) { 595 switch (inst & 0xf0) { 596 case 0x40: 597 return ARM_BARRIER_DSB; 598 case 0x50: 599 return ARM_BARRIER_DMB; 600 case 0x60: 601 return ARM_BARRIER_ISB; 602 default: 603 return ARM_BARRIER_NONE; 604 } 605 } else if ((inst & 0xffff0f00) == 0xee070f00) { 606 /* Thumb2 CP15 barriers are unlikely... 1156T2 only? */ 607 switch (inst & 0xff) { 608 case 0x9a: 609 return ARM_BARRIER_DSB; /* mcr p15,0,Rt,c7,c10,4 */ 610 case 0xba: 611 return ARM_BARRIER_DMB; /* mcr p15,0,Rt,c7,c10,5 */ 612 case 0x95: 613 return ARM_BARRIER_ISB; /* mcr p15,0,Rt,c7,c5,4 */ 614 default: 615 return ARM_BARRIER_NONE; 616 } 617 return ARM_BARRIER_NONE; 618 } else { 619 return ARM_BARRIER_NONE; 620 } 621 } 622 623 arm_barrier_t inst_A64_barrier(uint32_t inst) 624 { 625 if ((inst & 0xfffff09f) == 0xd503309f) { 626 switch (inst & 0x60) { 627 case 0x0: 628 return ARM_BARRIER_DSB; 629 case 0x20: 630 return ARM_BARRIER_DMB; 631 case 0x40: 632 return ARM_BARRIER_ISB; 633 default: 634 return ARM_BARRIER_NONE; 635 } 636 } else { 637 return ARM_BARRIER_NONE; 638 } 639 } 640 641 int inst_ARM_is_UDF(uint32_t inst) 642 { 643 return (inst & 0xfff000f0) == 0xe7f000f0; 644 } 645 646 int inst_Thumb_is_UDF(uint32_t inst) 647 { 648 return (inst & 0xff000000) == 0xde000000 || /* T1 */ 649 (inst & 0xfff0f000) == 0xf7f0a000; /* T2 */ 650 } 651 652 int inst_A64_is_UDF(uint32_t inst) 653 { 654 /* No A64 encodings are formally allocated as permanently undefined, 655 but it is intended not to allocate any instructions in the 21-bit 656 regions at the bottom or top of the range. */ 657 return (inst & 0xffe00000) == 0x00000000 || 658 (inst & 0xffe00000) == 0xffe00000; 659 } 660 661 /* End of File trc_idec_arminst.cpp */ 662