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   if (Disassembler.Key.Arch == Triple::x86 ||
     34       Disassembler.Key.Arch == Triple::x86_64) {
     35     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
     36 
     37     switch (operandType) {
     38     default:
     39       break;
     40     case kOperandTypeImmediate:
     41       numMCOperands = 1;
     42       break;
     43     case kOperandTypeRegister:
     44       numMCOperands = 1;
     45       break;
     46     case kOperandTypeX86Memory:
     47       numMCOperands = 5;
     48       break;
     49     case kOperandTypeX86EffectiveAddress:
     50       numMCOperands = 4;
     51       break;
     52     case kOperandTypeX86PCRelative:
     53       numMCOperands = 1;
     54       break;
     55     }
     56   }
     57   else if (Disassembler.Key.Arch == Triple::arm ||
     58            Disassembler.Key.Arch == Triple::thumb) {
     59     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
     60 
     61     switch (operandType) {
     62     default:
     63     case kOperandTypeARMRegisterList:
     64     case kOperandTypeARMDPRRegisterList:
     65     case kOperandTypeARMSPRRegisterList:
     66       break;
     67     case kOperandTypeImmediate:
     68     case kOperandTypeRegister:
     69     case kOperandTypeARMBranchTarget:
     70     case kOperandTypeARMSoImm:
     71     case kOperandTypeARMRotImm:
     72     case kOperandTypeThumb2SoImm:
     73     case kOperandTypeARMSoImm2Part:
     74     case kOperandTypeARMPredicate:
     75     case kOperandTypeThumbITMask:
     76     case kOperandTypeThumb2AddrModeImm8Offset:
     77     case kOperandTypeARMTBAddrMode:
     78     case kOperandTypeThumb2AddrModeImm8s4Offset:
     79     case kOperandTypeARMAddrMode7:
     80     case kOperandTypeThumb2AddrModeReg:
     81       numMCOperands = 1;
     82       break;
     83     case kOperandTypeThumb2SoReg:
     84     case kOperandTypeAddrModeImm12:
     85     case kOperandTypeARMAddrMode2Offset:
     86     case kOperandTypeARMAddrMode3Offset:
     87     case kOperandTypeARMAddrMode4:
     88     case kOperandTypeARMAddrMode5:
     89     case kOperandTypeARMAddrModePC:
     90     case kOperandTypeThumb2AddrModeImm8:
     91     case kOperandTypeThumb2AddrModeImm12:
     92     case kOperandTypeThumb2AddrModeImm8s4:
     93     case kOperandTypeThumbAddrModeImmS1:
     94     case kOperandTypeThumbAddrModeImmS2:
     95     case kOperandTypeThumbAddrModeImmS4:
     96     case kOperandTypeThumbAddrModeRR:
     97     case kOperandTypeThumbAddrModeSP:
     98     case kOperandTypeThumbAddrModePC:
     99       numMCOperands = 2;
    100       break;
    101     case kOperandTypeARMSoReg:
    102     case kOperandTypeLdStSOReg:
    103     case kOperandTypeARMAddrMode2:
    104     case kOperandTypeARMAddrMode3:
    105     case kOperandTypeThumb2AddrModeSoReg:
    106     case kOperandTypeThumbAddrModeRegS1:
    107     case kOperandTypeThumbAddrModeRegS2:
    108     case kOperandTypeThumbAddrModeRegS4:
    109     case kOperandTypeARMAddrMode6Offset:
    110       numMCOperands = 3;
    111       break;
    112     case kOperandTypeARMAddrMode6:
    113       numMCOperands = 4;
    114       break;
    115     }
    116   }
    117 
    118   mcOpIndex += numMCOperands;
    119 }
    120 
    121 EDOperand::~EDOperand() {
    122 }
    123 
    124 int EDOperand::evaluate(uint64_t &result,
    125                         EDRegisterReaderCallback callback,
    126                         void *arg) {
    127   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
    128 
    129   switch (Disassembler.Key.Arch) {
    130   default:
    131     return -1;
    132   case Triple::x86:
    133   case Triple::x86_64:
    134     switch (operandType) {
    135     default:
    136       return -1;
    137     case kOperandTypeImmediate:
    138       result = Inst.Inst->getOperand(MCOpIndex).getImm();
    139       return 0;
    140     case kOperandTypeRegister:
    141     {
    142       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
    143       return callback(&result, reg, arg);
    144     }
    145     case kOperandTypeX86PCRelative:
    146     {
    147       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
    148 
    149       uint64_t ripVal;
    150 
    151       // TODO fix how we do this
    152 
    153       if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
    154         return -1;
    155 
    156       result = ripVal + displacement;
    157       return 0;
    158     }
    159     case kOperandTypeX86Memory:
    160     case kOperandTypeX86EffectiveAddress:
    161     {
    162       unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
    163       uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
    164       unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
    165       int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
    166 
    167       uint64_t addr = 0;
    168 
    169       unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
    170 
    171       if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
    172         unsigned fsID = Disassembler.registerIDWithName("FS");
    173         unsigned gsID = Disassembler.registerIDWithName("GS");
    174 
    175         if (segmentReg == fsID ||
    176             segmentReg == gsID) {
    177           uint64_t segmentBase;
    178           if (!callback(&segmentBase, segmentReg, arg))
    179             addr += segmentBase;
    180         }
    181       }
    182 
    183       if (baseReg) {
    184         uint64_t baseVal;
    185         if (callback(&baseVal, baseReg, arg))
    186           return -1;
    187         addr += baseVal;
    188       }
    189 
    190       if (indexReg) {
    191         uint64_t indexVal;
    192         if (callback(&indexVal, indexReg, arg))
    193           return -1;
    194         addr += (scaleAmount * indexVal);
    195       }
    196 
    197       addr += displacement;
    198 
    199       result = addr;
    200       return 0;
    201     }
    202     } // switch (operandType)
    203     break;
    204   case Triple::arm:
    205   case Triple::thumb:
    206     switch (operandType) {
    207     default:
    208       return -1;
    209     case kOperandTypeImmediate:
    210       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
    211         return -1;
    212 
    213       result = Inst.Inst->getOperand(MCOpIndex).getImm();
    214       return 0;
    215     case kOperandTypeRegister:
    216     {
    217       if (!Inst.Inst->getOperand(MCOpIndex).isReg())
    218         return -1;
    219 
    220       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
    221       return callback(&result, reg, arg);
    222     }
    223     case kOperandTypeARMBranchTarget:
    224     {
    225       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
    226         return -1;
    227 
    228       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
    229 
    230       uint64_t pcVal;
    231 
    232       if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
    233         return -1;
    234 
    235       result = pcVal + displacement;
    236       return 0;
    237     }
    238     }
    239     break;
    240   }
    241 
    242   return -1;
    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