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