mem.isa revision 2090
18191SN/A// -*- mode:c++ -*-
28191SN/A
38191SN/A// Copyright (c) 2003-2005 The Regents of The University of Michigan
48191SN/A// All rights reserved.
58191SN/A//
68191SN/A// Redistribution and use in source and binary forms, with or without
78191SN/A// modification, are permitted provided that the following conditions are
88191SN/A// met: redistributions of source code must retain the above copyright
98191SN/A// notice, this list of conditions and the following disclaimer;
108191SN/A// redistributions in binary form must reproduce the above copyright
118191SN/A// notice, this list of conditions and the following disclaimer in the
128191SN/A// documentation and/or other materials provided with the distribution;
138191SN/A// neither the name of the copyright holders nor the names of its
148191SN/A// contributors may be used to endorse or promote products derived from
158191SN/A// this software without specific prior written permission.
168191SN/A//
178191SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
188191SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
198191SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
208191SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
218191SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
228191SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
238191SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
248191SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
258191SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
268191SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
278191SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288191SN/A
298191SN/Aoutput header {{
308191SN/A    /**
318191SN/A     * Base class for general Alpha memory-format instructions.
3210441Snilay@cs.wisc.edu     */
3310441Snilay@cs.wisc.edu    class Memory : public AlphaStaticInst
348191SN/A    {
358191SN/A      protected:
368229SN/A
378191SN/A        /// Memory request flags.  See mem_req_base.hh.
388191SN/A        unsigned memAccessFlags;
399230SN/A        /// Pointer to EAComp object.
4010893Snilay@cs.wisc.edu        const StaticInstPtr<AlphaISA> eaCompPtr;
418191SN/A        /// Pointer to MemAcc object.
428191SN/A        const StaticInstPtr<AlphaISA> memAccPtr;
438191SN/A
448191SN/A        /// Constructor
458191SN/A        Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
468191SN/A               StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
478191SN/A               StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
488191SN/A            : AlphaStaticInst(mnem, _machInst, __opClass),
498191SN/A              memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
508191SN/A        {
518191SN/A        }
528191SN/A
538191SN/A        std::string
5410301Snilay@cs.wisc.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
558191SN/A
568191SN/A      public:
578191SN/A
588191SN/A        const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
598191SN/A        const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
608191SN/A    };
618191SN/A
628191SN/A    /**
638191SN/A     * Base class for memory-format instructions using a 32-bit
648191SN/A     * displacement (i.e. most of them).
658191SN/A     */
668191SN/A    class MemoryDisp32 : public Memory
678191SN/A    {
688191SN/A      protected:
698191SN/A        /// Displacement for EA calculation (signed).
708191SN/A        int32_t disp;
718191SN/A
728191SN/A        /// Constructor.
738191SN/A        MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass,
748191SN/A                     StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
7511116Santhony.gutierrez@amd.com                     StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
7611116Santhony.gutierrez@amd.com            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
778191SN/A              disp(MEMDISP)
7811116Santhony.gutierrez@amd.com        {
7911116Santhony.gutierrez@amd.com        }
8011116Santhony.gutierrez@amd.com    };
8111116Santhony.gutierrez@amd.com
828191SN/A
838191SN/A    /**
848191SN/A     * Base class for a few miscellaneous memory-format insts
858191SN/A     * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
868191SN/A     * None of these instructions has a destination register either.
878191SN/A     */
888191SN/A    class MemoryNoDisp : public Memory
898191SN/A    {
908191SN/A      protected:
918191SN/A        /// Constructor
928191SN/A        MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
938191SN/A                     StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
948191SN/A                     StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
958191SN/A            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
9610893Snilay@cs.wisc.edu        {
978191SN/A        }
988191SN/A
999554SN/A        std::string
1009554SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
10110441Snilay@cs.wisc.edu    };
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}};
169
170def template LoadStoreConstructor {{
171    /** TODO: change op_class to AddrGenOp or something (requires
172     * creating new member of OpClass enum in op_class.hh, updating
173     * config files, etc.). */
174    inline %(class_name)s::EAComp::EAComp(MachInst machInst)
175        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
176    {
177        %(ea_constructor)s;
178    }
179
180    inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
181        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
182    {
183        %(memacc_constructor)s;
184    }
185
186    inline %(class_name)s::%(class_name)s(MachInst machInst)
187         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
188                          new EAComp(machInst), new MemAcc(machInst))
189    {
190        %(constructor)s;
191    }
192}};
193
194
195def template EACompExecute {{
196    Fault *
197    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
198                                   Trace::InstRecord *traceData) const
199    {
200        Addr EA;
201        Fault * fault = NoFault;
202
203        %(fp_enable_check)s;
204        %(op_decl)s;
205        %(op_rd)s;
206        %(code)s;
207
208        if (fault == NoFault) {
209            %(op_wb)s;
210            xc->setEA(EA);
211        }
212
213        return fault;
214    }
215}};
216
217def template LoadMemAccExecute {{
218    Fault *
219    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
220                                   Trace::InstRecord *traceData) const
221    {
222        Addr EA;
223        Fault * fault = NoFault;
224
225        %(fp_enable_check)s;
226        %(op_decl)s;
227        %(op_rd)s;
228        EA = xc->getEA();
229
230        if (fault == NoFault) {
231            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
232            %(code)s;
233        }
234
235        if (fault == NoFault) {
236            %(op_wb)s;
237        }
238
239        return fault;
240    }
241}};
242
243
244def template LoadExecute {{
245    Fault * %(class_name)s::execute(%(CPU_exec_context)s *xc,
246                                  Trace::InstRecord *traceData) const
247    {
248        Addr EA;
249        Fault * fault = NoFault;
250
251        %(fp_enable_check)s;
252        %(op_decl)s;
253        %(op_rd)s;
254        %(ea_code)s;
255
256        if (fault == NoFault) {
257            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
258            %(memacc_code)s;
259        }
260
261        if (fault == NoFault) {
262            %(op_wb)s;
263        }
264
265        return fault;
266    }
267}};
268
269
270def template StoreMemAccExecute {{
271    Fault *
272    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
273                                   Trace::InstRecord *traceData) const
274    {
275        Addr EA;
276        Fault * fault = NoFault;
277        uint64_t write_result = 0;
278
279        %(fp_enable_check)s;
280        %(op_decl)s;
281        %(op_rd)s;
282        EA = xc->getEA();
283
284        if (fault == NoFault) {
285            %(code)s;
286        }
287
288        if (fault == NoFault) {
289            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
290                              memAccessFlags, &write_result);
291            if (traceData) { traceData->setData(Mem); }
292        }
293
294        if (fault == NoFault) {
295            %(postacc_code)s;
296        }
297
298        if (fault == NoFault) {
299            %(op_wb)s;
300        }
301
302        return fault;
303    }
304}};
305
306
307def template StoreExecute {{
308    Fault * %(class_name)s::execute(%(CPU_exec_context)s *xc,
309                                  Trace::InstRecord *traceData) const
310    {
311        Addr EA;
312        Fault * fault = NoFault;
313        uint64_t write_result = 0;
314
315        %(fp_enable_check)s;
316        %(op_decl)s;
317        %(op_rd)s;
318        %(ea_code)s;
319
320        if (fault == NoFault) {
321            %(memacc_code)s;
322        }
323
324        if (fault == NoFault) {
325            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
326                              memAccessFlags, &write_result);
327            if (traceData) { traceData->setData(Mem); }
328        }
329
330        if (fault == NoFault) {
331            %(postacc_code)s;
332        }
333
334        if (fault == NoFault) {
335            %(op_wb)s;
336        }
337
338        return fault;
339    }
340}};
341
342
343def template MiscMemAccExecute {{
344    Fault * %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
345                                          Trace::InstRecord *traceData) const
346    {
347        Addr EA;
348        Fault * fault = NoFault;
349
350        %(fp_enable_check)s;
351        %(op_decl)s;
352        %(op_rd)s;
353        EA = xc->getEA();
354
355        if (fault == NoFault) {
356            %(code)s;
357        }
358
359        return NoFault;
360    }
361}};
362
363def template MiscExecute {{
364    Fault * %(class_name)s::execute(%(CPU_exec_context)s *xc,
365                                  Trace::InstRecord *traceData) const
366    {
367        Addr EA;
368        Fault * fault = NoFault;
369
370        %(fp_enable_check)s;
371        %(op_decl)s;
372        %(op_rd)s;
373        %(ea_code)s;
374
375        if (fault == NoFault) {
376            %(memacc_code)s;
377        }
378
379        return NoFault;
380    }
381}};
382
383// load instructions use Ra as dest, so check for
384// Ra == 31 to detect nops
385def template LoadNopCheckDecode {{
386 {
387     AlphaStaticInst *i = new %(class_name)s(machInst);
388     if (RA == 31) {
389         i = makeNop(i);
390     }
391     return i;
392 }
393}};
394
395
396// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
397def template LoadPrefetchCheckDecode {{
398 {
399     if (RA != 31) {
400         return new %(class_name)s(machInst);
401     }
402     else {
403         return new %(class_name)sPrefetch(machInst);
404     }
405 }
406}};
407
408
409let {{
410def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
411                  postacc_code = '', base_class = 'MemoryDisp32',
412                  decode_template = BasicDecode, exec_template_base = ''):
413    # Make sure flags are in lists (convert to lists if not).
414    mem_flags = makeList(mem_flags)
415    inst_flags = makeList(inst_flags)
416
417    # add hook to get effective addresses into execution trace output.
418    ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
419
420    # generate code block objects
421    ea_cblk = CodeBlock(ea_code)
422    memacc_cblk = CodeBlock(memacc_code)
423    postacc_cblk = CodeBlock(postacc_code)
424
425    # Some CPU models execute the memory operation as an atomic unit,
426    # while others want to separate them into an effective address
427    # computation and a memory access operation.  As a result, we need
428    # to generate three StaticInst objects.  Note that the latter two
429    # are nested inside the larger "atomic" one.
430
431    # generate InstObjParams for EAComp object
432    ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
433
434    # generate InstObjParams for MemAcc object
435    memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
436    # in the split execution model, the MemAcc portion is responsible
437    # for the post-access code.
438    memacc_iop.postacc_code = postacc_cblk.code
439
440    # generate InstObjParams for unified execution
441    cblk = CodeBlock(ea_code + memacc_code + postacc_code)
442    iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
443
444    iop.ea_constructor = ea_cblk.constructor
445    iop.ea_code = ea_cblk.code
446    iop.memacc_constructor = memacc_cblk.constructor
447    iop.memacc_code = memacc_cblk.code
448    iop.postacc_code = postacc_cblk.code
449
450    if mem_flags:
451        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
452        iop.constructor += s
453        memacc_iop.constructor += s
454
455    # select templates
456    memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
457    fullExecTemplate = eval(exec_template_base + 'Execute')
458
459    # (header_output, decoder_output, decode_block, exec_output)
460    return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
461            decode_template.subst(iop),
462            EACompExecute.subst(ea_iop)
463            + memAccExecTemplate.subst(memacc_iop)
464            + fullExecTemplate.subst(iop))
465}};
466
467
468def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
469                     mem_flags = [], inst_flags = []) {{
470    (header_output, decoder_output, decode_block, exec_output) = \
471        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
472                      decode_template = LoadNopCheckDecode,
473                      exec_template_base = 'Load')
474}};
475
476
477// Note that the flags passed in apply only to the prefetch version
478def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
479                          mem_flags = [], pf_flags = [], inst_flags = []) {{
480    # declare the load instruction object and generate the decode block
481    (header_output, decoder_output, decode_block, exec_output) = \
482        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
483                      decode_template = LoadPrefetchCheckDecode,
484                      exec_template_base = 'Load')
485
486    # Declare the prefetch instruction object.
487
488    # Make sure flag args are lists so we can mess with them.
489    mem_flags = makeList(mem_flags)
490    pf_flags = makeList(pf_flags)
491    inst_flags = makeList(inst_flags)
492
493    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
494    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
495                                  'IsDataPrefetch', 'MemReadOp']
496
497    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
498        LoadStoreBase(name, Name + 'Prefetch', ea_code,
499                      'xc->prefetch(EA, memAccessFlags);',
500                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
501
502    header_output += pf_header_output
503    decoder_output += pf_decoder_output
504    exec_output += pf_exec_output
505}};
506
507
508def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
509                 mem_flags = [], inst_flags = []) {{
510    (header_output, decoder_output, decode_block, exec_output) = \
511        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
512                      exec_template_base = 'Store')
513}};
514
515
516def format StoreCond(memacc_code, postacc_code,
517                     ea_code = {{ EA = Rb + disp; }},
518                     mem_flags = [], inst_flags = []) {{
519    (header_output, decoder_output, decode_block, exec_output) = \
520        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
521                      postacc_code, exec_template_base = 'Store')
522}};
523
524
525// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
526def format MiscPrefetch(ea_code, memacc_code,
527                        mem_flags = [], inst_flags = []) {{
528    (header_output, decoder_output, decode_block, exec_output) = \
529        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
530                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
531}};
532
533
534