X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FDisassembler%2FARMDisassemblerCore.h;h=7d21256a14f9f9b9f71cee2f2304ecf1da115c48;hb=99405df044f2c584242e711cc9023ec90356da82;hp=23b309cd4f481e9a629e058168a6be669234c4db;hpb=d30a98e43ae18e1fc70a7dc748edf669d809c685;p=oota-llvm.git diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h index 23b309cd4f4..7d21256a14f 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h @@ -1,4 +1,4 @@ -//===- ARMDisassemblerCore.h - ARM disassembler helpers ----*- C++ -*-===// +//===- ARMDisassemblerCore.h - ARM disassembler helpers ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,8 +13,8 @@ // specifies the encoding used by the instruction, as well as a helper function // to convert the enums to printable char strings. // -// It also contains code to represent the concepts of Builder, Builder Factory, -// as well as the Algorithm to solve the problem of disassembling an ARM instr. +// It also contains code to represent the concepts of Builder and DisassembleFP +// to solve the problem of disassembling an ARM instr. // //===----------------------------------------------------------------------===// @@ -24,6 +24,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/Target/TargetInstrInfo.h" #include "ARMInstrInfo.h" +#include "ARMDisassembler.h" namespace llvm { @@ -32,6 +33,12 @@ public: static const char *OpcodeName(unsigned Opcode); }; +///////////////////////////////////////////////////// +// // +// Enums and Utilities for ARM Instruction Format // +// // +///////////////////////////////////////////////////// + #define ARM_FORMATS \ ENTRY(ARM_FORMAT_PSEUDO, 0) \ ENTRY(ARM_FORMAT_MULFRM, 1) \ @@ -44,26 +51,38 @@ public: ENTRY(ARM_FORMAT_LDMISCFRM, 8) \ ENTRY(ARM_FORMAT_STMISCFRM, 9) \ ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \ - ENTRY(ARM_FORMAT_ARITHMISCFRM, 11) \ - ENTRY(ARM_FORMAT_EXTFRM, 12) \ - ENTRY(ARM_FORMAT_VFPUNARYFRM, 13) \ - ENTRY(ARM_FORMAT_VFPBINARYFRM, 14) \ - ENTRY(ARM_FORMAT_VFPCONV1FRM, 15) \ - ENTRY(ARM_FORMAT_VFPCONV2FRM, 16) \ - ENTRY(ARM_FORMAT_VFPCONV3FRM, 17) \ - ENTRY(ARM_FORMAT_VFPCONV4FRM, 18) \ - ENTRY(ARM_FORMAT_VFPCONV5FRM, 19) \ - ENTRY(ARM_FORMAT_VFPLDSTFRM, 20) \ - ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 21) \ - ENTRY(ARM_FORMAT_VFPMISCFRM, 22) \ - ENTRY(ARM_FORMAT_THUMBFRM, 23) \ - ENTRY(ARM_FORMAT_NEONFRM, 24) \ - ENTRY(ARM_FORMAT_NEONGETLNFRM, 25) \ - ENTRY(ARM_FORMAT_NEONSETLNFRM, 26) \ - ENTRY(ARM_FORMAT_NEONDUPFRM, 27) \ - ENTRY(ARM_FORMAT_LDSTEXFRM, 28) \ + ENTRY(ARM_FORMAT_LDSTEXFRM, 11) \ + ENTRY(ARM_FORMAT_ARITHMISCFRM, 12) \ + ENTRY(ARM_FORMAT_EXTFRM, 13) \ + ENTRY(ARM_FORMAT_VFPUNARYFRM, 14) \ + ENTRY(ARM_FORMAT_VFPBINARYFRM, 15) \ + ENTRY(ARM_FORMAT_VFPCONV1FRM, 16) \ + ENTRY(ARM_FORMAT_VFPCONV2FRM, 17) \ + ENTRY(ARM_FORMAT_VFPCONV3FRM, 18) \ + ENTRY(ARM_FORMAT_VFPCONV4FRM, 19) \ + ENTRY(ARM_FORMAT_VFPCONV5FRM, 20) \ + ENTRY(ARM_FORMAT_VFPLDSTFRM, 21) \ + ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 22) \ + ENTRY(ARM_FORMAT_VFPMISCFRM, 23) \ + ENTRY(ARM_FORMAT_THUMBFRM, 24) \ + ENTRY(ARM_FORMAT_NEONFRM, 25) \ + ENTRY(ARM_FORMAT_NEONGETLNFRM, 26) \ + ENTRY(ARM_FORMAT_NEONSETLNFRM, 27) \ + ENTRY(ARM_FORMAT_NEONDUPFRM, 28) \ ENTRY(ARM_FORMAT_MISCFRM, 29) \ - ENTRY(ARM_FORMAT_THUMBMISCFRM, 30) + ENTRY(ARM_FORMAT_THUMBMISCFRM, 30) \ + ENTRY(ARM_FORMAT_NLdSt, 31) \ + ENTRY(ARM_FORMAT_N1RegModImm, 32) \ + ENTRY(ARM_FORMAT_N2Reg, 33) \ + ENTRY(ARM_FORMAT_NVCVT, 34) \ + ENTRY(ARM_FORMAT_NVecDupLn, 35) \ + ENTRY(ARM_FORMAT_N2RegVecShL, 36) \ + ENTRY(ARM_FORMAT_N2RegVecShR, 37) \ + ENTRY(ARM_FORMAT_N3Reg, 38) \ + ENTRY(ARM_FORMAT_N3RegVecSh, 39) \ + ENTRY(ARM_FORMAT_NVecExtract, 40) \ + ENTRY(ARM_FORMAT_NVecMulScalar, 41) \ + ENTRY(ARM_FORMAT_NVTBL, 42) // ARM instruction format specifies the encoding used by the instruction. #define ENTRY(n, v) n = v, @@ -85,46 +104,6 @@ static const inline char *stringForARMFormat(ARMFormat form) { #undef ENTRY } -#define NS_FORMATS \ - ENTRY(NS_FORMAT_NONE, 0) \ - ENTRY(NS_FORMAT_VLDSTLane, 1) \ - ENTRY(NS_FORMAT_VLDSTLaneDbl, 2) \ - ENTRY(NS_FORMAT_VLDSTRQ, 3) \ - ENTRY(NS_FORMAT_NVdImm, 4) \ - ENTRY(NS_FORMAT_NVdVmImm, 5) \ - ENTRY(NS_FORMAT_NVdVmImmVCVT, 6) \ - ENTRY(NS_FORMAT_NVdVmImmVDupLane, 7) \ - ENTRY(NS_FORMAT_NVdVmImmVSHLL, 8) \ - ENTRY(NS_FORMAT_NVectorShuffle, 9) \ - ENTRY(NS_FORMAT_NVectorShift, 10) \ - ENTRY(NS_FORMAT_NVectorShift2, 11) \ - ENTRY(NS_FORMAT_NVdVnVmImm, 12) \ - ENTRY(NS_FORMAT_NVdVnVmImmVectorShift, 13) \ - ENTRY(NS_FORMAT_NVdVnVmImmVectorExtract, 14) \ - ENTRY(NS_FORMAT_NVdVnVmImmMulScalar, 15) \ - ENTRY(NS_FORMAT_VTBL, 16) - -// NEON instruction sub-format further classify the NEONFrm instruction. -#define ENTRY(n, v) n = v, -typedef enum { - NS_FORMATS - NS_FORMAT_NA -} NSFormat; -#undef ENTRY - -// Converts enum to const char*. -static const inline char *stringForNSFormat(NSFormat form) { -#define ENTRY(n, v) case n: return #n; - switch(form) { - NS_FORMATS - case NS_FORMAT_NA: - return "NA"; - default: - return ""; - } -#undef ENTRY -} - /// Expands on the enum definitions from ARMBaseInstrInfo.h. /// They are being used by the disassembler implementation. namespace ARMII { @@ -158,83 +137,97 @@ static inline void setSlice(uint32_t &Bits, unsigned From, unsigned To, /// Various utilities for checking the target specific flags. /// A unary data processing instruction doesn't have an Rn operand. -static inline bool isUnaryDP(unsigned TSFlags) { +static inline bool isUnaryDP(uint64_t TSFlags) { return (TSFlags & ARMII::UnaryDP); } /// This four-bit field describes the addressing mode used. /// See also ARMBaseInstrInfo.h. -static inline unsigned getAddrMode(unsigned TSFlags) { +static inline unsigned getAddrMode(uint64_t TSFlags) { return (TSFlags & ARMII::AddrModeMask); } /// {IndexModePre, IndexModePost} /// Only valid for load and store ops. /// See also ARMBaseInstrInfo.h. -static inline unsigned getIndexMode(unsigned TSFlags) { +static inline unsigned getIndexMode(uint64_t TSFlags) { return (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; } /// Pre-/post-indexed operations define an extra $base_wb in the OutOperandList. -static inline bool isPrePostLdSt(unsigned TSFlags) { +static inline bool isPrePostLdSt(uint64_t TSFlags) { return (TSFlags & ARMII::IndexModeMask) != 0; } -/// AbstractARMMCBuilder - AbstractARMMCBuilder represents an interface of ARM -/// MCInst builder that knows how to build up the MCOperand list. -class AbstractARMMCBuilder { -public: - /// Build - Build the MCInst fully and return true. Return false if any - /// failure occurs. - virtual bool Build(MCInst &MI, uint32_t insn) { return false; } -}; - -/// ARMDisassemblyAlgorithm - ARMDisassemblyAlgorithm represents an interface of -/// ARM disassembly algorithm that relies on the entries of target operand info, -/// among other things, to solve the problem of disassembling an ARM machine -/// instruction. -class ARMDisassemblyAlgorithm { -public: - /// Return true if this algorithm successfully disassembles the instruction. - /// NumOpsAdded is updated to reflect the number of operands added by the - /// algorithm. NumOpsAdded may be less than NumOps, in which case, there are - /// operands unaccounted for which need to be dealt with by the API client. - virtual bool Solve(MCInst& MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded) const - = 0; -}; - -/// ARMBasicMCBuilder - ARMBasicMCBuilder represents a concrete subclass of -/// ARMAbstractMCBuilder. -class ARMBasicMCBuilder : public AbstractARMMCBuilder { +// Forward declaration. +class ARMBasicMCBuilder; + +// Builder Object is mostly ignored except in some Thumb disassemble functions. +typedef ARMBasicMCBuilder *BO; + +/// DisassembleFP - DisassembleFP points to a function that disassembles an insn +/// and builds the MCOperand list upon disassembly. It returns false on failure +/// or true on success. The number of operands added is updated upon success. +typedef bool (*DisassembleFP)(MCInst &MI, unsigned Opcode, uint32_t insn, + unsigned short NumOps, unsigned &NumOpsAdded, BO Builder); + +/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC +/// infrastructure of an MCInst given the Opcode and Format of the instr. +/// Return NULL if it fails to create/return a proper builder. API clients +/// are responsible for freeing up of the allocated memory. Cacheing can be +/// performed by the API clients to improve performance. +extern ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format); + +/// ARMBasicMCBuilder - ARMBasicMCBuilder represents an ARM MCInst builder that +/// knows how to build up the MCOperand list. +class ARMBasicMCBuilder { + friend ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format); unsigned Opcode; ARMFormat Format; - NSFormat NSF; unsigned short NumOps; - const ARMDisassemblyAlgorithm &Algo; - static unsigned ITCounter; // Possible values: 0, 1, 2, 3, 4. - static unsigned ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially. + DisassembleFP Disasm; + Session *SP; + int Err; // !=0 if the builder encounters some error condition during build. + +private: + /// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder. + ARMBasicMCBuilder(unsigned opc, ARMFormat format, unsigned short num); public: - ARMBasicMCBuilder(ARMBasicMCBuilder &MCB) : AbstractARMMCBuilder(), - Opcode(MCB.Opcode), Format(MCB.Format), NSF(MCB.NSF), NumOps(MCB.NumOps), - Algo(MCB.Algo) {} + ARMBasicMCBuilder(ARMBasicMCBuilder &B) + : Opcode(B.Opcode), Format(B.Format), NumOps(B.NumOps), Disasm(B.Disasm), + SP(B.SP) { + Err = 0; + } + + virtual ~ARMBasicMCBuilder() {} - /// Opcode, Format, NSF, NumOperands, and Algo make an ARM Basic MCBuilder. - ARMBasicMCBuilder(unsigned opc, ARMFormat format, NSFormat NSF, - unsigned short num, const ARMDisassemblyAlgorithm &algo) - : AbstractARMMCBuilder(), Opcode(opc), Format(format), NumOps(num), - Algo(algo) {} + void SetSession(Session *sp) { + SP = sp; + } + + void SetErr(int ErrCode) { + Err = ErrCode; + } + /// DoPredicateOperands - DoPredicateOperands process the predicate operands + /// of some Thumb instructions which come before the reglist operands. It + /// returns true if the two predicate operands have been processed. + bool DoPredicateOperands(MCInst& MI, unsigned Opcode, + uint32_t insn, unsigned short NumOpsRemaning); + /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process /// the possible Predicate and SBitModifier, to build the remaining MCOperand /// constituents. - static bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode, + bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode, uint32_t insn, unsigned short NumOpsRemaning); /// InITBlock - InITBlock returns true if we are inside an IT block. - static bool InITBlock() { - return ITCounter > 0; + bool InITBlock() { + if (SP) + return SP->ITCounter > 0; + + return false; } /// Build - Build delegates to BuildIt to perform the heavy liftling. After @@ -247,9 +240,9 @@ public: /// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder. /// The general idea is to set the Opcode for the MCInst, followed by adding /// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates - /// to the Algo (ARM Disassemble Algorithm) object to perform Format-specific - /// disassembly, followed by class method TryPredicateAndSBitModifier() to do - /// PredicateOperand and OptionalDefOperand which follow the Dst/Src Operands. + /// to the Format-specific disassemble function for disassembly, followed by + /// TryPredicateAndSBitModifier() for PredicateOperand and OptionalDefOperand + /// which follow the Dst/Src Operands. virtual bool BuildIt(MCInst &MI, uint32_t insn); /// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary @@ -258,42 +251,10 @@ public: private: /// Get condition of the current IT instruction. - static unsigned GetITCond() { - return slice(ITState, 7, 4); + unsigned GetITCond() { + assert(SP); + return slice(SP->ITState, 7, 4); } - - /// Init ITState. - static void InitITState(unsigned short bits7_0) { - ITState = bits7_0; - } - - /// Update ITState if necessary. - static void UpdateITState() { - assert(ITCounter); - --ITCounter; - if (ITCounter == 0) - ITState = 0; - else { - unsigned short NewITState4_0 = slice(ITState, 4, 0) << 1; - setSlice(ITState, 4, 0, NewITState4_0); - } - } -}; - -/// ARMMCBuilderFactory - ARMMCBuilderFactory represents the factory class that -/// vends out ARMAbstractMCBuilder instances through its class method. -class ARMMCBuilderFactory { -private: - ARMMCBuilderFactory(); // DO NOT IMPLEMENT. - -public: - /// CreateMCBuilder - Return an AbstractARMMCBuilder that can build up the MC - /// infrastructure of an MCInst given the Opcode and Format of the instr. - /// Return NULL if it fails to create/return a proper builder. API clients - /// are responsible for freeing up of the allocated memory. Cacheing can be - /// performed by the API clients to improve performance. - static AbstractARMMCBuilder *CreateMCBuilder(unsigned Opcode, - ARMFormat Format, NSFormat NSF); }; } // namespace llvm