mem.isa revision 6243
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, MachInst _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(MachInst 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(MachInst machInst);
150
151            %(BasicExecDeclare)s
152        };
153
154      public:
155
156        /// Constructor.
157        %(class_name)s(MachInst 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(MachInst 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(MachInst 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(MachInst 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        %(fp_enable_check)s;
215        %(op_decl)s;
216        %(op_rd)s;
217        %(ea_code)s;
218
219        if (%(predicate_test)s)
220        {
221            if (fault == NoFault) {
222                %(op_wb)s;
223                xc->setEA(EA);
224            }
225        }
226
227        return fault;
228    }
229}};
230
231def template LoadMemAccExecute {{
232    Fault
233    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
234                                   Trace::InstRecord *traceData) const
235    {
236        Addr EA;
237        Fault fault = NoFault;
238
239        %(fp_enable_check)s;
240        %(op_decl)s;
241        %(op_rd)s;
242        EA = xc->getEA();
243
244        if (%(predicate_test)s)
245        {
246            if (fault == NoFault) {
247                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
248                %(memacc_code)s;
249            }
250
251            if (fault == NoFault) {
252                %(op_wb)s;
253            }
254        }
255
256        return fault;
257    }
258}};
259
260
261def template LoadExecute {{
262    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
263                                  Trace::InstRecord *traceData) const
264    {
265        Addr EA;
266        Fault fault = NoFault;
267
268        %(fp_enable_check)s;
269        %(op_decl)s;
270        %(op_rd)s;
271        %(ea_code)s;
272
273        if (%(predicate_test)s)
274        {
275            if (fault == NoFault) {
276                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
277                %(memacc_code)s;
278            }
279
280            if (fault == NoFault) {
281                %(op_wb)s;
282            }
283        }
284
285        return fault;
286    }
287}};
288
289
290def template LoadInitiateAcc {{
291    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
292                                      Trace::InstRecord *traceData) const
293    {
294        Addr EA;
295        Fault fault = NoFault;
296
297        %(fp_enable_check)s;
298        %(op_src_decl)s;
299        %(op_rd)s;
300        %(ea_code)s;
301
302        if (%(predicate_test)s)
303        {
304            if (fault == NoFault) {
305                fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
306            }
307        }
308
309        return fault;
310    }
311}};
312
313
314def template LoadCompleteAcc {{
315    Fault %(class_name)s::completeAcc(PacketPtr pkt,
316                                      %(CPU_exec_context)s *xc,
317                                      Trace::InstRecord *traceData) const
318    {
319        Fault fault = NoFault;
320
321        %(fp_enable_check)s;
322        %(op_decl)s;
323        %(op_rd)s;
324
325        if (%(predicate_test)s)
326        {
327            // ARM instructions will not have a pkt if the predicate is false
328            Mem = pkt->get<typeof(Mem)>();
329
330            if (fault == NoFault) {
331                %(memacc_code)s;
332            }
333
334            if (fault == NoFault) {
335                %(op_wb)s;
336            }
337        }
338
339        return fault;
340    }
341}};
342
343
344def template StoreMemAccExecute {{
345    Fault
346    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
347                                   Trace::InstRecord *traceData) const
348    {
349        Addr EA;
350        Fault fault = NoFault;
351
352        %(fp_enable_check)s;
353        %(op_decl)s;
354        %(op_rd)s;
355
356        if (%(predicate_test)s)
357        {
358            EA = xc->getEA();
359
360            if (fault == NoFault) {
361                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
362                                  memAccessFlags, NULL);
363                if (traceData) { traceData->setData(Mem); }
364            }
365
366            if (fault == NoFault) {
367                %(op_wb)s;
368            }
369        }
370
371        return fault;
372    }
373}};
374
375
376def template StoreExecute {{
377    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
378                                  Trace::InstRecord *traceData) const
379    {
380        Addr EA;
381        Fault fault = NoFault;
382
383        %(fp_enable_check)s;
384        %(op_decl)s;
385        %(op_rd)s;
386        %(ea_code)s;
387
388        if (%(predicate_test)s)
389        {
390            if (fault == NoFault) {
391                %(memacc_code)s;
392            }
393
394            if (fault == NoFault) {
395                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
396                                  memAccessFlags, NULL);
397                if (traceData) { traceData->setData(Mem); }
398            }
399
400            if (fault == NoFault) {
401                %(op_wb)s;
402            }
403        }
404
405        return fault;
406    }
407}};
408
409def template StoreInitiateAcc {{
410    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
411                                      Trace::InstRecord *traceData) const
412    {
413        Addr EA;
414        Fault fault = NoFault;
415
416        %(fp_enable_check)s;
417        %(op_decl)s;
418        %(op_rd)s;
419        %(ea_code)s;
420
421        if (%(predicate_test)s)
422        {
423            if (fault == NoFault) {
424                %(memacc_code)s;
425            }
426
427            if (fault == NoFault) {
428                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
429                                  memAccessFlags, NULL);
430                if (traceData) { traceData->setData(Mem); }
431            }
432
433            // Need to write back any potential address register update
434            if (fault == NoFault) {
435                %(op_wb)s;
436            }
437        }
438
439        return fault;
440    }
441}};
442
443
444def template StoreCompleteAcc {{
445    Fault %(class_name)s::completeAcc(PacketPtr pkt,
446                                      %(CPU_exec_context)s *xc,
447                                      Trace::InstRecord *traceData) const
448    {
449        Fault fault = NoFault;
450
451        %(fp_enable_check)s;
452        %(op_dest_decl)s;
453
454        if (%(predicate_test)s)
455        {
456            if (fault == NoFault) {
457                %(op_wb)s;
458            }
459        }
460
461        return fault;
462    }
463}};
464
465def template StoreCondCompleteAcc {{
466    Fault %(class_name)s::completeAcc(PacketPtr pkt,
467                                      %(CPU_exec_context)s *xc,
468                                      Trace::InstRecord *traceData) const
469    {
470        Fault fault = NoFault;
471
472        %(fp_enable_check)s;
473        %(op_dest_decl)s;
474
475        if (%(predicate_test)s)
476        {
477            if (fault == NoFault) {
478                %(op_wb)s;
479            }
480        }
481
482        return fault;
483    }
484}};
485
486
487def template MiscMemAccExecute {{
488    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
489                                          Trace::InstRecord *traceData) const
490    {
491        Addr EA;
492        Fault fault = NoFault;
493
494        %(fp_enable_check)s;
495        %(op_decl)s;
496        %(op_rd)s;
497
498        if (%(predicate_test)s)
499        {
500            EA = xc->getEA();
501
502            if (fault == NoFault) {
503                %(memacc_code)s;
504            }
505        }
506
507        return NoFault;
508    }
509}};
510
511def template MiscExecute {{
512    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
513                                  Trace::InstRecord *traceData) const
514    {
515        Addr EA;
516        Fault fault = NoFault;
517
518        %(fp_enable_check)s;
519        %(op_decl)s;
520        %(op_rd)s;
521        %(ea_code)s;
522
523        if (%(predicate_test)s)
524        {
525            if (fault == NoFault) {
526                %(memacc_code)s;
527            }
528        }
529
530        return NoFault;
531    }
532}};
533
534def template MiscInitiateAcc {{
535    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
536                                      Trace::InstRecord *traceData) const
537    {
538        panic("Misc instruction does not support split access method!");
539        return NoFault;
540    }
541}};
542
543
544def template MiscCompleteAcc {{
545    Fault %(class_name)s::completeAcc(PacketPtr pkt,
546                                      %(CPU_exec_context)s *xc,
547                                      Trace::InstRecord *traceData) const
548    {
549        panic("Misc instruction does not support split access method!");
550
551        return NoFault;
552    }
553}};
554
555def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
556                     mem_flags = [], inst_flags = []) {{
557    ea_code = ArmGenericCodeSubs(ea_code)
558    memacc_code = ArmGenericCodeSubs(memacc_code)
559    (header_output, decoder_output, decode_block, exec_output) = \
560        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
561                      decode_template = BasicDecode,
562                      exec_template_base = 'Load')
563}};
564
565def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
566                     mem_flags = [], inst_flags = []) {{
567    ea_code = ArmGenericCodeSubs(ea_code)
568    memacc_code = ArmGenericCodeSubs(memacc_code)
569    (header_output, decoder_output, decode_block, exec_output) = \
570        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
571                      exec_template_base = 'Store')
572}};
573
574