branch.isa (8588:ef28ed90449d) branch.isa (10037:5cac77888310)
1// -*- mode:c++ -*-
2
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010 ARM Limited
3// Copyright (c) 2010-2012 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 '''
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 br_tgt_code = '''pcs.instNPC(branchPC.instPC() + imm);'''
51 br_tgt_code = '''pcs.instNPC((uint32_t)(branchPC.instPC() + imm));'''
52 instFlags = ["IsDirectControl"]
53 if (link):
54 bCode += '''
55 if (Thumb)
56 LR = PC | 1;
57 else
58 LR = PC - 4;
59 '''
60 instFlags += ["IsCall"]
61
62
63 bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
64 {"code": bCode, "predicate_test": predicateTest,
65 "brTgtCode" : br_tgt_code}, instFlags)
66 header_output += BranchImmCondDeclare.subst(bIop)
67 decoder_output += BranchImmCondConstructor.subst(bIop) + \
68 BranchTarget.subst(bIop)
69 exec_output += PredOpExecute.subst(bIop)
70
71 # BX, BLX
72 blxCode = '''
73 %(link)s
74 // Switch modes
75 %(branch)s
76 '''
77
78 blxList = (("blx", True, True),
79 ("blx", False, True),
80 ("bx", False, False))
81
82 for (mnem, imm, link) in blxList:
83 Name = mnem.capitalize()
84 isRasPop = 0
85 if imm:
86 Name += "Imm"
87 # Since we're switching ISAs, the target ISA will be the opposite
88 # of the current ISA. Thumb is whether the target is ARM.
52 instFlags = ["IsDirectControl"]
53 if (link):
54 bCode += '''
55 if (Thumb)
56 LR = PC | 1;
57 else
58 LR = PC - 4;
59 '''
60 instFlags += ["IsCall"]
61
62
63 bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
64 {"code": bCode, "predicate_test": predicateTest,
65 "brTgtCode" : br_tgt_code}, instFlags)
66 header_output += BranchImmCondDeclare.subst(bIop)
67 decoder_output += BranchImmCondConstructor.subst(bIop) + \
68 BranchTarget.subst(bIop)
69 exec_output += PredOpExecute.subst(bIop)
70
71 # BX, BLX
72 blxCode = '''
73 %(link)s
74 // Switch modes
75 %(branch)s
76 '''
77
78 blxList = (("blx", True, True),
79 ("blx", False, True),
80 ("bx", False, False))
81
82 for (mnem, imm, link) in blxList:
83 Name = mnem.capitalize()
84 isRasPop = 0
85 if imm:
86 Name += "Imm"
87 # Since we're switching ISAs, the target ISA will be the opposite
88 # of the current ISA. Thumb is whether the target is ARM.
89 newPC = '(Thumb ? (roundDown(PC, 4) + imm) : (PC + imm))'
89 newPC = '(uint32_t)(Thumb ? (roundDown(PC, 4) + imm) : (PC + imm))'
90 br_tgt_code = '''
90 br_tgt_code = '''
91 pcs.instNPC((branchPC.thumb() ? (roundDown(branchPC.instPC(),4) + imm) :
91 pcs.instNPC((uint32_t)(branchPC.thumb() ? (roundDown(branchPC.instPC(),4) + imm) :
92 (branchPC.instPC() + imm)));
93 '''
94 base = "BranchImmCond"
95 declare = BranchImmCondDeclare
96 constructor = BranchImmCondConstructor
97 instFlags = ["IsDirectControl"]
98 else:
99 Name += "Reg"
100 newPC = 'Op1'
101 br_tgt_code = ''
102 base = "BranchRegCond"
103 declare = BranchRegCondDeclare
104 constructor = BranchRegCondConstructor
105 instFlags = ["IsIndirectControl"]
106 if link and imm:
107 linkStr = '''
108 // The immediate version of the blx thumb instruction
109 // is 32 bits wide, but "next pc" doesn't reflect that
110 // so we don't want to substract 2 from it at this point
111 if (Thumb)
112 LR = PC | 1;
113 else
114 LR = PC - 4;
115 '''
116 instFlags += ["IsCall"]
117 elif link:
118 linkStr = '''
119 if (Thumb)
120 LR = (PC - 2) | 1;
121 else
122 LR = PC - 4;
123 '''
124 instFlags += ["IsCall"]
125 else:
126 linkStr = ""
127 isRasPop = "op1 == INTREG_LR"
128
129 if imm and link: #blx with imm
130 branchStr = '''
131 NextThumb = !Thumb;
132 NPC = %(newPC)s;
133 '''
134 br_tgt_code = '''pcs.nextThumb(!branchPC.thumb());\n''' + \
135 br_tgt_code
136 else:
137 branchStr = "IWNPC = %(newPC)s;"
138 branchStr = branchStr % { "newPC" : newPC }
139
140 code = blxCode % {"link": linkStr,
141 "newPC": newPC,
142 "branch": branchStr}
143 blxIop = InstObjParams(mnem, Name, base,
144 {"code": code, "brTgtCode" : br_tgt_code,
145 "predicate_test": predicateTest,
146 "is_ras_pop" : isRasPop }, instFlags)
147 header_output += declare.subst(blxIop)
148 decoder_output += constructor.subst(blxIop)
149 exec_output += PredOpExecute.subst(blxIop)
150 if imm:
151 decoder_output += BranchTarget.subst(blxIop)
152
92 (branchPC.instPC() + imm)));
93 '''
94 base = "BranchImmCond"
95 declare = BranchImmCondDeclare
96 constructor = BranchImmCondConstructor
97 instFlags = ["IsDirectControl"]
98 else:
99 Name += "Reg"
100 newPC = 'Op1'
101 br_tgt_code = ''
102 base = "BranchRegCond"
103 declare = BranchRegCondDeclare
104 constructor = BranchRegCondConstructor
105 instFlags = ["IsIndirectControl"]
106 if link and imm:
107 linkStr = '''
108 // The immediate version of the blx thumb instruction
109 // is 32 bits wide, but "next pc" doesn't reflect that
110 // so we don't want to substract 2 from it at this point
111 if (Thumb)
112 LR = PC | 1;
113 else
114 LR = PC - 4;
115 '''
116 instFlags += ["IsCall"]
117 elif link:
118 linkStr = '''
119 if (Thumb)
120 LR = (PC - 2) | 1;
121 else
122 LR = PC - 4;
123 '''
124 instFlags += ["IsCall"]
125 else:
126 linkStr = ""
127 isRasPop = "op1 == INTREG_LR"
128
129 if imm and link: #blx with imm
130 branchStr = '''
131 NextThumb = !Thumb;
132 NPC = %(newPC)s;
133 '''
134 br_tgt_code = '''pcs.nextThumb(!branchPC.thumb());\n''' + \
135 br_tgt_code
136 else:
137 branchStr = "IWNPC = %(newPC)s;"
138 branchStr = branchStr % { "newPC" : newPC }
139
140 code = blxCode % {"link": linkStr,
141 "newPC": newPC,
142 "branch": branchStr}
143 blxIop = InstObjParams(mnem, Name, base,
144 {"code": code, "brTgtCode" : br_tgt_code,
145 "predicate_test": predicateTest,
146 "is_ras_pop" : isRasPop }, instFlags)
147 header_output += declare.subst(blxIop)
148 decoder_output += constructor.subst(blxIop)
149 exec_output += PredOpExecute.subst(blxIop)
150 if imm:
151 decoder_output += BranchTarget.subst(blxIop)
152
153 #Ignore BXJ for now
153 bxjcode = '''
154 HSTR hstr = Hstr;
155 CPSR cpsr = Cpsr;
156 SCR scr = Scr;
154
157
158 if (ArmSystem::haveVirtualization(xc->tcBase()) && hstr.tjdbx &&
159 !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
160 fault = new HypervisorTrap(machInst, op1, EC_TRAPPED_BXJ);
161 }
162 IWNPC = Op1;
163 '''
164
165 bxjIop = InstObjParams("bxj", "BxjReg", "BranchRegCond",
166 {"code": bxjcode,
167 "predicate_test": predicateTest,
168 "is_ras_pop": "op1 == INTREG_LR" },
169 ["IsIndirectControl"])
170 header_output += BranchRegCondDeclare.subst(bxjIop)
171 decoder_output += BranchRegCondConstructor.subst(bxjIop)
172 exec_output += PredOpExecute.subst(bxjIop)
173
155 #CBNZ, CBZ. These are always unconditional as far as predicates
156 for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
157 code = 'NPC = (uint32_t)(PC + imm);\n'
158 predTest = "Op1 %(test)s 0" % {"test": test}
159 iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
160 {"code": code, "predicate_test": predTest},
161 ["IsIndirectControl"])
162 header_output += BranchImmRegDeclare.subst(iop)
163 decoder_output += BranchImmRegConstructor.subst(iop)
164 exec_output += PredOpExecute.subst(iop)
165
166 #TBB, TBH
167 for isTbh in (0, 1):
168 if isTbh:
169 eaCode = '''
170 unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
171 ArmISA::TLB::AlignHalfWord |
172 ArmISA::TLB::MustBeOne;
173 EA = Op1 + Op2 * 2
174 '''
175 accCode = 'NPC = PC + 2 * (Mem_uh);\n'
176 mnem = "tbh"
177 else:
178 eaCode = '''
179 unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
180 ArmISA::TLB::AlignByte |
181 ArmISA::TLB::MustBeOne;
182 EA = Op1 + Op2
183 '''
184 accCode = 'NPC = PC + 2 * (Mem_ub)'
185 mnem = "tbb"
186 iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
187 {'ea_code': eaCode,
188 'memacc_code': accCode,
189 'predicate_test': predicateTest},
190 ["IsIndirectControl"])
191 header_output += BranchTableDeclare.subst(iop)
192 decoder_output += BranchRegRegConstructor.subst(iop)
193 exec_output += LoadExecute.subst(iop) + \
194 LoadInitiateAcc.subst(iop) + \
195 LoadCompleteAcc.subst(iop)
196}};
174 #CBNZ, CBZ. These are always unconditional as far as predicates
175 for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
176 code = 'NPC = (uint32_t)(PC + imm);\n'
177 predTest = "Op1 %(test)s 0" % {"test": test}
178 iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
179 {"code": code, "predicate_test": predTest},
180 ["IsIndirectControl"])
181 header_output += BranchImmRegDeclare.subst(iop)
182 decoder_output += BranchImmRegConstructor.subst(iop)
183 exec_output += PredOpExecute.subst(iop)
184
185 #TBB, TBH
186 for isTbh in (0, 1):
187 if isTbh:
188 eaCode = '''
189 unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
190 ArmISA::TLB::AlignHalfWord |
191 ArmISA::TLB::MustBeOne;
192 EA = Op1 + Op2 * 2
193 '''
194 accCode = 'NPC = PC + 2 * (Mem_uh);\n'
195 mnem = "tbh"
196 else:
197 eaCode = '''
198 unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
199 ArmISA::TLB::AlignByte |
200 ArmISA::TLB::MustBeOne;
201 EA = Op1 + Op2
202 '''
203 accCode = 'NPC = PC + 2 * (Mem_ub)'
204 mnem = "tbb"
205 iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
206 {'ea_code': eaCode,
207 'memacc_code': accCode,
208 'predicate_test': predicateTest},
209 ["IsIndirectControl"])
210 header_output += BranchTableDeclare.subst(iop)
211 decoder_output += BranchRegRegConstructor.subst(iop)
212 exec_output += LoadExecute.subst(iop) + \
213 LoadInitiateAcc.subst(iop) + \
214 LoadCompleteAcc.subst(iop)
215}};