branch.isa revision 7294:fda2c00880db
112787Sgabeblack@google.com// -*- mode:c++ -*-
212787Sgabeblack@google.com
312787Sgabeblack@google.com// Copyright (c) 2010 ARM Limited
412787Sgabeblack@google.com// All rights reserved
512787Sgabeblack@google.com//
612787Sgabeblack@google.com// The license below extends only to copyright in the software and shall
712787Sgabeblack@google.com// not be construed as granting a license to any other intellectual
812787Sgabeblack@google.com// property including but not limited to intellectual property relating
912787Sgabeblack@google.com// to a hardware implementation of the functionality of the software
1012787Sgabeblack@google.com// licensed hereunder.  You may use the software subject to the license
1112787Sgabeblack@google.com// terms below provided that you ensure that this notice is replicated
1212787Sgabeblack@google.com// unmodified and in its entirety in all distributions of the software,
1312787Sgabeblack@google.com// modified or unmodified, in source code or in binary form.
1412787Sgabeblack@google.com//
1512787Sgabeblack@google.com// Redistribution and use in source and binary forms, with or without
1612787Sgabeblack@google.com// modification, are permitted provided that the following conditions are
1712787Sgabeblack@google.com// met: redistributions of source code must retain the above copyright
1812787Sgabeblack@google.com// notice, this list of conditions and the following disclaimer;
1912787Sgabeblack@google.com// redistributions in binary form must reproduce the above copyright
2012787Sgabeblack@google.com// notice, this list of conditions and the following disclaimer in the
2112787Sgabeblack@google.com// documentation and/or other materials provided with the distribution;
2212787Sgabeblack@google.com// neither the name of the copyright holders nor the names of its
2312787Sgabeblack@google.com// contributors may be used to endorse or promote products derived from
2412787Sgabeblack@google.com// this software without specific prior written permission.
2512787Sgabeblack@google.com//
2612787Sgabeblack@google.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2712787Sgabeblack@google.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2812787Sgabeblack@google.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2912787Sgabeblack@google.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3012787Sgabeblack@google.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3112787Sgabeblack@google.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3212787Sgabeblack@google.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3312787Sgabeblack@google.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3412787Sgabeblack@google.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3512787Sgabeblack@google.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3612787Sgabeblack@google.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3712787Sgabeblack@google.com//
3812787Sgabeblack@google.com// Authors: Gabe Black
3912787Sgabeblack@google.com
4012787Sgabeblack@google.comlet {{
4112787Sgabeblack@google.com
4212787Sgabeblack@google.com    header_output = ""
4312787Sgabeblack@google.com    decoder_output = ""
4412787Sgabeblack@google.com    exec_output = ""
4512787Sgabeblack@google.com
4612787Sgabeblack@google.com    # B, BL
4712787Sgabeblack@google.com    for (mnem, link) in (("b", False), ("bl", True)):
4812787Sgabeblack@google.com        bCode = '''
4912787Sgabeblack@google.com        Addr PC = readPC(xc);
5012787Sgabeblack@google.com        NPC = ((PC + imm) & mask(32)) | (PC & ~mask(32));
5112787Sgabeblack@google.com        '''
5212787Sgabeblack@google.com        if (link):
5312787Sgabeblack@google.com            bCode += '''
5412787Sgabeblack@google.com                Addr tBit = PC & (ULL(1) << PcTBitShift);
5512787Sgabeblack@google.com                if (!tBit)
5612787Sgabeblack@google.com                    LR = PC - 4;
5712787Sgabeblack@google.com                else
5812787Sgabeblack@google.com                    LR = PC | 1;
5912787Sgabeblack@google.com            '''
6012787Sgabeblack@google.com
6112787Sgabeblack@google.com        bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
6212787Sgabeblack@google.com                             {"code": bCode,
6312787Sgabeblack@google.com                              "predicate_test": predicateTest})
6412787Sgabeblack@google.com        header_output += BranchImmCondDeclare.subst(bIop)
6512787Sgabeblack@google.com        decoder_output += BranchImmCondConstructor.subst(bIop)
6612787Sgabeblack@google.com        exec_output += PredOpExecute.subst(bIop)
6712787Sgabeblack@google.com
6812787Sgabeblack@google.com    # BX, BLX
6912787Sgabeblack@google.com    blxCode = '''
7012787Sgabeblack@google.com    Addr PC = readPC(xc);
7112787Sgabeblack@google.com    Addr tBit = PC & (ULL(1) << PcTBitShift);
7212787Sgabeblack@google.com    bool arm = !tBit;
7312787Sgabeblack@google.com    arm = arm; // In case it's not used otherwise.
7412787Sgabeblack@google.com    %(link)s
7512787Sgabeblack@google.com    // Switch modes
7612787Sgabeblack@google.com    %(branch)s
7712787Sgabeblack@google.com    '''
7812787Sgabeblack@google.com
7912787Sgabeblack@google.com    blxList = (("blx", True, True),
8012787Sgabeblack@google.com               ("blx", False, True),
8112787Sgabeblack@google.com               ("bx", False, False))
8212787Sgabeblack@google.com
8312787Sgabeblack@google.com    for (mnem, imm, link) in blxList:
8412787Sgabeblack@google.com        Name = mnem.capitalize()
8512787Sgabeblack@google.com        if imm:
8612787Sgabeblack@google.com            Name += "Imm"
8712787Sgabeblack@google.com            # Since we're switching ISAs, the target ISA will be the opposite
8812787Sgabeblack@google.com            # of the current ISA. !arm is whether the target is ARM.
8912787Sgabeblack@google.com            newPC = '(!arm ? (roundDown(PC, 4) + imm) : (PC + imm))'
9012787Sgabeblack@google.com            base = "BranchImm"
9112787Sgabeblack@google.com            declare = BranchImmDeclare
9212787Sgabeblack@google.com            constructor = BranchImmConstructor
9312787Sgabeblack@google.com        else:
9412787Sgabeblack@google.com            Name += "Reg"
9512787Sgabeblack@google.com            newPC = 'Op1'
9612787Sgabeblack@google.com            base = "BranchRegCond"
9712787Sgabeblack@google.com            declare = BranchRegCondDeclare
9812787Sgabeblack@google.com            constructor = BranchRegCondConstructor
9912787Sgabeblack@google.com        if link and imm:
10012787Sgabeblack@google.com            linkStr = '''
10112787Sgabeblack@google.com                // The immediate version of the blx thumb instruction
10212787Sgabeblack@google.com                // is 32 bits wide, but "next pc" doesn't reflect that
10312787Sgabeblack@google.com                // so we don't want to substract 2 from it at this point
10412787Sgabeblack@google.com                if (arm)
10512787Sgabeblack@google.com                    LR = PC - 4;
10612787Sgabeblack@google.com                else
10712787Sgabeblack@google.com                    LR = PC  | 1;
10812787Sgabeblack@google.com            '''
10912787Sgabeblack@google.com        elif link:
11012787Sgabeblack@google.com            linkStr = '''
11112787Sgabeblack@google.com                if (arm)
11212787Sgabeblack@google.com                    LR = PC - 4;
11312787Sgabeblack@google.com                else
11412787Sgabeblack@google.com                    LR = (PC - 2) | 1;
11512787Sgabeblack@google.com            '''
11612787Sgabeblack@google.com        else:
11712787Sgabeblack@google.com            linkStr = ""
11812787Sgabeblack@google.com
11912787Sgabeblack@google.com        if imm and link: #blx with imm
12012787Sgabeblack@google.com            branchStr = '''
12112787Sgabeblack@google.com                Addr tempPc = ((%(newPC)s) & mask(32)) | (PC & ~mask(32));
12212787Sgabeblack@google.com                FNPC = tempPc ^ (ULL(1) << PcTBitShift);
12312787Sgabeblack@google.com            '''
12412787Sgabeblack@google.com        else:
12512787Sgabeblack@google.com            branchStr = "IWNPC = %(newPC)s;"
12612787Sgabeblack@google.com        branchStr = branchStr % { "newPC" : newPC }
12712787Sgabeblack@google.com
12812787Sgabeblack@google.com        code = blxCode % {"link": linkStr,
12912787Sgabeblack@google.com                          "newPC": newPC,
13012787Sgabeblack@google.com                          "branch": branchStr}
13112787Sgabeblack@google.com        blxIop = InstObjParams(mnem, Name, base,
13212787Sgabeblack@google.com                               {"code": code,
13312787Sgabeblack@google.com                                "predicate_test": predicateTest})
13412787Sgabeblack@google.com        header_output += declare.subst(blxIop)
13512787Sgabeblack@google.com        decoder_output += constructor.subst(blxIop)
13612787Sgabeblack@google.com        exec_output += PredOpExecute.subst(blxIop)
13712787Sgabeblack@google.com
13812787Sgabeblack@google.com    #Ignore BXJ for now
13912787Sgabeblack@google.com
14012787Sgabeblack@google.com    #CBNZ, CBZ. These are always unconditional as far as predicates
14112787Sgabeblack@google.com    for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
14212787Sgabeblack@google.com        code = '''
14312787Sgabeblack@google.com        Addr PC = readPC(xc);
14412787Sgabeblack@google.com        NPC = ((PC + imm) & mask(32)) | (PC & ~mask(32));
14512787Sgabeblack@google.com        '''
14612787Sgabeblack@google.com        predTest = "Op1 %(test)s 0" % {"test": test}
14712787Sgabeblack@google.com        iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
14812787Sgabeblack@google.com                            {"code": code, "predicate_test": predTest})
149        header_output += BranchImmRegDeclare.subst(iop)
150        decoder_output += BranchImmRegConstructor.subst(iop)
151        exec_output += PredOpExecute.subst(iop)
152
153    #TBB, TBH
154    for isTbh in (0, 1):
155        if isTbh:
156            eaCode = '''
157            unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
158                                      ArmISA::TLB::AlignHalfWord |
159                                      ArmISA::TLB::MustBeOne;
160            EA = Op1 + Op2 * 2
161            '''
162            accCode = "NPC = readPC(xc) + 2 * (Mem.uh);"
163            mnem = "tbh"
164        else:
165            eaCode = '''
166            unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
167                                      ArmISA::TLB::AlignByte |
168                                      ArmISA::TLB::MustBeOne;
169            EA = Op1 + Op2
170            '''
171            accCode = "NPC = readPC(xc) + 2 * (Mem.ub);"
172            mnem = "tbb"
173        iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
174                            {'ea_code': eaCode,
175                             'memacc_code': accCode,
176                             'predicate_test': predicateTest})
177        header_output += BranchTableDeclare.subst(iop)
178        decoder_output += BranchRegRegConstructor.subst(iop)
179        exec_output += LoadExecute.subst(iop) + \
180                       LoadInitiateAcc.subst(iop) + \
181                       LoadCompleteAcc.subst(iop)
182}};
183