1// Copyright 2017, 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 27extern "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 41namespace vixl { 42namespace aarch32 { 43 44 45bool 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 63std::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 79SRegister VRegister::S() const { 80 VIXL_ASSERT(GetType() == kSRegister); 81 return SRegister(GetCode()); 82} 83 84 85DRegister VRegister::D() const { 86 VIXL_ASSERT(GetType() == kDRegister); 87 return DRegister(GetCode()); 88} 89 90 91QRegister VRegister::Q() const { 92 VIXL_ASSERT(GetType() == kQRegister); 93 return QRegister(GetCode()); 94} 95 96 97Register 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 105std::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 127std::ostream& operator<<(std::ostream& os, RegisterList registers) { 128 return PrintRegisterList(os, registers.GetList()); 129} 130 131 132QRegister 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 140DRegister 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 148SRegister 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 156std::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 167std::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 177std::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 208const 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 220const 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 288const 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 361const 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 381const 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 420const 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 438const char* EncodingSize::GetName() const { 439 switch (size_) { 440 case Best: 441 case Narrow: 442 return ""; 443 case Wide: 444 return ".w"; 445 } 446 VIXL_UNREACHABLE(); 447 return "??"; 448} 449 450 451const char* DataType::GetName() const { 452 switch (value_) { 453 case kDataTypeValueInvalid: 454 return ".??"; 455 case kDataTypeValueNone: 456 return ""; 457 case S8: 458 return ".s8"; 459 case S16: 460 return ".s16"; 461 case S32: 462 return ".s32"; 463 case S64: 464 return ".s64"; 465 case U8: 466 return ".u8"; 467 case U16: 468 return ".u16"; 469 case U32: 470 return ".u32"; 471 case U64: 472 return ".u64"; 473 case F16: 474 return ".f16"; 475 case F32: 476 return ".f32"; 477 case F64: 478 return ".f64"; 479 case I8: 480 return ".i8"; 481 case I16: 482 return ".i16"; 483 case I32: 484 return ".i32"; 485 case I64: 486 return ".i64"; 487 case P8: 488 return ".p8"; 489 case P64: 490 return ".p64"; 491 case Untyped8: 492 return ".8"; 493 case Untyped16: 494 return ".16"; 495 case Untyped32: 496 return ".32"; 497 case Untyped64: 498 return ".64"; 499 } 500 VIXL_UNREACHABLE(); 501 return ".??"; 502} 503 504 505const char* MemoryBarrier::GetName() const { 506 switch (type_) { 507 case OSHLD: 508 return "oshld"; 509 case OSHST: 510 return "oshst"; 511 case OSH: 512 return "osh"; 513 case NSHLD: 514 return "nshld"; 515 case NSHST: 516 return "nshst"; 517 case NSH: 518 return "nsh"; 519 case ISHLD: 520 return "ishld"; 521 case ISHST: 522 return "ishst"; 523 case ISH: 524 return "ish"; 525 case LD: 526 return "ld"; 527 case ST: 528 return "st"; 529 case SY: 530 return "sy"; 531 } 532 switch (static_cast<int>(type_)) { 533 case 0: 534 return "#0x0"; 535 case 4: 536 return "#0x4"; 537 case 8: 538 return "#0x8"; 539 case 0xc: 540 return "#0xc"; 541 } 542 VIXL_UNREACHABLE(); 543 return "??"; 544} 545 546 547const char* InterruptFlags::GetName() const { 548 switch (type_) { 549 case F: 550 return "f"; 551 case I: 552 return "i"; 553 case IF: 554 return "if"; 555 case A: 556 return "a"; 557 case AF: 558 return "af"; 559 case AI: 560 return "ai"; 561 case AIF: 562 return "aif"; 563 } 564 VIXL_ASSERT(type_ == 0); 565 return ""; 566} 567 568 569const char* Endianness::GetName() const { 570 switch (type_) { 571 case LE: 572 return "le"; 573 case BE: 574 return "be"; 575 } 576 VIXL_UNREACHABLE(); 577 return "??"; 578} 579 580 581// Constructor used for disassembly. 582ImmediateShiftOperand::ImmediateShiftOperand(int shift_value, int amount_value) 583 : Shift(shift_value) { 584 switch (shift_value) { 585 case LSL: 586 amount_ = amount_value; 587 break; 588 case LSR: 589 case ASR: 590 amount_ = (amount_value == 0) ? 32 : amount_value; 591 break; 592 case ROR: 593 amount_ = amount_value; 594 if (amount_value == 0) SetType(RRX); 595 break; 596 default: 597 VIXL_UNREACHABLE(); 598 SetType(LSL); 599 amount_ = 0; 600 break; 601 } 602} 603 604 605ImmediateT32::ImmediateT32(uint32_t imm) { 606 // 00000000 00000000 00000000 abcdefgh 607 if ((imm & ~0xff) == 0) { 608 SetEncodingValue(imm); 609 return; 610 } 611 if ((imm >> 16) == (imm & 0xffff)) { 612 if ((imm & 0xff00) == 0) { 613 // 00000000 abcdefgh 00000000 abcdefgh 614 SetEncodingValue((imm & 0xff) | (0x1 << 8)); 615 return; 616 } 617 if ((imm & 0xff) == 0) { 618 // abcdefgh 00000000 abcdefgh 00000000 619 SetEncodingValue(((imm >> 8) & 0xff) | (0x2 << 8)); 620 return; 621 } 622 if (((imm >> 8) & 0xff) == (imm & 0xff)) { 623 // abcdefgh abcdefgh abcdefgh abcdefgh 624 SetEncodingValue((imm & 0xff) | (0x3 << 8)); 625 return; 626 } 627 } 628 for (int shift = 0; shift < 24; shift++) { 629 uint32_t imm8 = imm >> (24 - shift); 630 uint32_t overflow = imm << (8 + shift); 631 if ((imm8 <= 0xff) && ((imm8 & 0x80) != 0) && (overflow == 0)) { 632 SetEncodingValue(((shift + 8) << 7) | (imm8 & 0x7F)); 633 return; 634 } 635 } 636} 637 638 639static inline uint32_t ror(uint32_t x, int i) { 640 VIXL_ASSERT((0 < i) && (i < 32)); 641 return (x >> i) | (x << (32 - i)); 642} 643 644 645bool ImmediateT32::IsImmediateT32(uint32_t imm) { 646 /* abcdefgh abcdefgh abcdefgh abcdefgh */ 647 if ((imm ^ ror(imm, 8)) == 0) return true; 648 /* 00000000 abcdefgh 00000000 abcdefgh */ 649 /* abcdefgh 00000000 abcdefgh 00000000 */ 650 if ((imm ^ ror(imm, 16)) == 0 && 651 (((imm & 0xff00) == 0) || ((imm & 0xff) == 0))) 652 return true; 653 /* isolate least-significant set bit */ 654 uint32_t lsb = imm & -imm; 655 /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to 656 * avoid overflow (underflow is always a successful case) */ 657 return ((imm >> 8) < lsb); 658} 659 660 661uint32_t ImmediateT32::Decode(uint32_t value) { 662 uint32_t base = value & 0xff; 663 switch (value >> 8) { 664 case 0: 665 return base; 666 case 1: 667 return base | (base << 16); 668 case 2: 669 return (base << 8) | (base << 24); 670 case 3: 671 return base | (base << 8) | (base << 16) | (base << 24); 672 default: 673 base |= 0x80; 674 return base << (32 - (value >> 7)); 675 } 676} 677 678 679ImmediateA32::ImmediateA32(uint32_t imm) { 680 // Deal with rot = 0 first to avoid undefined shift by 32. 681 if (imm <= 0xff) { 682 SetEncodingValue(imm); 683 return; 684 } 685 for (int rot = 2; rot < 32; rot += 2) { 686 uint32_t imm8 = (imm << rot) | (imm >> (32 - rot)); 687 if (imm8 <= 0xff) { 688 SetEncodingValue((rot << 7) | imm8); 689 return; 690 } 691 } 692} 693 694 695bool ImmediateA32::IsImmediateA32(uint32_t imm) { 696 /* fast-out */ 697 if (imm < 256) return true; 698 /* avoid getting confused by wrapped-around bytes (this transform has no 699 * effect on pass/fail results) */ 700 if (imm & 0xff000000) imm = ror(imm, 16); 701 /* copy odd-numbered set bits into even-numbered bits immediately below, so 702 * that the least-significant set bit is always an even bit */ 703 imm = imm | ((imm >> 1) & 0x55555555); 704 /* isolate least-significant set bit (always even) */ 705 uint32_t lsb = imm & -imm; 706 /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to 707 * avoid overflow (underflow is always a successful case) */ 708 return ((imm >> 8) < lsb); 709} 710 711 712uint32_t ImmediateA32::Decode(uint32_t value) { 713 int rotation = (value >> 8) * 2; 714 VIXL_ASSERT(rotation >= 0); 715 VIXL_ASSERT(rotation <= 30); 716 value &= 0xff; 717 if (rotation == 0) return value; 718 return (value >> rotation) | (value << (32 - rotation)); 719} 720 721 722uint32_t TypeEncodingValue(Shift shift) { 723 return shift.IsRRX() ? kRRXEncodedValue : shift.GetValue(); 724} 725 726 727uint32_t AmountEncodingValue(Shift shift, uint32_t amount) { 728 switch (shift.GetType()) { 729 case LSL: 730 case ROR: 731 return amount; 732 case LSR: 733 case ASR: 734 return amount % 32; 735 case RRX: 736 return 0; 737 } 738 return 0; 739} 740 741} // namespace aarch32 742} // namespace vixl 743