KittyAsm.cpp
1 #include "KittyAsm.hpp" 2 3 // refs to 4 // https://github.com/CAS-Atlantic/AArch64-Encoding 5 // https://github.com/bminor/binutils-gdb 6 // https://github.com/capstone-engine/capstone 7 // https://github.com/qemu/QEMU 8 // https://reverseengineering.stackexchange.com/questions/15418/getting-function-address-by-reading-adrp-and-add-instruction-values 9 // https://stackoverflow.com/questions/41906688/what-are-the-semantics-of-adrp-and-adrl-instructions-in-arm-assembly 10 11 namespace KittyAsm 12 { 13 uint32_t bits(uint32_t v, int hi, int lo) 14 { 15 if (hi < lo) 16 return 0u; 17 18 int width = hi - lo + 1; 19 if (width >= 32) 20 return v >> lo; 21 22 uint32_t mask = (width == 32) ? 0xFFFFFFFFu : ((1u << width) - 1u); 23 return (v >> lo) & mask; 24 } 25 } // namespace KittyAsm 26 27 using namespace KittyAsm; 28 29 namespace KittyArm32 30 { 31 EKittyInsnTypeArm32 decodeInsnType(uint32_t instr) 32 { 33 if ((instr & 0x0C000000) == 0x00000000) 34 { 35 if ((instr & 0x01E00000) == 0x00800000) 36 return bits(instr, 19, 16) == 15 ? EKittyInsnTypeArm32::ADR : EKittyInsnTypeArm32::ADD; 37 38 if ((instr & 0x01E00000) == 0x00400000) 39 return bits(instr, 19, 16) == 15 ? EKittyInsnTypeArm32::ADR : EKittyInsnTypeArm32::SUB; 40 41 if ((instr & 0x01E00000) == 0x01A00000) 42 return EKittyInsnTypeArm32::MOV; 43 } 44 45 if ((instr & 0x0FF00000) == 0x02800000) 46 return EKittyInsnTypeArm32::LDR_LITERAL; 47 48 if ((instr & 0x0C500000) == 0x04100000) 49 return bits(instr, 19, 16) == 15 ? EKittyInsnTypeArm32::LDR_LITERAL : EKittyInsnTypeArm32::LDR; 50 51 if ((instr & 0x0C500000) == 0x04000000) 52 return EKittyInsnTypeArm32::STR; 53 54 if ((instr & 0x0C500000) == 0x04500000) 55 return bits(instr, 19, 16) == 15 ? EKittyInsnTypeArm32::LDR_LITERAL : EKittyInsnTypeArm32::LDRB; 56 57 if ((instr & 0x0C500000) == 0x04400000) 58 return EKittyInsnTypeArm32::STRB; 59 60 if ((instr & 0x0F1000F0) == 0x011000B0) 61 return EKittyInsnTypeArm32::LDRH; 62 63 if ((instr & 0x0F1000F0) == 0x010000B0) 64 return EKittyInsnTypeArm32::STRH; 65 66 if ((instr & 0x0F1000F0) == 0x011000D0) 67 return EKittyInsnTypeArm32::LDRSB; 68 69 if ((instr & 0x0F1000F0) == 0x011000F0) 70 return EKittyInsnTypeArm32::LDRSH; 71 72 if ((instr & 0x0F000000) == 0x0A000000) 73 return bits(instr, 31, 28) == 0xE ? EKittyInsnTypeArm32::B : EKittyInsnTypeArm32::B_COND; 74 75 if ((instr & 0x0F000000) == 0x0B000000) 76 return EKittyInsnTypeArm32::BL; 77 78 return EKittyInsnTypeArm32::UNKNOWN; 79 } 80 81 KittyInsnArm32 decodeInsn(uint32_t instr, uint32_t address) 82 { 83 KittyInsnArm32 insn{}; 84 85 EKittyInsnTypeArm32 insn_type = decodeInsnType(instr); 86 if (insn_type == EKittyInsnTypeArm32::UNKNOWN) 87 return insn; 88 89 insn.bytes = instr; 90 insn.address = address; 91 insn.type = insn_type; 92 insn.typeStr = typeToString(insn_type); 93 94 switch (insn_type) 95 { 96 case EKittyInsnTypeArm32::UNKNOWN: 97 return insn; 98 99 case EKittyInsnTypeArm32::ADD: 100 case EKittyInsnTypeArm32::SUB: 101 case EKittyInsnTypeArm32::MOV: 102 case EKittyInsnTypeArm32::ADR: 103 { 104 bool I = bit(instr, 25); 105 uint32_t rn = bits(instr, 19, 16); 106 uint32_t rd = bits(instr, 15, 12); 107 uint32_t imm12 = bits(instr, 11, 0); 108 uint32_t imm8 = bits(imm12, 7, 0); 109 uint32_t rot = bits(imm12, 11, 8) * 2u; 110 uint32_t imm32 = ror32(imm8, rot); 111 insn.rd = regName(rd); 112 113 if (insn_type != EKittyInsnTypeArm32::MOV) 114 insn.rn = regName(rn); 115 116 if (!I) 117 insn.rt = regName(imm12); 118 else 119 insn.immediate = I ? imm32 : 0; 120 121 if (rn == 15) 122 insn.target = address + 8u + insn.immediate; 123 124 break; 125 } 126 127 case EKittyInsnTypeArm32::LDRH: 128 case EKittyInsnTypeArm32::LDRSH: 129 case EKittyInsnTypeArm32::LDRSB: 130 case EKittyInsnTypeArm32::STRH: 131 { 132 bool U = bit(instr, 23); 133 uint32_t rn = bits(instr, 19, 16); 134 uint32_t rd = bits(instr, 15, 12); 135 uint32_t immH = bits(instr, 11, 8); 136 uint32_t immL = bits(instr, 3, 0); 137 uint32_t offset = (immH << 4) | immL; 138 insn.rd = regName(rd); 139 insn.rn = regName(rn); 140 insn.immediate = U ? offset : -((int32_t)offset); 141 break; 142 } 143 144 case EKittyInsnTypeArm32::LDR: 145 case EKittyInsnTypeArm32::LDRB: 146 case EKittyInsnTypeArm32::STR: 147 case EKittyInsnTypeArm32::STRB: 148 case EKittyInsnTypeArm32::LDR_LITERAL: 149 { 150 bool U = bit(instr, 23); 151 uint32_t rn = bits(instr, 19, 16); 152 uint32_t rd = bits(instr, 15, 12); 153 uint32_t imm12 = bits(instr, 11, 0); 154 insn.rd = regName(rd); 155 insn.rn = regName(rn); 156 insn.immediate = U ? imm12 : -((int32_t)imm12); 157 // PC 158 if (rn == 15) 159 { 160 insn.target = address + 8u + insn.immediate; 161 } 162 break; 163 } 164 165 case EKittyInsnTypeArm32::B: 166 case EKittyInsnTypeArm32::BL: 167 case EKittyInsnTypeArm32::B_COND: 168 { 169 uint32_t cond = bits(instr, 31, 28); 170 uint32_t imm24 = bits(instr, 23, 0); 171 int32_t simm = signExtend(imm24, 24) << 2; 172 insn.immediate = simm; 173 insn.target = address + 8u + simm; 174 if (insn_type == EKittyInsnTypeArm32::B_COND) 175 { 176 insn.cond = branchCondName(cond); 177 } 178 break; 179 } 180 } 181 182 return insn; 183 } 184 185 std::string typeToString(EKittyInsnTypeArm32 t) 186 { 187 #define CASE(x) \ 188 case EKittyInsnTypeArm32::x: \ 189 return #x; 190 switch (t) 191 { 192 CASE(UNKNOWN) 193 CASE(ADR) 194 CASE(ADD) 195 CASE(SUB) 196 CASE(MOV) 197 CASE(LDR) 198 CASE(STR) 199 CASE(LDRB) 200 CASE(STRB) 201 CASE(LDRH) 202 CASE(STRH) 203 CASE(LDRSH) 204 CASE(LDRSB) 205 CASE(LDR_LITERAL) 206 CASE(B) 207 CASE(BL) 208 CASE(B_COND) 209 } 210 #undef CASE 211 return "UNKNOWN"; 212 } 213 } // namespace KittyArm32 214 215 namespace KittyArm64 216 { 217 EKittyInsnTypeArm64 decodeInsnType(uint32_t instr) 218 { 219 // ADR 220 if ((instr & 0x9F000000u) == 0x10000000u) 221 { 222 return EKittyInsnTypeArm64::ADR; 223 } 224 // ADRP 225 if ((instr & 0x9F000000u) == 0x90000000u) 226 { 227 return EKittyInsnTypeArm64::ADRP; 228 } 229 230 // ADD 231 if ((instr & 0xFF000000u) == 0x11000000u || (instr & 0xFF000000u) == 0x91000000u) 232 { 233 return EKittyInsnTypeArm64::ADD; 234 } 235 // SUB 236 if ((instr & 0xFF000000u) == 0x51000000u || (instr & 0xFF000000u) == 0xD1000000u) 237 { 238 return EKittyInsnTypeArm64::SUB; 239 } 240 241 // MOVZ 242 if ((instr & 0x7F800000u) == 0x52800000u) 243 { 244 return EKittyInsnTypeArm64::MOVZ; 245 } 246 // MOVK 247 if ((instr & 0x7F800000u) == 0x72800000u) 248 { 249 return EKittyInsnTypeArm64::MOVK; 250 } 251 // MOVN 252 if ((instr & 0x7F800000u) == 0x12800000u) 253 { 254 return EKittyInsnTypeArm64::MOVN; 255 } 256 257 // Load/Store (immediate offset) 258 { 259 if ((instr & 0xFFC00000) == 0xF9400000) 260 return EKittyInsnTypeArm64::LDR; 261 if ((instr & 0xFFC00000) == 0xF9000000) 262 return EKittyInsnTypeArm64::STR; 263 if ((instr & 0xFFC00000) == 0xB9400000) 264 return EKittyInsnTypeArm64::LDRW; 265 if ((instr & 0xFFC00000) == 0xB9000000) 266 return EKittyInsnTypeArm64::STRW; 267 268 if ((instr & 0xFFC00000) == 0x39400000) 269 return EKittyInsnTypeArm64::LDRB; 270 if ((instr & 0xFFC00000) == 0x39000000) 271 return EKittyInsnTypeArm64::STRB; 272 273 if ((instr & 0xFFC00000) == 0x79400000) 274 return EKittyInsnTypeArm64::LDRH; 275 if ((instr & 0xFFC00000) == 0x79000000) 276 return EKittyInsnTypeArm64::STRH; 277 278 if ((instr & 0xFFC00000) == 0x39C00000 || (instr & 0xFFC00000) == 0x39800000) 279 return EKittyInsnTypeArm64::LDRSB; 280 if ((instr & 0xFFC00000) == 0x79C00000 || (instr & 0xFFC00000) == 0x79800000) 281 return EKittyInsnTypeArm64::LDRSH; 282 if ((instr & 0xFFC00000) == 0xB9800000) 283 return EKittyInsnTypeArm64::LDRSW; 284 } 285 286 // Load/Store (post-indexed) 287 { 288 if ((instr & 0xFFC00C00) == 0xB8400400 || (instr & 0xFFC00C00) == 0xF8400400) 289 return EKittyInsnTypeArm64::LDR_POST; 290 if ((instr & 0xFFC00C00) == 0xB8000400 || (instr & 0xFFC00C00) == 0xF8000400) 291 return EKittyInsnTypeArm64::STR_POST; 292 293 if ((instr & 0xFFC00C00) == 0x38400400) 294 return EKittyInsnTypeArm64::LDRB_POST; 295 if ((instr & 0xFFC00C00) == 0x38000400) 296 return EKittyInsnTypeArm64::STRB_POST; 297 298 if ((instr & 0xFFC00C00) == 0x78400400) 299 return EKittyInsnTypeArm64::LDRH_POST; 300 if ((instr & 0xFFC00C00) == 0x78000400) 301 return EKittyInsnTypeArm64::STRH_POST; 302 303 if ((instr & 0xFFC00C00) == 0x38C00400 || (instr & 0xFFC00C00) == 0x38800400) 304 return EKittyInsnTypeArm64::LDRSB_POST; 305 if ((instr & 0xFFC00C00) == 0x78C00400 || (instr & 0xFFC00C00) == 0x78800400) 306 return EKittyInsnTypeArm64::LDRSH_POST; 307 if ((instr & 0xFFC00C00) == 0xB8800400) 308 return EKittyInsnTypeArm64::LDRSW_POST; 309 } 310 311 // Load/Store (pre-indexed) 312 { 313 if ((instr & 0xFFC00C00) == 0xB8400C00 || (instr & 0xFFC00C00) == 0xF8400C00) 314 return EKittyInsnTypeArm64::LDR_PRE; 315 if ((instr & 0xFFC00C00) == 0xB8000C00 || (instr & 0xFFC00C00) == 0xF8000C00) 316 return EKittyInsnTypeArm64::STR_PRE; 317 318 if ((instr & 0xFFC00C00) == 0x38400C00) 319 return EKittyInsnTypeArm64::LDRB_PRE; 320 if ((instr & 0xFFC00C00) == 0x38000C00) 321 return EKittyInsnTypeArm64::STRB_PRE; 322 323 if ((instr & 0xFFC00C00) == 0x78400C00) 324 return EKittyInsnTypeArm64::LDRH_PRE; 325 if ((instr & 0xFFC00C00) == 0x78000C00) 326 return EKittyInsnTypeArm64::STRH_PRE; 327 328 if ((instr & 0xFFC00C00) == 0x38C00C00 || (instr & 0xFFC00C00) == 0x38800C00) 329 return EKittyInsnTypeArm64::LDRSB_PRE; 330 if ((instr & 0xFFC00C00) == 0x78C00C00 || (instr & 0xFFC00C00) == 0x78800C00) 331 return EKittyInsnTypeArm64::LDRSH_PRE; 332 if ((instr & 0xFFC00C00) == 0xB8800C00) 333 return EKittyInsnTypeArm64::LDRSW_PRE; 334 } 335 336 // === Load/Store (unscaled) 337 { 338 if ((instr & 0xFFC00000) == 0xF8400000) 339 return EKittyInsnTypeArm64::LDUR; 340 if ((instr & 0xFFC00000) == 0xF8000000) 341 return EKittyInsnTypeArm64::STUR; 342 if ((instr & 0xFFC00000) == 0xB8400000) 343 return EKittyInsnTypeArm64::LDURW; 344 if ((instr & 0xFFC00000) == 0xB8000000) 345 return EKittyInsnTypeArm64::STURW; 346 if ((instr & 0xFFC00000) == 0x38400000) 347 return EKittyInsnTypeArm64::LDURB; 348 if ((instr & 0xFFC00000) == 0x38000000) 349 return EKittyInsnTypeArm64::STURB; 350 if ((instr & 0xFFC00000) == 0x78400000) 351 return EKittyInsnTypeArm64::LDURH; 352 if ((instr & 0xFFC00000) == 0x78000000) 353 return EKittyInsnTypeArm64::STURH; 354 if ((instr & 0xFFC00000) == 0xB8800000) 355 return EKittyInsnTypeArm64::LDURSW; 356 if ((instr & 0xFFC00000) == 0x38800000u || (instr & 0xFFC00000) == 0x38C00000u) 357 return EKittyInsnTypeArm64::LDURSB; 358 if ((instr & 0xFFC00000) == 0x78800000u || (instr & 0xFFC00000) == 0x78C00000u) 359 return EKittyInsnTypeArm64::LDURSH; 360 } 361 362 // Load/Store (Literal) 363 { 364 if ((instr & 0xFFC00000) == 0x18000000) 365 return EKittyInsnTypeArm64::LDRW_LITERAL; 366 if ((instr & 0xFFC00000) == 0x58000000) 367 return EKittyInsnTypeArm64::LDR_LITERAL; 368 if ((instr & 0xFFC00000) == 0x98000000) 369 return EKittyInsnTypeArm64::LDRSW_LITERAL; 370 } 371 372 // B 373 if ((instr & 0xFC000000u) == 0x14000000u) 374 { 375 return EKittyInsnTypeArm64::B; 376 } 377 378 // BL 379 if ((instr & 0xFC000000u) == 0x94000000u) 380 { 381 return EKittyInsnTypeArm64::BL; 382 } 383 384 // B.Cond 385 if ((instr & 0xFF000010u) == 0x54000000u) 386 { 387 return EKittyInsnTypeArm64::B_COND; 388 } 389 390 // CBZ/CBNZ 391 { 392 if ((instr & 0x7F000000u) == 0x34000000u) 393 return EKittyInsnTypeArm64::CBZ; 394 if ((instr & 0x7F000000u) == 0x35000000u) 395 return EKittyInsnTypeArm64::CBNZ; 396 } 397 398 // TBZ/TBNZ 399 { 400 if ((instr & 0x7F000000u) == 0x36000000u) 401 return EKittyInsnTypeArm64::TBZ; 402 if ((instr & 0x7F000000u) == 0x37000000u) 403 return EKittyInsnTypeArm64::TBNZ; 404 } 405 406 return EKittyInsnTypeArm64::UNKNOWN; 407 } 408 409 KittyInsnArm64 decodeInsn(uint32_t instr, uint64_t address) 410 { 411 KittyInsnArm64 insn{}; 412 413 EKittyInsnTypeArm64 insn_type = decodeInsnType(instr); 414 if (insn_type == EKittyInsnTypeArm64::UNKNOWN) 415 return insn; 416 417 insn.bytes = instr; 418 insn.address = address; 419 insn.type = insn_type; 420 insn.typeStr = typeToString(insn_type); 421 422 switch (insn_type) 423 { 424 case EKittyInsnTypeArm64::UNKNOWN: 425 return insn; 426 427 case EKittyInsnTypeArm64::ADR: 428 case EKittyInsnTypeArm64::ADRP: 429 { 430 uint32_t rd = bits(instr, 4, 0); 431 uint32_t immlo = bits(instr, 30, 29); 432 uint32_t immhi = bits(instr, 23, 5); 433 uint64_t imm = (uint64_t)((immhi << 2) | immlo); 434 insn.rd = xRegName(rd, false); 435 if (insn_type == EKittyInsnTypeArm64::ADR) 436 { 437 438 int64_t simm = signExtend(imm, 21); 439 insn.immediate = simm; 440 insn.target = address + simm; 441 } 442 else 443 { 444 int64_t simm = signExtend(imm, 21) << 12; 445 insn.immediate = simm; 446 insn.target = (address & ~0xFFFULL) + simm; 447 } 448 break; 449 } 450 451 case EKittyInsnTypeArm64::MOVZ: 452 case EKittyInsnTypeArm64::MOVK: 453 case EKittyInsnTypeArm64::MOVN: 454 { 455 bool is64 = bit(instr, 31); 456 uint32_t rd = bits(instr, 4, 0); 457 uint32_t imm16 = bits(instr, 20, 5); 458 uint32_t hw = bits(instr, 22, 21); 459 uint64_t imm = (uint64_t)(imm16 << (hw * 16)); 460 insn.rd = is64 ? xRegName(rd, false) : wRegName(rd, false); 461 insn.immediate = insn_type != EKittyInsnTypeArm64::MOVN ? imm : (int64_t)~imm; 462 break; 463 } 464 465 case EKittyInsnTypeArm64::ADD: 466 case EKittyInsnTypeArm64::SUB: 467 { 468 bool is64 = bit(instr, 31); 469 uint32_t rd = bits(instr, 4, 0); 470 uint32_t rn = bits(instr, 9, 5); 471 uint32_t imm12 = bits(instr, 21, 10); 472 uint32_t sh = bits(instr, 23, 22); 473 uint64_t imm = (uint64_t)(sh == 1 ? imm12 << 12 : imm12); 474 insn.rd = is64 ? xRegName(rd, false) : wRegName(rd, false); 475 insn.rn = is64 ? xRegName(rn, true) : wRegName(rn, true); 476 insn.immediate = imm; 477 break; 478 } 479 480 // ldr/str uimm12 481 case EKittyInsnTypeArm64::LDR: 482 case EKittyInsnTypeArm64::STR: 483 case EKittyInsnTypeArm64::LDRW: 484 case EKittyInsnTypeArm64::STRW: 485 case EKittyInsnTypeArm64::LDRB: 486 case EKittyInsnTypeArm64::STRB: 487 case EKittyInsnTypeArm64::LDRH: 488 case EKittyInsnTypeArm64::STRH: 489 case EKittyInsnTypeArm64::LDRSB: 490 case EKittyInsnTypeArm64::LDRSH: 491 case EKittyInsnTypeArm64::LDRSW: 492 { 493 uint32_t size = bits(instr, 31, 30); 494 uint32_t rn = bits(instr, 9, 5); 495 uint32_t rt = bits(instr, 4, 0); 496 uint32_t imm12 = bits(instr, 21, 10); 497 uint64_t offset = (uint64_t)(imm12 << size); 498 insn.rn = xRegName(rn, true); 499 insn.rt = size == 3 ? xRegName(rt, false) : wRegName(rt, false); 500 insn.immediate = offset; 501 break; 502 } 503 504 // ldr/str post/pre indexed imm9 505 case EKittyInsnTypeArm64::LDR_PRE: 506 case EKittyInsnTypeArm64::STR_PRE: 507 case EKittyInsnTypeArm64::LDRB_PRE: 508 case EKittyInsnTypeArm64::STRB_PRE: 509 case EKittyInsnTypeArm64::LDRH_PRE: 510 case EKittyInsnTypeArm64::STRH_PRE: 511 case EKittyInsnTypeArm64::LDRSB_PRE: 512 case EKittyInsnTypeArm64::LDRSH_PRE: 513 case EKittyInsnTypeArm64::LDRSW_PRE: 514 case EKittyInsnTypeArm64::LDR_POST: 515 case EKittyInsnTypeArm64::STR_POST: 516 case EKittyInsnTypeArm64::LDRB_POST: 517 case EKittyInsnTypeArm64::STRB_POST: 518 case EKittyInsnTypeArm64::LDRH_POST: 519 case EKittyInsnTypeArm64::STRH_POST: 520 case EKittyInsnTypeArm64::LDRSB_POST: 521 case EKittyInsnTypeArm64::LDRSH_POST: 522 case EKittyInsnTypeArm64::LDRSW_POST: 523 { 524 uint32_t size = bits(instr, 31, 30); 525 uint32_t rn = bits(instr, 9, 5); 526 uint32_t rt = bits(instr, 4, 0); 527 uint32_t imm9 = bits(instr, 20, 12); 528 int64_t simm = signExtend(imm9, 9); 529 insn.rn = xRegName(rn, true); 530 insn.rt = size == 3 ? xRegName(rt, false) : wRegName(rt, false); 531 insn.immediate = simm; 532 break; 533 } 534 535 // imm9 unscaled ldr/str 536 case EKittyInsnTypeArm64::LDUR: 537 case EKittyInsnTypeArm64::STUR: 538 case EKittyInsnTypeArm64::LDURW: 539 case EKittyInsnTypeArm64::STURW: 540 case EKittyInsnTypeArm64::LDURB: 541 case EKittyInsnTypeArm64::STURB: 542 case EKittyInsnTypeArm64::LDURH: 543 case EKittyInsnTypeArm64::STURH: 544 case EKittyInsnTypeArm64::LDURSB: 545 case EKittyInsnTypeArm64::LDURSH: 546 case EKittyInsnTypeArm64::LDURSW: 547 { 548 uint32_t size = bits(instr, 31, 30); 549 uint32_t rn = bits(instr, 9, 5); 550 uint32_t rt = bits(instr, 4, 0); 551 uint32_t imm9 = bits(instr, 20, 12); 552 int64_t simm = signExtend(imm9, 9); 553 insn.rn = xRegName(rn, true); 554 insn.rt = size == 3 ? xRegName(rt, false) : wRegName(rt, false); 555 insn.immediate = simm; 556 break; 557 } 558 559 case EKittyInsnTypeArm64::LDR_LITERAL: 560 case EKittyInsnTypeArm64::LDRW_LITERAL: 561 case EKittyInsnTypeArm64::LDRSW_LITERAL: 562 { 563 uint32_t size = bits(instr, 31, 30); 564 uint32_t rt = bits(instr, 4, 0); 565 uint32_t imm19 = bits(instr, 23, 5); 566 int64_t simm = signExtend(imm19, 19) << 2; 567 insn.rn = "PC"; 568 insn.rt = size == 3 ? xRegName(rt, false) : wRegName(rt, false); 569 insn.immediate = simm; 570 insn.target = address + simm; 571 break; 572 } 573 574 case EKittyInsnTypeArm64::B: 575 case EKittyInsnTypeArm64::BL: 576 { 577 uint32_t imm26 = bits(instr, 25, 0); 578 int64_t simm = signExtend(imm26, 26) << 2; 579 insn.immediate = simm; 580 insn.target = address + simm; 581 break; 582 } 583 584 case EKittyInsnTypeArm64::B_COND: 585 { 586 uint32_t cond = bits(instr, 3, 0); 587 uint32_t imm19 = bits(instr, 23, 5); 588 int64_t simm = signExtend(imm19, 19) << 2; 589 insn.immediate = simm; 590 insn.target = address + simm; 591 insn.cond = branchCondName(cond); 592 break; 593 } 594 595 case EKittyInsnTypeArm64::CBZ: 596 case EKittyInsnTypeArm64::CBNZ: 597 { 598 bool is64 = bit(instr, 32); 599 uint32_t imm19 = bits(instr, 23, 5); 600 uint32_t rt = bits(instr, 4, 0); 601 int64_t simm = signExtend(imm19, 19) << 2; 602 insn.rt = is64 ? xRegName(rt, false) : wRegName(rt, false); 603 insn.immediate = simm; 604 insn.target = address + simm; 605 break; 606 } 607 608 case EKittyInsnTypeArm64::TBZ: 609 case EKittyInsnTypeArm64::TBNZ: 610 { 611 bool is64 = bit(instr, 32); 612 uint32_t rt = bits(instr, 4, 0); 613 uint32_t bit5 = (bits(instr, 31, 31) & 1) << 5; 614 uint32_t bit_lo = bits(instr, 23, 19); 615 uint32_t bitpos = bit5 | bit_lo; 616 uint32_t imm14 = bits(instr, 18, 5); 617 int64_t simm = signExtend(imm14, 14) << 2; 618 insn.rt = is64 ? xRegName(rt, false) : wRegName(rt, false); 619 insn.immediate = simm; 620 insn.bitpos = bitpos; 621 insn.target = address + simm; 622 break; 623 } 624 } 625 626 return insn; 627 } 628 629 std::string typeToString(EKittyInsnTypeArm64 t) 630 { 631 #define CASE(x) \ 632 case EKittyInsnTypeArm64::x: \ 633 return #x; 634 switch (t) 635 { 636 CASE(UNKNOWN) 637 CASE(ADR) 638 CASE(ADRP) 639 CASE(ADD) 640 CASE(SUB) 641 CASE(MOVZ) 642 CASE(MOVN) 643 CASE(MOVK) 644 CASE(LDR) 645 CASE(STR) 646 CASE(LDRW) 647 CASE(STRW) 648 CASE(LDRB) 649 CASE(STRB) 650 CASE(LDRH) 651 CASE(STRH) 652 CASE(LDRSB) 653 CASE(LDRSH) 654 CASE(LDRSW) 655 CASE(LDR_PRE) 656 CASE(STR_PRE) 657 CASE(LDRB_PRE) 658 CASE(STRB_PRE) 659 CASE(LDRH_PRE) 660 CASE(STRH_PRE) 661 CASE(LDRSB_PRE) 662 CASE(LDRSH_PRE) 663 CASE(LDRSW_PRE) 664 CASE(LDR_POST) 665 CASE(STR_POST) 666 CASE(LDRB_POST) 667 CASE(STRB_POST) 668 CASE(LDRH_POST) 669 CASE(STRH_POST) 670 CASE(LDRSB_POST) 671 CASE(LDRSH_POST) 672 CASE(LDRSW_POST) 673 CASE(LDUR) 674 CASE(STUR) 675 CASE(LDURW) 676 CASE(STURW) 677 CASE(LDURB) 678 CASE(STURB) 679 CASE(LDURH) 680 CASE(STURH) 681 CASE(LDURSB) 682 CASE(LDURSH) 683 CASE(LDURSW) 684 CASE(LDR_LITERAL) 685 CASE(LDRW_LITERAL) 686 CASE(LDRSW_LITERAL) 687 CASE(B) 688 CASE(BL) 689 CASE(B_COND) 690 CASE(CBZ) 691 CASE(CBNZ) 692 CASE(TBZ) 693 CASE(TBNZ) 694 } 695 #undef CASE 696 return "UNKNOWN"; 697 } 698 } // namespace KittyArm64