mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-16 11:24:39 +00:00
Added support for ARM disassembly to edis.
I also added a rule to the ARM target's Makefile to build the ARM-specific instruction information table for the enhanced disassembler. I will add the test harness for all this stuff in a separate commit. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100735 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -31,26 +31,77 @@ EDOperand::EDOperand(const EDDisassembler &disassembler,
|
||||
MCOpIndex(mcOpIndex) {
|
||||
unsigned int numMCOperands = 0;
|
||||
|
||||
if(Disassembler.Key.Arch == Triple::x86 ||
|
||||
Disassembler.Key.Arch == Triple::x86_64) {
|
||||
uint8_t operandFlags = inst.ThisInstInfo->operandFlags[opIndex];
|
||||
if (Disassembler.Key.Arch == Triple::x86 ||
|
||||
Disassembler.Key.Arch == Triple::x86_64) {
|
||||
uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
|
||||
|
||||
if (operandFlags & kOperandFlagImmediate) {
|
||||
switch (operandType) {
|
||||
default:
|
||||
break;
|
||||
case kOperandTypeImmediate:
|
||||
numMCOperands = 1;
|
||||
}
|
||||
else if (operandFlags & kOperandFlagRegister) {
|
||||
break;
|
||||
case kOperandTypeRegister:
|
||||
numMCOperands = 1;
|
||||
}
|
||||
else if (operandFlags & kOperandFlagMemory) {
|
||||
if (operandFlags & kOperandFlagPCRelative) {
|
||||
numMCOperands = 1;
|
||||
}
|
||||
else {
|
||||
numMCOperands = 5;
|
||||
}
|
||||
}
|
||||
else if (operandFlags & kOperandFlagEffectiveAddress) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,70 +114,103 @@ EDOperand::~EDOperand() {
|
||||
int EDOperand::evaluate(uint64_t &result,
|
||||
EDRegisterReaderCallback callback,
|
||||
void *arg) {
|
||||
if (Disassembler.Key.Arch == Triple::x86 ||
|
||||
Disassembler.Key.Arch == Triple::x86_64) {
|
||||
uint8_t operandFlags = Inst.ThisInstInfo->operandFlags[OpIndex];
|
||||
|
||||
if (operandFlags & kOperandFlagImmediate) {
|
||||
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;
|
||||
}
|
||||
if (operandFlags & kOperandFlagRegister) {
|
||||
case kOperandTypeRegister:
|
||||
{
|
||||
unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
|
||||
return callback(&result, reg, arg);
|
||||
}
|
||||
if (operandFlags & kOperandFlagMemory ||
|
||||
operandFlags & kOperandFlagEffectiveAddress){
|
||||
if(operandFlags & kOperandFlagPCRelative) {
|
||||
int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
|
||||
case kOperandTypeX86PCRelative:
|
||||
{
|
||||
int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
|
||||
|
||||
uint64_t ripVal;
|
||||
uint64_t ripVal;
|
||||
|
||||
// TODO fix how we do this
|
||||
// TODO fix how we do this
|
||||
|
||||
if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
|
||||
return -1;
|
||||
if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
|
||||
return -1;
|
||||
|
||||
result = ripVal + displacement;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int EDOperand::isRegister() {
|
||||
return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagRegister);
|
||||
return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
|
||||
}
|
||||
|
||||
unsigned EDOperand::regVal() {
|
||||
@@ -134,7 +218,7 @@ unsigned EDOperand::regVal() {
|
||||
}
|
||||
|
||||
int EDOperand::isImmediate() {
|
||||
return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagImmediate);
|
||||
return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
|
||||
}
|
||||
|
||||
uint64_t EDOperand::immediateVal() {
|
||||
@@ -142,7 +226,33 @@ uint64_t EDOperand::immediateVal() {
|
||||
}
|
||||
|
||||
int EDOperand::isMemory() {
|
||||
return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagMemory);
|
||||
switch (Inst.ThisInstInfo->operandFlags[OpIndex]) {
|
||||
default:
|
||||
return 0;
|
||||
case kOperandTypeX86Memory:
|
||||
case kOperandTypeARMSoReg:
|
||||
case kOperandTypeARMSoImm:
|
||||
case kOperandTypeARMAddrMode2:
|
||||
case kOperandTypeARMAddrMode2Offset:
|
||||
case kOperandTypeARMAddrMode3:
|
||||
case kOperandTypeARMAddrMode3Offset:
|
||||
case kOperandTypeARMAddrMode4:
|
||||
case kOperandTypeARMAddrMode5:
|
||||
case kOperandTypeARMAddrMode6:
|
||||
case kOperandTypeARMAddrModePC:
|
||||
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__
|
||||
|
Reference in New Issue
Block a user