1// -*- mode:c++ -*-
2
3// Copyright (c) 2007-2008 The Florida State University
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Stephen Hines
30
31////////////////////////////////////////////////////////////////////
32//
33// Predicated Instruction Execution
34//
35
36output header {{
37#include <iostream>
38
39 enum ArmPredicateBits {
40 COND_EQ = 0,
41 COND_NE, // 1
42 COND_CS, // 2
43 COND_CC, // 3
44 COND_MI, // 4
45 COND_PL, // 5
46 COND_VS, // 6
47 COND_VC, // 7
48 COND_HI, // 8
49 COND_LS, // 9
50 COND_GE, // 10
51 COND_LT, // 11
52 COND_GT, // 12
53 COND_LE, // 13
54 COND_AL, // 14
55 COND_NV // 15
56 };
57
39 inline uint32_t
40 rotate_imm(uint32_t immValue, uint32_t rotateValue)
41 {
42 return ((immValue >> (int)(rotateValue & 31)) |
43 (immValue << (32 - (int)(rotateValue & 31))));
44 }
45
65 inline uint32_t nSet(uint32_t cpsr) { return cpsr & (1<<31); }
66 inline uint32_t zSet(uint32_t cpsr) { return cpsr & (1<<30); }
67 inline uint32_t cSet(uint32_t cpsr) { return cpsr & (1<<29); }
68 inline uint32_t vSet(uint32_t cpsr) { return cpsr & (1<<28); }
69
70 inline bool arm_predicate(uint32_t cpsr, uint32_t predBits)
71 {
72
73 enum ArmPredicateBits armPredBits = (enum ArmPredicateBits) predBits;
74 uint32_t result = 0;
75 switch (armPredBits)
76 {
77 case COND_EQ:
78 result = zSet(cpsr); break;
79 case COND_NE:
80 result = !zSet(cpsr); break;
81 case COND_CS:
82 result = cSet(cpsr); break;
83 case COND_CC:
84 result = !cSet(cpsr); break;
85 case COND_MI:
86 result = nSet(cpsr); break;
87 case COND_PL:
88 result = !nSet(cpsr); break;
89 case COND_VS:
90 result = vSet(cpsr); break;
91 case COND_VC:
92 result = !vSet(cpsr); break;
93 case COND_HI:
94 result = cSet(cpsr) && !zSet(cpsr); break;
95 case COND_LS:
96 result = !cSet(cpsr) || zSet(cpsr); break;
97 case COND_GE:
98 result = (!nSet(cpsr) && !vSet(cpsr)) || (nSet(cpsr) && vSet(cpsr)); break;
99 case COND_LT:
100 result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)); break;
101 case COND_GT:
102 result = (!nSet(cpsr) && !vSet(cpsr) && !zSet(cpsr)) || (nSet(cpsr) && vSet(cpsr) && !zSet(cpsr)); break;
103 case COND_LE:
104 result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)) || zSet(cpsr); break;
105 case COND_AL: result = 1; break;
106 case COND_NV: result = 0; break;
107 default:
108 fprintf(stderr, "Unhandled predicate condition: %d\n", armPredBits);
109 exit(1);
110 }
111 if (result)
112 return true;
113 else
114 return false;
115 }
116
117
46 /**
47 * Base class for predicated integer operations.
48 */
49 class PredOp : public ArmStaticInst
50 {
123 protected:
51 protected:
52
125 uint32_t condCode;
53 ArmISA::ConditionCode condCode;
54
127 /// Constructor
128 PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
129 ArmStaticInst(mnem, _machInst, __opClass),
130 condCode(COND_CODE)
131 {
132 }
55 /// Constructor
56 PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
57 ArmStaticInst(mnem, _machInst, __opClass),
58 condCode((ArmISA::ConditionCode)COND_CODE)
59 {
60 }
61
134 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
62 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
63 };
64
65 /**
66 * Base class for predicated immediate operations.
67 */
68 class PredImmOp : public PredOp
69 {
70 protected:
71
72 uint32_t imm;
73 uint32_t rotate;
74 uint32_t rotated_imm;
75 uint32_t rotated_carry;
76
77 /// Constructor
78 PredImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
79 PredOp(mnem, _machInst, __opClass),
80 imm(IMM), rotate(ROTATE << 1), rotated_imm(0),
81 rotated_carry(0)
82 {
83 rotated_imm = rotate_imm(imm, rotate);
84 if (rotate != 0)
85 rotated_carry = (rotated_imm >> 31) & 1;
86 }
87
88 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
89 };
90
91 /**
92 * Base class for predicated integer operations.
93 */
94 class PredIntOp : public PredOp
95 {
96 protected:
97
98 uint32_t shift_size;
99 uint32_t shift;
100
101 /// Constructor
102 PredIntOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
103 PredOp(mnem, _machInst, __opClass),
104 shift_size(SHIFT_SIZE), shift(SHIFT)
105 {
106 }
107
108 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
109 };
110
111 /**
112 * Base class for predicated macro-operations.
113 */
114 class PredMacroOp : public PredOp
115 {
116 protected:
117
118 uint32_t numMicroops;
119 StaticInstPtr * microOps;
120
121 /// Constructor
122 PredMacroOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
123 PredOp(mnem, _machInst, __opClass),
124 numMicroops(0)
125 {
126 // We rely on the subclasses of this object to handle the
127 // initialization of the micro-operations, since they are
128 // all of variable length
129 flags[IsMacroop] = true;
130 }
131
132 ~PredMacroOp()
133 {
134 if (numMicroops)
135 delete [] microOps;
136 }
137
138 StaticInstPtr fetchMicroop(MicroPC microPC)
139 {
140 assert(microPC < numMicroops);
141 return microOps[microPC];
142 }
143
144 %(BasicExecPanic)s
145
146 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
147 };
148
149 /**
150 * Base class for predicated micro-operations.
151 */
152 class PredMicroop : public PredOp
153 {
154 /// Constructor
155 PredMicroop(const char *mnem, MachInst _machInst, OpClass __opClass) :
156 PredOp(mnem, _machInst, __opClass)
157 {
158 flags[IsMicroop] = true;
159 }
160 };
161
162}};
163
164def template PredOpExecute {{
165 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
166 {
167 Fault fault = NoFault;
168
169 %(fp_enable_check)s;
170 %(op_decl)s;
171 %(op_rd)s;
172 %(code)s;
173
246 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
174 if (testPredicate(xc->readMiscReg(ArmISA::MISCREG_CPSR), condCode))
175 {
176 if (fault == NoFault)
177 {
178 %(op_wb)s;
179 }
180 }
181 else
182 return NoFault;
183 // Predicated false instructions should not return faults
184
185 return fault;
186 }
187}};
188
189//Outputs to decoder.cc
190output decoder {{
191 std::string PredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
192 {
193 std::stringstream ss;
194
195 ccprintf(ss, "%-10s ", mnemonic);
196
197 if (_numDestRegs > 0) {
198 printReg(ss, _destRegIdx[0]);
199 }
200
201 ss << ", ";
202
203 if (_numSrcRegs > 0) {
204 printReg(ss, _srcRegIdx[0]);
205 ss << ", ";
206 }
207
208 return ss.str();
209 }
210
211 std::string PredImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
212 {
213 std::stringstream ss;
214
215 ccprintf(ss, "%-10s ", mnemonic);
216
217 if (_numDestRegs > 0) {
218 printReg(ss, _destRegIdx[0]);
219 }
220
221 ss << ", ";
222
223 if (_numSrcRegs > 0) {
224 printReg(ss, _srcRegIdx[0]);
225 ss << ", ";
226 }
227
228 return ss.str();
229 }
230
231 std::string PredIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
232 {
233 std::stringstream ss;
234
235 ccprintf(ss, "%-10s ", mnemonic);
236
237 if (_numDestRegs > 0) {
238 printReg(ss, _destRegIdx[0]);
239 }
240
241 ss << ", ";
242
243 if (_numSrcRegs > 0) {
244 printReg(ss, _srcRegIdx[0]);
245 ss << ", ";
246 }
247
248 return ss.str();
249 }
250
251 std::string PredMacroOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
252 {
253 std::stringstream ss;
254
255 ccprintf(ss, "%-10s ", mnemonic);
256
257 return ss.str();
258 }
259
260}};
261
262let {{
263
264 calcCcCode = '''
265 uint16_t _ic, _iv, _iz, _in;
266
267 _in = (resTemp >> 31) & 1;
268 _iz = (resTemp == 0);
269 _iv = %(ivValue)s & 1;
270 _ic = %(icValue)s & 1;
271
272 Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
273 (Cpsr & 0x0FFFFFFF);
274
275 DPRINTF(Arm, "in = %%d\\n", _in);
276 DPRINTF(Arm, "iz = %%d\\n", _iz);
277 DPRINTF(Arm, "ic = %%d\\n", _ic);
278 DPRINTF(Arm, "iv = %%d\\n", _iv);
279 '''
280
281}};
282
283def format PredOp(code, *opt_flags) {{
284 iop = InstObjParams(name, Name, 'PredOp', code, opt_flags)
285 header_output = BasicDeclare.subst(iop)
286 decoder_output = BasicConstructor.subst(iop)
287 decode_block = BasicDecode.subst(iop)
288 exec_output = PredOpExecute.subst(iop)
289}};
290
291def format PredImmOp(code, *opt_flags) {{
292 iop = InstObjParams(name, Name, 'PredImmOp', code, opt_flags)
293 header_output = BasicDeclare.subst(iop)
294 decoder_output = BasicConstructor.subst(iop)
295 decode_block = BasicDecode.subst(iop)
296 exec_output = PredOpExecute.subst(iop)
297}};
298
299def format PredImmOpCc(code, icValue, ivValue, *opt_flags) {{
300 ccCode = calcCcCode % vars()
301 code += ccCode;
302 iop = InstObjParams(name, Name, 'PredImmOp',
303 {"code": code, "cc_code": ccCode}, opt_flags)
304 header_output = BasicDeclare.subst(iop)
305 decoder_output = BasicConstructor.subst(iop)
306 decode_block = BasicDecode.subst(iop)
307 exec_output = PredOpExecute.subst(iop)
308}};
309
310def format PredIntOp(code, *opt_flags) {{
311 new_code = ArmGenericCodeSubs(code)
312 iop = InstObjParams(name, Name, 'PredIntOp', new_code, opt_flags)
313 header_output = BasicDeclare.subst(iop)
314 decoder_output = BasicConstructor.subst(iop)
315 decode_block = BasicDecode.subst(iop)
316 exec_output = PredOpExecute.subst(iop)
317}};
318
319def format PredIntOpCc(code, icValue, ivValue, *opt_flags) {{
320 ccCode = calcCcCode % vars()
321 code += ccCode;
322 new_code = ArmGenericCodeSubs(code)
323 iop = InstObjParams(name, Name, 'PredIntOp',
324 {"code": new_code, "cc_code": ccCode }, opt_flags)
325 header_output = BasicDeclare.subst(iop)
326 decoder_output = BasicConstructor.subst(iop)
327 decode_block = BasicDecode.subst(iop)
328 exec_output = PredOpExecute.subst(iop)
329}};
330