static_inst.cc revision 12520:bbed47626525
1/* 2 * Copyright (c) 2010-2014, 2016-2018 ARM Limited 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Copyright (c) 2007-2008 The Florida State University 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Stephen Hines 42 */ 43 44#include "arch/arm/insts/static_inst.hh" 45 46#include "arch/arm/faults.hh" 47#include "base/condcodes.hh" 48#include "base/cprintf.hh" 49#include "base/loader/symtab.hh" 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 294void 295ArmStaticInst::printIntReg(std::ostream &os, RegIndex reg_idx) const 296{ 297 if (aarch64) { 298 if (reg_idx == INTREG_UREG0) 299 ccprintf(os, "ureg0"); 300 else if (reg_idx == INTREG_SPX) 301 ccprintf(os, "%s%s", (intWidth == 32) ? "w" : "", "sp"); 302 else if (reg_idx == INTREG_X31) 303 ccprintf(os, "%szr", (intWidth == 32) ? "w" : "x"); 304 else 305 ccprintf(os, "%s%d", (intWidth == 32) ? "w" : "x", reg_idx); 306 } else { 307 switch (reg_idx) { 308 case PCReg: 309 ccprintf(os, "pc"); 310 break; 311 case StackPointerReg: 312 ccprintf(os, "sp"); 313 break; 314 case FramePointerReg: 315 ccprintf(os, "fp"); 316 break; 317 case ReturnAddressReg: 318 ccprintf(os, "lr"); 319 break; 320 default: 321 ccprintf(os, "r%d", reg_idx); 322 break; 323 } 324 } 325} 326 327void 328ArmStaticInst::printFloatReg(std::ostream &os, RegIndex reg_idx) const 329{ 330 ccprintf(os, "f%d", reg_idx); 331} 332 333void 334ArmStaticInst::printVecReg(std::ostream &os, RegIndex reg_idx) const 335{ 336 ccprintf(os, "v%d", reg_idx); 337} 338 339void 340ArmStaticInst::printCCReg(std::ostream &os, RegIndex reg_idx) const 341{ 342 ccprintf(os, "cc_%s", ArmISA::ccRegName[reg_idx]); 343} 344 345void 346ArmStaticInst::printMiscReg(std::ostream &os, RegIndex reg_idx) const 347{ 348 assert(reg_idx < NUM_MISCREGS); 349 ccprintf(os, "%s", ArmISA::miscRegName[reg_idx]); 350} 351 352void 353ArmStaticInst::printMnemonic(std::ostream &os, 354 const std::string &suffix, 355 bool withPred, 356 bool withCond64, 357 ConditionCode cond64) const 358{ 359 os << " " << mnemonic; 360 if (withPred && !aarch64) { 361 printCondition(os, machInst.condCode); 362 os << suffix; 363 } else if (withCond64) { 364 os << "."; 365 printCondition(os, cond64); 366 os << suffix; 367 } 368 if (machInst.bigThumb) 369 os << ".w"; 370 os << " "; 371} 372 373void 374ArmStaticInst::printTarget(std::ostream &os, Addr target, 375 const SymbolTable *symtab) const 376{ 377 Addr symbolAddr; 378 std::string symbol; 379 380 if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) { 381 ccprintf(os, "<%s", symbol); 382 if (symbolAddr != target) 383 ccprintf(os, "+%d>", target - symbolAddr); 384 else 385 ccprintf(os, ">"); 386 } else { 387 ccprintf(os, "%#x", target); 388 } 389} 390 391void 392ArmStaticInst::printCondition(std::ostream &os, 393 unsigned code, 394 bool noImplicit) const 395{ 396 switch (code) { 397 case COND_EQ: 398 os << "eq"; 399 break; 400 case COND_NE: 401 os << "ne"; 402 break; 403 case COND_CS: 404 os << "cs"; 405 break; 406 case COND_CC: 407 os << "cc"; 408 break; 409 case COND_MI: 410 os << "mi"; 411 break; 412 case COND_PL: 413 os << "pl"; 414 break; 415 case COND_VS: 416 os << "vs"; 417 break; 418 case COND_VC: 419 os << "vc"; 420 break; 421 case COND_HI: 422 os << "hi"; 423 break; 424 case COND_LS: 425 os << "ls"; 426 break; 427 case COND_GE: 428 os << "ge"; 429 break; 430 case COND_LT: 431 os << "lt"; 432 break; 433 case COND_GT: 434 os << "gt"; 435 break; 436 case COND_LE: 437 os << "le"; 438 break; 439 case COND_AL: 440 // This one is implicit. 441 if (noImplicit) 442 os << "al"; 443 break; 444 case COND_UC: 445 // Unconditional. 446 if (noImplicit) 447 os << "uc"; 448 break; 449 default: 450 panic("Unrecognized condition code %d.\n", code); 451 } 452} 453 454void 455ArmStaticInst::printMemSymbol(std::ostream &os, 456 const SymbolTable *symtab, 457 const std::string &prefix, 458 const Addr addr, 459 const std::string &suffix) const 460{ 461 Addr symbolAddr; 462 std::string symbol; 463 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) { 464 ccprintf(os, "%s%s", prefix, symbol); 465 if (symbolAddr != addr) 466 ccprintf(os, "+%d", addr - symbolAddr); 467 ccprintf(os, suffix); 468 } 469} 470 471void 472ArmStaticInst::printShiftOperand(std::ostream &os, 473 IntRegIndex rm, 474 bool immShift, 475 uint32_t shiftAmt, 476 IntRegIndex rs, 477 ArmShiftType type) const 478{ 479 bool firstOp = false; 480 481 if (rm != INTREG_ZERO) { 482 printIntReg(os, rm); 483 } 484 485 bool done = false; 486 487 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0) 488 shiftAmt = 32; 489 490 switch (type) { 491 case LSL: 492 if (immShift && shiftAmt == 0) { 493 done = true; 494 break; 495 } 496 if (!firstOp) 497 os << ", "; 498 os << "LSL"; 499 break; 500 case LSR: 501 if (!firstOp) 502 os << ", "; 503 os << "LSR"; 504 break; 505 case ASR: 506 if (!firstOp) 507 os << ", "; 508 os << "ASR"; 509 break; 510 case ROR: 511 if (immShift && shiftAmt == 0) { 512 if (!firstOp) 513 os << ", "; 514 os << "RRX"; 515 done = true; 516 break; 517 } 518 if (!firstOp) 519 os << ", "; 520 os << "ROR"; 521 break; 522 default: 523 panic("Tried to disassemble unrecognized shift type.\n"); 524 } 525 if (!done) { 526 if (!firstOp) 527 os << " "; 528 if (immShift) 529 os << "#" << shiftAmt; 530 else 531 printIntReg(os, rs); 532 } 533} 534 535void 536ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os, 537 IntRegIndex rm, ArmExtendType type, 538 int64_t shiftAmt) const 539{ 540 if (!firstOperand) 541 ccprintf(os, ", "); 542 printIntReg(os, rm); 543 if (type == UXTX && shiftAmt == 0) 544 return; 545 switch (type) { 546 case UXTB: ccprintf(os, ", UXTB"); 547 break; 548 case UXTH: ccprintf(os, ", UXTH"); 549 break; 550 case UXTW: ccprintf(os, ", UXTW"); 551 break; 552 case UXTX: ccprintf(os, ", LSL"); 553 break; 554 case SXTB: ccprintf(os, ", SXTB"); 555 break; 556 case SXTH: ccprintf(os, ", SXTH"); 557 break; 558 case SXTW: ccprintf(os, ", SXTW"); 559 break; 560 case SXTX: ccprintf(os, ", SXTW"); 561 break; 562 } 563 if (type == UXTX || shiftAmt) 564 ccprintf(os, " #%d", shiftAmt); 565} 566 567void 568ArmStaticInst::printDataInst(std::ostream &os, bool withImm, 569 bool immShift, bool s, IntRegIndex rd, IntRegIndex rn, 570 IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt, 571 ArmShiftType type, uint64_t imm) const 572{ 573 printMnemonic(os, s ? "s" : ""); 574 bool firstOp = true; 575 576 // Destination 577 if (rd != INTREG_ZERO) { 578 firstOp = false; 579 printIntReg(os, rd); 580 } 581 582 // Source 1. 583 if (rn != INTREG_ZERO) { 584 if (!firstOp) 585 os << ", "; 586 firstOp = false; 587 printIntReg(os, rn); 588 } 589 590 if (!firstOp) 591 os << ", "; 592 if (withImm) { 593 ccprintf(os, "#%ld", imm); 594 } else { 595 printShiftOperand(os, rm, immShift, shiftAmt, rs, type); 596 } 597} 598 599std::string 600ArmStaticInst::generateDisassembly(Addr pc, 601 const SymbolTable *symtab) const 602{ 603 std::stringstream ss; 604 printMnemonic(ss); 605 return ss.str(); 606} 607 608 609Fault 610ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const 611{ 612 switch (el) { 613 case EL1: 614 return std::make_shared<SupervisorTrap>(machInst, 0x1E00000, 615 EC_TRAPPED_SIMD_FP); 616 case EL2: 617 return std::make_shared<HypervisorTrap>(machInst, 0x1E00000, 618 EC_TRAPPED_SIMD_FP); 619 case EL3: 620 return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000, 621 EC_TRAPPED_SIMD_FP); 622 623 default: 624 panic("Illegal EL in advSIMDFPAccessTrap64\n"); 625 } 626} 627 628 629Fault 630ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const 631{ 632 if (ArmSystem::haveVirtualization(tc) && !inSecureState(tc)) { 633 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2); 634 if (cptrEnCheck.tfp) 635 return advSIMDFPAccessTrap64(EL2); 636 } 637 638 if (ArmSystem::haveSecurity(tc)) { 639 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 640 if (cptrEnCheck.tfp) 641 return advSIMDFPAccessTrap64(EL3); 642 } 643 644 return NoFault; 645} 646 647Fault 648ArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc, 649 CPSR cpsr, CPACR cpacr) const 650{ 651 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el; 652 if ((el == EL0 && cpacr.fpen != 0x3) || 653 (el == EL1 && !(cpacr.fpen & 0x1))) 654 return advSIMDFPAccessTrap64(EL1); 655 656 return checkFPAdvSIMDTrap64(tc, cpsr); 657} 658 659Fault 660ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc, 661 CPSR cpsr, CPACR cpacr, 662 NSACR nsacr, FPEXC fpexc, 663 bool fpexc_check, bool advsimd) const 664{ 665 const bool have_virtualization = ArmSystem::haveVirtualization(tc); 666 const bool have_security = ArmSystem::haveSecurity(tc); 667 const bool is_secure = inSecureState(tc); 668 const ExceptionLevel cur_el = opModeToEL(currOpMode(tc)); 669 670 if (cur_el == EL0 && ELIs64(tc, EL1)) 671 return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr); 672 673 uint8_t cpacr_cp10 = cpacr.cp10; 674 bool cpacr_asedis = cpacr.asedis; 675 676 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 677 if (nsacr.nsasedis) 678 cpacr_asedis = true; 679 if (nsacr.cp10 == 0) 680 cpacr_cp10 = 0; 681 } 682 683 if (cur_el != EL2) { 684 if (advsimd && cpacr_asedis) 685 return disabledFault(); 686 687 if ((cur_el == EL0 && cpacr_cp10 != 0x3) || 688 (cur_el != EL0 && !(cpacr_cp10 & 0x1))) 689 return disabledFault(); 690 } 691 692 if (fpexc_check && !fpexc.en) 693 return disabledFault(); 694 695 // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap -- 696 697 if (have_virtualization && !is_secure && ELIs64(tc, EL2)) 698 return checkFPAdvSIMDTrap64(tc, cpsr); 699 700 if (have_virtualization && !is_secure) { 701 HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR); 702 bool hcptr_cp10 = hcptr.tcp10; 703 bool hcptr_tase = hcptr.tase; 704 705 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 706 if (nsacr.nsasedis) 707 hcptr_tase = true; 708 if (nsacr.cp10) 709 hcptr_cp10 = true; 710 } 711 712 if ((advsimd && hcptr_tase) || hcptr_cp10) { 713 const uint32_t iss = advsimd ? (1 << 5) : 0xA; 714 if (cur_el == EL2) { 715 return std::make_shared<UndefinedInstruction>( 716 machInst, iss, 717 EC_TRAPPED_HCPTR, mnemonic); 718 } else { 719 return std::make_shared<HypervisorTrap>( 720 machInst, iss, 721 EC_TRAPPED_HCPTR); 722 } 723 724 } 725 } 726 727 if (have_security && ELIs64(tc, EL3)) { 728 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 729 if (cptrEnCheck.tfp) 730 return advSIMDFPAccessTrap64(EL3); 731 } 732 733 return NoFault; 734} 735 736inline bool 737ArmStaticInst::isWFxTrapping(ThreadContext *tc, 738 ExceptionLevel tgtEl, 739 bool isWfe) const 740{ 741 bool trap = false; 742 SCTLR sctlr = ((SCTLR)tc->readMiscReg(MISCREG_SCTLR_EL1)); 743 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 744 SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3)); 745 746 switch (tgtEl) { 747 case EL1: 748 trap = isWfe? !sctlr.ntwe : !sctlr.ntwi; 749 break; 750 case EL2: 751 trap = isWfe? hcr.twe : hcr.twi; 752 break; 753 case EL3: 754 trap = isWfe? scr.twe : scr.twi; 755 break; 756 default: 757 break; 758 } 759 760 return trap; 761} 762 763Fault 764ArmStaticInst::checkForWFxTrap32(ThreadContext *tc, 765 ExceptionLevel targetEL, 766 bool isWfe) const 767{ 768 // Check if target exception level is implemented. 769 assert(ArmSystem::haveEL(tc, targetEL)); 770 771 // Check for routing to AArch64: this happens if the 772 // target exception level (where the trap will be handled) 773 // is using aarch64 774 if (ELIs64(tc, targetEL)) { 775 return checkForWFxTrap64(tc, targetEL, isWfe); 776 } 777 778 // Check if processor needs to trap at selected exception level 779 bool trap = isWFxTrapping(tc, targetEL, isWfe); 780 781 if (trap) { 782 uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */ 783 0x1E00000; /* WFI Instruction syndrome */ 784 switch (targetEL) { 785 case EL1: 786 return std::make_shared<UndefinedInstruction>( 787 machInst, iss, 788 EC_TRAPPED_WFI_WFE, mnemonic); 789 case EL2: 790 return std::make_shared<HypervisorTrap>(machInst, iss, 791 EC_TRAPPED_WFI_WFE); 792 case EL3: 793 return std::make_shared<SecureMonitorTrap>(machInst, iss, 794 EC_TRAPPED_WFI_WFE); 795 default: 796 panic("Unrecognized Exception Level: %d\n", targetEL); 797 } 798 } 799 800 return NoFault; 801} 802 803Fault 804ArmStaticInst::checkForWFxTrap64(ThreadContext *tc, 805 ExceptionLevel targetEL, 806 bool isWfe) const 807{ 808 // Check if target exception level is implemented. 809 assert(ArmSystem::haveEL(tc, targetEL)); 810 811 // Check if processor needs to trap at selected exception level 812 bool trap = isWFxTrapping(tc, targetEL, isWfe); 813 814 if (trap) { 815 uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */ 816 0x1E00000; /* WFI Instruction syndrome */ 817 switch (targetEL) { 818 case EL1: 819 return std::make_shared<SupervisorTrap>(machInst, iss, 820 EC_TRAPPED_WFI_WFE); 821 case EL2: 822 return std::make_shared<HypervisorTrap>(machInst, iss, 823 EC_TRAPPED_WFI_WFE); 824 case EL3: 825 return std::make_shared<SecureMonitorTrap>(machInst, iss, 826 EC_TRAPPED_WFI_WFE); 827 default: 828 panic("Unrecognized Exception Level: %d\n", targetEL); 829 } 830 } 831 832 return NoFault; 833} 834 835Fault 836ArmStaticInst::trapWFx(ThreadContext *tc, 837 CPSR cpsr, SCR scr, 838 bool isWfe) const 839{ 840 Fault fault = NoFault; 841 if (cpsr.el == EL0) { 842 fault = checkForWFxTrap32(tc, EL1, isWfe); 843 } 844 845 if ((fault == NoFault) && 846 ArmSystem::haveEL(tc, EL2) && !inSecureState(scr, cpsr) && 847 ((cpsr.el == EL0) || (cpsr.el == EL1))) { 848 849 fault = checkForWFxTrap32(tc, EL2, isWfe); 850 } 851 852 if ((fault == NoFault) && 853 ArmSystem::haveEL(tc, EL3) && cpsr.el != EL3) { 854 fault = checkForWFxTrap32(tc, EL3, isWfe); 855 } 856 857 return fault; 858} 859 860Fault 861ArmStaticInst::checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const 862{ 863 bool setend_disabled(false); 864 ExceptionLevel pstateEL = (ExceptionLevel)(uint8_t)(cpsr.el); 865 866 if (pstateEL == EL2) { 867 setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(MISCREG_HSCTLR)).sed; 868 } else { 869 // Please note: in the armarm pseudocode there is a distinction 870 // whether EL1 is aarch32 or aarch64: 871 // if ELUsingAArch32(EL1) then SCTLR.SED else SCTLR[].SED; 872 // Considering that SETEND is aarch32 only, ELUsingAArch32(EL1) 873 // will always be true (hence using SCTLR.SED) except for 874 // instruction executed at EL0, and with an AArch64 EL1. 875 // In this case SCTLR_EL1 will be used. In gem5 the register is 876 // mapped to SCTLR_ns. We can safely use SCTLR and choose the 877 // appropriate bank version. 878 879 // Get the index of the banked version of SCTLR: 880 // SCTLR_s or SCTLR_ns. 881 auto banked_sctlr = snsBankedIndex( 882 MISCREG_SCTLR, tc, !inSecureState(tc)); 883 884 // SCTLR.SED bit is enabling/disabling the ue of SETEND instruction. 885 setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(banked_sctlr)).sed; 886 } 887 888 return setend_disabled ? undefinedFault32(tc, pstateEL) : 889 NoFault; 890} 891 892Fault 893ArmStaticInst::undefinedFault32(ThreadContext *tc, 894 ExceptionLevel pstateEL) const 895{ 896 // Even if we are running in aarch32, the fault might be dealt with in 897 // aarch64 ISA. 898 if (generalExceptionsToAArch64(tc, pstateEL)) { 899 return undefinedFault64(tc, pstateEL); 900 } else { 901 // Please note: according to the ARM ARM pseudocode we should handle 902 // the case when EL2 is aarch64 and HCR.TGE is 1 as well. 903 // However this case is already handled by the routeToHyp method in 904 // ArmFault class. 905 return std::make_shared<UndefinedInstruction>( 906 machInst, 0, 907 EC_UNKNOWN, mnemonic); 908 } 909} 910 911Fault 912ArmStaticInst::undefinedFault64(ThreadContext *tc, 913 ExceptionLevel pstateEL) const 914{ 915 switch (pstateEL) { 916 case EL0: 917 case EL1: 918 return std::make_shared<SupervisorTrap>(machInst, 0, EC_UNKNOWN); 919 case EL2: 920 return std::make_shared<HypervisorTrap>(machInst, 0, EC_UNKNOWN); 921 case EL3: 922 return std::make_shared<SecureMonitorTrap>(machInst, 0, EC_UNKNOWN); 923 default: 924 panic("Unrecognized Exception Level: %d\n", pstateEL); 925 break; 926 } 927 928 return NoFault; 929} 930 931static uint8_t 932getRestoredITBits(ThreadContext *tc, CPSR spsr) 933{ 934 // See: shared/functions/system/RestoredITBits in the ARM ARM 935 936 const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode); 937 const uint8_t it = itState(spsr); 938 939 if (!spsr.t || spsr.il) 940 return 0; 941 942 // The IT bits are forced to zero when they are set to a reserved 943 // value. 944 if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0) 945 return 0; 946 947 const bool itd = el == EL2 ? 948 ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd : 949 ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd; 950 951 // The IT bits are forced to zero when returning to A32 state, or 952 // when returning to an EL with the ITD bit set to 1, and the IT 953 // bits are describing a multi-instruction block. 954 if (itd && bits(it, 2, 0) != 0) 955 return 0; 956 957 return it; 958} 959 960static bool 961illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr) 962{ 963 const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode; 964 if (badMode(mode)) 965 return true; 966 967 const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode; 968 const ExceptionLevel target_el = opModeToEL(mode); 969 970 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 971 SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3)); 972 973 if (target_el > opModeToEL(cur_mode)) 974 return true; 975 976 if (!ArmSystem::haveEL(tc, target_el)) 977 return true; 978 979 if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && scr.ns && hcr.tge) 980 return true; 981 982 if (target_el == EL2 && ArmSystem::haveEL(tc, EL3) && !scr.ns) 983 return true; 984 985 bool spsr_mode_is_aarch32 = (spsr.width == 1); 986 bool known, target_el_is_aarch32; 987 std::tie(known, target_el_is_aarch32) = ELUsingAArch32K(tc, target_el); 988 assert(known || (target_el == EL0 && ELIs64(tc, EL1))); 989 990 if (known && (spsr_mode_is_aarch32 != target_el_is_aarch32)) 991 return true; 992 993 if (!spsr.width) { 994 // aarch64 995 if (!ArmSystem::highestELIs64(tc)) 996 return true; 997 if (spsr & 0x2) 998 return true; 999 if (target_el == EL0 && spsr.sp) 1000 return true; 1001 } else { 1002 // aarch32 1003 return badMode32(mode); 1004 } 1005 1006 return false; 1007} 1008 1009CPSR 1010ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const 1011{ 1012 CPSR new_cpsr = 0; 1013 1014 // gem5 doesn't implement single-stepping, so force the SS bit to 1015 // 0. 1016 new_cpsr.ss = 0; 1017 1018 if (illegalExceptionReturn(tc, cpsr, spsr)) { 1019 // If the SPSR specifies an illegal exception return, 1020 // then PSTATE.{M, nRW, EL, SP} are unchanged and PSTATE.IL 1021 // is set to 1. 1022 new_cpsr.il = 1; 1023 if (cpsr.width) { 1024 new_cpsr.mode = cpsr.mode; 1025 } else { 1026 new_cpsr.width = cpsr.width; 1027 new_cpsr.el = cpsr.el; 1028 new_cpsr.sp = cpsr.sp; 1029 } 1030 } else { 1031 new_cpsr.il = spsr.il; 1032 if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) { 1033 new_cpsr.il = 1; 1034 } else if (spsr.width) { 1035 new_cpsr.mode = spsr.mode; 1036 } else { 1037 new_cpsr.el = spsr.el; 1038 new_cpsr.sp = spsr.sp; 1039 } 1040 } 1041 1042 new_cpsr.nz = spsr.nz; 1043 new_cpsr.c = spsr.c; 1044 new_cpsr.v = spsr.v; 1045 if (new_cpsr.width) { 1046 // aarch32 1047 const ITSTATE it = getRestoredITBits(tc, spsr); 1048 new_cpsr.q = spsr.q; 1049 new_cpsr.ge = spsr.ge; 1050 new_cpsr.e = spsr.e; 1051 new_cpsr.aif = spsr.aif; 1052 new_cpsr.t = spsr.t; 1053 new_cpsr.it2 = it.top6; 1054 new_cpsr.it1 = it.bottom2; 1055 } else { 1056 // aarch64 1057 new_cpsr.daif = spsr.daif; 1058 } 1059 1060 return new_cpsr; 1061} 1062 1063bool 1064ArmStaticInst::generalExceptionsToAArch64(ThreadContext *tc, 1065 ExceptionLevel pstateEL) const 1066{ 1067 // Returns TRUE if exceptions normally routed to EL1 are being handled 1068 // at an Exception level using AArch64, because either EL1 is using 1069 // AArch64 or TGE is in force and EL2 is using AArch64. 1070 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 1071 return (pstateEL == EL0 && !ELIs32(tc, EL1)) || 1072 (ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) && 1073 !ELIs32(tc, EL2) && hcr.tge); 1074} 1075 1076 1077} 1078