ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SgAsmArmInstruction.C
Go to the documentation of this file.
1 /* SgAsmArmInstruction member definitions. Do not move them to src/ROSETTA/Grammar/BinaryInstruction.code (or any *.code file)
2  * because then they won't get indexed/formatted/etc. by C-aware tools. */
3 
4 #include "sage3basic.h"
5 #include "Disassembler.h"
6 
7 /* Returns true if the instruction modifies the instruction pointer (r15). */
8 static bool modifies_ip(SgAsmArmInstruction *insn)
9 {
10  switch (insn->get_kind()) {
11 
12  /* Branch instructions */
13  case arm_b:
14  case arm_bl:
15  case arm_blx:
16  case arm_bx:
17  case arm_bxj:
18  return true;
19 
20  /* Comparison instructions */
21  case arm_cmn:
22  case arm_cmp:
23  case arm_teq:
24  case arm_tst:
25  return false;
26 
27  /* Load multiple registers instructions. Second argument is the set of registers to load. If the instruction
28  * pointer (r15) can be one of them. */
29  case arm_ldm:
30  case arm_ldmda:
31  case arm_ldmdb:
32  case arm_ldmia:
33  case arm_ldmib: {
34  const std::vector<SgAsmExpression*> &exprs = insn->get_operandList()->get_operands();
35  ROSE_ASSERT(exprs.size()>=2);
36  SgAsmExprListExp *elist = isSgAsmExprListExp(exprs[1]);
37  if (!elist) {
39  ROSE_ASSERT(rlist);
40  elist = isSgAsmExprListExp(rlist->get_operand());
41  ROSE_ASSERT(elist);
42  }
43  for (size_t i=0; i<elist->get_expressions().size(); i++) {
45  ROSE_ASSERT(reg);
46  if (reg->get_descriptor().get_major()==arm_regclass_gpr && reg->get_descriptor().get_minor()==15) {
47  return true;
48  }
49  }
50  return false;
51  }
52 
53  /* Interrupt-causing instructions */
54  case arm_bkpt:
55  case arm_swi:
56  case arm_undefined:
57  return true;
58 
59  /* Other instructions modify the instruction pointer if it's the first (destination) argument. */
60  default: {
61  const std::vector<SgAsmExpression*> &exprs = insn->get_operandList()->get_operands();
62  if (exprs.size()>=1) {
64  if (rre &&
65  rre->get_descriptor().get_major()==arm_regclass_gpr && rre->get_descriptor().get_minor()==15) {
66  return true;
67  }
68  }
69  }
70  }
71  return false;
72 }
73 
78  const std::vector<SgAsmExpression*> &exprs = get_operandList()->get_operands();
79  *complete = true; /*assume retval is the complete set of successors for now*/
80 
81  switch (get_kind()) {
82  case arm_b:
83  case arm_bl:
84  case arm_blx:
85  case arm_bx: {
86  /* Branch target */
87  ROSE_ASSERT(exprs.size()==1);
88  SgAsmExpression *dest = exprs[0];
89  if (isSgAsmValueExpression(dest)) {
91  retval.insert(target_va);
92  } else {
93  /* Could also be a register reference expression, but we don't know the successor in that case. */
94  *complete = false;
95  }
96 
97  /* Fall-through address */
98  if (get_condition()!=arm_cond_al)
99  retval.insert(get_address()+4);
100  break;
101  }
102 
103  case arm_bxj: {
104  /* First argument is the register that holds the next instruction pointer value to use in the case that Jazelle is
105  * not available. We only know the successor if the register is the instruction pointer, in which case the
106  * successor is the fall-through address. */
107  ROSE_ASSERT(exprs.size()==1);
109  ROSE_ASSERT(rre);
110  if (rre->get_descriptor().get_major()==arm_regclass_gpr && rre->get_descriptor().get_minor()==15) {
111  retval.insert(get_address()+4);
112  } else {
113  *complete = false;
114  }
115  break;
116  }
117 
118  case arm_cmn:
119  case arm_cmp:
120  case arm_teq:
121  case arm_tst:
122  /* Comparison and test instructions don't ever affect the instruction pointer; they only fall through */
123  retval.insert(get_address()+4);
124  break;
125 
126  case arm_bkpt:
127  case arm_swi:
128  case arm_undefined:
129  case arm_unknown_instruction:
130  /* No known successors for interrupt-generating instructions */
131  break;
132 
133  default:
134  if (!modifies_ip(this) || get_condition()!=arm_cond_al) {
135  retval.insert(get_address()+4);
136  } else {
137  *complete = false;
138  }
139  break;
140  }
141  return retval;
142 }
143 
144 // Does instruction terminate basic block? See base class for full documentation.
145 bool
147  if (get_kind()==arm_unknown_instruction)
148  return true;
149  return modifies_ip(this);
150 }
151 
152 // Determines whether this is the special ARM "unkown" instruction. See base class for documentation.
153 bool
155 {
156  return arm_unknown_instruction == get_kind();
157 }
158