mem.isa revision 4673
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        uint64_t write_result = 0;
373
374        %(fp_enable_check)s;
375        %(op_decl)s;
376        %(op_rd)s;
377
378        EA = xc->getEA();
379
380        if (fault == NoFault) {
381            %(memacc_code)s;
382        }
383
384        if (fault == NoFault) {
385            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
386                              memAccessFlags, &write_result);
387            // @NOTE: Need to Call Complete Access to Set Trace Data
388            //if (traceData) { traceData->setData(Mem); }
389        }
390
391        return fault;
392    }
393}};
394
395def template StoreCondMemAccExecute {{
396    Fault
397    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
398                                   Trace::InstRecord *traceData) const
399    {
400        Addr EA;
401        Fault fault = NoFault;
402        uint64_t write_result = 0;
403
404        %(fp_enable_check)s;
405        %(op_decl)s;
406        %(op_rd)s;
407        EA = xc->getEA();
408
409        if (fault == NoFault) {
410            %(memacc_code)s;
411        }
412
413        if (fault == NoFault) {
414            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
415                              memAccessFlags, &write_result);
416            if (traceData) { traceData->setData(Mem); }
417        }
418
419        if (fault == NoFault) {
420            %(postacc_code)s;
421        }
422
423        if (fault == NoFault) {
424            %(op_wb)s;
425        }
426
427        return fault;
428    }
429}};
430
431def template StoreExecute {{
432    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
433                                  Trace::InstRecord *traceData) const
434    {
435        Addr EA;
436        Fault fault = NoFault;
437        uint64_t write_result = 0;
438
439        %(fp_enable_check)s;
440        %(op_decl)s;
441        %(op_rd)s;
442        %(ea_code)s;
443
444        if (fault == NoFault) {
445            %(memacc_code)s;
446        }
447
448        if (fault == NoFault) {
449            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
450                              memAccessFlags, &write_result);
451            if (traceData) { traceData->setData(Mem); }
452        }
453
454        if (fault == NoFault) {
455            %(postacc_code)s;
456        }
457
458        if (fault == NoFault) {
459            %(op_wb)s;
460        }
461
462        return fault;
463    }
464}};
465
466def template StoreCondExecute {{
467    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
468                                  Trace::InstRecord *traceData) const
469    {
470        Addr EA;
471        Fault fault = NoFault;
472        uint64_t write_result = 0;
473
474        %(fp_enable_check)s;
475        %(op_decl)s;
476        %(op_rd)s;
477        %(ea_code)s;
478
479        if (fault == NoFault) {
480            %(memacc_code)s;
481        }
482
483        if (fault == NoFault) {
484            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
485                              memAccessFlags, &write_result);
486            if (traceData) { traceData->setData(Mem); }
487        }
488
489        if (fault == NoFault) {
490            %(postacc_code)s;
491        }
492
493        if (fault == NoFault) {
494            %(op_wb)s;
495        }
496
497        return fault;
498    }
499}};
500
501def template StoreInitiateAcc {{
502    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
503                                      Trace::InstRecord *traceData) const
504    {
505        Addr EA;
506        Fault fault = NoFault;
507
508        %(fp_enable_check)s;
509        %(op_decl)s;
510        %(op_rd)s;
511        %(ea_code)s;
512
513        if (fault == NoFault) {
514            %(memacc_code)s;
515        }
516
517        if (fault == NoFault) {
518            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
519                              memAccessFlags, NULL);
520            if (traceData) { traceData->setData(Mem); }
521        }
522
523        return fault;
524    }
525}};
526
527
528def template StoreCompleteAcc {{
529    Fault %(class_name)s::completeAcc(Packet *pkt,
530                                      %(CPU_exec_context)s *xc,
531                                      Trace::InstRecord *traceData) const
532    {
533        Fault fault = NoFault;
534
535        %(fp_enable_check)s;
536        %(op_dest_decl)s;
537
538        if (fault == NoFault) {
539            %(postacc_code)s;
540        }
541
542        if (fault == NoFault) {
543            %(op_wb)s;
544
545            if (traceData) { traceData->setData(getStoreData(xc, pkt)); }
546        }
547
548        return fault;
549    }
550}};
551
552def template StoreCondCompleteAcc {{
553    Fault %(class_name)s::completeAcc(Packet *pkt,
554                                      %(CPU_exec_context)s *xc,
555                                      Trace::InstRecord *traceData) const
556    {
557        Fault fault = NoFault;
558
559        %(fp_enable_check)s;
560        %(op_dest_decl)s;
561
562        uint64_t write_result = pkt->req->getExtraData();
563
564        if (fault == NoFault) {
565            %(postacc_code)s;
566        }
567
568        if (fault == NoFault) {
569            %(op_wb)s;
570        }
571
572        return fault;
573    }
574}};
575
576
577def template MiscMemAccExecute {{
578    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
579                                          Trace::InstRecord *traceData) const
580    {
581        Addr EA;
582        Fault fault = NoFault;
583
584        %(fp_enable_check)s;
585        %(op_decl)s;
586        %(op_rd)s;
587        EA = xc->getEA();
588
589        if (fault == NoFault) {
590            %(memacc_code)s;
591        }
592
593        return NoFault;
594    }
595}};
596
597def template MiscExecute {{
598    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
599                                  Trace::InstRecord *traceData) const
600    {
601        Addr EA;
602        Fault fault = NoFault;
603
604        %(fp_enable_check)s;
605        %(op_decl)s;
606        %(op_rd)s;
607        %(ea_code)s;
608
609        if (fault == NoFault) {
610            %(memacc_code)s;
611        }
612
613        return NoFault;
614    }
615}};
616
617def template MiscInitiateAcc {{
618    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
619                                      Trace::InstRecord *traceData) const
620    {
621        panic("Misc instruction does not support split access method!");
622        return NoFault;
623    }
624}};
625
626
627def template MiscCompleteAcc {{
628    Fault %(class_name)s::completeAcc(Packet *pkt,
629                                      %(CPU_exec_context)s *xc,
630                                      Trace::InstRecord *traceData) const
631    {
632        panic("Misc instruction does not support split access method!");
633
634        return NoFault;
635    }
636}};
637
638
639def template MiscMemAccSize {{
640    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
641    {
642        panic("Misc instruction does not support split access method!");
643        return 0;
644    }
645}};
646
647def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
648                     mem_flags = [], inst_flags = []) {{
649    (header_output, decoder_output, decode_block, exec_output) = \
650        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
651                      decode_template = ImmNopCheckDecode,
652                      exec_template_base = 'Load')
653}};
654
655def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
656                     mem_flags = [], inst_flags = []) {{
657    (header_output, decoder_output, decode_block, exec_output) = \
658        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
659                      exec_template_base = 'Store')
660}};
661
662def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
663                     mem_flags = [], inst_flags = []) {{
664    (header_output, decoder_output, decode_block, exec_output) = \
665        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
666                      decode_template = ImmNopCheckDecode,
667                      exec_template_base = 'Load')
668}};
669
670def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
671                     mem_flags = [], inst_flags = []) {{
672    (header_output, decoder_output, decode_block, exec_output) = \
673        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
674                      exec_template_base = 'Store')
675}};
676
677def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
678                     mem_flags = [], inst_flags = []) {{
679    decl_code = 'uint32_t mem_word = Mem.uw;\n'
680    decl_code += 'uint32_t unalign_addr = Rs + disp;\n'
681    decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n'
682    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
683    decl_code += '\tbyte_offset ^= 3;\n'
684    decl_code += '#endif\n'
685
686    memacc_code = decl_code + memacc_code
687
688    (header_output, decoder_output, decode_block, exec_output) = \
689        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
690                      decode_template = ImmNopCheckDecode,
691                      exec_template_base = 'Load')
692}};
693
694def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
695                     mem_flags = [], inst_flags = []) {{
696    decl_code = 'uint32_t mem_word = 0;\n'
697    decl_code += 'uint32_t unaligned_addr = Rs + disp;\n'
698    decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n'
699    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
700    decl_code += '\tbyte_offset ^= 3;\n'
701    decl_code += '#endif\n'
702    decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n'
703    #decl_code += 'xc->readFunctional(EA,(uint32_t&)mem_word);'
704    memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n'
705
706    (header_output, decoder_output, decode_block, exec_output) = \
707        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
708                      exec_template_base = 'Store')
709}};
710
711def format Prefetch(ea_code = {{ EA = Rs + disp; }},
712                          mem_flags = [], pf_flags = [], inst_flags = []) {{
713    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
714    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
715                                  'IsDataPrefetch', 'MemReadOp']
716
717    (header_output, decoder_output, decode_block, exec_output) = \
718        LoadStoreBase(name, Name, ea_code,
719                      'xc->prefetch(EA, memAccessFlags);',
720                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
721
722}};
723
724def format StoreCond(memacc_code, postacc_code,
725                     ea_code = {{ EA = Rs + disp; }},
726                     mem_flags = [], inst_flags = []) {{
727    (header_output, decoder_output, decode_block, exec_output) = \
728        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
729                      postacc_code, exec_template_base = 'StoreCond')
730}};
731