1/* 2 * Copyright (c) 2010-2014, 2016-2019 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 "arch/arm/isa.hh" 48#include "base/condcodes.hh" 49#include "base/cprintf.hh" 50#include "base/loader/symtab.hh" 51#include "cpu/reg_class.hh" 52 53namespace ArmISA 54{ 55// Shift Rm by an immediate value 56int32_t 57ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, 58 uint32_t type, uint32_t cfval) const 59{ 60 assert(shamt < 32); 61 ArmShiftType shiftType; 62 shiftType = (ArmShiftType)type; 63 64 switch (shiftType) 65 { 66 case LSL: 67 return base << shamt; 68 case LSR: 69 if (shamt == 0) 70 return 0; 71 else 72 return base >> shamt; 73 case ASR: 74 if (shamt == 0) 75 return (base >> 31) | -((base & (1 << 31)) >> 31); 76 else 77 return (base >> shamt) | -((base & (1 << 31)) >> shamt); 78 case ROR: 79 if (shamt == 0) 80 return (cfval << 31) | (base >> 1); // RRX 81 else 82 return (base << (32 - shamt)) | (base >> shamt); 83 default: 84 ccprintf(std::cerr, "Unhandled shift type\n"); 85 exit(1); 86 break; 87 } 88 return 0; 89} 90 91int64_t 92ArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt, 93 ArmShiftType type, uint8_t width) const 94{ 95 shiftAmt = shiftAmt % width; 96 ArmShiftType shiftType; 97 shiftType = (ArmShiftType)type; 98 99 switch (shiftType) 100 { 101 case LSL: 102 return base << shiftAmt; 103 case LSR: 104 if (shiftAmt == 0) 105 return base; 106 else 107 return (base & mask(width)) >> shiftAmt; 108 case ASR: 109 if (shiftAmt == 0) { 110 return base; 111 } else { 112 int sign_bit = bits(base, intWidth - 1); 113 base >>= shiftAmt; 114 base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base; 115 return base & mask(intWidth); 116 } 117 case ROR: 118 if (shiftAmt == 0) 119 return base; 120 else 121 return (base << (width - shiftAmt)) | (base >> shiftAmt); 122 default: 123 ccprintf(std::cerr, "Unhandled shift type\n"); 124 exit(1); 125 break; 126 } 127 return 0; 128} 129 130int64_t 131ArmStaticInst::extendReg64(uint64_t base, ArmExtendType type, 132 uint64_t shiftAmt, uint8_t width) const 133{ 134 bool sign_extend = false; 135 int len = 0; 136 switch (type) { 137 case UXTB: 138 len = 8; 139 break; 140 case UXTH: 141 len = 16; 142 break; 143 case UXTW: 144 len = 32; 145 break; 146 case UXTX: 147 len = 64; 148 break; 149 case SXTB: 150 len = 8; 151 sign_extend = true; 152 break; 153 case SXTH: 154 len = 16; 155 sign_extend = true; 156 break; 157 case SXTW: 158 len = 32; 159 sign_extend = true; 160 break; 161 case SXTX: 162 len = 64; 163 sign_extend = true; 164 break; 165 } 166 len = len <= width - shiftAmt ? len : width - shiftAmt; 167 uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt; 168 if (sign_extend) { 169 int sign_bit = bits(tmp, len + shiftAmt - 1); 170 tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp; 171 } 172 return tmp & mask(width); 173} 174 175// Shift Rm by Rs 176int32_t 177ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, 178 uint32_t type, uint32_t cfval) const 179{ 180 enum ArmShiftType shiftType; 181 shiftType = (enum ArmShiftType) type; 182 183 switch (shiftType) 184 { 185 case LSL: 186 if (shamt >= 32) 187 return 0; 188 else 189 return base << shamt; 190 case LSR: 191 if (shamt >= 32) 192 return 0; 193 else 194 return base >> shamt; 195 case ASR: 196 if (shamt >= 32) 197 return (base >> 31) | -((base & (1 << 31)) >> 31); 198 else 199 return (base >> shamt) | -((base & (1 << 31)) >> shamt); 200 case ROR: 201 shamt = shamt & 0x1f; 202 if (shamt == 0) 203 return base; 204 else 205 return (base << (32 - shamt)) | (base >> shamt); 206 default: 207 ccprintf(std::cerr, "Unhandled shift type\n"); 208 exit(1); 209 break; 210 } 211 return 0; 212} 213 214 215// Generate C for a shift by immediate 216bool 217ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, 218 uint32_t type, uint32_t cfval) const 219{ 220 enum ArmShiftType shiftType; 221 shiftType = (enum ArmShiftType) type; 222 223 switch (shiftType) 224 { 225 case LSL: 226 if (shamt == 0) 227 return cfval; 228 else 229 return (base >> (32 - shamt)) & 1; 230 case LSR: 231 if (shamt == 0) 232 return (base >> 31); 233 else 234 return (base >> (shamt - 1)) & 1; 235 case ASR: 236 if (shamt == 0) 237 return (base >> 31); 238 else 239 return (base >> (shamt - 1)) & 1; 240 case ROR: 241 shamt = shamt & 0x1f; 242 if (shamt == 0) 243 return (base & 1); // RRX 244 else 245 return (base >> (shamt - 1)) & 1; 246 default: 247 ccprintf(std::cerr, "Unhandled shift type\n"); 248 exit(1); 249 break; 250 } 251 return 0; 252} 253 254 255// Generate C for a shift by Rs 256bool 257ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, 258 uint32_t type, uint32_t cfval) const 259{ 260 enum ArmShiftType shiftType; 261 shiftType = (enum ArmShiftType) type; 262 263 if (shamt == 0) 264 return cfval; 265 266 switch (shiftType) 267 { 268 case LSL: 269 if (shamt > 32) 270 return 0; 271 else 272 return (base >> (32 - shamt)) & 1; 273 case LSR: 274 if (shamt > 32) 275 return 0; 276 else 277 return (base >> (shamt - 1)) & 1; 278 case ASR: 279 if (shamt > 32) 280 shamt = 32; 281 return (base >> (shamt - 1)) & 1; 282 case ROR: 283 shamt = shamt & 0x1f; 284 if (shamt == 0) 285 shamt = 32; 286 return (base >> (shamt - 1)) & 1; 287 default: 288 ccprintf(std::cerr, "Unhandled shift type\n"); 289 exit(1); 290 break; 291 } 292 return 0; 293} 294 295void 296ArmStaticInst::printIntReg(std::ostream &os, RegIndex reg_idx, 297 uint8_t opWidth) const 298{ 299 if (opWidth == 0) 300 opWidth = intWidth; 301 if (aarch64) { 302 if (reg_idx == INTREG_UREG0) 303 ccprintf(os, "ureg0"); 304 else if (reg_idx == INTREG_SPX) 305 ccprintf(os, "%s%s", (opWidth == 32) ? "w" : "", "sp"); 306 else if (reg_idx == INTREG_X31) 307 ccprintf(os, "%szr", (opWidth == 32) ? "w" : "x"); 308 else 309 ccprintf(os, "%s%d", (opWidth == 32) ? "w" : "x", reg_idx); 310 } else { 311 switch (reg_idx) { 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_idx); 326 break; 327 } 328 } 329} 330 331void ArmStaticInst::printPFflags(std::ostream &os, int flag) const 332{ 333 const char *flagtoprfop[]= { "PLD", "PLI", "PST", "Reserved"}; 334 const char *flagtotarget[] = { "L1", "L2", "L3", "Reserved"}; 335 const char *flagtopolicy[] = { "KEEP", "STRM"}; 336 337 ccprintf(os, "%s%s%s", flagtoprfop[(flag>>3)&3], 338 flagtotarget[(flag>>1)&3], flagtopolicy[flag&1]); 339} 340 341void 342ArmStaticInst::printFloatReg(std::ostream &os, RegIndex reg_idx) const 343{ 344 ccprintf(os, "f%d", reg_idx); 345} 346 347void 348ArmStaticInst::printVecReg(std::ostream &os, RegIndex reg_idx, 349 bool isSveVecReg) const 350{ 351 ccprintf(os, "%s%d", isSveVecReg ? "z" : "v", reg_idx); 352} 353 354void 355ArmStaticInst::printVecPredReg(std::ostream &os, RegIndex reg_idx) const 356{ 357 ccprintf(os, "p%d", reg_idx); 358} 359 360void 361ArmStaticInst::printCCReg(std::ostream &os, RegIndex reg_idx) const 362{ 363 ccprintf(os, "cc_%s", ArmISA::ccRegName[reg_idx]); 364} 365 366void 367ArmStaticInst::printMiscReg(std::ostream &os, RegIndex reg_idx) const 368{ 369 assert(reg_idx < NUM_MISCREGS); 370 ccprintf(os, "%s", ArmISA::miscRegName[reg_idx]); 371} 372 373void 374ArmStaticInst::printMnemonic(std::ostream &os, 375 const std::string &suffix, 376 bool withPred, 377 bool withCond64, 378 ConditionCode cond64) const 379{ 380 os << " " << mnemonic; 381 if (withPred && !aarch64) { 382 printCondition(os, machInst.condCode); 383 os << suffix; 384 } else if (withCond64) { 385 os << "."; 386 printCondition(os, cond64); 387 os << suffix; 388 } 389 if (machInst.bigThumb) 390 os << ".w"; 391 os << " "; 392} 393 394void 395ArmStaticInst::printTarget(std::ostream &os, Addr target, 396 const SymbolTable *symtab) const 397{ 398 Addr symbolAddr; 399 std::string symbol; 400 401 if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) { 402 ccprintf(os, "<%s", symbol); 403 if (symbolAddr != target) 404 ccprintf(os, "+%d>", target - symbolAddr); 405 else 406 ccprintf(os, ">"); 407 } else { 408 ccprintf(os, "%#x", target); 409 } 410} 411 412void 413ArmStaticInst::printCondition(std::ostream &os, 414 unsigned code, 415 bool noImplicit) const 416{ 417 switch (code) { 418 case COND_EQ: 419 os << "eq"; 420 break; 421 case COND_NE: 422 os << "ne"; 423 break; 424 case COND_CS: 425 os << "cs"; 426 break; 427 case COND_CC: 428 os << "cc"; 429 break; 430 case COND_MI: 431 os << "mi"; 432 break; 433 case COND_PL: 434 os << "pl"; 435 break; 436 case COND_VS: 437 os << "vs"; 438 break; 439 case COND_VC: 440 os << "vc"; 441 break; 442 case COND_HI: 443 os << "hi"; 444 break; 445 case COND_LS: 446 os << "ls"; 447 break; 448 case COND_GE: 449 os << "ge"; 450 break; 451 case COND_LT: 452 os << "lt"; 453 break; 454 case COND_GT: 455 os << "gt"; 456 break; 457 case COND_LE: 458 os << "le"; 459 break; 460 case COND_AL: 461 // This one is implicit. 462 if (noImplicit) 463 os << "al"; 464 break; 465 case COND_UC: 466 // Unconditional. 467 if (noImplicit) 468 os << "uc"; 469 break; 470 default: 471 panic("Unrecognized condition code %d.\n", code); 472 } 473} 474 475void 476ArmStaticInst::printMemSymbol(std::ostream &os, 477 const SymbolTable *symtab, 478 const std::string &prefix, 479 const Addr addr, 480 const std::string &suffix) const 481{ 482 Addr symbolAddr; 483 std::string symbol; 484 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) { 485 ccprintf(os, "%s%s", prefix, symbol); 486 if (symbolAddr != addr) 487 ccprintf(os, "+%d", addr - symbolAddr); 488 ccprintf(os, suffix); 489 } 490} 491 492void 493ArmStaticInst::printShiftOperand(std::ostream &os, 494 IntRegIndex rm, 495 bool immShift, 496 uint32_t shiftAmt, 497 IntRegIndex rs, 498 ArmShiftType type) const 499{ 500 bool firstOp = false; 501 502 if (rm != INTREG_ZERO) { 503 printIntReg(os, rm); 504 } 505 506 bool done = false; 507 508 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0) 509 shiftAmt = 32; 510 511 switch (type) { 512 case LSL: 513 if (immShift && shiftAmt == 0) { 514 done = true; 515 break; 516 } 517 if (!firstOp) 518 os << ", "; 519 os << "LSL"; 520 break; 521 case LSR: 522 if (!firstOp) 523 os << ", "; 524 os << "LSR"; 525 break; 526 case ASR: 527 if (!firstOp) 528 os << ", "; 529 os << "ASR"; 530 break; 531 case ROR: 532 if (immShift && shiftAmt == 0) { 533 if (!firstOp) 534 os << ", "; 535 os << "RRX"; 536 done = true; 537 break; 538 } 539 if (!firstOp) 540 os << ", "; 541 os << "ROR"; 542 break; 543 default: 544 panic("Tried to disassemble unrecognized shift type.\n"); 545 } 546 if (!done) { 547 if (!firstOp) 548 os << " "; 549 if (immShift) 550 os << "#" << shiftAmt; 551 else 552 printIntReg(os, rs); 553 } 554} 555 556void 557ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os, 558 IntRegIndex rm, ArmExtendType type, 559 int64_t shiftAmt) const 560{ 561 if (!firstOperand) 562 ccprintf(os, ", "); 563 printIntReg(os, rm); 564 if (type == UXTX && shiftAmt == 0) 565 return; 566 switch (type) { 567 case UXTB: ccprintf(os, ", UXTB"); 568 break; 569 case UXTH: ccprintf(os, ", UXTH"); 570 break; 571 case UXTW: ccprintf(os, ", UXTW"); 572 break; 573 case UXTX: ccprintf(os, ", LSL"); 574 break; 575 case SXTB: ccprintf(os, ", SXTB"); 576 break; 577 case SXTH: ccprintf(os, ", SXTH"); 578 break; 579 case SXTW: ccprintf(os, ", SXTW"); 580 break; 581 case SXTX: ccprintf(os, ", SXTW"); 582 break; 583 } 584 if (type == UXTX || shiftAmt) 585 ccprintf(os, " #%d", shiftAmt); 586} 587 588void 589ArmStaticInst::printDataInst(std::ostream &os, bool withImm, 590 bool immShift, bool s, IntRegIndex rd, IntRegIndex rn, 591 IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt, 592 ArmShiftType type, uint64_t imm) const 593{ 594 printMnemonic(os, s ? "s" : ""); 595 bool firstOp = true; 596 597 // Destination 598 if (rd != INTREG_ZERO) { 599 firstOp = false; 600 printIntReg(os, rd); 601 } 602 603 // Source 1. 604 if (rn != INTREG_ZERO) { 605 if (!firstOp) 606 os << ", "; 607 firstOp = false; 608 printIntReg(os, rn); 609 } 610 611 if (!firstOp) 612 os << ", "; 613 if (withImm) { 614 ccprintf(os, "#%ld", imm); 615 } else { 616 printShiftOperand(os, rm, immShift, shiftAmt, rs, type); 617 } 618} 619 620std::string 621ArmStaticInst::generateDisassembly(Addr pc, 622 const SymbolTable *symtab) const 623{ 624 std::stringstream ss; 625 printMnemonic(ss); 626 return ss.str(); 627} 628 629Fault 630ArmStaticInst::softwareBreakpoint32(ExecContext *xc, uint16_t imm) const 631{ 632 const auto tc = xc->tcBase(); 633 const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); 634 const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2); 635 if ((ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) && 636 !ELIs32(tc, EL2) && (hcr.tge == 1 || mdcr.tde == 1)) || 637 !ELIs32(tc, EL1)) { 638 // Route to AArch64 Software Breakpoint 639 return std::make_shared<SoftwareBreakpoint>(machInst, imm); 640 } else { 641 // Execute AArch32 Software Breakpoint 642 return std::make_shared<PrefetchAbort>(readPC(xc), 643 ArmFault::DebugEvent); 644 } 645} 646 647Fault 648ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const 649{ 650 switch (el) { 651 case EL1: 652 return std::make_shared<SupervisorTrap>(machInst, 0x1E00000, 653 EC_TRAPPED_SIMD_FP); 654 case EL2: 655 return std::make_shared<HypervisorTrap>(machInst, 0x1E00000, 656 EC_TRAPPED_SIMD_FP); 657 case EL3: 658 return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000, 659 EC_TRAPPED_SIMD_FP); 660 661 default: 662 panic("Illegal EL in advSIMDFPAccessTrap64\n"); 663 } 664} 665 666 667Fault 668ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const 669{ 670 if (ArmSystem::haveVirtualization(tc) && !inSecureState(tc)) { 671 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2); 672 if (cptrEnCheck.tfp) 673 return advSIMDFPAccessTrap64(EL2); 674 } 675 676 if (ArmSystem::haveSecurity(tc)) { 677 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 678 if (cptrEnCheck.tfp) 679 return advSIMDFPAccessTrap64(EL3); 680 } 681 682 return NoFault; 683} 684 685Fault 686ArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc, 687 CPSR cpsr, CPACR cpacr) const 688{ 689 const ExceptionLevel el = currEL(tc); 690 if ((el == EL0 && cpacr.fpen != 0x3) || 691 (el == EL1 && !(cpacr.fpen & 0x1))) 692 return advSIMDFPAccessTrap64(EL1); 693 694 return checkFPAdvSIMDTrap64(tc, cpsr); 695} 696 697Fault 698ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc, 699 CPSR cpsr, CPACR cpacr, 700 NSACR nsacr, FPEXC fpexc, 701 bool fpexc_check, bool advsimd) const 702{ 703 const bool have_virtualization = ArmSystem::haveVirtualization(tc); 704 const bool have_security = ArmSystem::haveSecurity(tc); 705 const bool is_secure = inSecureState(tc); 706 const ExceptionLevel cur_el = currEL(tc); 707 708 if (cur_el == EL0 && ELIs64(tc, EL1)) 709 return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr); 710 711 uint8_t cpacr_cp10 = cpacr.cp10; 712 bool cpacr_asedis = cpacr.asedis; 713 714 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 715 if (nsacr.nsasedis) 716 cpacr_asedis = true; 717 if (nsacr.cp10 == 0) 718 cpacr_cp10 = 0; 719 } 720 721 if (cur_el != EL2) { 722 if (advsimd && cpacr_asedis) 723 return disabledFault(); 724 725 if ((cur_el == EL0 && cpacr_cp10 != 0x3) || 726 (cur_el != EL0 && !(cpacr_cp10 & 0x1))) 727 return disabledFault(); 728 } 729 730 if (fpexc_check && !fpexc.en) 731 return disabledFault(); 732 733 // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap -- 734 735 if (have_virtualization && !is_secure && ELIs64(tc, EL2)) 736 return checkFPAdvSIMDTrap64(tc, cpsr); 737 738 if (have_virtualization && !is_secure) { 739 HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR); 740 bool hcptr_cp10 = hcptr.tcp10; 741 bool hcptr_tase = hcptr.tase; 742 743 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 744 if (nsacr.nsasedis) 745 hcptr_tase = true; 746 if (nsacr.cp10) 747 hcptr_cp10 = true; 748 } 749 750 if ((advsimd && hcptr_tase) || hcptr_cp10) { 751 const uint32_t iss = advsimd ? (1 << 5) : 0xA; 752 if (cur_el == EL2) { 753 return std::make_shared<UndefinedInstruction>( 754 machInst, iss, 755 EC_TRAPPED_HCPTR, mnemonic); 756 } else { 757 return std::make_shared<HypervisorTrap>( 758 machInst, iss, 759 EC_TRAPPED_HCPTR); 760 } 761 762 } 763 } 764 765 if (have_security && ELIs64(tc, EL3)) { 766 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 767 if (cptrEnCheck.tfp) 768 return advSIMDFPAccessTrap64(EL3); 769 } 770 771 return NoFault; 772} 773 774inline bool 775ArmStaticInst::isWFxTrapping(ThreadContext *tc, 776 ExceptionLevel tgtEl, 777 bool isWfe) const 778{ 779 bool trap = false; 780 SCTLR sctlr = ((SCTLR)tc->readMiscReg(MISCREG_SCTLR_EL1)); 781 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 782 SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3)); 783 784 switch (tgtEl) { 785 case EL1: 786 trap = isWfe? !sctlr.ntwe : !sctlr.ntwi; 787 break; 788 case EL2: 789 trap = isWfe? hcr.twe : hcr.twi; 790 break; 791 case EL3: 792 trap = isWfe? scr.twe : scr.twi; 793 break; 794 default: 795 break; 796 } 797 798 return trap; 799} 800 801Fault 802ArmStaticInst::checkForWFxTrap32(ThreadContext *tc, 803 ExceptionLevel targetEL, 804 bool isWfe) const 805{ 806 // Check if target exception level is implemented. 807 assert(ArmSystem::haveEL(tc, targetEL)); 808 809 // Check for routing to AArch64: this happens if the 810 // target exception level (where the trap will be handled) 811 // is using aarch64 812 if (ELIs64(tc, targetEL)) { 813 return checkForWFxTrap64(tc, targetEL, isWfe); 814 } 815 816 // Check if processor needs to trap at selected exception level 817 bool trap = isWFxTrapping(tc, targetEL, isWfe); 818 819 if (trap) { 820 uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */ 821 0x1E00000; /* WFI Instruction syndrome */ 822 switch (targetEL) { 823 case EL1: 824 return std::make_shared<UndefinedInstruction>( 825 machInst, iss, 826 EC_TRAPPED_WFI_WFE, mnemonic); 827 case EL2: 828 return std::make_shared<HypervisorTrap>(machInst, iss, 829 EC_TRAPPED_WFI_WFE); 830 case EL3: 831 return std::make_shared<SecureMonitorTrap>(machInst, iss, 832 EC_TRAPPED_WFI_WFE); 833 default: 834 panic("Unrecognized Exception Level: %d\n", targetEL); 835 } 836 } 837 838 return NoFault; 839} 840 841Fault 842ArmStaticInst::checkForWFxTrap64(ThreadContext *tc, 843 ExceptionLevel targetEL, 844 bool isWfe) const 845{ 846 // Check if target exception level is implemented. 847 assert(ArmSystem::haveEL(tc, targetEL)); 848 849 // Check if processor needs to trap at selected exception level 850 bool trap = isWFxTrapping(tc, targetEL, isWfe); 851 852 if (trap) { 853 uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */ 854 0x1E00000; /* WFI Instruction syndrome */ 855 switch (targetEL) { 856 case EL1: 857 return std::make_shared<SupervisorTrap>(machInst, iss, 858 EC_TRAPPED_WFI_WFE); 859 case EL2: 860 return std::make_shared<HypervisorTrap>(machInst, iss, 861 EC_TRAPPED_WFI_WFE); 862 case EL3: 863 return std::make_shared<SecureMonitorTrap>(machInst, iss, 864 EC_TRAPPED_WFI_WFE); 865 default: 866 panic("Unrecognized Exception Level: %d\n", targetEL); 867 } 868 } 869 870 return NoFault; 871} 872 873Fault 874ArmStaticInst::trapWFx(ThreadContext *tc, 875 CPSR cpsr, SCR scr, 876 bool isWfe) const 877{ 878 Fault fault = NoFault; 879 ExceptionLevel curr_el = currEL(tc); 880 881 if (curr_el == EL0) { 882 fault = checkForWFxTrap32(tc, EL1, isWfe); 883 } 884 885 if ((fault == NoFault) && 886 ArmSystem::haveEL(tc, EL2) && !inSecureState(scr, cpsr) && 887 ((curr_el == EL0) || (curr_el == EL1))) { 888 889 fault = checkForWFxTrap32(tc, EL2, isWfe); 890 } 891 892 if ((fault == NoFault) && 893 ArmSystem::haveEL(tc, EL3) && curr_el != EL3) { 894 fault = checkForWFxTrap32(tc, EL3, isWfe); 895 } 896 897 return fault; 898} 899 900Fault 901ArmStaticInst::checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const 902{ 903 bool setend_disabled(false); 904 ExceptionLevel pstate_el = currEL(tc); 905 906 if (pstate_el == EL2) { 907 setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(MISCREG_HSCTLR)).sed; 908 } else { 909 // Please note: in the armarm pseudocode there is a distinction 910 // whether EL1 is aarch32 or aarch64: 911 // if ELUsingAArch32(EL1) then SCTLR.SED else SCTLR[].SED; 912 // Considering that SETEND is aarch32 only, ELUsingAArch32(EL1) 913 // will always be true (hence using SCTLR.SED) except for 914 // instruction executed at EL0, and with an AArch64 EL1. 915 // In this case SCTLR_EL1 will be used. In gem5 the register is 916 // mapped to SCTLR_ns. We can safely use SCTLR and choose the 917 // appropriate bank version. 918 919 // Get the index of the banked version of SCTLR: 920 // SCTLR_s or SCTLR_ns. 921 auto banked_sctlr = snsBankedIndex( 922 MISCREG_SCTLR, tc, !inSecureState(tc)); 923 924 // SCTLR.SED bit is enabling/disabling the ue of SETEND instruction. 925 setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(banked_sctlr)).sed; 926 } 927 928 return setend_disabled ? undefinedFault32(tc, pstate_el) : 929 NoFault; 930} 931 932Fault 933ArmStaticInst::undefinedFault32(ThreadContext *tc, 934 ExceptionLevel pstateEL) const 935{ 936 // Even if we are running in aarch32, the fault might be dealt with in 937 // aarch64 ISA. 938 if (generalExceptionsToAArch64(tc, pstateEL)) { 939 return undefinedFault64(tc, pstateEL); 940 } else { 941 // Please note: according to the ARM ARM pseudocode we should handle 942 // the case when EL2 is aarch64 and HCR.TGE is 1 as well. 943 // However this case is already handled by the routeToHyp method in 944 // ArmFault class. 945 return std::make_shared<UndefinedInstruction>( 946 machInst, 0, 947 EC_UNKNOWN, mnemonic); 948 } 949} 950 951Fault 952ArmStaticInst::undefinedFault64(ThreadContext *tc, 953 ExceptionLevel pstateEL) const 954{ 955 switch (pstateEL) { 956 case EL0: 957 case EL1: 958 return std::make_shared<SupervisorTrap>(machInst, 0, EC_UNKNOWN); 959 case EL2: 960 return std::make_shared<HypervisorTrap>(machInst, 0, EC_UNKNOWN); 961 case EL3: 962 return std::make_shared<SecureMonitorTrap>(machInst, 0, EC_UNKNOWN); 963 default: 964 panic("Unrecognized Exception Level: %d\n", pstateEL); 965 break; 966 } 967 968 return NoFault; 969} 970 971Fault 972ArmStaticInst::sveAccessTrap(ExceptionLevel el) const 973{ 974 switch (el) { 975 case EL1: 976 return std::make_shared<SupervisorTrap>(machInst, 0, EC_TRAPPED_SVE); 977 case EL2: 978 return std::make_shared<HypervisorTrap>(machInst, 0, EC_TRAPPED_SVE); 979 case EL3: 980 return std::make_shared<SecureMonitorTrap>(machInst, 0, 981 EC_TRAPPED_SVE); 982 983 default: 984 panic("Illegal EL in sveAccessTrap\n"); 985 } 986} 987 988Fault 989ArmStaticInst::checkSveTrap(ThreadContext *tc, CPSR cpsr) const 990{ 991 const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el; 992 993 if (ArmSystem::haveVirtualization(tc) && el <= EL2) { 994 CPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2); 995 if (cptrEnCheck.tz) 996 return sveAccessTrap(EL2); 997 } 998 999 if (ArmSystem::haveSecurity(tc)) { 1000 CPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 1001 if (!cptrEnCheck.ez) 1002 return sveAccessTrap(EL3); 1003 } 1004 1005 return NoFault; 1006} 1007 1008Fault 1009ArmStaticInst::checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const 1010{ 1011 const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el; 1012 if ((el == EL0 && cpacr.zen != 0x3) || 1013 (el == EL1 && !(cpacr.zen & 0x1))) 1014 return sveAccessTrap(EL1); 1015 1016 return checkSveTrap(tc, cpsr); 1017} 1018 1019 1020static uint8_t 1021getRestoredITBits(ThreadContext *tc, CPSR spsr) 1022{ 1023 // See: shared/functions/system/RestoredITBits in the ARM ARM 1024 1025 const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode); 1026 const uint8_t it = itState(spsr); 1027 1028 if (!spsr.t || spsr.il) 1029 return 0; 1030 1031 // The IT bits are forced to zero when they are set to a reserved 1032 // value. 1033 if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0) 1034 return 0; 1035 1036 const bool itd = el == EL2 ? 1037 ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd : 1038 ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd; 1039 1040 // The IT bits are forced to zero when returning to A32 state, or 1041 // when returning to an EL with the ITD bit set to 1, and the IT 1042 // bits are describing a multi-instruction block. 1043 if (itd && bits(it, 2, 0) != 0) 1044 return 0; 1045 1046 return it; 1047} 1048 1049static bool 1050illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr) 1051{ 1052 const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode; 1053 if (unknownMode(mode)) 1054 return true; 1055 1056 const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode; 1057 const ExceptionLevel target_el = opModeToEL(mode); 1058 1059 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 1060 SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3)); 1061 1062 if (target_el > opModeToEL(cur_mode)) 1063 return true; 1064 1065 if (!ArmSystem::haveEL(tc, target_el)) 1066 return true; 1067 1068 if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && scr.ns && hcr.tge) 1069 return true; 1070 1071 if (target_el == EL2 && ArmSystem::haveEL(tc, EL3) && !scr.ns) 1072 return true; 1073 1074 bool spsr_mode_is_aarch32 = (spsr.width == 1); 1075 bool known, target_el_is_aarch32; 1076 std::tie(known, target_el_is_aarch32) = ELUsingAArch32K(tc, target_el); 1077 assert(known || (target_el == EL0 && ELIs64(tc, EL1))); 1078 1079 if (known && (spsr_mode_is_aarch32 != target_el_is_aarch32)) 1080 return true; 1081 1082 if (!spsr.width) { 1083 // aarch64 1084 if (!ArmSystem::highestELIs64(tc)) 1085 return true; 1086 if (spsr & 0x2) 1087 return true; 1088 if (target_el == EL0 && spsr.sp) 1089 return true; 1090 } else { 1091 // aarch32 1092 return unknownMode32(mode); 1093 } 1094 1095 return false; 1096} 1097 1098CPSR 1099ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const 1100{ 1101 CPSR new_cpsr = 0; 1102 1103 // gem5 doesn't implement single-stepping, so force the SS bit to 1104 // 0. 1105 new_cpsr.ss = 0; 1106 1107 if (illegalExceptionReturn(tc, cpsr, spsr)) { 1108 // If the SPSR specifies an illegal exception return, 1109 // then PSTATE.{M, nRW, EL, SP} are unchanged and PSTATE.IL 1110 // is set to 1. 1111 new_cpsr.il = 1; 1112 if (cpsr.width) { 1113 new_cpsr.mode = cpsr.mode; 1114 } else { 1115 new_cpsr.width = cpsr.width; 1116 new_cpsr.el = cpsr.el; 1117 new_cpsr.sp = cpsr.sp; 1118 } 1119 } else { 1120 new_cpsr.il = spsr.il; 1121 if (spsr.width && unknownMode32((OperatingMode)(uint8_t)spsr.mode)) { 1122 new_cpsr.il = 1; 1123 } else if (spsr.width) { 1124 new_cpsr.mode = spsr.mode; 1125 } else { 1126 new_cpsr.el = spsr.el; 1127 new_cpsr.sp = spsr.sp; 1128 } 1129 } 1130 1131 new_cpsr.nz = spsr.nz; 1132 new_cpsr.c = spsr.c; 1133 new_cpsr.v = spsr.v; 1134 new_cpsr.pan = spsr.pan; 1135 if (new_cpsr.width) { 1136 // aarch32 1137 const ITSTATE it = getRestoredITBits(tc, spsr); 1138 new_cpsr.q = spsr.q; 1139 new_cpsr.ge = spsr.ge; 1140 new_cpsr.e = spsr.e; 1141 new_cpsr.aif = spsr.aif; 1142 new_cpsr.t = spsr.t; 1143 new_cpsr.it2 = it.top6; 1144 new_cpsr.it1 = it.bottom2; 1145 } else { 1146 // aarch64 1147 new_cpsr.daif = spsr.daif; 1148 } 1149 1150 return new_cpsr; 1151} 1152 1153bool 1154ArmStaticInst::generalExceptionsToAArch64(ThreadContext *tc, 1155 ExceptionLevel pstateEL) const 1156{ 1157 // Returns TRUE if exceptions normally routed to EL1 are being handled 1158 // at an Exception level using AArch64, because either EL1 is using 1159 // AArch64 or TGE is in force and EL2 is using AArch64. 1160 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 1161 return (pstateEL == EL0 && !ELIs32(tc, EL1)) || 1162 (ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) && 1163 !ELIs32(tc, EL2) && hcr.tge); 1164} 1165 1166unsigned 1167ArmStaticInst::getCurSveVecLenInBits(ThreadContext *tc) 1168{ 1169 return tc->getIsaPtr()->getCurSveVecLenInBits(tc); 1170} 1171 1172} 1173