branch.isa revision 3985
12348SN/A// Copyright (c) 2006-2007 The Regents of The University of Michigan
22348SN/A// All rights reserved.
32348SN/A//
42348SN/A// Redistribution and use in source and binary forms, with or without
52348SN/A// modification, are permitted provided that the following conditions are
62348SN/A// met: redistributions of source code must retain the above copyright
72348SN/A// notice, this list of conditions and the following disclaimer;
82348SN/A// redistributions in binary form must reproduce the above copyright
92348SN/A// notice, this list of conditions and the following disclaimer in the
102348SN/A// documentation and/or other materials provided with the distribution;
112348SN/A// neither the name of the copyright holders nor the names of its
122348SN/A// contributors may be used to endorse or promote products derived from
132348SN/A// this software without specific prior written permission.
142348SN/A//
152348SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162348SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172348SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182348SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
192348SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
202348SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212348SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222348SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232348SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242348SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
252348SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262348SN/A//
272689Sktlim@umich.edu// Authors: Gabe Black
282689Sktlim@umich.edu//          Steve Reinhardt
292348SN/A
302325SN/A////////////////////////////////////////////////////////////////////
315804Snate@binkert.org//
323918Ssaidi@eecs.umich.edu// Branch instructions
338229Snate@binkert.org//
347813Ssteve.reinhardt@amd.com
358232Snate@binkert.orgoutput header {{
362325SN/A        /**
375804Snate@binkert.org         * Base class for branch operations.
385804Snate@binkert.org         */
395804Snate@binkert.org        class Branch : public SparcStaticInst
405804Snate@binkert.org        {
415804Snate@binkert.org          protected:
425804Snate@binkert.org            // Constructor
435804Snate@binkert.org            Branch(const char *mnem, MachInst _machInst, OpClass __opClass) :
442325SN/A                SparcStaticInst(mnem, _machInst, __opClass)
452325SN/A            {
463918Ssaidi@eecs.umich.edu            }
472325SN/A
482325SN/A            std::string generateDisassembly(Addr pc,
492325SN/A                    const SymbolTable *symtab) const;
502325SN/A        };
512325SN/A
522348SN/A        /**
532348SN/A         * Base class for branch operations with an immediate displacement.
542325SN/A         */
552325SN/A        class BranchDisp : public Branch
562325SN/A        {
572325SN/A          protected:
582325SN/A            // Constructor
592325SN/A            BranchDisp(const char *mnem, MachInst _machInst,
602325SN/A                    OpClass __opClass) :
612325SN/A                Branch(mnem, _machInst, __opClass)
622325SN/A            {
632325SN/A            }
642325SN/A
652325SN/A            std::string generateDisassembly(Addr pc,
662325SN/A                    const SymbolTable *symtab) const;
672325SN/A
682348SN/A            int32_t disp;
692348SN/A        };
702325SN/A
712325SN/A        /**
722325SN/A         * Base class for branches with n bit displacements.
732325SN/A         */
742325SN/A        template<int bits>
752325SN/A        class BranchNBits : public BranchDisp
762325SN/A        {
772325SN/A          protected:
782325SN/A            // Constructor
792325SN/A            BranchNBits(const char *mnem, MachInst _machInst,
802325SN/A                    OpClass __opClass) :
812325SN/A                BranchDisp(mnem, _machInst, __opClass)
822325SN/A            {
832325SN/A                disp = sext<bits + 2>((_machInst & mask(bits)) << 2);
842325SN/A            }
852325SN/A        };
862325SN/A
872325SN/A        /**
882348SN/A         * Base class for 16bit split displacements.
892325SN/A         */
902325SN/A        class BranchSplit : public BranchDisp
912325SN/A        {
922325SN/A          protected:
932325SN/A            // Constructor
942325SN/A            BranchSplit(const char *mnem, MachInst _machInst,
952325SN/A                    OpClass __opClass) :
962325SN/A                BranchDisp(mnem, _machInst, __opClass)
972325SN/A            {
982325SN/A                disp = sext<18>((D16HI << 16) | (D16LO << 2));
992325SN/A            }
1002325SN/A        };
1012325SN/A
1022325SN/A        /**
1032325SN/A         * Base class for branches that use an immediate and a register to
1042325SN/A         * compute their displacements.
1052348SN/A         */
1062325SN/A        class BranchImm13 : public Branch
1072325SN/A        {
1082325SN/A          protected:
1092325SN/A            // Constructor
1102325SN/A            BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) :
1112325SN/A                Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
1122325SN/A            {
1132325SN/A            }
1142325SN/A
1152325SN/A            std::string generateDisassembly(Addr pc,
1162325SN/A                    const SymbolTable *symtab) const;
1172325SN/A
1182325SN/A            int32_t imm;
1192325SN/A        };
1202325SN/A}};
1212325SN/A
1222325SN/Aoutput decoder {{
1233918Ssaidi@eecs.umich.edu
1242325SN/A        template class BranchNBits<19>;
1252325SN/A
1262325SN/A        template class BranchNBits<22>;
1272325SN/A
1282325SN/A        template class BranchNBits<30>;
1292325SN/A
1302325SN/A        std::string Branch::generateDisassembly(Addr pc,
1312325SN/A                const SymbolTable *symtab) const
1322325SN/A        {
1332325SN/A            std::stringstream response;
1342325SN/A
1352325SN/A            printMnemonic(response, mnemonic);
1362325SN/A            printRegArray(response, _srcRegIdx, _numSrcRegs);
1372325SN/A            if(_numDestRegs && _numSrcRegs)
1382325SN/A                    response << ", ";
1392325SN/A            printDestReg(response, 0);
1402325SN/A
1412325SN/A            return response.str();
1422325SN/A        }
1432325SN/A
1442325SN/A        std::string BranchImm13::generateDisassembly(Addr pc,
1452325SN/A                const SymbolTable *symtab) const
1462325SN/A        {
1472325SN/A            std::stringstream response;
1482325SN/A
1492325SN/A            printMnemonic(response, mnemonic);
1502325SN/A            printRegArray(response, _srcRegIdx, _numSrcRegs);
1512325SN/A            if(_numSrcRegs > 0)
1522325SN/A                response << ", ";
1532325SN/A            ccprintf(response, "0x%x", imm);
1542325SN/A            if (_numDestRegs > 0)
1552325SN/A                response << ", ";
1562325SN/A            printDestReg(response, 0);
1572325SN/A
1582325SN/A            return response.str();
1592325SN/A        }
1602325SN/A
1612325SN/A        std::string BranchDisp::generateDisassembly(Addr pc,
1622325SN/A                const SymbolTable *symtab) const
1632325SN/A        {
164            std::stringstream response;
165            std::string symbol;
166            Addr symbolAddr;
167
168            Addr target = disp + pc;
169
170            printMnemonic(response, mnemonic);
171            ccprintf(response, "0x%x", target);
172
173            if(symtab && symtab->findNearestSymbol(target, symbol, symbolAddr))
174            {
175                ccprintf(response, " <%s", symbol);
176                if(symbolAddr != target)
177                    ccprintf(response, "+%d>", target - symbolAddr);
178                else
179                    ccprintf(response, ">");
180            }
181
182            return response.str();
183        }
184}};
185
186def template BranchExecute {{
187        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
188                Trace::InstRecord *traceData) const
189        {
190            //Attempt to execute the instruction
191            Fault fault = NoFault;
192
193            %(op_decl)s;
194            %(op_rd)s;
195
196            NNPC = xc->readNextNPC();
197            %(code)s;
198
199            if(fault == NoFault)
200            {
201                //Write the resulting state to the execution context
202                %(op_wb)s;
203            }
204
205            return fault;
206        }
207}};
208
209let {{
210    handle_annul = '''
211    {
212        if(A)
213        {
214            NPC = xc->readNextNPC();
215            NNPC = NPC + 4;
216        }
217        else
218        {
219            NPC = xc->readNextPC();
220            NNPC = xc->readNextNPC();
221        }
222    }'''
223}};
224
225// Primary format for branch instructions:
226def format Branch(code, *opt_flags) {{
227        (usesImm, code, immCode,
228         rString, iString) = splitOutImm(code)
229        iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
230        header_output = BasicDeclare.subst(iop)
231        decoder_output = BasicConstructor.subst(iop)
232        exec_output = BranchExecute.subst(iop)
233        if usesImm:
234            imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
235                    immCode, opt_flags)
236            header_output += BasicDeclare.subst(imm_iop)
237            decoder_output += BasicConstructor.subst(imm_iop)
238            exec_output += BranchExecute.subst(imm_iop)
239            decode_block = ROrImmDecode.subst(iop)
240        else:
241            decode_block = BasicDecode.subst(iop)
242}};
243
244// Primary format for branch instructions:
245def format BranchN(bits, code, *opt_flags) {{
246        code = re.sub(r'handle_annul', handle_annul, code)
247        new_opt_flags = []
248        for flag in opt_flags:
249            if flag == ',a':
250                name += ',a'
251                Name += 'Annul'
252            else:
253                new_opt_flags += flag
254        iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, code, new_opt_flags)
255        header_output = BasicDeclare.subst(iop)
256        decoder_output = BasicConstructor.subst(iop)
257        exec_output = BranchExecute.subst(iop)
258        decode_block = BasicDecode.subst(iop)
259}};
260
261// Primary format for branch instructions:
262def format BranchSplit(code, *opt_flags) {{
263        code = re.sub(r'handle_annul', handle_annul, code)
264        iop = InstObjParams(name, Name, 'BranchSplit', code, opt_flags)
265        header_output = BasicDeclare.subst(iop)
266        decoder_output = BasicConstructor.subst(iop)
267        exec_output = BranchExecute.subst(iop)
268        decode_block = BasicDecode.subst(iop)
269}};
270
271