1/* Copyright (c) 2007-2008 The Florida State University
2 * Copyright (c) 2009 The University of Edinburgh
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Timothy M. Jones
29 */
30
31#ifndef __ARCH_POWER_INSTS_BRANCH_HH__
32#define __ARCH_POWER_INSTS_BRANCH_HH__
33
34#include "arch/power/insts/static_inst.hh"
35
36namespace PowerISA
37{
38
39/**
40 * Base class for instructions whose disassembly is not purely a
41 * function of the machine instruction (i.e., it depends on the
42 * PC).  This class overrides the disassemble() method to check
43 * the PC and symbol table values before re-using a cached
44 * disassembly string.  This is necessary for branches and jumps,
45 * where the disassembly string includes the target address (which
46 * may depend on the PC and/or symbol table).
47 */
48class PCDependentDisassembly : public PowerStaticInst
49{
50  protected:
51    /// Cached program counter from last disassembly
52    mutable Addr cachedPC;
53    /// Cached symbol table pointer from last disassembly
54    mutable const SymbolTable *cachedSymtab;
55
56    /// Constructor
57    PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
58                           OpClass __opClass)
59        : PowerStaticInst(mnem, _machInst, __opClass),
60          cachedPC(0), cachedSymtab(0)
61    {
62    }
63
64    const std::string &
65    disassemble(Addr pc, const SymbolTable *symtab) const;
66};
67
68/**
69 * Base class for unconditional, PC-relative branches.
70 */
71class BranchPCRel : public PCDependentDisassembly
72{
73  protected:
74
75    /// Displacement
76    uint32_t disp;
77
78    /// Constructor.
79    BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
80        : PCDependentDisassembly(mnem, _machInst, __opClass),
81          disp(machInst.li << 2)
82    {
83        // If bit 26 is 1 then sign extend
84        if (disp & 0x2000000) {
85            disp |= 0xfc000000;
86        }
87    }
88
89    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
90
91    /// Explicitly import the otherwise hidden branchTarget
92    using StaticInst::branchTarget;
93
94    std::string generateDisassembly(
95            Addr pc, const SymbolTable *symtab) const override;
96};
97
98/**
99 * Base class for unconditional, non PC-relative branches.
100 */
101class BranchNonPCRel : public PCDependentDisassembly
102{
103  protected:
104
105    /// Target address
106    uint32_t targetAddr;
107
108    /// Constructor.
109    BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
110        : PCDependentDisassembly(mnem, _machInst, __opClass),
111          targetAddr(machInst.li << 2)
112    {
113        // If bit 26 is 1 then sign extend
114        if (targetAddr & 0x2000000) {
115            targetAddr |= 0xfc000000;
116        }
117    }
118
119    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
120
121    /// Explicitly import the otherwise hidden branchTarget
122    using StaticInst::branchTarget;
123
124    std::string generateDisassembly(
125            Addr pc, const SymbolTable *symtab) const override;
126};
127
128/**
129 * Base class for conditional branches.
130 */
131class BranchCond : public PCDependentDisassembly
132{
133  protected:
134
135    /// Fields needed for conditions
136    uint32_t bo;
137    uint32_t bi;
138
139    /// Constructor.
140    BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass)
141        : PCDependentDisassembly(mnem, _machInst, __opClass),
142          bo(machInst.bo),
143          bi(machInst.bi)
144    {
145    }
146
147    inline bool
148    ctrOk(uint32_t& ctr) const
149    {
150        bool ctr_ok;
151        if (bo & 4) {
152            ctr_ok = true;
153        } else {
154            ctr--;
155            if (ctr != 0) {
156                ctr_ok = ((bo & 2) == 0);
157            } else {
158                ctr_ok = ((bo & 2) != 0);
159            }
160        }
161        return ctr_ok;
162    }
163
164    inline bool
165    condOk(uint32_t cr) const
166    {
167        bool cond_ok;
168        if (bo & 16) {
169            cond_ok = true;
170        } else {
171            cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1));
172        }
173        return cond_ok;
174    }
175};
176
177/**
178 * Base class for conditional, PC-relative branches.
179 */
180class BranchPCRelCond : public BranchCond
181{
182  protected:
183
184    /// Displacement
185    uint32_t disp;
186
187    /// Constructor.
188    BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
189        : BranchCond(mnem, _machInst, __opClass),
190          disp(machInst.bd << 2)
191    {
192        // If bit 16 is 1 then sign extend
193        if (disp & 0x8000) {
194            disp |= 0xffff0000;
195        }
196    }
197
198    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
199
200    /// Explicitly import the otherwise hidden branchTarget
201    using StaticInst::branchTarget;
202
203    std::string generateDisassembly(
204            Addr pc, const SymbolTable *symtab) const override;
205};
206
207/**
208 * Base class for conditional, non PC-relative branches.
209 */
210class BranchNonPCRelCond : public BranchCond
211{
212  protected:
213
214    /// Target address
215    uint32_t targetAddr;
216
217    /// Constructor.
218    BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
219        : BranchCond(mnem, _machInst, __opClass),
220          targetAddr(machInst.bd << 2)
221    {
222        // If bit 16 is 1 then sign extend
223        if (targetAddr & 0x8000) {
224            targetAddr |= 0xffff0000;
225        }
226    }
227
228    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
229
230    /// Explicitly import the otherwise hidden branchTarget
231    using StaticInst::branchTarget;
232
233    std::string generateDisassembly(
234            Addr pc, const SymbolTable *symtab) const override;
235};
236
237/**
238 * Base class for conditional, register-based branches
239 */
240class BranchRegCond : public BranchCond
241{
242  protected:
243
244    /// Constructor.
245    BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass)
246        : BranchCond(mnem, _machInst, __opClass)
247    {
248    }
249
250    PowerISA::PCState branchTarget(ThreadContext *tc) const override;
251
252    /// Explicitly import the otherwise hidden branchTarget
253    using StaticInst::branchTarget;
254
255    std::string generateDisassembly(
256            Addr pc, const SymbolTable *symtab) const override;
257};
258
259} // namespace PowerISA
260
261#endif //__ARCH_POWER_INSTS_BRANCH_HH__
262