branch.isa revision 6019
1// -*- mode:c++ -*-
2
3// Copyright (c) 2007-2008 The Florida State University
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Stephen Hines
30
31////////////////////////////////////////////////////////////////////
32//
33// Control transfer instructions
34//
35
36output header {{
37
38#include <iostream>
39
40    /**
41     * Base class for instructions whose disassembly is not purely a
42     * function of the machine instruction (i.e., it depends on the
43     * PC).  This class overrides the disassemble() method to check
44     * the PC and symbol table values before re-using a cached
45     * disassembly string.  This is necessary for branches and jumps,
46     * where the disassembly string includes the target address (which
47     * may depend on the PC and/or symbol table).
48     */
49    class PCDependentDisassembly : public PredOp
50    {
51      protected:
52        /// Cached program counter from last disassembly
53        mutable Addr cachedPC;
54
55        /// Cached symbol table pointer from last disassembly
56        mutable const SymbolTable *cachedSymtab;
57
58        /// Constructor
59        PCDependentDisassembly(const char *mnem, MachInst _machInst,
60                               OpClass __opClass)
61            : PredOp(mnem, _machInst, __opClass),
62              cachedPC(0), cachedSymtab(0)
63        {
64        }
65
66        const std::string &
67        disassemble(Addr pc, const SymbolTable *symtab) const;
68    };
69
70    /**
71     * Base class for branches (PC-relative control transfers),
72     * conditional or unconditional.
73     */
74    class Branch : public PCDependentDisassembly
75    {
76      protected:
77        /// target address (signed) Displacement .
78        int32_t disp;
79
80        /// Constructor.
81        Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
82            : PCDependentDisassembly(mnem, _machInst, __opClass),
83              disp(OFFSET << 2)
84        {
85            //If Bit 26 is 1 then Sign Extend
86            if ( (disp & 0x02000000) > 0  ) {
87                disp |=  0xFC000000;
88            }
89        }
90
91        Addr branchTarget(Addr branchPC) const;
92
93        std::string
94        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
95    };
96
97    /**
98     * Base class for branch and exchange instructions on the ARM
99     */
100    class BranchExchange : public PredOp
101    {
102      protected:
103        /// Constructor
104        BranchExchange(const char *mnem, MachInst _machInst,
105                               OpClass __opClass)
106            : PredOp(mnem, _machInst, __opClass)
107        {
108        }
109
110        std::string
111        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
112    };
113
114
115    /**
116     * Base class for jumps (register-indirect control transfers).  In
117     * the Arm ISA, these are always unconditional.
118     */
119    class Jump : public PCDependentDisassembly
120    {
121      protected:
122
123        /// Displacement to target address (signed).
124        int32_t disp;
125
126        uint32_t target;
127
128      public:
129        /// Constructor
130        Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
131            : PCDependentDisassembly(mnem, _machInst, __opClass),
132              disp(OFFSET << 2)
133        {
134        }
135
136        Addr branchTarget(ThreadContext *tc) const;
137
138        std::string
139        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
140    };
141}};
142
143output decoder {{
144    Addr
145    Branch::branchTarget(Addr branchPC) const
146    {
147        return branchPC + 8 + disp;
148    }
149
150    Addr
151    Jump::branchTarget(ThreadContext *tc) const
152    {
153        Addr NPC = tc->readPC() + 8;
154        uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
155        return (Rb & ~3) | (NPC & 1);
156    }
157
158    const std::string &
159    PCDependentDisassembly::disassemble(Addr pc,
160                                        const SymbolTable *symtab) const
161    {
162        if (!cachedDisassembly ||
163            pc != cachedPC || symtab != cachedSymtab)
164        {
165            if (cachedDisassembly)
166                delete cachedDisassembly;
167
168            cachedDisassembly =
169                new std::string(generateDisassembly(pc, symtab));
170            cachedPC = pc;
171            cachedSymtab = symtab;
172        }
173
174        return *cachedDisassembly;
175    }
176
177    std::string
178    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
179    {
180        std::stringstream ss;
181
182        ccprintf(ss, "%-10s ", mnemonic);
183
184        Addr target = pc + 8 + disp;
185
186        std::string str;
187        if (symtab && symtab->findSymbol(target, str))
188            ss << str;
189        else
190            ccprintf(ss, "0x%x", target);
191
192        return ss.str();
193    }
194
195    std::string
196    BranchExchange::generateDisassembly(Addr pc, const SymbolTable *symtab) const
197    {
198        std::stringstream ss;
199
200        ccprintf(ss, "%-10s ", mnemonic);
201
202        if (_numSrcRegs > 0) {
203            printReg(ss, _srcRegIdx[0]);
204        }
205
206        return ss.str();
207    }
208
209    std::string
210    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
211    {
212        std::stringstream ss;
213
214        ccprintf(ss, "%-10s ", mnemonic);
215
216        return ss.str();
217    }
218}};
219
220def format Branch(code,*opt_flags) {{
221
222    #Build Instruction Flags
223    #Use Link & Likely Flags to Add Link/Condition Code
224    inst_flags = ('IsDirectControl', )
225    for x in opt_flags:
226        if x == 'Link':
227            code += 'LR = NPC;\n'
228        else:
229            inst_flags += (x, )
230
231    #Take into account uncond. branch instruction
232    if 'cond == 1' in code:
233         inst_flags += ('IsUnCondControl', )
234    else:
235         inst_flags += ('IsCondControl', )
236
237    icode =  'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n'
238    icode += code
239    icode += '  NPC = NPC + 4 + disp;\n'
240    icode += '} else {\n'
241    icode += '  NPC = NPC;\n'
242    icode += '};\n'
243
244    code = icode
245
246    iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
247    header_output = BasicDeclare.subst(iop)
248    decoder_output = BasicConstructor.subst(iop)
249    decode_block = BasicDecode.subst(iop)
250    exec_output = BasicExecute.subst(iop)
251}};
252
253def format BranchExchange(code,*opt_flags) {{
254    #Build Instruction Flags
255    #Use Link & Likely Flags to Add Link/Condition Code
256    inst_flags = ('IsIndirectControl', )
257    for x in opt_flags:
258        if x == 'Link':
259            code += 'LR = NPC;\n'
260        else:
261            inst_flags += (x, )
262
263    #Take into account uncond. branch instruction
264    if 'cond == 1' in code:
265         inst_flags += ('IsUnCondControl', )
266    else:
267         inst_flags += ('IsCondControl', )
268
269    #Condition code
270
271    icode =  'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n'
272    icode += code
273    icode += '  NPC = Rm & 0xfffffffe; // Masks off bottom bit\n'
274    icode += '} else {\n'
275    icode += '  NPC = NPC;\n'
276    icode += '};\n'
277
278    code = icode
279
280    iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags)
281    header_output = BasicDeclare.subst(iop)
282    decoder_output = BasicConstructor.subst(iop)
283    decode_block = BasicDecode.subst(iop)
284    exec_output = BasicExecute.subst(iop)
285}};
286
287def format Jump(code, *opt_flags) {{
288    #Build Instruction Flags
289    #Use Link Flag to Add Link Code
290    inst_flags = ('IsIndirectControl', 'IsUncondControl')
291    for x in opt_flags:
292        if x == 'Link':
293            code = 'LR = NPC;\n' + code
294        elif x == 'ClearHazards':
295            code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
296        else:
297            inst_flags += (x, )
298
299    iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
300    header_output = BasicDeclare.subst(iop)
301    decoder_output = BasicConstructor.subst(iop)
302    decode_block = BasicDecode.subst(iop)
303    exec_output = BasicExecute.subst(iop)
304    #exec_output = PredOpExecute.subst(iop)
305}};
306
307
308