mem.isa revision 4675
1// -*- mode:c++ -*-
2
3// Copyright (c) 2006 The Regents of The University of Michigan
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: Steve Reinhardt
30//          Korey Sewell
31
32////////////////////////////////////////////////////////////////////
33//
34// Memory-format instructions
35//
36
37output header {{
38    /**
39     * Base class for general Mips memory-format instructions.
40     */
41    class Memory : public MipsStaticInst
42    {
43      protected:
44
45        /// Memory request flags.  See mem_req_base.hh.
46        unsigned memAccessFlags;
47        /// Pointer to EAComp object.
48        const StaticInstPtr eaCompPtr;
49        /// Pointer to MemAcc object.
50        const StaticInstPtr memAccPtr;
51
52        /// Displacement for EA calculation (signed).
53        int32_t disp;
54
55        /// Constructor
56        Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
57               StaticInstPtr _eaCompPtr = nullStaticInstPtr,
58               StaticInstPtr _memAccPtr = nullStaticInstPtr)
59            : MipsStaticInst(mnem, _machInst, __opClass),
60              memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
61              disp(sext<16>(OFFSET))
62        {
63        }
64
65        std::string
66        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
67
68      public:
69
70        const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
71        const StaticInstPtr &memAccInst() const { return memAccPtr; }
72
73        unsigned memAccFlags() { return memAccessFlags; }
74    };
75
76     /**
77     * Base class for a few miscellaneous memory-format insts
78     * that don't interpret the disp field
79     */
80    class MemoryNoDisp : public Memory
81    {
82      protected:
83        /// Constructor
84        MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
85                     StaticInstPtr _eaCompPtr = nullStaticInstPtr,
86                     StaticInstPtr _memAccPtr = nullStaticInstPtr)
87            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
88        {
89        }
90
91        std::string
92        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
93    };
94}};
95
96
97output decoder {{
98    std::string
99    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
100    {
101        return csprintf("%-10s %c%d, %d(r%d)", mnemonic,
102                        flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
103    }
104
105    std::string
106    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
107    {
108        return csprintf("%-10s %c%d, r%d(r%d)", mnemonic,
109                        flags[IsFloating] ? 'f' : 'r',
110                        flags[IsFloating] ? FD : RD,
111                        RS, RT);
112    }
113
114}};
115
116output exec {{
117    /** return data in cases where there the size of data is only
118        known in the packet
119    */
120    uint64_t getStoreData(%(CPU_exec_context)s *xc, Packet *packet) {
121        switch (packet->getSize())
122        {
123          case 8:
124            return packet->get<uint8_t>();
125
126          case 16:
127            return packet->get<uint16_t>();
128
129          case 32:
130            return packet->get<uint32_t>();
131
132          case 864:
133            return packet->get<uint64_t>();
134
135          default:
136            std::cerr << "bad store data size = " << packet->getSize() << std::endl;
137
138            assert(0);
139            return 0;
140        }
141    }
142
143
144}};
145
146def template LoadStoreDeclare {{
147    /**
148     * Static instruction class for "%(mnemonic)s".
149     */
150    class %(class_name)s : public %(base_class)s
151    {
152      protected:
153
154        /**
155         * "Fake" effective address computation class for "%(mnemonic)s".
156         */
157        class EAComp : public %(base_class)s
158        {
159          public:
160            /// Constructor
161            EAComp(ExtMachInst machInst);
162
163            %(BasicExecDeclare)s
164        };
165
166        /**
167         * "Fake" memory access instruction class for "%(mnemonic)s".
168         */
169        class MemAcc : public %(base_class)s
170        {
171          public:
172            /// Constructor
173            MemAcc(ExtMachInst machInst);
174
175            %(BasicExecDeclare)s
176        };
177
178      public:
179
180        /// Constructor.
181        %(class_name)s(ExtMachInst machInst);
182
183        %(BasicExecDeclare)s
184
185        %(InitiateAccDeclare)s
186
187        %(CompleteAccDeclare)s
188
189        %(MemAccSizeDeclare)s
190    };
191}};
192
193
194def template InitiateAccDeclare {{
195    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
196}};
197
198
199def template CompleteAccDeclare {{
200    Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
201}};
202
203def template MemAccSizeDeclare {{
204    int memAccSize(%(CPU_exec_context)s *xc);
205}};
206
207def template EACompConstructor {{
208    /** TODO: change op_class to AddrGenOp or something (requires
209     * creating new member of OpClass enum in op_class.hh, updating
210     * config files, etc.). */
211    inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
212        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
213    {
214        %(constructor)s;
215    }
216}};
217
218
219def template MemAccConstructor {{
220    inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
221        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
222    {
223        %(constructor)s;
224    }
225}};
226
227
228def template LoadStoreConstructor {{
229    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
230         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
231                          new EAComp(machInst), new MemAcc(machInst))
232    {
233        %(constructor)s;
234    }
235}};
236
237
238def template EACompExecute {{
239    Fault
240    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
241                                   Trace::InstRecord *traceData) const
242    {
243        Addr EA;
244        Fault fault = NoFault;
245
246        %(fp_enable_check)s;
247        %(op_decl)s;
248        %(op_rd)s;
249        %(ea_code)s;
250
251        // NOTE: Trace Data is written using execute or completeAcc templates
252        if (fault == NoFault) {
253            xc->setEA(EA);
254        }
255
256        return fault;
257    }
258}};
259
260def template LoadMemAccExecute {{
261    Fault
262    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
263                                   Trace::InstRecord *traceData) const
264    {
265        Addr EA;
266        Fault fault = NoFault;
267
268        %(op_decl)s;
269        %(op_rd)s;
270
271        EA = xc->getEA();
272
273        fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
274
275        %(memacc_code)s;
276
277        // NOTE: Write back data using execute or completeAcc templates
278
279        return fault;
280    }
281}};
282
283
284def template LoadExecute {{
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        %(fp_enable_check)s;
292        %(op_decl)s;
293        %(op_rd)s;
294        %(ea_code)s;
295
296        if (fault == NoFault) {
297            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
298            %(memacc_code)s;
299        }
300
301        if (fault == NoFault) {
302            %(op_wb)s;
303        }
304
305        return fault;
306    }
307}};
308
309
310def template LoadInitiateAcc {{
311    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
312                                      Trace::InstRecord *traceData) const
313    {
314        Addr EA;
315        Fault fault = NoFault;
316
317        %(fp_enable_check)s;
318        %(op_src_decl)s;
319        %(op_rd)s;
320        %(ea_code)s;
321
322        if (fault == NoFault) {
323            fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
324        }
325
326        return fault;
327    }
328}};
329
330def template LoadCompleteAcc {{
331    Fault %(class_name)s::completeAcc(Packet *pkt,
332                                      %(CPU_exec_context)s *xc,
333                                      Trace::InstRecord *traceData) const
334    {
335        Fault fault = NoFault;
336
337        %(fp_enable_check)s;
338        %(op_decl)s;
339        %(op_rd)s;
340
341        Mem = pkt->get<typeof(Mem)>();
342
343        if (fault == NoFault) {
344            %(memacc_code)s;
345        }
346
347        if (fault == NoFault) {
348            %(op_wb)s;
349        }
350
351        return fault;
352    }
353}};
354
355
356
357def template LoadStoreMemAccSize {{
358    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
359    {
360        // Return the memory access size in bytes
361        return (%(mem_acc_size)d / 8);
362    }
363}};
364
365def template StoreMemAccExecute {{
366    Fault
367    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
368                                   Trace::InstRecord *traceData) const
369    {
370        Addr EA;
371        Fault fault = NoFault;
372
373        %(fp_enable_check)s;
374        %(op_decl)s;
375        %(op_rd)s;
376
377        EA = xc->getEA();
378
379        if (fault == NoFault) {
380            %(memacc_code)s;
381        }
382
383        if (fault == NoFault) {
384            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
385                              memAccessFlags, NULL);
386            // @NOTE: Need to Call Complete Access to Set Trace Data
387            //if (traceData) { traceData->setData(Mem); }
388        }
389
390        return fault;
391    }
392}};
393
394def template StoreCondMemAccExecute {{
395    Fault
396    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
397                                   Trace::InstRecord *traceData) const
398    {
399        Addr EA;
400        Fault fault = NoFault;
401        uint64_t write_result = 0;
402
403        %(fp_enable_check)s;
404        %(op_decl)s;
405        %(op_rd)s;
406        EA = xc->getEA();
407
408        if (fault == NoFault) {
409            %(memacc_code)s;
410        }
411
412        if (fault == NoFault) {
413            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
414                              memAccessFlags, &write_result);
415            if (traceData) { traceData->setData(Mem); }
416        }
417
418        if (fault == NoFault) {
419            %(postacc_code)s;
420        }
421
422        if (fault == NoFault) {
423            %(op_wb)s;
424        }
425
426        return fault;
427    }
428}};
429
430def template StoreExecute {{
431    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
432                                  Trace::InstRecord *traceData) const
433    {
434        Addr EA;
435        Fault fault = NoFault;
436
437        %(fp_enable_check)s;
438        %(op_decl)s;
439        %(op_rd)s;
440        %(ea_code)s;
441
442        if (fault == NoFault) {
443            %(memacc_code)s;
444        }
445
446        if (fault == NoFault) {
447            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
448                              memAccessFlags, NULL);
449            if (traceData) { traceData->setData(Mem); }
450        }
451
452        if (fault == NoFault) {
453            %(postacc_code)s;
454        }
455
456        if (fault == NoFault) {
457            %(op_wb)s;
458        }
459
460        return fault;
461    }
462}};
463
464def template StoreCondExecute {{
465    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
466                                  Trace::InstRecord *traceData) const
467    {
468        Addr EA;
469        Fault fault = NoFault;
470        uint64_t write_result = 0;
471
472        %(fp_enable_check)s;
473        %(op_decl)s;
474        %(op_rd)s;
475        %(ea_code)s;
476
477        if (fault == NoFault) {
478            %(memacc_code)s;
479        }
480
481        if (fault == NoFault) {
482            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
483                              memAccessFlags, &write_result);
484            if (traceData) { traceData->setData(Mem); }
485        }
486
487        if (fault == NoFault) {
488            %(postacc_code)s;
489        }
490
491        if (fault == NoFault) {
492            %(op_wb)s;
493        }
494
495        return fault;
496    }
497}};
498
499def template StoreInitiateAcc {{
500    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
501                                      Trace::InstRecord *traceData) const
502    {
503        Addr EA;
504        Fault fault = NoFault;
505
506        %(fp_enable_check)s;
507        %(op_decl)s;
508        %(op_rd)s;
509        %(ea_code)s;
510
511        if (fault == NoFault) {
512            %(memacc_code)s;
513        }
514
515        if (fault == NoFault) {
516            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
517                              memAccessFlags, NULL);
518            if (traceData) { traceData->setData(Mem); }
519        }
520
521        return fault;
522    }
523}};
524
525
526def template StoreCompleteAcc {{
527    Fault %(class_name)s::completeAcc(Packet *pkt,
528                                      %(CPU_exec_context)s *xc,
529                                      Trace::InstRecord *traceData) const
530    {
531        Fault fault = NoFault;
532
533        %(fp_enable_check)s;
534        %(op_dest_decl)s;
535
536        if (fault == NoFault) {
537            %(postacc_code)s;
538        }
539
540        if (fault == NoFault) {
541            %(op_wb)s;
542
543            if (traceData) { traceData->setData(getStoreData(xc, pkt)); }
544        }
545
546        return fault;
547    }
548}};
549
550def template StoreCondCompleteAcc {{
551    Fault %(class_name)s::completeAcc(Packet *pkt,
552                                      %(CPU_exec_context)s *xc,
553                                      Trace::InstRecord *traceData) const
554    {
555        Fault fault = NoFault;
556
557        %(fp_enable_check)s;
558        %(op_dest_decl)s;
559
560        uint64_t write_result = pkt->req->getExtraData();
561
562        if (fault == NoFault) {
563            %(postacc_code)s;
564        }
565
566        if (fault == NoFault) {
567            %(op_wb)s;
568        }
569
570        return fault;
571    }
572}};
573
574
575def template MiscMemAccExecute {{
576    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
577                                          Trace::InstRecord *traceData) const
578    {
579        Addr EA;
580        Fault fault = NoFault;
581
582        %(fp_enable_check)s;
583        %(op_decl)s;
584        %(op_rd)s;
585        EA = xc->getEA();
586
587        if (fault == NoFault) {
588            %(memacc_code)s;
589        }
590
591        return NoFault;
592    }
593}};
594
595def template MiscExecute {{
596    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
597                                  Trace::InstRecord *traceData) const
598    {
599        Addr EA;
600        Fault fault = NoFault;
601
602        %(fp_enable_check)s;
603        %(op_decl)s;
604        %(op_rd)s;
605        %(ea_code)s;
606
607        if (fault == NoFault) {
608            %(memacc_code)s;
609        }
610
611        return NoFault;
612    }
613}};
614
615def template MiscInitiateAcc {{
616    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
617                                      Trace::InstRecord *traceData) const
618    {
619        panic("Misc instruction does not support split access method!");
620        return NoFault;
621    }
622}};
623
624
625def template MiscCompleteAcc {{
626    Fault %(class_name)s::completeAcc(Packet *pkt,
627                                      %(CPU_exec_context)s *xc,
628                                      Trace::InstRecord *traceData) const
629    {
630        panic("Misc instruction does not support split access method!");
631
632        return NoFault;
633    }
634}};
635
636
637def template MiscMemAccSize {{
638    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
639    {
640        panic("Misc instruction does not support split access method!");
641        return 0;
642    }
643}};
644
645def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
646                     mem_flags = [], inst_flags = []) {{
647    (header_output, decoder_output, decode_block, exec_output) = \
648        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
649                      decode_template = ImmNopCheckDecode,
650                      exec_template_base = 'Load')
651}};
652
653def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
654                     mem_flags = [], inst_flags = []) {{
655    (header_output, decoder_output, decode_block, exec_output) = \
656        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
657                      exec_template_base = 'Store')
658}};
659
660def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
661                     mem_flags = [], inst_flags = []) {{
662    (header_output, decoder_output, decode_block, exec_output) = \
663        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
664                      decode_template = ImmNopCheckDecode,
665                      exec_template_base = 'Load')
666}};
667
668def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
669                     mem_flags = [], inst_flags = []) {{
670    (header_output, decoder_output, decode_block, exec_output) = \
671        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
672                      exec_template_base = 'Store')
673}};
674
675def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
676                     mem_flags = [], inst_flags = []) {{
677    decl_code = 'uint32_t mem_word = Mem.uw;\n'
678    decl_code += 'uint32_t unalign_addr = Rs + disp;\n'
679    decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n'
680    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
681    decl_code += '\tbyte_offset ^= 3;\n'
682    decl_code += '#endif\n'
683
684    memacc_code = decl_code + memacc_code
685
686    (header_output, decoder_output, decode_block, exec_output) = \
687        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
688                      decode_template = ImmNopCheckDecode,
689                      exec_template_base = 'Load')
690}};
691
692def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
693                     mem_flags = [], inst_flags = []) {{
694    decl_code = 'uint32_t mem_word = 0;\n'
695    decl_code += 'uint32_t unaligned_addr = Rs + disp;\n'
696    decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n'
697    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
698    decl_code += '\tbyte_offset ^= 3;\n'
699    decl_code += '#endif\n'
700    decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n'
701    #decl_code += 'xc->readFunctional(EA,(uint32_t&)mem_word);'
702    memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n'
703
704    (header_output, decoder_output, decode_block, exec_output) = \
705        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
706                      exec_template_base = 'Store')
707}};
708
709def format Prefetch(ea_code = {{ EA = Rs + disp; }},
710                          mem_flags = [], pf_flags = [], inst_flags = []) {{
711    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
712    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
713                                  'IsDataPrefetch', 'MemReadOp']
714
715    (header_output, decoder_output, decode_block, exec_output) = \
716        LoadStoreBase(name, Name, ea_code,
717                      'xc->prefetch(EA, memAccessFlags);',
718                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
719
720}};
721
722def format StoreCond(memacc_code, postacc_code,
723                     ea_code = {{ EA = Rs + disp; }},
724                     mem_flags = [], inst_flags = []) {{
725    (header_output, decoder_output, decode_block, exec_output) = \
726        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
727                      postacc_code, exec_template_base = 'StoreCond')
728}};
729