static_inst.hh revision 7424
1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2007-2008 The Florida State University
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Stephen Hines
41 */
42#ifndef __ARCH_ARM_INSTS_STATICINST_HH__
43#define __ARCH_ARM_INSTS_STATICINST_HH__
44
45#include "base/trace.hh"
46#include "cpu/static_inst.hh"
47
48namespace ArmISA
49{
50
51class ArmStaticInst : public StaticInst
52{
53  protected:
54    int32_t shift_rm_imm(uint32_t base, uint32_t shamt,
55                         uint32_t type, uint32_t cfval) const;
56    int32_t shift_rm_rs(uint32_t base, uint32_t shamt,
57                        uint32_t type, uint32_t cfval) const;
58
59    bool shift_carry_imm(uint32_t base, uint32_t shamt,
60                         uint32_t type, uint32_t cfval) const;
61    bool shift_carry_rs(uint32_t base, uint32_t shamt,
62                        uint32_t type, uint32_t cfval) const;
63
64    template<int width>
65    static inline bool
66    saturateOp(int32_t &res, int64_t op1, int64_t op2, bool sub=false)
67    {
68        int64_t midRes = sub ? (op1 - op2) : (op1 + op2);
69        if (bits(midRes, width) != bits(midRes, width - 1)) {
70            if (midRes > 0)
71                res = (LL(1) << (width - 1)) - 1;
72            else
73                res = -(LL(1) << (width - 1));
74            return true;
75        } else {
76            res = midRes;
77            return false;
78        }
79    }
80
81    static inline bool
82    satInt(int32_t &res, int64_t op, int width)
83    {
84        width--;
85        if (op >= (LL(1) << width)) {
86            res = (LL(1) << width) - 1;
87            return true;
88        } else if (op < -(LL(1) << width)) {
89            res = -(LL(1) << width);
90            return true;
91        } else {
92            res = op;
93            return false;
94        }
95    }
96
97    template<int width>
98    static inline bool
99    uSaturateOp(uint32_t &res, int64_t op1, int64_t op2, bool sub=false)
100    {
101        int64_t midRes = sub ? (op1 - op2) : (op1 + op2);
102        if (midRes >= (LL(1) << width)) {
103            res = (LL(1) << width) - 1;
104            return true;
105        } else if (midRes < 0) {
106            res = 0;
107            return true;
108        } else {
109            res = midRes;
110            return false;
111        }
112    }
113
114    static inline bool
115    uSatInt(int32_t &res, int64_t op, int width)
116    {
117        if (op >= (LL(1) << width)) {
118            res = (LL(1) << width) - 1;
119            return true;
120        } else if (op < 0) {
121            res = 0;
122            return true;
123        } else {
124            res = op;
125            return false;
126        }
127    }
128
129    // Constructor
130    ArmStaticInst(const char *mnem, ExtMachInst _machInst,
131                  OpClass __opClass)
132        : StaticInst(mnem, _machInst, __opClass)
133    {
134    }
135
136    /// Print a register name for disassembly given the unique
137    /// dependence tag number (FP or int).
138    void printReg(std::ostream &os, int reg) const;
139    void printMnemonic(std::ostream &os,
140                       const std::string &suffix = "",
141                       bool withPred = true) const;
142    void printMemSymbol(std::ostream &os, const SymbolTable *symtab,
143                        const std::string &prefix, const Addr addr,
144                        const std::string &suffix) const;
145    void printShiftOperand(std::ostream &os, IntRegIndex rm,
146                           bool immShift, uint32_t shiftAmt,
147                           IntRegIndex rs, ArmShiftType type) const;
148
149
150    void printDataInst(std::ostream &os, bool withImm) const;
151    void printDataInst(std::ostream &os, bool withImm, bool immShift, bool s,
152                       IntRegIndex rd, IntRegIndex rn, IntRegIndex rm,
153                       IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type,
154                       uint32_t imm) const;
155
156    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
157
158    static inline uint32_t
159    cpsrWriteByInstr(CPSR cpsr, uint32_t val,
160            uint8_t byteMask, bool affectState, bool nmfi)
161    {
162        bool privileged = (cpsr.mode != MODE_USER);
163
164        uint32_t bitMask = 0;
165
166        if (bits(byteMask, 3)) {
167            unsigned lowIdx = affectState ? 24 : 27;
168            bitMask = bitMask | mask(31, lowIdx);
169        }
170        if (bits(byteMask, 2)) {
171            bitMask = bitMask | mask(19, 16);
172        }
173        if (bits(byteMask, 1)) {
174            unsigned highIdx = affectState ? 15 : 9;
175            unsigned lowIdx = privileged ? 8 : 9;
176            bitMask = bitMask | mask(highIdx, lowIdx);
177        }
178        if (bits(byteMask, 0)) {
179            if (privileged) {
180                bitMask = bitMask | mask(7, 6);
181                if (!badMode((OperatingMode)(val & mask(5)))) {
182                    bitMask = bitMask | mask(5);
183                } else {
184                    warn_once("Ignoring write of bad mode to CPSR.\n");
185                }
186            }
187            if (affectState)
188                bitMask = bitMask | (1 << 5);
189        }
190
191        bool cpsr_f = cpsr.f;
192        uint32_t new_cpsr = ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
193        if (nmfi && !cpsr_f)
194            new_cpsr &= ~(1 << 6);
195        return new_cpsr;
196    }
197
198    static inline uint32_t
199    spsrWriteByInstr(uint32_t spsr, uint32_t val,
200            uint8_t byteMask, bool affectState)
201    {
202        uint32_t bitMask = 0;
203
204        if (bits(byteMask, 3))
205            bitMask = bitMask | mask(31, 24);
206        if (bits(byteMask, 2))
207            bitMask = bitMask | mask(19, 16);
208        if (bits(byteMask, 1))
209            bitMask = bitMask | mask(15, 8);
210        if (bits(byteMask, 0))
211            bitMask = bitMask | mask(7, 0);
212
213        return ((spsr & ~bitMask) | (val & bitMask));
214    }
215
216    template<class XC>
217    static inline Addr
218    readPC(XC *xc)
219    {
220        Addr pc = xc->readPC();
221        Addr tBit = pc & (ULL(1) << PcTBitShift);
222        if (tBit)
223            return pc + 4;
224        else
225            return pc + 8;
226    }
227
228    // Perform an regular branch.
229    template<class XC>
230    static inline void
231    setNextPC(XC *xc, Addr val)
232    {
233        Addr npc = xc->readNextPC();
234        if (npc & (ULL(1) << PcTBitShift)) {
235            val &= ~mask(1);
236        } else {
237            val &= ~mask(2);
238        }
239        xc->setNextPC((npc & PcModeMask) |
240                      (val & ~PcModeMask));
241    }
242
243    template<class T>
244    static inline T
245    cSwap(T val, bool big)
246    {
247        if (big) {
248            return gtobe(val);
249        } else {
250            return gtole(val);
251        }
252    }
253
254    // Perform an interworking branch.
255    template<class XC>
256    static inline void
257    setIWNextPC(XC *xc, Addr val)
258    {
259        Addr stateBits = xc->readPC() & PcModeMask;
260        Addr jBit = (ULL(1) << PcJBitShift);
261        Addr tBit = (ULL(1) << PcTBitShift);
262        bool thumbEE = (stateBits == (tBit | jBit));
263
264        Addr newPc = (val & ~PcModeMask);
265        if (thumbEE) {
266            if (bits(newPc, 0)) {
267                newPc = newPc & ~mask(1);
268            } else {
269                panic("Bad thumbEE interworking branch address %#x.\n", newPc);
270            }
271        } else {
272            if (bits(newPc, 0)) {
273                stateBits = tBit;
274                newPc = newPc & ~mask(1);
275            } else if (!bits(newPc, 1)) {
276                stateBits = 0;
277            } else {
278                warn("Bad interworking branch address %#x.\n", newPc);
279            }
280        }
281        newPc = newPc | stateBits;
282        xc->setNextPC(newPc);
283    }
284
285    // Perform an interworking branch in ARM mode, a regular branch
286    // otherwise.
287    template<class XC>
288    static inline void
289    setAIWNextPC(XC *xc, Addr val)
290    {
291        Addr stateBits = xc->readPC() & PcModeMask;
292        Addr jBit = (ULL(1) << PcJBitShift);
293        Addr tBit = (ULL(1) << PcTBitShift);
294        if (!jBit && !tBit) {
295            setIWNextPC(xc, val);
296        } else {
297            setNextPC(xc, val);
298        }
299    }
300};
301}
302
303#endif //__ARCH_ARM_INSTS_STATICINST_HH__
304