branch.isa revision 2665
12934Sktlim@umich.edu// -*- mode:c++ -*-
22934Sktlim@umich.edu
32934Sktlim@umich.edu// Copyright (c) 2003-2005 The Regents of The University of Michigan
42934Sktlim@umich.edu// All rights reserved.
52934Sktlim@umich.edu//
62934Sktlim@umich.edu// Redistribution and use in source and binary forms, with or without
72934Sktlim@umich.edu// modification, are permitted provided that the following conditions are
82934Sktlim@umich.edu// met: redistributions of source code must retain the above copyright
92934Sktlim@umich.edu// notice, this list of conditions and the following disclaimer;
102934Sktlim@umich.edu// redistributions in binary form must reproduce the above copyright
112934Sktlim@umich.edu// notice, this list of conditions and the following disclaimer in the
122934Sktlim@umich.edu// documentation and/or other materials provided with the distribution;
132934Sktlim@umich.edu// neither the name of the copyright holders nor the names of its
142934Sktlim@umich.edu// contributors may be used to endorse or promote products derived from
152934Sktlim@umich.edu// this software without specific prior written permission.
162934Sktlim@umich.edu//
172934Sktlim@umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182934Sktlim@umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192934Sktlim@umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202934Sktlim@umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212934Sktlim@umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222934Sktlim@umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232934Sktlim@umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242934Sktlim@umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252934Sktlim@umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262934Sktlim@umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272934Sktlim@umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282934Sktlim@umich.edu//
292934Sktlim@umich.edu// Authors: Steve Reinhardt
302934Sktlim@umich.edu
312934Sktlim@umich.edu////////////////////////////////////////////////////////////////////
322934Sktlim@umich.edu//
332934Sktlim@umich.edu// Control transfer instructions
342934Sktlim@umich.edu//
352934Sktlim@umich.edu
362934Sktlim@umich.eduoutput header {{
372934Sktlim@umich.edu
382934Sktlim@umich.edu    /**
392934Sktlim@umich.edu     * Base class for instructions whose disassembly is not purely a
402934Sktlim@umich.edu     * function of the machine instruction (i.e., it depends on the
412934Sktlim@umich.edu     * PC).  This class overrides the disassemble() method to check
422934Sktlim@umich.edu     * the PC and symbol table values before re-using a cached
432934Sktlim@umich.edu     * disassembly string.  This is necessary for branches and jumps,
442934Sktlim@umich.edu     * where the disassembly string includes the target address (which
452934Sktlim@umich.edu     * may depend on the PC and/or symbol table).
462934Sktlim@umich.edu     */
472934Sktlim@umich.edu    class PCDependentDisassembly : public AlphaStaticInst
482934Sktlim@umich.edu    {
492934Sktlim@umich.edu      protected:
502934Sktlim@umich.edu        /// Cached program counter from last disassembly
512934Sktlim@umich.edu        mutable Addr cachedPC;
522934Sktlim@umich.edu        /// Cached symbol table pointer from last disassembly
532934Sktlim@umich.edu        mutable const SymbolTable *cachedSymtab;
542934Sktlim@umich.edu
552934Sktlim@umich.edu        /// Constructor
562934Sktlim@umich.edu        PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
572934Sktlim@umich.edu                               OpClass __opClass)
582934Sktlim@umich.edu            : AlphaStaticInst(mnem, _machInst, __opClass),
592934Sktlim@umich.edu              cachedPC(0), cachedSymtab(0)
602934Sktlim@umich.edu        {
612934Sktlim@umich.edu        }
622934Sktlim@umich.edu
632934Sktlim@umich.edu        const std::string &
642934Sktlim@umich.edu        disassemble(Addr pc, const SymbolTable *symtab) const;
652934Sktlim@umich.edu    };
662934Sktlim@umich.edu
672934Sktlim@umich.edu    /**
682934Sktlim@umich.edu     * Base class for branches (PC-relative control transfers),
692934Sktlim@umich.edu     * conditional or unconditional.
702934Sktlim@umich.edu     */
712934Sktlim@umich.edu    class Branch : public PCDependentDisassembly
722934Sktlim@umich.edu    {
732934Sktlim@umich.edu      protected:
742934Sktlim@umich.edu        /// Displacement to target address (signed).
752934Sktlim@umich.edu        int32_t disp;
762934Sktlim@umich.edu
772934Sktlim@umich.edu        /// Constructor.
782934Sktlim@umich.edu        Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
792934Sktlim@umich.edu            : PCDependentDisassembly(mnem, _machInst, __opClass),
802934Sktlim@umich.edu              disp(BRDISP << 2)
812934Sktlim@umich.edu        {
822934Sktlim@umich.edu        }
832934Sktlim@umich.edu
842934Sktlim@umich.edu        Addr branchTarget(Addr branchPC) const;
852934Sktlim@umich.edu
862934Sktlim@umich.edu        std::string
872934Sktlim@umich.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
882934Sktlim@umich.edu    };
892934Sktlim@umich.edu
902934Sktlim@umich.edu    /**
912934Sktlim@umich.edu     * Base class for jumps (register-indirect control transfers).  In
922934Sktlim@umich.edu     * the Alpha ISA, these are always unconditional.
932934Sktlim@umich.edu     */
942934Sktlim@umich.edu    class Jump : public PCDependentDisassembly
952934Sktlim@umich.edu    {
962934Sktlim@umich.edu      protected:
972934Sktlim@umich.edu
982934Sktlim@umich.edu        /// Displacement to target address (signed).
992934Sktlim@umich.edu        int32_t disp;
1002934Sktlim@umich.edu
1012934Sktlim@umich.edu      public:
1022934Sktlim@umich.edu        /// Constructor
1032934Sktlim@umich.edu        Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
1042934Sktlim@umich.edu            : PCDependentDisassembly(mnem, _machInst, __opClass),
105              disp(BRDISP)
106        {
107        }
108
109        Addr branchTarget(ExecContext *xc) const;
110
111        std::string
112        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
113    };
114}};
115
116output decoder {{
117    Addr
118    Branch::branchTarget(Addr branchPC) const
119    {
120        return branchPC + 4 + disp;
121    }
122
123    Addr
124    Jump::branchTarget(ExecContext *xc) const
125    {
126        Addr NPC = xc->readPC() + 4;
127        uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
128        return (Rb & ~3) | (NPC & 1);
129    }
130
131    const std::string &
132    PCDependentDisassembly::disassemble(Addr pc,
133                                        const SymbolTable *symtab) const
134    {
135        if (!cachedDisassembly ||
136            pc != cachedPC || symtab != cachedSymtab)
137        {
138            if (cachedDisassembly)
139                delete cachedDisassembly;
140
141            cachedDisassembly =
142                new std::string(generateDisassembly(pc, symtab));
143            cachedPC = pc;
144            cachedSymtab = symtab;
145        }
146
147        return *cachedDisassembly;
148    }
149
150    std::string
151    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
152    {
153        std::stringstream ss;
154
155        ccprintf(ss, "%-10s ", mnemonic);
156
157        // There's only one register arg (RA), but it could be
158        // either a source (the condition for conditional
159        // branches) or a destination (the link reg for
160        // unconditional branches)
161        if (_numSrcRegs > 0) {
162            printReg(ss, _srcRegIdx[0]);
163            ss << ",";
164        }
165        else if (_numDestRegs > 0) {
166            printReg(ss, _destRegIdx[0]);
167            ss << ",";
168        }
169
170#ifdef SS_COMPATIBLE_DISASSEMBLY
171        if (_numSrcRegs == 0 && _numDestRegs == 0) {
172            printReg(ss, 31);
173            ss << ",";
174        }
175#endif
176
177        Addr target = pc + 4 + disp;
178
179        std::string str;
180        if (symtab && symtab->findSymbol(target, str))
181            ss << str;
182        else
183            ccprintf(ss, "0x%x", target);
184
185        return ss.str();
186    }
187
188    std::string
189    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
190    {
191        std::stringstream ss;
192
193        ccprintf(ss, "%-10s ", mnemonic);
194
195#ifdef SS_COMPATIBLE_DISASSEMBLY
196        if (_numDestRegs == 0) {
197            printReg(ss, 31);
198            ss << ",";
199        }
200#endif
201
202        if (_numDestRegs > 0) {
203            printReg(ss, _destRegIdx[0]);
204            ss << ",";
205        }
206
207        ccprintf(ss, "(r%d)", RB);
208
209        return ss.str();
210    }
211}};
212
213def template JumpOrBranchDecode {{
214    return (RA == 31)
215        ? (StaticInst *)new %(class_name)s(machInst)
216        : (StaticInst *)new %(class_name)sAndLink(machInst);
217}};
218
219def format CondBranch(code) {{
220    code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
221    iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
222                        ('IsDirectControl', 'IsCondControl'))
223    header_output = BasicDeclare.subst(iop)
224    decoder_output = BasicConstructor.subst(iop)
225    decode_block = BasicDecode.subst(iop)
226    exec_output = BasicExecute.subst(iop)
227}};
228
229let {{
230def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
231    # Declare basic control transfer w/o link (i.e. link reg is R31)
232    nolink_code = 'NPC = %s;\n' % npc_expr
233    nolink_iop = InstObjParams(name, Name, base_class,
234                               CodeBlock(nolink_code), flags)
235    header_output = BasicDeclare.subst(nolink_iop)
236    decoder_output = BasicConstructor.subst(nolink_iop)
237    exec_output = BasicExecute.subst(nolink_iop)
238
239    # Generate declaration of '*AndLink' version, append to decls
240    link_code = 'Ra = NPC & ~3;\n' + nolink_code
241    link_iop = InstObjParams(name, Name + 'AndLink', base_class,
242                             CodeBlock(link_code), flags)
243    header_output += BasicDeclare.subst(link_iop)
244    decoder_output += BasicConstructor.subst(link_iop)
245    exec_output += BasicExecute.subst(link_iop)
246
247    # need to use link_iop for the decode template since it is expecting
248    # the shorter version of class_name (w/o "AndLink")
249
250    return (header_output, decoder_output,
251            JumpOrBranchDecode.subst(nolink_iop), exec_output)
252}};
253
254def format UncondBranch(*flags) {{
255    flags += ('IsUncondControl', 'IsDirectControl')
256    (header_output, decoder_output, decode_block, exec_output) = \
257        UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
258}};
259
260def format Jump(*flags) {{
261    flags += ('IsUncondControl', 'IsIndirectControl')
262    (header_output, decoder_output, decode_block, exec_output) = \
263        UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
264}};
265
266
267