mem.isa revision 6302
12SN/A// -*- mode:c++ -*-
21762SN/A
37897Shestness@cs.utexas.edu// Copyright (c) 2007-2008 The Florida State University
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
272SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu//
292665Ssaidi@eecs.umich.edu// Authors: Stephen Hines
302665Ssaidi@eecs.umich.edu
312665Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////
327897Shestness@cs.utexas.edu//
332SN/A// Memory-format instructions
342SN/A//
352SN/A
362SN/Adef template LoadStoreDeclare {{
372SN/A    /**
382SN/A     * Static instruction class for "%(mnemonic)s".
3975SN/A     */
402SN/A    class %(class_name)s : public %(base_class)s
412439SN/A    {
422439SN/A      protected:
43603SN/A
442986Sgblack@eecs.umich.edu        /**
45603SN/A         * "Fake" effective address computation class for "%(mnemonic)s".
464762Snate@binkert.org         */
472520SN/A        class EAComp : public %(base_class)s
484762Snate@binkert.org        {
492378SN/A          public:
506658Snate@binkert.org            /// Constructor
512378SN/A            EAComp(ExtMachInst machInst);
52722SN/A
532378SN/A            %(BasicExecDeclare)s
54312SN/A        };
551634SN/A
562680Sktlim@umich.edu        /**
571634SN/A         * "Fake" memory access instruction class for "%(mnemonic)s".
582521SN/A         */
592378SN/A        class MemAcc : public %(base_class)s
602378SN/A        {
61803SN/A          public:
627723SAli.Saidi@ARM.com            /// Constructor
637723SAli.Saidi@ARM.com            MemAcc(ExtMachInst machInst);
643960Sgblack@eecs.umich.edu
652378SN/A            %(BasicExecDeclare)s
666658Snate@binkert.org        };
672SN/A
682SN/A      public:
692SN/A
70603SN/A        /// Constructor.
712901Ssaidi@eecs.umich.edu        %(class_name)s(ExtMachInst machInst);
722902Ssaidi@eecs.umich.edu
732902Ssaidi@eecs.umich.edu        %(BasicExecDeclare)s
744762Snate@binkert.org
754762Snate@binkert.org        %(InitiateAccDeclare)s
764762Snate@binkert.org
774762Snate@binkert.org        %(CompleteAccDeclare)s
784762Snate@binkert.org    };
794762Snate@binkert.org}};
802901Ssaidi@eecs.umich.edu
812901Ssaidi@eecs.umich.edu
822901Ssaidi@eecs.umich.edudef template InitiateAccDeclare {{
832901Ssaidi@eecs.umich.edu    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
842901Ssaidi@eecs.umich.edu}};
854762Snate@binkert.org
862901Ssaidi@eecs.umich.edu
872521SN/Adef template CompleteAccDeclare {{
882SN/A    Fault completeAcc(PacketPtr,  %(CPU_exec_context)s *, Trace::InstRecord *) const;
892SN/A}};
902680Sktlim@umich.edu
915714Shsul@eecs.umich.edu
921806SN/Adef template EACompConstructor {{
936221Snate@binkert.org    inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
945713Shsul@eecs.umich.edu        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
955713Shsul@eecs.umich.edu    {
965713Shsul@eecs.umich.edu        %(constructor)s;
975713Shsul@eecs.umich.edu    }
985714Shsul@eecs.umich.edu}};
991806SN/A
1006227Snate@binkert.org
1015714Shsul@eecs.umich.edudef template MemAccConstructor {{
1021806SN/A    inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
103180SN/A        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
1046029Ssteve.reinhardt@amd.com    {
1056029Ssteve.reinhardt@amd.com        %(constructor)s;
1066029Ssteve.reinhardt@amd.com    }
1076029Ssteve.reinhardt@amd.com}};
1088460SAli.Saidi@ARM.com
1098460SAli.Saidi@ARM.com
1108460SAli.Saidi@ARM.comdef template LoadStoreConstructor {{
1118460SAli.Saidi@ARM.com    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
1128460SAli.Saidi@ARM.com         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1138460SAli.Saidi@ARM.com                          new EAComp(machInst), new MemAcc(machInst))
1148460SAli.Saidi@ARM.com    {
1158460SAli.Saidi@ARM.com        %(constructor)s;
1162378SN/A    }
1172378SN/A}};
1182378SN/A
1192378SN/A
1202520SN/Adef template EACompExecute {{
1212520SN/A    Fault
1227723SAli.Saidi@ARM.com    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
1237723SAli.Saidi@ARM.com                                   Trace::InstRecord *traceData) const
1242520SN/A    {
1251885SN/A        Addr EA;
1261070SN/A        Fault fault = NoFault;
127954SN/A
1281070SN/A        %(op_decl)s;
1291070SN/A        %(op_rd)s;
1301070SN/A        %(ea_code)s;
1311070SN/A
1321070SN/A        if (%(predicate_test)s)
1331070SN/A        {
1341070SN/A            if (fault == NoFault) {
1351070SN/A                %(op_wb)s;
1361070SN/A                xc->setEA(EA);
1371070SN/A            }
1381070SN/A        }
1391070SN/A
1407580SAli.Saidi@arm.com        return fault;
1417580SAli.Saidi@arm.com    }
1427580SAli.Saidi@arm.com}};
1437580SAli.Saidi@arm.com
1447580SAli.Saidi@arm.comdef template LoadMemAccExecute {{
1457580SAli.Saidi@arm.com    Fault
1467580SAli.Saidi@arm.com    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
1477580SAli.Saidi@arm.com                                   Trace::InstRecord *traceData) const
1482378SN/A    {
1492378SN/A        Addr EA;
1507770SAli.Saidi@ARM.com        Fault fault = NoFault;
1512378SN/A
1524997Sgblack@eecs.umich.edu        %(op_decl)s;
1537770SAli.Saidi@ARM.com        %(op_rd)s;
1544997Sgblack@eecs.umich.edu        EA = xc->getEA();
1554997Sgblack@eecs.umich.edu
1564997Sgblack@eecs.umich.edu        if (%(predicate_test)s)
1574997Sgblack@eecs.umich.edu        {
1587770SAli.Saidi@ARM.com            if (fault == NoFault) {
1594997Sgblack@eecs.umich.edu                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
1604997Sgblack@eecs.umich.edu                %(memacc_code)s;
1615795Ssaidi@eecs.umich.edu            }
1625795Ssaidi@eecs.umich.edu
1635795Ssaidi@eecs.umich.edu            if (fault == NoFault) {
1645795Ssaidi@eecs.umich.edu                %(op_wb)s;
1655795Ssaidi@eecs.umich.edu            }
1665795Ssaidi@eecs.umich.edu        }
1672378SN/A
1682378SN/A        return fault;
1692378SN/A    }
1701885SN/A}};
1714762Snate@binkert.org
1727914SBrad.Beckmann@amd.com
1737914SBrad.Beckmann@amd.comdef template LoadExecute {{
1747914SBrad.Beckmann@amd.com    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
1757914SBrad.Beckmann@amd.com                                  Trace::InstRecord *traceData) const
1767914SBrad.Beckmann@amd.com    {
1777914SBrad.Beckmann@amd.com        Addr EA;
1787914SBrad.Beckmann@amd.com        Fault fault = NoFault;
1797914SBrad.Beckmann@amd.com
1807914SBrad.Beckmann@amd.com        %(op_decl)s;
1817914SBrad.Beckmann@amd.com        %(op_rd)s;
1827914SBrad.Beckmann@amd.com        %(ea_code)s;
1837914SBrad.Beckmann@amd.com
1847914SBrad.Beckmann@amd.com        if (%(predicate_test)s)
1857914SBrad.Beckmann@amd.com        {
1867914SBrad.Beckmann@amd.com            if (fault == NoFault) {
1877914SBrad.Beckmann@amd.com                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
1887914SBrad.Beckmann@amd.com                %(memacc_code)s;
1897914SBrad.Beckmann@amd.com            }
1907914SBrad.Beckmann@amd.com
1917914SBrad.Beckmann@amd.com            if (fault == NoFault) {
1927914SBrad.Beckmann@amd.com                %(op_wb)s;
1937914SBrad.Beckmann@amd.com            }
1947914SBrad.Beckmann@amd.com        }
1957914SBrad.Beckmann@amd.com
1967914SBrad.Beckmann@amd.com        return fault;
1977914SBrad.Beckmann@amd.com    }
1987914SBrad.Beckmann@amd.com}};
1997914SBrad.Beckmann@amd.com
2007914SBrad.Beckmann@amd.com
2017914SBrad.Beckmann@amd.comdef template LoadInitiateAcc {{
2027914SBrad.Beckmann@amd.com    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
2037914SBrad.Beckmann@amd.com                                      Trace::InstRecord *traceData) const
2047914SBrad.Beckmann@amd.com    {
2057914SBrad.Beckmann@amd.com        Addr EA;
2067914SBrad.Beckmann@amd.com        Fault fault = NoFault;
2077914SBrad.Beckmann@amd.com
2087914SBrad.Beckmann@amd.com        %(op_src_decl)s;
2097914SBrad.Beckmann@amd.com        %(op_rd)s;
2107914SBrad.Beckmann@amd.com        %(ea_code)s;
2117914SBrad.Beckmann@amd.com
2127914SBrad.Beckmann@amd.com        if (%(predicate_test)s)
2137914SBrad.Beckmann@amd.com        {
2142901Ssaidi@eecs.umich.edu            if (fault == NoFault) {
2152424SN/A                fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
2161885SN/A            }
2171885SN/A        }
2181885SN/A
2191885SN/A        return fault;
2201885SN/A    }
2212158SN/A}};
2221885SN/A
2231885SN/A
2241885SN/Adef template LoadCompleteAcc {{
2251885SN/A    Fault %(class_name)s::completeAcc(PacketPtr pkt,
2261885SN/A                                      %(CPU_exec_context)s *xc,
2271885SN/A                                      Trace::InstRecord *traceData) const
2282989Ssaidi@eecs.umich.edu    {
2291885SN/A        Fault fault = NoFault;
2301913SN/A
2311885SN/A        %(op_decl)s;
2321885SN/A        %(op_rd)s;
2331885SN/A
2341885SN/A        if (%(predicate_test)s)
2351885SN/A        {
2361885SN/A            // ARM instructions will not have a pkt if the predicate is false
2371885SN/A            Mem = pkt->get<typeof(Mem)>();
2381885SN/A
2391885SN/A            if (fault == NoFault) {
2401885SN/A                %(memacc_code)s;
2411885SN/A            }
2422989Ssaidi@eecs.umich.edu
2431885SN/A            if (fault == NoFault) {
2441885SN/A                %(op_wb)s;
2451885SN/A            }
2461885SN/A        }
2472378SN/A
24877SN/A        return fault;
2496658Snate@binkert.org    }
2501070SN/A}};
2513960Sgblack@eecs.umich.edu
2521070SN/A
2531070SN/Adef template StoreMemAccExecute {{
2544762Snate@binkert.org    Fault
2551070SN/A    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
2562158SN/A                                   Trace::InstRecord *traceData) const
2572158SN/A    {
2581070SN/A        Addr EA;
2592158SN/A        Fault fault = NoFault;
2601070SN/A
2612SN/A        %(op_decl)s;
2622SN/A        %(op_rd)s;
2637733SAli.Saidi@ARM.com
2641129SN/A        if (%(predicate_test)s)
2652158SN/A        {
2662158SN/A            EA = xc->getEA();
2671070SN/A
2682378SN/A            if (fault == NoFault) {
2692378SN/A                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
2701070SN/A                                  memAccessFlags, NULL);
2711070SN/A                if (traceData) { traceData->setData(Mem); }
2721070SN/A            }
2731070SN/A
2741070SN/A            if (fault == NoFault) {
2751070SN/A                %(op_wb)s;
2761070SN/A            }
2771070SN/A        }
2781070SN/A
2791070SN/A        return fault;
2801070SN/A    }
2811070SN/A}};
2821070SN/A
2831070SN/A
2841070SN/Adef template StoreExecute {{
2851070SN/A    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
2861070SN/A                                  Trace::InstRecord *traceData) const
2871070SN/A    {
2882378SN/A        Addr EA;
2892378SN/A        Fault fault = NoFault;
2902378SN/A
2912378SN/A        %(op_decl)s;
2922378SN/A        %(op_rd)s;
2932378SN/A        %(ea_code)s;
2945718Shsul@eecs.umich.edu
2955713Shsul@eecs.umich.edu        if (%(predicate_test)s)
2961070SN/A        {
2971070SN/A            if (fault == NoFault) {
2981070SN/A                %(memacc_code)s;
2997897Shestness@cs.utexas.edu            }
3002SN/A
30177SN/A            if (fault == NoFault) {
3027897Shestness@cs.utexas.edu                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
3037897Shestness@cs.utexas.edu                                  memAccessFlags, NULL);
3047897Shestness@cs.utexas.edu                if (traceData) { traceData->setData(Mem); }
3052SN/A            }
3062SN/A
3072SN/A            if (fault == NoFault) {
3082SN/A                %(op_wb)s;
3092SN/A            }
3102SN/A        }
3112SN/A
3122SN/A        return fault;
3132SN/A    }
3142SN/A}};
3152158SN/A
3162158SN/Adef template StoreInitiateAcc {{
3172SN/A    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
3182SN/A                                      Trace::InstRecord *traceData) const
3192SN/A    {
320        Addr EA;
321        Fault fault = NoFault;
322
323        %(op_decl)s;
324        %(op_rd)s;
325        %(ea_code)s;
326
327        if (%(predicate_test)s)
328        {
329            if (fault == NoFault) {
330                %(memacc_code)s;
331            }
332
333            if (fault == NoFault) {
334                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
335                                  memAccessFlags, NULL);
336                if (traceData) { traceData->setData(Mem); }
337            }
338
339            // Need to write back any potential address register update
340            if (fault == NoFault) {
341                %(op_wb)s;
342            }
343        }
344
345        return fault;
346    }
347}};
348
349
350def template StoreCompleteAcc {{
351    Fault %(class_name)s::completeAcc(PacketPtr pkt,
352                                      %(CPU_exec_context)s *xc,
353                                      Trace::InstRecord *traceData) const
354    {
355        Fault fault = NoFault;
356
357        %(op_decl)s;
358        %(op_rd)s;
359
360        if (%(predicate_test)s)
361        {
362            if (fault == NoFault) {
363                %(op_wb)s;
364            }
365        }
366
367        return fault;
368    }
369}};
370
371def template StoreCondCompleteAcc {{
372    Fault %(class_name)s::completeAcc(PacketPtr pkt,
373                                      %(CPU_exec_context)s *xc,
374                                      Trace::InstRecord *traceData) const
375    {
376        Fault fault = NoFault;
377
378        %(op_dest_decl)s;
379
380        if (%(predicate_test)s)
381        {
382            if (fault == NoFault) {
383                %(op_wb)s;
384            }
385        }
386
387        return fault;
388    }
389}};
390
391
392def template MiscMemAccExecute {{
393    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
394                                          Trace::InstRecord *traceData) const
395    {
396        Addr EA;
397        Fault fault = NoFault;
398
399        %(op_decl)s;
400        %(op_rd)s;
401
402        if (%(predicate_test)s)
403        {
404            EA = xc->getEA();
405
406            if (fault == NoFault) {
407                %(memacc_code)s;
408            }
409        }
410
411        return NoFault;
412    }
413}};
414
415def template MiscExecute {{
416    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
417                                  Trace::InstRecord *traceData) const
418    {
419        Addr EA;
420        Fault fault = NoFault;
421
422        %(op_decl)s;
423        %(op_rd)s;
424        %(ea_code)s;
425
426        if (%(predicate_test)s)
427        {
428            if (fault == NoFault) {
429                %(memacc_code)s;
430            }
431        }
432
433        return NoFault;
434    }
435}};
436
437def template MiscInitiateAcc {{
438    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
439                                      Trace::InstRecord *traceData) const
440    {
441        panic("Misc instruction does not support split access method!");
442        return NoFault;
443    }
444}};
445
446
447def template MiscCompleteAcc {{
448    Fault %(class_name)s::completeAcc(PacketPtr pkt,
449                                      %(CPU_exec_context)s *xc,
450                                      Trace::InstRecord *traceData) const
451    {
452        panic("Misc instruction does not support split access method!");
453
454        return NoFault;
455    }
456}};
457
458let {{
459    def buildPUBWLCase(p, u, b, w, l):
460        return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0)
461
462    def buildMode3Inst(p, u, i, w, type, code, mnem):
463        op = ("-", "+")[u]
464        offset = ("%s Rm", "%s hilo")[i] % op
465        ea_code = "EA = Rn %s;" % ("", offset)[p]
466        if p == 0 or w == 1:
467            code += "Rn = Rn %s;" % offset
468        suffix = "_P%dU%dI%dW%d" % (p, u, i, w)
469        return LoadStoreBase(mnem, mnem.capitalize() + suffix,
470                ea_code, code, mem_flags = [], inst_flags = [],
471                exec_template_base = type.capitalize())
472}};
473
474def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{
475    l0Code = ArmGenericCodeSubs(l0Code);
476    l1Code = ArmGenericCodeSubs(l1Code);
477
478    header_output = decoder_output = exec_output = ""
479    decode_block = "switch(PUBWL) {\n"
480    (l0Mnem, l1Mnem) = name.split("_");
481
482    # Loop over all the values of p, u, i, w and l and build instructions and
483    # a decode block for them.
484    for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem),
485                                  (1, l1Type, l1Code, l1Mnem)):
486        for p in (0, 1):
487            wset = (0, 1)
488            if (p == 0):
489                wset = (0,)
490            for u in (0, 1):
491                for i in (0, 1):
492                    for w in wset:
493                        (new_header_output,
494                         new_decoder_output,
495                         new_decode_block,
496                         new_exec_output) = buildMode3Inst(p, u, i, w,
497                                                           type, code, mnem)
498                        header_output += new_header_output
499                        decoder_output += new_decoder_output
500                        exec_output += new_exec_output
501                        decode_block += '''
502                            case %#x:
503                              {%s}
504                              break;
505                        ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block)
506
507    decode_block += '''
508        default:
509          return new Unknown(machInst);
510        break;
511    }'''
512}};
513
514def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
515                     mem_flags = [], inst_flags = []) {{
516    ea_code = ArmGenericCodeSubs(ea_code)
517    memacc_code = ArmGenericCodeSubs(memacc_code)
518    (header_output, decoder_output, decode_block, exec_output) = \
519        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
520                      decode_template = BasicDecode,
521                      exec_template_base = 'Load')
522}};
523
524def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
525                     mem_flags = [], inst_flags = []) {{
526    ea_code = ArmGenericCodeSubs(ea_code)
527    memacc_code = ArmGenericCodeSubs(memacc_code)
528    (header_output, decoder_output, decode_block, exec_output) = \
529        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
530                      exec_template_base = 'Store')
531}};
532
533