diff --git a/include/llvm-c/EnhancedDisassembly.h b/include/llvm-c/EnhancedDisassembly.h index 9cd1e1f5f3c..5ed6043f662 100644 --- a/include/llvm-c/EnhancedDisassembly.h +++ b/include/llvm-c/EnhancedDisassembly.h @@ -19,7 +19,7 @@ #ifndef LLVM_C_ENHANCEDDISASSEMBLY_H #define LLVM_C_ENHANCEDDISASSEMBLY_H -#include "llvm/System/DataTypes.h" +#include #ifdef __cplusplus extern "C" { @@ -55,7 +55,8 @@ typedef enum { /*! @constant kEDAssemblySyntaxX86Intel Intel syntax for i386 and x86_64. */ kEDAssemblySyntaxX86Intel = 0, /*! @constant kEDAssemblySyntaxX86ATT AT&T syntax for i386 and x86_64. */ - kEDAssemblySyntaxX86ATT = 1 + kEDAssemblySyntaxX86ATT = 1, + kEDAssemblySyntaxARMUAL = 2 } EDAssemblySyntax_t; /*! diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile index 47922436f53..9e3ff29e07c 100644 --- a/lib/Target/ARM/Makefile +++ b/lib/Target/ARM/Makefile @@ -17,7 +17,7 @@ BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \ ARMGenInstrInfo.inc ARMGenAsmWriter.inc \ ARMGenDAGISel.inc ARMGenSubtarget.inc \ ARMGenCodeEmitter.inc ARMGenCallingConv.inc \ - ARMGenDecoderTables.inc + ARMGenDecoderTables.inc ARMGenEDInfo.inc DIRS = AsmPrinter AsmParser Disassembler TargetInfo diff --git a/tools/edis/EDDisassembler.cpp b/tools/edis/EDDisassembler.cpp index 8729b4998fd..072df822bf3 100644 --- a/tools/edis/EDDisassembler.cpp +++ b/tools/edis/EDDisassembler.cpp @@ -13,6 +13,9 @@ // //===----------------------------------------------------------------------===// +#include "EDDisassembler.h" +#include "EDInst.h" + #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCAsmInfo.h" @@ -36,10 +39,8 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSelect.h" -#include "EDDisassembler.h" -#include "EDInst.h" - #include "../../lib/Target/X86/X86GenEDInfo.inc" +#include "../../lib/Target/ARM/ARMGenEDInfo.inc" using namespace llvm; @@ -55,6 +56,8 @@ struct InfoMap { static struct InfoMap infomap[] = { { Triple::x86, "i386-unknown-unknown", instInfoX86 }, { Triple::x86_64, "x86_64-unknown-unknown", instInfoX86 }, + { Triple::arm, "arm-unknown-unknown", instInfoARM }, + { Triple::thumb, "thumb-unknown-unknown", instInfoARM }, { Triple::InvalidArch, NULL, NULL } }; @@ -66,7 +69,7 @@ static const InfoMap *infoFromArch(Triple::ArchType arch) { unsigned int infoIndex; for (infoIndex = 0; infomap[infoIndex].String != NULL; ++infoIndex) { - if(arch == infomap[infoIndex].Arch) + if (arch == infomap[infoIndex].Arch) return &infomap[infoIndex]; } @@ -95,6 +98,11 @@ static int getLLVMSyntaxVariant(Triple::ArchType arch, return 1; else return -1; + case kEDAssemblySyntaxARMUAL: + if (arch == Triple::arm || arch == Triple::thumb) + return 0; + else + return -1; } } @@ -112,6 +120,7 @@ void EDDisassembler::initialize() { sInitialized = true; BRINGUP_TARGET(X86) + BRINGUP_TARGET(ARM) } #undef BRINGUP_TARGET @@ -126,10 +135,9 @@ EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch, if (i != sDisassemblers.end()) { return i->second; - } - else { + } else { EDDisassembler* sdd = new EDDisassembler(key); - if(!sdd->valid()) { + if (!sdd->valid()) { delete sdd; return NULL; } @@ -150,11 +158,16 @@ EDDisassembler *EDDisassembler::getDisassembler(StringRef str, } EDDisassembler::EDDisassembler(CPUKey &key) : - Valid(false), ErrorString(), ErrorStream(ErrorString), Key(key) { + Valid(false), + HasSemantics(false), + ErrorStream(nulls()), + Key(key) { const InfoMap *infoMap = infoFromArch(key.Arch); if (!infoMap) return; + + InstInfos = infoMap->Info; const char *triple = infoMap->String; @@ -182,6 +195,8 @@ EDDisassembler::EDDisassembler(CPUKey &key) : if (!registerInfo) return; + + initMaps(*registerInfo); AsmInfo.reset(Tgt->createAsmInfo(tripleString)); @@ -212,7 +227,7 @@ EDDisassembler::EDDisassembler(CPUKey &key) : } EDDisassembler::~EDDisassembler() { - if(!valid()) + if (!valid()) return; } @@ -230,10 +245,10 @@ namespace { uint64_t getBase() const { return 0x0; } uint64_t getExtent() const { return (uint64_t)-1; } int readByte(uint64_t address, uint8_t *ptr) const { - if(!Callback) + if (!Callback) return -1; - if(Callback(ptr, address, Arg)) + if (Callback(ptr, address, Arg)) return -1; return 0; @@ -256,9 +271,10 @@ EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader, ErrorStream)) { delete inst; return NULL; - } - else { - const InstInfo *thisInstInfo = &InstInfos[inst->getOpcode()]; + } else { + const InstInfo *thisInstInfo; + + thisInstInfo = &InstInfos[inst->getOpcode()]; EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo); return sdInst; @@ -276,8 +292,11 @@ void EDDisassembler::initMaps(const TargetRegisterInfo ®isterInfo) { RegRMap[registerName] = registerIndex; } - if (Key.Arch == Triple::x86 || - Key.Arch == Triple::x86_64) { + switch (Key.Arch) { + default: + break; + case Triple::x86: + case Triple::x86_64: stackPointers.insert(registerIDWithName("SP")); stackPointers.insert(registerIDWithName("ESP")); stackPointers.insert(registerIDWithName("RSP")); @@ -285,6 +304,13 @@ void EDDisassembler::initMaps(const TargetRegisterInfo ®isterInfo) { programCounters.insert(registerIDWithName("IP")); programCounters.insert(registerIDWithName("EIP")); programCounters.insert(registerIDWithName("RIP")); + break; + case Triple::arm: + case Triple::thumb: + stackPointers.insert(registerIDWithName("SP")); + + programCounters.insert(registerIDWithName("PC")); + break; } } @@ -329,6 +355,16 @@ int EDDisassembler::parseInst(SmallVectorImpl &operands, const std::string &str) { int ret = 0; + switch (Key.Arch) { + default: + return -1; + case Triple::x86: + case Triple::x86_64: + case Triple::arm: + case Triple::thumb: + break; + } + const char *cStr = str.c_str(); MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr)); @@ -343,14 +379,14 @@ int EDDisassembler::parseInst(SmallVectorImpl &operands, OwningPtr TargetParser(Tgt->createAsmParser(genericParser)); AsmToken OpcodeToken = genericParser.Lex(); + genericParser.Lex(); // consume next token, because specificParser expects us to - if(OpcodeToken.is(AsmToken::Identifier)) { + if (OpcodeToken.is(AsmToken::Identifier)) { instName = OpcodeToken.getString(); instLoc = OpcodeToken.getLoc(); if (TargetParser->ParseInstruction(instName, instLoc, operands)) ret = -1; - } - else { + } else { ret = -1; } diff --git a/tools/edis/EDDisassembler.h b/tools/edis/EDDisassembler.h index 6be9152facb..9b27fe81703 100644 --- a/tools/edis/EDDisassembler.h +++ b/tools/edis/EDDisassembler.h @@ -113,13 +113,13 @@ struct EDDisassembler { // Per-object members // //////////////////////// - /// True only if the object has been fully and successfully initialized + /// True only if the object has been successfully initialized bool Valid; + /// True if the disassembler can provide semantic information + bool HasSemantics; - /// The string that stores disassembler errors from the backend - std::string ErrorString; - /// The stream that wraps the ErrorString - llvm::raw_string_ostream ErrorStream; + /// The stream to write errors to + llvm::raw_ostream &ErrorStream; /// The architecture/syntax pair for the current architecture CPUKey Key; @@ -180,6 +180,12 @@ struct EDDisassembler { return Valid; } + /// hasSemantics - reports whether the disassembler can provide operands and + /// tokens. + bool hasSemantics() { + return HasSemantics; + } + ~EDDisassembler(); /// createInst - creates and returns an instruction given a callback and diff --git a/tools/edis/EDInst.cpp b/tools/edis/EDInst.cpp index 9ed27002ad5..1b6a3607ba8 100644 --- a/tools/edis/EDInst.cpp +++ b/tools/edis/EDInst.cpp @@ -81,21 +81,21 @@ unsigned EDInst::instID() { bool EDInst::isBranch() { if (ThisInstInfo) - return ThisInstInfo->instructionFlags & kInstructionFlagBranch; + return ThisInstInfo->instructionType == kInstructionTypeBranch; else return false; } bool EDInst::isMove() { if (ThisInstInfo) - return ThisInstInfo->instructionFlags & kInstructionFlagMove; + return ThisInstInfo->instructionType == kInstructionTypeMove; else return false; } int EDInst::parseOperands() { if (ParseResult.valid()) - return ParseResult.result(); + return ParseResult.result(); if (!ThisInstInfo) return ParseResult.setResult(-1); diff --git a/tools/edis/EDMain.cpp b/tools/edis/EDMain.cpp index 3585657ca62..b6ca32f2db8 100644 --- a/tools/edis/EDMain.cpp +++ b/tools/edis/EDMain.cpp @@ -29,8 +29,7 @@ int EDGetDisassembler(EDDisassemblerRef *disassembler, if (ret) { *disassembler = ret; return 0; - } - else { + } else { return -1; } } @@ -39,7 +38,7 @@ int EDGetRegisterName(const char** regName, EDDisassemblerRef disassembler, unsigned regID) { const char* name = disassembler->nameWithRegisterID(regID); - if(!name) + if (!name) return -1; *regName = name; return 0; @@ -63,10 +62,10 @@ unsigned int EDCreateInsts(EDInstRef *insts, void *arg) { unsigned int index; - for (index = 0; index < count; index++) { + for (index = 0; index < count; ++index) { EDInst *inst = disassembler->createInst(byteReader, address, arg); - if(!inst) + if (!inst) return index; insts[index] = inst; @@ -134,42 +133,42 @@ int EDOperandIndexForToken(EDTokenRef token) { } int EDTokenIsWhitespace(EDTokenRef token) { - if(token->type() == EDToken::kTokenWhitespace) + if (token->type() == EDToken::kTokenWhitespace) return 1; else return 0; } int EDTokenIsPunctuation(EDTokenRef token) { - if(token->type() == EDToken::kTokenPunctuation) + if (token->type() == EDToken::kTokenPunctuation) return 1; else return 0; } int EDTokenIsOpcode(EDTokenRef token) { - if(token->type() == EDToken::kTokenOpcode) + if (token->type() == EDToken::kTokenOpcode) return 1; else return 0; } int EDTokenIsLiteral(EDTokenRef token) { - if(token->type() == EDToken::kTokenLiteral) + if (token->type() == EDToken::kTokenLiteral) return 1; else return 0; } int EDTokenIsRegister(EDTokenRef token) { - if(token->type() == EDToken::kTokenRegister) + if (token->type() == EDToken::kTokenRegister) return 1; else return 0; } int EDTokenIsNegativeLiteral(EDTokenRef token) { - if(token->type() != EDToken::kTokenLiteral) + if (token->type() != EDToken::kTokenLiteral) return -1; return token->literalSign(); @@ -177,7 +176,7 @@ int EDTokenIsNegativeLiteral(EDTokenRef token) { int EDLiteralTokenAbsoluteValue(uint64_t *value, EDTokenRef token) { - if(token->type() != EDToken::kTokenLiteral) + if (token->type() != EDToken::kTokenLiteral) return -1; return token->literalAbsoluteValue(*value); @@ -185,7 +184,7 @@ int EDLiteralTokenAbsoluteValue(uint64_t *value, int EDRegisterTokenValue(unsigned *registerID, EDTokenRef token) { - if(token->type() != EDToken::kTokenRegister) + if (token->type() != EDToken::kTokenRegister) return -1; return token->registerID(*registerID); @@ -215,7 +214,7 @@ int EDOperandIsMemory(EDOperandRef operand) { int EDRegisterOperandValue(unsigned *value, EDOperandRef operand) { - if(!operand->isRegister()) + if (!operand->isRegister()) return -1; *value = operand->regVal(); return 0; @@ -223,7 +222,7 @@ int EDRegisterOperandValue(unsigned *value, int EDImmediateOperandValue(uint64_t *value, EDOperandRef operand) { - if(!operand->isImmediate()) + if (!operand->isImmediate()) return -1; *value = operand->immediateVal(); return 0; diff --git a/tools/edis/EDOperand.cpp b/tools/edis/EDOperand.cpp index da6797e035d..93efd470944 100644 --- a/tools/edis/EDOperand.cpp +++ b/tools/edis/EDOperand.cpp @@ -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__ diff --git a/tools/edis/EDToken.cpp b/tools/edis/EDToken.cpp index cd79152e359..3bcb0a14b8c 100644 --- a/tools/edis/EDToken.cpp +++ b/tools/edis/EDToken.cpp @@ -68,20 +68,20 @@ int EDToken::operandID() const { } int EDToken::literalSign() const { - if(Type != kTokenLiteral) + if (Type != kTokenLiteral) return -1; return (LiteralSign ? 1 : 0); } int EDToken::literalAbsoluteValue(uint64_t &value) const { - if(Type != kTokenLiteral) + if (Type != kTokenLiteral) return -1; value = LiteralAbsoluteValue; return 0; } int EDToken::registerID(unsigned ®isterID) const { - if(Type != kTokenRegister) + if (Type != kTokenRegister) return -1; registerID = RegisterID; return 0; @@ -94,7 +94,7 @@ int EDToken::tokenize(std::vector &tokens, SmallVector parsedOperands; SmallVector asmTokens; - if(disassembler.parseInst(parsedOperands, asmTokens, str)) + if (disassembler.parseInst(parsedOperands, asmTokens, str)) return -1; SmallVectorImpl::iterator operandIterator; @@ -115,7 +115,7 @@ int EDToken::tokenize(std::vector &tokens, const char *tokenPointer = tokenLoc.getPointer(); - if(tokenPointer > wsPointer) { + if (tokenPointer > wsPointer) { unsigned long wsLength = tokenPointer - wsPointer; EDToken *whitespaceToken = new EDToken(StringRef(wsPointer, wsLength), @@ -164,7 +164,7 @@ int EDToken::tokenize(std::vector &tokens, int64_t intVal = tokenIterator->getIntVal(); - if(intVal < 0) + if (intVal < 0) token->makeLiteral(true, -intVal); else token->makeLiteral(false, intVal); @@ -182,14 +182,14 @@ int EDToken::tokenize(std::vector &tokens, } } - if(operandIterator != parsedOperands.end() && + if (operandIterator != parsedOperands.end() && tokenLoc.getPointer() >= (*operandIterator)->getStartLoc().getPointer()) { /// operandIndex == 0 means the operand is the instruction (which the /// AsmParser treats as an operand but edis does not). We therefore skip /// operandIndex == 0 and subtract 1 from all other operand indices. - if(operandIndex > 0) + if (operandIndex > 0) token->setOperandID(operandOrder[operandIndex - 1]); } @@ -200,7 +200,7 @@ int EDToken::tokenize(std::vector &tokens, } int EDToken::getString(const char*& buf) { - if(PermStr.length() == 0) { + if (PermStr.length() == 0) { PermStr = Str.str(); } buf = PermStr.c_str(); diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index f83ab486825..c10d6802961 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -23,10 +23,11 @@ #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include +#include #include +#include -#define MAX_OPERANDS 5 +#define MAX_OPERANDS 13 #define MAX_SYNTAXES 2 using namespace llvm; @@ -54,9 +55,9 @@ namespace { unsigned int index = 0; unsigned int numEntries = Entries.size(); - for(index = 0; index < numEntries; ++index) { + for (index = 0; index < numEntries; ++index) { o.indent(i) << Entries[index]; - if(index < (numEntries - 1)) + if (index < (numEntries - 1)) o << ","; o << "\n"; } @@ -88,24 +89,24 @@ namespace { class StructEmitter { private: std::string Name; - std::vector MemberTypes; - std::vector MemberNames; + typedef std::pair member; + std::vector< member > Members; public: StructEmitter(const char *N) : Name(N) { } void addMember(const char *t, const char *n) { - MemberTypes.push_back(std::string(t)); - MemberNames.push_back(std::string(n)); + member m(t, n); + Members.push_back(m); } void emit(raw_ostream &o, unsigned int &i) { o.indent(i) << "struct " << Name.c_str() << " {" << "\n"; i += 2; unsigned int index = 0; - unsigned int numMembers = MemberTypes.size(); + unsigned int numMembers = Members.size(); for (index = 0; index < numMembers; ++index) { - o.indent(i) << MemberTypes[index] << " " << MemberNames[index] << ";"; - o << "\n"; + o.indent(i) << Members[index].first << " "; + o.indent(i) << Members[index].second << ";" << "\n"; } i -= 2; @@ -121,47 +122,87 @@ namespace { class LiteralConstantEmitter : public ConstantEmitter { private: - std::string Literal; + bool IsNumber; + union { + int Number; + const char* String; + }; public: - LiteralConstantEmitter(const char *literal) : Literal(literal) { + LiteralConstantEmitter(const char *string) : + IsNumber(false), + String(string) { } - LiteralConstantEmitter(int literal) { - char buf[256]; - snprintf(buf, 256, "%d", literal); - Literal = buf; + LiteralConstantEmitter(int number = 0) : + IsNumber(true), + Number(number) { + } + void set(const char *string) { + IsNumber = false; + Number = 0; + String = string; + } + void set(int number) { + IsNumber = true; + String = NULL; + Number = number; + } + bool is(const char *string) { + return !strcmp(String, string); } void emit(raw_ostream &o, unsigned int &i) { - o << Literal; + if (IsNumber) + o << Number; + else + o << String; } }; class CompoundConstantEmitter : public ConstantEmitter { private: - std::vector Entries; + unsigned int Padding; + std::vector Entries; public: - CompoundConstantEmitter() { - } - ~CompoundConstantEmitter() { - unsigned int index; - unsigned int numEntries = Entries.size(); - for (index = 0; index < numEntries; ++index) { - delete Entries[index]; - } + CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) { } CompoundConstantEmitter &addEntry(ConstantEmitter *e) { Entries.push_back(e); + return *this; } + ~CompoundConstantEmitter() { + while (Entries.size()) { + ConstantEmitter *entry = Entries.back(); + Entries.pop_back(); + delete entry; + } + } void emit(raw_ostream &o, unsigned int &i) { o << "{" << "\n"; i += 2; unsigned int index; unsigned int numEntries = Entries.size(); - for (index = 0; index < numEntries; ++index) { + + unsigned int numToPrint; + + if (Padding) { + if (numEntries > Padding) { + fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding); + llvm_unreachable("More entries than padding"); + } + numToPrint = Padding; + } else { + numToPrint = numEntries; + } + + for (index = 0; index < numToPrint; ++index) { o.indent(i); - Entries[index]->emit(o, i); - if (index < (numEntries - 1)) + if (index < numEntries) + Entries[index]->emit(o, i); + else + o << "-1"; + + if (index < (numToPrint - 1)) o << ","; o << "\n"; } @@ -226,40 +267,31 @@ void populateOperandOrder(CompoundConstantEmitter *operandOrder, ++operandIterator) { if (operandIterator->OperandType == AsmWriterOperand::isMachineInstrOperand) { - char buf[2]; - snprintf(buf, sizeof(buf), "%u", operandIterator->CGIOpNo); - operandOrder->addEntry(new LiteralConstantEmitter(buf)); + operandOrder->addEntry( + new LiteralConstantEmitter(operandIterator->CGIOpNo)); numArgs++; } } - - for(; numArgs < MAX_OPERANDS; numArgs++) { - operandOrder->addEntry(new LiteralConstantEmitter("-1")); - } } ///////////////////////////////////////////////////// // Support functions for handling X86 instructions // ///////////////////////////////////////////////////// -#define ADDFLAG(flag) flags->addEntry(flag) +#define SET(flag) { type->set(flag); return 0; } -#define REG(str) if (name == str) { ADDFLAG("kOperandFlagRegister"); return 0; } -#define MEM(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); return 0; } -#define LEA(str) if (name == str) { ADDFLAG("kOperandFlagEffectiveAddress"); \ - return 0; } -#define IMM(str) if (name == str) { ADDFLAG("kOperandFlagImmediate"); \ - return 0; } -#define PCR(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); \ - ADDFLAG("kOperandFlagPCRelative"); \ - return 0; } +#define REG(str) if (name == str) SET("kOperandTypeRegister"); +#define MEM(str) if (name == str) SET("kOperandTypeX86Memory"); +#define LEA(str) if (name == str) SET("kOperandTypeX86EffectiveAddress"); +#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); +#define PCR(str) if (name == str) SET("kOperandTypeX86PCRelative"); -/// X86FlagFromOpName - Processes the name of a single X86 operand (which is -/// actually its type) and translates it into an operand flag +/// X86TypeFromOpName - Processes the name of a single X86 operand (which is +/// actually its type) and translates it into an operand type /// -/// @arg flags - The flags object to add the flag to +/// @arg flags - The type object to set /// @arg name - The name of the operand -static int X86FlagFromOpName(FlagsConstantEmitter *flags, +static int X86TypeFromOpName(LiteralConstantEmitter *type, const std::string &name) { REG("GR8"); REG("GR8_NOREX"); @@ -282,6 +314,19 @@ static int X86FlagFromOpName(FlagsConstantEmitter *flags, REG("CONTROL_REG_32"); REG("CONTROL_REG_64"); + IMM("i8imm"); + IMM("i16imm"); + IMM("i16i8imm"); + IMM("i32imm"); + IMM("i32imm_pcrel"); + IMM("i32i8imm"); + IMM("i64imm"); + IMM("i64i8imm"); + IMM("i64i32imm"); + IMM("i64i32imm_pcrel"); + IMM("SSECC"); + + // all R, I, R, I, R MEM("i8mem"); MEM("i8mem_NOREX"); MEM("i16mem"); @@ -301,22 +346,12 @@ static int X86FlagFromOpName(FlagsConstantEmitter *flags, MEM("f128mem"); MEM("opaque512mem"); + // all R, I, R, I LEA("lea32mem"); LEA("lea64_32mem"); LEA("lea64mem"); - IMM("i8imm"); - IMM("i16imm"); - IMM("i16i8imm"); - IMM("i32imm"); - IMM("i32imm_pcrel"); - IMM("i32i8imm"); - IMM("i64imm"); - IMM("i64i8imm"); - IMM("i64i32imm"); - IMM("i64i32imm_pcrel"); - IMM("SSECC"); - + // all I PCR("brtarget8"); PCR("offset8"); PCR("offset16"); @@ -332,7 +367,8 @@ static int X86FlagFromOpName(FlagsConstantEmitter *flags, #undef LEA #undef IMM #undef PCR -#undef ADDFLAG + +#undef SET /// X86PopulateOperands - Handles all the operands in an X86 instruction, adding /// the appropriate flags to their descriptors @@ -340,7 +376,7 @@ static int X86FlagFromOpName(FlagsConstantEmitter *flags, /// @operandFlags - A reference the array of operand flag objects /// @inst - The instruction to use as a source of information static void X86PopulateOperands( - FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], + LiteralConstantEmitter *(&operandTypes)[MAX_OPERANDS], const CodeGenInstruction &inst) { if (!inst.TheDef->isSubClassOf("X86Inst")) return; @@ -353,7 +389,7 @@ static void X86PopulateOperands( inst.OperandList[index]; Record &rec = *operandInfo.Rec; - if (X86FlagFromOpName(operandFlags[index], rec.getName())) { + if (X86TypeFromOpName(operandTypes[index], rec.getName())) { errs() << "Operand type: " << rec.getName().c_str() << "\n"; errs() << "Operand name: " << operandInfo.Name.c_str() << "\n"; errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n"; @@ -369,10 +405,11 @@ static void X86PopulateOperands( /// between names and operand indices /// @opName - The name of the operand /// @flag - The name of the flag to add -static inline void decorate1(FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], - const CodeGenInstruction &inst, - const char *opName, - const char *opFlag) { +static inline void decorate1( + FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], + const CodeGenInstruction &inst, + const char *opName, + const char *opFlag) { unsigned opIndex; opIndex = inst.getOperandNamed(std::string(opName)); @@ -382,78 +419,70 @@ static inline void decorate1(FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS] #define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag) -#define MOV(source, target) { \ - instFlags.addEntry("kInstructionFlagMove"); \ - DECORATE1(source, "kOperandFlagSource"); \ - DECORATE1(target, "kOperandFlagTarget"); \ +#define MOV(source, target) { \ + instType.set("kInstructionTypeMove"); \ + DECORATE1(source, "kOperandFlagSource"); \ + DECORATE1(target, "kOperandFlagTarget"); \ } -#define BRANCH(target) { \ - instFlags.addEntry("kInstructionFlagBranch"); \ - DECORATE1(target, "kOperandFlagTarget"); \ +#define BRANCH(target) { \ + instType.set("kInstructionTypeBranch"); \ + DECORATE1(target, "kOperandFlagTarget"); \ } -#define PUSH(source) { \ - instFlags.addEntry("kInstructionFlagPush"); \ - DECORATE1(source, "kOperandFlagSource"); \ +#define PUSH(source) { \ + instType.set("kInstructionTypePush"); \ + DECORATE1(source, "kOperandFlagSource"); \ } -#define POP(target) { \ - instFlags.addEntry("kInstructionFlagPop"); \ - DECORATE1(target, "kOperandFlagTarget"); \ +#define POP(target) { \ + instType.set("kInstructionTypePop"); \ + DECORATE1(target, "kOperandFlagTarget"); \ } -#define CALL(target) { \ - instFlags.addEntry("kInstructionFlagCall"); \ - DECORATE1(target, "kOperandFlagTarget"); \ +#define CALL(target) { \ + instType.set("kInstructionTypeCall"); \ + DECORATE1(target, "kOperandFlagTarget"); \ } -#define RETURN() { \ - instFlags.addEntry("kInstructionFlagReturn"); \ +#define RETURN() { \ + instType.set("kInstructionTypeReturn"); \ } /// X86ExtractSemantics - Performs various checks on the name of an X86 /// instruction to determine what sort of an instruction it is and then adds /// the appropriate flags to the instruction and its operands /// -/// @arg instFlags - A reference to the flags for the instruction as a whole +/// @arg instType - A reference to the type for the instruction as a whole /// @arg operandFlags - A reference to the array of operand flag object pointers /// @arg inst - A reference to the original instruction -static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, - FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], - const CodeGenInstruction &inst) { +static void X86ExtractSemantics( + LiteralConstantEmitter &instType, + FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], + const CodeGenInstruction &inst) { const std::string &name = inst.TheDef->getName(); if (name.find("MOV") != name.npos) { if (name.find("MOV_V") != name.npos) { // ignore (this is a pseudoinstruction) - } - else if (name.find("MASK") != name.npos) { + } else if (name.find("MASK") != name.npos) { // ignore (this is a masking move) - } - else if (name.find("r0") != name.npos) { + } else if (name.find("r0") != name.npos) { // ignore (this is a pseudoinstruction) - } - else if (name.find("PS") != name.npos || + } else if (name.find("PS") != name.npos || name.find("PD") != name.npos) { // ignore (this is a shuffling move) - } - else if (name.find("MOVS") != name.npos) { + } else if (name.find("MOVS") != name.npos) { // ignore (this is a string move) - } - else if (name.find("_F") != name.npos) { + } else if (name.find("_F") != name.npos) { // TODO handle _F moves to ST(0) - } - else if (name.find("a") != name.npos) { + } else if (name.find("a") != name.npos) { // TODO handle moves to/from %ax - } - else if (name.find("CMOV") != name.npos) { + } else if (name.find("CMOV") != name.npos) { MOV("src2", "dst"); - } - else if (name.find("PC") != name.npos) { + } else if (name.find("PC") != name.npos) { MOV("label", "reg") - } - else { + } else { MOV("src", "dst"); } } @@ -462,8 +491,7 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, name.find("J") == 0) { if (name.find("FAR") != name.npos && name.find("i") != name.npos) { BRANCH("off"); - } - else { + } else { BRANCH("dst"); } } @@ -471,19 +499,15 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, if (name.find("PUSH") != name.npos) { if (name.find("FS") != name.npos || name.find("GS") != name.npos) { - instFlags.addEntry("kInstructionFlagPush"); + instType.set("kInstructionTypePush"); // TODO add support for fixed operands - } - else if (name.find("F") != name.npos) { + } else if (name.find("F") != name.npos) { // ignore (this pushes onto the FP stack) - } - else if (name[name.length() - 1] == 'm') { + } else if (name[name.length() - 1] == 'm') { PUSH("src"); - } - else if (name.find("i") != name.npos) { + } else if (name.find("i") != name.npos) { PUSH("imm"); - } - else { + } else { PUSH("reg"); } } @@ -491,19 +515,15 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, if (name.find("POP") != name.npos) { if (name.find("POPCNT") != name.npos) { // ignore (not a real pop) - } - else if (name.find("FS") != name.npos || + } else if (name.find("FS") != name.npos || name.find("GS") != name.npos) { - instFlags.addEntry("kInstructionFlagPop"); + instType.set("kInstructionTypePop"); // TODO add support for fixed operands - } - else if (name.find("F") != name.npos) { + } else if (name.find("F") != name.npos) { // ignore (this pops from the FP stack) - } - else if (name[name.length() - 1] == 'm') { + } else if (name[name.length() - 1] == 'm') { POP("dst"); - } - else { + } else { POP("reg"); } } @@ -511,17 +531,13 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, if (name.find("CALL") != name.npos) { if (name.find("ADJ") != name.npos) { // ignore (not a call) - } - else if (name.find("SYSCALL") != name.npos) { + } else if (name.find("SYSCALL") != name.npos) { // ignore (doesn't go anywhere we know about) - } - else if (name.find("VMCALL") != name.npos) { + } else if (name.find("VMCALL") != name.npos) { // ignore (rather different semantics than a regular call) - } - else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { + } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { CALL("off"); - } - else { + } else { CALL("dst"); } } @@ -538,9 +554,182 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, #undef CALL #undef RETURN -#undef COND_DECORATE_2 -#undef COND_DECORATE_1 -#undef DECORATE1 +///////////////////////////////////////////////////// +// Support functions for handling ARM instructions // +///////////////////////////////////////////////////// + +#define SET(flag) { type->set(flag); return 0; } + +#define REG(str) if (name == str) SET("kOperandTypeRegister"); +#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); + +#define MISC(str, type) if (name == str) SET(type); + +/// ARMFlagFromOpName - Processes the name of a single ARM operand (which is +/// actually its type) and translates it into an operand type +/// +/// @arg type - The type object to set +/// @arg name - The name of the operand +static int ARMFlagFromOpName(LiteralConstantEmitter *type, + const std::string &name) { + REG("GPR"); + REG("cc_out"); + REG("s_cc_out"); + REG("tGPR"); + REG("DPR"); + REG("SPR"); + REG("QPR"); + REG("DPR_VFP2"); + REG("DPR_8"); + + IMM("i32imm"); + IMM("bf_inv_mask_imm"); + IMM("jtblock_operand"); + IMM("nohash_imm"); + IMM("cpinst_operand"); + IMM("cps_opt"); + IMM("vfp_f64imm"); + IMM("vfp_f32imm"); + IMM("msr_mask"); + IMM("neg_zero"); + IMM("imm0_31"); + IMM("h8imm"); + IMM("h16imm"); + IMM("h32imm"); + IMM("h64imm"); + IMM("imm0_4095"); + IMM("jt2block_operand"); + IMM("t_imm_s4"); + IMM("pclabel"); + + MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I + MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I + MISC("so_imm", "kOperandTypeARMSoImm"); // I + MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I + MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I + MISC("pred", "kOperandTypeARMPredicate"); // I, R + MISC("it_pred", "kOperandTypeARMPredicate"); // I + MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I + MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I + MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I + MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I + MISC("addrmode4", "kOperandTypeARMAddrMode4"); // R, I + MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I + MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I + MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I + MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I + MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... + MISC("it_mask", "kOperandTypeThumbITMask"); // I + MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I + MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I + MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I + MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I + MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I + MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); + // R, I + MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I + MISC("t_addrmode_s1", "kOperandTypeThumbAddrModeS1"); // R, I, R + MISC("t_addrmode_s2", "kOperandTypeThumbAddrModeS2"); // R, I, R + MISC("t_addrmode_s4", "kOperandTypeThumbAddrModeS4"); // R, I, R + MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R + MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I + + return 1; +} + +#undef SOREG +#undef SOIMM +#undef PRED +#undef REG +#undef MEM +#undef LEA +#undef IMM +#undef PCR + +#undef SET + +/// ARMPopulateOperands - Handles all the operands in an ARM instruction, adding +/// the appropriate flags to their descriptors +/// +/// @operandFlags - A reference the array of operand flag objects +/// @inst - The instruction to use as a source of information +static void ARMPopulateOperands( + LiteralConstantEmitter *(&operandTypes)[MAX_OPERANDS], + const CodeGenInstruction &inst) { + if (!inst.TheDef->isSubClassOf("InstARM") && + !inst.TheDef->isSubClassOf("InstThumb")) + return; + + unsigned int index; + unsigned int numOperands = inst.OperandList.size(); + + if (numOperands > MAX_OPERANDS) { + fprintf(stderr, "numOperands == %llu > %llu\n", + (uint64_t)numOperands, (uint64_t)MAX_OPERANDS); + llvm_unreachable("Too many operands"); + } + + for (index = 0; index < numOperands; ++index) { + const CodeGenInstruction::OperandInfo &operandInfo = + inst.OperandList[index]; + Record &rec = *operandInfo.Rec; + + if (ARMFlagFromOpName(operandTypes[index], rec.getName())) { + errs() << "Operand type: " << rec.getName().c_str() << "\n"; + errs() << "Operand name: " << operandInfo.Name.c_str() << "\n"; + errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n"; + llvm_unreachable("Unhandled type"); + } + } +} + +#define BRANCH(target) { \ + instType.set("kInstructionTypeBranch"); \ + DECORATE1(target, "kOperandFlagTarget"); \ +} + +/// ARMExtractSemantics - Performs various checks on the name of an ARM +/// instruction to determine what sort of an instruction it is and then adds +/// the appropriate flags to the instruction and its operands +/// +/// @arg instType - A reference to the type for the instruction as a whole +/// @arg operandTypes - A reference to the array of operand type object pointers +/// @arg operandFlags - A reference to the array of operand flag object pointers +/// @arg inst - A reference to the original instruction +static void ARMExtractSemantics( + LiteralConstantEmitter &instType, + LiteralConstantEmitter *(&operandTypes)[MAX_OPERANDS], + FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], + const CodeGenInstruction &inst) { + const std::string &name = inst.TheDef->getName(); + + if (name == "tBcc" || + name == "tB" || + name == "t2Bcc" || + name == "Bcc" || + name == "tCBZ" || + name == "tCBNZ") { + BRANCH("target"); + } + + if (name == "tBLr9" || + name == "BLr9_pred" || + name == "tBLXi_r9" || + name == "tBLXr_r9" || + name == "BLXr9" || + name == "t2BXJ" || + name == "BXJ") { + BRANCH("func"); + + unsigned opIndex; + opIndex = inst.getOperandNamed("func"); + if (operandTypes[opIndex]->is("kOperandTypeImmediate")) + operandTypes[opIndex]->set("kOperandTypeARMBranchTarget"); + } +} + +#undef BRANCH /// populateInstInfo - Fills an array of InstInfos with information about each /// instruction in a target @@ -561,19 +750,29 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; infoArray.addEntry(infoStruct); - FlagsConstantEmitter *instFlags = new FlagsConstantEmitter; - infoStruct->addEntry(instFlags); + LiteralConstantEmitter *instType = new LiteralConstantEmitter; + infoStruct->addEntry(instType); LiteralConstantEmitter *numOperandsEmitter = new LiteralConstantEmitter(inst.OperandList.size()); infoStruct->addEntry(numOperandsEmitter); + + CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter; + infoStruct->addEntry(operandTypeArray); + + LiteralConstantEmitter *operandTypes[MAX_OPERANDS]; CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter; infoStruct->addEntry(operandFlagArray); FlagsConstantEmitter *operandFlags[MAX_OPERANDS]; - for (unsigned operandIndex = 0; operandIndex < MAX_OPERANDS; ++operandIndex) { + for (unsigned operandIndex = 0; + operandIndex < MAX_OPERANDS; + ++operandIndex) { + operandTypes[operandIndex] = new LiteralConstantEmitter; + operandTypeArray->addEntry(operandTypes[operandIndex]); + operandFlags[operandIndex] = new FlagsConstantEmitter; operandFlagArray->addEntry(operandFlags[operandIndex]); } @@ -581,29 +780,32 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, unsigned numSyntaxes = 0; if (target.getName() == "X86") { - X86PopulateOperands(operandFlags, inst); - X86ExtractSemantics(*instFlags, operandFlags, inst); + X86PopulateOperands(operandTypes, inst); + X86ExtractSemantics(*instType, operandFlags, inst); numSyntaxes = 2; } + else if (target.getName() == "ARM") { + ARMPopulateOperands(operandTypes, inst); + ARMExtractSemantics(*instType, operandTypes, operandFlags, inst); + numSyntaxes = 1; + } + + CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; - CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; infoStruct->addEntry(operandOrderArray); for (unsigned syntaxIndex = 0; syntaxIndex < MAX_SYNTAXES; ++syntaxIndex) { - CompoundConstantEmitter *operandOrder = new CompoundConstantEmitter; + CompoundConstantEmitter *operandOrder = + new CompoundConstantEmitter(MAX_OPERANDS); + operandOrderArray->addEntry(operandOrder); if (syntaxIndex < numSyntaxes) { populateOperandOrder(operandOrder, inst, syntaxIndex); } - else { - for (unsigned operandIndex = 0; - operandIndex < MAX_OPERANDS; - ++operandIndex) { - operandOrder->addEntry(new LiteralConstantEmitter("-1")); - } - } } + + infoStruct = NULL; } } @@ -634,32 +836,71 @@ void EDEmitter::runHeader(raw_ostream &o) { unsigned int i = 0; + EnumEmitter operandTypes("OperandTypes"); + operandTypes.addEntry("kOperandTypeNone"); + operandTypes.addEntry("kOperandTypeImmediate"); + operandTypes.addEntry("kOperandTypeRegister"); + operandTypes.addEntry("kOperandTypeX86Memory"); + operandTypes.addEntry("kOperandTypeX86EffectiveAddress"); + operandTypes.addEntry("kOperandTypeX86PCRelative"); + operandTypes.addEntry("kOperandTypeARMBranchTarget"); + operandTypes.addEntry("kOperandTypeARMSoReg"); + operandTypes.addEntry("kOperandTypeARMSoImm"); + operandTypes.addEntry("kOperandTypeARMSoImm2Part"); + operandTypes.addEntry("kOperandTypeARMPredicate"); + operandTypes.addEntry("kOperandTypeARMAddrMode2"); + operandTypes.addEntry("kOperandTypeARMAddrMode2Offset"); + operandTypes.addEntry("kOperandTypeARMAddrMode3"); + operandTypes.addEntry("kOperandTypeARMAddrMode3Offset"); + operandTypes.addEntry("kOperandTypeARMAddrMode4"); + operandTypes.addEntry("kOperandTypeARMAddrMode5"); + operandTypes.addEntry("kOperandTypeARMAddrMode6"); + operandTypes.addEntry("kOperandTypeARMAddrMode6Offset"); + operandTypes.addEntry("kOperandTypeARMAddrModePC"); + operandTypes.addEntry("kOperandTypeARMRegisterList"); + operandTypes.addEntry("kOperandTypeARMTBAddrMode"); + operandTypes.addEntry("kOperandTypeThumbITMask"); + operandTypes.addEntry("kOperandTypeThumbAddrModeS1"); + operandTypes.addEntry("kOperandTypeThumbAddrModeS2"); + operandTypes.addEntry("kOperandTypeThumbAddrModeS4"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); + operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); + operandTypes.addEntry("kOperandTypeThumb2SoReg"); + operandTypes.addEntry("kOperandTypeThumb2SoImm"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8Offset"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm12"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeSoReg"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset"); + + operandTypes.emit(o, i); + + o << "\n"; + EnumEmitter operandFlags("OperandFlags"); - operandFlags.addEntry("kOperandFlagImmediate"); - operandFlags.addEntry("kOperandFlagRegister"); - operandFlags.addEntry("kOperandFlagMemory"); - operandFlags.addEntry("kOperandFlagEffectiveAddress"); - operandFlags.addEntry("kOperandFlagPCRelative"); operandFlags.addEntry("kOperandFlagSource"); operandFlags.addEntry("kOperandFlagTarget"); operandFlags.emitAsFlags(o, i); o << "\n"; - EnumEmitter instructionFlags("InstructionFlags"); - instructionFlags.addEntry("kInstructionFlagMove"); - instructionFlags.addEntry("kInstructionFlagBranch"); - instructionFlags.addEntry("kInstructionFlagPush"); - instructionFlags.addEntry("kInstructionFlagPop"); - instructionFlags.addEntry("kInstructionFlagCall"); - instructionFlags.addEntry("kInstructionFlagReturn"); - instructionFlags.emitAsFlags(o, i); + EnumEmitter instructionTypes("InstructionTypes"); + instructionTypes.addEntry("kInstructionTypeNone"); + instructionTypes.addEntry("kInstructionTypeMove"); + instructionTypes.addEntry("kInstructionTypeBranch"); + instructionTypes.addEntry("kInstructionTypePush"); + instructionTypes.addEntry("kInstructionTypePop"); + instructionTypes.addEntry("kInstructionTypeCall"); + instructionTypes.addEntry("kInstructionTypeReturn"); + instructionTypes.emit(o, i); o << "\n"; StructEmitter instInfo("InstInfo"); - instInfo.addMember("uint32_t", "instructionFlags"); + instInfo.addMember("uint8_t", "instructionType"); instInfo.addMember("uint8_t", "numOperands"); + instInfo.addMember("uint8_t", "operandTypes[MAX_OPERANDS]"); instInfo.addMember("uint8_t", "operandFlags[MAX_OPERANDS]"); instInfo.addMember("const char", "operandOrders[MAX_SYNTAXES][MAX_OPERANDS]"); instInfo.emit(o, i);