17151Sgblack@eecs.umich.edu// -*- mode:c++ -*-
27151Sgblack@eecs.umich.edu
310334Smitch.hayenga@arm.com// Copyright (c) 2010-2012, 2014 ARM Limited
47151Sgblack@eecs.umich.edu// All rights reserved
57151Sgblack@eecs.umich.edu//
67151Sgblack@eecs.umich.edu// The license below extends only to copyright in the software and shall
77151Sgblack@eecs.umich.edu// not be construed as granting a license to any other intellectual
87151Sgblack@eecs.umich.edu// property including but not limited to intellectual property relating
97151Sgblack@eecs.umich.edu// to a hardware implementation of the functionality of the software
107151Sgblack@eecs.umich.edu// licensed hereunder.  You may use the software subject to the license
117151Sgblack@eecs.umich.edu// terms below provided that you ensure that this notice is replicated
127151Sgblack@eecs.umich.edu// unmodified and in its entirety in all distributions of the software,
137151Sgblack@eecs.umich.edu// modified or unmodified, in source code or in binary form.
147151Sgblack@eecs.umich.edu//
157151Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
167151Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
177151Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright
187151Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
197151Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
207151Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
217151Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
227151Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its
237151Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
247151Sgblack@eecs.umich.edu// this software without specific prior written permission.
257151Sgblack@eecs.umich.edu//
267151Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
277151Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
287151Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
297151Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
307151Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
317151Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
327151Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
337151Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
347151Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
357151Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
367151Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
377151Sgblack@eecs.umich.edu//
387151Sgblack@eecs.umich.edu// Authors: Gabe Black
397151Sgblack@eecs.umich.edu
407151Sgblack@eecs.umich.edulet {{
417151Sgblack@eecs.umich.edu
427151Sgblack@eecs.umich.edu    header_output = ""
437151Sgblack@eecs.umich.edu    decoder_output = ""
447151Sgblack@eecs.umich.edu    exec_output = ""
457151Sgblack@eecs.umich.edu
467151Sgblack@eecs.umich.edu    # B, BL
477151Sgblack@eecs.umich.edu    for (mnem, link) in (("b", False), ("bl", True)):
487151Sgblack@eecs.umich.edu        bCode = '''
497797Sgblack@eecs.umich.edu        NPC = (uint32_t)(PC + imm);
507151Sgblack@eecs.umich.edu        '''
5110037SARM gem5 Developers        br_tgt_code = '''pcs.instNPC((uint32_t)(branchPC.instPC() + imm));'''
528146SAli.Saidi@ARM.com        instFlags = ["IsDirectControl"]
537151Sgblack@eecs.umich.edu        if (link):
547151Sgblack@eecs.umich.edu            bCode += '''
557797Sgblack@eecs.umich.edu                if (Thumb)
567797Sgblack@eecs.umich.edu                    LR = PC | 1;
577720Sgblack@eecs.umich.edu                else
587797Sgblack@eecs.umich.edu                    LR = PC - 4;
597151Sgblack@eecs.umich.edu            '''
608146SAli.Saidi@ARM.com            instFlags += ["IsCall"]
618146SAli.Saidi@ARM.com
627151Sgblack@eecs.umich.edu
637151Sgblack@eecs.umich.edu        bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
648146SAli.Saidi@ARM.com                             {"code": bCode, "predicate_test": predicateTest,
658146SAli.Saidi@ARM.com                             "brTgtCode" : br_tgt_code}, instFlags)
667151Sgblack@eecs.umich.edu        header_output += BranchImmCondDeclare.subst(bIop)
678146SAli.Saidi@ARM.com        decoder_output += BranchImmCondConstructor.subst(bIop) + \
688146SAli.Saidi@ARM.com                       BranchTarget.subst(bIop)
697151Sgblack@eecs.umich.edu        exec_output += PredOpExecute.subst(bIop)
707151Sgblack@eecs.umich.edu
717151Sgblack@eecs.umich.edu    # BX, BLX
727151Sgblack@eecs.umich.edu    blxCode = '''
737151Sgblack@eecs.umich.edu    %(link)s
747151Sgblack@eecs.umich.edu    // Switch modes
757151Sgblack@eecs.umich.edu    %(branch)s
767151Sgblack@eecs.umich.edu    '''
777151Sgblack@eecs.umich.edu
787151Sgblack@eecs.umich.edu    blxList = (("blx", True, True),
797151Sgblack@eecs.umich.edu               ("blx", False, True),
807151Sgblack@eecs.umich.edu               ("bx", False, False))
817151Sgblack@eecs.umich.edu
827151Sgblack@eecs.umich.edu    for (mnem, imm, link) in blxList:
837151Sgblack@eecs.umich.edu        Name = mnem.capitalize()
848203SAli.Saidi@ARM.com        isRasPop = 0
857151Sgblack@eecs.umich.edu        if imm:
867151Sgblack@eecs.umich.edu            Name += "Imm"
877151Sgblack@eecs.umich.edu            # Since we're switching ISAs, the target ISA will be the opposite
887797Sgblack@eecs.umich.edu            # of the current ISA. Thumb is whether the target is ARM.
8910037SARM gem5 Developers            newPC = '(uint32_t)(Thumb ? (roundDown(PC, 4) + imm) : (PC + imm))'
908146SAli.Saidi@ARM.com            br_tgt_code = '''
9110037SARM gem5 Developers            pcs.instNPC((uint32_t)(branchPC.thumb() ? (roundDown(branchPC.instPC(),4) + imm) :
928146SAli.Saidi@ARM.com                                (branchPC.instPC() + imm)));
938146SAli.Saidi@ARM.com            '''
947602SGene.Wu@arm.com            base = "BranchImmCond"
957602SGene.Wu@arm.com            declare = BranchImmCondDeclare
967602SGene.Wu@arm.com            constructor = BranchImmCondConstructor
978146SAli.Saidi@ARM.com            instFlags = ["IsDirectControl"]
987151Sgblack@eecs.umich.edu        else:
997151Sgblack@eecs.umich.edu            Name += "Reg"
1007282Sgblack@eecs.umich.edu            newPC = 'Op1'
1018146SAli.Saidi@ARM.com            br_tgt_code = ''
1027151Sgblack@eecs.umich.edu            base = "BranchRegCond"
1037151Sgblack@eecs.umich.edu            declare = BranchRegCondDeclare
1047151Sgblack@eecs.umich.edu            constructor = BranchRegCondConstructor
1058146SAli.Saidi@ARM.com            instFlags = ["IsIndirectControl"]
1067151Sgblack@eecs.umich.edu        if link and imm:
1077151Sgblack@eecs.umich.edu            linkStr = '''
1087151Sgblack@eecs.umich.edu                // The immediate version of the blx thumb instruction
1097151Sgblack@eecs.umich.edu                // is 32 bits wide, but "next pc" doesn't reflect that
1107151Sgblack@eecs.umich.edu                // so we don't want to substract 2 from it at this point
1117797Sgblack@eecs.umich.edu                if (Thumb)
1127797Sgblack@eecs.umich.edu                    LR = PC  | 1;
1137720Sgblack@eecs.umich.edu                else
1147797Sgblack@eecs.umich.edu                    LR = PC - 4;
1157151Sgblack@eecs.umich.edu            '''
1168146SAli.Saidi@ARM.com            instFlags += ["IsCall"]
1177151Sgblack@eecs.umich.edu        elif link:
1187151Sgblack@eecs.umich.edu            linkStr = '''
1197797Sgblack@eecs.umich.edu                if (Thumb)
1207797Sgblack@eecs.umich.edu                    LR = (PC - 2) | 1;
1217720Sgblack@eecs.umich.edu                else
1227797Sgblack@eecs.umich.edu                    LR = PC - 4;
1237151Sgblack@eecs.umich.edu            '''
1248146SAli.Saidi@ARM.com            instFlags += ["IsCall"]
1257151Sgblack@eecs.umich.edu        else:
1267151Sgblack@eecs.umich.edu            linkStr = ""
1278203SAli.Saidi@ARM.com            isRasPop = "op1 == INTREG_LR"
1287282Sgblack@eecs.umich.edu
1297282Sgblack@eecs.umich.edu        if imm and link: #blx with imm
1307282Sgblack@eecs.umich.edu            branchStr = '''
1317797Sgblack@eecs.umich.edu                NextThumb = !Thumb;
1327797Sgblack@eecs.umich.edu                NPC = %(newPC)s;
1337282Sgblack@eecs.umich.edu            '''
1348146SAli.Saidi@ARM.com            br_tgt_code = '''pcs.nextThumb(!branchPC.thumb());\n''' + \
1358146SAli.Saidi@ARM.com                          br_tgt_code
1367282Sgblack@eecs.umich.edu        else:
1377797Sgblack@eecs.umich.edu            branchStr = "IWNPC = %(newPC)s;"
1387282Sgblack@eecs.umich.edu        branchStr = branchStr % { "newPC" : newPC }
1397282Sgblack@eecs.umich.edu
1407151Sgblack@eecs.umich.edu        code = blxCode % {"link": linkStr,
1417151Sgblack@eecs.umich.edu                          "newPC": newPC,
1427151Sgblack@eecs.umich.edu                          "branch": branchStr}
1437151Sgblack@eecs.umich.edu        blxIop = InstObjParams(mnem, Name, base,
1448146SAli.Saidi@ARM.com                               {"code": code, "brTgtCode" : br_tgt_code,
1458203SAli.Saidi@ARM.com                                "predicate_test": predicateTest,
1468203SAli.Saidi@ARM.com                                "is_ras_pop" : isRasPop }, instFlags)
1477151Sgblack@eecs.umich.edu        header_output += declare.subst(blxIop)
1487151Sgblack@eecs.umich.edu        decoder_output += constructor.subst(blxIop)
1497151Sgblack@eecs.umich.edu        exec_output += PredOpExecute.subst(blxIop)
1508146SAli.Saidi@ARM.com        if imm:
1518146SAli.Saidi@ARM.com            decoder_output += BranchTarget.subst(blxIop)
1527151Sgblack@eecs.umich.edu
15310037SARM gem5 Developers    bxjcode = '''
15410037SARM gem5 Developers    HSTR hstr = Hstr;
15510037SARM gem5 Developers    CPSR cpsr = Cpsr;
15610037SARM gem5 Developers    SCR  scr  = Scr;
15710037SARM gem5 Developers
15810037SARM gem5 Developers    if (ArmSystem::haveVirtualization(xc->tcBase()) && hstr.tjdbx &&
15910037SARM gem5 Developers        !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
16010474Sandreas.hansson@arm.com        fault = std::make_shared<HypervisorTrap>(machInst, op1, EC_TRAPPED_BXJ);
16110037SARM gem5 Developers    }
16210037SARM gem5 Developers    IWNPC = Op1;
16310037SARM gem5 Developers    '''
16410037SARM gem5 Developers
16510037SARM gem5 Developers    bxjIop = InstObjParams("bxj", "BxjReg", "BranchRegCond",
16610037SARM gem5 Developers                           {"code": bxjcode,
16710037SARM gem5 Developers                            "predicate_test": predicateTest,
16810037SARM gem5 Developers                            "is_ras_pop": "op1 == INTREG_LR" },
16910037SARM gem5 Developers                           ["IsIndirectControl"])
17010037SARM gem5 Developers    header_output += BranchRegCondDeclare.subst(bxjIop)
17110037SARM gem5 Developers    decoder_output += BranchRegCondConstructor.subst(bxjIop)
17210037SARM gem5 Developers    exec_output += PredOpExecute.subst(bxjIop)
1737151Sgblack@eecs.umich.edu
1747151Sgblack@eecs.umich.edu    #CBNZ, CBZ. These are always unconditional as far as predicates
1757151Sgblack@eecs.umich.edu    for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
1767797Sgblack@eecs.umich.edu        code = 'NPC = (uint32_t)(PC + imm);\n'
17710334Smitch.hayenga@arm.com        br_tgt_code = '''pcs.instNPC((uint32_t)(branchPC.instPC() + imm));'''
1787151Sgblack@eecs.umich.edu        predTest = "Op1 %(test)s 0" % {"test": test}
1797151Sgblack@eecs.umich.edu        iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
18010334Smitch.hayenga@arm.com                            {"code": code, "predicate_test": predTest,
18110334Smitch.hayenga@arm.com                            "brTgtCode" : br_tgt_code},
18210334Smitch.hayenga@arm.com                            ["IsDirectControl"])
1837151Sgblack@eecs.umich.edu        header_output += BranchImmRegDeclare.subst(iop)
18410334Smitch.hayenga@arm.com        decoder_output += BranchImmRegConstructor.subst(iop) + \
18510334Smitch.hayenga@arm.com                          BranchTarget.subst(iop)
1867151Sgblack@eecs.umich.edu        exec_output += PredOpExecute.subst(iop)
1877151Sgblack@eecs.umich.edu
1887151Sgblack@eecs.umich.edu    #TBB, TBH
1897151Sgblack@eecs.umich.edu    for isTbh in (0, 1):
1907151Sgblack@eecs.umich.edu        if isTbh:
1917294Sgblack@eecs.umich.edu            eaCode = '''
1927294Sgblack@eecs.umich.edu            unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
1937294Sgblack@eecs.umich.edu                                      ArmISA::TLB::AlignHalfWord |
1947294Sgblack@eecs.umich.edu                                      ArmISA::TLB::MustBeOne;
1957294Sgblack@eecs.umich.edu            EA = Op1 + Op2 * 2
1967294Sgblack@eecs.umich.edu            '''
1978588Sgblack@eecs.umich.edu            accCode = 'NPC = PC + 2 * (Mem_uh);\n'
1987151Sgblack@eecs.umich.edu            mnem = "tbh"
1997151Sgblack@eecs.umich.edu        else:
2007294Sgblack@eecs.umich.edu            eaCode = '''
2017294Sgblack@eecs.umich.edu            unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
2027294Sgblack@eecs.umich.edu                                      ArmISA::TLB::AlignByte |
2037294Sgblack@eecs.umich.edu                                      ArmISA::TLB::MustBeOne;
2047294Sgblack@eecs.umich.edu            EA = Op1 + Op2
2057294Sgblack@eecs.umich.edu            '''
2068588Sgblack@eecs.umich.edu            accCode = 'NPC = PC + 2 * (Mem_ub)'
2077151Sgblack@eecs.umich.edu            mnem = "tbb"
2087151Sgblack@eecs.umich.edu        iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
2097151Sgblack@eecs.umich.edu                            {'ea_code': eaCode,
2107151Sgblack@eecs.umich.edu                             'memacc_code': accCode,
2118146SAli.Saidi@ARM.com                             'predicate_test': predicateTest},
2128146SAli.Saidi@ARM.com                             ["IsIndirectControl"])
2137151Sgblack@eecs.umich.edu        header_output += BranchTableDeclare.subst(iop)
2147151Sgblack@eecs.umich.edu        decoder_output += BranchRegRegConstructor.subst(iop)
2157151Sgblack@eecs.umich.edu        exec_output += LoadExecute.subst(iop) + \
2167151Sgblack@eecs.umich.edu                       LoadInitiateAcc.subst(iop) + \
2177151Sgblack@eecs.umich.edu                       LoadCompleteAcc.subst(iop)
2187151Sgblack@eecs.umich.edu}};
219