Merge ARM into the head. ARM will compile but may not actually work.
[gem5.git] / src / arch / arm / isa / formats / pred.isa
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
36 output 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
58 inline uint32_t
59 rotate_imm(uint32_t immValue, uint32_t rotateValue)
60 {
61 return ((immValue >> (int)(rotateValue & 31)) |
62 (immValue << (32 - (int)(rotateValue & 31))));
63 }
64
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
118 /**
119 * Base class for predicated integer operations.
120 */
121 class PredOp : public ArmStaticInst
122 {
123 protected:
124
125 uint32_t condCode;
126
127 /// Constructor
128 PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
129 ArmStaticInst(mnem, _machInst, __opClass),
130 condCode(COND_CODE)
131 {
132 }
133
134 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
135 };
136
137 /**
138 * Base class for predicated immediate operations.
139 */
140 class PredImmOp : public PredOp
141 {
142 protected:
143
144 uint32_t imm;
145 uint32_t rotate;
146 uint32_t rotated_imm;
147 uint32_t rotated_carry;
148
149 /// Constructor
150 PredImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
151 PredOp(mnem, _machInst, __opClass),
152 imm(IMM), rotate(ROTATE << 1), rotated_imm(0),
153 rotated_carry(0)
154 {
155 rotated_imm = rotate_imm(imm, rotate);
156 if (rotate != 0)
157 rotated_carry = (rotated_imm >> 31) & 1;
158 }
159
160 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
161 };
162
163 /**
164 * Base class for predicated integer operations.
165 */
166 class PredIntOp : public PredOp
167 {
168 protected:
169
170 uint32_t shift_size;
171 uint32_t shift;
172
173 /// Constructor
174 PredIntOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
175 PredOp(mnem, _machInst, __opClass),
176 shift_size(SHIFT_SIZE), shift(SHIFT)
177 {
178 }
179
180 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
181 };
182
183 /**
184 * Base class for predicated macro-operations.
185 */
186 class PredMacroOp : public PredOp
187 {
188 protected:
189
190 uint32_t numMicroops;
191 StaticInstPtr * microOps;
192
193 /// Constructor
194 PredMacroOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
195 PredOp(mnem, _machInst, __opClass),
196 numMicroops(0)
197 {
198 // We rely on the subclasses of this object to handle the
199 // initialization of the micro-operations, since they are
200 // all of variable length
201 flags[IsMacroop] = true;
202 }
203
204 ~PredMacroOp()
205 {
206 if (numMicroops)
207 delete [] microOps;
208 }
209
210 StaticInstPtr fetchMicroop(MicroPC microPC)
211 {
212 assert(microPC < numMicroops);
213 return microOps[microPC];
214 }
215
216 %(BasicExecPanic)s
217
218 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
219 };
220
221 /**
222 * Base class for predicated micro-operations.
223 */
224 class PredMicroop : public PredOp
225 {
226 /// Constructor
227 PredMicroop(const char *mnem, MachInst _machInst, OpClass __opClass) :
228 PredOp(mnem, _machInst, __opClass)
229 {
230 flags[IsMicroop] = true;
231 }
232 };
233
234 }};
235
236 def template PredOpExecute {{
237 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
238 {
239 Fault fault = NoFault;
240
241 %(fp_enable_check)s;
242 %(op_decl)s;
243 %(op_rd)s;
244 %(code)s;
245
246 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
247 {
248 if (fault == NoFault)
249 {
250 %(op_wb)s;
251 }
252 }
253 else
254 return NoFault;
255 // Predicated false instructions should not return faults
256
257 return fault;
258 }
259 }};
260
261 //Outputs to decoder.cc
262 output decoder {{
263 std::string PredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
264 {
265 std::stringstream ss;
266
267 ccprintf(ss, "%-10s ", mnemonic);
268
269 if (_numDestRegs > 0) {
270 printReg(ss, _destRegIdx[0]);
271 }
272
273 ss << ", ";
274
275 if (_numSrcRegs > 0) {
276 printReg(ss, _srcRegIdx[0]);
277 ss << ", ";
278 }
279
280 return ss.str();
281 }
282
283 std::string PredImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
284 {
285 std::stringstream ss;
286
287 ccprintf(ss, "%-10s ", mnemonic);
288
289 if (_numDestRegs > 0) {
290 printReg(ss, _destRegIdx[0]);
291 }
292
293 ss << ", ";
294
295 if (_numSrcRegs > 0) {
296 printReg(ss, _srcRegIdx[0]);
297 ss << ", ";
298 }
299
300 return ss.str();
301 }
302
303 std::string PredIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
304 {
305 std::stringstream ss;
306
307 ccprintf(ss, "%-10s ", mnemonic);
308
309 if (_numDestRegs > 0) {
310 printReg(ss, _destRegIdx[0]);
311 }
312
313 ss << ", ";
314
315 if (_numSrcRegs > 0) {
316 printReg(ss, _srcRegIdx[0]);
317 ss << ", ";
318 }
319
320 return ss.str();
321 }
322
323 std::string PredMacroOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
324 {
325 std::stringstream ss;
326
327 ccprintf(ss, "%-10s ", mnemonic);
328
329 return ss.str();
330 }
331
332 }};
333
334 let {{
335
336 calcCcCode = '''
337 uint16_t _ic, _iv, _iz, _in;
338
339 _in = (resTemp >> 31) & 1;
340 _iz = (resTemp == 0);
341 _iv = %(ivValue)s & 1;
342 _ic = %(icValue)s & 1;
343
344 Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
345 (Cpsr & 0x0FFFFFFF);
346
347 DPRINTF(Arm, "in = %%d\\n", _in);
348 DPRINTF(Arm, "iz = %%d\\n", _iz);
349 DPRINTF(Arm, "ic = %%d\\n", _ic);
350 DPRINTF(Arm, "iv = %%d\\n", _iv);
351 '''
352
353 }};
354
355 def format PredOp(code, *opt_flags) {{
356 iop = InstObjParams(name, Name, 'PredOp', code, opt_flags)
357 header_output = BasicDeclare.subst(iop)
358 decoder_output = BasicConstructor.subst(iop)
359 decode_block = BasicDecode.subst(iop)
360 exec_output = PredOpExecute.subst(iop)
361 }};
362
363 def format PredImmOp(code, *opt_flags) {{
364 iop = InstObjParams(name, Name, 'PredImmOp', code, opt_flags)
365 header_output = BasicDeclare.subst(iop)
366 decoder_output = BasicConstructor.subst(iop)
367 decode_block = BasicDecode.subst(iop)
368 exec_output = PredOpExecute.subst(iop)
369 }};
370
371 def format PredImmOpCc(code, icValue, ivValue, *opt_flags) {{
372 ccCode = calcCcCode % vars()
373 code += ccCode;
374 iop = InstObjParams(name, Name, 'PredImmOp',
375 {"code": code, "cc_code": ccCode}, opt_flags)
376 header_output = BasicDeclare.subst(iop)
377 decoder_output = BasicConstructor.subst(iop)
378 decode_block = BasicDecode.subst(iop)
379 exec_output = PredOpExecute.subst(iop)
380 }};
381
382 def format PredIntOp(code, *opt_flags) {{
383 new_code = ArmGenericCodeSubs(code)
384 iop = InstObjParams(name, Name, 'PredIntOp', new_code, opt_flags)
385 header_output = BasicDeclare.subst(iop)
386 decoder_output = BasicConstructor.subst(iop)
387 decode_block = BasicDecode.subst(iop)
388 exec_output = PredOpExecute.subst(iop)
389 }};
390
391 def format PredIntOpCc(code, icValue, ivValue, *opt_flags) {{
392 ccCode = calcCcCode % vars()
393 code += ccCode;
394 new_code = ArmGenericCodeSubs(code)
395 iop = InstObjParams(name, Name, 'PredIntOp',
396 {"code": new_code, "cc_code": ccCode }, opt_flags)
397 header_output = BasicDeclare.subst(iop)
398 decoder_output = BasicConstructor.subst(iop)
399 decode_block = BasicDecode.subst(iop)
400 exec_output = PredOpExecute.subst(iop)
401 }};
402