static_inst.cc revision 13367:dc06baae4275
12810Srdreslin@umich.edu/* 211870Snikos.nikoleris@arm.com * Copyright (c) 2010-2014, 2016-2018 ARM Limited 39347SAndreas.Sandberg@arm.com * Copyright (c) 2013 Advanced Micro Devices, Inc. 49347SAndreas.Sandberg@arm.com * All rights reserved 59347SAndreas.Sandberg@arm.com * 69347SAndreas.Sandberg@arm.com * The license below extends only to copyright in the software and shall 79347SAndreas.Sandberg@arm.com * not be construed as granting a license to any other intellectual 89347SAndreas.Sandberg@arm.com * property including but not limited to intellectual property relating 99347SAndreas.Sandberg@arm.com * to a hardware implementation of the functionality of the software 109347SAndreas.Sandberg@arm.com * licensed hereunder. You may use the software subject to the license 119347SAndreas.Sandberg@arm.com * terms below provided that you ensure that this notice is replicated 129347SAndreas.Sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 139347SAndreas.Sandberg@arm.com * modified or unmodified, in source code or in binary form. 142810Srdreslin@umich.edu * 152810Srdreslin@umich.edu * Copyright (c) 2007-2008 The Florida State University 162810Srdreslin@umich.edu * All rights reserved. 172810Srdreslin@umich.edu * 182810Srdreslin@umich.edu * Redistribution and use in source and binary forms, with or without 192810Srdreslin@umich.edu * modification, are permitted provided that the following conditions are 202810Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright 212810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer; 222810Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright 232810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the 242810Srdreslin@umich.edu * documentation and/or other materials provided with the distribution; 252810Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its 262810Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from 272810Srdreslin@umich.edu * this software without specific prior written permission. 282810Srdreslin@umich.edu * 292810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 382810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402810Srdreslin@umich.edu * 412810Srdreslin@umich.edu * Authors: Stephen Hines 422810Srdreslin@umich.edu */ 432810Srdreslin@umich.edu 442810Srdreslin@umich.edu#include "arch/arm/insts/static_inst.hh" 452810Srdreslin@umich.edu 462810Srdreslin@umich.edu#include "arch/arm/faults.hh" 472810Srdreslin@umich.edu#include "base/condcodes.hh" 486216Snate@binkert.org#include "base/cprintf.hh" 496216Snate@binkert.org#include "base/loader/symtab.hh" 502810Srdreslin@umich.edu#include "cpu/reg_class.hh" 512810Srdreslin@umich.edu 5211168Sandreas.hansson@arm.comnamespace ArmISA 532810Srdreslin@umich.edu{ 5411722Ssophiane.senni@gmail.com// Shift Rm by an immediate value 5511486Snikos.nikoleris@arm.comint32_t 568229Snate@binkert.orgArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, 572810Srdreslin@umich.edu uint32_t type, uint32_t cfval) const 589796Sprakash.ramrakhyani@arm.com{ 592810Srdreslin@umich.edu assert(shamt < 32); 602810Srdreslin@umich.edu ArmShiftType shiftType; 612810Srdreslin@umich.edu shiftType = (ArmShiftType)type; 622810Srdreslin@umich.edu 632810Srdreslin@umich.edu switch (shiftType) 642810Srdreslin@umich.edu { 652810Srdreslin@umich.edu case LSL: 662810Srdreslin@umich.edu return base << shamt; 672810Srdreslin@umich.edu case LSR: 682810Srdreslin@umich.edu if (shamt == 0) 692810Srdreslin@umich.edu return 0; 702810Srdreslin@umich.edu else 712810Srdreslin@umich.edu return base >> shamt; 722810Srdreslin@umich.edu case ASR: 732810Srdreslin@umich.edu if (shamt == 0) 742810Srdreslin@umich.edu return (base >> 31) | -((base & (1 << 31)) >> 31); 752810Srdreslin@umich.edu else 762810Srdreslin@umich.edu return (base >> shamt) | -((base & (1 << 31)) >> shamt); 772810Srdreslin@umich.edu case ROR: 782810Srdreslin@umich.edu if (shamt == 0) 792810Srdreslin@umich.edu return (cfval << 31) | (base >> 1); // RRX 802810Srdreslin@umich.edu else 812810Srdreslin@umich.edu return (base << (32 - shamt)) | (base >> shamt); 822810Srdreslin@umich.edu default: 832810Srdreslin@umich.edu ccprintf(std::cerr, "Unhandled shift type\n"); 842810Srdreslin@umich.edu exit(1); 852810Srdreslin@umich.edu break; 862810Srdreslin@umich.edu } 872810Srdreslin@umich.edu return 0; 882810Srdreslin@umich.edu} 892810Srdreslin@umich.edu 902810Srdreslin@umich.eduint64_t 912810Srdreslin@umich.eduArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt, 922810Srdreslin@umich.edu ArmShiftType type, uint8_t width) const 936227Snate@binkert.org{ 942810Srdreslin@umich.edu shiftAmt = shiftAmt % width; 952810Srdreslin@umich.edu ArmShiftType shiftType; 962810Srdreslin@umich.edu shiftType = (ArmShiftType)type; 972810Srdreslin@umich.edu 982810Srdreslin@umich.edu switch (shiftType) 992810Srdreslin@umich.edu { 1006227Snate@binkert.org case LSL: 1012810Srdreslin@umich.edu return base << shiftAmt; 1022810Srdreslin@umich.edu case LSR: 1032810Srdreslin@umich.edu if (shiftAmt == 0) 1042810Srdreslin@umich.edu return base; 1052810Srdreslin@umich.edu else 1062810Srdreslin@umich.edu return (base & mask(width)) >> shiftAmt; 1072810Srdreslin@umich.edu case ASR: 1082810Srdreslin@umich.edu if (shiftAmt == 0) { 1092810Srdreslin@umich.edu return base; 1102810Srdreslin@umich.edu } else { 11111168Sandreas.hansson@arm.com int sign_bit = bits(base, intWidth - 1); 1122810Srdreslin@umich.edu base >>= shiftAmt; 1132810Srdreslin@umich.edu base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base; 1142810Srdreslin@umich.edu return base & mask(intWidth); 1152810Srdreslin@umich.edu } 1162810Srdreslin@umich.edu case ROR: 1172810Srdreslin@umich.edu if (shiftAmt == 0) 1182810Srdreslin@umich.edu return base; 1192810Srdreslin@umich.edu else 1202810Srdreslin@umich.edu return (base << (width - shiftAmt)) | (base >> shiftAmt); 1212810Srdreslin@umich.edu default: 1222810Srdreslin@umich.edu ccprintf(std::cerr, "Unhandled shift type\n"); 1232810Srdreslin@umich.edu exit(1); 1242810Srdreslin@umich.edu break; 1252810Srdreslin@umich.edu } 1262810Srdreslin@umich.edu return 0; 1272810Srdreslin@umich.edu} 1282810Srdreslin@umich.edu 1292810Srdreslin@umich.eduint64_t 1302810Srdreslin@umich.eduArmStaticInst::extendReg64(uint64_t base, ArmExtendType type, 1312810Srdreslin@umich.edu uint64_t shiftAmt, uint8_t width) const 1322810Srdreslin@umich.edu{ 1332810Srdreslin@umich.edu bool sign_extend = false; 1342810Srdreslin@umich.edu int len = 0; 1352810Srdreslin@umich.edu switch (type) { 1362810Srdreslin@umich.edu case UXTB: 1372810Srdreslin@umich.edu len = 8; 1382810Srdreslin@umich.edu break; 1392810Srdreslin@umich.edu case UXTH: 1402810Srdreslin@umich.edu len = 16; 1412810Srdreslin@umich.edu break; 1422810Srdreslin@umich.edu case UXTW: 1432810Srdreslin@umich.edu len = 32; 1442810Srdreslin@umich.edu break; 1452810Srdreslin@umich.edu case UXTX: 1465999Snate@binkert.org len = 64; 1472810Srdreslin@umich.edu break; 1485999Snate@binkert.org case SXTB: 1492810Srdreslin@umich.edu len = 8; 1505999Snate@binkert.org sign_extend = true; 1512810Srdreslin@umich.edu break; 1522810Srdreslin@umich.edu case SXTH: 1532810Srdreslin@umich.edu len = 16; 1542810Srdreslin@umich.edu sign_extend = true; 1552810Srdreslin@umich.edu break; 1562810Srdreslin@umich.edu case SXTW: 1579796Sprakash.ramrakhyani@arm.com len = 32; 1589796Sprakash.ramrakhyani@arm.com sign_extend = true; 1599796Sprakash.ramrakhyani@arm.com break; 1602810Srdreslin@umich.edu case SXTX: 1612810Srdreslin@umich.edu len = 64; 1622810Srdreslin@umich.edu sign_extend = true; 1639796Sprakash.ramrakhyani@arm.com break; 1649086Sandreas.hansson@arm.com } 1652810Srdreslin@umich.edu len = len <= width - shiftAmt ? len : width - shiftAmt; 1662810Srdreslin@umich.edu uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt; 1672810Srdreslin@umich.edu if (sign_extend) { 1682810Srdreslin@umich.edu int sign_bit = bits(tmp, len + shiftAmt - 1); 1692810Srdreslin@umich.edu tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp; 17011169Sandreas.hansson@arm.com } 1712810Srdreslin@umich.edu return tmp & mask(width); 1722810Srdreslin@umich.edu} 1733862Sstever@eecs.umich.edu 1743862Sstever@eecs.umich.edu// Shift Rm by Rs 1752810Srdreslin@umich.eduint32_t 17611169Sandreas.hansson@arm.comArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, 1772810Srdreslin@umich.edu uint32_t type, uint32_t cfval) const 1782810Srdreslin@umich.edu{ 17911483Snikos.nikoleris@arm.com enum ArmShiftType shiftType; 18011484Snikos.nikoleris@arm.com shiftType = (enum ArmShiftType) type; 18111484Snikos.nikoleris@arm.com 1825716Shsul@eecs.umich.edu switch (shiftType) 1832810Srdreslin@umich.edu { 18410028SGiacomo.Gabrielli@arm.com case LSL: 1852810Srdreslin@umich.edu if (shamt >= 32) 1862810Srdreslin@umich.edu return 0; 1872810Srdreslin@umich.edu else 1882810Srdreslin@umich.edu return base << shamt; 18910815Sdavid.guillen@arm.com case LSR: 19011870Snikos.nikoleris@arm.com if (shamt >= 32) 19110815Sdavid.guillen@arm.com return 0; 19210815Sdavid.guillen@arm.com else 19310815Sdavid.guillen@arm.com return base >> shamt; 19410815Sdavid.guillen@arm.com case ASR: 19511870Snikos.nikoleris@arm.com if (shamt >= 32) 1962810Srdreslin@umich.edu return (base >> 31) | -((base & (1 << 31)) >> 31); 1972810Srdreslin@umich.edu else 1982810Srdreslin@umich.edu return (base >> shamt) | -((base & (1 << 31)) >> shamt); 1992810Srdreslin@umich.edu case ROR: 20010028SGiacomo.Gabrielli@arm.com shamt = shamt & 0x1f; 2012810Srdreslin@umich.edu if (shamt == 0) 2022810Srdreslin@umich.edu return base; 2032810Srdreslin@umich.edu else 20411169Sandreas.hansson@arm.com return (base << (32 - shamt)) | (base >> shamt); 2052810Srdreslin@umich.edu default: 2062810Srdreslin@umich.edu ccprintf(std::cerr, "Unhandled shift type\n"); 2072810Srdreslin@umich.edu exit(1); 2082982Sstever@eecs.umich.edu break; 2092810Srdreslin@umich.edu } 2102810Srdreslin@umich.edu return 0; 21111169Sandreas.hansson@arm.com} 2125717Shsul@eecs.umich.edu 21311169Sandreas.hansson@arm.com 2142810Srdreslin@umich.edu// Generate C for a shift by immediate 2152810Srdreslin@umich.edubool 21610941Sdavid.guillen@arm.comArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, 21710941Sdavid.guillen@arm.com uint32_t type, uint32_t cfval) const 21810941Sdavid.guillen@arm.com{ 21910941Sdavid.guillen@arm.com enum ArmShiftType shiftType; 22010941Sdavid.guillen@arm.com shiftType = (enum ArmShiftType) type; 22111169Sandreas.hansson@arm.com 22210941Sdavid.guillen@arm.com switch (shiftType) 22310941Sdavid.guillen@arm.com { 2242810Srdreslin@umich.edu case LSL: 2252810Srdreslin@umich.edu if (shamt == 0) 2262810Srdreslin@umich.edu return cfval; 2272810Srdreslin@umich.edu else 2282810Srdreslin@umich.edu return (base >> (32 - shamt)) & 1; 22911169Sandreas.hansson@arm.com case LSR: 2302810Srdreslin@umich.edu if (shamt == 0) 2312810Srdreslin@umich.edu return (base >> 31); 2322810Srdreslin@umich.edu else 2332810Srdreslin@umich.edu return (base >> (shamt - 1)) & 1; 2342810Srdreslin@umich.edu case ASR: 2352810Srdreslin@umich.edu if (shamt == 0) 2362810Srdreslin@umich.edu return (base >> 31); 2372810Srdreslin@umich.edu else 2382810Srdreslin@umich.edu return (base >> (shamt - 1)) & 1; 23911169Sandreas.hansson@arm.com case ROR: 2402810Srdreslin@umich.edu shamt = shamt & 0x1f; 2412810Srdreslin@umich.edu if (shamt == 0) 2422810Srdreslin@umich.edu return (base & 1); // RRX 2432810Srdreslin@umich.edu else 2442810Srdreslin@umich.edu return (base >> (shamt - 1)) & 1; 24512574Sodanrc@yahoo.com.br default: 24612574Sodanrc@yahoo.com.br ccprintf(std::cerr, "Unhandled shift type\n"); 24712574Sodanrc@yahoo.com.br exit(1); 2482810Srdreslin@umich.edu break; 2492810Srdreslin@umich.edu } 25012574Sodanrc@yahoo.com.br return 0; 2512810Srdreslin@umich.edu} 25212574Sodanrc@yahoo.com.br 2532810Srdreslin@umich.edu 2547612SGene.Wu@arm.com// Generate C for a shift by Rs 2557612SGene.Wu@arm.combool 2569663Suri.wiener@arm.comArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, 2579663Suri.wiener@arm.com uint32_t type, uint32_t cfval) const 25811169Sandreas.hansson@arm.com{ 2599663Suri.wiener@arm.com enum ArmShiftType shiftType; 2609663Suri.wiener@arm.com shiftType = (enum ArmShiftType) type; 2619347SAndreas.Sandberg@arm.com 2629347SAndreas.Sandberg@arm.com if (shamt == 0) 2639347SAndreas.Sandberg@arm.com return cfval; 2649347SAndreas.Sandberg@arm.com 2659347SAndreas.Sandberg@arm.com switch (shiftType) 2669347SAndreas.Sandberg@arm.com { 2679347SAndreas.Sandberg@arm.com case LSL: 2689347SAndreas.Sandberg@arm.com if (shamt > 32) 2699347SAndreas.Sandberg@arm.com return 0; 2709347SAndreas.Sandberg@arm.com else 2719347SAndreas.Sandberg@arm.com return (base >> (32 - shamt)) & 1; 27211168Sandreas.hansson@arm.com case LSR: 2739347SAndreas.Sandberg@arm.com if (shamt > 32) 2749347SAndreas.Sandberg@arm.com return 0; 2759347SAndreas.Sandberg@arm.com else 2769347SAndreas.Sandberg@arm.com return (base >> (shamt - 1)) & 1; 2779347SAndreas.Sandberg@arm.com case ASR: 2789796Sprakash.ramrakhyani@arm.com if (shamt > 32) 2792810Srdreslin@umich.edu shamt = 32; 2802810Srdreslin@umich.edu return (base >> (shamt - 1)) & 1; 2816216Snate@binkert.org 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 ArmStaticInst::printPFflags(std::ostream &os, int flag) const 328{ 329 const char *flagtoprfop[]= { "PLD", "PLI", "PST", "Reserved"}; 330 const char *flagtotarget[] = { "L1", "L2", "L3", "Reserved"}; 331 const char *flagtopolicy[] = { "KEEP", "STRM"}; 332 333 ccprintf(os, "%s%s%s", flagtoprfop[(flag>>3)&3], 334 flagtotarget[(flag>>1)&3], flagtopolicy[flag&1]); 335} 336 337void 338ArmStaticInst::printFloatReg(std::ostream &os, RegIndex reg_idx) const 339{ 340 ccprintf(os, "f%d", reg_idx); 341} 342 343void 344ArmStaticInst::printVecReg(std::ostream &os, RegIndex reg_idx) const 345{ 346 ccprintf(os, "v%d", reg_idx); 347} 348 349void 350ArmStaticInst::printCCReg(std::ostream &os, RegIndex reg_idx) const 351{ 352 ccprintf(os, "cc_%s", ArmISA::ccRegName[reg_idx]); 353} 354 355void 356ArmStaticInst::printMiscReg(std::ostream &os, RegIndex reg_idx) const 357{ 358 assert(reg_idx < NUM_MISCREGS); 359 ccprintf(os, "%s", ArmISA::miscRegName[reg_idx]); 360} 361 362void 363ArmStaticInst::printMnemonic(std::ostream &os, 364 const std::string &suffix, 365 bool withPred, 366 bool withCond64, 367 ConditionCode cond64) const 368{ 369 os << " " << mnemonic; 370 if (withPred && !aarch64) { 371 printCondition(os, machInst.condCode); 372 os << suffix; 373 } else if (withCond64) { 374 os << "."; 375 printCondition(os, cond64); 376 os << suffix; 377 } 378 if (machInst.bigThumb) 379 os << ".w"; 380 os << " "; 381} 382 383void 384ArmStaticInst::printTarget(std::ostream &os, Addr target, 385 const SymbolTable *symtab) const 386{ 387 Addr symbolAddr; 388 std::string symbol; 389 390 if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) { 391 ccprintf(os, "<%s", symbol); 392 if (symbolAddr != target) 393 ccprintf(os, "+%d>", target - symbolAddr); 394 else 395 ccprintf(os, ">"); 396 } else { 397 ccprintf(os, "%#x", target); 398 } 399} 400 401void 402ArmStaticInst::printCondition(std::ostream &os, 403 unsigned code, 404 bool noImplicit) const 405{ 406 switch (code) { 407 case COND_EQ: 408 os << "eq"; 409 break; 410 case COND_NE: 411 os << "ne"; 412 break; 413 case COND_CS: 414 os << "cs"; 415 break; 416 case COND_CC: 417 os << "cc"; 418 break; 419 case COND_MI: 420 os << "mi"; 421 break; 422 case COND_PL: 423 os << "pl"; 424 break; 425 case COND_VS: 426 os << "vs"; 427 break; 428 case COND_VC: 429 os << "vc"; 430 break; 431 case COND_HI: 432 os << "hi"; 433 break; 434 case COND_LS: 435 os << "ls"; 436 break; 437 case COND_GE: 438 os << "ge"; 439 break; 440 case COND_LT: 441 os << "lt"; 442 break; 443 case COND_GT: 444 os << "gt"; 445 break; 446 case COND_LE: 447 os << "le"; 448 break; 449 case COND_AL: 450 // This one is implicit. 451 if (noImplicit) 452 os << "al"; 453 break; 454 case COND_UC: 455 // Unconditional. 456 if (noImplicit) 457 os << "uc"; 458 break; 459 default: 460 panic("Unrecognized condition code %d.\n", code); 461 } 462} 463 464void 465ArmStaticInst::printMemSymbol(std::ostream &os, 466 const SymbolTable *symtab, 467 const std::string &prefix, 468 const Addr addr, 469 const std::string &suffix) const 470{ 471 Addr symbolAddr; 472 std::string symbol; 473 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) { 474 ccprintf(os, "%s%s", prefix, symbol); 475 if (symbolAddr != addr) 476 ccprintf(os, "+%d", addr - symbolAddr); 477 ccprintf(os, suffix); 478 } 479} 480 481void 482ArmStaticInst::printShiftOperand(std::ostream &os, 483 IntRegIndex rm, 484 bool immShift, 485 uint32_t shiftAmt, 486 IntRegIndex rs, 487 ArmShiftType type) const 488{ 489 bool firstOp = false; 490 491 if (rm != INTREG_ZERO) { 492 printIntReg(os, rm); 493 } 494 495 bool done = false; 496 497 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0) 498 shiftAmt = 32; 499 500 switch (type) { 501 case LSL: 502 if (immShift && shiftAmt == 0) { 503 done = true; 504 break; 505 } 506 if (!firstOp) 507 os << ", "; 508 os << "LSL"; 509 break; 510 case LSR: 511 if (!firstOp) 512 os << ", "; 513 os << "LSR"; 514 break; 515 case ASR: 516 if (!firstOp) 517 os << ", "; 518 os << "ASR"; 519 break; 520 case ROR: 521 if (immShift && shiftAmt == 0) { 522 if (!firstOp) 523 os << ", "; 524 os << "RRX"; 525 done = true; 526 break; 527 } 528 if (!firstOp) 529 os << ", "; 530 os << "ROR"; 531 break; 532 default: 533 panic("Tried to disassemble unrecognized shift type.\n"); 534 } 535 if (!done) { 536 if (!firstOp) 537 os << " "; 538 if (immShift) 539 os << "#" << shiftAmt; 540 else 541 printIntReg(os, rs); 542 } 543} 544 545void 546ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os, 547 IntRegIndex rm, ArmExtendType type, 548 int64_t shiftAmt) const 549{ 550 if (!firstOperand) 551 ccprintf(os, ", "); 552 printIntReg(os, rm); 553 if (type == UXTX && shiftAmt == 0) 554 return; 555 switch (type) { 556 case UXTB: ccprintf(os, ", UXTB"); 557 break; 558 case UXTH: ccprintf(os, ", UXTH"); 559 break; 560 case UXTW: ccprintf(os, ", UXTW"); 561 break; 562 case UXTX: ccprintf(os, ", LSL"); 563 break; 564 case SXTB: ccprintf(os, ", SXTB"); 565 break; 566 case SXTH: ccprintf(os, ", SXTH"); 567 break; 568 case SXTW: ccprintf(os, ", SXTW"); 569 break; 570 case SXTX: ccprintf(os, ", SXTW"); 571 break; 572 } 573 if (type == UXTX || shiftAmt) 574 ccprintf(os, " #%d", shiftAmt); 575} 576 577void 578ArmStaticInst::printDataInst(std::ostream &os, bool withImm, 579 bool immShift, bool s, IntRegIndex rd, IntRegIndex rn, 580 IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt, 581 ArmShiftType type, uint64_t imm) const 582{ 583 printMnemonic(os, s ? "s" : ""); 584 bool firstOp = true; 585 586 // Destination 587 if (rd != INTREG_ZERO) { 588 firstOp = false; 589 printIntReg(os, rd); 590 } 591 592 // Source 1. 593 if (rn != INTREG_ZERO) { 594 if (!firstOp) 595 os << ", "; 596 firstOp = false; 597 printIntReg(os, rn); 598 } 599 600 if (!firstOp) 601 os << ", "; 602 if (withImm) { 603 ccprintf(os, "#%ld", imm); 604 } else { 605 printShiftOperand(os, rm, immShift, shiftAmt, rs, type); 606 } 607} 608 609std::string 610ArmStaticInst::generateDisassembly(Addr pc, 611 const SymbolTable *symtab) const 612{ 613 std::stringstream ss; 614 printMnemonic(ss); 615 return ss.str(); 616} 617 618Fault 619ArmStaticInst::softwareBreakpoint32(ExecContext *xc, uint16_t imm) const 620{ 621 const auto tc = xc->tcBase(); 622 const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); 623 const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2); 624 if ((ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) && 625 !ELIs32(tc, EL2) && (hcr.tge == 1 || mdcr.tde == 1)) || 626 !ELIs32(tc, EL1)) { 627 // Route to AArch64 Software Breakpoint 628 return std::make_shared<SoftwareBreakpoint>(machInst, imm); 629 } else { 630 // Execute AArch32 Software Breakpoint 631 return std::make_shared<PrefetchAbort>(readPC(xc), 632 ArmFault::DebugEvent); 633 } 634} 635 636Fault 637ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const 638{ 639 switch (el) { 640 case EL1: 641 return std::make_shared<SupervisorTrap>(machInst, 0x1E00000, 642 EC_TRAPPED_SIMD_FP); 643 case EL2: 644 return std::make_shared<HypervisorTrap>(machInst, 0x1E00000, 645 EC_TRAPPED_SIMD_FP); 646 case EL3: 647 return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000, 648 EC_TRAPPED_SIMD_FP); 649 650 default: 651 panic("Illegal EL in advSIMDFPAccessTrap64\n"); 652 } 653} 654 655 656Fault 657ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const 658{ 659 if (ArmSystem::haveVirtualization(tc) && !inSecureState(tc)) { 660 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2); 661 if (cptrEnCheck.tfp) 662 return advSIMDFPAccessTrap64(EL2); 663 } 664 665 if (ArmSystem::haveSecurity(tc)) { 666 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 667 if (cptrEnCheck.tfp) 668 return advSIMDFPAccessTrap64(EL3); 669 } 670 671 return NoFault; 672} 673 674Fault 675ArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc, 676 CPSR cpsr, CPACR cpacr) const 677{ 678 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el; 679 if ((el == EL0 && cpacr.fpen != 0x3) || 680 (el == EL1 && !(cpacr.fpen & 0x1))) 681 return advSIMDFPAccessTrap64(EL1); 682 683 return checkFPAdvSIMDTrap64(tc, cpsr); 684} 685 686Fault 687ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc, 688 CPSR cpsr, CPACR cpacr, 689 NSACR nsacr, FPEXC fpexc, 690 bool fpexc_check, bool advsimd) const 691{ 692 const bool have_virtualization = ArmSystem::haveVirtualization(tc); 693 const bool have_security = ArmSystem::haveSecurity(tc); 694 const bool is_secure = inSecureState(tc); 695 const ExceptionLevel cur_el = opModeToEL(currOpMode(tc)); 696 697 if (cur_el == EL0 && ELIs64(tc, EL1)) 698 return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr); 699 700 uint8_t cpacr_cp10 = cpacr.cp10; 701 bool cpacr_asedis = cpacr.asedis; 702 703 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 704 if (nsacr.nsasedis) 705 cpacr_asedis = true; 706 if (nsacr.cp10 == 0) 707 cpacr_cp10 = 0; 708 } 709 710 if (cur_el != EL2) { 711 if (advsimd && cpacr_asedis) 712 return disabledFault(); 713 714 if ((cur_el == EL0 && cpacr_cp10 != 0x3) || 715 (cur_el != EL0 && !(cpacr_cp10 & 0x1))) 716 return disabledFault(); 717 } 718 719 if (fpexc_check && !fpexc.en) 720 return disabledFault(); 721 722 // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap -- 723 724 if (have_virtualization && !is_secure && ELIs64(tc, EL2)) 725 return checkFPAdvSIMDTrap64(tc, cpsr); 726 727 if (have_virtualization && !is_secure) { 728 HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR); 729 bool hcptr_cp10 = hcptr.tcp10; 730 bool hcptr_tase = hcptr.tase; 731 732 if (have_security && !ELIs64(tc, EL3) && !is_secure) { 733 if (nsacr.nsasedis) 734 hcptr_tase = true; 735 if (nsacr.cp10) 736 hcptr_cp10 = true; 737 } 738 739 if ((advsimd && hcptr_tase) || hcptr_cp10) { 740 const uint32_t iss = advsimd ? (1 << 5) : 0xA; 741 if (cur_el == EL2) { 742 return std::make_shared<UndefinedInstruction>( 743 machInst, iss, 744 EC_TRAPPED_HCPTR, mnemonic); 745 } else { 746 return std::make_shared<HypervisorTrap>( 747 machInst, iss, 748 EC_TRAPPED_HCPTR); 749 } 750 751 } 752 } 753 754 if (have_security && ELIs64(tc, EL3)) { 755 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3); 756 if (cptrEnCheck.tfp) 757 return advSIMDFPAccessTrap64(EL3); 758 } 759 760 return NoFault; 761} 762 763inline bool 764ArmStaticInst::isWFxTrapping(ThreadContext *tc, 765 ExceptionLevel tgtEl, 766 bool isWfe) const 767{ 768 bool trap = false; 769 SCTLR sctlr = ((SCTLR)tc->readMiscReg(MISCREG_SCTLR_EL1)); 770 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 771 SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3)); 772 773 switch (tgtEl) { 774 case EL1: 775 trap = isWfe? !sctlr.ntwe : !sctlr.ntwi; 776 break; 777 case EL2: 778 trap = isWfe? hcr.twe : hcr.twi; 779 break; 780 case EL3: 781 trap = isWfe? scr.twe : scr.twi; 782 break; 783 default: 784 break; 785 } 786 787 return trap; 788} 789 790Fault 791ArmStaticInst::checkForWFxTrap32(ThreadContext *tc, 792 ExceptionLevel targetEL, 793 bool isWfe) const 794{ 795 // Check if target exception level is implemented. 796 assert(ArmSystem::haveEL(tc, targetEL)); 797 798 // Check for routing to AArch64: this happens if the 799 // target exception level (where the trap will be handled) 800 // is using aarch64 801 if (ELIs64(tc, targetEL)) { 802 return checkForWFxTrap64(tc, targetEL, isWfe); 803 } 804 805 // Check if processor needs to trap at selected exception level 806 bool trap = isWFxTrapping(tc, targetEL, isWfe); 807 808 if (trap) { 809 uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */ 810 0x1E00000; /* WFI Instruction syndrome */ 811 switch (targetEL) { 812 case EL1: 813 return std::make_shared<UndefinedInstruction>( 814 machInst, iss, 815 EC_TRAPPED_WFI_WFE, mnemonic); 816 case EL2: 817 return std::make_shared<HypervisorTrap>(machInst, iss, 818 EC_TRAPPED_WFI_WFE); 819 case EL3: 820 return std::make_shared<SecureMonitorTrap>(machInst, iss, 821 EC_TRAPPED_WFI_WFE); 822 default: 823 panic("Unrecognized Exception Level: %d\n", targetEL); 824 } 825 } 826 827 return NoFault; 828} 829 830Fault 831ArmStaticInst::checkForWFxTrap64(ThreadContext *tc, 832 ExceptionLevel targetEL, 833 bool isWfe) const 834{ 835 // Check if target exception level is implemented. 836 assert(ArmSystem::haveEL(tc, targetEL)); 837 838 // Check if processor needs to trap at selected exception level 839 bool trap = isWFxTrapping(tc, targetEL, isWfe); 840 841 if (trap) { 842 uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */ 843 0x1E00000; /* WFI Instruction syndrome */ 844 switch (targetEL) { 845 case EL1: 846 return std::make_shared<SupervisorTrap>(machInst, iss, 847 EC_TRAPPED_WFI_WFE); 848 case EL2: 849 return std::make_shared<HypervisorTrap>(machInst, iss, 850 EC_TRAPPED_WFI_WFE); 851 case EL3: 852 return std::make_shared<SecureMonitorTrap>(machInst, iss, 853 EC_TRAPPED_WFI_WFE); 854 default: 855 panic("Unrecognized Exception Level: %d\n", targetEL); 856 } 857 } 858 859 return NoFault; 860} 861 862Fault 863ArmStaticInst::trapWFx(ThreadContext *tc, 864 CPSR cpsr, SCR scr, 865 bool isWfe) const 866{ 867 Fault fault = NoFault; 868 if (cpsr.el == EL0) { 869 fault = checkForWFxTrap32(tc, EL1, isWfe); 870 } 871 872 if ((fault == NoFault) && 873 ArmSystem::haveEL(tc, EL2) && !inSecureState(scr, cpsr) && 874 ((cpsr.el == EL0) || (cpsr.el == EL1))) { 875 876 fault = checkForWFxTrap32(tc, EL2, isWfe); 877 } 878 879 if ((fault == NoFault) && 880 ArmSystem::haveEL(tc, EL3) && cpsr.el != EL3) { 881 fault = checkForWFxTrap32(tc, EL3, isWfe); 882 } 883 884 return fault; 885} 886 887Fault 888ArmStaticInst::checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const 889{ 890 bool setend_disabled(false); 891 ExceptionLevel pstateEL = (ExceptionLevel)(uint8_t)(cpsr.el); 892 893 if (pstateEL == EL2) { 894 setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(MISCREG_HSCTLR)).sed; 895 } else { 896 // Please note: in the armarm pseudocode there is a distinction 897 // whether EL1 is aarch32 or aarch64: 898 // if ELUsingAArch32(EL1) then SCTLR.SED else SCTLR[].SED; 899 // Considering that SETEND is aarch32 only, ELUsingAArch32(EL1) 900 // will always be true (hence using SCTLR.SED) except for 901 // instruction executed at EL0, and with an AArch64 EL1. 902 // In this case SCTLR_EL1 will be used. In gem5 the register is 903 // mapped to SCTLR_ns. We can safely use SCTLR and choose the 904 // appropriate bank version. 905 906 // Get the index of the banked version of SCTLR: 907 // SCTLR_s or SCTLR_ns. 908 auto banked_sctlr = snsBankedIndex( 909 MISCREG_SCTLR, tc, !inSecureState(tc)); 910 911 // SCTLR.SED bit is enabling/disabling the ue of SETEND instruction. 912 setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(banked_sctlr)).sed; 913 } 914 915 return setend_disabled ? undefinedFault32(tc, pstateEL) : 916 NoFault; 917} 918 919Fault 920ArmStaticInst::undefinedFault32(ThreadContext *tc, 921 ExceptionLevel pstateEL) const 922{ 923 // Even if we are running in aarch32, the fault might be dealt with in 924 // aarch64 ISA. 925 if (generalExceptionsToAArch64(tc, pstateEL)) { 926 return undefinedFault64(tc, pstateEL); 927 } else { 928 // Please note: according to the ARM ARM pseudocode we should handle 929 // the case when EL2 is aarch64 and HCR.TGE is 1 as well. 930 // However this case is already handled by the routeToHyp method in 931 // ArmFault class. 932 return std::make_shared<UndefinedInstruction>( 933 machInst, 0, 934 EC_UNKNOWN, mnemonic); 935 } 936} 937 938Fault 939ArmStaticInst::undefinedFault64(ThreadContext *tc, 940 ExceptionLevel pstateEL) const 941{ 942 switch (pstateEL) { 943 case EL0: 944 case EL1: 945 return std::make_shared<SupervisorTrap>(machInst, 0, EC_UNKNOWN); 946 case EL2: 947 return std::make_shared<HypervisorTrap>(machInst, 0, EC_UNKNOWN); 948 case EL3: 949 return std::make_shared<SecureMonitorTrap>(machInst, 0, EC_UNKNOWN); 950 default: 951 panic("Unrecognized Exception Level: %d\n", pstateEL); 952 break; 953 } 954 955 return NoFault; 956} 957 958static uint8_t 959getRestoredITBits(ThreadContext *tc, CPSR spsr) 960{ 961 // See: shared/functions/system/RestoredITBits in the ARM ARM 962 963 const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode); 964 const uint8_t it = itState(spsr); 965 966 if (!spsr.t || spsr.il) 967 return 0; 968 969 // The IT bits are forced to zero when they are set to a reserved 970 // value. 971 if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0) 972 return 0; 973 974 const bool itd = el == EL2 ? 975 ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd : 976 ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd; 977 978 // The IT bits are forced to zero when returning to A32 state, or 979 // when returning to an EL with the ITD bit set to 1, and the IT 980 // bits are describing a multi-instruction block. 981 if (itd && bits(it, 2, 0) != 0) 982 return 0; 983 984 return it; 985} 986 987static bool 988illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr) 989{ 990 const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode; 991 if (unknownMode(mode)) 992 return true; 993 994 const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode; 995 const ExceptionLevel target_el = opModeToEL(mode); 996 997 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 998 SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3)); 999 1000 if (target_el > opModeToEL(cur_mode)) 1001 return true; 1002 1003 if (!ArmSystem::haveEL(tc, target_el)) 1004 return true; 1005 1006 if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && scr.ns && hcr.tge) 1007 return true; 1008 1009 if (target_el == EL2 && ArmSystem::haveEL(tc, EL3) && !scr.ns) 1010 return true; 1011 1012 bool spsr_mode_is_aarch32 = (spsr.width == 1); 1013 bool known, target_el_is_aarch32; 1014 std::tie(known, target_el_is_aarch32) = ELUsingAArch32K(tc, target_el); 1015 assert(known || (target_el == EL0 && ELIs64(tc, EL1))); 1016 1017 if (known && (spsr_mode_is_aarch32 != target_el_is_aarch32)) 1018 return true; 1019 1020 if (!spsr.width) { 1021 // aarch64 1022 if (!ArmSystem::highestELIs64(tc)) 1023 return true; 1024 if (spsr & 0x2) 1025 return true; 1026 if (target_el == EL0 && spsr.sp) 1027 return true; 1028 } else { 1029 // aarch32 1030 return unknownMode32(mode); 1031 } 1032 1033 return false; 1034} 1035 1036CPSR 1037ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const 1038{ 1039 CPSR new_cpsr = 0; 1040 1041 // gem5 doesn't implement single-stepping, so force the SS bit to 1042 // 0. 1043 new_cpsr.ss = 0; 1044 1045 if (illegalExceptionReturn(tc, cpsr, spsr)) { 1046 // If the SPSR specifies an illegal exception return, 1047 // then PSTATE.{M, nRW, EL, SP} are unchanged and PSTATE.IL 1048 // is set to 1. 1049 new_cpsr.il = 1; 1050 if (cpsr.width) { 1051 new_cpsr.mode = cpsr.mode; 1052 } else { 1053 new_cpsr.width = cpsr.width; 1054 new_cpsr.el = cpsr.el; 1055 new_cpsr.sp = cpsr.sp; 1056 } 1057 } else { 1058 new_cpsr.il = spsr.il; 1059 if (spsr.width && unknownMode32((OperatingMode)(uint8_t)spsr.mode)) { 1060 new_cpsr.il = 1; 1061 } else if (spsr.width) { 1062 new_cpsr.mode = spsr.mode; 1063 } else { 1064 new_cpsr.el = spsr.el; 1065 new_cpsr.sp = spsr.sp; 1066 } 1067 } 1068 1069 new_cpsr.nz = spsr.nz; 1070 new_cpsr.c = spsr.c; 1071 new_cpsr.v = spsr.v; 1072 if (new_cpsr.width) { 1073 // aarch32 1074 const ITSTATE it = getRestoredITBits(tc, spsr); 1075 new_cpsr.q = spsr.q; 1076 new_cpsr.ge = spsr.ge; 1077 new_cpsr.e = spsr.e; 1078 new_cpsr.aif = spsr.aif; 1079 new_cpsr.t = spsr.t; 1080 new_cpsr.it2 = it.top6; 1081 new_cpsr.it1 = it.bottom2; 1082 } else { 1083 // aarch64 1084 new_cpsr.daif = spsr.daif; 1085 } 1086 1087 return new_cpsr; 1088} 1089 1090bool 1091ArmStaticInst::generalExceptionsToAArch64(ThreadContext *tc, 1092 ExceptionLevel pstateEL) const 1093{ 1094 // Returns TRUE if exceptions normally routed to EL1 are being handled 1095 // at an Exception level using AArch64, because either EL1 is using 1096 // AArch64 or TGE is in force and EL2 is using AArch64. 1097 HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); 1098 return (pstateEL == EL0 && !ELIs32(tc, EL1)) || 1099 (ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) && 1100 !ELIs32(tc, EL2) && hcr.tge); 1101} 1102 1103 1104} 1105