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