ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DisassemblerArm.C
Go to the documentation of this file.
1 #include "sage3basic.h"
2 #include "Assembler.h"
3 #include "AssemblerX86.h"
4 #include "AsmUnparser_compat.h"
5 #include "Disassembler.h"
6 #include "sageBuilderAsm.h"
7 #include "DisassemblerArm.h"
8 
9 /* See header file for full documentation. */
10 
11 bool
13 {
16 }
17 
18 void
20 {
22  set_wordsize(4);
23  set_alignment(4);
26 }
27 
28 /* This is a bit of a kludge for now because we're trying to use an unmodified version of the ArmDisassembler name space. */
31 {
32  if (start_va & 0x3)
33  throw Exception("instruction pointer not word aligned", start_va);
34  if (start_va >= 0xffffffff)
35  throw Exception("instruction pointer out of range", start_va);
36 
37  /* The old ArmDisassembler::disassemble() function doesn't understand MemoryMap mappings. Therefore, remap the next
38  * few bytes (enough for at least one instruction) into a temporary buffer. */
39  unsigned char temp[4]; /* all ARM instructions are 32 bits */
40  size_t tempsz = map->read(temp, start_va, sizeof temp, get_protection());
41 
42  /* Treat the bytes as a little-endian instruction. FIXME: This assumes a little-endian ARM system. */
43  if (tempsz<4)
44  throw Exception("short read", start_va);
45  uint32_t c = temp[0] | (temp[1]<<8) | (temp[2]<<16) | (temp[3]<<24);
46 
47  /* Disassemble the instruction */
48  startInstruction(start_va, c);
49  SgAsmArmInstruction *insn = disassemble(); /*throws an exception on error*/
50  ROSE_ASSERT(insn);
51 
52  /* Note successors if necessary */
53  if (successors) {
54  bool complete;
55  AddressSet suc2 = insn->get_successors(&complete);
56  successors->insert(suc2.begin(), suc2.end());
57  }
58 
59  update_progress(insn);
60  return insn;
61 }
62 
65 {
66  SgAsmArmInstruction *insn = new SgAsmArmInstruction(e.ip, "unknown", arm_unknown_instruction, arm_cond_unknown, 0);
67  SgAsmOperandList *operands = new SgAsmOperandList();
68  insn->set_operandList(operands);
69  operands->set_parent(insn);
70  insn->set_raw_bytes(e.bytes);
71  return insn;
72 }
73 
74 
75 
77 DisassemblerArm::makeInstructionWithoutOperands(uint32_t address, const std::string& mnemonic, int condPos,
78  ArmInstructionKind kind, ArmInstructionCondition cond, uint32_t insn)
79 {
80  SgAsmArmInstruction* instruction = new SgAsmArmInstruction(address, mnemonic, kind, cond, condPos);
81  ROSE_ASSERT (instruction);
82 
83  SgAsmOperandList* operands = new SgAsmOperandList();
84  instruction->set_operandList(operands);
85  operands->set_parent(instruction);
86 
87  SgUnsignedCharList bytes(4, '\0');
88  for (int i = 0; i < 4; ++i) {
89  bytes[i] = (insn >> (8 * i)) & 0xFF; /* Force little-endian */
90  }
91 
92  instruction->set_raw_bytes(bytes);
93 
94  return instruction;
95 }
96 
100 {
101  ROSE_ASSERT(get_registers()!=NULL);
102  ROSE_ASSERT(reg<16);
103  std::string name = "r" + StringUtility::numberToString(reg);
104  const RegisterDescriptor *rdesc = get_registers()->lookup(name);
105  ROSE_ASSERT(rdesc!=NULL);
107  return r;
108 }
109 
121 DisassemblerArm::makePsrFields(bool useSPSR, uint8_t fields) const
122 {
123  ROSE_ASSERT(get_registers()!=NULL);
124  std::string name = useSPSR ? "spsr" : "cpsr";
125  const RegisterDescriptor *rdesc = get_registers()->lookup(name);
126  ROSE_ASSERT(rdesc!=NULL);
128  if (fields!=0)
129  r->set_psr_mask(fields);
130  return r;
131 }
132 
134 DisassemblerArm::makePsr(bool useSPSR) const
135 {
136  return makePsrFields(useSPSR, 0);
137 }
138 
139 
142 {
143  uint8_t rsField = (insn >> 8) & 15;
144  uint8_t rotateCount = rsField * 2;
145  uint32_t immRaw = insn & 0xFF;
146  if (rotateCount == 0) {
147  return SageBuilderAsm::makeDWordValue(immRaw);
148  } else {
149  return SageBuilderAsm::makeDWordValue((immRaw >> rotateCount) | (immRaw << (32 - rotateCount)));
150  }
151 }
152 
155 {
156  bool i = (insn >> 25) & 1;
157  uint8_t rsField = (insn >> 8) & 15;
158  uint8_t rmField = insn & 15;
159  uint8_t shiftCount = (insn >> 7) & 31;
160  uint8_t shiftCountOr32 = shiftCount == 0 ? 32 : shiftCount;
161  if (i) {
162  return makeRotatedImmediate();
163  } else if ((insn & 0xFF0) == 0) {
164  return makeRegister(rmField);
165  } else if ((insn & 0x070) == 0) {
167  } else if ((insn & 0x0F0) == 0x010) {
168  return SageBuilderAsm::makeLsl(makeRegister(rmField), makeRegister(rsField));
169  } else if ((insn & 0x070) == 0x020) {
170  return SageBuilderAsm::makeLsr(makeRegister(rmField), SageBuilderAsm::makeByteValue(shiftCountOr32));
171  } else if ((insn & 0x0F0) == 0x030) {
172  return SageBuilderAsm::makeLsr(makeRegister(rmField), makeRegister(rsField));
173  } else if ((insn & 0x070) == 0x040) {
174  return SageBuilderAsm::makeAsr(makeRegister(rmField), SageBuilderAsm::makeByteValue(shiftCountOr32));
175  } else if ((insn & 0x0F0) == 0x050) {
176  return SageBuilderAsm::makeAsr(makeRegister(rmField), makeRegister(rsField));
177  } else if ((insn & 0xFF0) == 0x060) {
178  return SageBuilderAsm::makeRrx(makeRegister(rmField));
179  } else if ((insn & 0x070) == 0x060) {
181  } else if ((insn & 0x0F0) == 0x070) {
182  return SageBuilderAsm::makeRor(makeRegister(rmField), makeRegister(rsField));
183  } else {
184  throw ExceptionArm("bad shifter field", this, 25);
185  }
186 }
187 
188 #define MAKE_INSN0(Mne, CondPos) (makeInstructionWithoutOperands(ip, #Mne, (CondPos), arm_##Mne, cond, insn))
189 #define MAKE_INSN1(Mne, CondPos, Op1) (SageBuilderAsm::appendOperand(MAKE_INSN0(Mne, CondPos), (Op1)))
190 #define MAKE_INSN2(Mne, CondPos, Op1, Op2) (SageBuilderAsm::appendOperand(MAKE_INSN1(Mne, CondPos, Op1), (Op2)))
191 #define MAKE_INSN3(Mne, CondPos, Op1, Op2, Op3) (SageBuilderAsm::appendOperand(MAKE_INSN2(Mne, CondPos, Op1, Op2), (Op3)))
192 #define MAKE_INSN4(Mne, CondPos, Op1, Op2, Op3, Op4) (SageBuilderAsm::appendOperand(MAKE_INSN3(Mne, CondPos, Op1, Op2, Op3), (Op4)))
193 
196  SgAsmExpression* rhsOperand)
197 {
198  switch ((s ? 16 : 0) | opcode) {
199  case 0x00: return MAKE_INSN3(and, 3, rd, rn, rhsOperand);
200  case 0x01: return MAKE_INSN3(eor, 3, rd, rn, rhsOperand);
201  case 0x02: return MAKE_INSN3(sub, 3, rd, rn, rhsOperand);
202  case 0x03: return MAKE_INSN3(rsb, 3, rd, rn, rhsOperand);
203  case 0x04: return MAKE_INSN3(add, 3, rd, rn, rhsOperand);
204  case 0x05: return MAKE_INSN3(adc, 3, rd, rn, rhsOperand);
205  case 0x06: return MAKE_INSN3(sbc, 3, rd, rn, rhsOperand);
206  case 0x07: return MAKE_INSN3(rsc, 3, rd, rn, rhsOperand);
207  case 0x08: ROSE_ASSERT (!"Not a data processing insn");
208  case 0x09: ROSE_ASSERT (!"Not a data processing insn");
209  case 0x0A: ROSE_ASSERT (!"Not a data processing insn");
210  case 0x0B: ROSE_ASSERT (!"Not a data processing insn");
211  case 0x0C: return MAKE_INSN3(orr, 3, rd, rn, rhsOperand);
212  case 0x0D: return MAKE_INSN2(mov, 3, rd, rhsOperand);
213  case 0x0E: return MAKE_INSN3(bic, 3, rd, rn, rhsOperand);
214  case 0x0F: return MAKE_INSN2(mvn, 3, rd, rhsOperand);
215  case 0x10: return MAKE_INSN3(ands, 3, rd, rn, rhsOperand);
216  case 0x11: return MAKE_INSN3(eors, 3, rd, rn, rhsOperand);
217  case 0x12: return MAKE_INSN3(subs, 3, rd, rn, rhsOperand);
218  case 0x13: return MAKE_INSN3(rsbs, 3, rd, rn, rhsOperand);
219  case 0x14: return MAKE_INSN3(adds, 3, rd, rn, rhsOperand);
220  case 0x15: return MAKE_INSN3(adcs, 3, rd, rn, rhsOperand);
221  case 0x16: return MAKE_INSN3(sbcs, 3, rd, rn, rhsOperand);
222  case 0x17: return MAKE_INSN3(rscs, 3, rd, rn, rhsOperand);
223  case 0x18: return MAKE_INSN2(tst, 3, rn, rhsOperand);
224  case 0x19: return MAKE_INSN2(teq, 3, rn, rhsOperand);
225  case 0x1A: return MAKE_INSN2(cmp, 3, rn, rhsOperand);
226  case 0x1B: return MAKE_INSN2(cmn, 3, rn, rhsOperand);
227  case 0x1C: return MAKE_INSN3(orrs, 3, rd, rn, rhsOperand);
228  case 0x1D: return MAKE_INSN2(movs, 3, rd, rhsOperand);
229  case 0x1E: return MAKE_INSN3(bics, 3, rd, rn, rhsOperand);
230  case 0x1F: return MAKE_INSN2(mvns, 3, rd, rhsOperand);
231  default: ROSE_ASSERT (false);
232  }
233 // DQ (11/29/2009): Avoid MSVC warning.
234  return NULL;
235 }
236 
239 {
240  int32_t val = ((insn >> 4) & 0xF0) | (insn & 0xF);
241  val <<= 24;
242  val >>= 24; // Arithmetic shift to copy highest bit of immediate
243  return SageBuilderAsm::makeDWordValue((uint32_t)val);
244 }
245 
248 {
249  int32_t val = insn & 0xFFFFFF;
250  val <<= 8;
251  val >>= 6; // Arithmetic shift to copy highest bit of immediate
252  uint32_t targetAddr = ip + 8 + val;
253  return SageBuilderAsm::makeDWordValue(targetAddr);
254 }
255 
258 {
259  bool bit25 = (insn >> 25) & 1;
260  bool p = (insn >> 24) & 1;
261  bool u = (insn >> 23) & 1;
262  bool w = (insn >> 21) & 1;
264  switch ((p ? 4 : 0) | (u ? 2 : 0) | (w ? 1 : 0)) {
265  case 0: return SageBuilderAsm::makeSubtractPostupdate(rn, offset);
266  case 1: return SageBuilderAsm::makeSubtractPostupdate(rn, offset); // T suffix
267  case 2: return SageBuilderAsm::makeAddPostupdate(rn, offset);
268  case 3: return SageBuilderAsm::makeAddPostupdate(rn, offset); // T suffix
269  case 4: return SageBuilderAsm::makeSubtract(rn, offset);
270  case 5: return SageBuilderAsm::makeSubtractPreupdate(rn, offset);
271  case 6: return SageBuilderAsm::makeAdd(rn, offset);
272  case 7: return SageBuilderAsm::makeAddPreupdate(rn, offset);
273  default: {
274  ROSE_ASSERT (false);
275  // DQ (11/29/2009): Avoid MSVC warning.
276  return NULL;
277  }
278  }
279 }
280 
283 {
284  std::cerr << "ARM media instructions not supported: " << StringUtility::intToHex(insn) << std::endl;
285  throw ExceptionArm("media instruction not supported", this);
286 }
287 
290 {
291  SgAsmExpression* rn = makeRegister((insn >> 16) & 15);
292  SgAsmExpression* rd = makeRegister((insn >> 12) & 15);
293  SgAsmExpression* rs = makeRegister((insn >> 8) & 15);
294  SgAsmExpression* rm = makeRegister(insn & 15);
295  switch ((insn >> 20) & 15) {
296  case 0x0: return MAKE_INSN3(mul, 3, rn, rm, rs);
297  case 0x1: return MAKE_INSN3(muls, 3, rn, rm, rs);
298  case 0x2: return MAKE_INSN4(mla, 3, rn, rm, rs, rd);
299  case 0x3: return MAKE_INSN4(mlas, 3, rn, rm, rs, rd);
300  case 0x4: return MAKE_INSN4(umaal, 3, rd, rn, rm, rs);
301  case 0x5: throw ExceptionArm("bad bits in decodeMultiplyInstruction (0x5)", this, 20);
302  case 0x6: throw ExceptionArm("bad bits in decodeMultiplyInstruction (0x6)", this, 20);
303  case 0x7: throw ExceptionArm("bad bits in decodeMultiplyInstruction (0x7)", this, 20);
304  case 0x8: return MAKE_INSN4(umull, 5, rd, rn, rm, rs);
305  case 0x9: return MAKE_INSN4(umulls, 5, rd, rn, rm, rs);
306  case 0xA: return MAKE_INSN4(umlal, 5, rd, rn, rm, rs);
307  case 0xB: return MAKE_INSN4(umlals, 5, rd, rn, rm, rs);
308  case 0xC: return MAKE_INSN4(smull, 5, rd, rn, rm, rs);
309  case 0xD: return MAKE_INSN4(smulls, 5, rd, rn, rm, rs);
310  case 0xE: return MAKE_INSN4(smlal, 5, rd, rn, rm, rs);
311  case 0xF: return MAKE_INSN4(smlals, 5, rd, rn, rm, rs);
312  default: ROSE_ASSERT (false);
313  }
314 // DQ (11/29/2009): Avoid MSVC warning.
315  return NULL;
316 }
317 
320 {
321  bool bit5 = (insn >> 5) & 1;
322  bool bit6 = (insn >> 6) & 1;
323  bool bit20 = (insn >> 20) & 1;
324  bool bit21 = (insn >> 21) & 1;
325  bool bit22 = (insn >> 22) & 1;
326  bool bit23 = (insn >> 23) & 1;
327  bool bit24 = (insn >> 24) & 1;
328  SgAsmExpression* rn = makeRegister((insn >> 16) & 15);
329  SgAsmExpression* rd = makeRegister((insn >> 12) & 15);
331  SgAsmExpression* addr = NULL;
332  switch ((bit24 ? 4 : 0) | (bit23 ? 2 : 0) | (bit21 ? 1 : 0)) {
333  case 0: addr = SageBuilderAsm::makeSubtractPostupdate(rn, offset); break;
334  case 1: throw ExceptionArm("bad bits in decodeExtraLoadStores (1)", this, 21);
335  case 2: addr = SageBuilderAsm::makeAddPostupdate(rn, offset); break;
336  case 3: throw ExceptionArm("bad bits in decodeExtraLoadStores (3)", this, 21);
337  case 4: addr = SageBuilderAsm::makeSubtract(rn, offset); break;
338  case 5: addr = SageBuilderAsm::makeSubtractPreupdate(rn, offset); break;
339  case 6: addr = SageBuilderAsm::makeAdd(rn, offset); break;
340  case 7: addr = SageBuilderAsm::makeAddPreupdate(rn, offset); break;
341  default: ROSE_ASSERT (false);
342  }
344  uint8_t lsh = (bit20 ? 4 : 0) | (bit6 ? 2 : 0) | (bit5 ? 1 : 0);
345  switch (lsh) {
346  case 0:
347  /* Should have been handled in multiply code above */
348  throw ExceptionArm("bad bits in decodeExtraLoadStores (0)", this, 5);
349  case 1: return MAKE_INSN2(strh, 3, rd, memref);
350  case 2: return MAKE_INSN2(ldrd, 3, rd, memref);
351  case 3: return MAKE_INSN2(strd, 3, rd, memref);
352  case 4:
353  /* Should have been handled in multiply code above */
354  throw ExceptionArm("bad bits in decodeExtraLoadStores (4)", this, 5);
355  case 5: return MAKE_INSN2(ldruh, 3, rd, memref);
356  case 6: return MAKE_INSN2(ldrsb, 3, rd, memref);
357  case 7: return MAKE_INSN2(ldrsh, 3, rd, memref);
358  default: ROSE_ASSERT (false);
359  }
360 // DQ (11/29/2009): Avoid MSVC warning.
361  return NULL;
362 }
363 
366 {
367  bool bit7 = (insn >> 7) & 1;
368  bool bit21 = (insn >> 21) & 1;
369  bool bit22 = (insn >> 22) & 1;
370  if (!bit7) {
371  switch ((insn >> 4) & 7) {
372  case 0: {
373  if (bit21) {
375  bool useSPSR = bit22;
376  uint8_t mask = (insn >> 16) & 15;
378  return MAKE_INSN2(msr, 3, psr, rm);
379  } else {
380  bool useSPSR = bit22;
383  return MAKE_INSN2(mrs, 3, rd, psr);
384  }
385  }
386  case 1: {
387  if (bit22) {
390  return MAKE_INSN2(clz, 3, rd, rm);
391  } else {
392  return MAKE_INSN1(bx, 2, makeRegister(insn & 15));
393  }
394  }
395  case 2: return MAKE_INSN1(bxj, 3, makeRegister(insn & 15));
396  case 3: return MAKE_INSN1(blx, 3, makeRegister(insn & 15));
397  case 4: throw ExceptionArm("bad bits in decodeMiscInstruction (4)", this, 4);
398  case 5: {
402  uint8_t op = (insn >> 21) & 3;
403  switch (op) {
404  case 0: return MAKE_INSN3(qadd, 4, rd, rm, rn);
405  case 1: return MAKE_INSN3(qsub, 4, rd, rm, rn);
406  case 2: return MAKE_INSN3(qdadd, 5, rd, rm, rn);
407  case 3: return MAKE_INSN3(qdsub, 5, rd, rm, rn);
408  default: ROSE_ASSERT (false);
409  }
410  }
411  case 6: throw ExceptionArm("bad bits in decodeMiscInstruction (6)", this, 4);
412  case 7: {
413  uint16_t imm1 = (insn >> 8) & 0xFFF;
414  uint16_t imm2 = insn & 0xF;
415  uint16_t imm = (imm1 << 4) | imm2;
416  return MAKE_INSN1(bkpt, 4, SageBuilderAsm::makeWordValue(imm));
417  }
418  default: ROSE_ASSERT (false);
419  }
420  } else { // bit 7 set -- signed mul
425  uint8_t op = (insn >> 21) & 3;
426  bool y = (insn >> 6) & 1;
427  bool x = (insn >> 5) & 1;
428  switch ((op << 2) | (x ? 2 : 0) | (y ? 1 : 0)) {
429  case 0x0: return MAKE_INSN4(smlabb, 6, rd, rm, rs, rn);
430  case 0x1: return MAKE_INSN4(smlabt, 6, rd, rm, rs, rn);
431  case 0x2: return MAKE_INSN4(smlatb, 6, rd, rm, rs, rn);
432  case 0x3: return MAKE_INSN4(smlatt, 6, rd, rm, rs, rn);
433  case 0x4: return MAKE_INSN4(smlawb, 6, rd, rm, rs, rn);
434  case 0x5: return MAKE_INSN4(smlawt, 6, rd, rm, rs, rn);
435  case 0x6: return MAKE_INSN4(smluwb, 6, rd, rm, rs, rn);
436  case 0x7: return MAKE_INSN4(smluwt, 6, rd, rm, rs, rn);
437  case 0x8: return MAKE_INSN4(smlalbb, 7, rn, rd, rm, rs);
438  case 0x9: return MAKE_INSN4(smlalbt, 7, rn, rd, rm, rs);
439  case 0xA: return MAKE_INSN4(smlaltb, 7, rn, rd, rm, rs);
440  case 0xB: return MAKE_INSN4(smlaltt, 7, rn, rd, rm, rs);
441  case 0xC: return MAKE_INSN3(smulbb, 6, rd, rm, rs);
442  case 0xD: return MAKE_INSN3(smulbt, 6, rd, rm, rs);
443  case 0xE: return MAKE_INSN3(smultb, 6, rd, rm, rs);
444  case 0xF: return MAKE_INSN3(smultt, 6, rd, rm, rs);
445  default: ROSE_ASSERT (false);
446  }
447  }
448 // DQ (11/29/2009): Avoid MSVC warning.
449  return NULL;
450 }
451 
454 {
455  // fprintf(stderr, "Disassembling insn 0x%08" PRIx32 " at addr 0x%08" PRIx32 "\n", insn, p.ip);
456  uint8_t condField = (insn >> 28) & 0xF;
457  bool bit4 = (insn >> 4) & 1;
458  bool bit7 = (insn >> 7) & 1;
459  bool bit9 = (insn >> 9) & 1;
460  bool bit16 = (insn >> 16) & 1;
461  bool bit20 = (insn >> 20) & 1;
462  bool bit21 = (insn >> 21) & 1;
463  bool bit22 = (insn >> 22) & 1;
464  bool bit23 = (insn >> 23) & 1;
465  bool bit24 = (insn >> 24) & 1;
466  bool bit25 = (insn >> 25) & 1;
467  bool bit4_and_bit7 = bit4 && bit7;
468  if (condField != 15 || !decodeUnconditionalInstructions) { // Normal instructions (or arm_cond_nv instructions if they are not treated specially)
469  cond = (ArmInstructionCondition)(condField + 1);
470  uint8_t dataProcOpcode = (insn >> 21) & 15;
471  bool dpIsSpecial = (insn & 0x01900000) == 0x01000000;
472  switch ((insn >> 26) & 3) {
473  case 0: { // Data processing, misc, multiplies, undefined, move imm to status reg
474  if ((insn & 0x0F0000F0U) == 0x00000090U) { // Multiplies
475  return decodeMultiplyInstruction();
476  } else if (bit4_and_bit7 && !bit25) {
477  return decodeExtraLoadStores();
478  } else if (dpIsSpecial && bit25) {
479  if (bit21) {
481  bool useSPSR = bit22;
482  uint8_t mask = (insn >> 16) & 15;
484  return MAKE_INSN2(msr, 3, psr, imm);
485  } else {
486  throw ExceptionArm("bad bit21", this, 26);
487  }
488  } else if (dpIsSpecial && !bit25) {
489  return decodeMiscInstruction();
490  } else { // !dpIsSpecial && !bit4_and_bit7
491  SgAsmExpression* rn = makeRegister((insn >> 16) & 15);
492  SgAsmExpression* rd = makeRegister((insn >> 12) & 15);
493  SgAsmExpression* shifterField = makeShifterField();
494  return makeDataProcInstruction(dataProcOpcode, bit20, rn, rd, shifterField);
495  }
496  }
497  case 1: { // Load-store, media, undefined
498  if (!bit4 || !bit25) {
499  SgAsmExpression* rn = makeRegister((insn >> 16) & 15);
501  SgAsmExpression* rd = makeRegister((insn >> 12) & 15);
502  bool isLoad = bit20;
503  bool isByte = bit22;
504  bool isTranslated = !bit24 && bit21;
505  switch ((isTranslated ? 4 : 0) | (isLoad ? 2 : 0) | (isByte ? 1 : 0)) {
506  case 0: return MAKE_INSN2(str, 3, rd, memref);
507  case 1: return MAKE_INSN2(strb, 3, rd, memref);
508  case 2: return MAKE_INSN2(ldr, 3, rd, memref);
509  case 3: return MAKE_INSN2(ldrb, 3, rd, memref);
510  case 4: return MAKE_INSN2(strt, 3, rd, memref);
511  case 5: return MAKE_INSN2(strbt, 3, rd, memref);
512  case 6: return MAKE_INSN2(ldrt, 3, rd, memref);
513  case 7: return MAKE_INSN2(ldrbt, 3, rd, memref);
514  default: ROSE_ASSERT (false);
515  }
516  } else if ((insn & 0x0FF000F0U) == 0x07F000F0U) {
517  return MAKE_INSN0(undefined, 9);
518  } else {
519  return decodeMediaInstruction();
520  }
521  }
522  case 2: { // Load-store multiple, branches
523  if (!bit25) {
524  SgAsmExpression* rn = makeRegister((insn >> 16) & 15);
526  for (int i = 0; i < 16; ++i) {
527  if ((insn >> i) & 1) {
529  regs->get_expressions().push_back(reg);
530  reg->set_parent(regs);
531  }
532  }
533  SgAsmExpression* base = rn;
534  if (bit21) { // w
536  if (bit23) { // u
537  base = SageBuilderAsm::makeAddPostupdate(rn, offset);
538  } else {
539  base = SageBuilderAsm::makeSubtractPostupdate(rn, offset);
540  }
541  }
542 
543  // DQ (11/29/2009): This is a MSVC warning: warning C4805: '|' : unsafe mix of type 'uint32_t' and type 'bool' in operation
544  switch (((insn >> 21) & 62) | bit20) { // p, u, s, l
545  case 0x0: return MAKE_INSN2(stmda, 3, rn, regs);
546  case 0x1: return MAKE_INSN2(ldmda, 3, rn, regs);
547  case 0x2: return MAKE_INSN2(stmda, 3, rn, SageBuilderAsm::makeArmSpecialRegisterList(regs));
548  case 0x3: return MAKE_INSN2(ldmda, 3, rn, SageBuilderAsm::makeArmSpecialRegisterList(regs));
549  case 0x4: return MAKE_INSN2(stmia, 3, rn, regs);
550  case 0x5: return MAKE_INSN2(ldmia, 3, rn, regs);
551  case 0x6: return MAKE_INSN2(stmia, 3, rn, SageBuilderAsm::makeArmSpecialRegisterList(regs));
552  case 0x7: return MAKE_INSN2(ldmia, 3, rn, SageBuilderAsm::makeArmSpecialRegisterList(regs));
553  case 0x8: return MAKE_INSN2(stmdb, 3, rn, regs);
554  case 0x9: return MAKE_INSN2(ldmdb, 3, rn, regs);
555  case 0xA: return MAKE_INSN2(stmdb, 3, rn, SageBuilderAsm::makeArmSpecialRegisterList(regs));
556  case 0xB: return MAKE_INSN2(ldmdb, 3, rn, SageBuilderAsm::makeArmSpecialRegisterList(regs));
557  case 0xC: return MAKE_INSN2(stmib, 3, rn, regs);
558  case 0xD: return MAKE_INSN2(ldmib, 3, rn, regs);
559  case 0xE: return MAKE_INSN2(stmib, 3, rn, SageBuilderAsm::makeArmSpecialRegisterList(regs));
560  case 0xF: return MAKE_INSN2(ldmib, 3, rn, SageBuilderAsm::makeArmSpecialRegisterList(regs));
561  default: ROSE_ASSERT (false);
562  }
563  } else {
564  SgAsmExpression* target = makeBranchTarget();
565  if ((insn >> 24) & 1) {
566  return MAKE_INSN1(bl, 2, target);
567  } else {
568  return MAKE_INSN1(b, 1, target);
569  }
570  }
571  }
572  case 3: {
573  if ((insn & 0x0F000000U) == 0x0F000000U) {
574  return MAKE_INSN1(swi, 3, SageBuilderAsm::makeDWordValue(insn & 0x00FFFFFFU));
575  } else {
576  std::cerr << "Coprocessor not supported 0x" << StringUtility::intToHex(insn) << std::endl;
577  throw ExceptionArm("coprocessor not supported", this, 26);
578  }
579  }
580  default: ROSE_ASSERT (!"Can't happen");
581  }
582  } else { // Unconditional instructions
583  cond = arm_cond_al;
584  uint16_t opcode1 = (insn >> 20) & 0xFF;
585 
586  // DQ (8/30/2008): Unused value removed to avoid compiler warning.
587  // uint16_t opcode2 = (insn >> 4) & 0xF;
588 
589  switch (opcode1) {
590  case 0x10: {
591  if (bit16) {
592  return MAKE_INSN1(setend, 6, SageBuilderAsm::makeByteValue(bit9));
593  } else {
594  ROSE_ASSERT (!"CPS not supported");
595  }
596  }
597  default: {
598  std::cerr << "Cannot handle too many unconditional instructions: " << StringUtility::intToHex(insn) << std::endl;
599  throw ExceptionArm("too many unconditional instructions", this, 32);
600  }
601  }
602  }
603 
604  ROSE_ASSERT (!"Fell off end of disassemble");
605 // DQ (11/29/2009): Avoid MSVC warning.
606  return NULL;
607 }