branch64.isa revision 10037
110037SARM gem5 Developers// -*- mode:c++ -*-
210037SARM gem5 Developers
310037SARM gem5 Developers// Copyright (c) 2011-2013 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
10610037SARM gem5 Developers                ExceptionLevel curr_el = opModeToEL((OperatingMode) (uint8_t) cpsr.mode);
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:
11810037SARM gem5 Developers                    return new UndefinedInstruction(machInst, false, mnemonic);
11910037SARM gem5 Developers                    break;
12010037SARM gem5 Developers                }
12110037SARM gem5 Developers                if (spsr.width && (newPc & mask(2))) {
12210037SARM gem5 Developers                    // To avoid PC Alignment fault when returning to AArch32
12310037SARM gem5 Developers                    if (spsr.t)
12410037SARM gem5 Developers                        newPc = newPc & ~mask(1);
12510037SARM gem5 Developers                    else
12610037SARM gem5 Developers                        newPc = newPc & ~mask(2);
12710037SARM gem5 Developers                }
12810037SARM gem5 Developers                spsr.q = 0;
12910037SARM gem5 Developers                spsr.it1 = 0;
13010037SARM gem5 Developers                spsr.j = 0;
13110037SARM gem5 Developers                spsr.res0_23_22 = 0;
13210037SARM gem5 Developers                spsr.ge = 0;
13310037SARM gem5 Developers                spsr.it2 = 0;
13410037SARM gem5 Developers                spsr.t = 0;
13510037SARM gem5 Developers
13610037SARM gem5 Developers                OperatingMode mode = (OperatingMode) (uint8_t) spsr.mode;
13710037SARM gem5 Developers                bool illegal = false;
13810037SARM gem5 Developers                ExceptionLevel target_el;
13910037SARM gem5 Developers                if (badMode(mode)) {
14010037SARM gem5 Developers                    illegal = true;
14110037SARM gem5 Developers                } else {
14210037SARM gem5 Developers                    target_el = opModeToEL(mode);
14310037SARM gem5 Developers                    if (((target_el == EL2) &&
14410037SARM gem5 Developers                         !ArmSystem::haveVirtualization(xc->tcBase())) ||
14510037SARM gem5 Developers                            (target_el > curr_el) ||
14610037SARM gem5 Developers                            (spsr.width == 1)) {
14710037SARM gem5 Developers                        illegal = true;
14810037SARM gem5 Developers                    } else {
14910037SARM gem5 Developers                        bool known = true;
15010037SARM gem5 Developers                        bool from32 = (spsr.width == 1);
15110037SARM gem5 Developers                        bool to32 = false;
15210037SARM gem5 Developers                        if (false) { // TODO: !haveAArch32EL
15310037SARM gem5 Developers                            to32 = false;
15410037SARM gem5 Developers                        } else if (!ArmSystem::highestELIs64(xc->tcBase())) {
15510037SARM gem5 Developers                            to32 = true;
15610037SARM gem5 Developers                        } else {
15710037SARM gem5 Developers                            bool scr_rw, hcr_rw;
15810037SARM gem5 Developers                            if (ArmSystem::haveSecurity(xc->tcBase())) {
15910037SARM gem5 Developers                                SCR scr = xc->tcBase()->readMiscReg(MISCREG_SCR_EL3);
16010037SARM gem5 Developers                                scr_rw = scr.rw;
16110037SARM gem5 Developers                            } else {
16210037SARM gem5 Developers                                scr_rw = true;
16310037SARM gem5 Developers                            }
16410037SARM gem5 Developers
16510037SARM gem5 Developers                            if (ArmSystem::haveVirtualization(xc->tcBase())) {
16610037SARM gem5 Developers                                HCR hcr = xc->tcBase()->readMiscReg(MISCREG_HCR_EL2);
16710037SARM gem5 Developers                                hcr_rw = hcr.rw;
16810037SARM gem5 Developers                            } else {
16910037SARM gem5 Developers                                hcr_rw = scr_rw;
17010037SARM gem5 Developers                            }
17110037SARM gem5 Developers
17210037SARM gem5 Developers                            switch (target_el) {
17310037SARM gem5 Developers                              case EL3:
17410037SARM gem5 Developers                                to32 = false;
17510037SARM gem5 Developers                                break;
17610037SARM gem5 Developers                              case EL2:
17710037SARM gem5 Developers                                to32 = !scr_rw;
17810037SARM gem5 Developers                                break;
17910037SARM gem5 Developers                              case EL1:
18010037SARM gem5 Developers                                to32 = !scr_rw || !hcr_rw;
18110037SARM gem5 Developers                                break;
18210037SARM gem5 Developers                              case EL0:
18310037SARM gem5 Developers                                if (curr_el == EL0) {
18410037SARM gem5 Developers                                    to32 = cpsr.width;
18510037SARM gem5 Developers                                } else if (!scr_rw || !hcr_rw) {
18610037SARM gem5 Developers                                    // EL0 using AArch32 if EL1 using AArch32
18710037SARM gem5 Developers                                    to32 = true;
18810037SARM gem5 Developers                                } else {
18910037SARM gem5 Developers                                    known = false;
19010037SARM gem5 Developers                                    to32 = false;
19110037SARM gem5 Developers                                }
19210037SARM gem5 Developers                            }
19310037SARM gem5 Developers                        }
19410037SARM gem5 Developers                        if (known)
19510037SARM gem5 Developers                            illegal = (from32 != to32);
19610037SARM gem5 Developers                    }
19710037SARM gem5 Developers                }
19810037SARM gem5 Developers
19910037SARM gem5 Developers                if (illegal) {
20010037SARM gem5 Developers                    uint8_t old_mode = cpsr.mode;
20110037SARM gem5 Developers                    spsr.mode = old_mode; // Preserve old mode when invalid
20210037SARM gem5 Developers                    spsr.il = 1;
20310037SARM gem5 Developers                } else {
20410037SARM gem5 Developers                    if (cpsr.width != spsr.width)
20510037SARM gem5 Developers                        panic("AArch32/AArch64 interprocessing not supported yet");
20610037SARM gem5 Developers                }
20710037SARM gem5 Developers                Cpsr = spsr;
20810037SARM gem5 Developers
20910037SARM gem5 Developers                CondCodesNZ = spsr.nz;
21010037SARM gem5 Developers                CondCodesC  = spsr.c;
21110037SARM gem5 Developers                CondCodesV  = spsr.v;
21210037SARM gem5 Developers                NPC = purifyTaggedAddr(newPc, xc->tcBase(),
21310037SARM gem5 Developers                    opModeToEL((OperatingMode) (uint8_t) spsr.mode));
21410037SARM gem5 Developers                LLSCLock = 0;  // Clear exclusive monitor
21510037SARM gem5 Developers                SevMailbox = 1; //Set Event Register
21610037SARM gem5 Developers    '''
21710037SARM gem5 Developers    instFlags = ['IsSerializeAfter', 'IsNonSpeculative', 'IsSquashAfter']
21810037SARM gem5 Developers    bIop = InstObjParams('eret', 'Eret64', "BranchEret64", bCode, instFlags)
21910037SARM gem5 Developers    header_output += BasicDeclare.subst(bIop)
22010037SARM gem5 Developers    decoder_output += BasicConstructor64.subst(bIop)
22110037SARM gem5 Developers    exec_output += BasicExecute.subst(bIop)
22210037SARM gem5 Developers
22310037SARM gem5 Developers    # CBNZ, CBZ
22410037SARM gem5 Developers    for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
22510037SARM gem5 Developers        code = ('NPC = (Op164 %(test)s 0) ? '
22610037SARM gem5 Developers                'purifyTaggedAddr(RawPC + imm, xc->tcBase(), '
22710037SARM gem5 Developers                'currEL(xc->tcBase())) : NPC;\n')
22810037SARM gem5 Developers        code = code % {"test": test}
22910037SARM gem5 Developers        iop = InstObjParams(mnem, mnem.capitalize() + "64",
23010037SARM gem5 Developers                            "BranchImmReg64", code,
23110037SARM gem5 Developers                            ['IsCondControl', 'IsDirectControl'])
23210037SARM gem5 Developers        header_output += BranchImmReg64Declare.subst(iop)
23310037SARM gem5 Developers        decoder_output += BranchImmReg64Constructor.subst(iop)
23410037SARM gem5 Developers        exec_output += BasicExecute.subst(iop)
23510037SARM gem5 Developers
23610037SARM gem5 Developers    # TBNZ, TBZ
23710037SARM gem5 Developers    for (mnem, test) in (("tbz", "=="), ("tbnz", "!=")):
23810037SARM gem5 Developers        code = ('NPC = ((Op164 & imm1) %(test)s 0) ? '
23910037SARM gem5 Developers                'purifyTaggedAddr(RawPC + imm2, xc->tcBase(), '
24010037SARM gem5 Developers                'currEL(xc->tcBase())) : NPC;\n')
24110037SARM gem5 Developers        code = code % {"test": test}
24210037SARM gem5 Developers        iop = InstObjParams(mnem, mnem.capitalize() + "64",
24310037SARM gem5 Developers                            "BranchImmImmReg64", code,
24410037SARM gem5 Developers                            ['IsCondControl', 'IsDirectControl'])
24510037SARM gem5 Developers        header_output += BranchImmImmReg64Declare.subst(iop)
24610037SARM gem5 Developers        decoder_output += BranchImmImmReg64Constructor.subst(iop)
24710037SARM gem5 Developers        exec_output += BasicExecute.subst(iop)
24810037SARM gem5 Developers}};
249