ROSE  0.11.2.0
DispatcherA64.h
1 #include <featureTests.h>
2 #ifdef ROSE_ENABLE_ASM_A64
3 
4 #include <BaseSemantics2.h>
5 
6 #include <boost/serialization/access.hpp>
7 #include <boost/serialization/base_object.hpp>
8 #include <boost/serialization/export.hpp>
9 #include <boost/serialization/split_member.hpp>
10 
11 namespace Rose {
12 namespace BinaryAnalysis {
13 namespace InstructionSemantics2 {
14 
16 using DispatcherA64Ptr = boost::shared_ptr<class DispatcherA64>;
17 
18 class DispatcherA64: public BaseSemantics::Dispatcher {
19 public:
20  using Super = BaseSemantics::Dispatcher;
21 
22 public:
27  RegisterDescriptor REG_PC, REG_SP, REG_LR;
28  RegisterDescriptor REG_CPSR_N, REG_CPSR_Z, REG_CPSR_C, REG_CPSR_V;
29 
30 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
31 private:
32  friend class boost::serialization::access;
33 
34  template<class S>
35  void save(S &s, const unsigned /*version*/) const {
36  s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
37  }
38 
39  template<class S>
40  void load(S &s, const unsigned /*version*/) {
41  s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
42  initializeRegisterDescriptors();
43  initializeInsnDispatchTable();
44  initializeMemory();
45  }
46 
47  BOOST_SERIALIZATION_SPLIT_MEMBER();
48 #endif
49 
50 protected:
51  // prototypical constructor
52  DispatcherA64()
53  : BaseSemantics::Dispatcher(64, RegisterDictionary::dictionary_a64()) {}
54 
55  DispatcherA64(const BaseSemantics::RiscOperatorsPtr &ops, const RegisterDictionary *regs)
56  : BaseSemantics::Dispatcher(ops, 64, regs ? regs : RegisterDictionary::dictionary_a64()) {
57  initializeRegisterDescriptors();
58  initializeInsnDispatchTable();
59  initializeMemory();
60  }
61 
62 public:
66  static DispatcherA64Ptr instance() {
67  return DispatcherA64Ptr(new DispatcherA64);
68  }
69 
71  static DispatcherA64Ptr instance(const BaseSemantics::RiscOperatorsPtr &ops, const RegisterDictionary *regs = nullptr) {
72  return DispatcherA64Ptr(new DispatcherA64(ops, regs));
73  }
74 
76  virtual BaseSemantics::DispatcherPtr create(const BaseSemantics::RiscOperatorsPtr &ops, size_t addrWidth = 0,
77  const RegisterDictionary *regs = nullptr) const override {
78  ASSERT_require(0 == addrWidth || 64 == addrWidth);
79  return instance(ops, regs);
80  }
81 
83  static DispatcherA64Ptr promote(const BaseSemantics::DispatcherPtr &d) {
84  DispatcherA64Ptr retval = boost::dynamic_pointer_cast<DispatcherA64>(d);
85  ASSERT_not_null(retval);
86  return retval;
87  }
88 
89 protected:
91  void initializeRegisterDescriptors();
92 
96  void initializeInsnDispatchTable();
97 
99  void initializeMemory();
100 
101 public:
102  BaseSemantics::SValuePtr read(SgAsmExpression*, size_t value_nbits=0, size_t addr_nbits=0) override;
103  void write(SgAsmExpression*, const BaseSemantics::SValuePtr &value, size_t addr_nbits=0) override;
104 
105  // Operations more or less defined by the A64 reference manual. Replicates the specified value according to the vector type.
107 
108  struct NZCV {
113 
114  NZCV() {}
115 
116  NZCV(const BaseSemantics::SValuePtr &n, const BaseSemantics::SValuePtr &z,
118  : n(n), z(z), c(c), v(v) {}
119  };
120 
121  // Compute the NZCV bits based on the result of an addition and the carries returned by RiscOperators::addWithCarries.
122  NZCV computeNZCV(const BaseSemantics::SValuePtr &sum, const BaseSemantics::SValuePtr &carries);
123 
124  // Set the NZCV bits based on the result of an addition and the carries returned by RiscOperators::addWithCarries.
125  void updateNZCV(const BaseSemantics::SValuePtr &sum, const BaseSemantics::SValuePtr &carries);
126 
127  // Return true or false depending on whether the condition holds.
128  BaseSemantics::SValuePtr conditionHolds(A64InstructionCondition);
129 
130  // From ARM documentation: "Decode AArch64 bitfield and logical immediate masks which use a similar encoding structure."
131  std::pair<uint64_t, uint64_t> decodeBitMasks(size_t m, bool immN, uint64_t imms, uint64_t immr, bool immediate);
132 
133  // Handles the rather tricky BFM instruction, which is a general case of a few other instructions.
134  void bitfieldMove(BaseSemantics::RiscOperators *ops, SgAsmExpression *dst, SgAsmExpression *src, bool n,
135  uint64_t immR, uint64_t immS);
136 
137  // Handles the rather tricky UBFM instruction, which is a general case of a few other instructions.
138  void unsignedBitfieldMove(BaseSemantics::RiscOperators *ops, SgAsmExpression *dst, SgAsmExpression *src, bool n,
139  uint64_t immR, uint64_t immS);
140 
141  // Handles the rather tricky SBFM instruction, which is a general case of a few other instructions.
142  void signedBitfieldMove(BaseSemantics::RiscOperators *ops, SgAsmExpression *dst, SgAsmExpression *src, bool n,
143  uint64_t immR, uint64_t immS);
144 
145 protected:
146  int iproc_key(SgAsmInstruction*) const override;
147  RegisterDescriptor instructionPointerRegister() const override;
148  RegisterDescriptor stackPointerRegister() const override;
149  RegisterDescriptor callReturnRegister() const override;
150  void set_register_dictionary(const RegisterDictionary*) override;
151 };
152 
153 } // namespace
154 } // namespace
155 } // namespace
156 
157 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
158 BOOST_CLASS_EXPORT_KEY(Rose::BinaryAnalysis::InstructionSemantics2::DispatcherA64);
159 #endif
160 
161 #endif
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
Sum< T >::Ptr sum()
Factory for value agumenter.
Base class for machine instructions.
Main namespace for the ROSE library.
boost::shared_ptr< Dispatcher > DispatcherPtr
Shared-ownership pointer to a semantics instruction dispatcher.
Base class for most instruction semantics RISC operators.
Base class for expressions.
Base class for binary types.