static_inst.hh revision 8737:770ccf3af571
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 "arch/arm/faults.hh"
46#include "arch/arm/utility.hh"
47#include "base/trace.hh"
48#include "cpu/static_inst.hh"
49#include "sim/byteswap.hh"
50
51namespace ArmISA
52{
53
54class ArmStaticInst : public StaticInst
55{
56  protected:
57    int32_t shift_rm_imm(uint32_t base, uint32_t shamt,
58                         uint32_t type, uint32_t cfval) const;
59    int32_t shift_rm_rs(uint32_t base, uint32_t shamt,
60                        uint32_t type, uint32_t cfval) const;
61
62    bool shift_carry_imm(uint32_t base, uint32_t shamt,
63                         uint32_t type, uint32_t cfval) const;
64    bool shift_carry_rs(uint32_t base, uint32_t shamt,
65                        uint32_t type, uint32_t cfval) const;
66
67    template<int width>
68    static inline bool
69    saturateOp(int32_t &res, int64_t op1, int64_t op2, bool sub=false)
70    {
71        int64_t midRes = sub ? (op1 - op2) : (op1 + op2);
72        if (bits(midRes, width) != bits(midRes, width - 1)) {
73            if (midRes > 0)
74                res = (LL(1) << (width - 1)) - 1;
75            else
76                res = -(LL(1) << (width - 1));
77            return true;
78        } else {
79            res = midRes;
80            return false;
81        }
82    }
83
84    static inline bool
85    satInt(int32_t &res, int64_t op, int width)
86    {
87        width--;
88        if (op >= (LL(1) << width)) {
89            res = (LL(1) << width) - 1;
90            return true;
91        } else if (op < -(LL(1) << width)) {
92            res = -(LL(1) << width);
93            return true;
94        } else {
95            res = op;
96            return false;
97        }
98    }
99
100    template<int width>
101    static inline bool
102    uSaturateOp(uint32_t &res, int64_t op1, int64_t op2, bool sub=false)
103    {
104        int64_t midRes = sub ? (op1 - op2) : (op1 + op2);
105        if (midRes >= (LL(1) << width)) {
106            res = (LL(1) << width) - 1;
107            return true;
108        } else if (midRes < 0) {
109            res = 0;
110            return true;
111        } else {
112            res = midRes;
113            return false;
114        }
115    }
116
117    static inline bool
118    uSatInt(int32_t &res, int64_t op, int width)
119    {
120        if (op >= (LL(1) << width)) {
121            res = (LL(1) << width) - 1;
122            return true;
123        } else if (op < 0) {
124            res = 0;
125            return true;
126        } else {
127            res = op;
128            return false;
129        }
130    }
131
132    // Constructor
133    ArmStaticInst(const char *mnem, ExtMachInst _machInst,
134                  OpClass __opClass)
135        : StaticInst(mnem, _machInst, __opClass)
136    {
137    }
138
139    /// Print a register name for disassembly given the unique
140    /// dependence tag number (FP or int).
141    void printReg(std::ostream &os, int reg) const;
142    void printMnemonic(std::ostream &os,
143                       const std::string &suffix = "",
144                       bool withPred = true) const;
145    void printMemSymbol(std::ostream &os, const SymbolTable *symtab,
146                        const std::string &prefix, const Addr addr,
147                        const std::string &suffix) const;
148    void printShiftOperand(std::ostream &os, IntRegIndex rm,
149                           bool immShift, uint32_t shiftAmt,
150                           IntRegIndex rs, ArmShiftType type) const;
151
152
153    void printDataInst(std::ostream &os, bool withImm) const;
154    void printDataInst(std::ostream &os, bool withImm, bool immShift, bool s,
155                       IntRegIndex rd, IntRegIndex rn, IntRegIndex rm,
156                       IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type,
157                       uint32_t imm) const;
158
159    void
160    advancePC(PCState &pcState) const
161    {
162        pcState.advance();
163    }
164
165    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
166
167    static inline uint32_t
168    cpsrWriteByInstr(CPSR cpsr, uint32_t val,
169            uint8_t byteMask, bool affectState, bool nmfi)
170    {
171        bool privileged = (cpsr.mode != MODE_USER);
172
173        uint32_t bitMask = 0;
174
175        if (bits(byteMask, 3)) {
176            unsigned lowIdx = affectState ? 24 : 27;
177            bitMask = bitMask | mask(31, lowIdx);
178        }
179        if (bits(byteMask, 2)) {
180            bitMask = bitMask | mask(19, 16);
181        }
182        if (bits(byteMask, 1)) {
183            unsigned highIdx = affectState ? 15 : 9;
184            unsigned lowIdx = privileged ? 8 : 9;
185            bitMask = bitMask | mask(highIdx, lowIdx);
186        }
187        if (bits(byteMask, 0)) {
188            if (privileged) {
189                bitMask = bitMask | mask(7, 6);
190                if (!badMode((OperatingMode)(val & mask(5)))) {
191                    bitMask = bitMask | mask(5);
192                } else {
193                    warn_once("Ignoring write of bad mode to CPSR.\n");
194                }
195            }
196            if (affectState)
197                bitMask = bitMask | (1 << 5);
198        }
199
200        bool cpsr_f = cpsr.f;
201        uint32_t new_cpsr = ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
202        if (nmfi && !cpsr_f)
203            new_cpsr &= ~(1 << 6);
204        return new_cpsr;
205    }
206
207    static inline uint32_t
208    spsrWriteByInstr(uint32_t spsr, uint32_t val,
209            uint8_t byteMask, bool affectState)
210    {
211        uint32_t bitMask = 0;
212
213        if (bits(byteMask, 3))
214            bitMask = bitMask | mask(31, 24);
215        if (bits(byteMask, 2))
216            bitMask = bitMask | mask(19, 16);
217        if (bits(byteMask, 1))
218            bitMask = bitMask | mask(15, 8);
219        if (bits(byteMask, 0))
220            bitMask = bitMask | mask(7, 0);
221
222        return ((spsr & ~bitMask) | (val & bitMask));
223    }
224
225    template<class XC>
226    static inline Addr
227    readPC(XC *xc)
228    {
229        return xc->pcState().instPC();
230    }
231
232    template<class XC>
233    static inline void
234    setNextPC(XC *xc, Addr val)
235    {
236        PCState pc = xc->pcState();
237        pc.instNPC(val);
238        xc->pcState(pc);
239    }
240
241    template<class T>
242    static inline T
243    cSwap(T val, bool big)
244    {
245        if (big) {
246            return gtobe(val);
247        } else {
248            return gtole(val);
249        }
250    }
251
252    template<class T, class E>
253    static inline T
254    cSwap(T val, bool big)
255    {
256        const unsigned count = sizeof(T) / sizeof(E);
257        union {
258            T tVal;
259            E eVals[count];
260        } conv;
261        conv.tVal = htog(val);
262        if (big) {
263            for (unsigned i = 0; i < count; i++) {
264                conv.eVals[i] = gtobe(conv.eVals[i]);
265            }
266        } else {
267            for (unsigned i = 0; i < count; i++) {
268                conv.eVals[i] = gtole(conv.eVals[i]);
269            }
270        }
271        return gtoh(conv.tVal);
272    }
273
274    // Perform an interworking branch.
275    template<class XC>
276    static inline void
277    setIWNextPC(XC *xc, Addr val)
278    {
279        PCState pc = xc->pcState();
280        pc.instIWNPC(val);
281        xc->pcState(pc);
282    }
283
284    // Perform an interworking branch in ARM mode, a regular branch
285    // otherwise.
286    template<class XC>
287    static inline void
288    setAIWNextPC(XC *xc, Addr val)
289    {
290        PCState pc = xc->pcState();
291        pc.instAIWNPC(val);
292        xc->pcState(pc);
293    }
294
295    inline Fault
296    disabledFault() const
297    {
298#if FULL_SYSTEM
299            return new UndefinedInstruction();
300#else
301            return new UndefinedInstruction(machInst, false, mnemonic, true);
302#endif
303    }
304};
305}
306
307#endif //__ARCH_ARM_INSTS_STATICINST_HH__
308