static_inst.cc revision 7148
13546Sgblack@eecs.umich.edu/*
23546Sgblack@eecs.umich.edu * Copyright (c) 2010 ARM Limited
33546Sgblack@eecs.umich.edu * All rights reserved
43546Sgblack@eecs.umich.edu *
53546Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall
63546Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual
73546Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating
83546Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software
93546Sgblack@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
103546Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
113546Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
123546Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
133546Sgblack@eecs.umich.edu *
143546Sgblack@eecs.umich.edu * Copyright (c) 2007-2008 The Florida State University
153546Sgblack@eecs.umich.edu * All rights reserved.
163546Sgblack@eecs.umich.edu *
173546Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
183546Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
193546Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
203546Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
213546Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
223546Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
233546Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
243546Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
253546Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
263546Sgblack@eecs.umich.edu * this software without specific prior written permission.
273546Sgblack@eecs.umich.edu *
283546Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
293546Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
303546Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
314202Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
323546Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
337768SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
347768SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
357768SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
368770Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
378770Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
388770Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
394202Sbinkertn@umich.edu *
404202Sbinkertn@umich.edu * Authors: Stephen Hines
414202Sbinkertn@umich.edu */
423546Sgblack@eecs.umich.edu
438335Snate@binkert.org#include "arch/arm/faults.hh"
448335Snate@binkert.org#include "arch/arm/insts/static_inst.hh"
455192Ssaidi@eecs.umich.edu#include "base/condcodes.hh"
464202Sbinkertn@umich.edu#include "base/cprintf.hh"
474202Sbinkertn@umich.edu#include "base/loader/symtab.hh"
484202Sbinkertn@umich.edu
495406Ssaidi@eecs.umich.edunamespace ArmISA
504202Sbinkertn@umich.edu{
514202Sbinkertn@umich.edu// Shift Rm by an immediate value
524202Sbinkertn@umich.eduint32_t
534202Sbinkertn@umich.eduArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
544202Sbinkertn@umich.edu                                uint32_t type, uint32_t cfval) const
558335Snate@binkert.org{
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
89ArmStaticInst::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
129ArmStaticInst::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
169ArmStaticInst::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
208void
209ArmStaticInst::printReg(std::ostream &os, int reg) const
210{
211    if (reg < FP_Base_DepTag) {
212        switch (reg) {
213          case PCReg:
214            ccprintf(os, "pc");
215            break;
216          case StackPointerReg:
217            ccprintf(os, "sp");
218            break;
219          case FramePointerReg:
220            ccprintf(os, "fp");
221            break;
222          case ReturnAddressReg:
223            ccprintf(os, "lr");
224            break;
225          default:
226            ccprintf(os, "r%d", reg);
227            break;
228        }
229    } else if (reg < Ctrl_Base_DepTag) {
230        ccprintf(os, "f%d", reg - FP_Base_DepTag);
231    } else {
232        reg -= Ctrl_Base_DepTag;
233        assert(reg < NUM_MISCREGS);
234        ccprintf(os, "%s", ArmISA::miscRegName[reg]);
235    }
236}
237
238void
239ArmStaticInst::printMnemonic(std::ostream &os,
240                             const std::string &suffix,
241                             bool withPred) const
242{
243    os << "  " << mnemonic;
244    if (withPred) {
245        unsigned condCode = machInst.condCode;
246        switch (condCode) {
247          case COND_EQ:
248            os << "eq";
249            break;
250          case COND_NE:
251            os << "ne";
252            break;
253          case COND_CS:
254            os << "cs";
255            break;
256          case COND_CC:
257            os << "cc";
258            break;
259          case COND_MI:
260            os << "mi";
261            break;
262          case COND_PL:
263            os << "pl";
264            break;
265          case COND_VS:
266            os << "vs";
267            break;
268          case COND_VC:
269            os << "vc";
270            break;
271          case COND_HI:
272            os << "hi";
273            break;
274          case COND_LS:
275            os << "ls";
276            break;
277          case COND_GE:
278            os << "ge";
279            break;
280          case COND_LT:
281            os << "lt";
282            break;
283          case COND_GT:
284            os << "gt";
285            break;
286          case COND_LE:
287            os << "le";
288            break;
289          case COND_AL:
290            // This one is implicit.
291            break;
292          case COND_UC:
293            // Unconditional.
294            break;
295          default:
296            panic("Unrecognized condition code %d.\n", condCode);
297        }
298        os << suffix;
299        if (machInst.bigThumb)
300            os << ".w";
301        os << "   ";
302    }
303}
304
305void
306ArmStaticInst::printMemSymbol(std::ostream &os,
307                              const SymbolTable *symtab,
308                              const std::string &prefix,
309                              const Addr addr,
310                              const std::string &suffix) const
311{
312    Addr symbolAddr;
313    std::string symbol;
314    if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
315        ccprintf(os, "%s%s", prefix, symbol);
316        if (symbolAddr != addr)
317            ccprintf(os, "+%d", addr - symbolAddr);
318        ccprintf(os, suffix);
319    }
320}
321
322void
323ArmStaticInst::printShiftOperand(std::ostream &os,
324                                     IntRegIndex rm,
325                                     bool immShift,
326                                     uint32_t shiftAmt,
327                                     IntRegIndex rs,
328                                     ArmShiftType type) const
329{
330    bool firstOp = false;
331
332    if (rm != INTREG_ZERO) {
333        printReg(os, rm);
334    }
335
336    bool done = false;
337
338    if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
339        shiftAmt = 32;
340
341    switch (type) {
342      case LSL:
343        if (immShift && shiftAmt == 0) {
344            done = true;
345            break;
346        }
347        if (!firstOp)
348            os << ", ";
349        os << "LSL";
350        break;
351      case LSR:
352        if (!firstOp)
353            os << ", ";
354        os << "LSR";
355        break;
356      case ASR:
357        if (!firstOp)
358            os << ", ";
359        os << "ASR";
360        break;
361      case ROR:
362        if (immShift && shiftAmt == 0) {
363            if (!firstOp)
364                os << ", ";
365            os << "RRX";
366            done = true;
367            break;
368        }
369        if (!firstOp)
370            os << ", ";
371        os << "ROR";
372        break;
373      default:
374        panic("Tried to disassemble unrecognized shift type.\n");
375    }
376    if (!done) {
377        if (!firstOp)
378            os << " ";
379        if (immShift)
380            os << "#" << shiftAmt;
381        else
382            printReg(os, rs);
383    }
384}
385
386void
387ArmStaticInst::printDataInst(std::ostream &os, bool withImm,
388        bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
389        IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
390        ArmShiftType type, uint32_t imm) const
391{
392    printMnemonic(os, s ? "s" : "");
393    bool firstOp = true;
394
395    // Destination
396    if (rd != INTREG_ZERO) {
397        firstOp = false;
398        printReg(os, rd);
399    }
400
401    // Source 1.
402    if (rn != INTREG_ZERO) {
403        if (!firstOp)
404            os << ", ";
405        firstOp = false;
406        printReg(os, rn);
407    }
408
409    if (!firstOp)
410        os << ", ";
411    if (withImm) {
412        ccprintf(os, "#%d", imm);
413    } else {
414        printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
415    }
416}
417
418std::string
419ArmStaticInst::generateDisassembly(Addr pc,
420                                   const SymbolTable *symtab) const
421{
422    std::stringstream ss;
423    printMnemonic(ss);
424    return ss.str();
425}
426}
427