static_inst.cc revision 6262
1/* Copyright (c) 2007-2008 The Florida State University
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Authors: Stephen Hines
28 */
29
30#include "arch/arm/insts/static_inst.hh"
31#include "base/condcodes.hh"
32
33namespace ArmISA
34{
35// Shift Rm by an immediate value
36int32_t
37ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
38                            uint32_t type, uint32_t cfval) const
39{
40    assert(shamt < 32);
41    ArmShiftType shiftType;
42    shiftType = (ArmShiftType)type;
43
44    switch (shiftType)
45    {
46      case LSL:
47        return base << shamt;
48      case LSR:
49        if (shamt == 0)
50            return 0;
51        else
52            return base >> shamt;
53      case ASR:
54        if (shamt == 0)
55            return (int32_t)base >> 31;
56        else
57            return (int32_t)base >> shamt;
58      case ROR:
59        if (shamt == 0)
60            return (cfval << 31) | (base >> 1); // RRX
61        else
62            return (base << (32 - shamt)) | (base >> shamt);
63      default:
64        fprintf(stderr, "Unhandled shift type\n");
65        exit(1);
66        break;
67    }
68    return 0;
69}
70
71// Shift Rm by Rs
72int32_t
73ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
74                           uint32_t type, uint32_t cfval) const
75{
76    enum ArmShiftType shiftType;
77    shiftType = (enum ArmShiftType) type;
78
79    switch (shiftType)
80    {
81      case LSL:
82        if (shamt >= 32)
83            return 0;
84        else
85            return base << shamt;
86      case LSR:
87        if (shamt >= 32)
88            return 0;
89        else
90            return base >> shamt;
91      case ASR:
92        if (shamt >= 32)
93            return (int32_t)base >> 31;
94        else
95            return (int32_t)base >> shamt;
96      case ROR:
97        shamt = shamt & 0x1f;
98        if (shamt == 0)
99            return base;
100        else
101            return (base << (32 - shamt)) | (base >> shamt);
102      default:
103        fprintf(stderr, "Unhandled shift type\n");
104        exit(1);
105        break;
106    }
107    return 0;
108}
109
110
111// Generate C for a shift by immediate
112bool
113ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
114                               uint32_t type, uint32_t cfval) const
115{
116    enum ArmShiftType shiftType;
117    shiftType = (enum ArmShiftType) type;
118
119    switch (shiftType)
120    {
121      case LSL:
122        if (shamt == 0)
123            return cfval;
124        else
125            return (base >> (32 - shamt)) & 1;
126      case LSR:
127        if (shamt == 0)
128            return (base >> 31);
129        else
130            return (base >> (shamt - 1)) & 1;
131      case ASR:
132        if (shamt == 0)
133            return (base >> 31);
134        else
135            return (base >> (shamt - 1)) & 1;
136      case ROR:
137        shamt = shamt & 0x1f;
138        if (shamt == 0)
139            return (base & 1); // RRX
140        else
141            return (base >> (shamt - 1)) & 1;
142      default:
143        fprintf(stderr, "Unhandled shift type\n");
144        exit(1);
145        break;
146    }
147    return 0;
148}
149
150
151// Generate C for a shift by Rs
152bool
153ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
154                              uint32_t type, uint32_t cfval) const
155{
156    enum ArmShiftType shiftType;
157    shiftType = (enum ArmShiftType) type;
158
159    if (shamt == 0)
160        return cfval;
161
162    switch (shiftType)
163    {
164      case LSL:
165        if (shamt > 32)
166            return 0;
167        else
168            return (base >> (32 - shamt)) & 1;
169      case LSR:
170        if (shamt > 32)
171            return 0;
172        else
173            return (base >> (shamt - 1)) & 1;
174      case ASR:
175        if (shamt > 32)
176            shamt = 32;
177        return (base >> (shamt - 1)) & 1;
178      case ROR:
179        shamt = shamt & 0x1f;
180        if (shamt == 0)
181            shamt = 32;
182        return (base >> (shamt - 1)) & 1;
183      default:
184        fprintf(stderr, "Unhandled shift type\n");
185        exit(1);
186        break;
187    }
188    return 0;
189}
190
191
192// Generate the appropriate carry bit for an addition operation
193bool
194ArmStaticInst::arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const
195{
196    return findCarry(32, result, lhs, rhs);
197}
198
199// Generate the appropriate carry bit for a subtraction operation
200bool
201ArmStaticInst::arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const
202{
203    return findCarry(32, result, lhs, ~rhs);
204}
205
206bool
207ArmStaticInst::arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const
208{
209    return findOverflow(32, result, lhs, rhs);
210}
211
212bool
213ArmStaticInst::arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const
214{
215    return findOverflow(32, result, lhs, ~rhs);
216}
217
218void
219ArmStaticInst::printReg(std::ostream &os, int reg) const
220{
221    if (reg < FP_Base_DepTag) {
222        switch (reg) {
223          case PCReg:
224            ccprintf(os, "pc");
225            break;
226          case StackPointerReg:
227            ccprintf(os, "sp");
228            break;
229          case FramePointerReg:
230            ccprintf(os, "fp");
231            break;
232          case ReturnAddressReg:
233            ccprintf(os, "lr");
234            break;
235          default:
236            ccprintf(os, "r%d", reg);
237            break;
238        }
239    } else if (reg < Ctrl_Base_DepTag) {
240        ccprintf(os, "f%d", reg - FP_Base_DepTag);
241    } else {
242        reg -= Ctrl_Base_DepTag;
243        assert(reg < NUM_MISCREGS);
244        ccprintf(os, "%s", ArmISA::miscRegName[reg]);
245    }
246}
247
248void
249ArmStaticInst::printMnemonic(std::ostream &os,
250                             const std::string &suffix,
251                             bool withPred) const
252{
253    os << "  " << mnemonic;
254    if (withPred) {
255        unsigned condCode = machInst.condCode;
256        switch (condCode) {
257          case COND_EQ:
258            os << "eq";
259            break;
260          case COND_NE:
261            os << "ne";
262            break;
263          case COND_CS:
264            os << "cs";
265            break;
266          case COND_CC:
267            os << "cc";
268            break;
269          case COND_MI:
270            os << "mi";
271            break;
272          case COND_PL:
273            os << "pl";
274            break;
275          case COND_VS:
276            os << "vs";
277            break;
278          case COND_VC:
279            os << "vc";
280            break;
281          case COND_HI:
282            os << "hi";
283            break;
284          case COND_LS:
285            os << "ls";
286            break;
287          case COND_GE:
288            os << "ge";
289            break;
290          case COND_LT:
291            os << "lt";
292            break;
293          case COND_GT:
294            os << "gt";
295            break;
296          case COND_LE:
297            os << "le";
298            break;
299          case COND_AL:
300            // This one is implicit.
301            break;
302          case COND_NV:
303            os << "nv";
304            break;
305          default:
306            panic("Unrecognized condition code %d.\n", condCode);
307        }
308        os << suffix << "   ";
309    }
310}
311
312std::string
313ArmStaticInst::generateDisassembly(Addr pc,
314                                   const SymbolTable *symtab) const
315{
316    std::stringstream ss;
317    printMnemonic(ss);
318    return ss.str();
319}
320}
321