instructions-aarch32.cc revision 3c1635a4387a8d19b33d558b75c376e6587c317e
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 27extern "C" { 28#include <stdint.h> 29} 30 31#include <cassert> 32#include <cstdio> 33#include <cstdlib> 34#include <cstring> 35#include <iostream> // NOLINT 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, uint32_t list) { // NOLINT 106 os << "{"; 107 bool first = true; 108 int code = 0; 109 while (list != 0) { 110 if ((list & 1) != 0) { 111 if (first) { 112 first = false; 113 } else { 114 os << ","; 115 } 116 os << Register(code); 117 } 118 list >>= 1; 119 code++; 120 } 121 os << "}"; 122 return os; 123} 124 125 126std::ostream& operator<<(std::ostream& os, RegisterList registers) { 127 return PrintRegisterList(os, registers.GetList()); 128} 129 130 131QRegister VRegisterList::GetFirstAvailableQRegister() const { 132 for (uint32_t i = 0; i < kNumberOfQRegisters; i++) { 133 if (((list_ >> (i * 4)) & 0xf) == 0xf) return QRegister(i); 134 } 135 return QRegister(); 136} 137 138 139DRegister VRegisterList::GetFirstAvailableDRegister() const { 140 for (uint32_t i = 0; i < kMaxNumberOfDRegisters; i++) { 141 if (((list_ >> (i * 2)) & 0x3) == 0x3) return DRegister(i); 142 } 143 return DRegister(); 144} 145 146 147SRegister VRegisterList::GetFirstAvailableSRegister() const { 148 for (uint32_t i = 0; i < kNumberOfSRegisters; i++) { 149 if (((list_ >> i) & 0x1) != 0) return SRegister(i); 150 } 151 return SRegister(); 152} 153 154 155std::ostream& operator<<(std::ostream& os, SRegisterList reglist) { 156 SRegister first = reglist.GetFirstSRegister(); 157 SRegister last = reglist.GetLastSRegister(); 158 if (first.Is(last)) 159 os << "{" << first << "}"; 160 else 161 os << "{" << first << "-" << last << "}"; 162 return os; 163} 164 165 166std::ostream& operator<<(std::ostream& os, DRegisterList reglist) { 167 DRegister first = reglist.GetFirstDRegister(); 168 DRegister last = reglist.GetLastDRegister(); 169 if (first.Is(last)) 170 os << "{" << first << "}"; 171 else 172 os << "{" << first << "-" << last << "}"; 173 return os; 174} 175 176std::ostream& operator<<(std::ostream& os, NeonRegisterList nreglist) { 177 DRegister first = nreglist.GetFirstDRegister(); 178 int increment = nreglist.IsSingleSpaced() ? 1 : 2; 179 int count = 180 nreglist.GetLastDRegister().GetCode() - first.GetCode() + increment; 181 if (count < 0) count += kMaxNumberOfDRegisters; 182 os << "{"; 183 bool first_displayed = false; 184 for (;;) { 185 if (first_displayed) { 186 os << ","; 187 } else { 188 first_displayed = true; 189 } 190 os << first; 191 if (nreglist.IsTransferOneLane()) { 192 os << "[" << nreglist.GetTransferLane() << "]"; 193 } else if (nreglist.IsTransferAllLanes()) { 194 os << "[]"; 195 } 196 count -= increment; 197 if (count <= 0) break; 198 unsigned next = first.GetCode() + increment; 199 if (next >= kMaxNumberOfDRegisters) next -= kMaxNumberOfDRegisters; 200 first = DRegister(next); 201 } 202 os << "}"; 203 return os; 204} 205 206 207const char* SpecialRegister::GetName() const { 208 switch (reg_) { 209 case APSR: 210 return "APSR"; 211 case SPSR: 212 return "SPSR"; 213 } 214 VIXL_UNREACHABLE(); 215 return "??"; 216} 217 218 219const char* MaskedSpecialRegister::GetName() const { 220 switch (reg_) { 221 case APSR_nzcvq: 222 return "APSR_nzcvq"; 223 case APSR_g: 224 return "APSR_g"; 225 case APSR_nzcvqg: 226 return "APSR_nzcvqg"; 227 case CPSR_c: 228 return "CPSR_c"; 229 case CPSR_x: 230 return "CPSR_x"; 231 case CPSR_xc: 232 return "CPSR_xc"; 233 case CPSR_sc: 234 return "CPSR_sc"; 235 case CPSR_sx: 236 return "CPSR_sx"; 237 case CPSR_sxc: 238 return "CPSR_sxc"; 239 case CPSR_fc: 240 return "CPSR_fc"; 241 case CPSR_fx: 242 return "CPSR_fx"; 243 case CPSR_fxc: 244 return "CPSR_fxc"; 245 case CPSR_fsc: 246 return "CPSR_fsc"; 247 case CPSR_fsx: 248 return "CPSR_fsx"; 249 case CPSR_fsxc: 250 return "CPSR_fsxc"; 251 case SPSR_c: 252 return "SPSR_c"; 253 case SPSR_x: 254 return "SPSR_x"; 255 case SPSR_xc: 256 return "SPSR_xc"; 257 case SPSR_s: 258 return "SPSR_s"; 259 case SPSR_sc: 260 return "SPSR_sc"; 261 case SPSR_sx: 262 return "SPSR_sx"; 263 case SPSR_sxc: 264 return "SPSR_sxc"; 265 case SPSR_f: 266 return "SPSR_f"; 267 case SPSR_fc: 268 return "SPSR_fc"; 269 case SPSR_fx: 270 return "SPSR_fx"; 271 case SPSR_fxc: 272 return "SPSR_fxc"; 273 case SPSR_fs: 274 return "SPSR_fs"; 275 case SPSR_fsc: 276 return "SPSR_fsc"; 277 case SPSR_fsx: 278 return "SPSR_fsx"; 279 case SPSR_fsxc: 280 return "SPSR_fsxc"; 281 } 282 VIXL_UNREACHABLE(); 283 return "??"; 284} 285 286 287const char* BankedRegister::GetName() const { 288 switch (reg_) { 289 case R8_usr: 290 return "R8_usr"; 291 case R9_usr: 292 return "R9_usr"; 293 case R10_usr: 294 return "R10_usr"; 295 case R11_usr: 296 return "R11_usr"; 297 case R12_usr: 298 return "R12_usr"; 299 case SP_usr: 300 return "SP_usr"; 301 case LR_usr: 302 return "LR_usr"; 303 case R8_fiq: 304 return "R8_fiq"; 305 case R9_fiq: 306 return "R9_fiq"; 307 case R10_fiq: 308 return "R10_fiq"; 309 case R11_fiq: 310 return "R11_fiq"; 311 case R12_fiq: 312 return "R12_fiq"; 313 case SP_fiq: 314 return "SP_fiq"; 315 case LR_fiq: 316 return "LR_fiq"; 317 case LR_irq: 318 return "LR_irq"; 319 case SP_irq: 320 return "SP_irq"; 321 case LR_svc: 322 return "LR_svc"; 323 case SP_svc: 324 return "SP_svc"; 325 case LR_abt: 326 return "LR_abt"; 327 case SP_abt: 328 return "SP_abt"; 329 case LR_und: 330 return "LR_und"; 331 case SP_und: 332 return "SP_und"; 333 case LR_mon: 334 return "LR_mon"; 335 case SP_mon: 336 return "SP_mon"; 337 case ELR_hyp: 338 return "ELR_hyp"; 339 case SP_hyp: 340 return "SP_hyp"; 341 case SPSR_fiq: 342 return "SPSR_fiq"; 343 case SPSR_irq: 344 return "SPSR_irq"; 345 case SPSR_svc: 346 return "SPSR_svc"; 347 case SPSR_abt: 348 return "SPSR_abt"; 349 case SPSR_und: 350 return "SPSR_und"; 351 case SPSR_mon: 352 return "SPSR_mon"; 353 case SPSR_hyp: 354 return "SPSR_hyp"; 355 } 356 VIXL_UNREACHABLE(); 357 return "??"; 358} 359 360const char* SpecialFPRegister::GetName() const { 361 switch (reg_) { 362 case FPSID: 363 return "FPSID"; 364 case FPSCR: 365 return "FPSCR"; 366 case MVFR2: 367 return "MVFR2"; 368 case MVFR1: 369 return "MVFR1"; 370 case MVFR0: 371 return "MVFR0"; 372 case FPEXC: 373 return "FPEXC"; 374 } 375 VIXL_UNREACHABLE(); 376 return "??"; 377} 378 379 380const char* Condition::GetName() const { 381 switch (condition_) { 382 case eq: 383 return "eq"; 384 case ne: 385 return "ne"; 386 case cs: 387 return "cs"; 388 case cc: 389 return "cc"; 390 case mi: 391 return "mi"; 392 case pl: 393 return "pl"; 394 case vs: 395 return "vs"; 396 case vc: 397 return "vc"; 398 case hi: 399 return "hi"; 400 case ls: 401 return "ls"; 402 case ge: 403 return "ge"; 404 case lt: 405 return "lt"; 406 case gt: 407 return "gt"; 408 case le: 409 return "le"; 410 case al: 411 return ""; 412 case Condition::kNone: 413 return ""; 414 } 415 return "<und>"; 416} 417 418 419const char* Shift::GetName() const { 420 switch (shift_) { 421 case LSL: 422 return "lsl"; 423 case LSR: 424 return "lsr"; 425 case ASR: 426 return "asr"; 427 case ROR: 428 return "ror"; 429 case RRX: 430 return "rrx"; 431 } 432 VIXL_UNREACHABLE(); 433 return "??"; 434} 435 436 437const char* EncodingSize::GetName() const { 438 switch (size_) { 439 case Best: 440 return ""; 441 case Narrow: 442 return ".n"; 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