util.isa revision 3439
13388Sgblack@eecs.umich.edu// Copyright (c) 2006 The Regents of The University of Michigan
23388Sgblack@eecs.umich.edu// All rights reserved.
33388Sgblack@eecs.umich.edu//
43388Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
53388Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
63388Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright
73388Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
83388Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
93388Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
103388Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
113388Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its
123388Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
133388Sgblack@eecs.umich.edu// this software without specific prior written permission.
143388Sgblack@eecs.umich.edu//
153388Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163388Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173388Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
183388Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
193388Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
203388Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
213388Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
223388Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
233388Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
243388Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
253388Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
263388Sgblack@eecs.umich.edu//
273388Sgblack@eecs.umich.edu// Authors: Ali Saidi
283388Sgblack@eecs.umich.edu//          Gabe Black
293388Sgblack@eecs.umich.edu//          Steve Reinhardt
303388Sgblack@eecs.umich.edu
313388Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////
323388Sgblack@eecs.umich.edu//
333388Sgblack@eecs.umich.edu// Mem utility templates and functions
343388Sgblack@eecs.umich.edu//
353388Sgblack@eecs.umich.edu
363388Sgblack@eecs.umich.edu//This template provides the execute functions for a load
373388Sgblack@eecs.umich.edudef template LoadExecute {{
383388Sgblack@eecs.umich.edu        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
393388Sgblack@eecs.umich.edu                Trace::InstRecord *traceData) const
403388Sgblack@eecs.umich.edu        {
413388Sgblack@eecs.umich.edu            Fault fault = NoFault;
423388Sgblack@eecs.umich.edu            Addr EA;
433388Sgblack@eecs.umich.edu            %(op_decl)s;
443388Sgblack@eecs.umich.edu            %(op_rd)s;
453388Sgblack@eecs.umich.edu            %(ea_code)s;
463388Sgblack@eecs.umich.edu            DPRINTF(Sparc, "The address is 0x%x\n", EA);
473391Sgblack@eecs.umich.edu            %(fault_check)s;
483391Sgblack@eecs.umich.edu            if(fault == NoFault)
493391Sgblack@eecs.umich.edu            {
503391Sgblack@eecs.umich.edu                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
513391Sgblack@eecs.umich.edu            }
523391Sgblack@eecs.umich.edu            if(fault == NoFault)
533391Sgblack@eecs.umich.edu            {
543391Sgblack@eecs.umich.edu                %(code)s;
553391Sgblack@eecs.umich.edu            }
563388Sgblack@eecs.umich.edu            if(fault == NoFault)
573388Sgblack@eecs.umich.edu            {
583388Sgblack@eecs.umich.edu                //Write the resulting state to the execution context
593388Sgblack@eecs.umich.edu                %(op_wb)s;
603388Sgblack@eecs.umich.edu            }
613388Sgblack@eecs.umich.edu
623388Sgblack@eecs.umich.edu            return fault;
633388Sgblack@eecs.umich.edu        }
643388Sgblack@eecs.umich.edu
653388Sgblack@eecs.umich.edu        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
663388Sgblack@eecs.umich.edu                Trace::InstRecord * traceData) const
673388Sgblack@eecs.umich.edu        {
683388Sgblack@eecs.umich.edu            Fault fault = NoFault;
693388Sgblack@eecs.umich.edu            Addr EA;
703388Sgblack@eecs.umich.edu            uint%(mem_acc_size)s_t Mem;
713388Sgblack@eecs.umich.edu            %(ea_decl)s;
723388Sgblack@eecs.umich.edu            %(ea_rd)s;
733388Sgblack@eecs.umich.edu            %(ea_code)s;
743391Sgblack@eecs.umich.edu            %(fault_check)s;
753391Sgblack@eecs.umich.edu            if(fault == NoFault)
763391Sgblack@eecs.umich.edu            {
773391Sgblack@eecs.umich.edu                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
783391Sgblack@eecs.umich.edu            }
793388Sgblack@eecs.umich.edu            return fault;
803388Sgblack@eecs.umich.edu        }
813388Sgblack@eecs.umich.edu
823388Sgblack@eecs.umich.edu        Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc,
833388Sgblack@eecs.umich.edu                Trace::InstRecord * traceData) const
843388Sgblack@eecs.umich.edu        {
853388Sgblack@eecs.umich.edu            Fault fault = NoFault;
863388Sgblack@eecs.umich.edu            %(code_decl)s;
873388Sgblack@eecs.umich.edu            %(code_rd)s;
883388Sgblack@eecs.umich.edu            Mem = pkt->get<typeof(Mem)>();
893388Sgblack@eecs.umich.edu            %(code)s;
903388Sgblack@eecs.umich.edu            if(fault == NoFault)
913388Sgblack@eecs.umich.edu            {
923388Sgblack@eecs.umich.edu                %(code_wb)s;
933388Sgblack@eecs.umich.edu            }
943388Sgblack@eecs.umich.edu            return fault;
953388Sgblack@eecs.umich.edu        }
963388Sgblack@eecs.umich.edu}};
973388Sgblack@eecs.umich.edu
983388Sgblack@eecs.umich.edu//This template provides the execute functions for a store
993388Sgblack@eecs.umich.edudef template StoreExecute {{
1003388Sgblack@eecs.umich.edu        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
1013388Sgblack@eecs.umich.edu                Trace::InstRecord *traceData) const
1023388Sgblack@eecs.umich.edu        {
1033388Sgblack@eecs.umich.edu            Fault fault = NoFault;
1043388Sgblack@eecs.umich.edu            uint64_t write_result = 0;
1053439Sgblack@eecs.umich.edu            //This is to support the conditional store in cas instructions.
1063439Sgblack@eecs.umich.edu            //It should be optomized out in all the others
1073439Sgblack@eecs.umich.edu            bool storeCond = true;
1083388Sgblack@eecs.umich.edu            Addr EA;
1093388Sgblack@eecs.umich.edu            %(op_decl)s;
1103388Sgblack@eecs.umich.edu            %(op_rd)s;
1113388Sgblack@eecs.umich.edu            %(ea_code)s;
1123388Sgblack@eecs.umich.edu            DPRINTF(Sparc, "The address is 0x%x\n", EA);
1133391Sgblack@eecs.umich.edu            %(fault_check)s;
1143391Sgblack@eecs.umich.edu            if(fault == NoFault)
1153391Sgblack@eecs.umich.edu            {
1163391Sgblack@eecs.umich.edu                %(code)s;
1173391Sgblack@eecs.umich.edu            }
1183439Sgblack@eecs.umich.edu            if(storeCond && fault == NoFault)
1193388Sgblack@eecs.umich.edu            {
1203388Sgblack@eecs.umich.edu                fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
1213388Sgblack@eecs.umich.edu            }
1223388Sgblack@eecs.umich.edu            if(fault == NoFault)
1233388Sgblack@eecs.umich.edu            {
1243388Sgblack@eecs.umich.edu                //Write the resulting state to the execution context
1253388Sgblack@eecs.umich.edu                %(op_wb)s;
1263388Sgblack@eecs.umich.edu            }
1273388Sgblack@eecs.umich.edu
1283388Sgblack@eecs.umich.edu            return fault;
1293388Sgblack@eecs.umich.edu        }
1303388Sgblack@eecs.umich.edu
1313388Sgblack@eecs.umich.edu        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
1323388Sgblack@eecs.umich.edu                Trace::InstRecord * traceData) const
1333388Sgblack@eecs.umich.edu        {
1343388Sgblack@eecs.umich.edu            Fault fault = NoFault;
1353388Sgblack@eecs.umich.edu            uint64_t write_result = 0;
1363439Sgblack@eecs.umich.edu            bool storeCond = true;
1373388Sgblack@eecs.umich.edu            Addr EA;
1383388Sgblack@eecs.umich.edu            %(op_decl)s;
1393388Sgblack@eecs.umich.edu            %(op_rd)s;
1403388Sgblack@eecs.umich.edu            %(ea_code)s;
1413388Sgblack@eecs.umich.edu            DPRINTF(Sparc, "The address is 0x%x\n", EA);
1423391Sgblack@eecs.umich.edu            %(fault_check)s;
1433391Sgblack@eecs.umich.edu            if(fault == NoFault)
1443391Sgblack@eecs.umich.edu            {
1453391Sgblack@eecs.umich.edu                %(code)s;
1463391Sgblack@eecs.umich.edu            }
1473439Sgblack@eecs.umich.edu            if(storeCond && fault == NoFault)
1483388Sgblack@eecs.umich.edu            {
1493388Sgblack@eecs.umich.edu                fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
1503388Sgblack@eecs.umich.edu            }
1513388Sgblack@eecs.umich.edu            if(fault == NoFault)
1523388Sgblack@eecs.umich.edu            {
1533388Sgblack@eecs.umich.edu                //Write the resulting state to the execution context
1543388Sgblack@eecs.umich.edu                %(op_wb)s;
1553388Sgblack@eecs.umich.edu            }
1563388Sgblack@eecs.umich.edu            return fault;
1573388Sgblack@eecs.umich.edu        }
1583388Sgblack@eecs.umich.edu
1593388Sgblack@eecs.umich.edu        Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
1603388Sgblack@eecs.umich.edu                Trace::InstRecord * traceData) const
1613388Sgblack@eecs.umich.edu        {
1623388Sgblack@eecs.umich.edu            return NoFault;
1633388Sgblack@eecs.umich.edu        }
1643388Sgblack@eecs.umich.edu}};
1653388Sgblack@eecs.umich.edu
1663388Sgblack@eecs.umich.edu//This delcares the initiateAcc function in memory operations
1673388Sgblack@eecs.umich.edudef template InitiateAccDeclare {{
1683388Sgblack@eecs.umich.edu    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
1693388Sgblack@eecs.umich.edu}};
1703388Sgblack@eecs.umich.edu
1713388Sgblack@eecs.umich.edu//This declares the completeAcc function in memory operations
1723388Sgblack@eecs.umich.edudef template CompleteAccDeclare {{
1733388Sgblack@eecs.umich.edu    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
1743388Sgblack@eecs.umich.edu}};
1753388Sgblack@eecs.umich.edu
1763391Sgblack@eecs.umich.edu//Here are some code snippets which check for various fault conditions
1773391Sgblack@eecs.umich.edulet {{
1783391Sgblack@eecs.umich.edu    # The LSB can be zero, since it's really the MSB in doubles and quads
1793391Sgblack@eecs.umich.edu    # and we're dealing with doubles
1803391Sgblack@eecs.umich.edu    BlockAlignmentFaultCheck = '''
1813391Sgblack@eecs.umich.edu        if(RD & 0xe)
1823391Sgblack@eecs.umich.edu            fault = new IllegalInstruction;
1833391Sgblack@eecs.umich.edu        else if(EA & 0x3f)
1843391Sgblack@eecs.umich.edu            fault = new MemAddressNotAligned;
1853391Sgblack@eecs.umich.edu    '''
1863391Sgblack@eecs.umich.edu    # XXX Need to take care of pstate.hpriv as well. The lower ASIs
1873391Sgblack@eecs.umich.edu    # are split into ones that are available in priv and hpriv, and
1883391Sgblack@eecs.umich.edu    # those that are only available in hpriv
1893391Sgblack@eecs.umich.edu    AlternateASIPrivFaultCheck = '''
1903391Sgblack@eecs.umich.edu        if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
1913391Sgblack@eecs.umich.edu            fault = new PrivilegedAction;
1923391Sgblack@eecs.umich.edu        else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2))
1933391Sgblack@eecs.umich.edu            fault = new PrivilegedAction;
1943391Sgblack@eecs.umich.edu    '''
1953391Sgblack@eecs.umich.edu
1963391Sgblack@eecs.umich.edu}};
1973391Sgblack@eecs.umich.edu
1983391Sgblack@eecs.umich.edu//A simple function to generate the name of the macro op of a certain
1993391Sgblack@eecs.umich.edu//instruction at a certain micropc
2003391Sgblack@eecs.umich.edulet {{
2013391Sgblack@eecs.umich.edu    def makeMicroName(name, microPc):
2023391Sgblack@eecs.umich.edu        return name + "::" + name + "_" + str(microPc)
2033391Sgblack@eecs.umich.edu}};
2043391Sgblack@eecs.umich.edu
2053388Sgblack@eecs.umich.edu//This function properly generates the execute functions for one of the
2063388Sgblack@eecs.umich.edu//templates above. This is needed because in one case, ea computation,
2073391Sgblack@eecs.umich.edu//fault checks and the actual code all occur in the same function,
2083388Sgblack@eecs.umich.edu//and in the other they're distributed across two. Also note that for
2093388Sgblack@eecs.umich.edu//execute functions, the name of the base class doesn't matter.
2103388Sgblack@eecs.umich.edulet {{
2113439Sgblack@eecs.umich.edu    def doSplitExecute(code, eaCode, execute,
2123439Sgblack@eecs.umich.edu            faultCode, name, Name, opt_flags):
2133439Sgblack@eecs.umich.edu        codeIop = InstObjParams(name, Name, '', code, opt_flags)
2143439Sgblack@eecs.umich.edu        eaIop = InstObjParams(name, Name, '', eaCode,
2153439Sgblack@eecs.umich.edu                opt_flags, {"fault_check": faultCode})
2163439Sgblack@eecs.umich.edu        iop = InstObjParams(name, Name, '', code, opt_flags,
2173439Sgblack@eecs.umich.edu                {"fault_check": faultCode, "ea_code" : eaCode})
2183439Sgblack@eecs.umich.edu        (iop.ea_decl,
2193439Sgblack@eecs.umich.edu         iop.ea_rd,
2203439Sgblack@eecs.umich.edu         iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb)
2213439Sgblack@eecs.umich.edu        (iop.code_decl,
2223439Sgblack@eecs.umich.edu         iop.code_rd,
2233439Sgblack@eecs.umich.edu         iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb)
2243439Sgblack@eecs.umich.edu        return execute.subst(iop)
2253439Sgblack@eecs.umich.edu
2263439Sgblack@eecs.umich.edu
2273439Sgblack@eecs.umich.edu    def doDualSplitExecute(code, eaRegCode, eaImmCode, execute,
2283391Sgblack@eecs.umich.edu            faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags):
2293388Sgblack@eecs.umich.edu        executeCode = ''
2303388Sgblack@eecs.umich.edu        for (eaCode, name, Name) in (
2313388Sgblack@eecs.umich.edu                (eaRegCode, nameReg, NameReg),
2323388Sgblack@eecs.umich.edu                (eaImmCode, nameImm, NameImm)):
2333439Sgblack@eecs.umich.edu            executeCode += doSplitExecute(code, eaCode,
2343439Sgblack@eecs.umich.edu                    execute, faultCode, name, Name, opt_flags)
2353388Sgblack@eecs.umich.edu        return executeCode
2363388Sgblack@eecs.umich.edu}};
237