mem.isa revision 4056
1// -*- mode:c++ -*-
2
3// Copyright (c) 2003-2005 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//          Kevin Lim
31
32////////////////////////////////////////////////////////////////////
33//
34// Memory-format instructions: LoadAddress, Load, Store
35//
36
37output header {{
38    /**
39     * Base class for general Alpha memory-format instructions.
40     */
41    class Memory : public AlphaStaticInst
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        /// Constructor
53        Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
54               StaticInstPtr _eaCompPtr = nullStaticInstPtr,
55               StaticInstPtr _memAccPtr = nullStaticInstPtr)
56            : AlphaStaticInst(mnem, _machInst, __opClass),
57              memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
58        {
59        }
60
61        std::string
62        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
63
64      public:
65
66        const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
67        const StaticInstPtr &memAccInst() const { return memAccPtr; }
68    };
69
70    /**
71     * Base class for memory-format instructions using a 32-bit
72     * displacement (i.e. most of them).
73     */
74    class MemoryDisp32 : public Memory
75    {
76      protected:
77        /// Displacement for EA calculation (signed).
78        int32_t disp;
79
80        /// Constructor.
81        MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
82                     StaticInstPtr _eaCompPtr = nullStaticInstPtr,
83                     StaticInstPtr _memAccPtr = nullStaticInstPtr)
84            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
85              disp(MEMDISP)
86        {
87        }
88    };
89
90
91    /**
92     * Base class for a few miscellaneous memory-format insts
93     * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
94     * None of these instructions has a destination register either.
95     */
96    class MemoryNoDisp : public Memory
97    {
98      protected:
99        /// Constructor
100        MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
101                     StaticInstPtr _eaCompPtr = nullStaticInstPtr,
102                     StaticInstPtr _memAccPtr = nullStaticInstPtr)
103            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
104        {
105        }
106
107        std::string
108        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
109    };
110}};
111
112
113output decoder {{
114    std::string
115    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
116    {
117        return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
118                        flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
119    }
120
121    std::string
122    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
123    {
124        return csprintf("%-10s (r%d)", mnemonic, RB);
125    }
126}};
127
128def format LoadAddress(code) {{
129    iop = InstObjParams(name, Name, 'MemoryDisp32', code)
130    header_output = BasicDeclare.subst(iop)
131    decoder_output = BasicConstructor.subst(iop)
132    decode_block = BasicDecode.subst(iop)
133    exec_output = BasicExecute.subst(iop)
134}};
135
136
137def template LoadStoreDeclare {{
138    /**
139     * Static instruction class for "%(mnemonic)s".
140     */
141    class %(class_name)s : public %(base_class)s
142    {
143      protected:
144
145        /**
146         * "Fake" effective address computation class for "%(mnemonic)s".
147         */
148        class EAComp : public %(base_class)s
149        {
150          public:
151            /// Constructor
152            EAComp(ExtMachInst machInst);
153
154            %(BasicExecDeclare)s
155        };
156
157        /**
158         * "Fake" memory access instruction class for "%(mnemonic)s".
159         */
160        class MemAcc : public %(base_class)s
161        {
162          public:
163            /// Constructor
164            MemAcc(ExtMachInst machInst);
165
166            %(BasicExecDeclare)s
167        };
168
169      public:
170
171        /// Constructor.
172        %(class_name)s(ExtMachInst machInst);
173
174        %(BasicExecDeclare)s
175
176        %(InitiateAccDeclare)s
177
178        %(CompleteAccDeclare)s
179    };
180}};
181
182
183def template InitiateAccDeclare {{
184    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
185}};
186
187
188def template CompleteAccDeclare {{
189    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *,
190                      Trace::InstRecord *) const;
191}};
192
193
194def template EACompConstructor {{
195    /** TODO: change op_class to AddrGenOp or something (requires
196     * creating new member of OpClass enum in op_class.hh, updating
197     * config files, etc.). */
198    inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
199        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
200    {
201        %(constructor)s;
202    }
203}};
204
205
206def template MemAccConstructor {{
207    inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
208        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
209    {
210        %(constructor)s;
211    }
212}};
213
214
215def template LoadStoreConstructor {{
216    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
217         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
218                          new EAComp(machInst), new MemAcc(machInst))
219    {
220        %(constructor)s;
221    }
222}};
223
224
225def template EACompExecute {{
226    Fault
227    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
228                                   Trace::InstRecord *traceData) const
229    {
230        Addr EA;
231        Fault fault = NoFault;
232
233        %(fp_enable_check)s;
234        %(op_decl)s;
235        %(op_rd)s;
236        %(ea_code)s;
237
238        if (fault == NoFault) {
239            %(op_wb)s;
240            xc->setEA(EA);
241        }
242
243        return fault;
244    }
245}};
246
247def template LoadMemAccExecute {{
248    Fault
249    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
250                                   Trace::InstRecord *traceData) const
251    {
252        Addr EA;
253        Fault fault = NoFault;
254
255        %(fp_enable_check)s;
256        %(op_decl)s;
257        %(op_rd)s;
258        EA = xc->getEA();
259
260        if (fault == NoFault) {
261            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
262            %(memacc_code)s;
263        }
264
265        if (fault == NoFault) {
266            %(op_wb)s;
267        }
268
269        return fault;
270    }
271}};
272
273
274def template LoadExecute {{
275    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
276                                  Trace::InstRecord *traceData) const
277    {
278        Addr EA;
279        Fault fault = NoFault;
280
281        %(fp_enable_check)s;
282        %(op_decl)s;
283        %(op_rd)s;
284        %(ea_code)s;
285
286        if (fault == NoFault) {
287            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
288            %(memacc_code)s;
289        }
290
291        if (fault == NoFault) {
292            %(op_wb)s;
293        }
294
295        return fault;
296    }
297}};
298
299
300def template LoadInitiateAcc {{
301    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
302                                      Trace::InstRecord *traceData) const
303    {
304        Addr EA;
305        Fault fault = NoFault;
306
307        %(fp_enable_check)s;
308        %(op_src_decl)s;
309        %(op_rd)s;
310        %(ea_code)s;
311
312        if (fault == NoFault) {
313            fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
314        }
315
316        return fault;
317    }
318}};
319
320
321def template LoadCompleteAcc {{
322    Fault %(class_name)s::completeAcc(PacketPtr pkt,
323                                      %(CPU_exec_context)s *xc,
324                                      Trace::InstRecord *traceData) const
325    {
326        Fault fault = NoFault;
327
328        %(fp_enable_check)s;
329        %(op_decl)s;
330
331        Mem = pkt->get<typeof(Mem)>();
332
333        if (fault == NoFault) {
334            %(memacc_code)s;
335        }
336
337        if (fault == NoFault) {
338            %(op_wb)s;
339        }
340
341        return fault;
342    }
343}};
344
345
346def template StoreMemAccExecute {{
347    Fault
348    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
349                                   Trace::InstRecord *traceData) const
350    {
351        Addr EA;
352        Fault fault = NoFault;
353
354        %(fp_enable_check)s;
355        %(op_decl)s;
356        %(op_rd)s;
357        EA = xc->getEA();
358
359        if (fault == NoFault) {
360            %(memacc_code)s;
361        }
362
363        if (fault == NoFault) {
364            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
365                              memAccessFlags, NULL);
366            if (traceData) { traceData->setData(Mem); }
367        }
368
369        if (fault == NoFault) {
370            %(postacc_code)s;
371        }
372
373        if (fault == NoFault) {
374            %(op_wb)s;
375        }
376
377        return fault;
378    }
379}};
380
381def template StoreCondMemAccExecute {{
382    Fault
383    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
384                                   Trace::InstRecord *traceData) const
385    {
386        Addr EA;
387        Fault fault = NoFault;
388        uint64_t write_result = 0;
389
390        %(fp_enable_check)s;
391        %(op_decl)s;
392        %(op_rd)s;
393        EA = xc->getEA();
394
395        if (fault == NoFault) {
396            %(memacc_code)s;
397        }
398
399        if (fault == NoFault) {
400            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
401                              memAccessFlags, &write_result);
402            if (traceData) { traceData->setData(Mem); }
403        }
404
405        if (fault == NoFault) {
406            %(postacc_code)s;
407        }
408
409        if (fault == NoFault) {
410            %(op_wb)s;
411        }
412
413        return fault;
414    }
415}};
416
417
418def template StoreExecute {{
419    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
420                                  Trace::InstRecord *traceData) const
421    {
422        Addr EA;
423        Fault fault = NoFault;
424
425        %(fp_enable_check)s;
426        %(op_decl)s;
427        %(op_rd)s;
428        %(ea_code)s;
429
430        if (fault == NoFault) {
431            %(memacc_code)s;
432        }
433
434        if (fault == NoFault) {
435            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
436                              memAccessFlags, NULL);
437            if (traceData) { traceData->setData(Mem); }
438        }
439
440        if (fault == NoFault) {
441            %(postacc_code)s;
442        }
443
444        if (fault == NoFault) {
445            %(op_wb)s;
446        }
447
448        return fault;
449    }
450}};
451
452def template StoreCondExecute {{
453    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
454                                  Trace::InstRecord *traceData) const
455    {
456        Addr EA;
457        Fault fault = NoFault;
458        uint64_t write_result = 0;
459
460        %(fp_enable_check)s;
461        %(op_decl)s;
462        %(op_rd)s;
463        %(ea_code)s;
464
465        if (fault == NoFault) {
466            %(memacc_code)s;
467        }
468
469        if (fault == NoFault) {
470            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
471                              memAccessFlags, &write_result);
472            if (traceData) { traceData->setData(Mem); }
473        }
474
475        if (fault == NoFault) {
476            %(postacc_code)s;
477        }
478
479        if (fault == NoFault) {
480            %(op_wb)s;
481        }
482
483        return fault;
484    }
485}};
486
487def template StoreInitiateAcc {{
488    Fault %(class_name)s::initiateAcc(%(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        %(ea_code)s;
498
499        if (fault == NoFault) {
500            %(memacc_code)s;
501        }
502
503        if (fault == NoFault) {
504            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
505                              memAccessFlags, NULL);
506            if (traceData) { traceData->setData(Mem); }
507        }
508
509        return fault;
510    }
511}};
512
513
514def template StoreCompleteAcc {{
515    Fault %(class_name)s::completeAcc(PacketPtr pkt,
516                                      %(CPU_exec_context)s *xc,
517                                      Trace::InstRecord *traceData) const
518    {
519        Fault fault = NoFault;
520
521        %(fp_enable_check)s;
522        %(op_dest_decl)s;
523
524        if (fault == NoFault) {
525            %(postacc_code)s;
526        }
527
528        if (fault == NoFault) {
529            %(op_wb)s;
530        }
531
532        return fault;
533    }
534}};
535
536
537def template StoreCondCompleteAcc {{
538    Fault %(class_name)s::completeAcc(PacketPtr pkt,
539                                      %(CPU_exec_context)s *xc,
540                                      Trace::InstRecord *traceData) const
541    {
542        Fault fault = NoFault;
543
544        %(fp_enable_check)s;
545        %(op_dest_decl)s;
546
547        uint64_t write_result = pkt->req->getExtraData();
548
549        if (fault == NoFault) {
550            %(postacc_code)s;
551        }
552
553        if (fault == NoFault) {
554            %(op_wb)s;
555        }
556
557        return fault;
558    }
559}};
560
561
562def template MiscMemAccExecute {{
563    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
564                                          Trace::InstRecord *traceData) const
565    {
566        Addr EA;
567        Fault fault = NoFault;
568
569        %(fp_enable_check)s;
570        %(op_decl)s;
571        %(op_rd)s;
572        EA = xc->getEA();
573
574        if (fault == NoFault) {
575            %(memacc_code)s;
576        }
577
578        return NoFault;
579    }
580}};
581
582def template MiscExecute {{
583    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
584                                  Trace::InstRecord *traceData) const
585    {
586        Addr EA;
587        Fault fault = NoFault;
588
589        %(fp_enable_check)s;
590        %(op_decl)s;
591        %(op_rd)s;
592        %(ea_code)s;
593
594        if (fault == NoFault) {
595            %(memacc_code)s;
596        }
597
598        return NoFault;
599    }
600}};
601
602def template MiscInitiateAcc {{
603    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
604                                      Trace::InstRecord *traceData) const
605    {
606        warn("Misc instruction does not support split access method!");
607        return NoFault;
608    }
609}};
610
611
612def template MiscCompleteAcc {{
613    Fault %(class_name)s::completeAcc(PacketPtr pkt,
614                                      %(CPU_exec_context)s *xc,
615                                      Trace::InstRecord *traceData) const
616    {
617        warn("Misc instruction does not support split access method!");
618
619        return NoFault;
620    }
621}};
622
623// load instructions use Ra as dest, so check for
624// Ra == 31 to detect nops
625def template LoadNopCheckDecode {{
626 {
627     AlphaStaticInst *i = new %(class_name)s(machInst);
628     if (RA == 31) {
629         i = makeNop(i);
630     }
631     return i;
632 }
633}};
634
635
636// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
637def template LoadPrefetchCheckDecode {{
638 {
639     if (RA != 31) {
640         return new %(class_name)s(machInst);
641     }
642     else {
643         return new %(class_name)sPrefetch(machInst);
644     }
645 }
646}};
647
648
649let {{
650def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
651                  postacc_code = '', base_class = 'MemoryDisp32',
652                  decode_template = BasicDecode, exec_template_base = ''):
653    # Make sure flags are in lists (convert to lists if not).
654    mem_flags = makeList(mem_flags)
655    inst_flags = makeList(inst_flags)
656
657    # add hook to get effective addresses into execution trace output.
658    ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
659
660    # Some CPU models execute the memory operation as an atomic unit,
661    # while others want to separate them into an effective address
662    # computation and a memory access operation.  As a result, we need
663    # to generate three StaticInst objects.  Note that the latter two
664    # are nested inside the larger "atomic" one.
665
666    # Generate InstObjParams for each of the three objects.  Note that
667    # they differ only in the set of code objects contained (which in
668    # turn affects the object's overall operand list).
669    iop = InstObjParams(name, Name, base_class,
670                        { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code },
671                        inst_flags)
672    ea_iop = InstObjParams(name, Name, base_class,
673                        { 'ea_code':ea_code },
674                        inst_flags)
675    memacc_iop = InstObjParams(name, Name, base_class,
676                        { 'memacc_code':memacc_code, 'postacc_code':postacc_code },
677                        inst_flags)
678
679    if mem_flags:
680        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
681        iop.constructor += s
682        memacc_iop.constructor += s
683
684    # select templates
685
686    # The InitiateAcc template is the same for StoreCond templates as the
687    # corresponding Store template..
688    StoreCondInitiateAcc = StoreInitiateAcc
689
690    memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
691    fullExecTemplate = eval(exec_template_base + 'Execute')
692    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
693    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
694
695    # (header_output, decoder_output, decode_block, exec_output)
696    return (LoadStoreDeclare.subst(iop),
697            EACompConstructor.subst(ea_iop)
698            + MemAccConstructor.subst(memacc_iop)
699            + LoadStoreConstructor.subst(iop),
700            decode_template.subst(iop),
701            EACompExecute.subst(ea_iop)
702            + memAccExecTemplate.subst(memacc_iop)
703            + fullExecTemplate.subst(iop)
704            + initiateAccTemplate.subst(iop)
705            + completeAccTemplate.subst(iop))
706}};
707
708def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
709                     mem_flags = [], inst_flags = []) {{
710    (header_output, decoder_output, decode_block, exec_output) = \
711        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
712                      decode_template = LoadNopCheckDecode,
713                      exec_template_base = 'Load')
714}};
715
716
717// Note that the flags passed in apply only to the prefetch version
718def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
719                          mem_flags = [], pf_flags = [], inst_flags = []) {{
720    # declare the load instruction object and generate the decode block
721    (header_output, decoder_output, decode_block, exec_output) = \
722        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
723                      decode_template = LoadPrefetchCheckDecode,
724                      exec_template_base = 'Load')
725
726    # Declare the prefetch instruction object.
727
728    # Make sure flag args are lists so we can mess with them.
729    mem_flags = makeList(mem_flags)
730    pf_flags = makeList(pf_flags)
731    inst_flags = makeList(inst_flags)
732
733    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
734    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
735                                  'IsDataPrefetch', 'MemReadOp']
736
737    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
738        LoadStoreBase(name, Name + 'Prefetch', ea_code,
739                      'xc->prefetch(EA, memAccessFlags);',
740                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
741
742    header_output += pf_header_output
743    decoder_output += pf_decoder_output
744    exec_output += pf_exec_output
745}};
746
747
748def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
749                 mem_flags = [], inst_flags = []) {{
750    (header_output, decoder_output, decode_block, exec_output) = \
751        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
752                      exec_template_base = 'Store')
753}};
754
755
756def format StoreCond(memacc_code, postacc_code,
757                     ea_code = {{ EA = Rb + disp; }},
758                     mem_flags = [], inst_flags = []) {{
759    (header_output, decoder_output, decode_block, exec_output) = \
760        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
761                      postacc_code, exec_template_base = 'StoreCond')
762}};
763
764
765// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
766def format MiscPrefetch(ea_code, memacc_code,
767                        mem_flags = [], inst_flags = []) {{
768    (header_output, decoder_output, decode_block, exec_output) = \
769        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
770                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
771}};
772
773
774