static_inst.cc revision 12104:edd63f9c6184
11689SN/A/*
29444SAndreas.Sandberg@ARM.com * Copyright (c) 2010-2014, 2016 ARM Limited
38707Sandreas.hansson@arm.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
48707Sandreas.hansson@arm.com * All rights reserved
58707Sandreas.hansson@arm.com *
68707Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
78707Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
88707Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
98707Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
108707Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
118707Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
128707Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
138707Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
141689SN/A *
157897Shestness@cs.utexas.edu * Copyright (c) 2007-2008 The Florida State University
161689SN/A * All rights reserved.
171689SN/A *
181689SN/A * Redistribution and use in source and binary forms, with or without
191689SN/A * modification, are permitted provided that the following conditions are
201689SN/A * met: redistributions of source code must retain the above copyright
211689SN/A * notice, this list of conditions and the following disclaimer;
221689SN/A * redistributions in binary form must reproduce the above copyright
231689SN/A * notice, this list of conditions and the following disclaimer in the
241689SN/A * documentation and/or other materials provided with the distribution;
251689SN/A * neither the name of the copyright holders nor the names of its
261689SN/A * contributors may be used to endorse or promote products derived from
271689SN/A * this software without specific prior written permission.
281689SN/A *
291689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
301689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
311689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
321689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
331689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
341689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
351689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
361689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
371689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
381689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
391689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402665Ssaidi@eecs.umich.edu *
412665Ssaidi@eecs.umich.edu * Authors: Stephen Hines
422756Sksewell@umich.edu */
437897Shestness@cs.utexas.edu
441689SN/A#include "arch/arm/insts/static_inst.hh"
451689SN/A
462325SN/A#include "arch/arm/faults.hh"
472325SN/A#include "base/condcodes.hh"
481060SN/A#include "base/cprintf.hh"
491060SN/A#include "base/loader/symtab.hh"
501060SN/A#include "cpu/reg_class.hh"
512292SN/A
522292SN/Anamespace ArmISA
531681SN/A{
541060SN/A// Shift Rm by an immediate value
552980Sgblack@eecs.umich.eduint32_t
561060SN/AArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
576658Snate@binkert.org                                uint32_t type, uint32_t cfval) const
581717SN/A{
591717SN/A    assert(shamt < 32);
602292SN/A    ArmShiftType shiftType;
612292SN/A    shiftType = (ArmShiftType)type;
628229Snate@binkert.org
638229Snate@binkert.org    switch (shiftType)
648229Snate@binkert.org    {
658229Snate@binkert.org      case LSL:
662817Sksewell@umich.edu        return base << shamt;
678229Snate@binkert.org      case LSR:
681060SN/A        if (shamt == 0)
691060SN/A            return 0;
702316SN/A        else
712316SN/A            return base >> shamt;
722680Sktlim@umich.edu      case ASR:
732817Sksewell@umich.edu        if (shamt == 0)
742817Sksewell@umich.edu            return (base >> 31) | -((base & (1 << 31)) >> 31);
752843Sktlim@umich.edu        else
762843Sktlim@umich.edu            return (base >> shamt) | -((base & (1 << 31)) >> shamt);
772669Sktlim@umich.edu      case ROR:
781060SN/A        if (shamt == 0)
791060SN/A            return (cfval << 31) | (base >> 1); // RRX
808737Skoansin.tan@gmail.com        else
815529Snate@binkert.org            return (base << (32 - shamt)) | (base >> shamt);
822733Sktlim@umich.edu      default:
831060SN/A        ccprintf(std::cerr, "Unhandled shift type\n");
841060SN/A        exit(1);
851060SN/A        break;
865529Snate@binkert.org    }
872292SN/A    return 0;
882292SN/A}
891060SN/A
901060SN/Aint64_t
912348SN/AArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt,
922348SN/A                          ArmShiftType type, uint8_t width) const
932348SN/A{
942348SN/A    shiftAmt = shiftAmt % width;
952348SN/A    ArmShiftType shiftType;
961060SN/A    shiftType = (ArmShiftType)type;
972733Sktlim@umich.edu
981060SN/A    switch (shiftType)
991060SN/A    {
1002325SN/A      case LSL:
1011060SN/A        return base << shiftAmt;
1021061SN/A      case LSR:
1034329Sktlim@umich.edu        if (shiftAmt == 0)
1041060SN/A            return base;
1055595Sgblack@eecs.umich.edu        else
1062292SN/A            return (base & mask(width)) >> shiftAmt;
1072292SN/A      case ASR:
1082292SN/A        if (shiftAmt == 0) {
1092292SN/A            return base;
1102817Sksewell@umich.edu        } else {
1112829Sksewell@umich.edu            int sign_bit = bits(base, intWidth - 1);
1121060SN/A            base >>= shiftAmt;
1131060SN/A            base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base;
1141060SN/A            return base & mask(intWidth);
1151060SN/A        }
1161060SN/A      case ROR:
1172307SN/A        if (shiftAmt == 0)
1182307SN/A            return base;
1191060SN/A        else
1201060SN/A            return (base << (width - shiftAmt)) | (base >> shiftAmt);
1216022Sgblack@eecs.umich.edu      default:
1226022Sgblack@eecs.umich.edu        ccprintf(std::cerr, "Unhandled shift type\n");
1233781Sgblack@eecs.umich.edu        exit(1);
1242292SN/A        break;
1251060SN/A    }
1261060SN/A    return 0;
1271060SN/A}
1288707Sandreas.hansson@arm.com
1298707Sandreas.hansson@arm.comint64_t
1308707Sandreas.hansson@arm.comArmStaticInst::extendReg64(uint64_t base, ArmExtendType type,
1318707Sandreas.hansson@arm.com                           uint64_t shiftAmt, uint8_t width) const
1328707Sandreas.hansson@arm.com{
1338707Sandreas.hansson@arm.com    bool sign_extend = false;
1348707Sandreas.hansson@arm.com    int len = 0;
1358707Sandreas.hansson@arm.com    switch (type) {
1368707Sandreas.hansson@arm.com      case UXTB:
1378707Sandreas.hansson@arm.com        len = 8;
1388707Sandreas.hansson@arm.com        break;
1398707Sandreas.hansson@arm.com      case UXTH:
1408707Sandreas.hansson@arm.com        len = 16;
1419095Sandreas.hansson@arm.com        break;
1428707Sandreas.hansson@arm.com      case UXTW:
1438707Sandreas.hansson@arm.com        len = 32;
1448707Sandreas.hansson@arm.com        break;
1458707Sandreas.hansson@arm.com      case UXTX:
1468707Sandreas.hansson@arm.com        len = 64;
1478707Sandreas.hansson@arm.com        break;
1488975Sandreas.hansson@arm.com      case SXTB:
1498975Sandreas.hansson@arm.com        len = 8;
1508707Sandreas.hansson@arm.com        sign_extend = true;
1518707Sandreas.hansson@arm.com        break;
1528707Sandreas.hansson@arm.com      case SXTH:
1538707Sandreas.hansson@arm.com        len = 16;
1548707Sandreas.hansson@arm.com        sign_extend = true;
1558707Sandreas.hansson@arm.com        break;
1568707Sandreas.hansson@arm.com      case SXTW:
1578707Sandreas.hansson@arm.com        len = 32;
1588707Sandreas.hansson@arm.com        sign_extend = true;
1598707Sandreas.hansson@arm.com        break;
1608707Sandreas.hansson@arm.com      case SXTX:
1618707Sandreas.hansson@arm.com        len = 64;
1628707Sandreas.hansson@arm.com        sign_extend = true;
1638707Sandreas.hansson@arm.com        break;
1648707Sandreas.hansson@arm.com    }
1658707Sandreas.hansson@arm.com    len = len <= width - shiftAmt ? len : width - shiftAmt;
1668707Sandreas.hansson@arm.com    uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt;
1678707Sandreas.hansson@arm.com    if (sign_extend) {
1689095Sandreas.hansson@arm.com        int sign_bit = bits(tmp, len + shiftAmt - 1);
1698707Sandreas.hansson@arm.com        tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp;
1708707Sandreas.hansson@arm.com    }
1718707Sandreas.hansson@arm.com    return tmp & mask(width);
1728707Sandreas.hansson@arm.com}
1738707Sandreas.hansson@arm.com
1748707Sandreas.hansson@arm.com// Shift Rm by Rs
1758707Sandreas.hansson@arm.comint32_t
1768975Sandreas.hansson@arm.comArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
1778975Sandreas.hansson@arm.com                               uint32_t type, uint32_t cfval) const
1788707Sandreas.hansson@arm.com{
1798707Sandreas.hansson@arm.com    enum ArmShiftType shiftType;
1808707Sandreas.hansson@arm.com    shiftType = (enum ArmShiftType) type;
1818707Sandreas.hansson@arm.com
1828707Sandreas.hansson@arm.com    switch (shiftType)
1838707Sandreas.hansson@arm.com    {
1848707Sandreas.hansson@arm.com      case LSL:
1858707Sandreas.hansson@arm.com        if (shamt >= 32)
1868711Sandreas.hansson@arm.com            return 0;
1878707Sandreas.hansson@arm.com        else
1888922Swilliam.wang@arm.com            return base << shamt;
1898707Sandreas.hansson@arm.com      case LSR:
1908707Sandreas.hansson@arm.com        if (shamt >= 32)
1911060SN/A            return 0;
1921060SN/A        else
1931060SN/A            return base >> shamt;
1942292SN/A      case ASR:
1951755SN/A        if (shamt >= 32)
1961060SN/A            return (base >> 31) | -((base & (1 << 31)) >> 31);
1971060SN/A        else
1982292SN/A            return (base >> shamt) | -((base & (1 << 31)) >> shamt);
1991755SN/A      case ROR:
2002292SN/A        shamt = shamt & 0x1f;
2012292SN/A        if (shamt == 0)
2021060SN/A            return base;
2032292SN/A        else
2045336Shines@cs.fsu.edu            return (base << (32 - shamt)) | (base >> shamt);
2051060SN/A      default:
2061060SN/A        ccprintf(std::cerr, "Unhandled shift type\n");
2072292SN/A        exit(1);
2081060SN/A        break;
2091060SN/A    }
2102292SN/A    return 0;
2119180Sandreas.hansson@arm.com}
2121060SN/A
2131060SN/A
2149179Sandreas.hansson@arm.com// Generate C for a shift by immediate
2151060SN/Abool
2169179Sandreas.hansson@arm.comArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
2171060SN/A                                   uint32_t type, uint32_t cfval) const
2181060SN/A{
2192292SN/A    enum ArmShiftType shiftType;
2201060SN/A    shiftType = (enum ArmShiftType) type;
2211060SN/A
2221060SN/A    switch (shiftType)
2231060SN/A    {
2241060SN/A      case LSL:
2251060SN/A        if (shamt == 0)
2262829Sksewell@umich.edu            return cfval;
2272829Sksewell@umich.edu        else
2282829Sksewell@umich.edu            return (base >> (32 - shamt)) & 1;
2292829Sksewell@umich.edu      case LSR:
2306221Snate@binkert.org        if (shamt == 0)
2312829Sksewell@umich.edu            return (base >> 31);
2322829Sksewell@umich.edu        else
2332829Sksewell@umich.edu            return (base >> (shamt - 1)) & 1;
2342829Sksewell@umich.edu      case ASR:
2352829Sksewell@umich.edu        if (shamt == 0)
2362829Sksewell@umich.edu            return (base >> 31);
2372829Sksewell@umich.edu        else
2382829Sksewell@umich.edu            return (base >> (shamt - 1)) & 1;
2392829Sksewell@umich.edu      case ROR:
2402829Sksewell@umich.edu        shamt = shamt & 0x1f;
2412829Sksewell@umich.edu        if (shamt == 0)
2422829Sksewell@umich.edu            return (base & 1); // RRX
2432829Sksewell@umich.edu        else
2442829Sksewell@umich.edu            return (base >> (shamt - 1)) & 1;
2452829Sksewell@umich.edu      default:
2465336Shines@cs.fsu.edu        ccprintf(std::cerr, "Unhandled shift type\n");
2472829Sksewell@umich.edu        exit(1);
2482829Sksewell@umich.edu        break;
2492829Sksewell@umich.edu    }
2506221Snate@binkert.org    return 0;
2519180Sandreas.hansson@arm.com}
2522829Sksewell@umich.edu
2532829Sksewell@umich.edu
2542829Sksewell@umich.edu// Generate C for a shift by Rs
2555606Snate@binkert.orgbool
2569179Sandreas.hansson@arm.comArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
2578518Sgeoffrey.blake@arm.com                                  uint32_t type, uint32_t cfval) const
2589179Sandreas.hansson@arm.com{
2598518Sgeoffrey.blake@arm.com    enum ArmShiftType shiftType;
2608518Sgeoffrey.blake@arm.com    shiftType = (enum ArmShiftType) type;
2618518Sgeoffrey.blake@arm.com
2628518Sgeoffrey.blake@arm.com    if (shamt == 0)
2638518Sgeoffrey.blake@arm.com        return cfval;
2648518Sgeoffrey.blake@arm.com
2658518Sgeoffrey.blake@arm.com    switch (shiftType)
2668518Sgeoffrey.blake@arm.com    {
2678518Sgeoffrey.blake@arm.com      case LSL:
2688518Sgeoffrey.blake@arm.com        if (shamt > 32)
2698518Sgeoffrey.blake@arm.com            return 0;
2702829Sksewell@umich.edu        else
2712829Sksewell@umich.edu            return (base >> (32 - shamt)) & 1;
2722829Sksewell@umich.edu      case LSR:
2736221Snate@binkert.org        if (shamt > 32)
2746221Snate@binkert.org            return 0;
2752829Sksewell@umich.edu        else
2762829Sksewell@umich.edu            return (base >> (shamt - 1)) & 1;
2772829Sksewell@umich.edu      case ASR:
2782829Sksewell@umich.edu        if (shamt > 32)
2792829Sksewell@umich.edu            shamt = 32;
2802829Sksewell@umich.edu        return (base >> (shamt - 1)) & 1;
2812829Sksewell@umich.edu      case ROR:
2822829Sksewell@umich.edu        shamt = shamt & 0x1f;
2832875Sksewell@umich.edu        if (shamt == 0)
2842875Sksewell@umich.edu            shamt = 32;
2852875Sksewell@umich.edu        return (base >> (shamt - 1)) & 1;
2863221Sktlim@umich.edu      default:
2876221Snate@binkert.org        ccprintf(std::cerr, "Unhandled shift type\n");
2882875Sksewell@umich.edu        exit(1);
2893221Sktlim@umich.edu        break;
2903221Sktlim@umich.edu    }
2913221Sktlim@umich.edu    return 0;
2922875Sksewell@umich.edu}
2932875Sksewell@umich.edu
2942875Sksewell@umich.eduvoid
2952875Sksewell@umich.eduArmStaticInst::printIntReg(std::ostream &os, RegIndex reg_idx) const
2962875Sksewell@umich.edu{
2972875Sksewell@umich.edu    if (aarch64) {
2982875Sksewell@umich.edu        if (reg_idx == INTREG_UREG0)
2992875Sksewell@umich.edu            ccprintf(os, "ureg0");
3002875Sksewell@umich.edu        else if (reg_idx == INTREG_SPX)
3012875Sksewell@umich.edu            ccprintf(os, "%s%s", (intWidth == 32) ? "w" : "", "sp");
3022875Sksewell@umich.edu        else if (reg_idx == INTREG_X31)
3032875Sksewell@umich.edu            ccprintf(os, "%szr", (intWidth == 32) ? "w" : "x");
3042875Sksewell@umich.edu        else
3053221Sktlim@umich.edu            ccprintf(os, "%s%d", (intWidth == 32) ? "w" : "x", reg_idx);
3063221Sktlim@umich.edu    } else {
3073221Sktlim@umich.edu        switch (reg_idx) {
3082875Sksewell@umich.edu          case PCReg:
3095336Shines@cs.fsu.edu            ccprintf(os, "pc");
3102875Sksewell@umich.edu            break;
3112875Sksewell@umich.edu          case StackPointerReg:
3122875Sksewell@umich.edu            ccprintf(os, "sp");
3136221Snate@binkert.org            break;
3149180Sandreas.hansson@arm.com          case FramePointerReg:
3152875Sksewell@umich.edu             ccprintf(os, "fp");
3162875Sksewell@umich.edu             break;
3172875Sksewell@umich.edu          case ReturnAddressReg:
3185606Snate@binkert.org             ccprintf(os, "lr");
3199179Sandreas.hansson@arm.com             break;
3202875Sksewell@umich.edu          default:
3215606Snate@binkert.org             ccprintf(os, "r%d", reg_idx);
3229179Sandreas.hansson@arm.com             break;
3232875Sksewell@umich.edu        }
3242875Sksewell@umich.edu    }
3252875Sksewell@umich.edu}
3266221Snate@binkert.org
3276221Snate@binkert.orgvoid
3282875Sksewell@umich.eduArmStaticInst::printFloatReg(std::ostream &os, RegIndex reg_idx) const
3292875Sksewell@umich.edu{
3302875Sksewell@umich.edu    ccprintf(os, "f%d", reg_idx);
3312875Sksewell@umich.edu}
3322875Sksewell@umich.edu
3332875Sksewell@umich.eduvoid
3342875Sksewell@umich.eduArmStaticInst::printCCReg(std::ostream &os, RegIndex reg_idx) const
3352875Sksewell@umich.edu{
3369444SAndreas.Sandberg@ARM.com    ccprintf(os, "cc_%s", ArmISA::ccRegName[reg_idx]);
3379444SAndreas.Sandberg@ARM.com}
3389444SAndreas.Sandberg@ARM.com
3399444SAndreas.Sandberg@ARM.comvoid
3409444SAndreas.Sandberg@ARM.comArmStaticInst::printMiscReg(std::ostream &os, RegIndex reg_idx) const
3419444SAndreas.Sandberg@ARM.com{
3429444SAndreas.Sandberg@ARM.com    assert(reg_idx < NUM_MISCREGS);
3439444SAndreas.Sandberg@ARM.com    ccprintf(os, "%s", ArmISA::miscRegName[reg_idx]);
3449444SAndreas.Sandberg@ARM.com}
3459444SAndreas.Sandberg@ARM.com
3469444SAndreas.Sandberg@ARM.comvoid
3479444SAndreas.Sandberg@ARM.comArmStaticInst::printMnemonic(std::ostream &os,
3489444SAndreas.Sandberg@ARM.com                             const std::string &suffix,
3499444SAndreas.Sandberg@ARM.com                             bool withPred,
3509444SAndreas.Sandberg@ARM.com                             bool withCond64,
3519444SAndreas.Sandberg@ARM.com                             ConditionCode cond64) const
3529444SAndreas.Sandberg@ARM.com{
3539444SAndreas.Sandberg@ARM.com    os << "  " << mnemonic;
3549444SAndreas.Sandberg@ARM.com    if (withPred && !aarch64) {
3559444SAndreas.Sandberg@ARM.com        printCondition(os, machInst.condCode);
3569444SAndreas.Sandberg@ARM.com        os << suffix;
3579444SAndreas.Sandberg@ARM.com    } else if (withCond64) {
3589444SAndreas.Sandberg@ARM.com        os << ".";
3599444SAndreas.Sandberg@ARM.com        printCondition(os, cond64);
3609444SAndreas.Sandberg@ARM.com        os << suffix;
3619444SAndreas.Sandberg@ARM.com    }
3629444SAndreas.Sandberg@ARM.com    if (machInst.bigThumb)
3631060SN/A        os << ".w";
3642292SN/A    os << "   ";
3655595Sgblack@eecs.umich.edu}
3662292SN/A
3671755SN/Avoid
3681060SN/AArmStaticInst::printTarget(std::ostream &os, Addr target,
3692292SN/A                           const SymbolTable *symtab) const
3705595Sgblack@eecs.umich.edu{
3711684SN/A    Addr symbolAddr;
3725358Sgblack@eecs.umich.edu    std::string symbol;
3735358Sgblack@eecs.umich.edu
3745358Sgblack@eecs.umich.edu    if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) {
3755358Sgblack@eecs.umich.edu        ccprintf(os, "<%s", symbol);
3765358Sgblack@eecs.umich.edu        if (symbolAddr != target)
3775358Sgblack@eecs.umich.edu            ccprintf(os, "+%d>", target - symbolAddr);
3785358Sgblack@eecs.umich.edu        else
3795358Sgblack@eecs.umich.edu            ccprintf(os, ">");
3805358Sgblack@eecs.umich.edu    } else {
3815358Sgblack@eecs.umich.edu        ccprintf(os, "%#x", target);
3825358Sgblack@eecs.umich.edu    }
3835358Sgblack@eecs.umich.edu}
3845358Sgblack@eecs.umich.edu
3855358Sgblack@eecs.umich.eduvoid
3865358Sgblack@eecs.umich.eduArmStaticInst::printCondition(std::ostream &os,
3875358Sgblack@eecs.umich.edu                              unsigned code,
3882292SN/A                              bool noImplicit) const
3892292SN/A{
3902292SN/A    switch (code) {
3911684SN/A      case COND_EQ:
3921684SN/A        os << "eq";
3932292SN/A        break;
3941060SN/A      case COND_NE:
3951060SN/A        os << "ne";
3969427SAndreas.Sandberg@ARM.com        break;
3979427SAndreas.Sandberg@ARM.com      case COND_CS:
3982834Sksewell@umich.edu        os << "cs";
3992834Sksewell@umich.edu        break;
4002834Sksewell@umich.edu      case COND_CC:
4012834Sksewell@umich.edu        os << "cc";
4022829Sksewell@umich.edu        break;
4036221Snate@binkert.org      case COND_MI:
4042875Sksewell@umich.edu        os << "mi";
4052875Sksewell@umich.edu        break;
4066221Snate@binkert.org      case COND_PL:
4072829Sksewell@umich.edu        os << "pl";
4082292SN/A        break;
4096221Snate@binkert.org      case COND_VS:
4101060SN/A        os << "vs";
4112292SN/A        break;
4126221Snate@binkert.org      case COND_VC:
4132292SN/A        os << "vc";
4142292SN/A        break;
4158834Satgutier@umich.edu      case COND_HI:
4168834Satgutier@umich.edu        os << "hi";
4178834Satgutier@umich.edu        break;
4188834Satgutier@umich.edu      case COND_LS:
4192292SN/A        os << "ls";
4202292SN/A        break;
4219180Sandreas.hansson@arm.com      case COND_GE:
4222292SN/A        os << "ge";
4232292SN/A        break;
4246221Snate@binkert.org      case COND_LT:
4252292SN/A        os << "lt";
4262292SN/A        break;
4273221Sktlim@umich.edu      case COND_GT:
4282292SN/A        os << "gt";
4299180Sandreas.hansson@arm.com        break;
4309180Sandreas.hansson@arm.com      case COND_LE:
4312292SN/A        os << "le";
4322292SN/A        break;
4332292SN/A      case COND_AL:
4342292SN/A        // This one is implicit.
4356221Snate@binkert.org        if (noImplicit)
4362292SN/A            os << "al";
4372292SN/A        break;
4386221Snate@binkert.org      case COND_UC:
4392292SN/A        // Unconditional.
4402292SN/A        if (noImplicit)
4412292SN/A            os << "uc";
4422292SN/A        break;
4432292SN/A      default:
4442292SN/A        panic("Unrecognized condition code %d.\n", code);
4452292SN/A    }
4469444SAndreas.Sandberg@ARM.com}
4479444SAndreas.Sandberg@ARM.com
4489444SAndreas.Sandberg@ARM.comvoid
4492864Sktlim@umich.eduArmStaticInst::printMemSymbol(std::ostream &os,
4502864Sktlim@umich.edu                              const SymbolTable *symtab,
4512864Sktlim@umich.edu                              const std::string &prefix,
4522864Sktlim@umich.edu                              const Addr addr,
4532864Sktlim@umich.edu                              const std::string &suffix) const
4542864Sktlim@umich.edu{
4552864Sktlim@umich.edu    Addr symbolAddr;
4565595Sgblack@eecs.umich.edu    std::string symbol;
4575595Sgblack@eecs.umich.edu    if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
4582292SN/A        ccprintf(os, "%s%s", prefix, symbol);
4596221Snate@binkert.org        if (symbolAddr != addr)
4602292SN/A            ccprintf(os, "+%d", addr - symbolAddr);
4612843Sktlim@umich.edu        ccprintf(os, suffix);
4622843Sktlim@umich.edu    }
4639342SAndreas.Sandberg@arm.com}
4642843Sktlim@umich.edu
4652843Sktlim@umich.eduvoid
4669342SAndreas.Sandberg@arm.comArmStaticInst::printShiftOperand(std::ostream &os,
4672292SN/A                                     IntRegIndex rm,
4689444SAndreas.Sandberg@ARM.com                                     bool immShift,
4699444SAndreas.Sandberg@ARM.com                                     uint32_t shiftAmt,
4709444SAndreas.Sandberg@ARM.com                                     IntRegIndex rs,
4719444SAndreas.Sandberg@ARM.com                                     ArmShiftType type) const
4729444SAndreas.Sandberg@ARM.com{
4739444SAndreas.Sandberg@ARM.com    bool firstOp = false;
4749444SAndreas.Sandberg@ARM.com
4759444SAndreas.Sandberg@ARM.com    if (rm != INTREG_ZERO) {
4762843Sktlim@umich.edu        printIntReg(os, rm);
4772843Sktlim@umich.edu    }
4782843Sktlim@umich.edu
4792316SN/A    bool done = false;
4802348SN/A
4812843Sktlim@umich.edu    if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
4821060SN/A        shiftAmt = 32;
4831060SN/A
4842316SN/A    switch (type) {
4852316SN/A      case LSL:
4861060SN/A        if (immShift && shiftAmt == 0) {
4875595Sgblack@eecs.umich.edu            done = true;
4887684Sgblack@eecs.umich.edu            break;
4895595Sgblack@eecs.umich.edu        }
4905702Ssaidi@eecs.umich.edu        if (!firstOp)
4916221Snate@binkert.org            os << ", ";
4925702Ssaidi@eecs.umich.edu        os << "LSL";
4936221Snate@binkert.org        break;
4945702Ssaidi@eecs.umich.edu      case LSR:
4955595Sgblack@eecs.umich.edu        if (!firstOp)
4965595Sgblack@eecs.umich.edu            os << ", ";
4975595Sgblack@eecs.umich.edu        os << "LSR";
4985595Sgblack@eecs.umich.edu        break;
4995595Sgblack@eecs.umich.edu      case ASR:
5005595Sgblack@eecs.umich.edu        if (!firstOp)
5015595Sgblack@eecs.umich.edu            os << ", ";
5025595Sgblack@eecs.umich.edu        os << "ASR";
5035595Sgblack@eecs.umich.edu        break;
5041060SN/A      case ROR:
5051060SN/A        if (immShift && shiftAmt == 0) {
5061060SN/A            if (!firstOp)
5071060SN/A                os << ", ";
5081060SN/A            os << "RRX";
5091060SN/A            done = true;
5102348SN/A            break;
5115595Sgblack@eecs.umich.edu        }
5125595Sgblack@eecs.umich.edu        if (!firstOp)
5136221Snate@binkert.org            os << ", ";
5145595Sgblack@eecs.umich.edu        os << "ROR";
5155595Sgblack@eecs.umich.edu        break;
5165595Sgblack@eecs.umich.edu      default:
5175595Sgblack@eecs.umich.edu        panic("Tried to disassemble unrecognized shift type.\n");
5186221Snate@binkert.org    }
5195595Sgblack@eecs.umich.edu    if (!done) {
5205595Sgblack@eecs.umich.edu        if (!firstOp)
5216221Snate@binkert.org            os << " ";
5226221Snate@binkert.org        if (immShift)
5235595Sgblack@eecs.umich.edu            os << "#" << shiftAmt;
5245595Sgblack@eecs.umich.edu        else
5255595Sgblack@eecs.umich.edu            printIntReg(os, rs);
5265595Sgblack@eecs.umich.edu    }
5275595Sgblack@eecs.umich.edu}
5286221Snate@binkert.org
5295595Sgblack@eecs.umich.eduvoid
5301060SN/AArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os,
5311060SN/A                                  IntRegIndex rm, ArmExtendType type,
5323781Sgblack@eecs.umich.edu                                  int64_t shiftAmt) const
5331060SN/A{
5343781Sgblack@eecs.umich.edu    if (!firstOperand)
5352455SN/A        ccprintf(os, ", ");
5361060SN/A    printIntReg(os, rm);
5371060SN/A    if (type == UXTX && shiftAmt == 0)
5383781Sgblack@eecs.umich.edu        return;
5391060SN/A    switch (type) {
5403781Sgblack@eecs.umich.edu      case UXTB: ccprintf(os, ", UXTB");
5412455SN/A        break;
5426221Snate@binkert.org      case UXTH: ccprintf(os, ", UXTH");
5431060SN/A        break;
5446314Sgblack@eecs.umich.edu      case UXTW: ccprintf(os, ", UXTW");
5452292SN/A        break;
5466221Snate@binkert.org      case UXTX: ccprintf(os, ", LSL");
5472292SN/A        break;
5482348SN/A      case SXTB: ccprintf(os, ", SXTB");
5492348SN/A        break;
5502348SN/A      case SXTH: ccprintf(os, ", SXTH");
5512348SN/A        break;
5522348SN/A      case SXTW: ccprintf(os, ", SXTW");
5536221Snate@binkert.org        break;
5542292SN/A      case SXTX: ccprintf(os, ", SXTW");
5556314Sgblack@eecs.umich.edu        break;
5562292SN/A    }
5576221Snate@binkert.org    if (type == UXTX || shiftAmt)
5582292SN/A        ccprintf(os, " #%d", shiftAmt);
5597720Sgblack@eecs.umich.edu}
5607720Sgblack@eecs.umich.edu
5617720Sgblack@eecs.umich.eduvoid
5627720Sgblack@eecs.umich.eduArmStaticInst::printDataInst(std::ostream &os, bool withImm,
5637720Sgblack@eecs.umich.edu        bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
5647720Sgblack@eecs.umich.edu        IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
5652348SN/A        ArmShiftType type, uint64_t imm) const
5667720Sgblack@eecs.umich.edu{
5672292SN/A    printMnemonic(os, s ? "s" : "");
5684636Sgblack@eecs.umich.edu    bool firstOp = true;
5697720Sgblack@eecs.umich.edu
5704636Sgblack@eecs.umich.edu    // Destination
5712348SN/A    if (rd != INTREG_ZERO) {
5727720Sgblack@eecs.umich.edu        firstOp = false;
5732756Sksewell@umich.edu        printIntReg(os, rd);
5745595Sgblack@eecs.umich.edu    }
5755595Sgblack@eecs.umich.edu
5765595Sgblack@eecs.umich.edu    // Source 1.
5775595Sgblack@eecs.umich.edu    if (rn != INTREG_ZERO) {
5786221Snate@binkert.org        if (!firstOp)
5795595Sgblack@eecs.umich.edu            os << ", ";
5801060SN/A        firstOp = false;
5811060SN/A        printIntReg(os, rn);
5821060SN/A    }
5832292SN/A
5841060SN/A    if (!firstOp)
5851060SN/A        os << ", ";
5868834Satgutier@umich.edu    if (withImm) {
5871060SN/A        ccprintf(os, "#%ld", imm);
5882325SN/A    } else {
5892325SN/A        printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
5901060SN/A    }
5911061SN/A}
5921060SN/A
5932935Sksewell@umich.edustd::string
5942935Sksewell@umich.eduArmStaticInst::generateDisassembly(Addr pc,
5956221Snate@binkert.org                                   const SymbolTable *symtab) const
5961060SN/A{
5971062SN/A    std::stringstream ss;
5986221Snate@binkert.org    printMnemonic(ss);
5992292SN/A    return ss.str();
6002348SN/A}
6016221Snate@binkert.org
6022292SN/A
6032348SN/AFault
6042292SN/AArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const
6051062SN/A{
6062348SN/A    switch (el) {
6071060SN/A      case EL1:
6081060SN/A        return std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
6091060SN/A                                                EC_TRAPPED_SIMD_FP);
6105737Scws3k@cs.virginia.edu      case EL2:
6115737Scws3k@cs.virginia.edu        return std::make_shared<HypervisorTrap>(machInst, 0x1E00000,
6125737Scws3k@cs.virginia.edu                                                EC_TRAPPED_SIMD_FP);
6135737Scws3k@cs.virginia.edu      case EL3:
6145737Scws3k@cs.virginia.edu        return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000,
6151060SN/A                                                   EC_TRAPPED_SIMD_FP);
6162292SN/A
6171060SN/A      default:
6182292SN/A        panic("Illegal EL in advSIMDFPAccessTrap64\n");
6192292SN/A    }
6202292SN/A}
6212292SN/A
6222292SN/A
6232325SN/AFault
6242348SN/AArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const
6252348SN/A{
6262348SN/A    const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el;
6272292SN/A
6282325SN/A    if (ArmSystem::haveVirtualization(tc) && el <= EL2) {
6292292SN/A        HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2);
6302325SN/A        if (cptrEnCheck.tfp)
6312325SN/A            return advSIMDFPAccessTrap64(EL2);
6322292SN/A    }
6332292SN/A
6342292SN/A    if (ArmSystem::haveSecurity(tc)) {
6351060SN/A        HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
6361060SN/A        if (cptrEnCheck.tfp)
6371060SN/A            return advSIMDFPAccessTrap64(EL3);
6381060SN/A    }
6391060SN/A
6401060SN/A    return NoFault;
6411060SN/A}
6421060SN/A
6431060SN/AFault
6441060SN/AArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc,
6451060SN/A                                       CPSR cpsr, CPACR cpacr) const
6461060SN/A{
6471060SN/A    const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el;
6481060SN/A    if ((el == EL0 && cpacr.fpen != 0x3) ||
6491060SN/A        (el == EL1 && !(cpacr.fpen & 0x1)))
6501060SN/A        return advSIMDFPAccessTrap64(EL1);
6511060SN/A
6521060SN/A    return checkFPAdvSIMDTrap64(tc, cpsr);
6531060SN/A}
6541060SN/A
6551060SN/AFault
6561060SN/AArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc,
6571060SN/A                                         CPSR cpsr, CPACR cpacr,
6582292SN/A                                         NSACR nsacr, FPEXC fpexc,
6592292SN/A                                         bool fpexc_check, bool advsimd) const
6602292SN/A{
6612292SN/A    const bool have_virtualization = ArmSystem::haveVirtualization(tc);
6621060SN/A    const bool have_security = ArmSystem::haveSecurity(tc);
6631060SN/A    const bool is_secure = inSecureState(tc);
6641060SN/A    const ExceptionLevel cur_el = opModeToEL(currOpMode(tc));
6651060SN/A
6662292SN/A    if (cur_el == EL0 && ELIs64(tc, EL1))
6676221Snate@binkert.org        return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr);
6682292SN/A
6692292SN/A    uint8_t cpacr_cp10 = cpacr.cp10;
6702292SN/A    bool cpacr_asedis = cpacr.asedis;
6712292SN/A
6729384SAndreas.Sandberg@arm.com    if (have_security && !ELIs64(tc, EL3) && !is_secure) {
6736313Sgblack@eecs.umich.edu        if (nsacr.nsasedis)
6748707Sandreas.hansson@arm.com            cpacr_asedis = true;
6758707Sandreas.hansson@arm.com        if (nsacr.cp10 == 0)
6768707Sandreas.hansson@arm.com            cpacr_cp10 = 0;
6778707Sandreas.hansson@arm.com    }
6788707Sandreas.hansson@arm.com
6798707Sandreas.hansson@arm.com    if (cur_el != EL2) {
6801060SN/A        if (advsimd && cpacr_asedis)
6812292SN/A            return disabledFault();
6822292SN/A
6832292SN/A        if ((cur_el == EL0 && cpacr_cp10 != 0x3) ||
6842292SN/A            (cur_el != EL0 && !(cpacr_cp10 & 0x1)))
6852292SN/A            return disabledFault();
6862292SN/A    }
6872292SN/A
6882292SN/A    if (fpexc_check && !fpexc.en)
6892292SN/A        return disabledFault();
6902292SN/A
6912292SN/A    // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap --
6922292SN/A
6931060SN/A    if (have_virtualization && !is_secure && ELIs64(tc, EL2))
6941060SN/A        return checkFPAdvSIMDTrap64(tc, cpsr);
6951060SN/A
6961061SN/A    if (have_virtualization && !is_secure) {
6971060SN/A        HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR);
6981061SN/A        bool hcptr_cp10 = hcptr.tcp10;
6991060SN/A        bool hcptr_tase = hcptr.tase;
7001061SN/A
7011060SN/A        if (have_security && !ELIs64(tc, EL3) && !is_secure) {
7021061SN/A            if (nsacr.nsasedis)
7031060SN/A                hcptr_tase = true;
7041061SN/A            if (nsacr.cp10)
7051060SN/A                hcptr_cp10 = true;
7061060SN/A        }
7071060SN/A
7081060SN/A        if ((advsimd && hcptr_tase) || hcptr_cp10) {
7091060SN/A            const uint32_t iss = advsimd ? (1 << 5) : 0xA;
7101060SN/A            if (cur_el == EL2) {
7111060SN/A                return std::make_shared<UndefinedInstruction>(
7121060SN/A                    machInst, iss,
7131060SN/A                    EC_TRAPPED_HCPTR, mnemonic);
7141060SN/A            } else {
7151060SN/A                return std::make_shared<HypervisorTrap>(
7161060SN/A                    machInst, iss,
7171060SN/A                    EC_TRAPPED_HCPTR);
7181060SN/A            }
7191060SN/A
7201060SN/A        }
7212348SN/A    }
7222348SN/A
7232348SN/A    if (have_security && ELIs64(tc, EL3)) {
7242348SN/A        HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
7252348SN/A        if (cptrEnCheck.tfp)
7262325SN/A            return advSIMDFPAccessTrap64(EL3);
7271060SN/A    }
7282348SN/A
7292348SN/A    return NoFault;
7302325SN/A}
7312292SN/A
7322348SN/A
7332325SN/Astatic uint8_t
7342325SN/AgetRestoredITBits(ThreadContext *tc, CPSR spsr)
7352292SN/A{
7362348SN/A    // See: shared/functions/system/RestoredITBits in the ARM ARM
7372325SN/A
7382325SN/A    const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode);
7392292SN/A    const uint8_t it = itState(spsr);
7402292SN/A
7412292SN/A    if (!spsr.t || spsr.il)
7422260SN/A        return 0;
7435807Snate@binkert.org
7445807Snate@binkert.org    // The IT bits are forced to zero when they are set to a reserved
7452292SN/A    // value.
7466221Snate@binkert.org    if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0)
7472292SN/A        return 0;
7482292SN/A
7492680Sktlim@umich.edu    const bool itd = el == EL2 ?
7506221Snate@binkert.org        ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd :
7516221Snate@binkert.org        ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd;
7521681SN/A
7532680Sktlim@umich.edu    // The IT bits are forced to zero when returning to A32 state, or
7542190SN/A    // when returning to an EL with the ITD bit set to 1, and the IT
7552190SN/A    // bits are describing a multi-instruction block.
7562292SN/A    if (itd && bits(it, 2, 0) != 0)
7573093Sksewell@umich.edu        return 0;
7581060SN/A
7592348SN/A    return it;
7602348SN/A}
7612348SN/A
7622348SN/Astatic bool
7638733Sgeoffrey.blake@arm.comillegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
7642316SN/A{
7652292SN/A    const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode;
7661060SN/A    if (badMode(mode))
7671060SN/A        return true;
7689342SAndreas.Sandberg@arm.com
7699342SAndreas.Sandberg@arm.com    const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode;
7702843Sktlim@umich.edu    const ExceptionLevel target_el = opModeToEL(mode);
7712348SN/A    if (target_el > opModeToEL(cur_mode))
7722292SN/A        return true;
7732260SN/A
7742292SN/A    if (target_el == EL3 && !ArmSystem::haveSecurity(tc))
7752292SN/A        return true;
7761060SN/A
7772292SN/A    if (target_el == EL2 && !ArmSystem::haveVirtualization(tc))
7782292SN/A        return true;
7792292SN/A
7802292SN/A    if (!spsr.width) {
7819180Sandreas.hansson@arm.com        // aarch64
7822292SN/A        if (!ArmSystem::highestELIs64(tc))
7832829Sksewell@umich.edu            return true;
7842829Sksewell@umich.edu
7852829Sksewell@umich.edu        if (spsr & 0x2)
7862292SN/A            return true;
7876221Snate@binkert.org        if (target_el == EL0 && spsr.sp)
7882292SN/A            return true;
7892292SN/A        if (target_el == EL2 && !((SCR)tc->readMiscReg(MISCREG_SCR_EL3)).ns)
7906221Snate@binkert.org            return false;
7912292SN/A    } else {
7925595Sgblack@eecs.umich.edu        return badMode32(mode);
7936974Stjones1@inf.ed.ac.uk    }
7947520Sgblack@eecs.umich.edu
7955595Sgblack@eecs.umich.edu    return false;
7966974Stjones1@inf.ed.ac.uk}
7976974Stjones1@inf.ed.ac.uk
7985595Sgblack@eecs.umich.eduCPSR
7995595Sgblack@eecs.umich.eduArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
8005595Sgblack@eecs.umich.edu{
8016974Stjones1@inf.ed.ac.uk    CPSR new_cpsr = 0;
8027520Sgblack@eecs.umich.edu
8035595Sgblack@eecs.umich.edu    // gem5 doesn't implement single-stepping, so force the SS bit to
8046974Stjones1@inf.ed.ac.uk    // 0.
8056974Stjones1@inf.ed.ac.uk    new_cpsr.ss = 0;
8065595Sgblack@eecs.umich.edu
8075595Sgblack@eecs.umich.edu    if (illegalExceptionReturn(tc, cpsr, spsr)) {
8088707Sandreas.hansson@arm.com        new_cpsr.il = 1;
8098850Sandreas.hansson@arm.com    } else {
8108707Sandreas.hansson@arm.com        new_cpsr.il = spsr.il;
8116974Stjones1@inf.ed.ac.uk        if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) {
8128850Sandreas.hansson@arm.com            new_cpsr.il = 1;
8136974Stjones1@inf.ed.ac.uk        } else if (spsr.width) {
8142292SN/A            new_cpsr.mode = spsr.mode;
8155999Snate@binkert.org        } else {
8162292SN/A            new_cpsr.el = spsr.el;
8175999Snate@binkert.org            new_cpsr.sp = spsr.sp;
8188627SAli.Saidi@ARM.com        }
8198627SAli.Saidi@ARM.com    }
8208627SAli.Saidi@ARM.com
8212292SN/A    new_cpsr.nz = spsr.nz;
8225999Snate@binkert.org    new_cpsr.c = spsr.c;
8238834Satgutier@umich.edu    new_cpsr.v = spsr.v;
8248834Satgutier@umich.edu    if (new_cpsr.width) {
8252292SN/A        // aarch32
8265999Snate@binkert.org        const ITSTATE it = getRestoredITBits(tc, spsr);
8272292SN/A        new_cpsr.q = spsr.q;
8282292SN/A        new_cpsr.ge = spsr.ge;
8292292SN/A        new_cpsr.e = spsr.e;
8302292SN/A        new_cpsr.aif = spsr.aif;
8312292SN/A        new_cpsr.t = spsr.t;
8322292SN/A        new_cpsr.it2 = it.top6;
8332292SN/A        new_cpsr.it1 = it.bottom2;
8342292SN/A    } else {
8357897Shestness@cs.utexas.edu        // aarch64
8367897Shestness@cs.utexas.edu        new_cpsr.daif = spsr.daif;
8377897Shestness@cs.utexas.edu    }
8387897Shestness@cs.utexas.edu
8397897Shestness@cs.utexas.edu    return new_cpsr;
8407897Shestness@cs.utexas.edu}
8417897Shestness@cs.utexas.edu
8427897Shestness@cs.utexas.edu
8437897Shestness@cs.utexas.edu
8447897Shestness@cs.utexas.edu}
8451060SN/A