static_inst.cc revision 7148:1f8d18f5fe5d
17584SAli.Saidi@arm.com/*
27584SAli.Saidi@arm.com * Copyright (c) 2010 ARM Limited
37584SAli.Saidi@arm.com * All rights reserved
47584SAli.Saidi@arm.com *
57584SAli.Saidi@arm.com * The license below extends only to copyright in the software and shall
67584SAli.Saidi@arm.com * not be construed as granting a license to any other intellectual
77584SAli.Saidi@arm.com * property including but not limited to intellectual property relating
87584SAli.Saidi@arm.com * to a hardware implementation of the functionality of the software
97584SAli.Saidi@arm.com * licensed hereunder.  You may use the software subject to the license
107584SAli.Saidi@arm.com * terms below provided that you ensure that this notice is replicated
117584SAli.Saidi@arm.com * unmodified and in its entirety in all distributions of the software,
127584SAli.Saidi@arm.com * modified or unmodified, in source code or in binary form.
137584SAli.Saidi@arm.com *
147584SAli.Saidi@arm.com * Copyright (c) 2007-2008 The Florida State University
157584SAli.Saidi@arm.com * All rights reserved.
167584SAli.Saidi@arm.com *
177584SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without
187584SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are
197584SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright
207584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer;
217584SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright
227584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the
237584SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution;
247584SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its
257584SAli.Saidi@arm.com * contributors may be used to endorse or promote products derived from
267584SAli.Saidi@arm.com * this software without specific prior written permission.
277584SAli.Saidi@arm.com *
287584SAli.Saidi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
297584SAli.Saidi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
307584SAli.Saidi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
317584SAli.Saidi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
327584SAli.Saidi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
337584SAli.Saidi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
347584SAli.Saidi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
357584SAli.Saidi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
367584SAli.Saidi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
377584SAli.Saidi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
387584SAli.Saidi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
397584SAli.Saidi@arm.com *
407584SAli.Saidi@arm.com * Authors: Stephen Hines
417584SAli.Saidi@arm.com */
427584SAli.Saidi@arm.com
437584SAli.Saidi@arm.com#include "arch/arm/faults.hh"
447584SAli.Saidi@arm.com#include "arch/arm/insts/static_inst.hh"
457584SAli.Saidi@arm.com#include "base/condcodes.hh"
467584SAli.Saidi@arm.com#include "base/cprintf.hh"
477584SAli.Saidi@arm.com#include "base/loader/symtab.hh"
487584SAli.Saidi@arm.com
497584SAli.Saidi@arm.comnamespace ArmISA
509525SAndreas.Sandberg@ARM.com{
517584SAli.Saidi@arm.com// Shift Rm by an immediate value
529806Sstever@gmail.comint32_t
537584SAli.Saidi@arm.comArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
547584SAli.Saidi@arm.com                                uint32_t type, uint32_t cfval) const
5510905Sandreas.sandberg@arm.com{
567584SAli.Saidi@arm.com    assert(shamt < 32);
577584SAli.Saidi@arm.com    ArmShiftType shiftType;
587584SAli.Saidi@arm.com    shiftType = (ArmShiftType)type;
597584SAli.Saidi@arm.com
607584SAli.Saidi@arm.com    switch (shiftType)
617584SAli.Saidi@arm.com    {
627584SAli.Saidi@arm.com      case LSL:
637584SAli.Saidi@arm.com        return base << shamt;
647584SAli.Saidi@arm.com      case LSR:
657584SAli.Saidi@arm.com        if (shamt == 0)
667584SAli.Saidi@arm.com            return 0;
677584SAli.Saidi@arm.com        else
687584SAli.Saidi@arm.com            return base >> shamt;
697584SAli.Saidi@arm.com      case ASR:
707584SAli.Saidi@arm.com        if (shamt == 0)
717584SAli.Saidi@arm.com            return (int32_t)base >> 31;
727584SAli.Saidi@arm.com        else
737584SAli.Saidi@arm.com            return (int32_t)base >> shamt;
747584SAli.Saidi@arm.com      case ROR:
757584SAli.Saidi@arm.com        if (shamt == 0)
767584SAli.Saidi@arm.com            return (cfval << 31) | (base >> 1); // RRX
777584SAli.Saidi@arm.com        else
787584SAli.Saidi@arm.com            return (base << (32 - shamt)) | (base >> shamt);
797584SAli.Saidi@arm.com      default:
807584SAli.Saidi@arm.com        ccprintf(std::cerr, "Unhandled shift type\n");
817584SAli.Saidi@arm.com        exit(1);
827584SAli.Saidi@arm.com        break;
837584SAli.Saidi@arm.com    }
847584SAli.Saidi@arm.com    return 0;
857584SAli.Saidi@arm.com}
869421Sandreas.hansson@arm.com
877584SAli.Saidi@arm.com// Shift Rm by Rs
887584SAli.Saidi@arm.comint32_t
899421Sandreas.hansson@arm.comArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
907584SAli.Saidi@arm.com                               uint32_t type, uint32_t cfval) const
917584SAli.Saidi@arm.com{
927584SAli.Saidi@arm.com    enum ArmShiftType shiftType;
937584SAli.Saidi@arm.com    shiftType = (enum ArmShiftType) type;
947584SAli.Saidi@arm.com
957584SAli.Saidi@arm.com    switch (shiftType)
967584SAli.Saidi@arm.com    {
977584SAli.Saidi@arm.com      case LSL:
987584SAli.Saidi@arm.com        if (shamt >= 32)
997584SAli.Saidi@arm.com            return 0;
1007584SAli.Saidi@arm.com        else
1017584SAli.Saidi@arm.com            return base << shamt;
1027584SAli.Saidi@arm.com      case LSR:
1037584SAli.Saidi@arm.com        if (shamt >= 32)
1047584SAli.Saidi@arm.com            return 0;
1057584SAli.Saidi@arm.com        else
1067584SAli.Saidi@arm.com            return base >> shamt;
1077584SAli.Saidi@arm.com      case ASR:
1087584SAli.Saidi@arm.com        if (shamt >= 32)
1097584SAli.Saidi@arm.com            return (int32_t)base >> 31;
1107584SAli.Saidi@arm.com        else
1117584SAli.Saidi@arm.com            return (int32_t)base >> shamt;
1127584SAli.Saidi@arm.com      case ROR:
1137584SAli.Saidi@arm.com        shamt = shamt & 0x1f;
1147584SAli.Saidi@arm.com        if (shamt == 0)
1157584SAli.Saidi@arm.com            return base;
1167584SAli.Saidi@arm.com        else
1177584SAli.Saidi@arm.com            return (base << (32 - shamt)) | (base >> shamt);
1187584SAli.Saidi@arm.com      default:
1197584SAli.Saidi@arm.com        ccprintf(std::cerr, "Unhandled shift type\n");
1207584SAli.Saidi@arm.com        exit(1);
1217584SAli.Saidi@arm.com        break;
1227584SAli.Saidi@arm.com    }
1237733SAli.Saidi@ARM.com    return 0;
12410905Sandreas.sandberg@arm.com}
12510905Sandreas.sandberg@arm.com
1267584SAli.Saidi@arm.com
1277584SAli.Saidi@arm.com// Generate C for a shift by immediate
1287584SAli.Saidi@arm.combool
1299525SAndreas.Sandberg@ARM.comArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
1307584SAli.Saidi@arm.com                                   uint32_t type, uint32_t cfval) const
1317584SAli.Saidi@arm.com{
1327584SAli.Saidi@arm.com    enum ArmShiftType shiftType;
1337584SAli.Saidi@arm.com    shiftType = (enum ArmShiftType) type;
1347584SAli.Saidi@arm.com
1357584SAli.Saidi@arm.com    switch (shiftType)
1367584SAli.Saidi@arm.com    {
1377584SAli.Saidi@arm.com      case LSL:
1387584SAli.Saidi@arm.com        if (shamt == 0)
1397584SAli.Saidi@arm.com            return cfval;
1407584SAli.Saidi@arm.com        else
1417584SAli.Saidi@arm.com            return (base >> (32 - shamt)) & 1;
1427584SAli.Saidi@arm.com      case LSR:
1437584SAli.Saidi@arm.com        if (shamt == 0)
1447584SAli.Saidi@arm.com            return (base >> 31);
1457584SAli.Saidi@arm.com        else
1467584SAli.Saidi@arm.com            return (base >> (shamt - 1)) & 1;
1477584SAli.Saidi@arm.com      case ASR:
1487584SAli.Saidi@arm.com        if (shamt == 0)
1497584SAli.Saidi@arm.com            return (base >> 31);
1507584SAli.Saidi@arm.com        else
1517584SAli.Saidi@arm.com            return (base >> (shamt - 1)) & 1;
1527584SAli.Saidi@arm.com      case ROR:
1537584SAli.Saidi@arm.com        shamt = shamt & 0x1f;
1547584SAli.Saidi@arm.com        if (shamt == 0)
1557584SAli.Saidi@arm.com            return (base & 1); // RRX
1567584SAli.Saidi@arm.com        else
1577584SAli.Saidi@arm.com            return (base >> (shamt - 1)) & 1;
1587584SAli.Saidi@arm.com      default:
1597584SAli.Saidi@arm.com        ccprintf(std::cerr, "Unhandled shift type\n");
1607584SAli.Saidi@arm.com        exit(1);
1617584SAli.Saidi@arm.com        break;
1627584SAli.Saidi@arm.com    }
16310905Sandreas.sandberg@arm.com    return 0;
16410905Sandreas.sandberg@arm.com}
1657584SAli.Saidi@arm.com
1667584SAli.Saidi@arm.com
1677584SAli.Saidi@arm.com// Generate C for a shift by Rs
1687584SAli.Saidi@arm.combool
1697584SAli.Saidi@arm.comArmStaticInst::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