branch.isa revision 7151:672a20bbd4ff
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010 ARM Limited
4// All rights reserved
5//
6// The license below extends only to copyright in the software and shall
7// not be construed as granting a license to any other intellectual
8// property including but not limited to intellectual property relating
9// to a hardware implementation of the functionality of the software
10// licensed hereunder.  You may use the software subject to the license
11// terms below provided that you ensure that this notice is replicated
12// unmodified and in its entirety in all distributions of the software,
13// modified or unmodified, in source code or in binary form.
14//
15// Redistribution and use in source and binary forms, with or without
16// modification, are permitted provided that the following conditions are
17// met: redistributions of source code must retain the above copyright
18// notice, this list of conditions and the following disclaimer;
19// redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution;
22// neither the name of the copyright holders nor the names of its
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Authors: Gabe Black
39
40let {{
41
42    header_output = ""
43    decoder_output = ""
44    exec_output = ""
45
46    # B, BL
47    for (mnem, link) in (("b", False), ("bl", True)):
48        bCode = '''
49        Addr PC = readPC(xc);
50        NPC = ((PC + imm) & mask(32)) | (PC & ~mask(32));
51        '''
52        if (link):
53            bCode += '''
54                Addr tBit = PC & (ULL(1) << PcTBitShift);
55                if (!tBit)
56                    LR = PC - 4;
57                else
58                    LR = PC | 1;
59            '''
60
61        bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
62                             {"code": bCode,
63                              "predicate_test": predicateTest})
64        header_output += BranchImmCondDeclare.subst(bIop)
65        decoder_output += BranchImmCondConstructor.subst(bIop)
66        exec_output += PredOpExecute.subst(bIop)
67
68    # BX, BLX
69    blxCode = '''
70    Addr PC = readPC(xc);
71    Addr tBit = PC & (ULL(1) << PcTBitShift);
72    // Other than the assert below, jBit isn't used.
73#if !defined(NDEBUG)
74    Addr jBit = PC & (ULL(1) << PcJBitShift);
75#endif
76    // X isn't permitted in ThumbEE mode. We shouldn't be in jazzelle mode?
77    assert(!jBit);
78    bool arm = !tBit;
79    arm = arm; // In case it's not used otherwise.
80    Addr tempPc = ((%(newPC)s) & mask(32)) | (PC & ~mask(32));
81    %(link)s
82    // Switch modes
83    %(branch)s
84    '''
85
86    blxList = (("blx", True, True),
87               ("blx", False, True),
88               ("bx", False, False))
89
90    for (mnem, imm, link) in blxList:
91        Name = mnem.capitalize()
92        if imm and link: #blx with imm
93            branchStr = "FNPC = tempPc ^ (ULL(1) << PcTBitShift);"
94        else:
95            branchStr = "IWNPC = tempPc ^ (ULL(1) << PcTBitShift);"
96
97        if imm:
98            Name += "Imm"
99            # Since we're switching ISAs, the target ISA will be the opposite
100            # of the current ISA. !arm is whether the target is ARM.
101            newPC = '(!arm ? (roundDown(PC, 4) + imm) : (PC + imm))'
102            base = "BranchImm"
103            declare = BranchImmDeclare
104            constructor = BranchImmConstructor
105        else:
106            Name += "Reg"
107            newPC = '(PC & PcModeMask) | Op1'
108            base = "BranchRegCond"
109            declare = BranchRegCondDeclare
110            constructor = BranchRegCondConstructor
111        if link and imm:
112            linkStr = '''
113                // The immediate version of the blx thumb instruction
114                // is 32 bits wide, but "next pc" doesn't reflect that
115                // so we don't want to substract 2 from it at this point
116                if (arm)
117                    LR = PC - 4;
118                else
119                    LR = PC  | 1;
120            '''
121        elif link:
122            linkStr = '''
123                if (arm)
124                    LR = PC - 4;
125                else
126                    LR = (PC - 2) | 1;
127            '''
128        else:
129            linkStr = ""
130        code = blxCode % {"link": linkStr,
131                          "newPC": newPC,
132                          "branch": branchStr}
133        blxIop = InstObjParams(mnem, Name, base,
134                               {"code": code,
135                                "predicate_test": predicateTest})
136        header_output += declare.subst(blxIop)
137        decoder_output += constructor.subst(blxIop)
138        exec_output += PredOpExecute.subst(blxIop)
139
140    #Ignore BXJ for now
141
142    #CBNZ, CBZ. These are always unconditional as far as predicates
143    for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
144        code = '''
145        Addr PC = readPC(xc);
146        NPC = ((PC + imm) & mask(32)) | (PC & ~mask(32));
147        '''
148        predTest = "Op1 %(test)s 0" % {"test": test}
149        iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
150                            {"code": code, "predicate_test": predTest})
151        header_output += BranchImmRegDeclare.subst(iop)
152        decoder_output += BranchImmRegConstructor.subst(iop)
153        exec_output += PredOpExecute.subst(iop)
154
155    #TBB, TBH
156    for isTbh in (0, 1):
157        if isTbh:
158            eaCode = "EA = Op1 + Op2 * 2"
159            accCode = "NPC = readPC(xc) + 2 * (Mem.uh);"
160            mnem = "tbh"
161        else:
162            eaCode = "EA = Op1 + Op2"
163            accCode = "NPC = readPC(xc) + 2 * (Mem.ub);"
164            mnem = "tbb"
165        eaCode = "unsigned memAccessFlags = 0;\n" + eaCode
166        iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
167                            {'ea_code': eaCode,
168                             'memacc_code': accCode,
169                             'predicate_test': predicateTest})
170        header_output += BranchTableDeclare.subst(iop)
171        decoder_output += BranchRegRegConstructor.subst(iop)
172        exec_output += LoadExecute.subst(iop) + \
173                       LoadInitiateAcc.subst(iop) + \
174                       LoadCompleteAcc.subst(iop)
175}};
176