static_inst.cc revision 10934:5af8f40d8f2c
1/*
2 * Copyright (c) 2010-2014 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
89int64_t
90ArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt,
91                          ArmShiftType type, uint8_t width) const
92{
93    shiftAmt = shiftAmt % width;
94    ArmShiftType shiftType;
95    shiftType = (ArmShiftType)type;
96
97    switch (shiftType)
98    {
99      case LSL:
100        return base << shiftAmt;
101      case LSR:
102        if (shiftAmt == 0)
103            return base;
104        else
105            return (base & mask(width)) >> shiftAmt;
106      case ASR:
107        if (shiftAmt == 0) {
108            return base;
109        } else {
110            int sign_bit = bits(base, intWidth - 1);
111            base >>= shiftAmt;
112            base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base;
113            return base & mask(intWidth);
114        }
115      case ROR:
116        if (shiftAmt == 0)
117            return base;
118        else
119            return (base << (width - shiftAmt)) | (base >> shiftAmt);
120      default:
121        ccprintf(std::cerr, "Unhandled shift type\n");
122        exit(1);
123        break;
124    }
125    return 0;
126}
127
128int64_t
129ArmStaticInst::extendReg64(uint64_t base, ArmExtendType type,
130                           uint64_t shiftAmt, uint8_t width) const
131{
132    bool sign_extend = false;
133    int len = 0;
134    switch (type) {
135      case UXTB:
136        len = 8;
137        break;
138      case UXTH:
139        len = 16;
140        break;
141      case UXTW:
142        len = 32;
143        break;
144      case UXTX:
145        len = 64;
146        break;
147      case SXTB:
148        len = 8;
149        sign_extend = true;
150        break;
151      case SXTH:
152        len = 16;
153        sign_extend = true;
154        break;
155      case SXTW:
156        len = 32;
157        sign_extend = true;
158        break;
159      case SXTX:
160        len = 64;
161        sign_extend = true;
162        break;
163    }
164    len = len <= width - shiftAmt ? len : width - shiftAmt;
165    uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt;
166    if (sign_extend) {
167        int sign_bit = bits(tmp, len + shiftAmt - 1);
168        tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp;
169    }
170    return tmp & mask(width);
171}
172
173// Shift Rm by Rs
174int32_t
175ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
176                               uint32_t type, uint32_t cfval) const
177{
178    enum ArmShiftType shiftType;
179    shiftType = (enum ArmShiftType) type;
180
181    switch (shiftType)
182    {
183      case LSL:
184        if (shamt >= 32)
185            return 0;
186        else
187            return base << shamt;
188      case LSR:
189        if (shamt >= 32)
190            return 0;
191        else
192            return base >> shamt;
193      case ASR:
194        if (shamt >= 32)
195            return (base >> 31) | -((base & (1 << 31)) >> 31);
196        else
197            return (base >> shamt) | -((base & (1 << 31)) >> shamt);
198      case ROR:
199        shamt = shamt & 0x1f;
200        if (shamt == 0)
201            return base;
202        else
203            return (base << (32 - shamt)) | (base >> shamt);
204      default:
205        ccprintf(std::cerr, "Unhandled shift type\n");
206        exit(1);
207        break;
208    }
209    return 0;
210}
211
212
213// Generate C for a shift by immediate
214bool
215ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
216                                   uint32_t type, uint32_t cfval) const
217{
218    enum ArmShiftType shiftType;
219    shiftType = (enum ArmShiftType) type;
220
221    switch (shiftType)
222    {
223      case LSL:
224        if (shamt == 0)
225            return cfval;
226        else
227            return (base >> (32 - shamt)) & 1;
228      case LSR:
229        if (shamt == 0)
230            return (base >> 31);
231        else
232            return (base >> (shamt - 1)) & 1;
233      case ASR:
234        if (shamt == 0)
235            return (base >> 31);
236        else
237            return (base >> (shamt - 1)) & 1;
238      case ROR:
239        shamt = shamt & 0x1f;
240        if (shamt == 0)
241            return (base & 1); // RRX
242        else
243            return (base >> (shamt - 1)) & 1;
244      default:
245        ccprintf(std::cerr, "Unhandled shift type\n");
246        exit(1);
247        break;
248    }
249    return 0;
250}
251
252
253// Generate C for a shift by Rs
254bool
255ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
256                                  uint32_t type, uint32_t cfval) const
257{
258    enum ArmShiftType shiftType;
259    shiftType = (enum ArmShiftType) type;
260
261    if (shamt == 0)
262        return cfval;
263
264    switch (shiftType)
265    {
266      case LSL:
267        if (shamt > 32)
268            return 0;
269        else
270            return (base >> (32 - shamt)) & 1;
271      case LSR:
272        if (shamt > 32)
273            return 0;
274        else
275            return (base >> (shamt - 1)) & 1;
276      case ASR:
277        if (shamt > 32)
278            shamt = 32;
279        return (base >> (shamt - 1)) & 1;
280      case ROR:
281        shamt = shamt & 0x1f;
282        if (shamt == 0)
283            shamt = 32;
284        return (base >> (shamt - 1)) & 1;
285      default:
286        ccprintf(std::cerr, "Unhandled shift type\n");
287        exit(1);
288        break;
289    }
290    return 0;
291}
292
293
294void
295ArmStaticInst::printReg(std::ostream &os, int reg) const
296{
297    RegIndex rel_reg;
298
299    switch (regIdxToClass(reg, &rel_reg)) {
300      case IntRegClass:
301        if (aarch64) {
302            if (reg == INTREG_UREG0)
303                ccprintf(os, "ureg0");
304            else if (reg == INTREG_SPX)
305               ccprintf(os, "%s%s", (intWidth == 32) ? "w" : "", "sp");
306            else if (reg == INTREG_X31)
307                ccprintf(os, "%szr", (intWidth == 32) ? "w" : "x");
308            else
309                ccprintf(os, "%s%d", (intWidth == 32) ? "w" : "x", reg);
310        } else {
311            switch (rel_reg) {
312              case PCReg:
313                ccprintf(os, "pc");
314                break;
315              case StackPointerReg:
316                ccprintf(os, "sp");
317                break;
318              case FramePointerReg:
319                ccprintf(os, "fp");
320                break;
321              case ReturnAddressReg:
322                ccprintf(os, "lr");
323                break;
324              default:
325                ccprintf(os, "r%d", reg);
326                break;
327            }
328        }
329        break;
330      case FloatRegClass:
331        ccprintf(os, "f%d", rel_reg);
332        break;
333      case MiscRegClass:
334        assert(rel_reg < NUM_MISCREGS);
335        ccprintf(os, "%s", ArmISA::miscRegName[rel_reg]);
336        break;
337      case CCRegClass:
338        ccprintf(os, "cc_%s", ArmISA::ccRegName[rel_reg]);
339        break;
340      case VectorRegClass:
341        panic("ARM ISA does not have any vector registers yet!");
342    }
343}
344
345void
346ArmStaticInst::printMnemonic(std::ostream &os,
347                             const std::string &suffix,
348                             bool withPred,
349                             bool withCond64,
350                             ConditionCode cond64) const
351{
352    os << "  " << mnemonic;
353    if (withPred && !aarch64) {
354        printCondition(os, machInst.condCode);
355        os << suffix;
356    } else if (withCond64) {
357        os << ".";
358        printCondition(os, cond64);
359        os << suffix;
360    }
361    if (machInst.bigThumb)
362        os << ".w";
363    os << "   ";
364}
365
366void
367ArmStaticInst::printTarget(std::ostream &os, Addr target,
368                           const SymbolTable *symtab) const
369{
370    Addr symbolAddr;
371    std::string symbol;
372
373    if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) {
374        ccprintf(os, "<%s", symbol);
375        if (symbolAddr != target)
376            ccprintf(os, "+%d>", target - symbolAddr);
377        else
378            ccprintf(os, ">");
379    } else {
380        ccprintf(os, "%#x", target);
381    }
382}
383
384void
385ArmStaticInst::printCondition(std::ostream &os,
386                              unsigned code,
387                              bool noImplicit) const
388{
389    switch (code) {
390      case COND_EQ:
391        os << "eq";
392        break;
393      case COND_NE:
394        os << "ne";
395        break;
396      case COND_CS:
397        os << "cs";
398        break;
399      case COND_CC:
400        os << "cc";
401        break;
402      case COND_MI:
403        os << "mi";
404        break;
405      case COND_PL:
406        os << "pl";
407        break;
408      case COND_VS:
409        os << "vs";
410        break;
411      case COND_VC:
412        os << "vc";
413        break;
414      case COND_HI:
415        os << "hi";
416        break;
417      case COND_LS:
418        os << "ls";
419        break;
420      case COND_GE:
421        os << "ge";
422        break;
423      case COND_LT:
424        os << "lt";
425        break;
426      case COND_GT:
427        os << "gt";
428        break;
429      case COND_LE:
430        os << "le";
431        break;
432      case COND_AL:
433        // This one is implicit.
434        if (noImplicit)
435            os << "al";
436        break;
437      case COND_UC:
438        // Unconditional.
439        if (noImplicit)
440            os << "uc";
441        break;
442      default:
443        panic("Unrecognized condition code %d.\n", code);
444    }
445}
446
447void
448ArmStaticInst::printMemSymbol(std::ostream &os,
449                              const SymbolTable *symtab,
450                              const std::string &prefix,
451                              const Addr addr,
452                              const std::string &suffix) const
453{
454    Addr symbolAddr;
455    std::string symbol;
456    if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
457        ccprintf(os, "%s%s", prefix, symbol);
458        if (symbolAddr != addr)
459            ccprintf(os, "+%d", addr - symbolAddr);
460        ccprintf(os, suffix);
461    }
462}
463
464void
465ArmStaticInst::printShiftOperand(std::ostream &os,
466                                     IntRegIndex rm,
467                                     bool immShift,
468                                     uint32_t shiftAmt,
469                                     IntRegIndex rs,
470                                     ArmShiftType type) const
471{
472    bool firstOp = false;
473
474    if (rm != INTREG_ZERO) {
475        printReg(os, rm);
476    }
477
478    bool done = false;
479
480    if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
481        shiftAmt = 32;
482
483    switch (type) {
484      case LSL:
485        if (immShift && shiftAmt == 0) {
486            done = true;
487            break;
488        }
489        if (!firstOp)
490            os << ", ";
491        os << "LSL";
492        break;
493      case LSR:
494        if (!firstOp)
495            os << ", ";
496        os << "LSR";
497        break;
498      case ASR:
499        if (!firstOp)
500            os << ", ";
501        os << "ASR";
502        break;
503      case ROR:
504        if (immShift && shiftAmt == 0) {
505            if (!firstOp)
506                os << ", ";
507            os << "RRX";
508            done = true;
509            break;
510        }
511        if (!firstOp)
512            os << ", ";
513        os << "ROR";
514        break;
515      default:
516        panic("Tried to disassemble unrecognized shift type.\n");
517    }
518    if (!done) {
519        if (!firstOp)
520            os << " ";
521        if (immShift)
522            os << "#" << shiftAmt;
523        else
524            printReg(os, rs);
525    }
526}
527
528void
529ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os,
530                                  IntRegIndex rm, ArmExtendType type,
531                                  int64_t shiftAmt) const
532{
533    if (!firstOperand)
534        ccprintf(os, ", ");
535    printReg(os, rm);
536    if (type == UXTX && shiftAmt == 0)
537        return;
538    switch (type) {
539      case UXTB: ccprintf(os, ", UXTB");
540        break;
541      case UXTH: ccprintf(os, ", UXTH");
542        break;
543      case UXTW: ccprintf(os, ", UXTW");
544        break;
545      case UXTX: ccprintf(os, ", LSL");
546        break;
547      case SXTB: ccprintf(os, ", SXTB");
548        break;
549      case SXTH: ccprintf(os, ", SXTH");
550        break;
551      case SXTW: ccprintf(os, ", SXTW");
552        break;
553      case SXTX: ccprintf(os, ", SXTW");
554        break;
555    }
556    if (type == UXTX || shiftAmt)
557        ccprintf(os, " #%d", shiftAmt);
558}
559
560void
561ArmStaticInst::printDataInst(std::ostream &os, bool withImm,
562        bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
563        IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
564        ArmShiftType type, uint32_t imm) const
565{
566    printMnemonic(os, s ? "s" : "");
567    bool firstOp = true;
568
569    // Destination
570    if (rd != INTREG_ZERO) {
571        firstOp = false;
572        printReg(os, rd);
573    }
574
575    // Source 1.
576    if (rn != INTREG_ZERO) {
577        if (!firstOp)
578            os << ", ";
579        firstOp = false;
580        printReg(os, rn);
581    }
582
583    if (!firstOp)
584        os << ", ";
585    if (withImm) {
586        ccprintf(os, "#%d", imm);
587    } else {
588        printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
589    }
590}
591
592std::string
593ArmStaticInst::generateDisassembly(Addr pc,
594                                   const SymbolTable *symtab) const
595{
596    std::stringstream ss;
597    printMnemonic(ss);
598    return ss.str();
599}
600}
601