mem.isa revision 6305
16145Snate@binkert.org// -*- mode:c++ -*-
26145Snate@binkert.org
36145Snate@binkert.org// Copyright (c) 2007-2008 The Florida State University
46145Snate@binkert.org// All rights reserved.
56145Snate@binkert.org//
66145Snate@binkert.org// Redistribution and use in source and binary forms, with or without
76145Snate@binkert.org// modification, are permitted provided that the following conditions are
86145Snate@binkert.org// met: redistributions of source code must retain the above copyright
96145Snate@binkert.org// notice, this list of conditions and the following disclaimer;
106145Snate@binkert.org// redistributions in binary form must reproduce the above copyright
116145Snate@binkert.org// notice, this list of conditions and the following disclaimer in the
126145Snate@binkert.org// documentation and/or other materials provided with the distribution;
136145Snate@binkert.org// neither the name of the copyright holders nor the names of its
146145Snate@binkert.org// contributors may be used to endorse or promote products derived from
156145Snate@binkert.org// this software without specific prior written permission.
166145Snate@binkert.org//
176145Snate@binkert.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
186145Snate@binkert.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
196145Snate@binkert.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
206145Snate@binkert.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
216145Snate@binkert.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
226145Snate@binkert.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
236145Snate@binkert.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
246145Snate@binkert.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256145Snate@binkert.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
266145Snate@binkert.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
276145Snate@binkert.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
286145Snate@binkert.org//
296145Snate@binkert.org// Authors: Stephen Hines
306145Snate@binkert.org
316145Snate@binkert.org////////////////////////////////////////////////////////////////////
326145Snate@binkert.org//
336145Snate@binkert.org// Memory-format instructions
346145Snate@binkert.org//
356145Snate@binkert.org
366145Snate@binkert.orgdef template LoadStoreDeclare {{
376145Snate@binkert.org    /**
386145Snate@binkert.org     * Static instruction class for "%(mnemonic)s".
396145Snate@binkert.org     */
406145Snate@binkert.org    class %(class_name)s : public %(base_class)s
416145Snate@binkert.org    {
426145Snate@binkert.org      public:
436145Snate@binkert.org
446145Snate@binkert.org        /// Constructor.
456145Snate@binkert.org        %(class_name)s(ExtMachInst machInst);
466145Snate@binkert.org
476145Snate@binkert.org        %(BasicExecDeclare)s
486145Snate@binkert.org
496145Snate@binkert.org        %(InitiateAccDeclare)s
506145Snate@binkert.org
516145Snate@binkert.org        %(CompleteAccDeclare)s
526145Snate@binkert.org    };
536145Snate@binkert.org}};
546145Snate@binkert.org
556145Snate@binkert.org
566145Snate@binkert.orgdef template InitiateAccDeclare {{
576145Snate@binkert.org    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
586145Snate@binkert.org}};
596145Snate@binkert.org
606145Snate@binkert.org
616145Snate@binkert.orgdef template CompleteAccDeclare {{
626145Snate@binkert.org    Fault completeAcc(PacketPtr,  %(CPU_exec_context)s *, Trace::InstRecord *) const;
636145Snate@binkert.org}};
646145Snate@binkert.org
656145Snate@binkert.org
666145Snate@binkert.orgdef template LoadStoreConstructor {{
676145Snate@binkert.org    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
686145Snate@binkert.org         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
696145Snate@binkert.org    {
706145Snate@binkert.org        %(constructor)s;
716145Snate@binkert.org    }
726145Snate@binkert.org}};
736145Snate@binkert.org
746145Snate@binkert.org
756145Snate@binkert.orgdef template LoadExecute {{
766145Snate@binkert.org    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
776145Snate@binkert.org                                  Trace::InstRecord *traceData) const
786145Snate@binkert.org    {
796145Snate@binkert.org        Addr EA;
806145Snate@binkert.org        Fault fault = NoFault;
816145Snate@binkert.org
826145Snate@binkert.org        %(op_decl)s;
836145Snate@binkert.org        %(op_rd)s;
846145Snate@binkert.org        %(ea_code)s;
856145Snate@binkert.org
866145Snate@binkert.org        if (%(predicate_test)s)
876145Snate@binkert.org        {
886145Snate@binkert.org            if (fault == NoFault) {
896145Snate@binkert.org                fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
906145Snate@binkert.org                %(memacc_code)s;
916145Snate@binkert.org            }
926145Snate@binkert.org
936145Snate@binkert.org            if (fault == NoFault) {
946145Snate@binkert.org                %(op_wb)s;
956145Snate@binkert.org            }
966145Snate@binkert.org        }
976145Snate@binkert.org
986145Snate@binkert.org        return fault;
996145Snate@binkert.org    }
1006145Snate@binkert.org}};
1016145Snate@binkert.org
1026145Snate@binkert.org
1036145Snate@binkert.orgdef template LoadInitiateAcc {{
1046145Snate@binkert.org    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
1056145Snate@binkert.org                                      Trace::InstRecord *traceData) const
1066145Snate@binkert.org    {
1076145Snate@binkert.org        Addr EA;
1086145Snate@binkert.org        Fault fault = NoFault;
1096145Snate@binkert.org
1106145Snate@binkert.org        %(op_src_decl)s;
1116145Snate@binkert.org        %(op_rd)s;
1126145Snate@binkert.org        %(ea_code)s;
1136145Snate@binkert.org
1146145Snate@binkert.org        if (%(predicate_test)s)
1156145Snate@binkert.org        {
1166145Snate@binkert.org            if (fault == NoFault) {
1176145Snate@binkert.org                fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
1186145Snate@binkert.org            }
1196145Snate@binkert.org        }
1206145Snate@binkert.org
1216145Snate@binkert.org        return fault;
1226145Snate@binkert.org    }
1236145Snate@binkert.org}};
1246145Snate@binkert.org
1256145Snate@binkert.org
1266145Snate@binkert.orgdef template LoadCompleteAcc {{
1276145Snate@binkert.org    Fault %(class_name)s::completeAcc(PacketPtr pkt,
1286145Snate@binkert.org                                      %(CPU_exec_context)s *xc,
1296145Snate@binkert.org                                      Trace::InstRecord *traceData) const
1306145Snate@binkert.org    {
1316145Snate@binkert.org        Fault fault = NoFault;
1326145Snate@binkert.org
1336145Snate@binkert.org        %(op_decl)s;
1346145Snate@binkert.org        %(op_rd)s;
1356145Snate@binkert.org
1366145Snate@binkert.org        if (%(predicate_test)s)
1376145Snate@binkert.org        {
1386145Snate@binkert.org            // ARM instructions will not have a pkt if the predicate is false
1396145Snate@binkert.org            Mem = pkt->get<typeof(Mem)>();
1406145Snate@binkert.org
1416145Snate@binkert.org            if (fault == NoFault) {
1426145Snate@binkert.org                %(memacc_code)s;
1436145Snate@binkert.org            }
1446145Snate@binkert.org
1456145Snate@binkert.org            if (fault == NoFault) {
1466145Snate@binkert.org                %(op_wb)s;
1476145Snate@binkert.org            }
1486145Snate@binkert.org        }
1496145Snate@binkert.org
1506145Snate@binkert.org        return fault;
1516145Snate@binkert.org    }
1526145Snate@binkert.org}};
1536145Snate@binkert.org
1546145Snate@binkert.org
1556145Snate@binkert.orgdef template StoreExecute {{
1566145Snate@binkert.org    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
1576145Snate@binkert.org                                  Trace::InstRecord *traceData) const
1586145Snate@binkert.org    {
1596145Snate@binkert.org        Addr EA;
1606145Snate@binkert.org        Fault fault = NoFault;
1616145Snate@binkert.org
1626145Snate@binkert.org        %(op_decl)s;
1636145Snate@binkert.org        %(op_rd)s;
1646145Snate@binkert.org        %(ea_code)s;
1656145Snate@binkert.org
1666145Snate@binkert.org        if (%(predicate_test)s)
1676145Snate@binkert.org        {
1686145Snate@binkert.org            if (fault == NoFault) {
1696145Snate@binkert.org                %(memacc_code)s;
1706145Snate@binkert.org            }
1716145Snate@binkert.org
1726145Snate@binkert.org            if (fault == NoFault) {
1736145Snate@binkert.org                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
1746145Snate@binkert.org                                  memAccessFlags, NULL);
1756145Snate@binkert.org                if (traceData) { traceData->setData(Mem); }
1766145Snate@binkert.org            }
1776145Snate@binkert.org
1786145Snate@binkert.org            if (fault == NoFault) {
1796145Snate@binkert.org                %(op_wb)s;
1806145Snate@binkert.org            }
1816145Snate@binkert.org        }
1826145Snate@binkert.org
1836145Snate@binkert.org        return fault;
1846145Snate@binkert.org    }
1856145Snate@binkert.org}};
1866145Snate@binkert.org
1876145Snate@binkert.orgdef template StoreInitiateAcc {{
1886145Snate@binkert.org    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
1896145Snate@binkert.org                                      Trace::InstRecord *traceData) const
1906145Snate@binkert.org    {
1916145Snate@binkert.org        Addr EA;
1926145Snate@binkert.org        Fault fault = NoFault;
1936145Snate@binkert.org
1946145Snate@binkert.org        %(op_decl)s;
1956145Snate@binkert.org        %(op_rd)s;
1966145Snate@binkert.org        %(ea_code)s;
1976145Snate@binkert.org
1986145Snate@binkert.org        if (%(predicate_test)s)
1996145Snate@binkert.org        {
2006145Snate@binkert.org            if (fault == NoFault) {
2016145Snate@binkert.org                %(memacc_code)s;
2026145Snate@binkert.org            }
2036145Snate@binkert.org
2046145Snate@binkert.org            if (fault == NoFault) {
2056145Snate@binkert.org                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
2066145Snate@binkert.org                                  memAccessFlags, NULL);
2076145Snate@binkert.org                if (traceData) { traceData->setData(Mem); }
2086145Snate@binkert.org            }
2096145Snate@binkert.org
2106145Snate@binkert.org            // Need to write back any potential address register update
2116145Snate@binkert.org            if (fault == NoFault) {
2126145Snate@binkert.org                %(op_wb)s;
2136145Snate@binkert.org            }
2146145Snate@binkert.org        }
2156145Snate@binkert.org
2166145Snate@binkert.org        return fault;
2176145Snate@binkert.org    }
2186145Snate@binkert.org}};
2196145Snate@binkert.org
2206145Snate@binkert.org
2216145Snate@binkert.orgdef template StoreCompleteAcc {{
2226145Snate@binkert.org    Fault %(class_name)s::completeAcc(PacketPtr pkt,
2236145Snate@binkert.org                                      %(CPU_exec_context)s *xc,
2246145Snate@binkert.org                                      Trace::InstRecord *traceData) const
2256145Snate@binkert.org    {
2266145Snate@binkert.org        Fault fault = NoFault;
2276145Snate@binkert.org
2286145Snate@binkert.org        %(op_decl)s;
2296145Snate@binkert.org        %(op_rd)s;
2306145Snate@binkert.org
2316145Snate@binkert.org        if (%(predicate_test)s)
2326145Snate@binkert.org        {
2336145Snate@binkert.org            if (fault == NoFault) {
2346145Snate@binkert.org                %(op_wb)s;
2356145Snate@binkert.org            }
2366145Snate@binkert.org        }
2376145Snate@binkert.org
2386145Snate@binkert.org        return fault;
2396145Snate@binkert.org    }
2406145Snate@binkert.org}};
2416145Snate@binkert.org
2426145Snate@binkert.orgdef template StoreCondCompleteAcc {{
2436145Snate@binkert.org    Fault %(class_name)s::completeAcc(PacketPtr pkt,
2446145Snate@binkert.org                                      %(CPU_exec_context)s *xc,
2456145Snate@binkert.org                                      Trace::InstRecord *traceData) const
2466145Snate@binkert.org    {
2476145Snate@binkert.org        Fault fault = NoFault;
2486145Snate@binkert.org
2496145Snate@binkert.org        %(op_dest_decl)s;
2506145Snate@binkert.org
2516145Snate@binkert.org        if (%(predicate_test)s)
2526145Snate@binkert.org        {
2536145Snate@binkert.org            if (fault == NoFault) {
2546145Snate@binkert.org                %(op_wb)s;
2556145Snate@binkert.org            }
2566145Snate@binkert.org        }
2576145Snate@binkert.org
2586145Snate@binkert.org        return fault;
2596145Snate@binkert.org    }
2606145Snate@binkert.org}};
2616145Snate@binkert.org
2626145Snate@binkert.orglet {{
2636145Snate@binkert.org    def buildPUBWLCase(p, u, b, w, l):
2646145Snate@binkert.org        return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0)
2656145Snate@binkert.org
2666145Snate@binkert.org    def buildMode2Inst(p, u, b, w, l, suffix, offset):
2676145Snate@binkert.org        mnem = ("str", "ldr")[l]
2686145Snate@binkert.org        op = ("-", "+")[u]
2696145Snate@binkert.org        offset = op + ArmGenericCodeSubs(offset);
2706145Snate@binkert.org        mem = ("Mem", "Mem.ub")[b]
2716145Snate@binkert.org        code = ("%s = Rd;", "Rd = %s;")[l] % mem
2726145Snate@binkert.org        ea_code = "EA = Rn %s;" % ("", offset)[p]
2736145Snate@binkert.org        if p == 0 or w == 1:
2746145Snate@binkert.org            code += "Rn = Rn %s;" % offset
2756145Snate@binkert.org        if p == 0 and w == 0:
2766145Snate@binkert.org            # Here's where we'll tack on a flag to make this a usermode access.
2776145Snate@binkert.org            mnem += "t"
2786145Snate@binkert.org        type = ("Store", "Load")[l]
2796145Snate@binkert.org        suffix = "_%s_P%dU%dB%dW%d" % (suffix, p, u, b, w)
2806145Snate@binkert.org        if b == 1:
2816145Snate@binkert.org            mnem += "b"
2826145Snate@binkert.org        return LoadStoreBase(mnem, mnem.capitalize() + suffix,
2836145Snate@binkert.org                ea_code, code, mem_flags = [], inst_flags = [],
2846145Snate@binkert.org                exec_template_base = type.capitalize())
2856145Snate@binkert.org
2866145Snate@binkert.org    def buildMode3Inst(p, u, i, w, type, code, mnem):
2876145Snate@binkert.org        op = ("-", "+")[u]
2886145Snate@binkert.org        offset = ("%s Rm", "%s hilo")[i] % op
2896145Snate@binkert.org        ea_code = "EA = Rn %s;" % ("", offset)[p]
2906145Snate@binkert.org        if p == 0 or w == 1:
2916145Snate@binkert.org            code += "Rn = Rn %s;" % offset
2926145Snate@binkert.org        suffix = "_P%dU%dI%dW%d" % (p, u, i, w)
2936145Snate@binkert.org        return LoadStoreBase(mnem, mnem.capitalize() + suffix,
2946145Snate@binkert.org                ea_code, code, mem_flags = [], inst_flags = [],
2956145Snate@binkert.org                exec_template_base = type.capitalize())
2966145Snate@binkert.org}};
2976145Snate@binkert.org
2986145Snate@binkert.orgdef format AddrMode2(suffix, offset) {{
2996145Snate@binkert.org    header_output = decoder_output = exec_output = ""
3006145Snate@binkert.org    decode_block = "switch(PUBWL) {\n"
3016145Snate@binkert.org
3026145Snate@binkert.org    # Loop over all the values of p, u, b, w and l and build instructions and
3036145Snate@binkert.org    # a decode block for them.
3046145Snate@binkert.org    for p in (0, 1):
3056145Snate@binkert.org        for u in (0, 1):
3066145Snate@binkert.org            for b in (0, 1):
3076145Snate@binkert.org                for w in (0, 1):
3086145Snate@binkert.org                    for l in (0, 1):
3096145Snate@binkert.org                        (new_header_output,
3106145Snate@binkert.org                         new_decoder_output,
311                         new_decode_block,
312                         new_exec_output) = buildMode2Inst(p, u, b, w, l,
313                                                           suffix, offset)
314                        header_output += new_header_output
315                        decoder_output += new_decoder_output
316                        exec_output += new_exec_output
317                        decode_block += '''
318                            case %#x:
319                              {%s}
320                              break;
321                        ''' % (buildPUBWLCase(p,u,b,w,l), new_decode_block)
322    decode_block += '''
323        default:
324          return new Unknown(machInst);
325        break;
326    }'''
327}};
328
329def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{
330    l0Code = ArmGenericCodeSubs(l0Code);
331    l1Code = ArmGenericCodeSubs(l1Code);
332
333    header_output = decoder_output = exec_output = ""
334    decode_block = "switch(PUBWL) {\n"
335    (l0Mnem, l1Mnem) = name.split("_");
336
337    # Loop over all the values of p, u, i, w and l and build instructions and
338    # a decode block for them.
339    for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem),
340                                  (1, l1Type, l1Code, l1Mnem)):
341        for p in (0, 1):
342            wset = (0, 1)
343            if (p == 0):
344                wset = (0,)
345            for u in (0, 1):
346                for i in (0, 1):
347                    for w in wset:
348                        (new_header_output,
349                         new_decoder_output,
350                         new_decode_block,
351                         new_exec_output) = buildMode3Inst(p, u, i, w,
352                                                           type, code, mnem)
353                        header_output += new_header_output
354                        decoder_output += new_decoder_output
355                        exec_output += new_exec_output
356                        decode_block += '''
357                            case %#x:
358                              {%s}
359                              break;
360                        ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block)
361
362    decode_block += '''
363        default:
364          return new Unknown(machInst);
365        break;
366    }'''
367}};
368
369def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
370                     mem_flags = [], inst_flags = []) {{
371    ea_code = ArmGenericCodeSubs(ea_code)
372    memacc_code = ArmGenericCodeSubs(memacc_code)
373    (header_output, decoder_output, decode_block, exec_output) = \
374        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
375                      decode_template = BasicDecode,
376                      exec_template_base = 'Load')
377}};
378
379def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
380                     mem_flags = [], inst_flags = []) {{
381    ea_code = ArmGenericCodeSubs(ea_code)
382    memacc_code = ArmGenericCodeSubs(memacc_code)
383    (header_output, decoder_output, decode_block, exec_output) = \
384        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
385                      exec_template_base = 'Store')
386}};
387
388