Home | History | Annotate | Download | only in MCDisassembler
      1 //===-- EDOperand.cpp - LLVM Enhanced Disassembler ------------------------===//
      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 // This file implements the Enhanced Disassembly library's operand class.  The
     11 // operand is responsible for allowing evaluation given a particular register
     12 // context.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "EDOperand.h"
     17 #include "EDDisassembler.h"
     18 #include "EDInst.h"
     19 #include "llvm/MC/EDInstInfo.h"
     20 #include "llvm/MC/MCInst.h"
     21 using namespace llvm;
     22 
     23 EDOperand::EDOperand(const EDDisassembler &disassembler,
     24                      const EDInst &inst,
     25                      unsigned int opIndex,
     26                      unsigned int &mcOpIndex) :
     27   Disassembler(disassembler),
     28   Inst(inst),
     29   OpIndex(opIndex),
     30   MCOpIndex(mcOpIndex) {
     31   unsigned int numMCOperands = 0;
     32 
     33   Triple::ArchType arch = Disassembler.TgtTriple.getArch();
     34 
     35   if (arch == Triple::x86 ||
     36       arch == Triple::x86_64) {
     37     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
     38 
     39     switch (operandType) {
     40     default:
     41       break;
     42     case kOperandTypeImmediate:
     43       numMCOperands = 1;
     44       break;
     45     case kOperandTypeRegister:
     46       numMCOperands = 1;
     47       break;
     48     case kOperandTypeX86Memory:
     49       numMCOperands = 5;
     50       break;
     51     case kOperandTypeX86EffectiveAddress:
     52       numMCOperands = 4;
     53       break;
     54     case kOperandTypeX86PCRelative:
     55       numMCOperands = 1;
     56       break;
     57     }
     58   }
     59   else if (arch == Triple::arm ||
     60            arch == Triple::thumb) {
     61     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
     62 
     63     switch (operandType) {
     64     default:
     65     case kOperandTypeARMRegisterList:
     66     case kOperandTypeARMDPRRegisterList:
     67     case kOperandTypeARMSPRRegisterList:
     68       break;
     69     case kOperandTypeImmediate:
     70     case kOperandTypeRegister:
     71     case kOperandTypeARMBranchTarget:
     72     case kOperandTypeARMSoImm:
     73     case kOperandTypeARMRotImm:
     74     case kOperandTypeThumb2SoImm:
     75     case kOperandTypeARMSoImm2Part:
     76     case kOperandTypeARMPredicate:
     77     case kOperandTypeThumbITMask:
     78     case kOperandTypeThumb2AddrModeImm8Offset:
     79     case kOperandTypeARMTBAddrMode:
     80     case kOperandTypeThumb2AddrModeImm8s4Offset:
     81     case kOperandTypeARMAddrMode7:
     82     case kOperandTypeThumb2AddrModeReg:
     83       numMCOperands = 1;
     84       break;
     85     case kOperandTypeThumb2SoReg:
     86     case kOperandTypeAddrModeImm12:
     87     case kOperandTypeARMAddrMode2Offset:
     88     case kOperandTypeARMAddrMode3Offset:
     89     case kOperandTypeARMAddrMode4:
     90     case kOperandTypeARMAddrMode5:
     91     case kOperandTypeARMAddrModePC:
     92     case kOperandTypeThumb2AddrModeImm8:
     93     case kOperandTypeThumb2AddrModeImm12:
     94     case kOperandTypeThumb2AddrModeImm8s4:
     95     case kOperandTypeThumbAddrModeImmS1:
     96     case kOperandTypeThumbAddrModeImmS2:
     97     case kOperandTypeThumbAddrModeImmS4:
     98     case kOperandTypeThumbAddrModeRR:
     99     case kOperandTypeThumbAddrModeSP:
    100     case kOperandTypeThumbAddrModePC:
    101       numMCOperands = 2;
    102       break;
    103     case kOperandTypeARMSoReg:
    104     case kOperandTypeLdStSOReg:
    105     case kOperandTypeARMAddrMode2:
    106     case kOperandTypeARMAddrMode3:
    107     case kOperandTypeThumb2AddrModeSoReg:
    108     case kOperandTypeThumbAddrModeRegS1:
    109     case kOperandTypeThumbAddrModeRegS2:
    110     case kOperandTypeThumbAddrModeRegS4:
    111     case kOperandTypeARMAddrMode6Offset:
    112       numMCOperands = 3;
    113       break;
    114     case kOperandTypeARMAddrMode6:
    115       numMCOperands = 4;
    116       break;
    117     }
    118   }
    119 
    120   mcOpIndex += numMCOperands;
    121 }
    122 
    123 EDOperand::~EDOperand() {
    124 }
    125 
    126 int EDOperand::evaluate(uint64_t &result,
    127                         EDRegisterReaderCallback callback,
    128                         void *arg) {
    129   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
    130 
    131   Triple::ArchType arch = Disassembler.TgtTriple.getArch();
    132 
    133   switch (arch) {
    134   default:
    135     return -1;
    136   case Triple::x86:
    137   case Triple::x86_64:
    138     switch (operandType) {
    139     default:
    140       return -1;
    141     case kOperandTypeImmediate:
    142       result = Inst.Inst->getOperand(MCOpIndex).getImm();
    143       return 0;
    144     case kOperandTypeRegister:
    145     {
    146       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
    147       return callback(&result, reg, arg);
    148     }
    149     case kOperandTypeX86PCRelative:
    150     {
    151       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
    152 
    153       uint64_t ripVal;
    154 
    155       // TODO fix how we do this
    156 
    157       if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
    158         return -1;
    159 
    160       result = ripVal + displacement;
    161       return 0;
    162     }
    163     case kOperandTypeX86Memory:
    164     case kOperandTypeX86EffectiveAddress:
    165     {
    166       unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
    167       uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
    168       unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
    169       int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
    170 
    171       uint64_t addr = 0;
    172 
    173       unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
    174 
    175       if (segmentReg != 0 && arch == Triple::x86_64) {
    176         unsigned fsID = Disassembler.registerIDWithName("FS");
    177         unsigned gsID = Disassembler.registerIDWithName("GS");
    178 
    179         if (segmentReg == fsID ||
    180             segmentReg == gsID) {
    181           uint64_t segmentBase;
    182           if (!callback(&segmentBase, segmentReg, arg))
    183             addr += segmentBase;
    184         }
    185       }
    186 
    187       if (baseReg) {
    188         uint64_t baseVal;
    189         if (callback(&baseVal, baseReg, arg))
    190           return -1;
    191         addr += baseVal;
    192       }
    193 
    194       if (indexReg) {
    195         uint64_t indexVal;
    196         if (callback(&indexVal, indexReg, arg))
    197           return -1;
    198         addr += (scaleAmount * indexVal);
    199       }
    200 
    201       addr += displacement;
    202 
    203       result = addr;
    204       return 0;
    205     }
    206     } // switch (operandType)
    207   case Triple::arm:
    208   case Triple::thumb:
    209     switch (operandType) {
    210     default:
    211       return -1;
    212     case kOperandTypeImmediate:
    213       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
    214         return -1;
    215 
    216       result = Inst.Inst->getOperand(MCOpIndex).getImm();
    217       return 0;
    218     case kOperandTypeRegister:
    219     {
    220       if (!Inst.Inst->getOperand(MCOpIndex).isReg())
    221         return -1;
    222 
    223       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
    224       return callback(&result, reg, arg);
    225     }
    226     case kOperandTypeARMBranchTarget:
    227     {
    228       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
    229         return -1;
    230 
    231       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
    232 
    233       uint64_t pcVal;
    234 
    235       if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
    236         return -1;
    237 
    238       result = pcVal + displacement;
    239       return 0;
    240     }
    241     }
    242   }
    243 }
    244 
    245 int EDOperand::isRegister() {
    246   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
    247 }
    248 
    249 unsigned EDOperand::regVal() {
    250   return Inst.Inst->getOperand(MCOpIndex).getReg();
    251 }
    252 
    253 int EDOperand::isImmediate() {
    254   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
    255 }
    256 
    257 uint64_t EDOperand::immediateVal() {
    258   return Inst.Inst->getOperand(MCOpIndex).getImm();
    259 }
    260 
    261 int EDOperand::isMemory() {
    262   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
    263 
    264   switch (operandType) {
    265   default:
    266     return 0;
    267   case kOperandTypeX86Memory:
    268   case kOperandTypeX86PCRelative:
    269   case kOperandTypeX86EffectiveAddress:
    270   case kOperandTypeARMSoReg:
    271   case kOperandTypeARMSoImm:
    272   case kOperandTypeARMAddrMode2:
    273   case kOperandTypeARMAddrMode2Offset:
    274   case kOperandTypeARMAddrMode3:
    275   case kOperandTypeARMAddrMode3Offset:
    276   case kOperandTypeARMAddrMode4:
    277   case kOperandTypeARMAddrMode5:
    278   case kOperandTypeARMAddrMode6:
    279   case kOperandTypeARMAddrMode7:
    280   case kOperandTypeARMAddrModePC:
    281   case kOperandTypeARMBranchTarget:
    282   case kOperandTypeThumbAddrModeRegS1:
    283   case kOperandTypeThumbAddrModeRegS2:
    284   case kOperandTypeThumbAddrModeRegS4:
    285   case kOperandTypeThumbAddrModeRR:
    286   case kOperandTypeThumbAddrModeSP:
    287   case kOperandTypeThumb2SoImm:
    288   case kOperandTypeThumb2AddrModeImm8:
    289   case kOperandTypeThumb2AddrModeImm8Offset:
    290   case kOperandTypeThumb2AddrModeImm12:
    291   case kOperandTypeThumb2AddrModeSoReg:
    292   case kOperandTypeThumb2AddrModeImm8s4:
    293   case kOperandTypeThumb2AddrModeReg:
    294     return 1;
    295   }
    296 }
    297 
    298 #ifdef __BLOCKS__
    299 namespace {
    300   struct RegisterReaderWrapper {
    301     EDOperand::EDRegisterBlock_t regBlock;
    302   };
    303 }
    304 
    305 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
    306   RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
    307   return wrapper->regBlock(value, regID);
    308 }
    309 
    310 int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
    311   RegisterReaderWrapper wrapper;
    312   wrapper.regBlock = regBlock;
    313   return evaluate(result, readerWrapperCallback, (void*)&wrapper);
    314 }
    315 #endif
    316