Reapply r105521, this time appending "LLU" to 64 bit
[oota-llvm.git] / lib / Target / ARM / Disassembler / ARMDisassemblerCore.h
index 23b309cd4f481e9a629e058168a6be669234c4db..7d21256a14f9f9b9f71cee2f2304ecf1da115c48 100644 (file)
@@ -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