1 // Copyright 2015, VIXL authors 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 extern "C" { 28 #include <stdint.h> 29 } 30 31 #include <cassert> 32 #include <cstdio> 33 #include <cstdlib> 34 #include <cstring> 35 #include <iostream> 36 37 #include "utils-vixl.h" 38 #include "aarch32/constants-aarch32.h" 39 #include "aarch32/instructions-aarch32.h" 40 41 namespace vixl { 42 namespace aarch32 { 43 44 45 bool Shift::IsValidAmount(uint32_t amount) const { 46 switch (GetType()) { 47 case LSL: 48 return amount <= 31; 49 case ROR: 50 return (amount > 0) && (amount <= 31); 51 case LSR: 52 case ASR: 53 return (amount > 0) && (amount <= 32); 54 case RRX: 55 return amount == 0; 56 default: 57 VIXL_UNREACHABLE(); 58 return false; 59 } 60 } 61 62 63 std::ostream& operator<<(std::ostream& os, const Register reg) { 64 switch (reg.GetCode()) { 65 case 12: 66 return os << "ip"; 67 case 13: 68 return os << "sp"; 69 case 14: 70 return os << "lr"; 71 case 15: 72 return os << "pc"; 73 default: 74 return os << "r" << reg.GetCode(); 75 } 76 } 77 78 79 SRegister VRegister::S() const { 80 VIXL_ASSERT(GetType() == kSRegister); 81 return SRegister(GetCode()); 82 } 83 84 85 DRegister VRegister::D() const { 86 VIXL_ASSERT(GetType() == kDRegister); 87 return DRegister(GetCode()); 88 } 89 90 91 QRegister VRegister::Q() const { 92 VIXL_ASSERT(GetType() == kQRegister); 93 return QRegister(GetCode()); 94 } 95 96 97 Register RegisterList::GetFirstAvailableRegister() const { 98 for (uint32_t i = 0; i < kNumberOfRegisters; i++) { 99 if (((list_ >> i) & 1) != 0) return Register(i); 100 } 101 return Register(); 102 } 103 104 105 std::ostream& PrintRegisterList(std::ostream& os, // NOLINT(runtime/references) 106 uint32_t list) { 107 os << "{"; 108 bool first = true; 109 int code = 0; 110 while (list != 0) { 111 if ((list & 1) != 0) { 112 if (first) { 113 first = false; 114 } else { 115 os << ","; 116 } 117 os << Register(code); 118 } 119 list >>= 1; 120 code++; 121 } 122 os << "}"; 123 return os; 124 } 125 126 127 std::ostream& operator<<(std::ostream& os, RegisterList registers) { 128 return PrintRegisterList(os, registers.GetList()); 129 } 130 131 132 QRegister VRegisterList::GetFirstAvailableQRegister() const { 133 for (uint32_t i = 0; i < kNumberOfQRegisters; i++) { 134 if (((list_ >> (i * 4)) & 0xf) == 0xf) return QRegister(i); 135 } 136 return QRegister(); 137 } 138 139 140 DRegister VRegisterList::GetFirstAvailableDRegister() const { 141 for (uint32_t i = 0; i < kMaxNumberOfDRegisters; i++) { 142 if (((list_ >> (i * 2)) & 0x3) == 0x3) return DRegister(i); 143 } 144 return DRegister(); 145 } 146 147 148 SRegister VRegisterList::GetFirstAvailableSRegister() const { 149 for (uint32_t i = 0; i < kNumberOfSRegisters; i++) { 150 if (((list_ >> i) & 0x1) != 0) return SRegister(i); 151 } 152 return SRegister(); 153 } 154 155 156 std::ostream& operator<<(std::ostream& os, SRegisterList reglist) { 157 SRegister first = reglist.GetFirstSRegister(); 158 SRegister last = reglist.GetLastSRegister(); 159 if (first.Is(last)) 160 os << "{" << first << "}"; 161 else 162 os << "{" << first << "-" << last << "}"; 163 return os; 164 } 165 166 167 std::ostream& operator<<(std::ostream& os, DRegisterList reglist) { 168 DRegister first = reglist.GetFirstDRegister(); 169 DRegister last = reglist.GetLastDRegister(); 170 if (first.Is(last)) 171 os << "{" << first << "}"; 172 else 173 os << "{" << first << "-" << last << "}"; 174 return os; 175 } 176 177 std::ostream& operator<<(std::ostream& os, NeonRegisterList nreglist) { 178 DRegister first = nreglist.GetFirstDRegister(); 179 int increment = nreglist.IsSingleSpaced() ? 1 : 2; 180 int count = 181 nreglist.GetLastDRegister().GetCode() - first.GetCode() + increment; 182 if (count < 0) count += kMaxNumberOfDRegisters; 183 os << "{"; 184 bool first_displayed = false; 185 for (;;) { 186 if (first_displayed) { 187 os << ","; 188 } else { 189 first_displayed = true; 190 } 191 os << first; 192 if (nreglist.IsTransferOneLane()) { 193 os << "[" << nreglist.GetTransferLane() << "]"; 194 } else if (nreglist.IsTransferAllLanes()) { 195 os << "[]"; 196 } 197 count -= increment; 198 if (count <= 0) break; 199 unsigned next = first.GetCode() + increment; 200 if (next >= kMaxNumberOfDRegisters) next -= kMaxNumberOfDRegisters; 201 first = DRegister(next); 202 } 203 os << "}"; 204 return os; 205 } 206 207 208 const char* SpecialRegister::GetName() const { 209 switch (reg_) { 210 case APSR: 211 return "APSR"; 212 case SPSR: 213 return "SPSR"; 214 } 215 VIXL_UNREACHABLE(); 216 return "??"; 217 } 218 219 220 const char* MaskedSpecialRegister::GetName() const { 221 switch (reg_) { 222 case APSR_nzcvq: 223 return "APSR_nzcvq"; 224 case APSR_g: 225 return "APSR_g"; 226 case APSR_nzcvqg: 227 return "APSR_nzcvqg"; 228 case CPSR_c: 229 return "CPSR_c"; 230 case CPSR_x: 231 return "CPSR_x"; 232 case CPSR_xc: 233 return "CPSR_xc"; 234 case CPSR_sc: 235 return "CPSR_sc"; 236 case CPSR_sx: 237 return "CPSR_sx"; 238 case CPSR_sxc: 239 return "CPSR_sxc"; 240 case CPSR_fc: 241 return "CPSR_fc"; 242 case CPSR_fx: 243 return "CPSR_fx"; 244 case CPSR_fxc: 245 return "CPSR_fxc"; 246 case CPSR_fsc: 247 return "CPSR_fsc"; 248 case CPSR_fsx: 249 return "CPSR_fsx"; 250 case CPSR_fsxc: 251 return "CPSR_fsxc"; 252 case SPSR_c: 253 return "SPSR_c"; 254 case SPSR_x: 255 return "SPSR_x"; 256 case SPSR_xc: 257 return "SPSR_xc"; 258 case SPSR_s: 259 return "SPSR_s"; 260 case SPSR_sc: 261 return "SPSR_sc"; 262 case SPSR_sx: 263 return "SPSR_sx"; 264 case SPSR_sxc: 265 return "SPSR_sxc"; 266 case SPSR_f: 267 return "SPSR_f"; 268 case SPSR_fc: 269 return "SPSR_fc"; 270 case SPSR_fx: 271 return "SPSR_fx"; 272 case SPSR_fxc: 273 return "SPSR_fxc"; 274 case SPSR_fs: 275 return "SPSR_fs"; 276 case SPSR_fsc: 277 return "SPSR_fsc"; 278 case SPSR_fsx: 279 return "SPSR_fsx"; 280 case SPSR_fsxc: 281 return "SPSR_fsxc"; 282 } 283 VIXL_UNREACHABLE(); 284 return "??"; 285 } 286 287 288 const char* BankedRegister::GetName() const { 289 switch (reg_) { 290 case R8_usr: 291 return "R8_usr"; 292 case R9_usr: 293 return "R9_usr"; 294 case R10_usr: 295 return "R10_usr"; 296 case R11_usr: 297 return "R11_usr"; 298 case R12_usr: 299 return "R12_usr"; 300 case SP_usr: 301 return "SP_usr"; 302 case LR_usr: 303 return "LR_usr"; 304 case R8_fiq: 305 return "R8_fiq"; 306 case R9_fiq: 307 return "R9_fiq"; 308 case R10_fiq: 309 return "R10_fiq"; 310 case R11_fiq: 311 return "R11_fiq"; 312 case R12_fiq: 313 return "R12_fiq"; 314 case SP_fiq: 315 return "SP_fiq"; 316 case LR_fiq: 317 return "LR_fiq"; 318 case LR_irq: 319 return "LR_irq"; 320 case SP_irq: 321 return "SP_irq"; 322 case LR_svc: 323 return "LR_svc"; 324 case SP_svc: 325 return "SP_svc"; 326 case LR_abt: 327 return "LR_abt"; 328 case SP_abt: 329 return "SP_abt"; 330 case LR_und: 331 return "LR_und"; 332 case SP_und: 333 return "SP_und"; 334 case LR_mon: 335 return "LR_mon"; 336 case SP_mon: 337 return "SP_mon"; 338 case ELR_hyp: 339 return "ELR_hyp"; 340 case SP_hyp: 341 return "SP_hyp"; 342 case SPSR_fiq: 343 return "SPSR_fiq"; 344 case SPSR_irq: 345 return "SPSR_irq"; 346 case SPSR_svc: 347 return "SPSR_svc"; 348 case SPSR_abt: 349 return "SPSR_abt"; 350 case SPSR_und: 351 return "SPSR_und"; 352 case SPSR_mon: 353 return "SPSR_mon"; 354 case SPSR_hyp: 355 return "SPSR_hyp"; 356 } 357 VIXL_UNREACHABLE(); 358 return "??"; 359 } 360 361 const char* SpecialFPRegister::GetName() const { 362 switch (reg_) { 363 case FPSID: 364 return "FPSID"; 365 case FPSCR: 366 return "FPSCR"; 367 case MVFR2: 368 return "MVFR2"; 369 case MVFR1: 370 return "MVFR1"; 371 case MVFR0: 372 return "MVFR0"; 373 case FPEXC: 374 return "FPEXC"; 375 } 376 VIXL_UNREACHABLE(); 377 return "??"; 378 } 379 380 381 const char* Condition::GetName() const { 382 switch (condition_) { 383 case eq: 384 return "eq"; 385 case ne: 386 return "ne"; 387 case cs: 388 return "cs"; 389 case cc: 390 return "cc"; 391 case mi: 392 return "mi"; 393 case pl: 394 return "pl"; 395 case vs: 396 return "vs"; 397 case vc: 398 return "vc"; 399 case hi: 400 return "hi"; 401 case ls: 402 return "ls"; 403 case ge: 404 return "ge"; 405 case lt: 406 return "lt"; 407 case gt: 408 return "gt"; 409 case le: 410 return "le"; 411 case al: 412 return ""; 413 case Condition::kNone: 414 return ""; 415 } 416 return "<und>"; 417 } 418 419 420 const char* Shift::GetName() const { 421 switch (shift_) { 422 case LSL: 423 return "lsl"; 424 case LSR: 425 return "lsr"; 426 case ASR: 427 return "asr"; 428 case ROR: 429 return "ror"; 430 case RRX: 431 return "rrx"; 432 } 433 VIXL_UNREACHABLE(); 434 return "??"; 435 } 436 437 438 const char* EncodingSize::GetName() const { 439 switch (size_) { 440 case Best: 441 return ""; 442 case Narrow: 443 return ".n"; 444 case Wide: 445 return ".w"; 446 } 447 VIXL_UNREACHABLE(); 448 return "??"; 449 } 450 451 452 const char* DataType::GetName() const { 453 switch (value_) { 454 case kDataTypeValueInvalid: 455 return ".??"; 456 case kDataTypeValueNone: 457 return ""; 458 case S8: 459 return ".s8"; 460 case S16: 461 return ".s16"; 462 case S32: 463 return ".s32"; 464 case S64: 465 return ".s64"; 466 case U8: 467 return ".u8"; 468 case U16: 469 return ".u16"; 470 case U32: 471 return ".u32"; 472 case U64: 473 return ".u64"; 474 case F16: 475 return ".f16"; 476 case F32: 477 return ".f32"; 478 case F64: 479 return ".f64"; 480 case I8: 481 return ".i8"; 482 case I16: 483 return ".i16"; 484 case I32: 485 return ".i32"; 486 case I64: 487 return ".i64"; 488 case P8: 489 return ".p8"; 490 case P64: 491 return ".p64"; 492 case Untyped8: 493 return ".8"; 494 case Untyped16: 495 return ".16"; 496 case Untyped32: 497 return ".32"; 498 case Untyped64: 499 return ".64"; 500 } 501 VIXL_UNREACHABLE(); 502 return ".??"; 503 } 504 505 506 const char* MemoryBarrier::GetName() const { 507 switch (type_) { 508 case OSHLD: 509 return "oshld"; 510 case OSHST: 511 return "oshst"; 512 case OSH: 513 return "osh"; 514 case NSHLD: 515 return "nshld"; 516 case NSHST: 517 return "nshst"; 518 case NSH: 519 return "nsh"; 520 case ISHLD: 521 return "ishld"; 522 case ISHST: 523 return "ishst"; 524 case ISH: 525 return "ish"; 526 case LD: 527 return "ld"; 528 case ST: 529 return "st"; 530 case SY: 531 return "sy"; 532 } 533 switch (static_cast<int>(type_)) { 534 case 0: 535 return "#0x0"; 536 case 4: 537 return "#0x4"; 538 case 8: 539 return "#0x8"; 540 case 0xc: 541 return "#0xc"; 542 } 543 VIXL_UNREACHABLE(); 544 return "??"; 545 } 546 547 548 const char* InterruptFlags::GetName() const { 549 switch (type_) { 550 case F: 551 return "f"; 552 case I: 553 return "i"; 554 case IF: 555 return "if"; 556 case A: 557 return "a"; 558 case AF: 559 return "af"; 560 case AI: 561 return "ai"; 562 case AIF: 563 return "aif"; 564 } 565 VIXL_ASSERT(type_ == 0); 566 return ""; 567 } 568 569 570 const char* Endianness::GetName() const { 571 switch (type_) { 572 case LE: 573 return "le"; 574 case BE: 575 return "be"; 576 } 577 VIXL_UNREACHABLE(); 578 return "??"; 579 } 580 581 582 // Constructor used for disassembly. 583 ImmediateShiftOperand::ImmediateShiftOperand(int shift_value, int amount_value) 584 : Shift(shift_value) { 585 switch (shift_value) { 586 case LSL: 587 amount_ = amount_value; 588 break; 589 case LSR: 590 case ASR: 591 amount_ = (amount_value == 0) ? 32 : amount_value; 592 break; 593 case ROR: 594 amount_ = amount_value; 595 if (amount_value == 0) SetType(RRX); 596 break; 597 default: 598 VIXL_UNREACHABLE(); 599 SetType(LSL); 600 amount_ = 0; 601 break; 602 } 603 } 604 605 606 ImmediateT32::ImmediateT32(uint32_t imm) { 607 // 00000000 00000000 00000000 abcdefgh 608 if ((imm & ~0xff) == 0) { 609 SetEncodingValue(imm); 610 return; 611 } 612 if ((imm >> 16) == (imm & 0xffff)) { 613 if ((imm & 0xff00) == 0) { 614 // 00000000 abcdefgh 00000000 abcdefgh 615 SetEncodingValue((imm & 0xff) | (0x1 << 8)); 616 return; 617 } 618 if ((imm & 0xff) == 0) { 619 // abcdefgh 00000000 abcdefgh 00000000 620 SetEncodingValue(((imm >> 8) & 0xff) | (0x2 << 8)); 621 return; 622 } 623 if (((imm >> 8) & 0xff) == (imm & 0xff)) { 624 // abcdefgh abcdefgh abcdefgh abcdefgh 625 SetEncodingValue((imm & 0xff) | (0x3 << 8)); 626 return; 627 } 628 } 629 for (int shift = 0; shift < 24; shift++) { 630 uint32_t imm8 = imm >> (24 - shift); 631 uint32_t overflow = imm << (8 + shift); 632 if ((imm8 <= 0xff) && ((imm8 & 0x80) != 0) && (overflow == 0)) { 633 SetEncodingValue(((shift + 8) << 7) | (imm8 & 0x7F)); 634 return; 635 } 636 } 637 } 638 639 640 static inline uint32_t ror(uint32_t x, int i) { 641 VIXL_ASSERT((0 < i) && (i < 32)); 642 return (x >> i) | (x << (32 - i)); 643 } 644 645 646 bool ImmediateT32::IsImmediateT32(uint32_t imm) { 647 /* abcdefgh abcdefgh abcdefgh abcdefgh */ 648 if ((imm ^ ror(imm, 8)) == 0) return true; 649 /* 00000000 abcdefgh 00000000 abcdefgh */ 650 /* abcdefgh 00000000 abcdefgh 00000000 */ 651 if ((imm ^ ror(imm, 16)) == 0 && 652 (((imm & 0xff00) == 0) || ((imm & 0xff) == 0))) 653 return true; 654 /* isolate least-significant set bit */ 655 uint32_t lsb = imm & -imm; 656 /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to 657 * avoid overflow (underflow is always a successful case) */ 658 return ((imm >> 8) < lsb); 659 } 660 661 662 uint32_t ImmediateT32::Decode(uint32_t value) { 663 uint32_t base = value & 0xff; 664 switch (value >> 8) { 665 case 0: 666 return base; 667 case 1: 668 return base | (base << 16); 669 case 2: 670 return (base << 8) | (base << 24); 671 case 3: 672 return base | (base << 8) | (base << 16) | (base << 24); 673 default: 674 base |= 0x80; 675 return base << (32 - (value >> 7)); 676 } 677 } 678 679 680 ImmediateA32::ImmediateA32(uint32_t imm) { 681 // Deal with rot = 0 first to avoid undefined shift by 32. 682 if (imm <= 0xff) { 683 SetEncodingValue(imm); 684 return; 685 } 686 for (int rot = 2; rot < 32; rot += 2) { 687 uint32_t imm8 = (imm << rot) | (imm >> (32 - rot)); 688 if (imm8 <= 0xff) { 689 SetEncodingValue((rot << 7) | imm8); 690 return; 691 } 692 } 693 } 694 695 696 bool ImmediateA32::IsImmediateA32(uint32_t imm) { 697 /* fast-out */ 698 if (imm < 256) return true; 699 /* avoid getting confused by wrapped-around bytes (this transform has no 700 * effect on pass/fail results) */ 701 if (imm & 0xff000000) imm = ror(imm, 16); 702 /* copy odd-numbered set bits into even-numbered bits immediately below, so 703 * that the least-significant set bit is always an even bit */ 704 imm = imm | ((imm >> 1) & 0x55555555); 705 /* isolate least-significant set bit (always even) */ 706 uint32_t lsb = imm & -imm; 707 /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to 708 * avoid overflow (underflow is always a successful case) */ 709 return ((imm >> 8) < lsb); 710 } 711 712 713 uint32_t ImmediateA32::Decode(uint32_t value) { 714 int rotation = (value >> 8) * 2; 715 VIXL_ASSERT(rotation >= 0); 716 VIXL_ASSERT(rotation <= 30); 717 value &= 0xff; 718 if (rotation == 0) return value; 719 return (value >> rotation) | (value << (32 - rotation)); 720 } 721 722 723 uint32_t TypeEncodingValue(Shift shift) { 724 return shift.IsRRX() ? kRRXEncodedValue : shift.GetValue(); 725 } 726 727 728 uint32_t AmountEncodingValue(Shift shift, uint32_t amount) { 729 switch (shift.GetType()) { 730 case LSL: 731 case ROR: 732 return amount; 733 case LSR: 734 case ASR: 735 return amount % 32; 736 case RRX: 737 return 0; 738 } 739 return 0; 740 } 741 742 } // namespace aarch32 743 } // namespace vixl 744