static_inst.cc revision 9913:7f43babfde6a
1/*
2 * Copyright (c) 2010 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder.  You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2007-2008 The Florida State University
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Stephen Hines
42 */
43
44#include "arch/arm/insts/static_inst.hh"
45#include "arch/arm/faults.hh"
46#include "base/loader/symtab.hh"
47#include "base/condcodes.hh"
48#include "base/cprintf.hh"
49#include "cpu/reg_class.hh"
50
51namespace ArmISA
52{
53// Shift Rm by an immediate value
54int32_t
55ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
56                                uint32_t type, uint32_t cfval) const
57{
58    assert(shamt < 32);
59    ArmShiftType shiftType;
60    shiftType = (ArmShiftType)type;
61
62    switch (shiftType)
63    {
64      case LSL:
65        return base << shamt;
66      case LSR:
67        if (shamt == 0)
68            return 0;
69        else
70            return base >> shamt;
71      case ASR:
72        if (shamt == 0)
73            return (base >> 31) | -((base & (1 << 31)) >> 31);
74        else
75            return (base >> shamt) | -((base & (1 << 31)) >> shamt);
76      case ROR:
77        if (shamt == 0)
78            return (cfval << 31) | (base >> 1); // RRX
79        else
80            return (base << (32 - shamt)) | (base >> shamt);
81      default:
82        ccprintf(std::cerr, "Unhandled shift type\n");
83        exit(1);
84        break;
85    }
86    return 0;
87}
88
89// Shift Rm by Rs
90int32_t
91ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
92                               uint32_t type, uint32_t cfval) const
93{
94    enum ArmShiftType shiftType;
95    shiftType = (enum ArmShiftType) type;
96
97    switch (shiftType)
98    {
99      case LSL:
100        if (shamt >= 32)
101            return 0;
102        else
103            return base << shamt;
104      case LSR:
105        if (shamt >= 32)
106            return 0;
107        else
108            return base >> shamt;
109      case ASR:
110        if (shamt >= 32)
111            return (base >> 31) | -((base & (1 << 31)) >> 31);
112        else
113            return (base >> shamt) | -((base & (1 << 31)) >> shamt);
114      case ROR:
115        shamt = shamt & 0x1f;
116        if (shamt == 0)
117            return base;
118        else
119            return (base << (32 - shamt)) | (base >> shamt);
120      default:
121        ccprintf(std::cerr, "Unhandled shift type\n");
122        exit(1);
123        break;
124    }
125    return 0;
126}
127
128
129// Generate C for a shift by immediate
130bool
131ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
132                                   uint32_t type, uint32_t cfval) const
133{
134    enum ArmShiftType shiftType;
135    shiftType = (enum ArmShiftType) type;
136
137    switch (shiftType)
138    {
139      case LSL:
140        if (shamt == 0)
141            return cfval;
142        else
143            return (base >> (32 - shamt)) & 1;
144      case LSR:
145        if (shamt == 0)
146            return (base >> 31);
147        else
148            return (base >> (shamt - 1)) & 1;
149      case ASR:
150        if (shamt == 0)
151            return (base >> 31);
152        else
153            return (base >> (shamt - 1)) & 1;
154      case ROR:
155        shamt = shamt & 0x1f;
156        if (shamt == 0)
157            return (base & 1); // RRX
158        else
159            return (base >> (shamt - 1)) & 1;
160      default:
161        ccprintf(std::cerr, "Unhandled shift type\n");
162        exit(1);
163        break;
164    }
165    return 0;
166}
167
168
169// Generate C for a shift by Rs
170bool
171ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
172                                  uint32_t type, uint32_t cfval) const
173{
174    enum ArmShiftType shiftType;
175    shiftType = (enum ArmShiftType) type;
176
177    if (shamt == 0)
178        return cfval;
179
180    switch (shiftType)
181    {
182      case LSL:
183        if (shamt > 32)
184            return 0;
185        else
186            return (base >> (32 - shamt)) & 1;
187      case LSR:
188        if (shamt > 32)
189            return 0;
190        else
191            return (base >> (shamt - 1)) & 1;
192      case ASR:
193        if (shamt > 32)
194            shamt = 32;
195        return (base >> (shamt - 1)) & 1;
196      case ROR:
197        shamt = shamt & 0x1f;
198        if (shamt == 0)
199            shamt = 32;
200        return (base >> (shamt - 1)) & 1;
201      default:
202        ccprintf(std::cerr, "Unhandled shift type\n");
203        exit(1);
204        break;
205    }
206    return 0;
207}
208
209
210void
211ArmStaticInst::printReg(std::ostream &os, int reg) const
212{
213    RegIndex rel_reg;
214
215    switch (regIdxToClass(reg, &rel_reg)) {
216      case IntRegClass:
217        switch (rel_reg) {
218          case PCReg:
219            ccprintf(os, "pc");
220            break;
221          case StackPointerReg:
222            ccprintf(os, "sp");
223            break;
224          case FramePointerReg:
225            ccprintf(os, "fp");
226            break;
227          case ReturnAddressReg:
228            ccprintf(os, "lr");
229            break;
230          default:
231            ccprintf(os, "r%d", reg);
232            break;
233        }
234        break;
235      case FloatRegClass:
236        ccprintf(os, "f%d", rel_reg);
237        break;
238      case MiscRegClass:
239        assert(rel_reg < NUM_MISCREGS);
240        ccprintf(os, "%s", ArmISA::miscRegName[rel_reg]);
241        break;
242    }
243}
244
245void
246ArmStaticInst::printMnemonic(std::ostream &os,
247                             const std::string &suffix,
248                             bool withPred) const
249{
250    os << "  " << mnemonic;
251    if (withPred) {
252        unsigned condCode = machInst.condCode;
253        switch (condCode) {
254          case COND_EQ:
255            os << "eq";
256            break;
257          case COND_NE:
258            os << "ne";
259            break;
260          case COND_CS:
261            os << "cs";
262            break;
263          case COND_CC:
264            os << "cc";
265            break;
266          case COND_MI:
267            os << "mi";
268            break;
269          case COND_PL:
270            os << "pl";
271            break;
272          case COND_VS:
273            os << "vs";
274            break;
275          case COND_VC:
276            os << "vc";
277            break;
278          case COND_HI:
279            os << "hi";
280            break;
281          case COND_LS:
282            os << "ls";
283            break;
284          case COND_GE:
285            os << "ge";
286            break;
287          case COND_LT:
288            os << "lt";
289            break;
290          case COND_GT:
291            os << "gt";
292            break;
293          case COND_LE:
294            os << "le";
295            break;
296          case COND_AL:
297            // This one is implicit.
298            break;
299          case COND_UC:
300            // Unconditional.
301            break;
302          default:
303            panic("Unrecognized condition code %d.\n", condCode);
304        }
305        os << suffix;
306        if (machInst.bigThumb)
307            os << ".w";
308        os << "   ";
309    }
310}
311
312void
313ArmStaticInst::printMemSymbol(std::ostream &os,
314                              const SymbolTable *symtab,
315                              const std::string &prefix,
316                              const Addr addr,
317                              const std::string &suffix) const
318{
319    Addr symbolAddr;
320    std::string symbol;
321    if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
322        ccprintf(os, "%s%s", prefix, symbol);
323        if (symbolAddr != addr)
324            ccprintf(os, "+%d", addr - symbolAddr);
325        ccprintf(os, suffix);
326    }
327}
328
329void
330ArmStaticInst::printShiftOperand(std::ostream &os,
331                                     IntRegIndex rm,
332                                     bool immShift,
333                                     uint32_t shiftAmt,
334                                     IntRegIndex rs,
335                                     ArmShiftType type) const
336{
337    bool firstOp = false;
338
339    if (rm != INTREG_ZERO) {
340        printReg(os, rm);
341    }
342
343    bool done = false;
344
345    if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
346        shiftAmt = 32;
347
348    switch (type) {
349      case LSL:
350        if (immShift && shiftAmt == 0) {
351            done = true;
352            break;
353        }
354        if (!firstOp)
355            os << ", ";
356        os << "LSL";
357        break;
358      case LSR:
359        if (!firstOp)
360            os << ", ";
361        os << "LSR";
362        break;
363      case ASR:
364        if (!firstOp)
365            os << ", ";
366        os << "ASR";
367        break;
368      case ROR:
369        if (immShift && shiftAmt == 0) {
370            if (!firstOp)
371                os << ", ";
372            os << "RRX";
373            done = true;
374            break;
375        }
376        if (!firstOp)
377            os << ", ";
378        os << "ROR";
379        break;
380      default:
381        panic("Tried to disassemble unrecognized shift type.\n");
382    }
383    if (!done) {
384        if (!firstOp)
385            os << " ";
386        if (immShift)
387            os << "#" << shiftAmt;
388        else
389            printReg(os, rs);
390    }
391}
392
393void
394ArmStaticInst::printDataInst(std::ostream &os, bool withImm,
395        bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
396        IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
397        ArmShiftType type, uint32_t imm) const
398{
399    printMnemonic(os, s ? "s" : "");
400    bool firstOp = true;
401
402    // Destination
403    if (rd != INTREG_ZERO) {
404        firstOp = false;
405        printReg(os, rd);
406    }
407
408    // Source 1.
409    if (rn != INTREG_ZERO) {
410        if (!firstOp)
411            os << ", ";
412        firstOp = false;
413        printReg(os, rn);
414    }
415
416    if (!firstOp)
417        os << ", ";
418    if (withImm) {
419        ccprintf(os, "#%d", imm);
420    } else {
421        printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
422    }
423}
424
425std::string
426ArmStaticInst::generateDisassembly(Addr pc,
427                                   const SymbolTable *symtab) const
428{
429    std::stringstream ss;
430    printMnemonic(ss);
431    return ss.str();
432}
433}
434