mem.isa revision 6250
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
122def template LoadStoreDeclare {{
123    /**
124     * Static instruction class for "%(mnemonic)s".
125     */
126    class %(class_name)s : public %(base_class)s
127    {
128      protected:
129
130        /**
131         * "Fake" effective address computation class for "%(mnemonic)s".
132         */
133        class EAComp : public %(base_class)s
134        {
135          public:
136            /// Constructor
137            EAComp(ExtMachInst machInst);
138
139            %(BasicExecDeclare)s
140        };
141
142        /**
143         * "Fake" memory access instruction class for "%(mnemonic)s".
144         */
145        class MemAcc : public %(base_class)s
146        {
147          public:
148            /// Constructor
149            MemAcc(ExtMachInst machInst);
150
151            %(BasicExecDeclare)s
152        };
153
154      public:
155
156        /// Constructor.
157        %(class_name)s(ExtMachInst machInst);
158
159        %(BasicExecDeclare)s
160
161        %(InitiateAccDeclare)s
162
163        %(CompleteAccDeclare)s
164    };
165}};
166
167
168def template InitiateAccDeclare {{
169    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
170}};
171
172
173def template CompleteAccDeclare {{
174    Fault completeAcc(PacketPtr,  %(CPU_exec_context)s *, Trace::InstRecord *) const;
175}};
176
177
178def template EACompConstructor {{
179    inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
180        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
181    {
182        %(constructor)s;
183    }
184}};
185
186
187def template MemAccConstructor {{
188    inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
189        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
190    {
191        %(constructor)s;
192    }
193}};
194
195
196def template LoadStoreConstructor {{
197    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
198         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
199                          new EAComp(machInst), new MemAcc(machInst))
200    {
201        %(constructor)s;
202    }
203}};
204
205
206def template EACompExecute {{
207    Fault
208    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
209                                   Trace::InstRecord *traceData) const
210    {
211        Addr EA;
212        Fault fault = NoFault;
213
214        %(op_decl)s;
215        %(op_rd)s;
216        %(ea_code)s;
217
218        if (%(predicate_test)s)
219        {
220            if (fault == NoFault) {
221                %(op_wb)s;
222                xc->setEA(EA);
223            }
224        }
225
226        return fault;
227    }
228}};
229
230def template LoadMemAccExecute {{
231    Fault
232    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
233                                   Trace::InstRecord *traceData) const
234    {
235        Addr EA;
236        Fault fault = NoFault;
237
238        %(op_decl)s;
239        %(op_rd)s;
240        EA = xc->getEA();
241
242        if (%(predicate_test)s)
243        {
244            if (fault == NoFault) {
245                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
246                %(memacc_code)s;
247            }
248
249            if (fault == NoFault) {
250                %(op_wb)s;
251            }
252        }
253
254        return fault;
255    }
256}};
257
258
259def template LoadExecute {{
260    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
261                                  Trace::InstRecord *traceData) const
262    {
263        Addr EA;
264        Fault fault = NoFault;
265
266        %(op_decl)s;
267        %(op_rd)s;
268        %(ea_code)s;
269
270        if (%(predicate_test)s)
271        {
272            if (fault == NoFault) {
273                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
274                %(memacc_code)s;
275            }
276
277            if (fault == NoFault) {
278                %(op_wb)s;
279            }
280        }
281
282        return fault;
283    }
284}};
285
286
287def template LoadInitiateAcc {{
288    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
289                                      Trace::InstRecord *traceData) const
290    {
291        Addr EA;
292        Fault fault = NoFault;
293
294        %(op_src_decl)s;
295        %(op_rd)s;
296        %(ea_code)s;
297
298        if (%(predicate_test)s)
299        {
300            if (fault == NoFault) {
301                fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
302            }
303        }
304
305        return fault;
306    }
307}};
308
309
310def template LoadCompleteAcc {{
311    Fault %(class_name)s::completeAcc(PacketPtr pkt,
312                                      %(CPU_exec_context)s *xc,
313                                      Trace::InstRecord *traceData) const
314    {
315        Fault fault = NoFault;
316
317        %(op_decl)s;
318        %(op_rd)s;
319
320        if (%(predicate_test)s)
321        {
322            // ARM instructions will not have a pkt if the predicate is false
323            Mem = pkt->get<typeof(Mem)>();
324
325            if (fault == NoFault) {
326                %(memacc_code)s;
327            }
328
329            if (fault == NoFault) {
330                %(op_wb)s;
331            }
332        }
333
334        return fault;
335    }
336}};
337
338
339def template StoreMemAccExecute {{
340    Fault
341    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
342                                   Trace::InstRecord *traceData) const
343    {
344        Addr EA;
345        Fault fault = NoFault;
346
347        %(op_decl)s;
348        %(op_rd)s;
349
350        if (%(predicate_test)s)
351        {
352            EA = xc->getEA();
353
354            if (fault == NoFault) {
355                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
356                                  memAccessFlags, NULL);
357                if (traceData) { traceData->setData(Mem); }
358            }
359
360            if (fault == NoFault) {
361                %(op_wb)s;
362            }
363        }
364
365        return fault;
366    }
367}};
368
369
370def template StoreExecute {{
371    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
372                                  Trace::InstRecord *traceData) const
373    {
374        Addr EA;
375        Fault fault = NoFault;
376
377        %(op_decl)s;
378        %(op_rd)s;
379        %(ea_code)s;
380
381        if (%(predicate_test)s)
382        {
383            if (fault == NoFault) {
384                %(memacc_code)s;
385            }
386
387            if (fault == NoFault) {
388                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
389                                  memAccessFlags, NULL);
390                if (traceData) { traceData->setData(Mem); }
391            }
392
393            if (fault == NoFault) {
394                %(op_wb)s;
395            }
396        }
397
398        return fault;
399    }
400}};
401
402def template StoreInitiateAcc {{
403    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
404                                      Trace::InstRecord *traceData) const
405    {
406        Addr EA;
407        Fault fault = NoFault;
408
409        %(op_decl)s;
410        %(op_rd)s;
411        %(ea_code)s;
412
413        if (%(predicate_test)s)
414        {
415            if (fault == NoFault) {
416                %(memacc_code)s;
417            }
418
419            if (fault == NoFault) {
420                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
421                                  memAccessFlags, NULL);
422                if (traceData) { traceData->setData(Mem); }
423            }
424
425            // Need to write back any potential address register update
426            if (fault == NoFault) {
427                %(op_wb)s;
428            }
429        }
430
431        return fault;
432    }
433}};
434
435
436def template StoreCompleteAcc {{
437    Fault %(class_name)s::completeAcc(PacketPtr pkt,
438                                      %(CPU_exec_context)s *xc,
439                                      Trace::InstRecord *traceData) const
440    {
441        Fault fault = NoFault;
442
443        %(op_dest_decl)s;
444
445        if (%(predicate_test)s)
446        {
447            if (fault == NoFault) {
448                %(op_wb)s;
449            }
450        }
451
452        return fault;
453    }
454}};
455
456def template StoreCondCompleteAcc {{
457    Fault %(class_name)s::completeAcc(PacketPtr pkt,
458                                      %(CPU_exec_context)s *xc,
459                                      Trace::InstRecord *traceData) const
460    {
461        Fault fault = NoFault;
462
463        %(op_dest_decl)s;
464
465        if (%(predicate_test)s)
466        {
467            if (fault == NoFault) {
468                %(op_wb)s;
469            }
470        }
471
472        return fault;
473    }
474}};
475
476
477def template MiscMemAccExecute {{
478    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
479                                          Trace::InstRecord *traceData) const
480    {
481        Addr EA;
482        Fault fault = NoFault;
483
484        %(op_decl)s;
485        %(op_rd)s;
486
487        if (%(predicate_test)s)
488        {
489            EA = xc->getEA();
490
491            if (fault == NoFault) {
492                %(memacc_code)s;
493            }
494        }
495
496        return NoFault;
497    }
498}};
499
500def template MiscExecute {{
501    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
502                                  Trace::InstRecord *traceData) const
503    {
504        Addr EA;
505        Fault fault = NoFault;
506
507        %(op_decl)s;
508        %(op_rd)s;
509        %(ea_code)s;
510
511        if (%(predicate_test)s)
512        {
513            if (fault == NoFault) {
514                %(memacc_code)s;
515            }
516        }
517
518        return NoFault;
519    }
520}};
521
522def template MiscInitiateAcc {{
523    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
524                                      Trace::InstRecord *traceData) const
525    {
526        panic("Misc instruction does not support split access method!");
527        return NoFault;
528    }
529}};
530
531
532def template MiscCompleteAcc {{
533    Fault %(class_name)s::completeAcc(PacketPtr pkt,
534                                      %(CPU_exec_context)s *xc,
535                                      Trace::InstRecord *traceData) const
536    {
537        panic("Misc instruction does not support split access method!");
538
539        return NoFault;
540    }
541}};
542
543def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
544                     mem_flags = [], inst_flags = []) {{
545    ea_code = ArmGenericCodeSubs(ea_code)
546    memacc_code = ArmGenericCodeSubs(memacc_code)
547    (header_output, decoder_output, decode_block, exec_output) = \
548        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
549                      decode_template = BasicDecode,
550                      exec_template_base = 'Load')
551}};
552
553def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
554                     mem_flags = [], inst_flags = []) {{
555    ea_code = ArmGenericCodeSubs(ea_code)
556    memacc_code = ArmGenericCodeSubs(memacc_code)
557    (header_output, decoder_output, decode_block, exec_output) = \
558        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
559                      exec_template_base = 'Store')
560}};
561
562