static_inst.cc revision 10037:5cac77888310
1/*
2 * Copyright (c) 2010-2013 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        panic("printReg: CCRegClass but ARM has no CC regs\n");
339    }
340}
341
342void
343ArmStaticInst::printMnemonic(std::ostream &os,
344                             const std::string &suffix,
345                             bool withPred,
346                             bool withCond64,
347                             ConditionCode cond64) const
348{
349    os << "  " << mnemonic;
350    if (withPred && !aarch64) {
351        printCondition(os, machInst.condCode);
352        os << suffix;
353    } else if (withCond64) {
354        os << ".";
355        printCondition(os, cond64);
356        os << suffix;
357    }
358    if (machInst.bigThumb)
359        os << ".w";
360    os << "   ";
361}
362
363void
364ArmStaticInst::printTarget(std::ostream &os, Addr target,
365                           const SymbolTable *symtab) const
366{
367    Addr symbolAddr;
368    std::string symbol;
369
370    if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) {
371        ccprintf(os, "<%s", symbol);
372        if (symbolAddr != target)
373            ccprintf(os, "+%d>", target - symbolAddr);
374        else
375            ccprintf(os, ">");
376    } else {
377        ccprintf(os, "%#x", target);
378    }
379}
380
381void
382ArmStaticInst::printCondition(std::ostream &os,
383                              unsigned code,
384                              bool noImplicit) const
385{
386    switch (code) {
387      case COND_EQ:
388        os << "eq";
389        break;
390      case COND_NE:
391        os << "ne";
392        break;
393      case COND_CS:
394        os << "cs";
395        break;
396      case COND_CC:
397        os << "cc";
398        break;
399      case COND_MI:
400        os << "mi";
401        break;
402      case COND_PL:
403        os << "pl";
404        break;
405      case COND_VS:
406        os << "vs";
407        break;
408      case COND_VC:
409        os << "vc";
410        break;
411      case COND_HI:
412        os << "hi";
413        break;
414      case COND_LS:
415        os << "ls";
416        break;
417      case COND_GE:
418        os << "ge";
419        break;
420      case COND_LT:
421        os << "lt";
422        break;
423      case COND_GT:
424        os << "gt";
425        break;
426      case COND_LE:
427        os << "le";
428        break;
429      case COND_AL:
430        // This one is implicit.
431        if (noImplicit)
432            os << "al";
433        break;
434      case COND_UC:
435        // Unconditional.
436        if (noImplicit)
437            os << "uc";
438        break;
439      default:
440        panic("Unrecognized condition code %d.\n", code);
441    }
442}
443
444void
445ArmStaticInst::printMemSymbol(std::ostream &os,
446                              const SymbolTable *symtab,
447                              const std::string &prefix,
448                              const Addr addr,
449                              const std::string &suffix) const
450{
451    Addr symbolAddr;
452    std::string symbol;
453    if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
454        ccprintf(os, "%s%s", prefix, symbol);
455        if (symbolAddr != addr)
456            ccprintf(os, "+%d", addr - symbolAddr);
457        ccprintf(os, suffix);
458    }
459}
460
461void
462ArmStaticInst::printShiftOperand(std::ostream &os,
463                                     IntRegIndex rm,
464                                     bool immShift,
465                                     uint32_t shiftAmt,
466                                     IntRegIndex rs,
467                                     ArmShiftType type) const
468{
469    bool firstOp = false;
470
471    if (rm != INTREG_ZERO) {
472        printReg(os, rm);
473    }
474
475    bool done = false;
476
477    if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
478        shiftAmt = 32;
479
480    switch (type) {
481      case LSL:
482        if (immShift && shiftAmt == 0) {
483            done = true;
484            break;
485        }
486        if (!firstOp)
487            os << ", ";
488        os << "LSL";
489        break;
490      case LSR:
491        if (!firstOp)
492            os << ", ";
493        os << "LSR";
494        break;
495      case ASR:
496        if (!firstOp)
497            os << ", ";
498        os << "ASR";
499        break;
500      case ROR:
501        if (immShift && shiftAmt == 0) {
502            if (!firstOp)
503                os << ", ";
504            os << "RRX";
505            done = true;
506            break;
507        }
508        if (!firstOp)
509            os << ", ";
510        os << "ROR";
511        break;
512      default:
513        panic("Tried to disassemble unrecognized shift type.\n");
514    }
515    if (!done) {
516        if (!firstOp)
517            os << " ";
518        if (immShift)
519            os << "#" << shiftAmt;
520        else
521            printReg(os, rs);
522    }
523}
524
525void
526ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os,
527                                  IntRegIndex rm, ArmExtendType type,
528                                  int64_t shiftAmt) const
529{
530    if (!firstOperand)
531        ccprintf(os, ", ");
532    printReg(os, rm);
533    if (type == UXTX && shiftAmt == 0)
534        return;
535    switch (type) {
536      case UXTB: ccprintf(os, ", UXTB");
537        break;
538      case UXTH: ccprintf(os, ", UXTH");
539        break;
540      case UXTW: ccprintf(os, ", UXTW");
541        break;
542      case UXTX: ccprintf(os, ", LSL");
543        break;
544      case SXTB: ccprintf(os, ", SXTB");
545        break;
546      case SXTH: ccprintf(os, ", SXTH");
547        break;
548      case SXTW: ccprintf(os, ", SXTW");
549        break;
550      case SXTX: ccprintf(os, ", SXTW");
551        break;
552    }
553    if (type == UXTX || shiftAmt)
554        ccprintf(os, " #%d", shiftAmt);
555}
556
557void
558ArmStaticInst::printDataInst(std::ostream &os, bool withImm,
559        bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
560        IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
561        ArmShiftType type, uint32_t imm) const
562{
563    printMnemonic(os, s ? "s" : "");
564    bool firstOp = true;
565
566    // Destination
567    if (rd != INTREG_ZERO) {
568        firstOp = false;
569        printReg(os, rd);
570    }
571
572    // Source 1.
573    if (rn != INTREG_ZERO) {
574        if (!firstOp)
575            os << ", ";
576        firstOp = false;
577        printReg(os, rn);
578    }
579
580    if (!firstOp)
581        os << ", ";
582    if (withImm) {
583        ccprintf(os, "#%d", imm);
584    } else {
585        printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
586    }
587}
588
589std::string
590ArmStaticInst::generateDisassembly(Addr pc,
591                                   const SymbolTable *symtab) const
592{
593    std::stringstream ss;
594    printMnemonic(ss);
595    return ss.str();
596}
597}
598