static_inst.cc revision 7109
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_NV:
342            os << "nv";
343            break;
344          default:
345            panic("Unrecognized condition code %d.\n", condCode);
346        }
347        os << suffix << "   ";
348    }
349}
350
351void
352ArmStaticInstBase::printMemSymbol(std::ostream &os,
353                              const SymbolTable *symtab,
354                              const std::string &prefix,
355                              const Addr addr,
356                              const std::string &suffix) const
357{
358    Addr symbolAddr;
359    std::string symbol;
360    if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
361        ccprintf(os, "%s%s", prefix, symbol);
362        if (symbolAddr != addr)
363            ccprintf(os, "+%d", addr - symbolAddr);
364        ccprintf(os, suffix);
365    }
366}
367
368void
369ArmStaticInstBase::printShiftOperand(std::ostream &os) const
370{
371    printReg(os, machInst.rm);
372
373    bool immShift = (machInst.opcode4 == 0);
374    bool done = false;
375    unsigned shiftAmt = (machInst.shiftSize);
376    ArmShiftType type = (ArmShiftType)(uint32_t)machInst.shift;
377
378    if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
379        shiftAmt = 32;
380
381    switch (type) {
382      case LSL:
383        if (immShift && shiftAmt == 0) {
384            done = true;
385            break;
386        }
387        os << ", LSL";
388        break;
389      case LSR:
390        os << ", LSR";
391        break;
392      case ASR:
393        os << ", ASR";
394        break;
395      case ROR:
396        if (immShift && shiftAmt == 0) {
397            os << ", RRX";
398            done = true;
399            break;
400        }
401        os << ", ROR";
402        break;
403      default:
404        panic("Tried to disassemble unrecognized shift type.\n");
405    }
406    if (!done) {
407        os << " ";
408        if (immShift)
409            os << "#" << shiftAmt;
410        else
411            printReg(os, machInst.rs);
412    }
413}
414
415void
416ArmStaticInstBase::printDataInst(std::ostream &os, bool withImm) const
417{
418    printMnemonic(os, machInst.sField ? "s" : "");
419    //XXX It would be nice if the decoder figured this all out for us.
420    unsigned opcode = machInst.opcode;
421    bool firstOp = true;
422
423    // Destination
424    // Cmp, cmn, teq, and tst don't have one.
425    if (opcode < 8 || opcode > 0xb) {
426        firstOp = false;
427        printReg(os, machInst.rd);
428    }
429
430    // Source 1.
431    // Mov and Movn don't have one of these.
432    if (opcode != 0xd && opcode != 0xf) {
433        if (!firstOp)
434            os << ", ";
435        firstOp = false;
436        printReg(os, machInst.rn);
437    }
438
439    if (!firstOp)
440        os << ", ";
441    if (withImm) {
442        unsigned rotate = machInst.rotate * 2;
443        uint32_t imm = machInst.imm;
444        ccprintf(os, "#%#x", (imm << (32 - rotate)) | (imm >> rotate));
445    } else {
446        printShiftOperand(os);
447    }
448}
449
450std::string
451ArmStaticInstBase::generateDisassembly(Addr pc,
452                                   const SymbolTable *symtab) const
453{
454    std::stringstream ss;
455    printMnemonic(ss);
456    return ss.str();
457}
458}
459