mem.isa revision 6019
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 (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
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 (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
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 (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
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 (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
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 (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
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 (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
357        {
358            EA = xc->getEA();
359
360            if (fault == NoFault) {
361                %(postacc_code)s;
362            }
363
364            if (fault == NoFault) {
365                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
366                                  memAccessFlags, NULL);
367                if (traceData) { traceData->setData(Mem); }
368            }
369
370            if (fault == NoFault) {
371                %(postacc_code)s;
372            }
373
374            if (fault == NoFault) {
375                %(op_wb)s;
376            }
377        }
378
379        return fault;
380    }
381}};
382
383
384def template StoreExecute {{
385    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
386                                  Trace::InstRecord *traceData) const
387    {
388        Addr EA;
389        Fault fault = NoFault;
390
391        %(fp_enable_check)s;
392        %(op_decl)s;
393        %(op_rd)s;
394        %(ea_code)s;
395
396        if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
397        {
398            if (fault == NoFault) {
399                %(memacc_code)s;
400            }
401
402            if (fault == NoFault) {
403                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
404                                  memAccessFlags, NULL);
405                if (traceData) { traceData->setData(Mem); }
406            }
407
408            if (fault == NoFault) {
409                %(postacc_code)s;
410            }
411
412            if (fault == NoFault) {
413                %(op_wb)s;
414            }
415        }
416
417        return fault;
418    }
419}};
420
421def template StoreInitiateAcc {{
422    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
423                                      Trace::InstRecord *traceData) const
424    {
425        Addr EA;
426        Fault fault = NoFault;
427
428        %(fp_enable_check)s;
429        %(op_decl)s;
430        %(op_rd)s;
431        %(ea_code)s;
432
433        if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
434        {
435            if (fault == NoFault) {
436                %(memacc_code)s;
437            }
438
439            if (fault == NoFault) {
440                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
441                                  memAccessFlags, NULL);
442                if (traceData) { traceData->setData(Mem); }
443            }
444
445            // Need to write back any potential address register update
446            if (fault == NoFault) {
447                %(op_wb)s;
448            }
449        }
450
451        return fault;
452    }
453}};
454
455
456def template StoreCompleteAcc {{
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        %(fp_enable_check)s;
464        %(op_dest_decl)s;
465
466        if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
467        {
468            if (fault == NoFault) {
469                %(postacc_code)s;
470            }
471
472            if (fault == NoFault) {
473                %(op_wb)s;
474            }
475        }
476
477        return fault;
478    }
479}};
480
481def template StoreCondCompleteAcc {{
482    Fault %(class_name)s::completeAcc(PacketPtr pkt,
483                                      %(CPU_exec_context)s *xc,
484                                      Trace::InstRecord *traceData) const
485    {
486        Fault fault = NoFault;
487
488        %(fp_enable_check)s;
489        %(op_dest_decl)s;
490
491        if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
492        {
493            if (fault == NoFault) {
494                %(postacc_code)s;
495            }
496
497            if (fault == NoFault) {
498                %(op_wb)s;
499            }
500        }
501
502        return fault;
503    }
504}};
505
506
507def template MiscMemAccExecute {{
508    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
509                                          Trace::InstRecord *traceData) const
510    {
511        Addr EA;
512        Fault fault = NoFault;
513
514        %(fp_enable_check)s;
515        %(op_decl)s;
516        %(op_rd)s;
517
518        if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
519        {
520            EA = xc->getEA();
521
522            if (fault == NoFault) {
523                %(memacc_code)s;
524            }
525        }
526
527        return NoFault;
528    }
529}};
530
531def template MiscExecute {{
532    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
533                                  Trace::InstRecord *traceData) const
534    {
535        Addr EA;
536        Fault fault = NoFault;
537
538        %(fp_enable_check)s;
539        %(op_decl)s;
540        %(op_rd)s;
541        %(ea_code)s;
542
543        if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
544        {
545            if (fault == NoFault) {
546                %(memacc_code)s;
547            }
548        }
549
550        return NoFault;
551    }
552}};
553
554def template MiscInitiateAcc {{
555    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
556                                      Trace::InstRecord *traceData) const
557    {
558        panic("Misc instruction does not support split access method!");
559        return NoFault;
560    }
561}};
562
563
564def template MiscCompleteAcc {{
565    Fault %(class_name)s::completeAcc(PacketPtr pkt,
566                                      %(CPU_exec_context)s *xc,
567                                      Trace::InstRecord *traceData) const
568    {
569        panic("Misc instruction does not support split access method!");
570
571        return NoFault;
572    }
573}};
574
575def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
576                     mem_flags = [], inst_flags = []) {{
577    ea_code = ArmGenericCodeSubs(ea_code)
578    memacc_code = ArmGenericCodeSubs(memacc_code)
579    (header_output, decoder_output, decode_block, exec_output) = \
580        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
581                      decode_template = BasicDecode,
582                      exec_template_base = 'Load')
583}};
584
585def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
586                     mem_flags = [], inst_flags = []) {{
587    ea_code = ArmGenericCodeSubs(ea_code)
588    memacc_code = ArmGenericCodeSubs(memacc_code)
589    (header_output, decoder_output, decode_block, exec_output) = \
590        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
591                      exec_template_base = 'Store')
592}};
593
594