mem.isa revision 2095
12SN/A// -*- mode:c++ -*-
21762SN/A
32SN/A// Copyright (c) 2003-2005 The Regents of The University of Michigan
42SN/A// All rights reserved.
52SN/A//
62SN/A// Redistribution and use in source and binary forms, with or without
72SN/A// modification, are permitted provided that the following conditions are
82SN/A// met: redistributions of source code must retain the above copyright
92SN/A// notice, this list of conditions and the following disclaimer;
102SN/A// redistributions in binary form must reproduce the above copyright
112SN/A// notice, this list of conditions and the following disclaimer in the
122SN/A// documentation and/or other materials provided with the distribution;
132SN/A// neither the name of the copyright holders nor the names of its
142SN/A// contributors may be used to endorse or promote products derived from
152SN/A// this software without specific prior written permission.
162SN/A//
172SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272665Ssaidi@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu
292665Ssaidi@eecs.umich.eduoutput header {{
302SN/A    /**
312SN/A     * Base class for general Alpha memory-format instructions.
322SN/A     */
332SN/A    class Memory : public AlphaStaticInst
342SN/A    {
352147SN/A      protected:
362147SN/A
372174SN/A        /// Memory request flags.  See mem_req_base.hh.
382147SN/A        unsigned memAccessFlags;
392680Sktlim@umich.edu        /// Pointer to EAComp object.
402132SN/A        const StaticInstPtr<AlphaISA> eaCompPtr;
412147SN/A        /// Pointer to MemAcc object.
422132SN/A        const StaticInstPtr<AlphaISA> memAccPtr;
432147SN/A
445999Snate@binkert.org        /// Constructor
452147SN/A        Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
462147SN/A               StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
472147SN/A               StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
482147SN/A            : AlphaStaticInst(mnem, _machInst, __opClass),
492147SN/A              memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
502147SN/A        {
512147SN/A        }
522147SN/A
532147SN/A        std::string
542090SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
552147SN/A
564695Sgblack@eecs.umich.edu      public:
572680Sktlim@umich.edu
582201SN/A        const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
592201SN/A        const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
604695Sgblack@eecs.umich.edu    };
614695Sgblack@eecs.umich.edu
622SN/A    /**
632SN/A     * Base class for memory-format instructions using a 32-bit
642168SN/A     * displacement (i.e. most of them).
652168SN/A     */
662612SN/A    class MemoryDisp32 : public Memory
672612SN/A    {
682612SN/A      protected:
692612SN/A        /// Displacement for EA calculation (signed).
702612SN/A        int32_t disp;
712612SN/A
722612SN/A        /// Constructor.
732612SN/A        MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass,
742612SN/A                     StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
754695Sgblack@eecs.umich.edu                     StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
762680Sktlim@umich.edu            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
772612SN/A              disp(MEMDISP)
782612SN/A        {
794183Sgblack@eecs.umich.edu        }
805004Sgblack@eecs.umich.edu    };
814183Sgblack@eecs.umich.edu
824183Sgblack@eecs.umich.edu
834183Sgblack@eecs.umich.edu    /**
844183Sgblack@eecs.umich.edu     * Base class for a few miscellaneous memory-format insts
855004Sgblack@eecs.umich.edu     * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
865004Sgblack@eecs.umich.edu     * None of these instructions has a destination register either.
875004Sgblack@eecs.umich.edu     */
885004Sgblack@eecs.umich.edu    class MemoryNoDisp : public Memory
895004Sgblack@eecs.umich.edu    {
905004Sgblack@eecs.umich.edu      protected:
915004Sgblack@eecs.umich.edu        /// Constructor
925004Sgblack@eecs.umich.edu        MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
935004Sgblack@eecs.umich.edu                     StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
945004Sgblack@eecs.umich.edu                     StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
955004Sgblack@eecs.umich.edu            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
965004Sgblack@eecs.umich.edu        {
974183Sgblack@eecs.umich.edu        }
984183Sgblack@eecs.umich.edu
994183Sgblack@eecs.umich.edu        std::string
1004183Sgblack@eecs.umich.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1012SN/A    };
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(MachInst 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(MachInst machInst);
157
158            %(BasicExecDeclare)s
159        };
160
161      public:
162
163        /// Constructor.
164        %(class_name)s(MachInst 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(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
182}};
183
184
185def template LoadStoreConstructor {{
186    /** TODO: change op_class to AddrGenOp or something (requires
187     * creating new member of OpClass enum in op_class.hh, updating
188     * config files, etc.). */
189    inline %(class_name)s::EAComp::EAComp(MachInst machInst)
190        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
191    {
192        %(ea_constructor)s;
193    }
194
195    inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
196        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
197    {
198        %(memacc_constructor)s;
199    }
200
201    inline %(class_name)s::%(class_name)s(MachInst machInst)
202         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
203                          new EAComp(machInst), new MemAcc(machInst))
204    {
205        %(constructor)s;
206    }
207}};
208
209
210def template EACompExecute {{
211    Fault
212    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
213                                   Trace::InstRecord *traceData) const
214    {
215        Addr EA;
216        Fault fault = No_Fault;
217
218        %(fp_enable_check)s;
219        %(op_decl)s;
220        %(op_rd)s;
221        %(code)s;
222
223        if (fault == No_Fault) {
224            %(op_wb)s;
225            xc->setEA(EA);
226        }
227
228        return fault;
229    }
230}};
231
232def template LoadMemAccExecute {{
233    Fault
234    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
235                                   Trace::InstRecord *traceData) const
236    {
237        Addr EA;
238        Fault fault = No_Fault;
239
240        %(fp_enable_check)s;
241        %(op_decl)s;
242        %(op_rd)s;
243        EA = xc->getEA();
244
245        if (fault == No_Fault) {
246            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
247            %(code)s;
248        }
249
250        if (fault == No_Fault) {
251            %(op_wb)s;
252        }
253
254        return fault;
255    }
256}};
257
258
259def template LoadExecute {{
260    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
261                                  Trace::InstRecord *traceData) const
262    {
263        Addr EA;
264        Fault fault = No_Fault;
265
266        %(fp_enable_check)s;
267        %(op_decl)s;
268        %(op_rd)s;
269        %(ea_code)s;
270
271        if (fault == No_Fault) {
272            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
273            %(memacc_code)s;
274        }
275
276        if (fault == No_Fault) {
277            %(op_wb)s;
278        }
279
280        return fault;
281    }
282}};
283
284
285def template LoadInitiateAcc {{
286    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
287                                      Trace::InstRecord *traceData) const
288    {
289        Addr EA;
290        Fault fault = No_Fault;
291        %(mem_acc_type)s Mem = 0;
292
293        %(fp_enable_check)s;
294        %(op_src_decl)s;
295        %(op_rd)s;
296        %(ea_code)s;
297
298        if (fault == No_Fault) {
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(uint8_t *data,
309                                      %(CPU_exec_context)s *xc,
310                                      Trace::InstRecord *traceData) const
311    {
312        Fault fault = No_Fault;
313        %(mem_acc_type)s Mem = 0;
314
315        %(fp_enable_check)s;
316        %(op_dest_decl)s;
317
318        memcpy(&Mem, data, sizeof(Mem));
319
320        if (fault == No_Fault) {
321            %(memacc_code)s;
322        }
323
324        if (fault == No_Fault) {
325            %(op_wb)s;
326        }
327
328        return fault;
329    }
330}};
331
332
333def template StoreMemAccExecute {{
334    Fault
335    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
336                                   Trace::InstRecord *traceData) const
337    {
338        Addr EA;
339        Fault fault = No_Fault;
340        uint64_t write_result = 0;
341
342        %(fp_enable_check)s;
343        %(op_decl)s;
344        %(op_rd)s;
345        EA = xc->getEA();
346
347        if (fault == No_Fault) {
348            %(code)s;
349        }
350
351        if (fault == No_Fault) {
352            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
353                              memAccessFlags, &write_result);
354            if (traceData) { traceData->setData(Mem); }
355        }
356
357        if (fault == No_Fault) {
358            %(postacc_code)s;
359        }
360
361        if (fault == No_Fault) {
362            %(op_wb)s;
363        }
364
365        return fault;
366    }
367}};
368
369
370def template StoreExecute {{
371    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
372                                  Trace::InstRecord *traceData) const
373    {
374        Addr EA;
375        Fault fault = No_Fault;
376        uint64_t write_result = 0;
377
378        %(fp_enable_check)s;
379        %(op_decl)s;
380        %(op_rd)s;
381        %(ea_code)s;
382
383        if (fault == No_Fault) {
384            %(memacc_code)s;
385        }
386
387        if (fault == No_Fault) {
388            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
389                              memAccessFlags, &write_result);
390            if (traceData) { traceData->setData(Mem); }
391        }
392
393        if (fault == No_Fault) {
394            %(postacc_code)s;
395        }
396
397        if (fault == No_Fault) {
398            %(op_wb)s;
399        }
400
401        return fault;
402    }
403}};
404
405def template StoreInitiateAcc {{
406    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
407                                      Trace::InstRecord *traceData) const
408    {
409        Addr EA;
410        Fault fault = No_Fault;
411        uint64_t write_result = 0;
412        %(mem_acc_type)s Mem = 0;
413
414        %(fp_enable_check)s;
415        %(op_src_decl)s;
416        %(op_rd)s;
417        %(ea_code)s;
418
419        if (fault == No_Fault) {
420            %(memacc_code)s;
421        }
422
423        if (fault == No_Fault) {
424            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
425                              memAccessFlags, &write_result);
426            if (traceData) { traceData->setData(Mem); }
427        }
428
429        return fault;
430    }
431}};
432
433
434def template StoreCompleteAcc {{
435    Fault %(class_name)s::completeAcc(uint8_t *data,
436                                      %(CPU_exec_context)s *xc,
437                                      Trace::InstRecord *traceData) const
438    {
439        Fault fault = No_Fault;
440        uint64_t write_result = 0;
441
442        %(fp_enable_check)s;
443        %(op_dest_decl)s;
444
445        memcpy(&write_result, data, sizeof(write_result));
446
447        if (fault == No_Fault) {
448            %(postacc_code)s;
449        }
450
451        if (fault == No_Fault) {
452            %(op_wb)s;
453        }
454
455        return fault;
456    }
457}};
458
459
460def template MiscMemAccExecute {{
461    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
462                                          Trace::InstRecord *traceData) const
463    {
464        Addr EA;
465        Fault fault = No_Fault;
466
467        %(fp_enable_check)s;
468        %(op_decl)s;
469        %(op_rd)s;
470        EA = xc->getEA();
471
472        if (fault == No_Fault) {
473            %(code)s;
474        }
475
476        return No_Fault;
477    }
478}};
479
480def template MiscExecute {{
481    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
482                                  Trace::InstRecord *traceData) const
483    {
484        Addr EA;
485        Fault fault = No_Fault;
486
487        %(fp_enable_check)s;
488        %(op_decl)s;
489        %(op_rd)s;
490        %(ea_code)s;
491
492        if (fault == No_Fault) {
493            %(memacc_code)s;
494        }
495
496        return No_Fault;
497    }
498}};
499
500def template MiscInitiateAcc {{
501    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
502                                      Trace::InstRecord *traceData) const
503    {
504        Addr EA;
505        Fault fault = No_Fault;
506
507        %(fp_enable_check)s;
508        %(op_decl)s;
509        %(op_rd)s;
510        %(ea_code)s;
511
512        if (fault == No_Fault) {
513            %(memacc_code)s;
514        }
515
516        return No_Fault;
517    }
518}};
519
520
521def template MiscCompleteAcc {{
522    Fault %(class_name)s::completeAcc(uint8_t *data,
523                                      %(CPU_exec_context)s *xc,
524                                      Trace::InstRecord *traceData) const
525    {
526        return No_Fault;
527    }
528}};
529
530// load instructions use Ra as dest, so check for
531// Ra == 31 to detect nops
532def template LoadNopCheckDecode {{
533 {
534     AlphaStaticInst *i = new %(class_name)s(machInst);
535     if (RA == 31) {
536         i = makeNop(i);
537     }
538     return i;
539 }
540}};
541
542
543// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
544def template LoadPrefetchCheckDecode {{
545 {
546     if (RA != 31) {
547         return new %(class_name)s(machInst);
548     }
549     else {
550         return new %(class_name)sPrefetch(machInst);
551     }
552 }
553}};
554
555
556let {{
557def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
558                  postacc_code = '', base_class = 'MemoryDisp32',
559                  decode_template = BasicDecode, exec_template_base = ''):
560    # Make sure flags are in lists (convert to lists if not).
561    mem_flags = makeList(mem_flags)
562    inst_flags = makeList(inst_flags)
563
564    # add hook to get effective addresses into execution trace output.
565    ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
566
567    # generate code block objects
568    ea_cblk = CodeBlock(ea_code)
569    memacc_cblk = CodeBlock(memacc_code)
570    postacc_cblk = CodeBlock(postacc_code)
571
572    # Some CPU models execute the memory operation as an atomic unit,
573    # while others want to separate them into an effective address
574    # computation and a memory access operation.  As a result, we need
575    # to generate three StaticInst objects.  Note that the latter two
576    # are nested inside the larger "atomic" one.
577
578    # generate InstObjParams for EAComp object
579    ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
580
581    # generate InstObjParams for MemAcc object
582    memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
583    # in the split execution model, the MemAcc portion is responsible
584    # for the post-access code.
585    memacc_iop.postacc_code = postacc_cblk.code
586
587    # generate InstObjParams for unified execution
588    cblk = CodeBlock(ea_code + memacc_code + postacc_code)
589    iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
590
591    iop.ea_constructor = ea_cblk.constructor
592    iop.ea_code = ea_cblk.code
593    iop.memacc_constructor = memacc_cblk.constructor
594    iop.memacc_code = memacc_cblk.code
595    iop.postacc_code = postacc_cblk.code
596
597    if mem_flags:
598        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
599        iop.constructor += s
600        memacc_iop.constructor += s
601
602    # select templates
603    memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
604    fullExecTemplate = eval(exec_template_base + 'Execute')
605    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
606    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
607
608    # (header_output, decoder_output, decode_block, exec_output)
609    return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
610            decode_template.subst(iop),
611            EACompExecute.subst(ea_iop)
612            + memAccExecTemplate.subst(memacc_iop)
613            + fullExecTemplate.subst(iop)
614            + initiateAccTemplate.subst(iop)
615            + completeAccTemplate.subst(iop))
616}};
617
618
619def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
620                     mem_flags = [], inst_flags = []) {{
621    (header_output, decoder_output, decode_block, exec_output) = \
622        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
623                      decode_template = LoadNopCheckDecode,
624                      exec_template_base = 'Load')
625}};
626
627
628// Note that the flags passed in apply only to the prefetch version
629def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
630                          mem_flags = [], pf_flags = [], inst_flags = []) {{
631    # declare the load instruction object and generate the decode block
632    (header_output, decoder_output, decode_block, exec_output) = \
633        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
634                      decode_template = LoadPrefetchCheckDecode,
635                      exec_template_base = 'Load')
636
637    # Declare the prefetch instruction object.
638
639    # Make sure flag args are lists so we can mess with them.
640    mem_flags = makeList(mem_flags)
641    pf_flags = makeList(pf_flags)
642    inst_flags = makeList(inst_flags)
643
644    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
645    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
646                                  'IsDataPrefetch', 'MemReadOp']
647
648    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
649        LoadStoreBase(name, Name + 'Prefetch', ea_code,
650                      'xc->prefetch(EA, memAccessFlags);',
651                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
652
653    header_output += pf_header_output
654    decoder_output += pf_decoder_output
655    exec_output += pf_exec_output
656}};
657
658
659def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
660                 mem_flags = [], inst_flags = []) {{
661    (header_output, decoder_output, decode_block, exec_output) = \
662        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
663                      exec_template_base = 'Store')
664}};
665
666
667def format StoreCond(memacc_code, postacc_code,
668                     ea_code = {{ EA = Rb + disp; }},
669                     mem_flags = [], inst_flags = []) {{
670    (header_output, decoder_output, decode_block, exec_output) = \
671        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
672                      postacc_code, exec_template_base = 'Store')
673}};
674
675
676// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
677def format MiscPrefetch(ea_code, memacc_code,
678                        mem_flags = [], inst_flags = []) {{
679    (header_output, decoder_output, decode_block, exec_output) = \
680        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
681                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
682}};
683
684
685