Home | History | Annotate | Download | only in Disassembler
      1 //===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// This file is part of the ARC Disassembler.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "ARC.h"
     16 #include "ARCRegisterInfo.h"
     17 #include "MCTargetDesc/ARCMCTargetDesc.h"
     18 #include "llvm/MC/MCContext.h"
     19 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
     20 #include "llvm/MC/MCFixedLenDisassembler.h"
     21 #include "llvm/MC/MCInst.h"
     22 #include "llvm/MC/MCInstrInfo.h"
     23 #include "llvm/MC/MCSubtargetInfo.h"
     24 #include "llvm/Support/TargetRegistry.h"
     25 
     26 using namespace llvm;
     27 
     28 #define DEBUG_TYPE "arc-disassembler"
     29 
     30 using DecodeStatus = MCDisassembler::DecodeStatus;
     31 
     32 namespace {
     33 
     34 /// A disassembler class for ARC.
     35 class ARCDisassembler : public MCDisassembler {
     36 public:
     37   std::unique_ptr<MCInstrInfo const> const MCII;
     38 
     39   ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
     40                   MCInstrInfo const *MCII)
     41       : MCDisassembler(STI, Ctx), MCII(MCII) {}
     42 
     43   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
     44                               ArrayRef<uint8_t> Bytes, uint64_t Address,
     45                               raw_ostream &VStream,
     46                               raw_ostream &CStream) const override;
     47 };
     48 
     49 } // end anonymous namespace
     50 
     51 static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
     52                               uint64_t &Size, uint32_t &Insn) {
     53   Size = 4;
     54   // Read 2 16-bit values, but swap hi/lo parts.
     55   Insn =
     56       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
     57   return true;
     58 }
     59 
     60 static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
     61                               uint64_t &Size, uint64_t &Insn) {
     62   Size = 8;
     63   Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
     64          ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
     65          ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
     66          ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
     67   return true;
     68 }
     69 
     70 static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
     71                               uint64_t &Size, uint64_t &Insn) {
     72   Size = 6;
     73   Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
     74          ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
     75          ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
     76   return true;
     77 }
     78 
     79 static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
     80                               uint64_t &Size, uint32_t &Insn) {
     81   Size = 2;
     82   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
     83   return true;
     84 }
     85 
     86 template <unsigned B>
     87 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
     88                                         uint64_t Address = 0,
     89                                         const void *Decoder = nullptr);
     90 
     91 template <unsigned B>
     92 static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
     93                                         uint64_t Address = 0,
     94                                         const void *Decoder = nullptr);
     95 
     96 template <unsigned B>
     97 static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
     98                                         uint64_t Address, const void *Decoder);
     99 
    100 static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
    101 
    102 static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
    103                                             const void *);
    104 
    105 static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
    106                                             const void *);
    107 
    108 static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
    109                                              const void *);
    110 
    111 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
    112                                               const void *);
    113 
    114 static const uint16_t GPR32DecoderTable[] = {
    115     ARC::R0,  ARC::R1,    ARC::R2,  ARC::R3,   ARC::R4,  ARC::R5,  ARC::R6,
    116     ARC::R7,  ARC::R8,    ARC::R9,  ARC::R10,  ARC::R11, ARC::R12, ARC::R13,
    117     ARC::R14, ARC::R15,   ARC::R16, ARC::R17,  ARC::R18, ARC::R19, ARC::R20,
    118     ARC::R21, ARC::R22,   ARC::R23, ARC::R24,  ARC::R25, ARC::GP,  ARC::FP,
    119     ARC::SP,  ARC::ILINK, ARC::R30, ARC::BLINK};
    120 
    121 static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
    122                                              uint64_t Address,
    123                                              const void *Decoder) {
    124   if (RegNo >= 32) {
    125     LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
    126     return MCDisassembler::Fail;
    127   }
    128 
    129   unsigned Reg = GPR32DecoderTable[RegNo];
    130   Inst.addOperand(MCOperand::createReg(Reg));
    131   return MCDisassembler::Success;
    132 }
    133 
    134 static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
    135                                                uint64_t Address,
    136                                                const void *Decoder) {
    137   // Enumerates registers from ranges [r0-r3],[r12-r15].
    138   if (RegNo > 3)
    139     RegNo += 8; // 4 for r12, etc...
    140 
    141   return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
    142 }
    143 
    144 #include "ARCGenDisassemblerTables.inc"
    145 
    146 static unsigned decodeCField(unsigned Insn) {
    147   return fieldFromInstruction(Insn, 6, 6);
    148 }
    149 
    150 static unsigned decodeBField(unsigned Insn) {
    151   return (fieldFromInstruction(Insn, 12, 3) << 3) |
    152          fieldFromInstruction(Insn, 24, 3);
    153 }
    154 
    155 static unsigned decodeAField(unsigned Insn) {
    156   return fieldFromInstruction(Insn, 0, 6);
    157 }
    158 
    159 static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
    160                                  const void *Dec) {
    161   // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
    162   unsigned S9 = Insn & 0x1ff;
    163   unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
    164   DecodeGPR32RegisterClass(Inst, R, Address, Dec);
    165   Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
    166   return MCDisassembler::Success;
    167 }
    168 
    169 static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
    170                                   uint64_t Value, const void *Decoder) {
    171   static const uint64_t atLeast = 2;
    172   // TODO: Try to force emitter to use MCDisassembler* instead of void*.
    173   auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
    174   return (nullptr != Disassembler &&
    175           Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
    176                                                  atLeast));
    177 }
    178 
    179 static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
    180                                      uint64_t Offset, const void *Decoder) {
    181   uint64_t nextAddress = Address + Offset;
    182 
    183   if (!DecodeSymbolicOperand(Inst, Address, nextAddress, Decoder))
    184     Inst.addOperand(MCOperand::createImm(Offset));
    185 }
    186 
    187 template <unsigned B>
    188 static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
    189                                         uint64_t Address, const void *Decoder) {
    190 
    191   static_assert(B > 0, "field is empty");
    192   DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
    193   return MCDisassembler::Success;
    194 }
    195 
    196 template <unsigned B>
    197 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
    198                                         uint64_t /*Address*/,
    199                                         const void * /*Decoder*/) {
    200 
    201   static_assert(B > 0, "field is empty");
    202   Inst.addOperand(MCOperand::createImm(
    203       SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
    204   return MCDisassembler::Success;
    205 }
    206 
    207 template <unsigned B>
    208 static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
    209                                           uint64_t /*Address*/,
    210                                           const void * /*Decoder*/) {
    211 
    212   static_assert(B > 0, "field is empty");
    213   const unsigned max = (1u << B) - 1;
    214   Inst.addOperand(
    215       MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
    216   return MCDisassembler::Success;
    217 }
    218 
    219 static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
    220                                             uint64_t Address,
    221                                             const void *Decoder) {
    222   unsigned SrcC, DstB, LImm;
    223   DstB = decodeBField(Insn);
    224   if (DstB != 62) {
    225     LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
    226     return MCDisassembler::Fail;
    227   }
    228   SrcC = decodeCField(Insn);
    229   DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
    230   LImm = (Insn >> 32);
    231   Inst.addOperand(MCOperand::createImm(LImm));
    232   Inst.addOperand(MCOperand::createImm(0));
    233   return MCDisassembler::Success;
    234 }
    235 
    236 static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
    237                                             uint64_t Address,
    238                                             const void *Decoder) {
    239   unsigned DstA, SrcB, LImm;
    240   LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
    241   SrcB = decodeBField(Insn);
    242   if (SrcB != 62) {
    243     LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
    244     return MCDisassembler::Fail;
    245   }
    246   DstA = decodeAField(Insn);
    247   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
    248   LImm = (Insn >> 32);
    249   Inst.addOperand(MCOperand::createImm(LImm));
    250   Inst.addOperand(MCOperand::createImm(0));
    251   return MCDisassembler::Success;
    252 }
    253 
    254 static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
    255                                              uint64_t Address,
    256                                              const void *Decoder) {
    257   unsigned DstA, SrcB;
    258   LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
    259   DstA = decodeAField(Insn);
    260   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
    261   SrcB = decodeBField(Insn);
    262   DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
    263   if (decodeCField(Insn) != 62) {
    264     LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
    265     return MCDisassembler::Fail;
    266   }
    267   Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
    268   return MCDisassembler::Success;
    269 }
    270 
    271 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
    272                                               uint64_t Address,
    273                                               const void *Decoder) {
    274   LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
    275   using Field = decltype(Insn);
    276   Field h = fieldFromInstruction(Insn, 5, 3) |
    277             (fieldFromInstruction(Insn, 0, 2) << 3);
    278   Field g = fieldFromInstruction(Insn, 8, 3) |
    279             (fieldFromInstruction(Insn, 3, 2) << 3);
    280 
    281   auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
    282                                                        Field Value) {
    283     if (30 == RegNum) {
    284       Inst.addOperand(MCOperand::createImm(Value));
    285       return MCDisassembler::Success;
    286     }
    287 
    288     return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
    289   };
    290 
    291   if (MCDisassembler::Success != DecodeRegisterOrImm(g, 0))
    292     return MCDisassembler::Fail;
    293 
    294   return DecodeRegisterOrImm(h, Insn >> 16u);
    295 }
    296 
    297 DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
    298                                              ArrayRef<uint8_t> Bytes,
    299                                              uint64_t Address,
    300                                              raw_ostream &vStream,
    301                                              raw_ostream &cStream) const {
    302   MCDisassembler::DecodeStatus Result;
    303   if (Bytes.size() < 2) {
    304     Size = 0;
    305     return Fail;
    306   }
    307   uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
    308   // 0x00 -> 0x07 are 32-bit instructions.
    309   // 0x08 -> 0x1F are 16-bit instructions.
    310   if (DecodeByte < 0x08) {
    311     // 32-bit instruction.
    312     if (Bytes.size() < 4) {
    313       // Did we decode garbage?
    314       Size = 0;
    315       return Fail;
    316     }
    317     if (Bytes.size() >= 8) {
    318       // Attempt to decode 64-bit instruction.
    319       uint64_t Insn64;
    320       if (!readInstruction64(Bytes, Address, Size, Insn64))
    321         return Fail;
    322       Result =
    323           decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
    324       if (Success == Result) {
    325         LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
    326         return Result;
    327       }
    328       LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
    329     }
    330     uint32_t Insn32;
    331     if (!readInstruction32(Bytes, Address, Size, Insn32)) {
    332       return Fail;
    333     }
    334     // Calling the auto-generated decoder function.
    335     return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
    336   } else {
    337     if (Bytes.size() >= 6) {
    338       // Attempt to treat as instr. with limm data.
    339       uint64_t Insn48;
    340       if (!readInstruction48(Bytes, Address, Size, Insn48))
    341         return Fail;
    342       Result =
    343           decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
    344       if (Success == Result) {
    345         LLVM_DEBUG(
    346             dbgs() << "Successfully decoded 16-bit instruction with limm.");
    347         return Result;
    348       }
    349       LLVM_DEBUG(
    350           dbgs() << "Not a 16-bit instruction with limm, try without it.");
    351     }
    352 
    353     uint32_t Insn16;
    354     if (!readInstruction16(Bytes, Address, Size, Insn16))
    355       return Fail;
    356 
    357     // Calling the auto-generated decoder function.
    358     return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
    359   }
    360 }
    361 
    362 static MCDisassembler *createARCDisassembler(const Target &T,
    363                                              const MCSubtargetInfo &STI,
    364                                              MCContext &Ctx) {
    365   return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
    366 }
    367 
    368 extern "C" void LLVMInitializeARCDisassembler() {
    369   // Register the disassembler.
    370   TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
    371                                          createARCDisassembler);
    372 }
    373