branch.isa revision 5222:bb733a878f85
1// -*- mode:c++ -*-
2
3// Copyright .AN) 2007 MIPS Technologies, Inc.  All Rights Reserved
4
5//  This software is part of the M5 simulator.
6
7//  THIS IS A LEGAL AGREEMENT.  BY DOWNLOADING, USING, COPYING, CREATING
8//  DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING
9//  TO THESE TERMS AND CONDITIONS.
10
11//  Permission is granted to use, copy, create derivative works and
12//  distribute this software and such derivative works for any purpose,
13//  so long as (1) the copyright notice above, this grant of permission,
14//  and the disclaimer below appear in all copies and derivative works
15//  made, (2) the copyright notice above is augmented as appropriate to
16//  reflect the addition of any new copyrightable work in a derivative
17//  work (e.g., Copyright .AN) <Publication Year> Copyright Owner), and (3)
18//  the name of MIPS Technologies, Inc. ($B!H(BMIPS$B!I(B) is not used in any
19//  advertising or publicity pertaining to the use or distribution of
20//  this software without specific, written prior authorization.
21
22//  THIS SOFTWARE IS PROVIDED $B!H(BAS IS.$B!I(B  MIPS MAKES NO WARRANTIES AND
23//  DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR
24//  OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25//  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
26//  NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE.
27//  IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT,
28//  INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF
29//  ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT,
30//  THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY
31//  IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR
32//  STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE
33//  POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE.
34
35//Authors: Korey L. Sewell
36
37////////////////////////////////////////////////////////////////////
38//
39// Control transfer instructions
40//
41
42output header {{
43
44#include <iostream>
45    using namespace std;
46
47    /**
48     * Base class for instructions whose disassembly is not purely a
49     * function of the machine instruction (i.e., it depends on the
50     * PC).  This class overrides the disassemble() method to check
51     * the PC and symbol table values before re-using a cached
52     * disassembly string.  This is necessary for branches and jumps,
53     * where the disassembly string includes the target address (which
54     * may depend on the PC and/or symbol table).
55     */
56    class PCDependentDisassembly : public MipsStaticInst
57    {
58      protected:
59        /// Cached program counter from last disassembly
60        mutable Addr cachedPC;
61
62        /// Cached symbol table pointer from last disassembly
63        mutable const SymbolTable *cachedSymtab;
64
65        /// Constructor
66        PCDependentDisassembly(const char *mnem, MachInst _machInst,
67                               OpClass __opClass)
68            : MipsStaticInst(mnem, _machInst, __opClass),
69              cachedPC(0), cachedSymtab(0)
70        {
71        }
72
73        const std::string &
74        disassemble(Addr pc, const SymbolTable *symtab) const;
75    };
76
77    /**
78     * Base class for branches (PC-relative control transfers),
79     * conditional or unconditional.
80     */
81    class Branch : public PCDependentDisassembly
82    {
83      protected:
84        /// target address (signed) Displacement .
85        int32_t disp;
86
87        /// Constructor.
88        Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
89            : PCDependentDisassembly(mnem, _machInst, __opClass),
90              disp(OFFSET << 2)
91        {
92            //If Bit 17 is 1 then Sign Extend
93            if ( (disp & 0x00020000) > 0  ) {
94                disp |= 0xFFFE0000;
95            }
96        }
97
98        Addr branchTarget(Addr branchPC) const;
99
100        std::string
101        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
102    };
103
104    /**
105     * Base class for jumps (register-indirect control transfers).  In
106     * the Mips ISA, these are always unconditional.
107     */
108    class Jump : public PCDependentDisassembly
109    {
110      protected:
111
112        /// Displacement to target address (signed).
113        int32_t disp;
114
115        uint32_t target;
116
117      public:
118        /// Constructor
119        Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
120            : PCDependentDisassembly(mnem, _machInst, __opClass),
121              disp(JMPTARG << 2)
122        {
123        }
124
125        Addr branchTarget(ThreadContext *tc) const;
126
127        std::string
128        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
129    };
130}};
131
132output decoder {{
133    Addr
134    Branch::branchTarget(Addr branchPC) const
135    {
136        return branchPC + 4 + disp;
137    }
138
139    Addr
140    Jump::branchTarget(ThreadContext *tc) const
141    {
142      Addr NPC = tc->readNextPC();
143      return (NPC & 0xF0000000) | (disp);
144    }
145
146    const std::string &
147    PCDependentDisassembly::disassemble(Addr pc,
148                                        const SymbolTable *symtab) const
149    {
150        if (!cachedDisassembly ||
151            pc != cachedPC || symtab != cachedSymtab)
152        {
153            if (cachedDisassembly)
154                delete cachedDisassembly;
155
156            cachedDisassembly =
157                new std::string(generateDisassembly(pc, symtab));
158            cachedPC = pc;
159            cachedSymtab = symtab;
160        }
161
162        return *cachedDisassembly;
163    }
164
165    std::string
166    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
167    {
168        std::stringstream ss;
169
170        ccprintf(ss, "%-10s ", mnemonic);
171
172        // There's only one register arg (RA), but it could be
173        // either a source (the condition for conditional
174        // branches) or a destination (the link reg for
175        // unconditional branches)
176        if (_numSrcRegs == 1) {
177            printReg(ss, _srcRegIdx[0]);
178            ss << ", ";
179        } else if(_numSrcRegs == 2) {
180            printReg(ss, _srcRegIdx[0]);
181            ss << ", ";
182            printReg(ss, _srcRegIdx[1]);
183            ss << ", ";
184        }
185
186        Addr target = pc + 4 + disp;
187
188        std::string str;
189        if (symtab && symtab->findSymbol(target, str))
190            ss << str;
191        else
192            ccprintf(ss, "0x%x", target);
193
194        return ss.str();
195    }
196
197    std::string
198    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
199    {
200        std::stringstream ss;
201
202        ccprintf(ss, "%-10s ", mnemonic);
203
204        if ( mnemonic == "jal" ) {
205            Addr npc = pc + 4;
206            ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
207        } else if (_numSrcRegs == 0) {
208            std::string str;
209            if (symtab && symtab->findSymbol(disp, str))
210                ss << str;
211            else
212                ccprintf(ss, "0x%x", disp);
213        } else if (_numSrcRegs == 1) {
214             printReg(ss, _srcRegIdx[0]);
215        } else if(_numSrcRegs == 2) {
216            printReg(ss, _srcRegIdx[0]);
217            ss << ", ";
218            printReg(ss, _srcRegIdx[1]);
219        }
220
221        return ss.str();
222    }
223}};
224
225def format Branch(code, *opt_flags) {{
226    not_taken_code = '  NNPC = NNPC;\n'
227    not_taken_code += '} \n'
228
229    #Build Instruction Flags
230    #Use Link & Likely Flags to Add Link/Condition Code
231    inst_flags = ('IsDirectControl', )
232    for x in opt_flags:
233        if x == 'Link':
234            code += 'R31 = NNPC;\n'
235        elif x == 'Likely':
236            not_taken_code = '  NPC = NNPC;\n'
237            not_taken_code += '  NNPC = NNPC + 4;\n'
238            not_taken_code += '} \n'
239            inst_flags += ('IsCondDelaySlot', )
240        else:
241            inst_flags += (x, )
242
243    #Take into account uncond. branch instruction
244    if 'cond = 1' in code:
245         inst_flags += ('IsUncondControl', )
246    else:
247         inst_flags += ('IsCondControl', )
248
249    #Condition code
250    code = 'bool cond;\n' + code
251    code += 'if (cond) {\n'
252    code += '  NNPC = NPC + disp;\n'
253    code += '} else {\n'
254    code += not_taken_code
255
256    iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
257    header_output = BasicDeclare.subst(iop)
258    decoder_output = BasicConstructor.subst(iop)
259    decode_block = BasicDecode.subst(iop)
260    exec_output = BasicExecute.subst(iop)
261}};
262
263def format DspBranch(code, *opt_flags) {{
264    not_taken_code = '  NNPC = NNPC;\n'
265    not_taken_code += '} \n'
266
267    #Build Instruction Flags
268    #Use Link & Likely Flags to Add Link/Condition Code
269    inst_flags = ('IsDirectControl', )
270    for x in opt_flags:
271        if x == 'Link':
272            code += 'R31 = NNPC;\n'
273        elif x == 'Likely':
274            not_taken_code = '  NPC = NNPC;\n'
275            not_taken_code += '  NNPC = NNPC + 4;\n'
276            not_taken_code += '} \n'
277            inst_flags += ('IsCondDelaySlot', )
278        else:
279            inst_flags += (x, )
280
281    #Take into account uncond. branch instruction
282    if 'cond = 1' in code:
283         inst_flags += ('IsUncondControl', )
284    else:
285         inst_flags += ('IsCondControl', )
286
287    #Declaration code
288    decl_code = 'bool cond;\n'
289    decl_code += 'uint32_t dspctl;\n'
290
291    #Fetch code
292    fetch_code = 'dspctl = DSPControl;\n'
293
294    #Condition code
295    code = decl_code + fetch_code + code
296    code += 'if (cond) {\n'
297    code += '  NNPC = NPC + disp;\n'
298    code += '} else {\n'
299    code += not_taken_code
300
301    iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
302    header_output = BasicDeclare.subst(iop)
303    decoder_output = BasicConstructor.subst(iop)
304    decode_block = BasicDecode.subst(iop)
305    exec_output = BasicExecute.subst(iop)
306}};
307
308def format Jump(code, *opt_flags) {{
309    #Build Instruction Flags
310    #Use Link Flag to Add Link Code
311    inst_flags = ('IsIndirectControl', 'IsUncondControl')
312    for x in opt_flags:
313        if x == 'Link':
314            code = 'R31 = NNPC;\n' + code
315        elif x == 'ClearHazards':
316            code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
317        else:
318            inst_flags += (x, )
319
320    iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
321    header_output = BasicDeclare.subst(iop)
322    decoder_output = BasicConstructor.subst(iop)
323    decode_block = BasicDecode.subst(iop)
324    exec_output = BasicExecute.subst(iop)
325}};
326
327
328
329
330