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