util.isa revision 4040
12SN/A// Copyright (c) 2006-2007 The Regents of The University of Michigan
21762SN/A// All rights reserved.
32SN/A//
42SN/A// Redistribution and use in source and binary forms, with or without
52SN/A// modification, are permitted provided that the following conditions are
62SN/A// met: redistributions of source code must retain the above copyright
72SN/A// notice, this list of conditions and the following disclaimer;
82SN/A// redistributions in binary form must reproduce the above copyright
92SN/A// notice, this list of conditions and the following disclaimer in the
102SN/A// documentation and/or other materials provided with the distribution;
112SN/A// neither the name of the copyright holders nor the names of its
122SN/A// contributors may be used to endorse or promote products derived from
132SN/A// this software without specific prior written permission.
142SN/A//
152SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
192SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
202SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
252SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262SN/A//
272665Ssaidi@eecs.umich.edu// Authors: Ali Saidi
282665Ssaidi@eecs.umich.edu//          Gabe Black
292665Ssaidi@eecs.umich.edu//          Steve Reinhardt
302SN/A
312SN/A////////////////////////////////////////////////////////////////////
322SN/A//
332SN/A// Mem utility templates and functions
342SN/A//
352SN/A
361354SN/Aoutput header {{
371354SN/A        /**
382SN/A         * Base class for memory operations.
392SN/A         */
405501Snate@binkert.org        class Mem : public SparcStaticInst
415546Snate@binkert.org        {
427004Snate@binkert.org          protected:
432SN/A
442SN/A            // Constructor
455769Snate@binkert.org            Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
462361SN/A                SparcStaticInst(mnem, _machInst, __opClass)
476216Snate@binkert.org            {
488232Snate@binkert.org            }
4956SN/A
502SN/A            std::string generateDisassembly(Addr pc,
515543Ssaidi@eecs.umich.edu                    const SymbolTable *symtab) const;
522SN/A        };
531354SN/A
541354SN/A        /**
552SN/A         * Class for memory operations which use an immediate offset.
562SN/A         */
572SN/A        class MemImm : public Mem
582SN/A        {
595501Snate@binkert.org          protected:
605501Snate@binkert.org
612SN/A            // Constructor
629044SAli.Saidi@ARM.com            MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
632SN/A                Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
642SN/A            {}
652SN/A
665769Snate@binkert.org            std::string generateDisassembly(Addr pc,
678902Sandreas.hansson@arm.com                    const SymbolTable *symtab) const;
685769Snate@binkert.org
695769Snate@binkert.org            const int32_t imm;
707059Snate@binkert.org        };
717059Snate@binkert.org}};
727059Snate@binkert.org
737059Snate@binkert.orgoutput decoder {{
747059Snate@binkert.org        std::string Mem::generateDisassembly(Addr pc,
757059Snate@binkert.org                const SymbolTable *symtab) const
767059Snate@binkert.org        {
777059Snate@binkert.org            std::stringstream response;
787059Snate@binkert.org            bool load = flags[IsLoad];
797059Snate@binkert.org            bool store = flags[IsStore];
807059Snate@binkert.org
817059Snate@binkert.org            printMnemonic(response, mnemonic);
827059Snate@binkert.org            if(store)
837059Snate@binkert.org            {
847059Snate@binkert.org                printReg(response, _srcRegIdx[0]);
857059Snate@binkert.org                ccprintf(response, ", ");
865769Snate@binkert.org            }
877058Snate@binkert.org            ccprintf(response, "[");
887058Snate@binkert.org            if(_srcRegIdx[!store ? 0 : 1] != 0)
897058Snate@binkert.org            {
902SN/A                printSrcReg(response, !store ? 0 : 1);
915502Snate@binkert.org                ccprintf(response, " + ");
925502Snate@binkert.org            }
935502Snate@binkert.org            printSrcReg(response, !store ? 1 : 2);
945503Snate@binkert.org            ccprintf(response, "]");
955503Snate@binkert.org            if(load)
965502Snate@binkert.org            {
975502Snate@binkert.org                ccprintf(response, ", ");
985502Snate@binkert.org                printReg(response, _destRegIdx[0]);
995502Snate@binkert.org            }
1005502Snate@binkert.org
1015502Snate@binkert.org            return response.str();
1025502Snate@binkert.org        }
1035602Snate@binkert.org
1045602Snate@binkert.org        std::string MemImm::generateDisassembly(Addr pc,
1055501Snate@binkert.org                const SymbolTable *symtab) const
1065543Ssaidi@eecs.umich.edu        {
1077058Snate@binkert.org            std::stringstream response;
1085769Snate@binkert.org            bool load = flags[IsLoad];
1094016Sstever@eecs.umich.edu            bool save = flags[IsStore];
1104016Sstever@eecs.umich.edu
1114016Sstever@eecs.umich.edu            printMnemonic(response, mnemonic);
1124016Sstever@eecs.umich.edu            if(save)
1134016Sstever@eecs.umich.edu            {
1144016Sstever@eecs.umich.edu                printReg(response, _srcRegIdx[0]);
1154016Sstever@eecs.umich.edu                ccprintf(response, ", ");
1164016Sstever@eecs.umich.edu            }
1174016Sstever@eecs.umich.edu            ccprintf(response, "[");
1185501Snate@binkert.org            if(_srcRegIdx[!save ? 0 : 1] != 0)
1195605Snate@binkert.org            {
1205605Snate@binkert.org                printReg(response, _srcRegIdx[!save ? 0 : 1]);
1215605Snate@binkert.org                ccprintf(response, " + ");
1225605Snate@binkert.org            }
1235501Snate@binkert.org            if(imm >= 0)
1244016Sstever@eecs.umich.edu                ccprintf(response, "0x%x]", imm);
1255577SSteve.Reinhardt@amd.com            else
1265501Snate@binkert.org                ccprintf(response, "-0x%x]", -imm);
1275501Snate@binkert.org            if(load)
1285501Snate@binkert.org            {
1295502Snate@binkert.org                ccprintf(response, ", ");
1305502Snate@binkert.org                printReg(response, _destRegIdx[0]);
1315605Snate@binkert.org            }
1325502Snate@binkert.org
1335502Snate@binkert.org            return response.str();
1345605Snate@binkert.org        }
1355605Snate@binkert.org}};
1365605Snate@binkert.org
1375577SSteve.Reinhardt@amd.com//This template provides the execute functions for a load
1387823Ssteve.reinhardt@amd.comdef template LoadExecute {{
1395502Snate@binkert.org        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
1405502Snate@binkert.org                Trace::InstRecord *traceData) const
1415502Snate@binkert.org        {
1422SN/A            Fault fault = NoFault;
1435769Snate@binkert.org            Addr EA;
1445769Snate@binkert.org            %(fp_enable_check)s;
1455769Snate@binkert.org            %(op_decl)s;
1465769Snate@binkert.org            %(op_rd)s;
1475769Snate@binkert.org            %(ea_code)s;
1485769Snate@binkert.org            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
1492SN/A            %(fault_check)s;
1508581Ssteve.reinhardt@amd.com            if(fault == NoFault)
1518581Ssteve.reinhardt@amd.com            {
1525769Snate@binkert.org                fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s);
1537059Snate@binkert.org            }
1545769Snate@binkert.org            if(fault == NoFault)
1555769Snate@binkert.org            {
1562SN/A                %(code)s;
1575769Snate@binkert.org            }
1585769Snate@binkert.org            if(fault == NoFault)
1595769Snate@binkert.org            {
1605769Snate@binkert.org                    //Write the resulting state to the execution context
1615769Snate@binkert.org                    %(op_wb)s;
1625769Snate@binkert.org            }
1635769Snate@binkert.org
1645769Snate@binkert.org            return fault;
1655769Snate@binkert.org        }
1665769Snate@binkert.org}};
1675769Snate@binkert.org
1685769Snate@binkert.orgdef template LoadInitiateAcc {{
1695769Snate@binkert.org        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
1705769Snate@binkert.org                Trace::InstRecord * traceData) const
1715769Snate@binkert.org        {
1725769Snate@binkert.org            Fault fault = NoFault;
1735769Snate@binkert.org            Addr EA;
1745769Snate@binkert.org            %(fp_enable_check)s;
1755769Snate@binkert.org            %(op_decl)s;
1765769Snate@binkert.org            %(op_rd)s;
1775769Snate@binkert.org            %(ea_code)s;
1785501Snate@binkert.org            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
1795543Ssaidi@eecs.umich.edu            %(fault_check)s;
1802SN/A            if(fault == NoFault)
1812SN/A            {
182396SN/A                fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s);
183396SN/A            }
184396SN/A            return fault;
185396SN/A        }
1865501Snate@binkert.org}};
1877058Snate@binkert.org
1887058Snate@binkert.orgdef template LoadCompleteAcc {{
1893329Sstever@eecs.umich.edu        Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc,
1907058Snate@binkert.org                Trace::InstRecord * traceData) const
1917058Snate@binkert.org        {
1927058Snate@binkert.org            Fault fault = NoFault;
1937058Snate@binkert.org            %(op_decl)s;
194396SN/A            %(op_rd)s;
1957058Snate@binkert.org            Mem = pkt->get<typeof(Mem)>();
1967058Snate@binkert.org            %(code)s;
1977058Snate@binkert.org            if(fault == NoFault)
1987058Snate@binkert.org            {
1993329Sstever@eecs.umich.edu                %(op_wb)s;
2007058Snate@binkert.org            }
2017058Snate@binkert.org            return fault;
2027058Snate@binkert.org        }
2037058Snate@binkert.org}};
2047058Snate@binkert.org
205396SN/A//This template provides the execute functions for a store
2067058Snate@binkert.orgdef template StoreExecute {{
2077058Snate@binkert.org        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
2087058Snate@binkert.org                Trace::InstRecord *traceData) const
2097058Snate@binkert.org        {
210396SN/A            Fault fault = NoFault;
2117058Snate@binkert.org            //This is to support the conditional store in cas instructions.
2127058Snate@binkert.org            //It should be optomized out in all the others
213396SN/A            bool storeCond = true;
2147058Snate@binkert.org            Addr EA;
2157058Snate@binkert.org            %(fp_enable_check)s;
2167058Snate@binkert.org            %(op_decl)s;
2177058Snate@binkert.org            %(op_rd)s;
218396SN/A            %(ea_code)s;
2197058Snate@binkert.org            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
2207058Snate@binkert.org            %(fault_check)s;
2217058Snate@binkert.org            if(fault == NoFault)
222396SN/A            {
2237058Snate@binkert.org                %(code)s;
2247058Snate@binkert.org            }
2257058Snate@binkert.org            if(storeCond && fault == NoFault)
2264075Sbinkertn@umich.edu            {
2277058Snate@binkert.org                fault = xc->write((uint%(mem_acc_size)s_t)Mem,
2287058Snate@binkert.org                        EA, %(asi_val)s, 0);
2295501Snate@binkert.org            }
2307058Snate@binkert.org            if(fault == NoFault)
2317058Snate@binkert.org            {
2327058Snate@binkert.org                    //Write the resulting state to the execution context
2337058Snate@binkert.org                    %(op_wb)s;
2347058Snate@binkert.org            }
2357058Snate@binkert.org
236396SN/A            return fault;
2372SN/A        }
2382SN/A}};
2392SN/A
2402SN/Adef template StoreInitiateAcc {{
2418581Ssteve.reinhardt@amd.com        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
2428581Ssteve.reinhardt@amd.com                Trace::InstRecord * traceData) const
2438581Ssteve.reinhardt@amd.com        {
244224SN/A            Fault fault = NoFault;
2458581Ssteve.reinhardt@amd.com            bool storeCond = true;
2464016Sstever@eecs.umich.edu            Addr EA;
2475501Snate@binkert.org            %(fp_enable_check)s;
2485605Snate@binkert.org            %(op_decl)s;
2495501Snate@binkert.org
2505501Snate@binkert.org            %(op_rd)s;
2517823Ssteve.reinhardt@amd.com            %(ea_code)s;
2525501Snate@binkert.org            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
2534016Sstever@eecs.umich.edu            %(fault_check)s;
254224SN/A            if(fault == NoFault)
255224SN/A            {
2565768Snate@binkert.org                %(code)s;
2575768Snate@binkert.org            }
258265SN/A            if(storeCond && fault == NoFault)
2595501Snate@binkert.org            {
2605501Snate@binkert.org                fault = xc->write((uint%(mem_acc_size)s_t)Mem,
2615501Snate@binkert.org                        EA, %(asi_val)s, 0);
2625501Snate@binkert.org            }
2635501Snate@binkert.org            if(fault == NoFault)
2645501Snate@binkert.org            {
2655501Snate@binkert.org                    //Write the resulting state to the execution context
2665501Snate@binkert.org                %(op_wb)s;
2675501Snate@binkert.org            }
2685501Snate@binkert.org            return fault;
2695501Snate@binkert.org        }
2705501Snate@binkert.org}};
2715501Snate@binkert.org
2725501Snate@binkert.orgdef template StoreCompleteAcc {{
2735501Snate@binkert.org        Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
2745501Snate@binkert.org                Trace::InstRecord * traceData) const
2755501Snate@binkert.org        {
2765501Snate@binkert.org            return NoFault;
2775501Snate@binkert.org        }
2785501Snate@binkert.org}};
2795501Snate@binkert.org
2802SN/A//This delcares the initiateAcc function in memory operations
2815769Snate@binkert.orgdef template InitiateAccDeclare {{
2822SN/A    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
2832SN/A}};
2845769Snate@binkert.org
2852SN/A//This declares the completeAcc function in memory operations
2862SN/Adef template CompleteAccDeclare {{
2875769Snate@binkert.org    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
2882SN/A}};
2892667Sstever@eecs.umich.edu
2905769Snate@binkert.org//Here are some code snippets which check for various fault conditions
2912667Sstever@eecs.umich.edulet {{
2922SN/A    LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc]
2932SN/A    StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc]
2942SN/A
2952SN/A    # The LSB can be zero, since it's really the MSB in doubles and quads
2967058Snate@binkert.org    # and we're dealing with doubles
2972SN/A    BlockAlignmentFaultCheck = '''
2985605Snate@binkert.org        if(RD & 0xe)
2995501Snate@binkert.org            fault = new IllegalInstruction;
3005501Snate@binkert.org        else if(EA & 0x3f)
3012SN/A            fault = new MemAddressNotAligned;
3025501Snate@binkert.org    '''
3035501Snate@binkert.org    TwinAlignmentFaultCheck = '''
3045501Snate@binkert.org        if(RD & 0x1)
3052SN/A            fault = new IllegalInstruction;
3062SN/A        else if(EA & 0xf)
3072SN/A            fault = new MemAddressNotAligned;
308224SN/A    '''
309224SN/A    # XXX Need to take care of pstate.hpriv as well. The lower ASIs
310237SN/A    # are split into ones that are available in priv and hpriv, and
3115605Snate@binkert.org    # those that are only available in hpriv
312571SN/A    AlternateASIPrivFaultCheck = '''
313571SN/A        if(!bits(Pstate,2,2) && !bits(Hpstate,2,2) && !AsiIsUnPriv((ASI)EXT_ASI) ||
3147005Snate@binkert.org                             !bits(Hpstate,2,2) && AsiIsHPriv((ASI)EXT_ASI))
3157005Snate@binkert.org                fault = new PrivilegedAction;
3167005Snate@binkert.org        else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2))
3177005Snate@binkert.org            fault = new PrivilegedAction;
3187005Snate@binkert.org    '''
3197005Snate@binkert.org
3207005Snate@binkert.org}};
3217005Snate@binkert.org
3227005Snate@binkert.org//A simple function to generate the name of the macro op of a certain
3237005Snate@binkert.org//instruction at a certain micropc
3247005Snate@binkert.orglet {{
3257005Snate@binkert.org    def makeMicroName(name, microPc):
3267005Snate@binkert.org            return name + "::" + name + "_" + str(microPc)
3277005Snate@binkert.org}};
3287005Snate@binkert.org
3297005Snate@binkert.org//This function properly generates the execute functions for one of the
3307005Snate@binkert.org//templates above. This is needed because in one case, ea computation,
3317005Snate@binkert.org//fault checks and the actual code all occur in the same function,
3327005Snate@binkert.org//and in the other they're distributed across two. Also note that for
3337005Snate@binkert.org//execute functions, the name of the base class doesn't matter.
3347005Snate@binkert.orglet {{
3357005Snate@binkert.org    def doSplitExecute(execute, name, Name, asi, opt_flags, microParam):
3367005Snate@binkert.org        microParam["asi_val"] = asi;
3377005Snate@binkert.org        iop = InstObjParams(name, Name, '', microParam, opt_flags)
3387005Snate@binkert.org        (execf, initf, compf) = execute
3397005Snate@binkert.org        return execf.subst(iop) + initf.subst(iop) + compf.subst(iop)
3407005Snate@binkert.org
3417005Snate@binkert.org
3427005Snate@binkert.org    def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute,
3437005Snate@binkert.org            faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
3447005Snate@binkert.org        executeCode = ''
3457005Snate@binkert.org        for (eaCode, name, Name) in (
3467005Snate@binkert.org                (eaRegCode, nameReg, NameReg),
3477005Snate@binkert.org                (eaImmCode, nameImm, NameImm)):
3487005Snate@binkert.org            microParams = {"code": code, "postacc_code" : postacc_code,
3497005Snate@binkert.org                "ea_code": eaCode, "fault_check": faultCode}
3507005Snate@binkert.org            executeCode += doSplitExecute(execute, name, Name,
3517005Snate@binkert.org                    asi, opt_flags, microParams)
3527005Snate@binkert.org        return executeCode
3537005Snate@binkert.org}};
3547005Snate@binkert.org