110037SARM gem5 Developers// -*- mode:c++ -*-
210037SARM gem5 Developers
312580Sgiacomo.travaglini@arm.com// Copyright (c) 2011-2013, 2016,2018 ARM Limited
410037SARM gem5 Developers// All rights reserved
510037SARM gem5 Developers//
610037SARM gem5 Developers// The license below extends only to copyright in the software and shall
710037SARM gem5 Developers// not be construed as granting a license to any other intellectual
810037SARM gem5 Developers// property including but not limited to intellectual property relating
910037SARM gem5 Developers// to a hardware implementation of the functionality of the software
1010037SARM gem5 Developers// licensed hereunder.  You may use the software subject to the license
1110037SARM gem5 Developers// terms below provided that you ensure that this notice is replicated
1210037SARM gem5 Developers// unmodified and in its entirety in all distributions of the software,
1310037SARM gem5 Developers// modified or unmodified, in source code or in binary form.
1410037SARM gem5 Developers//
1510037SARM gem5 Developers// Redistribution and use in source and binary forms, with or without
1610037SARM gem5 Developers// modification, are permitted provided that the following conditions are
1710037SARM gem5 Developers// met: redistributions of source code must retain the above copyright
1810037SARM gem5 Developers// notice, this list of conditions and the following disclaimer;
1910037SARM gem5 Developers// redistributions in binary form must reproduce the above copyright
2010037SARM gem5 Developers// notice, this list of conditions and the following disclaimer in the
2110037SARM gem5 Developers// documentation and/or other materials provided with the distribution;
2210037SARM gem5 Developers// neither the name of the copyright holders nor the names of its
2310037SARM gem5 Developers// contributors may be used to endorse or promote products derived from
2410037SARM gem5 Developers// this software without specific prior written permission.
2510037SARM gem5 Developers//
2610037SARM gem5 Developers// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2710037SARM gem5 Developers// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2810037SARM gem5 Developers// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2910037SARM gem5 Developers// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3010037SARM gem5 Developers// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3110037SARM gem5 Developers// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3210037SARM gem5 Developers// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3310037SARM gem5 Developers// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3410037SARM gem5 Developers// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3510037SARM gem5 Developers// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3610037SARM gem5 Developers// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3710037SARM gem5 Developers//
3810037SARM gem5 Developers// Authors: Gabe Black
3910037SARM gem5 Developers//          Giacomo Gabrielli
4010037SARM gem5 Developers
4110037SARM gem5 Developerslet {{
4210037SARM gem5 Developers
4310037SARM gem5 Developers    header_output = ""
4410037SARM gem5 Developers    decoder_output = ""
4510037SARM gem5 Developers    exec_output = ""
4610037SARM gem5 Developers
4710037SARM gem5 Developers    # B, BL
4810037SARM gem5 Developers    for (mnem, link) in (("b", False), ("bl", True)):
4910037SARM gem5 Developers        bCode = ('NPC = purifyTaggedAddr(RawPC + imm, xc->tcBase(), '
5010037SARM gem5 Developers                 'currEL(xc->tcBase()));\n')
5110037SARM gem5 Developers        instFlags = ['IsDirectControl', 'IsUncondControl']
5210037SARM gem5 Developers        if (link):
5310037SARM gem5 Developers            bCode += 'XLR = RawPC + 4;\n'
5410037SARM gem5 Developers            instFlags += ['IsCall']
5510037SARM gem5 Developers
5610037SARM gem5 Developers        bIop = InstObjParams(mnem, mnem.capitalize() + "64",
5710037SARM gem5 Developers                             "BranchImm64", bCode, instFlags)
5810037SARM gem5 Developers        header_output += BranchImm64Declare.subst(bIop)
5910037SARM gem5 Developers        decoder_output += BranchImm64Constructor.subst(bIop)
6010037SARM gem5 Developers        exec_output += BasicExecute.subst(bIop)
6110037SARM gem5 Developers
6210037SARM gem5 Developers    # BR, BLR
6310037SARM gem5 Developers    for (mnem, link) in (("br", False), ("blr", True)):
6410037SARM gem5 Developers        bCode = ('NPC = purifyTaggedAddr(XOp1, xc->tcBase(), '
6510037SARM gem5 Developers                 'currEL(xc->tcBase()));\n')
6610037SARM gem5 Developers        instFlags = ['IsIndirectControl', 'IsUncondControl']
6710037SARM gem5 Developers        if (link):
6810037SARM gem5 Developers            bCode += 'XLR = RawPC + 4;\n'
6910037SARM gem5 Developers            instFlags += ['IsCall']
7010037SARM gem5 Developers
7110037SARM gem5 Developers        bIop = InstObjParams(mnem, mnem.capitalize() + "64",
7210037SARM gem5 Developers                             "BranchReg64", bCode, instFlags)
7310037SARM gem5 Developers        header_output += BranchReg64Declare.subst(bIop)
7410037SARM gem5 Developers        decoder_output += BranchReg64Constructor.subst(bIop)
7510037SARM gem5 Developers        exec_output += BasicExecute.subst(bIop)
7610037SARM gem5 Developers
7710037SARM gem5 Developers    # B conditional
7810037SARM gem5 Developers    bCode = '''
7910037SARM gem5 Developers        if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode))
8010037SARM gem5 Developers            NPC = purifyTaggedAddr(RawPC + imm, xc->tcBase(),
8110037SARM gem5 Developers                                   currEL(xc->tcBase()));
8210037SARM gem5 Developers        else
8310037SARM gem5 Developers            NPC = NPC;
8410037SARM gem5 Developers    '''
8510037SARM gem5 Developers    bIop = InstObjParams("b", "BCond64", "BranchImmCond64", bCode,
8610037SARM gem5 Developers                         ['IsCondControl', 'IsDirectControl'])
8710037SARM gem5 Developers    header_output += BranchImmCond64Declare.subst(bIop)
8810037SARM gem5 Developers    decoder_output += BranchImmCond64Constructor.subst(bIop)
8910037SARM gem5 Developers    exec_output += BasicExecute.subst(bIop)
9010037SARM gem5 Developers
9110037SARM gem5 Developers    # RET
9210037SARM gem5 Developers    bCode = ('NPC = purifyTaggedAddr(XOp1, xc->tcBase(), '
9310037SARM gem5 Developers             'currEL(xc->tcBase()));\n')
9410037SARM gem5 Developers    instFlags = ['IsIndirectControl', 'IsUncondControl', 'IsReturn']
9510037SARM gem5 Developers
9610037SARM gem5 Developers    bIop = InstObjParams('ret', 'Ret64', "BranchRet64", bCode, instFlags)
9710037SARM gem5 Developers    header_output += BranchReg64Declare.subst(bIop)
9810037SARM gem5 Developers    decoder_output += BranchReg64Constructor.subst(bIop)
9910037SARM gem5 Developers    exec_output += BasicExecute.subst(bIop)
10010037SARM gem5 Developers
10110037SARM gem5 Developers    # ERET
10210037SARM gem5 Developers    bCode = '''Addr newPc;
10310037SARM gem5 Developers                CPSR cpsr = Cpsr;
10410037SARM gem5 Developers                CPSR spsr = Spsr;
10510037SARM gem5 Developers
10614172Sgiacomo.travaglini@arm.com                ExceptionLevel curr_el = currEL(cpsr);
10710037SARM gem5 Developers                switch (curr_el) {
10810037SARM gem5 Developers                  case EL3:
10910037SARM gem5 Developers                    newPc = xc->tcBase()->readMiscReg(MISCREG_ELR_EL3);
11010037SARM gem5 Developers                    break;
11110037SARM gem5 Developers                  case EL2:
11210037SARM gem5 Developers                    newPc = xc->tcBase()->readMiscReg(MISCREG_ELR_EL2);
11310037SARM gem5 Developers                    break;
11410037SARM gem5 Developers                  case EL1:
11510037SARM gem5 Developers                    newPc = xc->tcBase()->readMiscReg(MISCREG_ELR_EL1);
11610037SARM gem5 Developers                    break;
11710037SARM gem5 Developers                  default:
11810474Sandreas.hansson@arm.com                    return std::make_shared<UndefinedInstruction>(machInst,
11910474Sandreas.hansson@arm.com                                                                  false,
12010474Sandreas.hansson@arm.com                                                                  mnemonic);
12110037SARM gem5 Developers                    break;
12210037SARM gem5 Developers                }
12312580Sgiacomo.travaglini@arm.com                if (spsr.width) {
12412580Sgiacomo.travaglini@arm.com                    // Exception return to AArch32.
12512580Sgiacomo.travaglini@arm.com                    // 32 most significant bits are ignored
12612580Sgiacomo.travaglini@arm.com                    newPc &= mask(32);
12712580Sgiacomo.travaglini@arm.com
12812580Sgiacomo.travaglini@arm.com                    if (newPc & mask(2)) {
12912580Sgiacomo.travaglini@arm.com                        // Mask bits to avoid PC Alignment fault when returning
13012580Sgiacomo.travaglini@arm.com                        // to AArch32
13112580Sgiacomo.travaglini@arm.com                        if (spsr.t)
13212580Sgiacomo.travaglini@arm.com                            newPc = newPc & ~mask(1);
13312580Sgiacomo.travaglini@arm.com                        else
13412580Sgiacomo.travaglini@arm.com                            newPc = newPc & ~mask(2);
13512580Sgiacomo.travaglini@arm.com                    }
13610037SARM gem5 Developers                }
13710037SARM gem5 Developers
13811514Sandreas.sandberg@arm.com                CPSR new_cpsr = getPSTATEFromPSR(xc->tcBase(), cpsr, spsr);
13910037SARM gem5 Developers
14011514Sandreas.sandberg@arm.com                Cpsr = new_cpsr;
14111514Sandreas.sandberg@arm.com                CondCodesNZ = new_cpsr.nz;
14211514Sandreas.sandberg@arm.com                CondCodesC  = new_cpsr.c;
14311514Sandreas.sandberg@arm.com                CondCodesV  = new_cpsr.v;
14410037SARM gem5 Developers
14511514Sandreas.sandberg@arm.com                NextAArch64 = !new_cpsr.width;
14611514Sandreas.sandberg@arm.com                NextItState = itState(new_cpsr);
14711514Sandreas.sandberg@arm.com                NPC = purifyTaggedAddr(newPc, xc->tcBase(),
14814172Sgiacomo.travaglini@arm.com                    currEL(new_cpsr));
14910037SARM gem5 Developers
15010037SARM gem5 Developers                LLSCLock = 0;  // Clear exclusive monitor
15110037SARM gem5 Developers                SevMailbox = 1; //Set Event Register
15210037SARM gem5 Developers    '''
15310037SARM gem5 Developers    instFlags = ['IsSerializeAfter', 'IsNonSpeculative', 'IsSquashAfter']
15410037SARM gem5 Developers    bIop = InstObjParams('eret', 'Eret64', "BranchEret64", bCode, instFlags)
15510037SARM gem5 Developers    header_output += BasicDeclare.subst(bIop)
15610037SARM gem5 Developers    decoder_output += BasicConstructor64.subst(bIop)
15710037SARM gem5 Developers    exec_output += BasicExecute.subst(bIop)
15810037SARM gem5 Developers
15910037SARM gem5 Developers    # CBNZ, CBZ
16010037SARM gem5 Developers    for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
16110037SARM gem5 Developers        code = ('NPC = (Op164 %(test)s 0) ? '
16210037SARM gem5 Developers                'purifyTaggedAddr(RawPC + imm, xc->tcBase(), '
16310037SARM gem5 Developers                'currEL(xc->tcBase())) : NPC;\n')
16410037SARM gem5 Developers        code = code % {"test": test}
16510037SARM gem5 Developers        iop = InstObjParams(mnem, mnem.capitalize() + "64",
16610037SARM gem5 Developers                            "BranchImmReg64", code,
16710037SARM gem5 Developers                            ['IsCondControl', 'IsDirectControl'])
16810037SARM gem5 Developers        header_output += BranchImmReg64Declare.subst(iop)
16910037SARM gem5 Developers        decoder_output += BranchImmReg64Constructor.subst(iop)
17010037SARM gem5 Developers        exec_output += BasicExecute.subst(iop)
17110037SARM gem5 Developers
17210037SARM gem5 Developers    # TBNZ, TBZ
17310037SARM gem5 Developers    for (mnem, test) in (("tbz", "=="), ("tbnz", "!=")):
17410037SARM gem5 Developers        code = ('NPC = ((Op164 & imm1) %(test)s 0) ? '
17510037SARM gem5 Developers                'purifyTaggedAddr(RawPC + imm2, xc->tcBase(), '
17610037SARM gem5 Developers                'currEL(xc->tcBase())) : NPC;\n')
17710037SARM gem5 Developers        code = code % {"test": test}
17810037SARM gem5 Developers        iop = InstObjParams(mnem, mnem.capitalize() + "64",
17910037SARM gem5 Developers                            "BranchImmImmReg64", code,
18010037SARM gem5 Developers                            ['IsCondControl', 'IsDirectControl'])
18110037SARM gem5 Developers        header_output += BranchImmImmReg64Declare.subst(iop)
18210037SARM gem5 Developers        decoder_output += BranchImmImmReg64Constructor.subst(iop)
18310037SARM gem5 Developers        exec_output += BasicExecute.subst(iop)
18410037SARM gem5 Developers}};
185