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