mem.isa revision 6192
12SN/A// -*- mode:c++ -*-
211071SN/A
311071SN/A// Copyright (c) 2003-2005 The Regents of The University of Michigan
411071SN/A// All rights reserved.
511071SN/A//
611071SN/A// Redistribution and use in source and binary forms, with or without
711071SN/A// modification, are permitted provided that the following conditions are
811071SN/A// met: redistributions of source code must retain the above copyright
911071SN/A// notice, this list of conditions and the following disclaimer;
1011071SN/A// redistributions in binary form must reproduce the above copyright
1111071SN/A// notice, this list of conditions and the following disclaimer in the
1211071SN/A// documentation and/or other materials provided with the distribution;
1311071SN/A// neither the name of the copyright holders nor the names of its
141762SN/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
272SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282SN/A//
292SN/A// Authors: Steve Reinhardt
302SN/A//          Kevin Lim
312SN/A
322SN/A////////////////////////////////////////////////////////////////////
332SN/A//
342SN/A// Memory-format instructions: LoadAddress, Load, Store
352SN/A//
362SN/A
372SN/Aoutput header {{
382SN/A    /**
392665SN/A     * Base class for general Alpha memory-format instructions.
402665SN/A     */
412665SN/A    class Memory : public AlphaStaticInst
422SN/A    {
432SN/A      protected:
442SN/A
452SN/A        /// Memory request flags.  See mem_req_base.hh.
462SN/A        Request::Flags memAccessFlags;
472SN/A
4811263Sandreas.sandberg@arm.com        /// Constructor
4911263Sandreas.sandberg@arm.com        Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
50146SN/A            : AlphaStaticInst(mnem, _machInst, __opClass)
512SN/A        {
522SN/A        }
532SN/A
542SN/A        std::string
551954SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
56146SN/A    };
578232SN/A
588232SN/A    /**
5911263Sandreas.sandberg@arm.com     * Base class for memory-format instructions using a 32-bit
6011263Sandreas.sandberg@arm.com     * displacement (i.e. most of them).
6111263Sandreas.sandberg@arm.com     */
624762SN/A    class MemoryDisp32 : public Memory
638229SN/A    {
641078SN/A      protected:
651078SN/A        /// Displacement for EA calculation (signed).
662SN/A        int32_t disp;
672SN/A
682SN/A        /// Constructor.
694981SN/A        MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
704981SN/A            : Memory(mnem, _machInst, __opClass),
712SN/A              disp(MEMDISP)
725034SN/A        {
735034SN/A        }
745034SN/A    };
755034SN/A
762SN/A
774981SN/A    /**
784981SN/A     * Base class for a few miscellaneous memory-format insts
794981SN/A     * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
802SN/A     * None of these instructions has a destination register either.
812SN/A     */
822SN/A    class MemoryNoDisp : public Memory
832SN/A    {
841435SN/A      protected:
851435SN/A        /// Constructor
862SN/A        MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
871435SN/A            : Memory(mnem, _machInst, __opClass)
881435SN/A        {
892SN/A        }
902SN/A
914981SN/A        std::string
924981SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
934981SN/A    };
944981SN/A}};
954981SN/A
964981SN/A
974981SN/Aoutput decoder {{
984981SN/A    std::string
994981SN/A    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1004981SN/A    {
1014981SN/A        return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
1024981SN/A                        flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
1034981SN/A    }
1044981SN/A
1054981SN/A    std::string
1064981SN/A    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1074981SN/A    {
108633SN/A        return csprintf("%-10s (r%d)", mnemonic, RB);
1092SN/A    }
1102SN/A}};
1112SN/A
1122SN/Adef format LoadAddress(code) {{
1132SN/A    iop = InstObjParams(name, Name, 'MemoryDisp32', code)
1142SN/A    header_output = BasicDeclare.subst(iop)
1151435SN/A    decoder_output = BasicConstructor.subst(iop)
1161954SN/A    decode_block = BasicDecode.subst(iop)
1171435SN/A    exec_output = BasicExecute.subst(iop)
1181954SN/A}};
11912087Sspwilson2@wisc.edu
12012087Sspwilson2@wisc.edu
1211435SN/Adef template LoadStoreDeclare {{
1222SN/A    /**
1232SN/A     * Static instruction class for "%(mnemonic)s".
12410905SN/A     */
125558SN/A    class %(class_name)s : public %(base_class)s
12610905SN/A    {
12710905SN/A      public:
128558SN/A
129558SN/A        /// Constructor.
130558SN/A        %(class_name)s(ExtMachInst machInst);
13110905SN/A
132558SN/A        %(BasicExecDeclare)s
13310905SN/A
13410905SN/A        %(EACompDeclare)s
135558SN/A
136558SN/A        %(InitiateAccDeclare)s
137558SN/A
1382566SN/A        %(CompleteAccDeclare)s
139633SN/A    };
140633SN/A}};
141633SN/A
142633SN/A
143633SN/Adef template EACompDeclare {{
144633SN/A    Fault eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const;
145633SN/A}};
1462SN/A
1472SN/Adef template InitiateAccDeclare {{
1482SN/A    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
1492SN/A}};
1502SN/A
151633SN/A
152633SN/Adef template CompleteAccDeclare {{
15311071SN/A    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *,
15411071SN/A                      Trace::InstRecord *) const;
15511071SN/A}};
156633SN/A
15711071SN/Adef template LoadStoreConstructor {{
158633SN/A    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
159633SN/A         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
160195SN/A    {
1612SN/A        %(constructor)s;
1622SN/A    }
1632SN/A}};
1642SN/A
1652SN/Adef template EACompExecute {{
1662SN/A    Fault %(class_name)s::eaComp(%(CPU_exec_context)s *xc,
16711071SN/A                                  Trace::InstRecord *traceData) const
16811071SN/A    {
16911071SN/A        Addr EA;
17011071SN/A        Fault fault = NoFault;
17111071SN/A
17211071SN/A        %(fp_enable_check)s;
17311071SN/A        %(op_decl)s;
17411071SN/A        %(op_rd)s;
17511071SN/A        %(ea_code)s;
17611071SN/A
17711071SN/A        if (fault == NoFault) {
17811071SN/A            %(op_wb)s;
17911071SN/A            xc->setEA(EA);
18011071SN/A        }
18111071SN/A
18211071SN/A        return fault;
18311071SN/A    }
1842SN/A}};
1852566SN/A
1862SN/A
1872SN/Adef template LoadExecute {{
188633SN/A    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
1892SN/A                                  Trace::InstRecord *traceData) const
1902SN/A    {
1912SN/A        Addr EA;
192633SN/A        Fault fault = NoFault;
1932SN/A
1942SN/A        %(fp_enable_check)s;
1952SN/A        %(op_decl)s;
19611701Smichael.lebeane@amd.com        %(op_rd)s;
1975190SN/A        %(ea_code)s;
1985190SN/A
1995190SN/A        if (fault == NoFault) {
200633SN/A            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
201633SN/A            %(memacc_code)s;
2027823SN/A        }
2032SN/A
2042SN/A        if (fault == NoFault) {
2052SN/A            %(op_wb)s;
2062SN/A        }
207558SN/A
20810905SN/A        return fault;
209558SN/A    }
21010469SN/A}};
21110905SN/A
2121435SN/A
21310905SN/Adef template LoadInitiateAcc {{
214558SN/A    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
215633SN/A                                      Trace::InstRecord *traceData) const
21610905SN/A    {
217558SN/A        Addr EA;
218633SN/A        Fault fault = NoFault;
21910905SN/A
220574SN/A        %(fp_enable_check)s;
221574SN/A        %(op_src_decl)s;
22211071SN/A        %(op_rd)s;
22311071SN/A        %(ea_code)s;
22411071SN/A
22511071SN/A        if (fault == NoFault) {
22611071SN/A            fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
22711071SN/A        }
22811071SN/A
22911071SN/A        return fault;
23011071SN/A    }
231558SN/A}};
232558SN/A
233558SN/A
23410905SN/Adef template LoadCompleteAcc {{
235558SN/A    Fault %(class_name)s::completeAcc(PacketPtr pkt,
236574SN/A                                      %(CPU_exec_context)s *xc,
23710905SN/A                                      Trace::InstRecord *traceData) const
238574SN/A    {
23911701Smichael.lebeane@amd.com        Fault fault = NoFault;
24010905SN/A
241558SN/A        %(fp_enable_check)s;
242558SN/A        %(op_decl)s;
243574SN/A
24410905SN/A        Mem = pkt->get<typeof(Mem)>();
245558SN/A
246574SN/A        if (fault == NoFault) {
24710905SN/A            %(memacc_code)s;
2485606SN/A        }
249558SN/A
25011071SN/A        if (fault == NoFault) {
25111071SN/A            %(op_wb)s;
25211071SN/A        }
25311071SN/A
25411071SN/A        return fault;
25511701Smichael.lebeane@amd.com    }
25611071SN/A}};
25711071SN/A
25811071SN/A
25911071SN/Adef template StoreExecute {{
26011071SN/A    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
26111071SN/A                                  Trace::InstRecord *traceData) const
26211071SN/A    {
26311071SN/A        Addr EA;
26411071SN/A        Fault fault = NoFault;
26511071SN/A
26611071SN/A        %(fp_enable_check)s;
26711071SN/A        %(op_decl)s;
26811071SN/A        %(op_rd)s;
26911071SN/A        %(ea_code)s;
27011071SN/A
27111071SN/A        if (fault == NoFault) {
27211071SN/A            %(memacc_code)s;
27311071SN/A        }
27411071SN/A
275558SN/A        if (fault == NoFault) {
276558SN/A            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
2774762SN/A                              memAccessFlags, NULL);
2784762SN/A            if (traceData) { traceData->setData(Mem); }
2792SN/A        }
2804981SN/A
2812SN/A        if (fault == NoFault) {
282            %(postacc_code)s;
283        }
284
285        if (fault == NoFault) {
286            %(op_wb)s;
287        }
288
289        return fault;
290    }
291}};
292
293def template StoreCondExecute {{
294    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
295                                  Trace::InstRecord *traceData) const
296    {
297        Addr EA;
298        Fault fault = NoFault;
299        uint64_t write_result = 0;
300
301        %(fp_enable_check)s;
302        %(op_decl)s;
303        %(op_rd)s;
304        %(ea_code)s;
305
306        if (fault == NoFault) {
307            %(memacc_code)s;
308        }
309
310        if (fault == NoFault) {
311            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
312                              memAccessFlags, &write_result);
313            if (traceData) { traceData->setData(Mem); }
314        }
315
316        if (fault == NoFault) {
317            %(postacc_code)s;
318        }
319
320        if (fault == NoFault) {
321            %(op_wb)s;
322        }
323
324        return fault;
325    }
326}};
327
328def template StoreInitiateAcc {{
329    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
330                                      Trace::InstRecord *traceData) const
331    {
332        Addr EA;
333        Fault fault = NoFault;
334
335        %(fp_enable_check)s;
336        %(op_decl)s;
337        %(op_rd)s;
338        %(ea_code)s;
339
340        if (fault == NoFault) {
341            %(memacc_code)s;
342        }
343
344        if (fault == NoFault) {
345            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
346                              memAccessFlags, NULL);
347            if (traceData) { traceData->setData(Mem); }
348        }
349
350        return fault;
351    }
352}};
353
354
355def template StoreCompleteAcc {{
356    Fault %(class_name)s::completeAcc(PacketPtr pkt,
357                                      %(CPU_exec_context)s *xc,
358                                      Trace::InstRecord *traceData) const
359    {
360        Fault fault = NoFault;
361
362        %(fp_enable_check)s;
363        %(op_dest_decl)s;
364
365        if (fault == NoFault) {
366            %(postacc_code)s;
367        }
368
369        if (fault == NoFault) {
370            %(op_wb)s;
371        }
372
373        return fault;
374    }
375}};
376
377
378def template StoreCondCompleteAcc {{
379    Fault %(class_name)s::completeAcc(PacketPtr pkt,
380                                      %(CPU_exec_context)s *xc,
381                                      Trace::InstRecord *traceData) const
382    {
383        Fault fault = NoFault;
384
385        %(fp_enable_check)s;
386        %(op_dest_decl)s;
387
388        uint64_t write_result = pkt->req->getExtraData();
389
390        if (fault == NoFault) {
391            %(postacc_code)s;
392        }
393
394        if (fault == NoFault) {
395            %(op_wb)s;
396        }
397
398        return fault;
399    }
400}};
401
402
403def template MiscExecute {{
404    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
405                                  Trace::InstRecord *traceData) const
406    {
407        Addr EA;
408        Fault fault = NoFault;
409
410        %(fp_enable_check)s;
411        %(op_decl)s;
412        %(op_rd)s;
413        %(ea_code)s;
414
415        if (fault == NoFault) {
416            %(memacc_code)s;
417        }
418
419        return NoFault;
420    }
421}};
422
423def template MiscInitiateAcc {{
424    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
425                                      Trace::InstRecord *traceData) const
426    {
427        warn("initiateAcc undefined: Misc instruction does not support split "
428             "access method!");
429        return NoFault;
430    }
431}};
432
433
434def template MiscCompleteAcc {{
435    Fault %(class_name)s::completeAcc(PacketPtr pkt,
436                                      %(CPU_exec_context)s *xc,
437                                      Trace::InstRecord *traceData) const
438    {
439        warn("completeAcc undefined: Misc instruction does not support split "
440             "access method!");
441
442        return NoFault;
443    }
444}};
445
446
447// load instructions use Ra as dest, so check for
448// Ra == 31 to detect nops
449def template LoadNopCheckDecode {{
450 {
451     AlphaStaticInst *i = new %(class_name)s(machInst);
452     if (RA == 31) {
453         i = makeNop(i);
454     }
455     return i;
456 }
457}};
458
459
460// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
461def template LoadPrefetchCheckDecode {{
462 {
463     if (RA != 31) {
464         return new %(class_name)s(machInst);
465     }
466     else {
467         return new %(class_name)sPrefetch(machInst);
468     }
469 }
470}};
471
472
473let {{
474def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
475                  postacc_code = '', base_class = 'MemoryDisp32',
476                  decode_template = BasicDecode, exec_template_base = ''):
477    # Make sure flags are in lists (convert to lists if not).
478    mem_flags = makeList(mem_flags)
479    inst_flags = makeList(inst_flags)
480
481    # add hook to get effective addresses into execution trace output.
482    ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
483
484    # Some CPU models execute the memory operation as an atomic unit,
485    # while others want to separate them into an effective address
486    # computation and a memory access operation.  As a result, we need
487    # to generate three StaticInst objects.  Note that the latter two
488    # are nested inside the larger "atomic" one.
489
490    # Generate InstObjParams for each of the three objects.  Note that
491    # they differ only in the set of code objects contained (which in
492    # turn affects the object's overall operand list).
493    iop = InstObjParams(name, Name, base_class,
494                        { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code },
495                        inst_flags)
496    memacc_iop = InstObjParams(name, Name, base_class,
497                        { 'memacc_code':memacc_code, 'postacc_code':postacc_code },
498                        inst_flags)
499
500    if mem_flags:
501        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
502        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
503        iop.constructor += s
504        memacc_iop.constructor += s
505
506    # select templates
507
508    # The InitiateAcc template is the same for StoreCond templates as the
509    # corresponding Store template..
510    StoreCondInitiateAcc = StoreInitiateAcc
511
512    fullExecTemplate = eval(exec_template_base + 'Execute')
513    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
514    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
515
516    # (header_output, decoder_output, decode_block, exec_output)
517    return (LoadStoreDeclare.subst(iop),
518            LoadStoreConstructor.subst(iop),
519            decode_template.subst(iop),
520            fullExecTemplate.subst(iop)
521            + EACompExecute.subst(iop)
522            + initiateAccTemplate.subst(iop)
523            + completeAccTemplate.subst(iop))
524}};
525
526def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
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                      decode_template = LoadNopCheckDecode,
531                      exec_template_base = 'Load')
532}};
533
534
535// Note that the flags passed in apply only to the prefetch version
536def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
537                          mem_flags = [], pf_flags = [], inst_flags = []) {{
538    # declare the load instruction object and generate the decode block
539    (header_output, decoder_output, decode_block, exec_output) = \
540        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
541                      decode_template = LoadPrefetchCheckDecode,
542                      exec_template_base = 'Load')
543
544    # Declare the prefetch instruction object.
545
546    # Make sure flag args are lists so we can mess with them.
547    mem_flags = makeList(mem_flags)
548    pf_flags = makeList(pf_flags)
549    inst_flags = makeList(inst_flags)
550
551    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
552    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
553                                  'IsDataPrefetch', 'MemReadOp']
554
555    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
556        LoadStoreBase(name, Name + 'Prefetch', ea_code,
557                      'xc->prefetch(EA, memAccessFlags);',
558                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
559
560    header_output += pf_header_output
561    decoder_output += pf_decoder_output
562    exec_output += pf_exec_output
563}};
564
565
566def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
567                 mem_flags = [], inst_flags = []) {{
568    (header_output, decoder_output, decode_block, exec_output) = \
569        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
570                      exec_template_base = 'Store')
571}};
572
573
574def format StoreCond(memacc_code, postacc_code,
575                     ea_code = {{ EA = Rb + disp; }},
576                     mem_flags = [], inst_flags = []) {{
577    (header_output, decoder_output, decode_block, exec_output) = \
578        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
579                      postacc_code, exec_template_base = 'StoreCond')
580}};
581
582
583// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
584def format MiscPrefetch(ea_code, memacc_code,
585                        mem_flags = [], inst_flags = []) {{
586    (header_output, decoder_output, decode_block, exec_output) = \
587        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
588                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
589}};
590
591
592