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