branch.isa revision 3273:5aa5cc05fff9
1298SN/A// Copyright (c) 2006 The Regents of The University of Michigan
211270Sandreas.sandberg@arm.com// All rights reserved.
38142SAli.Saidi@ARM.com//
48142SAli.Saidi@ARM.com// Redistribution and use in source and binary forms, with or without
58142SAli.Saidi@ARM.com// modification, are permitted provided that the following conditions are
68142SAli.Saidi@ARM.com// met: redistributions of source code must retain the above copyright
78142SAli.Saidi@ARM.com// notice, this list of conditions and the following disclaimer;
88142SAli.Saidi@ARM.com// redistributions in binary form must reproduce the above copyright
98142SAli.Saidi@ARM.com// notice, this list of conditions and the following disclaimer in the
108142SAli.Saidi@ARM.com// documentation and/or other materials provided with the distribution;
118142SAli.Saidi@ARM.com// neither the name of the copyright holders nor the names of its
128142SAli.Saidi@ARM.com// contributors may be used to endorse or promote products derived from
138142SAli.Saidi@ARM.com// this software without specific prior written permission.
148580Ssteve.reinhardt@amd.com//
152188SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16298SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17298SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18298SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19298SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20298SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21298SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22298SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23298SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24298SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25298SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26298SN/A//
27298SN/A// Authors: Gabe Black
28298SN/A//          Steve Reinhardt
29298SN/A
30298SN/A////////////////////////////////////////////////////////////////////
31298SN/A//
32298SN/A// Branch instructions
33298SN/A//
34298SN/A
35298SN/Aoutput header {{
36298SN/A        /**
37298SN/A         * Base class for branch operations.
38298SN/A         */
39298SN/A        class Branch : public SparcStaticInst
402665Ssaidi@eecs.umich.edu        {
412665Ssaidi@eecs.umich.edu          protected:
42298SN/A            // Constructor
43298SN/A            Branch(const char *mnem, MachInst _machInst, OpClass __opClass) :
44954SN/A                SparcStaticInst(mnem, _machInst, __opClass)
45956SN/A            {
46956SN/A            }
478229Snate@binkert.org
484078Sbinkertn@umich.edu            std::string generateDisassembly(Addr pc,
49299SN/A                    const SymbolTable *symtab) const;
509659SAndreas.Sandberg@ARM.com        };
51299SN/A
528777Sgblack@eecs.umich.edu        /**
539659SAndreas.Sandberg@ARM.com         * Base class for branch operations with an immediate displacement.
542170SN/A         */
5510553Salexandru.dutu@amd.com        class BranchDisp : public Branch
565882Snate@binkert.org        {
578734Sdam.sunwoo@arm.com          protected:
586658Snate@binkert.org            // Constructor
591717SN/A            BranchDisp(const char *mnem, MachInst _machInst,
608229Snate@binkert.org                    OpClass __opClass) :
612680Sktlim@umich.edu                Branch(mnem, _machInst, __opClass)
628232Snate@binkert.org            {
639733Sandreas@sandberg.pp.se            }
648232Snate@binkert.org
658232Snate@binkert.org            std::string generateDisassembly(Addr pc,
6611290Sgabor.dozsa@arm.com                    const SymbolTable *symtab) const;
675529Snate@binkert.org
688784Sgblack@eecs.umich.edu            int32_t disp;
6911290Sgabor.dozsa@arm.com        };
7010553Salexandru.dutu@amd.com
713565Sgblack@eecs.umich.edu        /**
72298SN/A         * Base class for branches with n bit displacements.
735606Snate@binkert.org         */
74298SN/A        template<int bits>
75695SN/A        class BranchNBits : public BranchDisp
76695SN/A        {
77954SN/A          protected:
782080SN/A            // Constructor
79298SN/A            BranchNBits(const char *mnem, MachInst _machInst,
80299SN/A                    OpClass __opClass) :
811052SN/A                BranchDisp(mnem, _machInst, __opClass)
82729SN/A            {
832107SN/A                disp = sext<bits + 2>((_machInst & mask(bits)) << 2);
84298SN/A            }
855504Snate@binkert.org        };
865504Snate@binkert.org
878784Sgblack@eecs.umich.edu        /**
888784Sgblack@eecs.umich.edu         * Base class for 16bit split displacements.
898784Sgblack@eecs.umich.edu         */
908784Sgblack@eecs.umich.edu        class BranchSplit : public BranchDisp
918784Sgblack@eecs.umich.edu        {
925780Ssteve.reinhardt@amd.com          protected:
939659SAndreas.Sandberg@ARM.com            // Constructor
949659SAndreas.Sandberg@ARM.com            BranchSplit(const char *mnem, MachInst _machInst,
959659SAndreas.Sandberg@ARM.com                    OpClass __opClass) :
969659SAndreas.Sandberg@ARM.com                BranchDisp(mnem, _machInst, __opClass)
979659SAndreas.Sandberg@ARM.com            {
989733Sandreas@sandberg.pp.se                disp = sext<18>((D16HI << 16) | (D16LO << 2));
999733Sandreas@sandberg.pp.se            }
1009659SAndreas.Sandberg@ARM.com        };
1019659SAndreas.Sandberg@ARM.com
1029659SAndreas.Sandberg@ARM.com        /**
1039659SAndreas.Sandberg@ARM.com         * Base class for branches that use an immediate and a register to
1049659SAndreas.Sandberg@ARM.com         * compute their displacements.
1059879Sandreas@sandberg.pp.se         */
1069879Sandreas@sandberg.pp.se        class BranchImm13 : public Branch
1079879Sandreas@sandberg.pp.se        {
1089879Sandreas@sandberg.pp.se          protected:
1099659SAndreas.Sandberg@ARM.com            // Constructor
1109659SAndreas.Sandberg@ARM.com            BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) :
1119659SAndreas.Sandberg@ARM.com                Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
1129659SAndreas.Sandberg@ARM.com            {
1139659SAndreas.Sandberg@ARM.com            }
1149659SAndreas.Sandberg@ARM.com
1159659SAndreas.Sandberg@ARM.com            std::string generateDisassembly(Addr pc,
1169659SAndreas.Sandberg@ARM.com                    const SymbolTable *symtab) const;
1179659SAndreas.Sandberg@ARM.com
1189659SAndreas.Sandberg@ARM.com            int32_t imm;
1199659SAndreas.Sandberg@ARM.com        };
1209659SAndreas.Sandberg@ARM.com}};
1219659SAndreas.Sandberg@ARM.com
1229659SAndreas.Sandberg@ARM.comoutput decoder {{
1239659SAndreas.Sandberg@ARM.com
1249659SAndreas.Sandberg@ARM.com        template class BranchNBits<19>;
1259659SAndreas.Sandberg@ARM.com
1269659SAndreas.Sandberg@ARM.com        template class BranchNBits<22>;
1279659SAndreas.Sandberg@ARM.com
1289659SAndreas.Sandberg@ARM.com        template class BranchNBits<30>;
1299659SAndreas.Sandberg@ARM.com
1309659SAndreas.Sandberg@ARM.com        std::string Branch::generateDisassembly(Addr pc,
1319659SAndreas.Sandberg@ARM.com                const SymbolTable *symtab) const
1329659SAndreas.Sandberg@ARM.com        {
1339659SAndreas.Sandberg@ARM.com            std::stringstream response;
1349659SAndreas.Sandberg@ARM.com
1359659SAndreas.Sandberg@ARM.com            printMnemonic(response, mnemonic);
1369659SAndreas.Sandberg@ARM.com            printRegArray(response, _srcRegIdx, _numSrcRegs);
1379659SAndreas.Sandberg@ARM.com            if(_numDestRegs && _numSrcRegs)
1389659SAndreas.Sandberg@ARM.com                    response << ", ";
1399659SAndreas.Sandberg@ARM.com            printDestReg(response, 0);
1409659SAndreas.Sandberg@ARM.com
1419681Sandreas@sandberg.pp.se            return response.str();
1429681Sandreas@sandberg.pp.se        }
1439681Sandreas@sandberg.pp.se
1449681Sandreas@sandberg.pp.se        std::string BranchImm13::generateDisassembly(Addr pc,
1459659SAndreas.Sandberg@ARM.com                const SymbolTable *symtab) const
14611289Sgabor.dozsa@arm.com        {
1479659SAndreas.Sandberg@ARM.com            std::stringstream response;
1489659SAndreas.Sandberg@ARM.com
1499659SAndreas.Sandberg@ARM.com            printMnemonic(response, mnemonic);
1509659SAndreas.Sandberg@ARM.com            printRegArray(response, _srcRegIdx, _numSrcRegs);
1519659SAndreas.Sandberg@ARM.com            if(_numSrcRegs > 0)
1529659SAndreas.Sandberg@ARM.com                response << ", ";
1539659SAndreas.Sandberg@ARM.com            ccprintf(response, "0x%x", imm);
1549659SAndreas.Sandberg@ARM.com            if (_numDestRegs > 0)
1559659SAndreas.Sandberg@ARM.com                response << ", ";
1569659SAndreas.Sandberg@ARM.com            printDestReg(response, 0);
1579659SAndreas.Sandberg@ARM.com
1589659SAndreas.Sandberg@ARM.com            return response.str();
1599659SAndreas.Sandberg@ARM.com        }
1609659SAndreas.Sandberg@ARM.com
1619659SAndreas.Sandberg@ARM.com        std::string BranchDisp::generateDisassembly(Addr pc,
1629659SAndreas.Sandberg@ARM.com                const SymbolTable *symtab) const
1639659SAndreas.Sandberg@ARM.com        {
1649659SAndreas.Sandberg@ARM.com            std::stringstream response;
1659659SAndreas.Sandberg@ARM.com            std::string symbol;
1669659SAndreas.Sandberg@ARM.com            Addr symbolAddr;
1679659SAndreas.Sandberg@ARM.com
1689659SAndreas.Sandberg@ARM.com            Addr target = disp + pc;
1699659SAndreas.Sandberg@ARM.com
1709659SAndreas.Sandberg@ARM.com            printMnemonic(response, mnemonic);
1719659SAndreas.Sandberg@ARM.com            ccprintf(response, "0x%x", target);
1729659SAndreas.Sandberg@ARM.com
1739659SAndreas.Sandberg@ARM.com            if(symtab->findNearestSymbol(target, symbol, symbolAddr))
1749659SAndreas.Sandberg@ARM.com            {
1759659SAndreas.Sandberg@ARM.com                ccprintf(response, " <%s", symbol);
1769659SAndreas.Sandberg@ARM.com                if(symbolAddr != target)
1779659SAndreas.Sandberg@ARM.com                    ccprintf(response, "+%d>", target - symbolAddr);
1789659SAndreas.Sandberg@ARM.com                else
1799659SAndreas.Sandberg@ARM.com                    ccprintf(response, ">");
1809659SAndreas.Sandberg@ARM.com            }
1819659SAndreas.Sandberg@ARM.com
1829659SAndreas.Sandberg@ARM.com            return response.str();
1839659SAndreas.Sandberg@ARM.com        }
1849659SAndreas.Sandberg@ARM.com}};
1859659SAndreas.Sandberg@ARM.com
1869659SAndreas.Sandberg@ARM.comdef template BranchExecute {{
1879659SAndreas.Sandberg@ARM.com        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
1889659SAndreas.Sandberg@ARM.com                Trace::InstRecord *traceData) const
1899659SAndreas.Sandberg@ARM.com        {
1909659SAndreas.Sandberg@ARM.com            //Attempt to execute the instruction
1919659SAndreas.Sandberg@ARM.com            Fault fault = NoFault;
1929659SAndreas.Sandberg@ARM.com
1939659SAndreas.Sandberg@ARM.com            %(op_decl)s;
1949659SAndreas.Sandberg@ARM.com            %(op_rd)s;
1959659SAndreas.Sandberg@ARM.com
1969659SAndreas.Sandberg@ARM.com            NNPC = xc->readNextNPC();
1979659SAndreas.Sandberg@ARM.com            %(code)s;
1989659SAndreas.Sandberg@ARM.com
1999659SAndreas.Sandberg@ARM.com            if(fault == NoFault)
2009659SAndreas.Sandberg@ARM.com            {
2019659SAndreas.Sandberg@ARM.com                //Write the resulting state to the execution context
2029659SAndreas.Sandberg@ARM.com                %(op_wb)s;
2039659SAndreas.Sandberg@ARM.com            }
2049659SAndreas.Sandberg@ARM.com
20510553Salexandru.dutu@amd.com            return fault;
20610553Salexandru.dutu@amd.com        }
20710553Salexandru.dutu@amd.com}};
20810553Salexandru.dutu@amd.com
20910553Salexandru.dutu@amd.comlet {{
21010553Salexandru.dutu@amd.com    handle_annul = '''
21110553Salexandru.dutu@amd.com    {
21210553Salexandru.dutu@amd.com        if(A)
21310553Salexandru.dutu@amd.com        {
2149659SAndreas.Sandberg@ARM.com            NPC = xc->readNextNPC();
2159659SAndreas.Sandberg@ARM.com            NNPC = NPC + 4;
2169659SAndreas.Sandberg@ARM.com        }
2179659SAndreas.Sandberg@ARM.com        else
2189659SAndreas.Sandberg@ARM.com        {
2199659SAndreas.Sandberg@ARM.com            NPC = xc->readNextPC();
2209659SAndreas.Sandberg@ARM.com            NNPC = xc->readNextNPC();
2219659SAndreas.Sandberg@ARM.com        }
2225504Snate@binkert.org    }'''
2235504Snate@binkert.org}};
224298SN/A
2259733Sandreas@sandberg.pp.se// Primary format for branch instructions:
2268806Sgblack@eecs.umich.edudef format Branch(code, *opt_flags) {{
2278784Sgblack@eecs.umich.edu        (usesImm, code, immCode,
2288806Sgblack@eecs.umich.edu         rString, iString) = splitOutImm(code)
2295504Snate@binkert.org        iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
2305504Snate@binkert.org        header_output = BasicDeclare.subst(iop)
2315504Snate@binkert.org        decoder_output = BasicConstructor.subst(iop)
2325504Snate@binkert.org        exec_output = BranchExecute.subst(iop)
2335504Snate@binkert.org        if usesImm:
2345504Snate@binkert.org            imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
2355504Snate@binkert.org                    immCode, opt_flags)
2369733Sandreas@sandberg.pp.se            header_output += BasicDeclare.subst(imm_iop)
2378806Sgblack@eecs.umich.edu            decoder_output += BasicConstructor.subst(imm_iop)
2388806Sgblack@eecs.umich.edu            exec_output += BranchExecute.subst(imm_iop)
2398666SPrakash.Ramrakhyani@arm.com            decode_block = ROrImmDecode.subst(iop)
2405529Snate@binkert.org        else:
2415504Snate@binkert.org            decode_block = BasicDecode.subst(iop)
2425504Snate@binkert.org}};
2435504Snate@binkert.org
2445504Snate@binkert.org// Primary format for branch instructions:
2455504Snate@binkert.orgdef format BranchN(bits, code, *opt_flags) {{
2465504Snate@binkert.org        code = re.sub(r'handle_annul', handle_annul, code)
2475504Snate@binkert.org        codeBlk = CodeBlock(code)
2485504Snate@binkert.org        new_opt_flags = []
2495504Snate@binkert.org        for flag in opt_flags:
2505504Snate@binkert.org            if flag == ',a':
2518142SAli.Saidi@ARM.com                name += ',a'
2528142SAli.Saidi@ARM.com                Name += 'Annul'
2539733Sandreas@sandberg.pp.se            else:
2548806Sgblack@eecs.umich.edu                new_opt_flags += flag
2558806Sgblack@eecs.umich.edu        iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, new_opt_flags)
2568666SPrakash.Ramrakhyani@arm.com        header_output = BasicDeclare.subst(iop)
2578142SAli.Saidi@ARM.com        decoder_output = BasicConstructor.subst(iop)
2588142SAli.Saidi@ARM.com        exec_output = BranchExecute.subst(iop)
2598142SAli.Saidi@ARM.com        decode_block = BasicDecode.subst(iop)
2608142SAli.Saidi@ARM.com}};
2618142SAli.Saidi@ARM.com
2628142SAli.Saidi@ARM.com// Primary format for branch instructions:
2638142SAli.Saidi@ARM.comdef format BranchSplit(code, *opt_flags) {{
2648142SAli.Saidi@ARM.com        code = re.sub(r'handle_annul', handle_annul, code)
2658142SAli.Saidi@ARM.com        codeBlk = CodeBlock(code)
2668142SAli.Saidi@ARM.com        iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags)
2678142SAli.Saidi@ARM.com        header_output = BasicDeclare.subst(iop)
2688142SAli.Saidi@ARM.com        decoder_output = BasicConstructor.subst(iop)
2698142SAli.Saidi@ARM.com        exec_output = BranchExecute.subst(iop)
2708142SAli.Saidi@ARM.com        decode_block = BasicDecode.subst(iop)
2718142SAli.Saidi@ARM.com}};
2728142SAli.Saidi@ARM.com
2738142SAli.Saidi@ARM.com