static_inst.cc revision 7142:c63c06703d0f
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
43#include "arch/arm/faults.hh"
44#include "arch/arm/insts/static_inst.hh"
45#include "base/condcodes.hh"
46#include "base/cprintf.hh"
47#include "base/loader/symtab.hh"
48
49namespace ArmISA
50{
51// Shift Rm by an immediate value
52int32_t
53ArmStaticInstBase::shift_rm_imm(uint32_t base, uint32_t shamt,
54                                uint32_t type, uint32_t cfval) const
55{
56    assert(shamt < 32);
57    ArmShiftType shiftType;
58    shiftType = (ArmShiftType)type;
59
60    switch (shiftType)
61    {
62      case LSL:
63        return base << shamt;
64      case LSR:
65        if (shamt == 0)
66            return 0;
67        else
68            return base >> shamt;
69      case ASR:
70        if (shamt == 0)
71            return (int32_t)base >> 31;
72        else
73            return (int32_t)base >> shamt;
74      case ROR:
75        if (shamt == 0)
76            return (cfval << 31) | (base >> 1); // RRX
77        else
78            return (base << (32 - shamt)) | (base >> shamt);
79      default:
80        ccprintf(std::cerr, "Unhandled shift type\n");
81        exit(1);
82        break;
83    }
84    return 0;
85}
86
87// Shift Rm by Rs
88int32_t
89ArmStaticInstBase::shift_rm_rs(uint32_t base, uint32_t shamt,
90                               uint32_t type, uint32_t cfval) const
91{
92    enum ArmShiftType shiftType;
93    shiftType = (enum ArmShiftType) type;
94
95    switch (shiftType)
96    {
97      case LSL:
98        if (shamt >= 32)
99            return 0;
100        else
101            return base << shamt;
102      case LSR:
103        if (shamt >= 32)
104            return 0;
105        else
106            return base >> shamt;
107      case ASR:
108        if (shamt >= 32)
109            return (int32_t)base >> 31;
110        else
111            return (int32_t)base >> shamt;
112      case ROR:
113        shamt = shamt & 0x1f;
114        if (shamt == 0)
115            return base;
116        else
117            return (base << (32 - shamt)) | (base >> shamt);
118      default:
119        ccprintf(std::cerr, "Unhandled shift type\n");
120        exit(1);
121        break;
122    }
123    return 0;
124}
125
126
127// Generate C for a shift by immediate
128bool
129ArmStaticInstBase::shift_carry_imm(uint32_t base, uint32_t shamt,
130                                   uint32_t type, uint32_t cfval) const
131{
132    enum ArmShiftType shiftType;
133    shiftType = (enum ArmShiftType) type;
134
135    switch (shiftType)
136    {
137      case LSL:
138        if (shamt == 0)
139            return cfval;
140        else
141            return (base >> (32 - shamt)) & 1;
142      case LSR:
143        if (shamt == 0)
144            return (base >> 31);
145        else
146            return (base >> (shamt - 1)) & 1;
147      case ASR:
148        if (shamt == 0)
149            return (base >> 31);
150        else
151            return (base >> (shamt - 1)) & 1;
152      case ROR:
153        shamt = shamt & 0x1f;
154        if (shamt == 0)
155            return (base & 1); // RRX
156        else
157            return (base >> (shamt - 1)) & 1;
158      default:
159        ccprintf(std::cerr, "Unhandled shift type\n");
160        exit(1);
161        break;
162    }
163    return 0;
164}
165
166
167// Generate C for a shift by Rs
168bool
169ArmStaticInstBase::shift_carry_rs(uint32_t base, uint32_t shamt,
170                                  uint32_t type, uint32_t cfval) const
171{
172    enum ArmShiftType shiftType;
173    shiftType = (enum ArmShiftType) type;
174
175    if (shamt == 0)
176        return cfval;
177
178    switch (shiftType)
179    {
180      case LSL:
181        if (shamt > 32)
182            return 0;
183        else
184            return (base >> (32 - shamt)) & 1;
185      case LSR:
186        if (shamt > 32)
187            return 0;
188        else
189            return (base >> (shamt - 1)) & 1;
190      case ASR:
191        if (shamt > 32)
192            shamt = 32;
193        return (base >> (shamt - 1)) & 1;
194      case ROR:
195        shamt = shamt & 0x1f;
196        if (shamt == 0)
197            shamt = 32;
198        return (base >> (shamt - 1)) & 1;
199      default:
200        ccprintf(std::cerr, "Unhandled shift type\n");
201        exit(1);
202        break;
203    }
204    return 0;
205}
206
207
208// Generate the appropriate carry bit for an addition operation
209bool
210ArmStaticInstBase::arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const
211{
212    return findCarry(32, result, lhs, rhs);
213}
214
215// Generate the appropriate carry bit for a subtraction operation
216bool
217ArmStaticInstBase::arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const
218{
219    return findCarry(32, result, lhs, ~rhs);
220}
221
222bool
223ArmStaticInstBase::arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const
224{
225    return findOverflow(32, result, lhs, rhs);
226}
227
228bool
229ArmStaticInstBase::arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const
230{
231    return findOverflow(32, result, lhs, ~rhs);
232}
233
234void
235ArmStaticInstBase::printReg(std::ostream &os, int reg) const
236{
237    if (reg < FP_Base_DepTag) {
238        switch (reg) {
239          case PCReg:
240            ccprintf(os, "pc");
241            break;
242          case StackPointerReg:
243            ccprintf(os, "sp");
244            break;
245          case FramePointerReg:
246            ccprintf(os, "fp");
247            break;
248          case ReturnAddressReg:
249            ccprintf(os, "lr");
250            break;
251          default:
252            ccprintf(os, "r%d", reg);
253            break;
254        }
255    } else if (reg < Ctrl_Base_DepTag) {
256        ccprintf(os, "f%d", reg - FP_Base_DepTag);
257    } else {
258        reg -= Ctrl_Base_DepTag;
259        assert(reg < NUM_MISCREGS);
260        ccprintf(os, "%s", ArmISA::miscRegName[reg]);
261    }
262}
263
264void
265ArmStaticInstBase::printMnemonic(std::ostream &os,
266                             const std::string &suffix,
267                             bool withPred) const
268{
269    os << "  " << mnemonic;
270    if (withPred) {
271        unsigned condCode = machInst.condCode;
272        switch (condCode) {
273          case COND_EQ:
274            os << "eq";
275            break;
276          case COND_NE:
277            os << "ne";
278            break;
279          case COND_CS:
280            os << "cs";
281            break;
282          case COND_CC:
283            os << "cc";
284            break;
285          case COND_MI:
286            os << "mi";
287            break;
288          case COND_PL:
289            os << "pl";
290            break;
291          case COND_VS:
292            os << "vs";
293            break;
294          case COND_VC:
295            os << "vc";
296            break;
297          case COND_HI:
298            os << "hi";
299            break;
300          case COND_LS:
301            os << "ls";
302            break;
303          case COND_GE:
304            os << "ge";
305            break;
306          case COND_LT:
307            os << "lt";
308            break;
309          case COND_GT:
310            os << "gt";
311            break;
312          case COND_LE:
313            os << "le";
314            break;
315          case COND_AL:
316            // This one is implicit.
317            break;
318          case COND_UC:
319            // Unconditional.
320            break;
321          default:
322            panic("Unrecognized condition code %d.\n", condCode);
323        }
324        os << suffix;
325        if (machInst.bigThumb)
326            os << ".w";
327        os << "   ";
328    }
329}
330
331void
332ArmStaticInstBase::printMemSymbol(std::ostream &os,
333                              const SymbolTable *symtab,
334                              const std::string &prefix,
335                              const Addr addr,
336                              const std::string &suffix) const
337{
338    Addr symbolAddr;
339    std::string symbol;
340    if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
341        ccprintf(os, "%s%s", prefix, symbol);
342        if (symbolAddr != addr)
343            ccprintf(os, "+%d", addr - symbolAddr);
344        ccprintf(os, suffix);
345    }
346}
347
348void
349ArmStaticInstBase::printShiftOperand(std::ostream &os,
350                                     IntRegIndex rm,
351                                     bool immShift,
352                                     uint32_t shiftAmt,
353                                     IntRegIndex rs,
354                                     ArmShiftType type) const
355{
356    bool firstOp = false;
357
358    if (rm != INTREG_ZERO) {
359        printReg(os, rm);
360    }
361
362    bool done = false;
363
364    if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
365        shiftAmt = 32;
366
367    switch (type) {
368      case LSL:
369        if (immShift && shiftAmt == 0) {
370            done = true;
371            break;
372        }
373        if (!firstOp)
374            os << ", ";
375        os << "LSL";
376        break;
377      case LSR:
378        if (!firstOp)
379            os << ", ";
380        os << "LSR";
381        break;
382      case ASR:
383        if (!firstOp)
384            os << ", ";
385        os << "ASR";
386        break;
387      case ROR:
388        if (immShift && shiftAmt == 0) {
389            if (!firstOp)
390                os << ", ";
391            os << "RRX";
392            done = true;
393            break;
394        }
395        if (!firstOp)
396            os << ", ";
397        os << "ROR";
398        break;
399      default:
400        panic("Tried to disassemble unrecognized shift type.\n");
401    }
402    if (!done) {
403        if (!firstOp)
404            os << " ";
405        if (immShift)
406            os << "#" << shiftAmt;
407        else
408            printReg(os, rs);
409    }
410}
411
412void
413ArmStaticInstBase::printDataInst(std::ostream &os, bool withImm,
414        bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
415        IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
416        ArmShiftType type, uint32_t imm) const
417{
418    printMnemonic(os, s ? "s" : "");
419    bool firstOp = true;
420
421    // Destination
422    if (rd != INTREG_ZERO) {
423        firstOp = false;
424        printReg(os, rd);
425    }
426
427    // Source 1.
428    if (rn != INTREG_ZERO) {
429        if (!firstOp)
430            os << ", ";
431        firstOp = false;
432        printReg(os, rn);
433    }
434
435    if (!firstOp)
436        os << ", ";
437    if (withImm) {
438        ccprintf(os, "#%d", imm);
439    } else {
440        printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
441    }
442}
443
444std::string
445ArmStaticInstBase::generateDisassembly(Addr pc,
446                                   const SymbolTable *symtab) const
447{
448    std::stringstream ss;
449    printMnemonic(ss);
450    return ss.str();
451}
452}
453