util.isa revision 3970:d54945bab95d
12810SN/A// Copyright (c) 2006-2007 The Regents of The University of Michigan
211893Snikos.nikoleris@arm.com// All rights reserved.
39796Sprakash.ramrakhyani@arm.com//
49796Sprakash.ramrakhyani@arm.com// Redistribution and use in source and binary forms, with or without
59796Sprakash.ramrakhyani@arm.com// modification, are permitted provided that the following conditions are
69796Sprakash.ramrakhyani@arm.com// met: redistributions of source code must retain the above copyright
79796Sprakash.ramrakhyani@arm.com// notice, this list of conditions and the following disclaimer;
89796Sprakash.ramrakhyani@arm.com// redistributions in binary form must reproduce the above copyright
99796Sprakash.ramrakhyani@arm.com// notice, this list of conditions and the following disclaimer in the
109796Sprakash.ramrakhyani@arm.com// documentation and/or other materials provided with the distribution;
119796Sprakash.ramrakhyani@arm.com// neither the name of the copyright holders nor the names of its
129796Sprakash.ramrakhyani@arm.com// contributors may be used to endorse or promote products derived from
139796Sprakash.ramrakhyani@arm.com// this software without specific prior written permission.
142810SN/A//
152810SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162810SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172810SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182810SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
192810SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
202810SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212810SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222810SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232810SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242810SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
252810SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262810SN/A//
272810SN/A// Authors: Ali Saidi
282810SN/A//          Gabe Black
292810SN/A//          Steve Reinhardt
302810SN/A
312810SN/A////////////////////////////////////////////////////////////////////
322810SN/A//
332810SN/A// Mem utility templates and functions
342810SN/A//
352810SN/A
362810SN/Aoutput header {{
372810SN/A        /**
382810SN/A         * Base class for memory operations.
392810SN/A         */
402810SN/A        class Mem : public SparcStaticInst
412810SN/A        {
422810SN/A          protected:
432810SN/A
442810SN/A            // Constructor
452810SN/A            Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
462810SN/A                SparcStaticInst(mnem, _machInst, __opClass)
472810SN/A            {
482810SN/A            }
4911486Snikos.nikoleris@arm.com
5011486Snikos.nikoleris@arm.com            std::string generateDisassembly(Addr pc,
515338Sstever@gmail.com                    const SymbolTable *symtab) const;
522810SN/A        };
532810SN/A
549796Sprakash.ramrakhyani@arm.com        /**
5511893Snikos.nikoleris@arm.com         * Class for memory operations which use an immediate offset.
5611893Snikos.nikoleris@arm.com         */
5711722Ssophiane.senni@gmail.com        class MemImm : public Mem
5811722Ssophiane.senni@gmail.com        {
5911722Ssophiane.senni@gmail.com          protected:
6011722Ssophiane.senni@gmail.com
6112513Sodanrc@yahoo.com.br            // Constructor
6212513Sodanrc@yahoo.com.br            MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
6312629Sodanrc@yahoo.com.br                Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
6412629Sodanrc@yahoo.com.br            {}
659796Sprakash.ramrakhyani@arm.com
669796Sprakash.ramrakhyani@arm.com            std::string generateDisassembly(Addr pc,
679796Sprakash.ramrakhyani@arm.com                    const SymbolTable *symtab) const;
682810SN/A
692810SN/A            const int32_t imm;
702810SN/A        };
7110360Sandreas.hansson@arm.com}};
722810SN/A
732810SN/Aoutput decoder {{
742810SN/A        std::string Mem::generateDisassembly(Addr pc,
752810SN/A                const SymbolTable *symtab) const
7612636Sodanrc@yahoo.com.br        {
7712636Sodanrc@yahoo.com.br            std::stringstream response;
7812636Sodanrc@yahoo.com.br            bool load = flags[IsLoad];
7912636Sodanrc@yahoo.com.br            bool store = flags[IsStore];
8012636Sodanrc@yahoo.com.br
8112636Sodanrc@yahoo.com.br            printMnemonic(response, mnemonic);
8212636Sodanrc@yahoo.com.br            if(store)
8312636Sodanrc@yahoo.com.br            {
8412636Sodanrc@yahoo.com.br                printReg(response, _srcRegIdx[0]);
8512636Sodanrc@yahoo.com.br                ccprintf(response, ", ");
8612636Sodanrc@yahoo.com.br            }
8712636Sodanrc@yahoo.com.br            ccprintf(response, "[");
8812636Sodanrc@yahoo.com.br            if(_srcRegIdx[!store ? 0 : 1] != 0)
8912636Sodanrc@yahoo.com.br            {
9012636Sodanrc@yahoo.com.br                printSrcReg(response, !store ? 0 : 1);
9112636Sodanrc@yahoo.com.br                ccprintf(response, " + ");
9212636Sodanrc@yahoo.com.br            }
9312636Sodanrc@yahoo.com.br            printSrcReg(response, !store ? 1 : 2);
9412636Sodanrc@yahoo.com.br            ccprintf(response, "]");
9512636Sodanrc@yahoo.com.br            if(load)
9612636Sodanrc@yahoo.com.br            {
9712636Sodanrc@yahoo.com.br                ccprintf(response, ", ");
9812636Sodanrc@yahoo.com.br                printReg(response, _destRegIdx[0]);
9912636Sodanrc@yahoo.com.br            }
10012636Sodanrc@yahoo.com.br
10112691Sodanrc@yahoo.com.br            return response.str();
10212691Sodanrc@yahoo.com.br        }
10312691Sodanrc@yahoo.com.br
10412636Sodanrc@yahoo.com.br        std::string MemImm::generateDisassembly(Addr pc,
10512703Snikos.nikoleris@arm.com                const SymbolTable *symtab) const
10612703Snikos.nikoleris@arm.com        {
10712703Snikos.nikoleris@arm.com            std::stringstream response;
10812703Snikos.nikoleris@arm.com            bool load = flags[IsLoad];
10912703Snikos.nikoleris@arm.com            bool save = flags[IsStore];
11012703Snikos.nikoleris@arm.com
11112636Sodanrc@yahoo.com.br            printMnemonic(response, mnemonic);
11212636Sodanrc@yahoo.com.br            if(save)
11312636Sodanrc@yahoo.com.br            {
11412636Sodanrc@yahoo.com.br                printReg(response, _srcRegIdx[0]);
11512636Sodanrc@yahoo.com.br                ccprintf(response, ", ");
11612636Sodanrc@yahoo.com.br            }
1179796Sprakash.ramrakhyani@arm.com            ccprintf(response, "[");
1182810SN/A            if(_srcRegIdx[!save ? 0 : 1] != 0)
11911522Sstephan.diestelhorst@arm.com            {
12011522Sstephan.diestelhorst@arm.com                printReg(response, _srcRegIdx[!save ? 0 : 1]);
1212810SN/A                ccprintf(response, " + ");
12211522Sstephan.diestelhorst@arm.com            }
1232810SN/A            if(imm >= 0)
1249796Sprakash.ramrakhyani@arm.com                ccprintf(response, "0x%x]", imm);
1252810SN/A            else
1262810SN/A                ccprintf(response, "-0x%x]", -imm);
1272810SN/A            if(load)
1282810SN/A            {
1299796Sprakash.ramrakhyani@arm.com                ccprintf(response, ", ");
1302810SN/A                printReg(response, _destRegIdx[0]);
1312810SN/A            }
1322810SN/A
1332810SN/A            return response.str();
1349796Sprakash.ramrakhyani@arm.com        }
1352810SN/A}};
1362810SN/A
1372810SN/A//This template provides the execute functions for a load
1382810SN/Adef template LoadExecute {{
1399796Sprakash.ramrakhyani@arm.com        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
1402810SN/A                Trace::InstRecord *traceData) const
1412810SN/A        {
1422810SN/A            Fault fault = NoFault;
1432810SN/A            Addr EA;
1442810SN/A            %(op_decl)s;
1452810SN/A            %(op_rd)s;
1469796Sprakash.ramrakhyani@arm.com            %(ea_code)s;
1472810SN/A            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
1482810SN/A            %(fault_check)s;
1492810SN/A            if(fault == NoFault)
1506978SLisa.Hsu@amd.com            {
1518833Sdam.sunwoo@arm.com                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s);
1529796Sprakash.ramrakhyani@arm.com            }
1538833Sdam.sunwoo@arm.com            if(fault == NoFault)
1546978SLisa.Hsu@amd.com            {
1556978SLisa.Hsu@amd.com                %(code)s;
1568833Sdam.sunwoo@arm.com            }
1578833Sdam.sunwoo@arm.com            if(fault == NoFault)
1588833Sdam.sunwoo@arm.com            {
1596978SLisa.Hsu@amd.com                    //Write the resulting state to the execution context
1606978SLisa.Hsu@amd.com                    %(op_wb)s;
1619796Sprakash.ramrakhyani@arm.com            }
1626978SLisa.Hsu@amd.com
1638833Sdam.sunwoo@arm.com            return fault;
1646978SLisa.Hsu@amd.com        }
1658833Sdam.sunwoo@arm.com}};
1668833Sdam.sunwoo@arm.com
1678833Sdam.sunwoo@arm.comdef template LoadInitiateAcc {{
1686978SLisa.Hsu@amd.com        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
1696978SLisa.Hsu@amd.com                Trace::InstRecord * traceData) const
1706978SLisa.Hsu@amd.com        {
17110024Sdam.sunwoo@arm.com            Fault fault = NoFault;
17210024Sdam.sunwoo@arm.com            Addr EA;
17310024Sdam.sunwoo@arm.com            %(op_decl)s;
17410024Sdam.sunwoo@arm.com            %(op_rd)s;
17510024Sdam.sunwoo@arm.com            %(ea_code)s;
17610024Sdam.sunwoo@arm.com            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
17710024Sdam.sunwoo@arm.com            %(fault_check)s;
17810024Sdam.sunwoo@arm.com            if(fault == NoFault)
17910024Sdam.sunwoo@arm.com            {
18010024Sdam.sunwoo@arm.com                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s);
18110024Sdam.sunwoo@arm.com            }
18210024Sdam.sunwoo@arm.com            return fault;
18310024Sdam.sunwoo@arm.com        }
18410024Sdam.sunwoo@arm.com}};
18510024Sdam.sunwoo@arm.com
18610024Sdam.sunwoo@arm.comdef template LoadCompleteAcc {{
18710024Sdam.sunwoo@arm.com        Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc,
18810024Sdam.sunwoo@arm.com                Trace::InstRecord * traceData) const
18910024Sdam.sunwoo@arm.com        {
19010024Sdam.sunwoo@arm.com            Fault fault = NoFault;
19110024Sdam.sunwoo@arm.com            %(op_decl)s;
19210024Sdam.sunwoo@arm.com            %(op_rd)s;
19310025Stimothy.jones@arm.com            Mem = pkt->get<typeof(Mem)>();
19410025Stimothy.jones@arm.com            %(code)s;
19510025Stimothy.jones@arm.com            if(fault == NoFault)
19610025Stimothy.jones@arm.com            {
19710025Stimothy.jones@arm.com                %(op_wb)s;
19810025Stimothy.jones@arm.com            }
19910025Stimothy.jones@arm.com            return fault;
20010025Stimothy.jones@arm.com        }
20110025Stimothy.jones@arm.com}};
20210025Stimothy.jones@arm.com
20310024Sdam.sunwoo@arm.com//This template provides the execute functions for a store
2042810SN/Adef template StoreExecute {{
2052810SN/A        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
206                Trace::InstRecord *traceData) const
207        {
208            Fault fault = NoFault;
209            //This is to support the conditional store in cas instructions.
210            //It should be optomized out in all the others
211            bool storeCond = true;
212            Addr EA;
213            %(op_decl)s;
214            %(op_rd)s;
215            %(ea_code)s;
216            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
217            %(fault_check)s;
218            if(fault == NoFault)
219            {
220                %(code)s;
221            }
222            if(storeCond && fault == NoFault)
223            {
224                fault = xc->write((uint%(mem_acc_size)s_t)Mem,
225                        EA, %(asi_val)s, 0);
226            }
227            if(fault == NoFault)
228            {
229                    //Write the resulting state to the execution context
230                    %(op_wb)s;
231            }
232
233            return fault;
234        }
235}};
236
237def template StoreInitiateAcc {{
238        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
239                Trace::InstRecord * traceData) const
240        {
241            Fault fault = NoFault;
242            bool storeCond = true;
243            Addr EA;
244            %(op_decl)s;
245            %(op_rd)s;
246            %(ea_code)s;
247            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
248            %(fault_check)s;
249            if(fault == NoFault)
250            {
251                %(code)s;
252            }
253            if(storeCond && fault == NoFault)
254            {
255                fault = xc->write((uint%(mem_acc_size)s_t)Mem,
256                        EA, %(asi_val)s, 0);
257            }
258            if(fault == NoFault)
259            {
260                    //Write the resulting state to the execution context
261                %(op_wb)s;
262            }
263            return fault;
264        }
265}};
266
267def template StoreCompleteAcc {{
268        Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
269                Trace::InstRecord * traceData) const
270        {
271            return NoFault;
272        }
273}};
274
275//This delcares the initiateAcc function in memory operations
276def template InitiateAccDeclare {{
277    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
278}};
279
280//This declares the completeAcc function in memory operations
281def template CompleteAccDeclare {{
282    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
283}};
284
285//Here are some code snippets which check for various fault conditions
286let {{
287    LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc]
288    StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc]
289    # The LSB can be zero, since it's really the MSB in doubles and quads
290    # and we're dealing with doubles
291    BlockAlignmentFaultCheck = '''
292        if(RD & 0xe)
293            fault = new IllegalInstruction;
294        else if(EA & 0x3f)
295            fault = new MemAddressNotAligned;
296    '''
297    TwinAlignmentFaultCheck = '''
298        if(RD & 0x1)
299            fault = new IllegalInstruction;
300        else if(EA & 0xf)
301            fault = new MemAddressNotAligned;
302    '''
303    # XXX Need to take care of pstate.hpriv as well. The lower ASIs
304    # are split into ones that are available in priv and hpriv, and
305    # those that are only available in hpriv
306    AlternateASIPrivFaultCheck = '''
307        if(!bits(Pstate,2,2) && !bits(Hpstate,2,2) && !AsiIsUnPriv((ASI)EXT_ASI) ||
308                             !bits(Hpstate,2,2) && AsiIsHPriv((ASI)EXT_ASI))
309                fault = new PrivilegedAction;
310        else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2))
311            fault = new PrivilegedAction;
312    '''
313
314}};
315
316//A simple function to generate the name of the macro op of a certain
317//instruction at a certain micropc
318let {{
319    def makeMicroName(name, microPc):
320            return name + "::" + name + "_" + str(microPc)
321}};
322
323//This function properly generates the execute functions for one of the
324//templates above. This is needed because in one case, ea computation,
325//fault checks and the actual code all occur in the same function,
326//and in the other they're distributed across two. Also note that for
327//execute functions, the name of the base class doesn't matter.
328let {{
329    def doSplitExecute(execute, name, Name, asi, opt_flags, microParam):
330        microParam["asi_val"] = asi;
331        iop = InstObjParams(name, Name, '', microParam, opt_flags)
332        (execf, initf, compf) = execute
333        return execf.subst(iop) + initf.subst(iop) + compf.subst(iop)
334
335
336    def doDualSplitExecute(code, eaRegCode, eaImmCode, execute,
337            faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
338        executeCode = ''
339        for (eaCode, name, Name) in (
340                (eaRegCode, nameReg, NameReg),
341                (eaImmCode, nameImm, NameImm)):
342            microParams = {"code": code, "ea_code": eaCode,
343                "fault_check": faultCode}
344            executeCode += doSplitExecute(execute, name, Name,
345                    asi, opt_flags, microParams)
346        return executeCode
347}};
348