static_inst.cc revision 7122:0c8bb53cdffe
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
234uint32_t
235ArmStaticInstBase::modified_imm(uint8_t ctrlImm, uint8_t dataImm) const
236{
237    uint32_t bigData = dataImm;
238    uint32_t bigCtrl = ctrlImm;
239    if (bigCtrl < 4) {
240        switch (bigCtrl) {
241          case 0:
242            return bigData;
243          case 1:
244            return bigData | (bigData << 16);
245          case 2:
246            return (bigData << 8) | (bigData << 24);
247          case 3:
248            return (bigData << 0) | (bigData << 8) |
249                   (bigData << 16) | (bigData << 24);
250        }
251    }
252    bigCtrl = (bigCtrl << 1) | ((bigData >> 7) & 0x1);
253    bigData |= (1 << 7);
254    return bigData << (32 - bigCtrl);
255}
256
257void
258ArmStaticInstBase::printReg(std::ostream &os, int reg) const
259{
260    if (reg < FP_Base_DepTag) {
261        switch (reg) {
262          case PCReg:
263            ccprintf(os, "pc");
264            break;
265          case StackPointerReg:
266            ccprintf(os, "sp");
267            break;
268          case FramePointerReg:
269            ccprintf(os, "fp");
270            break;
271          case ReturnAddressReg:
272            ccprintf(os, "lr");
273            break;
274          default:
275            ccprintf(os, "r%d", reg);
276            break;
277        }
278    } else if (reg < Ctrl_Base_DepTag) {
279        ccprintf(os, "f%d", reg - FP_Base_DepTag);
280    } else {
281        reg -= Ctrl_Base_DepTag;
282        assert(reg < NUM_MISCREGS);
283        ccprintf(os, "%s", ArmISA::miscRegName[reg]);
284    }
285}
286
287void
288ArmStaticInstBase::printMnemonic(std::ostream &os,
289                             const std::string &suffix,
290                             bool withPred) const
291{
292    os << "  " << mnemonic;
293    if (withPred) {
294        unsigned condCode = machInst.condCode;
295        switch (condCode) {
296          case COND_EQ:
297            os << "eq";
298            break;
299          case COND_NE:
300            os << "ne";
301            break;
302          case COND_CS:
303            os << "cs";
304            break;
305          case COND_CC:
306            os << "cc";
307            break;
308          case COND_MI:
309            os << "mi";
310            break;
311          case COND_PL:
312            os << "pl";
313            break;
314          case COND_VS:
315            os << "vs";
316            break;
317          case COND_VC:
318            os << "vc";
319            break;
320          case COND_HI:
321            os << "hi";
322            break;
323          case COND_LS:
324            os << "ls";
325            break;
326          case COND_GE:
327            os << "ge";
328            break;
329          case COND_LT:
330            os << "lt";
331            break;
332          case COND_GT:
333            os << "gt";
334            break;
335          case COND_LE:
336            os << "le";
337            break;
338          case COND_AL:
339            // This one is implicit.
340            break;
341          case COND_UC:
342            // Unconditional.
343            break;
344          default:
345            panic("Unrecognized condition code %d.\n", condCode);
346        }
347        os << suffix;
348        if (machInst.bigThumb)
349            os << ".w";
350        os << "   ";
351    }
352}
353
354void
355ArmStaticInstBase::printMemSymbol(std::ostream &os,
356                              const SymbolTable *symtab,
357                              const std::string &prefix,
358                              const Addr addr,
359                              const std::string &suffix) const
360{
361    Addr symbolAddr;
362    std::string symbol;
363    if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
364        ccprintf(os, "%s%s", prefix, symbol);
365        if (symbolAddr != addr)
366            ccprintf(os, "+%d", addr - symbolAddr);
367        ccprintf(os, suffix);
368    }
369}
370
371void
372ArmStaticInstBase::printShiftOperand(std::ostream &os) const
373{
374    printReg(os, machInst.rm);
375
376    bool immShift = (machInst.opcode4 == 0);
377    bool done = false;
378    unsigned shiftAmt = (machInst.shiftSize);
379    ArmShiftType type = (ArmShiftType)(uint32_t)machInst.shift;
380
381    if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
382        shiftAmt = 32;
383
384    switch (type) {
385      case LSL:
386        if (immShift && shiftAmt == 0) {
387            done = true;
388            break;
389        }
390        os << ", LSL";
391        break;
392      case LSR:
393        os << ", LSR";
394        break;
395      case ASR:
396        os << ", ASR";
397        break;
398      case ROR:
399        if (immShift && shiftAmt == 0) {
400            os << ", RRX";
401            done = true;
402            break;
403        }
404        os << ", ROR";
405        break;
406      default:
407        panic("Tried to disassemble unrecognized shift type.\n");
408    }
409    if (!done) {
410        os << " ";
411        if (immShift)
412            os << "#" << shiftAmt;
413        else
414            printReg(os, machInst.rs);
415    }
416}
417
418void
419ArmStaticInstBase::printDataInst(std::ostream &os, bool withImm) const
420{
421    printMnemonic(os, machInst.sField ? "s" : "");
422    //XXX It would be nice if the decoder figured this all out for us.
423    unsigned opcode = machInst.opcode;
424    bool firstOp = true;
425
426    // Destination
427    // Cmp, cmn, teq, and tst don't have one.
428    if (opcode < 8 || opcode > 0xb) {
429        firstOp = false;
430        printReg(os, machInst.rd);
431    }
432
433    // Source 1.
434    // Mov and Movn don't have one of these.
435    if (opcode != 0xd && opcode != 0xf) {
436        if (!firstOp)
437            os << ", ";
438        firstOp = false;
439        printReg(os, machInst.rn);
440    }
441
442    if (!firstOp)
443        os << ", ";
444    if (withImm) {
445        unsigned rotate = machInst.rotate * 2;
446        uint32_t imm = machInst.imm;
447        ccprintf(os, "#%#x", (imm << (32 - rotate)) | (imm >> rotate));
448    } else {
449        printShiftOperand(os);
450    }
451}
452
453std::string
454ArmStaticInstBase::generateDisassembly(Addr pc,
455                                   const SymbolTable *symtab) const
456{
457    std::stringstream ss;
458    printMnemonic(ss);
459    return ss.str();
460}
461}
462