branch.isa revision 7720:65d338a8dba4
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        ArmISA::PCState pc = PCS;
50        Addr curPc = pc.instPC();
51        pc.instNPC((uint32_t)(curPc + imm));
52        PCS = pc;
53        '''
54        if (link):
55            bCode += '''
56                if (pc.thumb())
57                    LR = curPc | 1;
58                else
59                    LR = curPc - 4;
60            '''
61
62        bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
63                             {"code": bCode,
64                              "predicate_test": predicateTest})
65        header_output += BranchImmCondDeclare.subst(bIop)
66        decoder_output += BranchImmCondConstructor.subst(bIop)
67        exec_output += PredOpExecute.subst(bIop)
68
69    # BX, BLX
70    blxCode = '''
71    ArmISA::PCState pc = PCS;
72    Addr curPc M5_VAR_USED = pc.instPC();
73    %(link)s
74    // Switch modes
75    %(branch)s
76    PCS = pc;
77    '''
78
79    blxList = (("blx", True, True),
80               ("blx", False, True),
81               ("bx", False, False))
82
83    for (mnem, imm, link) in blxList:
84        Name = mnem.capitalize()
85        if imm:
86            Name += "Imm"
87            # Since we're switching ISAs, the target ISA will be the opposite
88            # of the current ISA. pc.thumb() is whether the target is ARM.
89            newPC = '(pc.thumb() ? (roundDown(curPc, 4) + imm) : (curPc + imm))'
90            base = "BranchImmCond"
91            declare = BranchImmCondDeclare
92            constructor = BranchImmCondConstructor
93        else:
94            Name += "Reg"
95            newPC = 'Op1'
96            base = "BranchRegCond"
97            declare = BranchRegCondDeclare
98            constructor = BranchRegCondConstructor
99        if link and imm:
100            linkStr = '''
101                // The immediate version of the blx thumb instruction
102                // is 32 bits wide, but "next pc" doesn't reflect that
103                // so we don't want to substract 2 from it at this point
104                if (pc.thumb())
105                    LR = curPc  | 1;
106                else
107                    LR = curPc - 4;
108            '''
109        elif link:
110            linkStr = '''
111                if (pc.thumb())
112                    LR = (curPc - 2) | 1;
113                else
114                    LR = curPc - 4;
115            '''
116        else:
117            linkStr = ""
118
119        if imm and link: #blx with imm
120            branchStr = '''
121                pc.nextThumb(!pc.thumb());
122                pc.instNPC(%(newPC)s);
123            '''
124        else:
125            branchStr = "pc.instIWNPC(%(newPC)s);"
126        branchStr = branchStr % { "newPC" : newPC }
127
128        code = blxCode % {"link": linkStr,
129                          "newPC": newPC,
130                          "branch": branchStr}
131        blxIop = InstObjParams(mnem, Name, base,
132                               {"code": code,
133                                "predicate_test": predicateTest})
134        header_output += declare.subst(blxIop)
135        decoder_output += constructor.subst(blxIop)
136        exec_output += PredOpExecute.subst(blxIop)
137
138    #Ignore BXJ for now
139
140    #CBNZ, CBZ. These are always unconditional as far as predicates
141    for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
142        code = '''
143        ArmISA::PCState pc = PCS;
144        Addr curPc = pc.instPC();
145        pc.instNPC((uint32_t)(curPc + imm));
146        PCS = pc;
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 = '''
159            unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
160                                      ArmISA::TLB::AlignHalfWord |
161                                      ArmISA::TLB::MustBeOne;
162            EA = Op1 + Op2 * 2
163            '''
164            accCode = '''
165            ArmISA::PCState pc = PCS;
166            pc.instNPC(pc.instPC() + 2 * (Mem.uh));
167            PCS = pc;
168            '''
169            mnem = "tbh"
170        else:
171            eaCode = '''
172            unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
173                                      ArmISA::TLB::AlignByte |
174                                      ArmISA::TLB::MustBeOne;
175            EA = Op1 + Op2
176            '''
177            accCode = '''
178            ArmISA::PCState pc = PCS;
179            pc.instNPC(pc.instPC() + 2 * (Mem.ub));
180            PCS = pc;
181            '''
182            mnem = "tbb"
183        iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
184                            {'ea_code': eaCode,
185                             'memacc_code': accCode,
186                             'predicate_test': predicateTest})
187        header_output += BranchTableDeclare.subst(iop)
188        decoder_output += BranchRegRegConstructor.subst(iop)
189        exec_output += LoadExecute.subst(iop) + \
190                       LoadInitiateAcc.subst(iop) + \
191                       LoadCompleteAcc.subst(iop)
192}};
193