mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 00:16:48 +00:00 
			
		
		
		
	MCInst operands for ARM. This allows it to be more tolerant of malformed MCInsts or incorrect instruction metadata. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129840 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			307 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			307 lines
		
	
	
		
			8.5 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:
 | |
|     case kOperandTypeARMAddrMode7:
 | |
|     case kOperandTypeThumb2AddrModeReg:
 | |
|       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();
 | |
|     
 | |
|       uint64_t addr = 0;
 | |
|         
 | |
|       unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
 | |
|         
 | |
|       if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
 | |
|         unsigned fsID = Disassembler.registerIDWithName("FS");
 | |
|         unsigned gsID = Disassembler.registerIDWithName("GS");
 | |
|         
 | |
|         if (segmentReg == fsID ||
 | |
|             segmentReg == gsID) {
 | |
|           uint64_t segmentBase;
 | |
|           if (!callback(&segmentBase, segmentReg, arg))
 | |
|             addr += segmentBase;        
 | |
|         }
 | |
|       }
 | |
|         
 | |
|       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;
 | |
|     }
 | |
|     } // switch (operandType)
 | |
|     break;
 | |
|   case Triple::arm:
 | |
|   case Triple::thumb:
 | |
|     switch (operandType) {
 | |
|     default:
 | |
|       return -1;
 | |
|     case kOperandTypeImmediate:
 | |
|       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
 | |
|         return -1;
 | |
|             
 | |
|       result = Inst.Inst->getOperand(MCOpIndex).getImm();
 | |
|       return 0;
 | |
|     case kOperandTypeRegister:
 | |
|     {
 | |
|       if (!Inst.Inst->getOperand(MCOpIndex).isReg())
 | |
|         return -1;
 | |
|         
 | |
|       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
 | |
|       return callback(&result, reg, arg);
 | |
|     }
 | |
|     case kOperandTypeARMBranchTarget:
 | |
|     {
 | |
|       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
 | |
|         return -1;
 | |
|         
 | |
|       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;
 | |
|     }
 | |
|     }
 | |
|     break;
 | |
|   }
 | |
|   
 | |
|   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 kOperandTypeARMAddrMode7:
 | |
|   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:
 | |
|   case kOperandTypeThumb2AddrModeReg:
 | |
|     return 1;
 | |
|   }
 | |
| }
 | |
| 
 | |
| #ifdef __BLOCKS__
 | |
| namespace {
 | |
|   struct RegisterReaderWrapper {
 | |
|     EDOperand::EDRegisterBlock_t regBlock;
 | |
|   };
 | |
| }
 | |
| 
 | |
| static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
 | |
|   RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
 | |
|   return wrapper->regBlock(value, regID);
 | |
| }
 | |
| 
 | |
| int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
 | |
|   RegisterReaderWrapper wrapper;
 | |
|   wrapper.regBlock = regBlock;
 | |
|   return evaluate(result, readerWrapperCallback, (void*)&wrapper);
 | |
| }
 | |
| #endif
 |