util.isa revision 11303
13395Shsul@eecs.umich.edu// Copyright (c) 2006-2007 The Regents of The University of Michigan
23395Shsul@eecs.umich.edu// All rights reserved.
33395Shsul@eecs.umich.edu//
43395Shsul@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
53395Shsul@eecs.umich.edu// modification, are permitted provided that the following conditions are
63395Shsul@eecs.umich.edu// met: redistributions of source code must retain the above copyright
73395Shsul@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
83395Shsul@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
93395Shsul@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
103395Shsul@eecs.umich.edu// documentation and/or other materials provided with the distribution;
113395Shsul@eecs.umich.edu// neither the name of the copyright holders nor the names of its
123395Shsul@eecs.umich.edu// contributors may be used to endorse or promote products derived from
133395Shsul@eecs.umich.edu// this software without specific prior written permission.
143395Shsul@eecs.umich.edu//
153395Shsul@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163395Shsul@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173395Shsul@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
183395Shsul@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
193395Shsul@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
203395Shsul@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
213395Shsul@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
223395Shsul@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
233395Shsul@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
243395Shsul@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
253395Shsul@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
263395Shsul@eecs.umich.edu//
273395Shsul@eecs.umich.edu// Authors: Ali Saidi
283395Shsul@eecs.umich.edu//          Gabe Black
293395Shsul@eecs.umich.edu//          Steve Reinhardt
303395Shsul@eecs.umich.edu
313395Shsul@eecs.umich.edu////////////////////////////////////////////////////////////////////
323395Shsul@eecs.umich.edu//
333395Shsul@eecs.umich.edu// Mem utility templates and functions
343395Shsul@eecs.umich.edu//
353395Shsul@eecs.umich.edu
363395Shsul@eecs.umich.eduoutput header {{
373395Shsul@eecs.umich.edu        /**
383395Shsul@eecs.umich.edu         * Base class for memory operations.
393395Shsul@eecs.umich.edu         */
403395Shsul@eecs.umich.edu        class Mem : public SparcStaticInst
413395Shsul@eecs.umich.edu        {
423395Shsul@eecs.umich.edu          protected:
433395Shsul@eecs.umich.edu
443395Shsul@eecs.umich.edu            // Constructor
453395Shsul@eecs.umich.edu            Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
463395Shsul@eecs.umich.edu                SparcStaticInst(mnem, _machInst, __opClass)
473395Shsul@eecs.umich.edu            {
483395Shsul@eecs.umich.edu            }
493395Shsul@eecs.umich.edu
503395Shsul@eecs.umich.edu            std::string generateDisassembly(Addr pc,
513395Shsul@eecs.umich.edu                    const SymbolTable *symtab) const;
523395Shsul@eecs.umich.edu        };
533395Shsul@eecs.umich.edu
543395Shsul@eecs.umich.edu        /**
553395Shsul@eecs.umich.edu         * Class for memory operations which use an immediate offset.
563395Shsul@eecs.umich.edu         */
573395Shsul@eecs.umich.edu        class MemImm : public Mem
583395Shsul@eecs.umich.edu        {
593395Shsul@eecs.umich.edu          protected:
603395Shsul@eecs.umich.edu
613395Shsul@eecs.umich.edu            // Constructor
623395Shsul@eecs.umich.edu            MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
633395Shsul@eecs.umich.edu                Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
643395Shsul@eecs.umich.edu            {}
653395Shsul@eecs.umich.edu
663395Shsul@eecs.umich.edu            std::string generateDisassembly(Addr pc,
673395Shsul@eecs.umich.edu                    const SymbolTable *symtab) const;
683395Shsul@eecs.umich.edu
693395Shsul@eecs.umich.edu            const int32_t imm;
703395Shsul@eecs.umich.edu        };
713395Shsul@eecs.umich.edu}};
723395Shsul@eecs.umich.edu
733395Shsul@eecs.umich.eduoutput decoder {{
743395Shsul@eecs.umich.edu        std::string Mem::generateDisassembly(Addr pc,
753395Shsul@eecs.umich.edu                const SymbolTable *symtab) const
763395Shsul@eecs.umich.edu        {
773395Shsul@eecs.umich.edu            std::stringstream response;
783395Shsul@eecs.umich.edu            bool load = flags[IsLoad];
793395Shsul@eecs.umich.edu            bool store = flags[IsStore];
803395Shsul@eecs.umich.edu
813395Shsul@eecs.umich.edu            printMnemonic(response, mnemonic);
823395Shsul@eecs.umich.edu            if (store) {
833395Shsul@eecs.umich.edu                printReg(response, _srcRegIdx[0]);
843395Shsul@eecs.umich.edu                ccprintf(response, ", ");
853395Shsul@eecs.umich.edu            }
863395Shsul@eecs.umich.edu            ccprintf(response, "[");
873395Shsul@eecs.umich.edu            if (_srcRegIdx[!store ? 0 : 1] != 0) {
883395Shsul@eecs.umich.edu                printSrcReg(response, !store ? 0 : 1);
893395Shsul@eecs.umich.edu                ccprintf(response, " + ");
903395Shsul@eecs.umich.edu            }
913395Shsul@eecs.umich.edu            printSrcReg(response, !store ? 1 : 2);
923395Shsul@eecs.umich.edu            ccprintf(response, "]");
933395Shsul@eecs.umich.edu            if (load) {
943395Shsul@eecs.umich.edu                ccprintf(response, ", ");
953395Shsul@eecs.umich.edu                printReg(response, _destRegIdx[0]);
963395Shsul@eecs.umich.edu            }
973395Shsul@eecs.umich.edu
983395Shsul@eecs.umich.edu            return response.str();
993395Shsul@eecs.umich.edu        }
1003395Shsul@eecs.umich.edu
1013395Shsul@eecs.umich.edu        std::string MemImm::generateDisassembly(Addr pc,
1023395Shsul@eecs.umich.edu                const SymbolTable *symtab) const
1033395Shsul@eecs.umich.edu        {
1043395Shsul@eecs.umich.edu            std::stringstream response;
1053395Shsul@eecs.umich.edu            bool load = flags[IsLoad];
1063395Shsul@eecs.umich.edu            bool save = flags[IsStore];
1073395Shsul@eecs.umich.edu
1083395Shsul@eecs.umich.edu            printMnemonic(response, mnemonic);
1093395Shsul@eecs.umich.edu            if (save) {
1103395Shsul@eecs.umich.edu                printReg(response, _srcRegIdx[0]);
1113395Shsul@eecs.umich.edu                ccprintf(response, ", ");
1123395Shsul@eecs.umich.edu            }
1133395Shsul@eecs.umich.edu            ccprintf(response, "[");
1143395Shsul@eecs.umich.edu            if (_srcRegIdx[!save ? 0 : 1] != 0) {
1153395Shsul@eecs.umich.edu                printReg(response, _srcRegIdx[!save ? 0 : 1]);
1163395Shsul@eecs.umich.edu                ccprintf(response, " + ");
1173395Shsul@eecs.umich.edu            }
1183395Shsul@eecs.umich.edu            if (imm >= 0)
1193445Shsul@eecs.umich.edu                ccprintf(response, "0x%x]", imm);
1203395Shsul@eecs.umich.edu            else
1213395Shsul@eecs.umich.edu                ccprintf(response, "-0x%x]", -imm);
1223395Shsul@eecs.umich.edu            if (load) {
1233395Shsul@eecs.umich.edu                ccprintf(response, ", ");
1243395Shsul@eecs.umich.edu                printReg(response, _destRegIdx[0]);
1253410Shsul@eecs.umich.edu            }
1263410Shsul@eecs.umich.edu
1273410Shsul@eecs.umich.edu            return response.str();
1283395Shsul@eecs.umich.edu        }
1293395Shsul@eecs.umich.edu}};
1303395Shsul@eecs.umich.edu
1313395Shsul@eecs.umich.edu// This template provides the execute functions for a load
1323395Shsul@eecs.umich.edudef template LoadExecute {{
1333395Shsul@eecs.umich.edu        Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
1343395Shsul@eecs.umich.edu                Trace::InstRecord *traceData) const
1353395Shsul@eecs.umich.edu        {
1363395Shsul@eecs.umich.edu            Fault fault = NoFault;
1373395Shsul@eecs.umich.edu            Addr EA;
1383395Shsul@eecs.umich.edu            %(fp_enable_check)s;
1393395Shsul@eecs.umich.edu            %(op_decl)s;
1403395Shsul@eecs.umich.edu            %(op_rd)s;
1413395Shsul@eecs.umich.edu            %(ea_code)s;
1423395Shsul@eecs.umich.edu            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
1433395Shsul@eecs.umich.edu            %(fault_check)s;
1443395Shsul@eecs.umich.edu            if (fault == NoFault) {
1453395Shsul@eecs.umich.edu                %(EA_trunc)s
1463395Shsul@eecs.umich.edu                fault = readMemAtomic(xc, traceData, EA, Mem, %(asi_val)s);
1473395Shsul@eecs.umich.edu            }
1483395Shsul@eecs.umich.edu            if (fault == NoFault) {
1493395Shsul@eecs.umich.edu                %(code)s;
1503395Shsul@eecs.umich.edu            }
1513395Shsul@eecs.umich.edu            if (fault == NoFault) {
1523395Shsul@eecs.umich.edu                // Write the resulting state to the execution context
1533395Shsul@eecs.umich.edu                %(op_wb)s;
1543395Shsul@eecs.umich.edu            }
1553395Shsul@eecs.umich.edu
1563395Shsul@eecs.umich.edu            return fault;
1573395Shsul@eecs.umich.edu        }
1583395Shsul@eecs.umich.edu}};
1593395Shsul@eecs.umich.edu
1603395Shsul@eecs.umich.edudef template LoadInitiateAcc {{
1613395Shsul@eecs.umich.edu        Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
1623395Shsul@eecs.umich.edu                Trace::InstRecord * traceData) const
1633395Shsul@eecs.umich.edu        {
1643395Shsul@eecs.umich.edu            Fault fault = NoFault;
1653395Shsul@eecs.umich.edu            Addr EA;
1663395Shsul@eecs.umich.edu            %(fp_enable_check)s;
1673395Shsul@eecs.umich.edu            %(op_decl)s;
1683395Shsul@eecs.umich.edu            %(op_rd)s;
1693395Shsul@eecs.umich.edu            %(ea_code)s;
1703395Shsul@eecs.umich.edu            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
1713395Shsul@eecs.umich.edu            %(fault_check)s;
1723395Shsul@eecs.umich.edu            if (fault == NoFault) {
1733395Shsul@eecs.umich.edu                %(EA_trunc)s
1743395Shsul@eecs.umich.edu                fault = initiateMemRead(xc, traceData, EA, Mem, %(asi_val)s);
1753395Shsul@eecs.umich.edu            }
1763395Shsul@eecs.umich.edu            return fault;
1773395Shsul@eecs.umich.edu        }
178}};
179
180def template LoadCompleteAcc {{
181        Fault %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT * xc,
182                Trace::InstRecord * traceData) const
183        {
184            Fault fault = NoFault;
185            %(op_decl)s;
186            %(op_rd)s;
187            getMem(pkt, Mem, traceData);
188            %(code)s;
189            if (fault == NoFault) {
190                %(op_wb)s;
191            }
192            return fault;
193        }
194}};
195
196// This template provides the execute functions for a store
197def template StoreExecute {{
198        Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
199                Trace::InstRecord *traceData) const
200        {
201            Fault fault = NoFault;
202            // This is to support the conditional store in cas instructions.
203            // It should be optomized out in all the others
204            bool storeCond = true;
205            Addr EA;
206            %(fp_enable_check)s;
207            %(op_decl)s;
208            %(op_rd)s;
209            %(ea_code)s;
210            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
211            %(fault_check)s;
212            if (fault == NoFault) {
213                %(code)s;
214            }
215            if (storeCond && fault == NoFault) {
216                %(EA_trunc)s
217                fault = writeMemAtomic(xc, traceData, Mem, EA, %(asi_val)s, 0);
218            }
219            if (fault == NoFault) {
220                // Write the resulting state to the execution context
221                %(op_wb)s;
222            }
223
224            return fault;
225        }
226}};
227
228def template StoreInitiateAcc {{
229        Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
230                Trace::InstRecord * traceData) const
231        {
232            Fault fault = NoFault;
233            bool storeCond = true;
234            Addr EA;
235            %(fp_enable_check)s;
236            %(op_decl)s;
237
238            %(op_rd)s;
239            %(ea_code)s;
240            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
241            %(fault_check)s;
242            if (fault == NoFault) {
243                %(code)s;
244            }
245            if (storeCond && fault == NoFault) {
246                %(EA_trunc)s
247                fault = writeMemTiming(xc, traceData, Mem, EA, %(asi_val)s, 0);
248            }
249            return fault;
250        }
251}};
252
253def template StoreCompleteAcc {{
254        Fault %(class_name)s::completeAcc(PacketPtr, CPU_EXEC_CONTEXT * xc,
255                Trace::InstRecord * traceData) const
256        {
257            return NoFault;
258        }
259}};
260
261def template EACompExecute {{
262    Fault
263    %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
264                                   Trace::InstRecord *traceData) const
265    {
266        Addr EA;
267        Fault fault = NoFault;
268        %(op_decl)s;
269        %(op_rd)s;
270        %(ea_code)s;
271        %(fault_check)s;
272
273        // NOTE: Trace Data is written using execute or completeAcc templates
274        if (fault == NoFault) {
275            %(EA_trunc)s
276            xc->setEA(EA);
277        }
278
279        return fault;
280    }
281}};
282
283def template EACompDeclare {{
284    Fault eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const;
285}};
286
287// This delcares the initiateAcc function in memory operations
288def template InitiateAccDeclare {{
289    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
290}};
291
292// This declares the completeAcc function in memory operations
293def template CompleteAccDeclare {{
294    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
295}};
296
297// Here are some code snippets which check for various fault conditions
298let {{
299    LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc]
300    StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc]
301
302    # The LSB can be zero, since it's really the MSB in doubles and quads
303    # and we're dealing with doubles
304    BlockAlignmentFaultCheck = '''
305        if (RD & 0xe)
306            fault = std::make_shared<IllegalInstruction>();
307        else if (EA & 0x3f)
308            fault = std::make_shared<MemAddressNotAligned>();
309    '''
310    TwinAlignmentFaultCheck = '''
311        if (RD & 0x1)
312            fault = std::make_shared<IllegalInstruction>();
313        else if (EA & 0xf)
314            fault = std::make_shared<MemAddressNotAligned>();
315    '''
316    # XXX Need to take care of pstate.hpriv as well. The lower ASIs
317    # are split into ones that are available in priv and hpriv, and
318    # those that are only available in hpriv
319    AlternateASIPrivFaultCheck = '''
320        if ((!Pstate.priv && !Hpstate.hpriv &&
321             !asiIsUnPriv((ASI)EXT_ASI)) ||
322            (!Hpstate.hpriv && asiIsHPriv((ASI)EXT_ASI)))
323            fault = std::make_shared<PrivilegedAction>();
324        else if (asiIsAsIfUser((ASI)EXT_ASI) && !Pstate.priv)
325            fault = std::make_shared<PrivilegedAction>();
326    '''
327
328    TruncateEA = '''
329        if (!FullSystem)
330            EA = Pstate.am ? EA<31:0> : EA;
331    '''
332}};
333
334// A simple function to generate the name of the macro op of a certain
335// instruction at a certain micropc
336let {{
337    def makeMicroName(name, microPc):
338            return name + "::" + name + "_" + str(microPc)
339}};
340
341// This function properly generates the execute functions for one of the
342// templates above. This is needed because in one case, ea computation,
343// fault checks and the actual code all occur in the same function,
344// and in the other they're distributed across two. Also note that for
345// execute functions, the name of the base class doesn't matter.
346let {{
347    def doSplitExecute(execute, name, Name, asi, opt_flags, microParam):
348        microParam["asi_val"] = asi;
349        iop = InstObjParams(name, Name, '', microParam, opt_flags)
350        (execf, initf, compf) = execute
351        return execf.subst(iop) + initf.subst(iop) + compf.subst(iop)
352
353
354    def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute,
355            faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
356        executeCode = ''
357        for (eaCode, name, Name) in (
358                (eaRegCode, nameReg, NameReg),
359                (eaImmCode, nameImm, NameImm)):
360            microParams = {"code": code, "postacc_code" : postacc_code,
361                "ea_code": eaCode, "fault_check": faultCode,
362                "EA_trunc" : TruncateEA}
363            executeCode += doSplitExecute(execute, name, Name,
364                    asi, opt_flags, microParams)
365        return executeCode
366}};
367