mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	better in the llvm world. Among other things, this changes: 1. The guts of libedis are now moved into lib/MC/MCDisassembler 2. llvm-mc now depends on lib/MC/MCDisassembler, not tools/edis, so edis and mc don't have to be built in series. 3. lib/MC/MCDisassembler no longer depends on the C api, the C API depends on it. 4. Various code cleanup changes. There is still a lot to be done to make edis fit with the llvm design, but this is an incremental step in the right direction. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108869 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			283 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===-- EDOperand.cpp - LLVM Enhanced Disassembler ------------------------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
// 
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file implements the Enhanced Disassembly library's operand class.  The
 | 
						|
// operand is responsible for allowing evaluation given a particular register 
 | 
						|
// context.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "EDOperand.h"
 | 
						|
#include "EDDisassembler.h"
 | 
						|
#include "EDInst.h"
 | 
						|
#include "llvm/MC/EDInstInfo.h"
 | 
						|
#include "llvm/MC/MCInst.h"
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
EDOperand::EDOperand(const EDDisassembler &disassembler,
 | 
						|
                     const EDInst &inst,
 | 
						|
                     unsigned int opIndex,
 | 
						|
                     unsigned int &mcOpIndex) :
 | 
						|
  Disassembler(disassembler),
 | 
						|
  Inst(inst),
 | 
						|
  OpIndex(opIndex),
 | 
						|
  MCOpIndex(mcOpIndex) {
 | 
						|
  unsigned int numMCOperands = 0;
 | 
						|
    
 | 
						|
  if (Disassembler.Key.Arch == Triple::x86 ||
 | 
						|
      Disassembler.Key.Arch == Triple::x86_64) {
 | 
						|
    uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
 | 
						|
    
 | 
						|
    switch (operandType) {
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    case kOperandTypeImmediate:
 | 
						|
      numMCOperands = 1;
 | 
						|
      break;
 | 
						|
    case kOperandTypeRegister:
 | 
						|
      numMCOperands = 1;
 | 
						|
      break;
 | 
						|
    case kOperandTypeX86Memory:
 | 
						|
      numMCOperands = 5;
 | 
						|
      break;
 | 
						|
    case kOperandTypeX86EffectiveAddress:
 | 
						|
      numMCOperands = 4;
 | 
						|
      break;
 | 
						|
    case kOperandTypeX86PCRelative:
 | 
						|
      numMCOperands = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else if (Disassembler.Key.Arch == Triple::arm ||
 | 
						|
           Disassembler.Key.Arch == Triple::thumb) {
 | 
						|
    uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
 | 
						|
    
 | 
						|
    switch (operandType) {
 | 
						|
    default:
 | 
						|
    case kOperandTypeARMRegisterList:
 | 
						|
      break;
 | 
						|
    case kOperandTypeImmediate:
 | 
						|
    case kOperandTypeRegister:
 | 
						|
    case kOperandTypeARMBranchTarget:
 | 
						|
    case kOperandTypeARMSoImm:
 | 
						|
    case kOperandTypeThumb2SoImm:
 | 
						|
    case kOperandTypeARMSoImm2Part:
 | 
						|
    case kOperandTypeARMPredicate:
 | 
						|
    case kOperandTypeThumbITMask:
 | 
						|
    case kOperandTypeThumb2AddrModeImm8Offset:
 | 
						|
    case kOperandTypeARMTBAddrMode:
 | 
						|
    case kOperandTypeThumb2AddrModeImm8s4Offset:
 | 
						|
      numMCOperands = 1;
 | 
						|
      break;
 | 
						|
    case kOperandTypeThumb2SoReg:
 | 
						|
    case kOperandTypeARMAddrMode2Offset:
 | 
						|
    case kOperandTypeARMAddrMode3Offset:
 | 
						|
    case kOperandTypeARMAddrMode4:
 | 
						|
    case kOperandTypeARMAddrMode5:
 | 
						|
    case kOperandTypeARMAddrModePC:
 | 
						|
    case kOperandTypeThumb2AddrModeImm8:
 | 
						|
    case kOperandTypeThumb2AddrModeImm12:
 | 
						|
    case kOperandTypeThumb2AddrModeImm8s4:
 | 
						|
    case kOperandTypeThumbAddrModeRR:
 | 
						|
    case kOperandTypeThumbAddrModeSP:
 | 
						|
      numMCOperands = 2;
 | 
						|
      break;
 | 
						|
    case kOperandTypeARMSoReg:
 | 
						|
    case kOperandTypeARMAddrMode2:
 | 
						|
    case kOperandTypeARMAddrMode3:
 | 
						|
    case kOperandTypeThumb2AddrModeSoReg:
 | 
						|
    case kOperandTypeThumbAddrModeS1:
 | 
						|
    case kOperandTypeThumbAddrModeS2:
 | 
						|
    case kOperandTypeThumbAddrModeS4:
 | 
						|
    case kOperandTypeARMAddrMode6Offset:
 | 
						|
      numMCOperands = 3;
 | 
						|
      break;
 | 
						|
    case kOperandTypeARMAddrMode6:
 | 
						|
      numMCOperands = 4;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
    
 | 
						|
  mcOpIndex += numMCOperands;
 | 
						|
}
 | 
						|
 | 
						|
EDOperand::~EDOperand() {
 | 
						|
}
 | 
						|
 | 
						|
int EDOperand::evaluate(uint64_t &result,
 | 
						|
                        EDRegisterReaderCallback callback,
 | 
						|
                        void *arg) {
 | 
						|
  uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
 | 
						|
  
 | 
						|
  switch (Disassembler.Key.Arch) {
 | 
						|
  default:
 | 
						|
    return -1;  
 | 
						|
  case Triple::x86:
 | 
						|
  case Triple::x86_64:    
 | 
						|
    switch (operandType) {
 | 
						|
    default:
 | 
						|
      return -1;
 | 
						|
    case kOperandTypeImmediate:
 | 
						|
      result = Inst.Inst->getOperand(MCOpIndex).getImm();
 | 
						|
      return 0;
 | 
						|
    case kOperandTypeRegister:
 | 
						|
    {
 | 
						|
      unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
 | 
						|
      return callback(&result, reg, arg);
 | 
						|
    }
 | 
						|
    case kOperandTypeX86PCRelative:
 | 
						|
    {
 | 
						|
      int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
 | 
						|
        
 | 
						|
      uint64_t ripVal;
 | 
						|
        
 | 
						|
      // TODO fix how we do this
 | 
						|
        
 | 
						|
      if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
 | 
						|
        return -1;
 | 
						|
        
 | 
						|
      result = ripVal + displacement;
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    case kOperandTypeX86Memory:
 | 
						|
    case kOperandTypeX86EffectiveAddress:  
 | 
						|
    {
 | 
						|
      unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
 | 
						|
      uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
 | 
						|
      unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
 | 
						|
      int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
 | 
						|
      //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
 | 
						|
      
 | 
						|
      uint64_t addr = 0;
 | 
						|
        
 | 
						|
      if (baseReg) {
 | 
						|
        uint64_t baseVal;
 | 
						|
        if (callback(&baseVal, baseReg, arg))
 | 
						|
          return -1;
 | 
						|
        addr += baseVal;
 | 
						|
      }
 | 
						|
        
 | 
						|
      if (indexReg) {
 | 
						|
        uint64_t indexVal;
 | 
						|
        if (callback(&indexVal, indexReg, arg))
 | 
						|
          return -1;
 | 
						|
        addr += (scaleAmount * indexVal);
 | 
						|
      }
 | 
						|
       
 | 
						|
      addr += displacement;
 | 
						|
       
 | 
						|
      result = addr;
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case Triple::arm:
 | 
						|
  case Triple::thumb:
 | 
						|
    switch (operandType) {
 | 
						|
    default:
 | 
						|
      return -1;
 | 
						|
    case kOperandTypeImmediate:
 | 
						|
      result = Inst.Inst->getOperand(MCOpIndex).getImm();
 | 
						|
      return 0;
 | 
						|
    case kOperandTypeRegister:
 | 
						|
    {
 | 
						|
      unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
 | 
						|
      return callback(&result, reg, arg);
 | 
						|
    }
 | 
						|
    case kOperandTypeARMBranchTarget:
 | 
						|
    {
 | 
						|
      int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
 | 
						|
      
 | 
						|
      uint64_t pcVal;
 | 
						|
      
 | 
						|
      if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
 | 
						|
        return -1;
 | 
						|
      
 | 
						|
      result = pcVal + displacement;
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
int EDOperand::isRegister() {
 | 
						|
  return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
 | 
						|
}
 | 
						|
 | 
						|
unsigned EDOperand::regVal() {
 | 
						|
  return Inst.Inst->getOperand(MCOpIndex).getReg(); 
 | 
						|
}
 | 
						|
 | 
						|
int EDOperand::isImmediate() {
 | 
						|
  return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
 | 
						|
}
 | 
						|
 | 
						|
uint64_t EDOperand::immediateVal() {
 | 
						|
  return Inst.Inst->getOperand(MCOpIndex).getImm();
 | 
						|
}
 | 
						|
 | 
						|
int EDOperand::isMemory() {
 | 
						|
  uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
 | 
						|
    
 | 
						|
  switch (operandType) {
 | 
						|
  default:
 | 
						|
    return 0;
 | 
						|
  case kOperandTypeX86Memory:
 | 
						|
  case kOperandTypeX86PCRelative:
 | 
						|
  case kOperandTypeX86EffectiveAddress:
 | 
						|
  case kOperandTypeARMSoReg:
 | 
						|
  case kOperandTypeARMSoImm:
 | 
						|
  case kOperandTypeARMAddrMode2:
 | 
						|
  case kOperandTypeARMAddrMode2Offset:
 | 
						|
  case kOperandTypeARMAddrMode3:
 | 
						|
  case kOperandTypeARMAddrMode3Offset:
 | 
						|
  case kOperandTypeARMAddrMode4:
 | 
						|
  case kOperandTypeARMAddrMode5:
 | 
						|
  case kOperandTypeARMAddrMode6:
 | 
						|
  case kOperandTypeARMAddrModePC:
 | 
						|
  case kOperandTypeARMBranchTarget:
 | 
						|
  case kOperandTypeThumbAddrModeS1:
 | 
						|
  case kOperandTypeThumbAddrModeS2:
 | 
						|
  case kOperandTypeThumbAddrModeS4:
 | 
						|
  case kOperandTypeThumbAddrModeRR:
 | 
						|
  case kOperandTypeThumbAddrModeSP:
 | 
						|
  case kOperandTypeThumb2SoImm:
 | 
						|
  case kOperandTypeThumb2AddrModeImm8:
 | 
						|
  case kOperandTypeThumb2AddrModeImm8Offset:
 | 
						|
  case kOperandTypeThumb2AddrModeImm12:
 | 
						|
  case kOperandTypeThumb2AddrModeSoReg:
 | 
						|
  case kOperandTypeThumb2AddrModeImm8s4:
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
#ifdef __BLOCKS__
 | 
						|
struct RegisterReaderWrapper {
 | 
						|
  EDOperand::EDRegisterBlock_t regBlock;
 | 
						|
};
 | 
						|
 | 
						|
int readerWrapperCallback(uint64_t *value, 
 | 
						|
                          unsigned regID, 
 | 
						|
                          void *arg) {
 | 
						|
  struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
 | 
						|
  return wrapper->regBlock(value, regID);
 | 
						|
}
 | 
						|
 | 
						|
int EDOperand::evaluate(uint64_t &result,
 | 
						|
                        EDRegisterBlock_t regBlock) {
 | 
						|
  struct RegisterReaderWrapper wrapper;
 | 
						|
  wrapper.regBlock = regBlock;
 | 
						|
  return evaluate(result, 
 | 
						|
                  readerWrapperCallback, 
 | 
						|
                  (void*)&wrapper);
 | 
						|
}
 | 
						|
#endif
 |