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