ROSE  0.11.17.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  initializeState(ops->currentState());
61  }
62 
63 public:
67  static DispatcherA64Ptr instance() {
68  return DispatcherA64Ptr(new DispatcherA64);
69  }
70 
72  static DispatcherA64Ptr instance(const BaseSemantics::RiscOperatorsPtr &ops, const RegisterDictionary *regs = nullptr) {
73  return DispatcherA64Ptr(new DispatcherA64(ops, regs));
74  }
75 
77  virtual BaseSemantics::DispatcherPtr create(const BaseSemantics::RiscOperatorsPtr &ops, size_t addrWidth = 0,
78  const RegisterDictionary *regs = nullptr) const override {
79  ASSERT_require(0 == addrWidth || 64 == addrWidth);
80  return instance(ops, regs);
81  }
82 
84  static DispatcherA64Ptr promote(const BaseSemantics::DispatcherPtr &d) {
85  DispatcherA64Ptr retval = boost::dynamic_pointer_cast<DispatcherA64>(d);
86  ASSERT_not_null(retval);
87  return retval;
88  }
89 
90 protected:
92  void initializeRegisterDescriptors();
93 
97  void initializeInsnDispatchTable();
98 
100  void initializeMemory();
101 
102 public:
103  BaseSemantics::SValuePtr read(SgAsmExpression*, size_t value_nbits=0, size_t addr_nbits=0) override;
104  void write(SgAsmExpression*, const BaseSemantics::SValuePtr &value, size_t addr_nbits=0) override;
105 
106  // Operations more or less defined by the A64 reference manual. Replicates the specified value according to the vector type.
108 
109  struct NZCV {
114 
115  NZCV() {}
116 
117  NZCV(const BaseSemantics::SValuePtr &n, const BaseSemantics::SValuePtr &z,
119  : n(n), z(z), c(c), v(v) {}
120  };
121 
122  // Compute the NZCV bits based on the result of an addition and the carries returned by RiscOperators::addWithCarries.
123  NZCV computeNZCV(const BaseSemantics::SValuePtr &sum, const BaseSemantics::SValuePtr &carries);
124 
125  // Set the NZCV bits based on the result of an addition and the carries returned by RiscOperators::addWithCarries.
126  void updateNZCV(const BaseSemantics::SValuePtr &sum, const BaseSemantics::SValuePtr &carries);
127 
128  // Return true or false depending on whether the condition holds.
129  BaseSemantics::SValuePtr conditionHolds(A64InstructionCondition);
130 
131  // From ARM documentation: "Decode AArch64 bitfield and logical immediate masks which use a similar encoding structure."
132  std::pair<uint64_t, uint64_t> decodeBitMasks(size_t m, bool immN, uint64_t imms, uint64_t immr, bool immediate);
133 
134  // Handles the rather tricky BFM instruction, which is a general case of a few other instructions.
135  void bitfieldMove(BaseSemantics::RiscOperators *ops, SgAsmExpression *dst, SgAsmExpression *src, bool n,
136  uint64_t immR, uint64_t immS);
137 
138  // Handles the rather tricky UBFM instruction, which is a general case of a few other instructions.
139  void unsignedBitfieldMove(BaseSemantics::RiscOperators *ops, SgAsmExpression *dst, SgAsmExpression *src, bool n,
140  uint64_t immR, uint64_t immS);
141 
142  // Handles the rather tricky SBFM instruction, which is a general case of a few other instructions.
143  void signedBitfieldMove(BaseSemantics::RiscOperators *ops, SgAsmExpression *dst, SgAsmExpression *src, bool n,
144  uint64_t immR, uint64_t immS);
145 
146 protected:
147  int iproc_key(SgAsmInstruction*) const override;
148  RegisterDescriptor instructionPointerRegister() const override;
149  RegisterDescriptor stackPointerRegister() const override;
150  RegisterDescriptor callReturnRegister() const override;
151  void set_register_dictionary(const RegisterDictionary*) override;
152 };
153 
154 } // namespace
155 } // namespace
156 } // namespace
157 
158 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
159 BOOST_CLASS_EXPORT_KEY(Rose::BinaryAnalysis::InstructionSemantics2::DispatcherA64);
160 #endif
161 
162 #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.