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// Memory-format instructions
34//
35
36output header {{
37 /**
38 * Base class for general Arm memory-format instructions.
39 */
40 class Memory : public PredOp
41 {
42 protected:
43
44 /// Memory request flags. See mem_req_base.hh.
45 unsigned memAccessFlags;
46 /// Pointer to EAComp object.
47 const StaticInstPtr eaCompPtr;
48 /// Pointer to MemAcc object.
49 const StaticInstPtr memAccPtr;
50
51 /// Displacement for EA calculation (signed).
52 int32_t disp;
53 int32_t disp8;
54 int32_t up;
55 int32_t hilo,
56 shift_size,
57 shift;
58
59 /// Constructor
60 Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
61 StaticInstPtr _eaCompPtr = nullStaticInstPtr,
62 StaticInstPtr _memAccPtr = nullStaticInstPtr)
63 : PredOp(mnem, _machInst, __opClass),
64 memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
65 disp(IMMED_11_0), disp8(IMMED_7_0 << 2), up(UP),
66 hilo((IMMED_HI_11_8 << 4) | IMMED_LO_3_0),
67 shift_size(SHIFT_SIZE), shift(SHIFT)
68 {
69 // When Up is not set, then we must subtract by the displacement
70 if (!up)
71 {
72 disp = -disp;
73 disp8 = -disp8;
74 hilo = -hilo;
75 }
76 }
77
78 std::string
79 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
80
81 public:
82
83 const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
84 const StaticInstPtr &memAccInst() const { return memAccPtr; }
85 };
86
87 /**
88 * Base class for a few miscellaneous memory-format insts
89 * that don't interpret the disp field
90 */
91 class MemoryNoDisp : public Memory
92 {
93 protected:
94 /// Constructor
95 MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
96 StaticInstPtr _eaCompPtr = nullStaticInstPtr,
97 StaticInstPtr _memAccPtr = nullStaticInstPtr)
98 : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
99 {
100 }
101
102 std::string
103 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
104 };
105}};
106
107
108output decoder {{
109 std::string
110 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
111 {
112 return csprintf("%-10s", mnemonic);
113 }
114
115 std::string
116 MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
117 {
118 return csprintf("%-10s", mnemonic);
119 }
120}};
121
36def template LoadStoreDeclare {{
37 /**
38 * Static instruction class for "%(mnemonic)s".
39 */
40 class %(class_name)s : public %(base_class)s
41 {
42 protected:
43
44 /**
45 * "Fake" effective address computation class for "%(mnemonic)s".
46 */
47 class EAComp : public %(base_class)s
48 {
49 public:
50 /// Constructor
51 EAComp(ExtMachInst machInst);
52
53 %(BasicExecDeclare)s
54 };
55
56 /**
57 * "Fake" memory access instruction class for "%(mnemonic)s".
58 */
59 class MemAcc : public %(base_class)s
60 {
61 public:
62 /// Constructor
63 MemAcc(ExtMachInst machInst);
64
65 %(BasicExecDeclare)s
66 };
67
68 public:
69
70 /// Constructor.
71 %(class_name)s(ExtMachInst machInst);
72
73 %(BasicExecDeclare)s
74
75 %(InitiateAccDeclare)s
76
77 %(CompleteAccDeclare)s
78 };
79}};
80
81
82def template InitiateAccDeclare {{
83 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
84}};
85
86
87def template CompleteAccDeclare {{
88 Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
89}};
90
91
92def template EACompConstructor {{
93 inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
94 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
95 {
96 %(constructor)s;
97 }
98}};
99
100
101def template MemAccConstructor {{
102 inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
103 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
104 {
105 %(constructor)s;
106 }
107}};
108
109
110def template LoadStoreConstructor {{
111 inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
112 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
113 new EAComp(machInst), new MemAcc(machInst))
114 {
115 %(constructor)s;
116 }
117}};
118
119
120def template EACompExecute {{
121 Fault
122 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
123 Trace::InstRecord *traceData) const
124 {
125 Addr EA;
126 Fault fault = NoFault;
127
128 %(op_decl)s;
129 %(op_rd)s;
130 %(ea_code)s;
131
132 if (%(predicate_test)s)
133 {
134 if (fault == NoFault) {
135 %(op_wb)s;
136 xc->setEA(EA);
137 }
138 }
139
140 return fault;
141 }
142}};
143
144def template LoadMemAccExecute {{
145 Fault
146 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
147 Trace::InstRecord *traceData) const
148 {
149 Addr EA;
150 Fault fault = NoFault;
151
152 %(op_decl)s;
153 %(op_rd)s;
154 EA = xc->getEA();
155
156 if (%(predicate_test)s)
157 {
158 if (fault == NoFault) {
159 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
160 %(memacc_code)s;
161 }
162
163 if (fault == NoFault) {
164 %(op_wb)s;
165 }
166 }
167
168 return fault;
169 }
170}};
171
172
173def template LoadExecute {{
174 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
175 Trace::InstRecord *traceData) const
176 {
177 Addr EA;
178 Fault fault = NoFault;
179
180 %(op_decl)s;
181 %(op_rd)s;
182 %(ea_code)s;
183
184 if (%(predicate_test)s)
185 {
186 if (fault == NoFault) {
187 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
188 %(memacc_code)s;
189 }
190
191 if (fault == NoFault) {
192 %(op_wb)s;
193 }
194 }
195
196 return fault;
197 }
198}};
199
200
201def template LoadInitiateAcc {{
202 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
203 Trace::InstRecord *traceData) const
204 {
205 Addr EA;
206 Fault fault = NoFault;
207
208 %(op_src_decl)s;
209 %(op_rd)s;
210 %(ea_code)s;
211
212 if (%(predicate_test)s)
213 {
214 if (fault == NoFault) {
215 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
216 }
217 }
218
219 return fault;
220 }
221}};
222
223
224def template LoadCompleteAcc {{
225 Fault %(class_name)s::completeAcc(PacketPtr pkt,
226 %(CPU_exec_context)s *xc,
227 Trace::InstRecord *traceData) const
228 {
229 Fault fault = NoFault;
230
231 %(op_decl)s;
232 %(op_rd)s;
233
234 if (%(predicate_test)s)
235 {
236 // ARM instructions will not have a pkt if the predicate is false
237 Mem = pkt->get<typeof(Mem)>();
238
239 if (fault == NoFault) {
240 %(memacc_code)s;
241 }
242
243 if (fault == NoFault) {
244 %(op_wb)s;
245 }
246 }
247
248 return fault;
249 }
250}};
251
252
253def template StoreMemAccExecute {{
254 Fault
255 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
256 Trace::InstRecord *traceData) const
257 {
258 Addr EA;
259 Fault fault = NoFault;
260
261 %(op_decl)s;
262 %(op_rd)s;
263
264 if (%(predicate_test)s)
265 {
266 EA = xc->getEA();
267
268 if (fault == NoFault) {
269 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
270 memAccessFlags, NULL);
271 if (traceData) { traceData->setData(Mem); }
272 }
273
274 if (fault == NoFault) {
275 %(op_wb)s;
276 }
277 }
278
279 return fault;
280 }
281}};
282
283
284def template StoreExecute {{
285 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
286 Trace::InstRecord *traceData) const
287 {
288 Addr EA;
289 Fault fault = NoFault;
290
291 %(op_decl)s;
292 %(op_rd)s;
293 %(ea_code)s;
294
295 if (%(predicate_test)s)
296 {
297 if (fault == NoFault) {
298 %(memacc_code)s;
299 }
300
301 if (fault == NoFault) {
302 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
303 memAccessFlags, NULL);
304 if (traceData) { traceData->setData(Mem); }
305 }
306
307 if (fault == NoFault) {
308 %(op_wb)s;
309 }
310 }
311
312 return fault;
313 }
314}};
315
316def template StoreInitiateAcc {{
317 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
318 Trace::InstRecord *traceData) const
319 {
320 Addr EA;
321 Fault fault = NoFault;
322
323 %(op_decl)s;
324 %(op_rd)s;
325 %(ea_code)s;
326
327 if (%(predicate_test)s)
328 {
329 if (fault == NoFault) {
330 %(memacc_code)s;
331 }
332
333 if (fault == NoFault) {
334 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
335 memAccessFlags, NULL);
336 if (traceData) { traceData->setData(Mem); }
337 }
338
339 // Need to write back any potential address register update
340 if (fault == NoFault) {
341 %(op_wb)s;
342 }
343 }
344
345 return fault;
346 }
347}};
348
349
350def template StoreCompleteAcc {{
351 Fault %(class_name)s::completeAcc(PacketPtr pkt,
352 %(CPU_exec_context)s *xc,
353 Trace::InstRecord *traceData) const
354 {
355 Fault fault = NoFault;
356
357 %(op_dest_decl)s;
358
359 if (%(predicate_test)s)
360 {
361 if (fault == NoFault) {
362 %(op_wb)s;
363 }
364 }
365
366 return fault;
367 }
368}};
369
370def template StoreCondCompleteAcc {{
371 Fault %(class_name)s::completeAcc(PacketPtr pkt,
372 %(CPU_exec_context)s *xc,
373 Trace::InstRecord *traceData) const
374 {
375 Fault fault = NoFault;
376
377 %(op_dest_decl)s;
378
379 if (%(predicate_test)s)
380 {
381 if (fault == NoFault) {
382 %(op_wb)s;
383 }
384 }
385
386 return fault;
387 }
388}};
389
390
391def template MiscMemAccExecute {{
392 Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
393 Trace::InstRecord *traceData) const
394 {
395 Addr EA;
396 Fault fault = NoFault;
397
398 %(op_decl)s;
399 %(op_rd)s;
400
401 if (%(predicate_test)s)
402 {
403 EA = xc->getEA();
404
405 if (fault == NoFault) {
406 %(memacc_code)s;
407 }
408 }
409
410 return NoFault;
411 }
412}};
413
414def template MiscExecute {{
415 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
416 Trace::InstRecord *traceData) const
417 {
418 Addr EA;
419 Fault fault = NoFault;
420
421 %(op_decl)s;
422 %(op_rd)s;
423 %(ea_code)s;
424
425 if (%(predicate_test)s)
426 {
427 if (fault == NoFault) {
428 %(memacc_code)s;
429 }
430 }
431
432 return NoFault;
433 }
434}};
435
436def template MiscInitiateAcc {{
437 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
438 Trace::InstRecord *traceData) const
439 {
440 panic("Misc instruction does not support split access method!");
441 return NoFault;
442 }
443}};
444
445
446def template MiscCompleteAcc {{
447 Fault %(class_name)s::completeAcc(PacketPtr pkt,
448 %(CPU_exec_context)s *xc,
449 Trace::InstRecord *traceData) const
450 {
451 panic("Misc instruction does not support split access method!");
452
453 return NoFault;
454 }
455}};
456
457def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
458 mem_flags = [], inst_flags = []) {{
459 ea_code = ArmGenericCodeSubs(ea_code)
460 memacc_code = ArmGenericCodeSubs(memacc_code)
461 (header_output, decoder_output, decode_block, exec_output) = \
462 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
463 decode_template = BasicDecode,
464 exec_template_base = 'Load')
465}};
466
467def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
468 mem_flags = [], inst_flags = []) {{
469 ea_code = ArmGenericCodeSubs(ea_code)
470 memacc_code = ArmGenericCodeSubs(memacc_code)
471 (header_output, decoder_output, decode_block, exec_output) = \
472 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
473 exec_template_base = 'Store')
474}};
475