49#include "cpu/reg_class.hh" 50 51namespace ArmISA 52{ 53// Shift Rm by an immediate value 54int32_t 55ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, 56 uint32_t type, uint32_t cfval) const 57{ 58 assert(shamt < 32); 59 ArmShiftType shiftType; 60 shiftType = (ArmShiftType)type; 61 62 switch (shiftType) 63 { 64 case LSL: 65 return base << shamt; 66 case LSR: 67 if (shamt == 0) 68 return 0; 69 else 70 return base >> shamt; 71 case ASR: 72 if (shamt == 0) 73 return (base >> 31) | -((base & (1 << 31)) >> 31); 74 else 75 return (base >> shamt) | -((base & (1 << 31)) >> shamt); 76 case ROR: 77 if (shamt == 0) 78 return (cfval << 31) | (base >> 1); // RRX 79 else 80 return (base << (32 - shamt)) | (base >> shamt); 81 default: 82 ccprintf(std::cerr, "Unhandled shift type\n"); 83 exit(1); 84 break; 85 } 86 return 0; 87} 88 89int64_t 90ArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt, 91 ArmShiftType type, uint8_t width) const 92{ 93 shiftAmt = shiftAmt % width; 94 ArmShiftType shiftType; 95 shiftType = (ArmShiftType)type; 96 97 switch (shiftType) 98 { 99 case LSL: 100 return base << shiftAmt; 101 case LSR: 102 if (shiftAmt == 0) 103 return base; 104 else 105 return (base & mask(width)) >> shiftAmt; 106 case ASR: 107 if (shiftAmt == 0) { 108 return base; 109 } else { 110 int sign_bit = bits(base, intWidth - 1); 111 base >>= shiftAmt; 112 base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base; 113 return base & mask(intWidth); 114 } 115 case ROR: 116 if (shiftAmt == 0) 117 return base; 118 else 119 return (base << (width - shiftAmt)) | (base >> shiftAmt); 120 default: 121 ccprintf(std::cerr, "Unhandled shift type\n"); 122 exit(1); 123 break; 124 } 125 return 0; 126} 127 128int64_t 129ArmStaticInst::extendReg64(uint64_t base, ArmExtendType type, 130 uint64_t shiftAmt, uint8_t width) const 131{ 132 bool sign_extend = false; 133 int len = 0; 134 switch (type) { 135 case UXTB: 136 len = 8; 137 break; 138 case UXTH: 139 len = 16; 140 break; 141 case UXTW: 142 len = 32; 143 break; 144 case UXTX: 145 len = 64; 146 break; 147 case SXTB: 148 len = 8; 149 sign_extend = true; 150 break; 151 case SXTH: 152 len = 16; 153 sign_extend = true; 154 break; 155 case SXTW: 156 len = 32; 157 sign_extend = true; 158 break; 159 case SXTX: 160 len = 64; 161 sign_extend = true; 162 break; 163 } 164 len = len <= width - shiftAmt ? len : width - shiftAmt; 165 uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt; 166 if (sign_extend) { 167 int sign_bit = bits(tmp, len + shiftAmt - 1); 168 tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp; 169 } 170 return tmp & mask(width); 171} 172 173// Shift Rm by Rs 174int32_t 175ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, 176 uint32_t type, uint32_t cfval) const 177{ 178 enum ArmShiftType shiftType; 179 shiftType = (enum ArmShiftType) type; 180 181 switch (shiftType) 182 { 183 case LSL: 184 if (shamt >= 32) 185 return 0; 186 else 187 return base << shamt; 188 case LSR: 189 if (shamt >= 32) 190 return 0; 191 else 192 return base >> shamt; 193 case ASR: 194 if (shamt >= 32) 195 return (base >> 31) | -((base & (1 << 31)) >> 31); 196 else 197 return (base >> shamt) | -((base & (1 << 31)) >> shamt); 198 case ROR: 199 shamt = shamt & 0x1f; 200 if (shamt == 0) 201 return base; 202 else 203 return (base << (32 - shamt)) | (base >> shamt); 204 default: 205 ccprintf(std::cerr, "Unhandled shift type\n"); 206 exit(1); 207 break; 208 } 209 return 0; 210} 211 212 213// Generate C for a shift by immediate 214bool 215ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, 216 uint32_t type, uint32_t cfval) const 217{ 218 enum ArmShiftType shiftType; 219 shiftType = (enum ArmShiftType) type; 220 221 switch (shiftType) 222 { 223 case LSL: 224 if (shamt == 0) 225 return cfval; 226 else 227 return (base >> (32 - shamt)) & 1; 228 case LSR: 229 if (shamt == 0) 230 return (base >> 31); 231 else 232 return (base >> (shamt - 1)) & 1; 233 case ASR: 234 if (shamt == 0) 235 return (base >> 31); 236 else 237 return (base >> (shamt - 1)) & 1; 238 case ROR: 239 shamt = shamt & 0x1f; 240 if (shamt == 0) 241 return (base & 1); // RRX 242 else 243 return (base >> (shamt - 1)) & 1; 244 default: 245 ccprintf(std::cerr, "Unhandled shift type\n"); 246 exit(1); 247 break; 248 } 249 return 0; 250} 251 252 253// Generate C for a shift by Rs 254bool 255ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, 256 uint32_t type, uint32_t cfval) const 257{ 258 enum ArmShiftType shiftType; 259 shiftType = (enum ArmShiftType) type; 260 261 if (shamt == 0) 262 return cfval; 263 264 switch (shiftType) 265 { 266 case LSL: 267 if (shamt > 32) 268 return 0; 269 else 270 return (base >> (32 - shamt)) & 1; 271 case LSR: 272 if (shamt > 32) 273 return 0; 274 else 275 return (base >> (shamt - 1)) & 1; 276 case ASR: 277 if (shamt > 32) 278 shamt = 32; 279 return (base >> (shamt - 1)) & 1; 280 case ROR: 281 shamt = shamt & 0x1f; 282 if (shamt == 0) 283 shamt = 32; 284 return (base >> (shamt - 1)) & 1; 285 default: 286 ccprintf(std::cerr, "Unhandled shift type\n"); 287 exit(1); 288 break; 289 } 290 return 0; 291} 292 293 294void 295ArmStaticInst::printReg(std::ostream &os, int reg) const 296{ 297 RegIndex rel_reg; 298 299 switch (regIdxToClass(reg, &rel_reg)) { 300 case IntRegClass: 301 if (aarch64) { 302 if (reg == INTREG_UREG0) 303 ccprintf(os, "ureg0"); 304 else if (reg == INTREG_SPX) 305 ccprintf(os, "%s%s", (intWidth == 32) ? "w" : "", "sp"); 306 else if (reg == INTREG_X31) 307 ccprintf(os, "%szr", (intWidth == 32) ? "w" : "x"); 308 else 309 ccprintf(os, "%s%d", (intWidth == 32) ? "w" : "x", reg); 310 } else { 311 switch (rel_reg) { 312 case PCReg: 313 ccprintf(os, "pc"); 314 break; 315 case StackPointerReg: 316 ccprintf(os, "sp"); 317 break; 318 case FramePointerReg: 319 ccprintf(os, "fp"); 320 break; 321 case ReturnAddressReg: 322 ccprintf(os, "lr"); 323 break; 324 default: 325 ccprintf(os, "r%d", reg); 326 break; 327 } 328 } 329 break; 330 case FloatRegClass: 331 ccprintf(os, "f%d", rel_reg); 332 break; 333 case MiscRegClass: 334 assert(rel_reg < NUM_MISCREGS); 335 ccprintf(os, "%s", ArmISA::miscRegName[rel_reg]); 336 break; 337 case CCRegClass: 338 ccprintf(os, "cc_%s", ArmISA::ccRegName[rel_reg]); 339 break; 340 } 341} 342 343void 344ArmStaticInst::printMnemonic(std::ostream &os, 345 const std::string &suffix, 346 bool withPred, 347 bool withCond64, 348 ConditionCode cond64) const 349{ 350 os << " " << mnemonic; 351 if (withPred && !aarch64) { 352 printCondition(os, machInst.condCode); 353 os << suffix; 354 } else if (withCond64) { 355 os << "."; 356 printCondition(os, cond64); 357 os << suffix; 358 } 359 if (machInst.bigThumb) 360 os << ".w"; 361 os << " "; 362} 363 364void 365ArmStaticInst::printTarget(std::ostream &os, Addr target, 366 const SymbolTable *symtab) const 367{ 368 Addr symbolAddr; 369 std::string symbol; 370 371 if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) { 372 ccprintf(os, "<%s", symbol); 373 if (symbolAddr != target) 374 ccprintf(os, "+%d>", target - symbolAddr); 375 else 376 ccprintf(os, ">"); 377 } else { 378 ccprintf(os, "%#x", target); 379 } 380} 381 382void 383ArmStaticInst::printCondition(std::ostream &os, 384 unsigned code, 385 bool noImplicit) const 386{ 387 switch (code) { 388 case COND_EQ: 389 os << "eq"; 390 break; 391 case COND_NE: 392 os << "ne"; 393 break; 394 case COND_CS: 395 os << "cs"; 396 break; 397 case COND_CC: 398 os << "cc"; 399 break; 400 case COND_MI: 401 os << "mi"; 402 break; 403 case COND_PL: 404 os << "pl"; 405 break; 406 case COND_VS: 407 os << "vs"; 408 break; 409 case COND_VC: 410 os << "vc"; 411 break; 412 case COND_HI: 413 os << "hi"; 414 break; 415 case COND_LS: 416 os << "ls"; 417 break; 418 case COND_GE: 419 os << "ge"; 420 break; 421 case COND_LT: 422 os << "lt"; 423 break; 424 case COND_GT: 425 os << "gt"; 426 break; 427 case COND_LE: 428 os << "le"; 429 break; 430 case COND_AL: 431 // This one is implicit. 432 if (noImplicit) 433 os << "al"; 434 break; 435 case COND_UC: 436 // Unconditional. 437 if (noImplicit) 438 os << "uc"; 439 break; 440 default: 441 panic("Unrecognized condition code %d.\n", code); 442 } 443} 444 445void 446ArmStaticInst::printMemSymbol(std::ostream &os, 447 const SymbolTable *symtab, 448 const std::string &prefix, 449 const Addr addr, 450 const std::string &suffix) const 451{ 452 Addr symbolAddr; 453 std::string symbol; 454 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) { 455 ccprintf(os, "%s%s", prefix, symbol); 456 if (symbolAddr != addr) 457 ccprintf(os, "+%d", addr - symbolAddr); 458 ccprintf(os, suffix); 459 } 460} 461 462void 463ArmStaticInst::printShiftOperand(std::ostream &os, 464 IntRegIndex rm, 465 bool immShift, 466 uint32_t shiftAmt, 467 IntRegIndex rs, 468 ArmShiftType type) const 469{ 470 bool firstOp = false; 471 472 if (rm != INTREG_ZERO) { 473 printReg(os, rm); 474 } 475 476 bool done = false; 477 478 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0) 479 shiftAmt = 32; 480 481 switch (type) { 482 case LSL: 483 if (immShift && shiftAmt == 0) { 484 done = true; 485 break; 486 } 487 if (!firstOp) 488 os << ", "; 489 os << "LSL"; 490 break; 491 case LSR: 492 if (!firstOp) 493 os << ", "; 494 os << "LSR"; 495 break; 496 case ASR: 497 if (!firstOp) 498 os << ", "; 499 os << "ASR"; 500 break; 501 case ROR: 502 if (immShift && shiftAmt == 0) { 503 if (!firstOp) 504 os << ", "; 505 os << "RRX"; 506 done = true; 507 break; 508 } 509 if (!firstOp) 510 os << ", "; 511 os << "ROR"; 512 break; 513 default: 514 panic("Tried to disassemble unrecognized shift type.\n"); 515 } 516 if (!done) { 517 if (!firstOp) 518 os << " "; 519 if (immShift) 520 os << "#" << shiftAmt; 521 else 522 printReg(os, rs); 523 } 524} 525 526void 527ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os, 528 IntRegIndex rm, ArmExtendType type, 529 int64_t shiftAmt) const 530{ 531 if (!firstOperand) 532 ccprintf(os, ", "); 533 printReg(os, rm); 534 if (type == UXTX && shiftAmt == 0) 535 return; 536 switch (type) { 537 case UXTB: ccprintf(os, ", UXTB"); 538 break; 539 case UXTH: ccprintf(os, ", UXTH"); 540 break; 541 case UXTW: ccprintf(os, ", UXTW"); 542 break; 543 case UXTX: ccprintf(os, ", LSL"); 544 break; 545 case SXTB: ccprintf(os, ", SXTB"); 546 break; 547 case SXTH: ccprintf(os, ", SXTH"); 548 break; 549 case SXTW: ccprintf(os, ", SXTW"); 550 break; 551 case SXTX: ccprintf(os, ", SXTW"); 552 break; 553 } 554 if (type == UXTX || shiftAmt) 555 ccprintf(os, " #%d", shiftAmt); 556} 557 558void 559ArmStaticInst::printDataInst(std::ostream &os, bool withImm, 560 bool immShift, bool s, IntRegIndex rd, IntRegIndex rn, 561 IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt, 562 ArmShiftType type, uint64_t imm) const 563{ 564 printMnemonic(os, s ? "s" : ""); 565 bool firstOp = true; 566 567 // Destination 568 if (rd != INTREG_ZERO) { 569 firstOp = false; 570 printReg(os, rd); 571 } 572 573 // Source 1. 574 if (rn != INTREG_ZERO) { 575 if (!firstOp) 576 os << ", "; 577 firstOp = false; 578 printReg(os, rn); 579 } 580 581 if (!firstOp) 582 os << ", "; 583 if (withImm) { 584 ccprintf(os, "#%ld", imm); 585 } else { 586 printShiftOperand(os, rm, immShift, shiftAmt, rs, type); 587 } 588} 589 590std::string 591ArmStaticInst::generateDisassembly(Addr pc, 592 const SymbolTable *symtab) const 593{ 594 std::stringstream ss; 595 printMnemonic(ss); 596 return ss.str(); 597} 598 599 600Fault 601ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const 602{ 603 switch (el) { 604 case EL1: 605 return std::make_shared<SupervisorTrap>(machInst, 0x1E00000, 606 EC_TRAPPED_SIMD_FP); 607 case EL2: 608 return std::make_shared<HypervisorTrap>(machInst, 0x1E00000, 609 EC_TRAPPED_SIMD_FP); 610 case EL3: 611 return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000, 612 EC_TRAPPED_SIMD_FP); 613 614 default: 615 panic("Illegal EL in advSIMDFPAccessTrap64\n"); 616 } 617} 618 619 620Fault 621ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const 622{ 623 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el; 624 625 if (ArmSystem::haveVirtualization(tc) && el <= EL2) { 626 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2); 627 if (cptrEnCheck.tfp) 628 return advSIMDFPAccessTrap64(EL2); 629 } 630 631 if (ArmSystem::haveSecurity(tc)) { 632 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 633 if (cptrEnCheck.tfp) 634 return advSIMDFPAccessTrap64(EL3); 635 } 636 637 return NoFault; 638} 639 640Fault 641ArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc, 642 CPSR cpsr, CPACR cpacr) const 643{ 644 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el; 645 if ((el == EL0 && cpacr.fpen != 0x3) || 646 (el == EL1 && !(cpacr.fpen & 0x1))) 647 return advSIMDFPAccessTrap64(EL1); 648 649 return checkFPAdvSIMDTrap64(tc, cpsr); 650} 651 652Fault 653ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc, 654 CPSR cpsr, CPACR cpacr, 655 NSACR nsacr, FPEXC fpexc, 656 bool fpexc_check, bool advsimd) const 657{ 658 const bool have_virtualization = ArmSystem::haveVirtualization(tc); 659 const bool have_security = ArmSystem::haveSecurity(tc); 660 const bool is_secure = inSecureState(tc); 661 const ExceptionLevel cur_el = opModeToEL(currOpMode(tc)); 662 663 if (cur_el == EL0 && ELIs64(tc, EL1)) 664 return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr); 665 666 uint8_t cpacr_cp10 = cpacr.cp10; 667 bool cpacr_asedis = cpacr.asedis; 668 669 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 670 if (nsacr.nsasedis) 671 cpacr_asedis = true; 672 if (nsacr.cp10 == 0) 673 cpacr_cp10 = 0; 674 } 675 676 if (cur_el != EL2) { 677 if (advsimd && cpacr_asedis) 678 return disabledFault(); 679 680 if ((cur_el == EL0 && cpacr_cp10 != 0x3) || 681 (cur_el != EL0 && !(cpacr_cp10 & 0x1))) 682 return disabledFault(); 683 } 684 685 if (fpexc_check && !fpexc.en) 686 return disabledFault(); 687 688 // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap -- 689 690 if (have_virtualization && !is_secure && ELIs64(tc, EL2)) 691 return checkFPAdvSIMDTrap64(tc, cpsr); 692 693 if (have_virtualization && !is_secure) { 694 HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR); 695 bool hcptr_cp10 = hcptr.tcp10; 696 bool hcptr_tase = hcptr.tase; 697 698 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 699 if (nsacr.nsasedis) 700 hcptr_tase = true; 701 if (nsacr.cp10) 702 hcptr_cp10 = true; 703 } 704 705 if ((advsimd && hcptr_tase) || hcptr_cp10) { 706 const uint32_t iss = advsimd ? (1 << 5) : 0xA; 707 if (cur_el == EL2) { 708 return std::make_shared<UndefinedInstruction>( 709 machInst, iss, 710 EC_TRAPPED_HCPTR, mnemonic); 711 } else { 712 return std::make_shared<HypervisorTrap>( 713 machInst, iss, 714 EC_TRAPPED_HCPTR); 715 } 716 717 } 718 } 719 720 if (have_security && ELIs64(tc, EL3)) { 721 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 722 if (cptrEnCheck.tfp) 723 return advSIMDFPAccessTrap64(EL3); 724 } 725 726 return NoFault; 727} 728 729 730static uint8_t 731getRestoredITBits(ThreadContext *tc, CPSR spsr) 732{ 733 // See: shared/functions/system/RestoredITBits in the ARM ARM 734 735 const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode); 736 const uint8_t it = itState(spsr); 737 738 if (!spsr.t || spsr.il) 739 return 0; 740 741 // The IT bits are forced to zero when they are set to a reserved 742 // value. 743 if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0) 744 return 0; 745 746 const bool itd = el == EL2 ? 747 ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd : 748 ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd; 749 750 // The IT bits are forced to zero when returning to A32 state, or 751 // when returning to an EL with the ITD bit set to 1, and the IT 752 // bits are describing a multi-instruction block. 753 if (itd && bits(it, 2, 0) != 0) 754 return 0; 755 756 return it; 757} 758 759static bool 760illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr) 761{ 762 const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode; 763 if (badMode(mode)) 764 return true; 765 766 const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode; 767 const ExceptionLevel target_el = opModeToEL(mode); 768 if (target_el > opModeToEL(cur_mode)) 769 return true; 770 771 if (target_el == EL3 && !ArmSystem::haveSecurity(tc)) 772 return true; 773 774 if (target_el == EL2 && !ArmSystem::haveVirtualization(tc)) 775 return true; 776 777 if (!spsr.width) { 778 // aarch64 779 if (!ArmSystem::highestELIs64(tc)) 780 return true; 781 782 if (spsr & 0x2) 783 return true; 784 if (target_el == EL0 && spsr.sp) 785 return true; 786 if (target_el == EL2 && !((SCR)tc->readMiscReg(MISCREG_SCR_EL3)).ns) 787 return false; 788 } else { 789 return badMode32(mode); 790 } 791 792 return false; 793} 794 795CPSR 796ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const 797{ 798 CPSR new_cpsr = 0; 799 800 // gem5 doesn't implement single-stepping, so force the SS bit to 801 // 0. 802 new_cpsr.ss = 0; 803 804 if (illegalExceptionReturn(tc, cpsr, spsr)) { 805 new_cpsr.il = 1; 806 } else { 807 new_cpsr.il = spsr.il; 808 if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) { 809 new_cpsr.il = 1; 810 } else if (spsr.width) { 811 new_cpsr.mode = spsr.mode; 812 } else { 813 new_cpsr.el = spsr.el; 814 new_cpsr.sp = spsr.sp; 815 } 816 } 817 818 new_cpsr.nz = spsr.nz; 819 new_cpsr.c = spsr.c; 820 new_cpsr.v = spsr.v; 821 if (new_cpsr.width) { 822 // aarch32 823 const ITSTATE it = getRestoredITBits(tc, spsr); 824 new_cpsr.q = spsr.q; 825 new_cpsr.ge = spsr.ge; 826 new_cpsr.e = spsr.e; 827 new_cpsr.aif = spsr.aif; 828 new_cpsr.t = spsr.t; 829 new_cpsr.it2 = it.top6; 830 new_cpsr.it1 = it.bottom2; 831 } else { 832 // aarch64 833 new_cpsr.daif = spsr.daif; 834 } 835 836 return new_cpsr; 837} 838 839 840 841}
| 50#include "cpu/reg_class.hh" 51 52namespace ArmISA 53{ 54// Shift Rm by an immediate value 55int32_t 56ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, 57 uint32_t type, uint32_t cfval) const 58{ 59 assert(shamt < 32); 60 ArmShiftType shiftType; 61 shiftType = (ArmShiftType)type; 62 63 switch (shiftType) 64 { 65 case LSL: 66 return base << shamt; 67 case LSR: 68 if (shamt == 0) 69 return 0; 70 else 71 return base >> shamt; 72 case ASR: 73 if (shamt == 0) 74 return (base >> 31) | -((base & (1 << 31)) >> 31); 75 else 76 return (base >> shamt) | -((base & (1 << 31)) >> shamt); 77 case ROR: 78 if (shamt == 0) 79 return (cfval << 31) | (base >> 1); // RRX 80 else 81 return (base << (32 - shamt)) | (base >> shamt); 82 default: 83 ccprintf(std::cerr, "Unhandled shift type\n"); 84 exit(1); 85 break; 86 } 87 return 0; 88} 89 90int64_t 91ArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt, 92 ArmShiftType type, uint8_t width) const 93{ 94 shiftAmt = shiftAmt % width; 95 ArmShiftType shiftType; 96 shiftType = (ArmShiftType)type; 97 98 switch (shiftType) 99 { 100 case LSL: 101 return base << shiftAmt; 102 case LSR: 103 if (shiftAmt == 0) 104 return base; 105 else 106 return (base & mask(width)) >> shiftAmt; 107 case ASR: 108 if (shiftAmt == 0) { 109 return base; 110 } else { 111 int sign_bit = bits(base, intWidth - 1); 112 base >>= shiftAmt; 113 base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base; 114 return base & mask(intWidth); 115 } 116 case ROR: 117 if (shiftAmt == 0) 118 return base; 119 else 120 return (base << (width - shiftAmt)) | (base >> shiftAmt); 121 default: 122 ccprintf(std::cerr, "Unhandled shift type\n"); 123 exit(1); 124 break; 125 } 126 return 0; 127} 128 129int64_t 130ArmStaticInst::extendReg64(uint64_t base, ArmExtendType type, 131 uint64_t shiftAmt, uint8_t width) const 132{ 133 bool sign_extend = false; 134 int len = 0; 135 switch (type) { 136 case UXTB: 137 len = 8; 138 break; 139 case UXTH: 140 len = 16; 141 break; 142 case UXTW: 143 len = 32; 144 break; 145 case UXTX: 146 len = 64; 147 break; 148 case SXTB: 149 len = 8; 150 sign_extend = true; 151 break; 152 case SXTH: 153 len = 16; 154 sign_extend = true; 155 break; 156 case SXTW: 157 len = 32; 158 sign_extend = true; 159 break; 160 case SXTX: 161 len = 64; 162 sign_extend = true; 163 break; 164 } 165 len = len <= width - shiftAmt ? len : width - shiftAmt; 166 uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt; 167 if (sign_extend) { 168 int sign_bit = bits(tmp, len + shiftAmt - 1); 169 tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp; 170 } 171 return tmp & mask(width); 172} 173 174// Shift Rm by Rs 175int32_t 176ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, 177 uint32_t type, uint32_t cfval) const 178{ 179 enum ArmShiftType shiftType; 180 shiftType = (enum ArmShiftType) type; 181 182 switch (shiftType) 183 { 184 case LSL: 185 if (shamt >= 32) 186 return 0; 187 else 188 return base << shamt; 189 case LSR: 190 if (shamt >= 32) 191 return 0; 192 else 193 return base >> shamt; 194 case ASR: 195 if (shamt >= 32) 196 return (base >> 31) | -((base & (1 << 31)) >> 31); 197 else 198 return (base >> shamt) | -((base & (1 << 31)) >> shamt); 199 case ROR: 200 shamt = shamt & 0x1f; 201 if (shamt == 0) 202 return base; 203 else 204 return (base << (32 - shamt)) | (base >> shamt); 205 default: 206 ccprintf(std::cerr, "Unhandled shift type\n"); 207 exit(1); 208 break; 209 } 210 return 0; 211} 212 213 214// Generate C for a shift by immediate 215bool 216ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, 217 uint32_t type, uint32_t cfval) const 218{ 219 enum ArmShiftType shiftType; 220 shiftType = (enum ArmShiftType) type; 221 222 switch (shiftType) 223 { 224 case LSL: 225 if (shamt == 0) 226 return cfval; 227 else 228 return (base >> (32 - shamt)) & 1; 229 case LSR: 230 if (shamt == 0) 231 return (base >> 31); 232 else 233 return (base >> (shamt - 1)) & 1; 234 case ASR: 235 if (shamt == 0) 236 return (base >> 31); 237 else 238 return (base >> (shamt - 1)) & 1; 239 case ROR: 240 shamt = shamt & 0x1f; 241 if (shamt == 0) 242 return (base & 1); // RRX 243 else 244 return (base >> (shamt - 1)) & 1; 245 default: 246 ccprintf(std::cerr, "Unhandled shift type\n"); 247 exit(1); 248 break; 249 } 250 return 0; 251} 252 253 254// Generate C for a shift by Rs 255bool 256ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, 257 uint32_t type, uint32_t cfval) const 258{ 259 enum ArmShiftType shiftType; 260 shiftType = (enum ArmShiftType) type; 261 262 if (shamt == 0) 263 return cfval; 264 265 switch (shiftType) 266 { 267 case LSL: 268 if (shamt > 32) 269 return 0; 270 else 271 return (base >> (32 - shamt)) & 1; 272 case LSR: 273 if (shamt > 32) 274 return 0; 275 else 276 return (base >> (shamt - 1)) & 1; 277 case ASR: 278 if (shamt > 32) 279 shamt = 32; 280 return (base >> (shamt - 1)) & 1; 281 case ROR: 282 shamt = shamt & 0x1f; 283 if (shamt == 0) 284 shamt = 32; 285 return (base >> (shamt - 1)) & 1; 286 default: 287 ccprintf(std::cerr, "Unhandled shift type\n"); 288 exit(1); 289 break; 290 } 291 return 0; 292} 293 294 295void 296ArmStaticInst::printReg(std::ostream &os, int reg) const 297{ 298 RegIndex rel_reg; 299 300 switch (regIdxToClass(reg, &rel_reg)) { 301 case IntRegClass: 302 if (aarch64) { 303 if (reg == INTREG_UREG0) 304 ccprintf(os, "ureg0"); 305 else if (reg == INTREG_SPX) 306 ccprintf(os, "%s%s", (intWidth == 32) ? "w" : "", "sp"); 307 else if (reg == INTREG_X31) 308 ccprintf(os, "%szr", (intWidth == 32) ? "w" : "x"); 309 else 310 ccprintf(os, "%s%d", (intWidth == 32) ? "w" : "x", reg); 311 } else { 312 switch (rel_reg) { 313 case PCReg: 314 ccprintf(os, "pc"); 315 break; 316 case StackPointerReg: 317 ccprintf(os, "sp"); 318 break; 319 case FramePointerReg: 320 ccprintf(os, "fp"); 321 break; 322 case ReturnAddressReg: 323 ccprintf(os, "lr"); 324 break; 325 default: 326 ccprintf(os, "r%d", reg); 327 break; 328 } 329 } 330 break; 331 case FloatRegClass: 332 ccprintf(os, "f%d", rel_reg); 333 break; 334 case MiscRegClass: 335 assert(rel_reg < NUM_MISCREGS); 336 ccprintf(os, "%s", ArmISA::miscRegName[rel_reg]); 337 break; 338 case CCRegClass: 339 ccprintf(os, "cc_%s", ArmISA::ccRegName[rel_reg]); 340 break; 341 } 342} 343 344void 345ArmStaticInst::printMnemonic(std::ostream &os, 346 const std::string &suffix, 347 bool withPred, 348 bool withCond64, 349 ConditionCode cond64) const 350{ 351 os << " " << mnemonic; 352 if (withPred && !aarch64) { 353 printCondition(os, machInst.condCode); 354 os << suffix; 355 } else if (withCond64) { 356 os << "."; 357 printCondition(os, cond64); 358 os << suffix; 359 } 360 if (machInst.bigThumb) 361 os << ".w"; 362 os << " "; 363} 364 365void 366ArmStaticInst::printTarget(std::ostream &os, Addr target, 367 const SymbolTable *symtab) const 368{ 369 Addr symbolAddr; 370 std::string symbol; 371 372 if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) { 373 ccprintf(os, "<%s", symbol); 374 if (symbolAddr != target) 375 ccprintf(os, "+%d>", target - symbolAddr); 376 else 377 ccprintf(os, ">"); 378 } else { 379 ccprintf(os, "%#x", target); 380 } 381} 382 383void 384ArmStaticInst::printCondition(std::ostream &os, 385 unsigned code, 386 bool noImplicit) const 387{ 388 switch (code) { 389 case COND_EQ: 390 os << "eq"; 391 break; 392 case COND_NE: 393 os << "ne"; 394 break; 395 case COND_CS: 396 os << "cs"; 397 break; 398 case COND_CC: 399 os << "cc"; 400 break; 401 case COND_MI: 402 os << "mi"; 403 break; 404 case COND_PL: 405 os << "pl"; 406 break; 407 case COND_VS: 408 os << "vs"; 409 break; 410 case COND_VC: 411 os << "vc"; 412 break; 413 case COND_HI: 414 os << "hi"; 415 break; 416 case COND_LS: 417 os << "ls"; 418 break; 419 case COND_GE: 420 os << "ge"; 421 break; 422 case COND_LT: 423 os << "lt"; 424 break; 425 case COND_GT: 426 os << "gt"; 427 break; 428 case COND_LE: 429 os << "le"; 430 break; 431 case COND_AL: 432 // This one is implicit. 433 if (noImplicit) 434 os << "al"; 435 break; 436 case COND_UC: 437 // Unconditional. 438 if (noImplicit) 439 os << "uc"; 440 break; 441 default: 442 panic("Unrecognized condition code %d.\n", code); 443 } 444} 445 446void 447ArmStaticInst::printMemSymbol(std::ostream &os, 448 const SymbolTable *symtab, 449 const std::string &prefix, 450 const Addr addr, 451 const std::string &suffix) const 452{ 453 Addr symbolAddr; 454 std::string symbol; 455 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) { 456 ccprintf(os, "%s%s", prefix, symbol); 457 if (symbolAddr != addr) 458 ccprintf(os, "+%d", addr - symbolAddr); 459 ccprintf(os, suffix); 460 } 461} 462 463void 464ArmStaticInst::printShiftOperand(std::ostream &os, 465 IntRegIndex rm, 466 bool immShift, 467 uint32_t shiftAmt, 468 IntRegIndex rs, 469 ArmShiftType type) const 470{ 471 bool firstOp = false; 472 473 if (rm != INTREG_ZERO) { 474 printReg(os, rm); 475 } 476 477 bool done = false; 478 479 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0) 480 shiftAmt = 32; 481 482 switch (type) { 483 case LSL: 484 if (immShift && shiftAmt == 0) { 485 done = true; 486 break; 487 } 488 if (!firstOp) 489 os << ", "; 490 os << "LSL"; 491 break; 492 case LSR: 493 if (!firstOp) 494 os << ", "; 495 os << "LSR"; 496 break; 497 case ASR: 498 if (!firstOp) 499 os << ", "; 500 os << "ASR"; 501 break; 502 case ROR: 503 if (immShift && shiftAmt == 0) { 504 if (!firstOp) 505 os << ", "; 506 os << "RRX"; 507 done = true; 508 break; 509 } 510 if (!firstOp) 511 os << ", "; 512 os << "ROR"; 513 break; 514 default: 515 panic("Tried to disassemble unrecognized shift type.\n"); 516 } 517 if (!done) { 518 if (!firstOp) 519 os << " "; 520 if (immShift) 521 os << "#" << shiftAmt; 522 else 523 printReg(os, rs); 524 } 525} 526 527void 528ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os, 529 IntRegIndex rm, ArmExtendType type, 530 int64_t shiftAmt) const 531{ 532 if (!firstOperand) 533 ccprintf(os, ", "); 534 printReg(os, rm); 535 if (type == UXTX && shiftAmt == 0) 536 return; 537 switch (type) { 538 case UXTB: ccprintf(os, ", UXTB"); 539 break; 540 case UXTH: ccprintf(os, ", UXTH"); 541 break; 542 case UXTW: ccprintf(os, ", UXTW"); 543 break; 544 case UXTX: ccprintf(os, ", LSL"); 545 break; 546 case SXTB: ccprintf(os, ", SXTB"); 547 break; 548 case SXTH: ccprintf(os, ", SXTH"); 549 break; 550 case SXTW: ccprintf(os, ", SXTW"); 551 break; 552 case SXTX: ccprintf(os, ", SXTW"); 553 break; 554 } 555 if (type == UXTX || shiftAmt) 556 ccprintf(os, " #%d", shiftAmt); 557} 558 559void 560ArmStaticInst::printDataInst(std::ostream &os, bool withImm, 561 bool immShift, bool s, IntRegIndex rd, IntRegIndex rn, 562 IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt, 563 ArmShiftType type, uint64_t imm) const 564{ 565 printMnemonic(os, s ? "s" : ""); 566 bool firstOp = true; 567 568 // Destination 569 if (rd != INTREG_ZERO) { 570 firstOp = false; 571 printReg(os, rd); 572 } 573 574 // Source 1. 575 if (rn != INTREG_ZERO) { 576 if (!firstOp) 577 os << ", "; 578 firstOp = false; 579 printReg(os, rn); 580 } 581 582 if (!firstOp) 583 os << ", "; 584 if (withImm) { 585 ccprintf(os, "#%ld", imm); 586 } else { 587 printShiftOperand(os, rm, immShift, shiftAmt, rs, type); 588 } 589} 590 591std::string 592ArmStaticInst::generateDisassembly(Addr pc, 593 const SymbolTable *symtab) const 594{ 595 std::stringstream ss; 596 printMnemonic(ss); 597 return ss.str(); 598} 599 600 601Fault 602ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const 603{ 604 switch (el) { 605 case EL1: 606 return std::make_shared<SupervisorTrap>(machInst, 0x1E00000, 607 EC_TRAPPED_SIMD_FP); 608 case EL2: 609 return std::make_shared<HypervisorTrap>(machInst, 0x1E00000, 610 EC_TRAPPED_SIMD_FP); 611 case EL3: 612 return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000, 613 EC_TRAPPED_SIMD_FP); 614 615 default: 616 panic("Illegal EL in advSIMDFPAccessTrap64\n"); 617 } 618} 619 620 621Fault 622ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const 623{ 624 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el; 625 626 if (ArmSystem::haveVirtualization(tc) && el <= EL2) { 627 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2); 628 if (cptrEnCheck.tfp) 629 return advSIMDFPAccessTrap64(EL2); 630 } 631 632 if (ArmSystem::haveSecurity(tc)) { 633 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 634 if (cptrEnCheck.tfp) 635 return advSIMDFPAccessTrap64(EL3); 636 } 637 638 return NoFault; 639} 640 641Fault 642ArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc, 643 CPSR cpsr, CPACR cpacr) const 644{ 645 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el; 646 if ((el == EL0 && cpacr.fpen != 0x3) || 647 (el == EL1 && !(cpacr.fpen & 0x1))) 648 return advSIMDFPAccessTrap64(EL1); 649 650 return checkFPAdvSIMDTrap64(tc, cpsr); 651} 652 653Fault 654ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc, 655 CPSR cpsr, CPACR cpacr, 656 NSACR nsacr, FPEXC fpexc, 657 bool fpexc_check, bool advsimd) const 658{ 659 const bool have_virtualization = ArmSystem::haveVirtualization(tc); 660 const bool have_security = ArmSystem::haveSecurity(tc); 661 const bool is_secure = inSecureState(tc); 662 const ExceptionLevel cur_el = opModeToEL(currOpMode(tc)); 663 664 if (cur_el == EL0 && ELIs64(tc, EL1)) 665 return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr); 666 667 uint8_t cpacr_cp10 = cpacr.cp10; 668 bool cpacr_asedis = cpacr.asedis; 669 670 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 671 if (nsacr.nsasedis) 672 cpacr_asedis = true; 673 if (nsacr.cp10 == 0) 674 cpacr_cp10 = 0; 675 } 676 677 if (cur_el != EL2) { 678 if (advsimd && cpacr_asedis) 679 return disabledFault(); 680 681 if ((cur_el == EL0 && cpacr_cp10 != 0x3) || 682 (cur_el != EL0 && !(cpacr_cp10 & 0x1))) 683 return disabledFault(); 684 } 685 686 if (fpexc_check && !fpexc.en) 687 return disabledFault(); 688 689 // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap -- 690 691 if (have_virtualization && !is_secure && ELIs64(tc, EL2)) 692 return checkFPAdvSIMDTrap64(tc, cpsr); 693 694 if (have_virtualization && !is_secure) { 695 HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR); 696 bool hcptr_cp10 = hcptr.tcp10; 697 bool hcptr_tase = hcptr.tase; 698 699 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 700 if (nsacr.nsasedis) 701 hcptr_tase = true; 702 if (nsacr.cp10) 703 hcptr_cp10 = true; 704 } 705 706 if ((advsimd && hcptr_tase) || hcptr_cp10) { 707 const uint32_t iss = advsimd ? (1 << 5) : 0xA; 708 if (cur_el == EL2) { 709 return std::make_shared<UndefinedInstruction>( 710 machInst, iss, 711 EC_TRAPPED_HCPTR, mnemonic); 712 } else { 713 return std::make_shared<HypervisorTrap>( 714 machInst, iss, 715 EC_TRAPPED_HCPTR); 716 } 717 718 } 719 } 720 721 if (have_security && ELIs64(tc, EL3)) { 722 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 723 if (cptrEnCheck.tfp) 724 return advSIMDFPAccessTrap64(EL3); 725 } 726 727 return NoFault; 728} 729 730 731static uint8_t 732getRestoredITBits(ThreadContext *tc, CPSR spsr) 733{ 734 // See: shared/functions/system/RestoredITBits in the ARM ARM 735 736 const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode); 737 const uint8_t it = itState(spsr); 738 739 if (!spsr.t || spsr.il) 740 return 0; 741 742 // The IT bits are forced to zero when they are set to a reserved 743 // value. 744 if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0) 745 return 0; 746 747 const bool itd = el == EL2 ? 748 ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd : 749 ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd; 750 751 // The IT bits are forced to zero when returning to A32 state, or 752 // when returning to an EL with the ITD bit set to 1, and the IT 753 // bits are describing a multi-instruction block. 754 if (itd && bits(it, 2, 0) != 0) 755 return 0; 756 757 return it; 758} 759 760static bool 761illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr) 762{ 763 const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode; 764 if (badMode(mode)) 765 return true; 766 767 const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode; 768 const ExceptionLevel target_el = opModeToEL(mode); 769 if (target_el > opModeToEL(cur_mode)) 770 return true; 771 772 if (target_el == EL3 && !ArmSystem::haveSecurity(tc)) 773 return true; 774 775 if (target_el == EL2 && !ArmSystem::haveVirtualization(tc)) 776 return true; 777 778 if (!spsr.width) { 779 // aarch64 780 if (!ArmSystem::highestELIs64(tc)) 781 return true; 782 783 if (spsr & 0x2) 784 return true; 785 if (target_el == EL0 && spsr.sp) 786 return true; 787 if (target_el == EL2 && !((SCR)tc->readMiscReg(MISCREG_SCR_EL3)).ns) 788 return false; 789 } else { 790 return badMode32(mode); 791 } 792 793 return false; 794} 795 796CPSR 797ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const 798{ 799 CPSR new_cpsr = 0; 800 801 // gem5 doesn't implement single-stepping, so force the SS bit to 802 // 0. 803 new_cpsr.ss = 0; 804 805 if (illegalExceptionReturn(tc, cpsr, spsr)) { 806 new_cpsr.il = 1; 807 } else { 808 new_cpsr.il = spsr.il; 809 if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) { 810 new_cpsr.il = 1; 811 } else if (spsr.width) { 812 new_cpsr.mode = spsr.mode; 813 } else { 814 new_cpsr.el = spsr.el; 815 new_cpsr.sp = spsr.sp; 816 } 817 } 818 819 new_cpsr.nz = spsr.nz; 820 new_cpsr.c = spsr.c; 821 new_cpsr.v = spsr.v; 822 if (new_cpsr.width) { 823 // aarch32 824 const ITSTATE it = getRestoredITBits(tc, spsr); 825 new_cpsr.q = spsr.q; 826 new_cpsr.ge = spsr.ge; 827 new_cpsr.e = spsr.e; 828 new_cpsr.aif = spsr.aif; 829 new_cpsr.t = spsr.t; 830 new_cpsr.it2 = it.top6; 831 new_cpsr.it1 = it.bottom2; 832 } else { 833 // aarch64 834 new_cpsr.daif = spsr.daif; 835 } 836 837 return new_cpsr; 838} 839 840 841 842}
|