V8 Project
disasm-arm.cc
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // A Disassembler object is used to disassemble a block of code instruction by
6 // instruction. The default implementation of the NameConverter object can be
7 // overriden to modify register names or to do symbol lookup on addresses.
8 //
9 // The example below will disassemble a block of code and print it to stdout.
10 //
11 // NameConverter converter;
12 // Disassembler d(converter);
13 // for (byte* pc = begin; pc < end;) {
14 // v8::internal::EmbeddedVector<char, 256> buffer;
15 // byte* prev_pc = pc;
16 // pc += d.InstructionDecode(buffer, pc);
17 // printf("%p %08x %s\n",
18 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
19 // }
20 //
21 // The Disassembler class also has a convenience method to disassemble a block
22 // of code into a FILE*, meaning that the above functionality could also be
23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
24 
25 
26 #include <assert.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "src/v8.h"
32 
33 #if V8_TARGET_ARCH_ARM
34 
35 #include "src/arm/constants-arm.h"
37 #include "src/disasm.h"
38 #include "src/macro-assembler.h"
39 
40 
41 namespace v8 {
42 namespace internal {
43 
44 
45 //------------------------------------------------------------------------------
46 
47 // Decoder decodes and disassembles instructions into an output buffer.
48 // It uses the converter to convert register names and call destinations into
49 // more informative description.
50 class Decoder {
51  public:
52  Decoder(const disasm::NameConverter& converter,
53  Vector<char> out_buffer)
54  : converter_(converter),
55  out_buffer_(out_buffer),
56  out_buffer_pos_(0) {
57  out_buffer_[out_buffer_pos_] = '\0';
58  }
59 
60  ~Decoder() {}
61 
62  // Writes one disassembled instruction into 'buffer' (0-terminated).
63  // Returns the length of the disassembled machine instruction in bytes.
64  int InstructionDecode(byte* instruction);
65 
66  static bool IsConstantPoolAt(byte* instr_ptr);
67  static int ConstantPoolSizeAt(byte* instr_ptr);
68 
69  private:
70  // Bottleneck functions to print into the out_buffer.
71  void PrintChar(const char ch);
72  void Print(const char* str);
73 
74  // Printing of common values.
75  void PrintRegister(int reg);
76  void PrintSRegister(int reg);
77  void PrintDRegister(int reg);
78  int FormatVFPRegister(Instruction* instr, const char* format);
79  void PrintMovwMovt(Instruction* instr);
80  int FormatVFPinstruction(Instruction* instr, const char* format);
81  void PrintCondition(Instruction* instr);
82  void PrintShiftRm(Instruction* instr);
83  void PrintShiftImm(Instruction* instr);
84  void PrintShiftSat(Instruction* instr);
85  void PrintPU(Instruction* instr);
86  void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
87 
88  // Handle formatting of instructions and their options.
89  int FormatRegister(Instruction* instr, const char* option);
90  void FormatNeonList(int Vd, int type);
91  void FormatNeonMemory(int Rn, int align, int Rm);
92  int FormatOption(Instruction* instr, const char* option);
93  void Format(Instruction* instr, const char* format);
94  void Unknown(Instruction* instr);
95 
96  // Each of these functions decodes one particular instruction type, a 3-bit
97  // field in the instruction encoding.
98  // Types 0 and 1 are combined as they are largely the same except for the way
99  // they interpret the shifter operand.
100  void DecodeType01(Instruction* instr);
101  void DecodeType2(Instruction* instr);
102  void DecodeType3(Instruction* instr);
103  void DecodeType4(Instruction* instr);
104  void DecodeType5(Instruction* instr);
105  void DecodeType6(Instruction* instr);
106  // Type 7 includes special Debugger instructions.
107  int DecodeType7(Instruction* instr);
108  // For VFP support.
109  void DecodeTypeVFP(Instruction* instr);
110  void DecodeType6CoprocessorIns(Instruction* instr);
111 
112  void DecodeSpecialCondition(Instruction* instr);
113 
114  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
115  void DecodeVCMP(Instruction* instr);
116  void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
117  void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
118 
119  const disasm::NameConverter& converter_;
120  Vector<char> out_buffer_;
121  int out_buffer_pos_;
122 
124 };
125 
126 
127 // Support for assertions in the Decoder formatting functions.
128 #define STRING_STARTS_WITH(string, compare_string) \
129  (strncmp(string, compare_string, strlen(compare_string)) == 0)
130 
131 
132 // Append the ch to the output buffer.
133 void Decoder::PrintChar(const char ch) {
134  out_buffer_[out_buffer_pos_++] = ch;
135 }
136 
137 
138 // Append the str to the output buffer.
139 void Decoder::Print(const char* str) {
140  char cur = *str++;
141  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
142  PrintChar(cur);
143  cur = *str++;
144  }
145  out_buffer_[out_buffer_pos_] = 0;
146 }
147 
148 
149 // These condition names are defined in a way to match the native disassembler
150 // formatting. See for example the command "objdump -d <binary file>".
151 static const char* cond_names[kNumberOfConditions] = {
152  "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
153  "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
154 };
155 
156 
157 // Print the condition guarding the instruction.
158 void Decoder::PrintCondition(Instruction* instr) {
159  Print(cond_names[instr->ConditionValue()]);
160 }
161 
162 
163 // Print the register name according to the active name converter.
164 void Decoder::PrintRegister(int reg) {
165  Print(converter_.NameOfCPURegister(reg));
166 }
167 
168 
169 // Print the VFP S register name according to the active name converter.
170 void Decoder::PrintSRegister(int reg) {
171  Print(VFPRegisters::Name(reg, false));
172 }
173 
174 
175 // Print the VFP D register name according to the active name converter.
176 void Decoder::PrintDRegister(int reg) {
177  Print(VFPRegisters::Name(reg, true));
178 }
179 
180 
181 // These shift names are defined in a way to match the native disassembler
182 // formatting. See for example the command "objdump -d <binary file>".
183 static const char* const shift_names[kNumberOfShifts] = {
184  "lsl", "lsr", "asr", "ror"
185 };
186 
187 
188 // Print the register shift operands for the instruction. Generally used for
189 // data processing instructions.
190 void Decoder::PrintShiftRm(Instruction* instr) {
191  ShiftOp shift = instr->ShiftField();
192  int shift_index = instr->ShiftValue();
193  int shift_amount = instr->ShiftAmountValue();
194  int rm = instr->RmValue();
195 
196  PrintRegister(rm);
197 
198  if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) {
199  // Special case for using rm only.
200  return;
201  }
202  if (instr->RegShiftValue() == 0) {
203  // by immediate
204  if ((shift == ROR) && (shift_amount == 0)) {
205  Print(", RRX");
206  return;
207  } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
208  shift_amount = 32;
209  }
210  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
211  ", %s #%d",
212  shift_names[shift_index],
213  shift_amount);
214  } else {
215  // by register
216  int rs = instr->RsValue();
217  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
218  ", %s ", shift_names[shift_index]);
219  PrintRegister(rs);
220  }
221 }
222 
223 
224 // Print the immediate operand for the instruction. Generally used for data
225 // processing instructions.
226 void Decoder::PrintShiftImm(Instruction* instr) {
227  int rotate = instr->RotateValue() * 2;
228  int immed8 = instr->Immed8Value();
229  int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
230  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm);
231 }
232 
233 
234 // Print the optional shift and immediate used by saturating instructions.
235 void Decoder::PrintShiftSat(Instruction* instr) {
236  int shift = instr->Bits(11, 7);
237  if (shift > 0) {
238  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
239  ", %s #%d",
240  shift_names[instr->Bit(6) * 2],
241  instr->Bits(11, 7));
242  }
243 }
244 
245 
246 // Print PU formatting to reduce complexity of FormatOption.
247 void Decoder::PrintPU(Instruction* instr) {
248  switch (instr->PUField()) {
249  case da_x: {
250  Print("da");
251  break;
252  }
253  case ia_x: {
254  Print("ia");
255  break;
256  }
257  case db_x: {
258  Print("db");
259  break;
260  }
261  case ib_x: {
262  Print("ib");
263  break;
264  }
265  default: {
266  UNREACHABLE();
267  break;
268  }
269  }
270 }
271 
272 
273 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
274 // the FormatOption method.
275 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
276  switch (svc) {
277  case kCallRtRedirected:
278  Print("call rt redirected");
279  return;
280  case kBreakpoint:
281  Print("breakpoint");
282  return;
283  default:
284  if (svc >= kStopCode) {
285  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
286  "%d - 0x%x",
287  svc & kStopCodeMask,
288  svc & kStopCodeMask);
289  } else {
290  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
291  "%d",
292  svc);
293  }
294  return;
295  }
296 }
297 
298 
299 // Handle all register based formatting in this function to reduce the
300 // complexity of FormatOption.
301 int Decoder::FormatRegister(Instruction* instr, const char* format) {
302  DCHECK(format[0] == 'r');
303  if (format[1] == 'n') { // 'rn: Rn register
304  int reg = instr->RnValue();
305  PrintRegister(reg);
306  return 2;
307  } else if (format[1] == 'd') { // 'rd: Rd register
308  int reg = instr->RdValue();
309  PrintRegister(reg);
310  return 2;
311  } else if (format[1] == 's') { // 'rs: Rs register
312  int reg = instr->RsValue();
313  PrintRegister(reg);
314  return 2;
315  } else if (format[1] == 'm') { // 'rm: Rm register
316  int reg = instr->RmValue();
317  PrintRegister(reg);
318  return 2;
319  } else if (format[1] == 't') { // 'rt: Rt register
320  int reg = instr->RtValue();
321  PrintRegister(reg);
322  return 2;
323  } else if (format[1] == 'l') {
324  // 'rlist: register list for load and store multiple instructions
325  DCHECK(STRING_STARTS_WITH(format, "rlist"));
326  int rlist = instr->RlistValue();
327  int reg = 0;
328  Print("{");
329  // Print register list in ascending order, by scanning the bit mask.
330  while (rlist != 0) {
331  if ((rlist & 1) != 0) {
332  PrintRegister(reg);
333  if ((rlist >> 1) != 0) {
334  Print(", ");
335  }
336  }
337  reg++;
338  rlist >>= 1;
339  }
340  Print("}");
341  return 5;
342  }
343  UNREACHABLE();
344  return -1;
345 }
346 
347 
348 // Handle all VFP register based formatting in this function to reduce the
349 // complexity of FormatOption.
350 int Decoder::FormatVFPRegister(Instruction* instr, const char* format) {
351  DCHECK((format[0] == 'S') || (format[0] == 'D'));
352 
353  VFPRegPrecision precision =
354  format[0] == 'D' ? kDoublePrecision : kSinglePrecision;
355 
356  int retval = 2;
357  int reg = -1;
358  if (format[1] == 'n') {
359  reg = instr->VFPNRegValue(precision);
360  } else if (format[1] == 'm') {
361  reg = instr->VFPMRegValue(precision);
362  } else if (format[1] == 'd') {
363  if ((instr->TypeValue() == 7) &&
364  (instr->Bit(24) == 0x0) &&
365  (instr->Bits(11, 9) == 0x5) &&
366  (instr->Bit(4) == 0x1)) {
367  // vmov.32 has Vd in a different place.
368  reg = instr->Bits(19, 16) | (instr->Bit(7) << 4);
369  } else {
370  reg = instr->VFPDRegValue(precision);
371  }
372 
373  if (format[2] == '+') {
374  int immed8 = instr->Immed8Value();
375  if (format[0] == 'S') reg += immed8 - 1;
376  if (format[0] == 'D') reg += (immed8 / 2 - 1);
377  }
378  if (format[2] == '+') retval = 3;
379  } else {
380  UNREACHABLE();
381  }
382 
383  if (precision == kSinglePrecision) {
384  PrintSRegister(reg);
385  } else {
386  PrintDRegister(reg);
387  }
388 
389  return retval;
390 }
391 
392 
393 int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) {
394  Print(format);
395  return 0;
396 }
397 
398 
399 void Decoder::FormatNeonList(int Vd, int type) {
400  if (type == nlt_1) {
401  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
402  "{d%d}", Vd);
403  } else if (type == nlt_2) {
404  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
405  "{d%d, d%d}", Vd, Vd + 1);
406  } else if (type == nlt_3) {
407  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
408  "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2);
409  } else if (type == nlt_4) {
410  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
411  "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3);
412  }
413 }
414 
415 
416 void Decoder::FormatNeonMemory(int Rn, int align, int Rm) {
417  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
418  "[r%d", Rn);
419  if (align != 0) {
420  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
421  ":%d", (1 << align) << 6);
422  }
423  if (Rm == 15) {
424  Print("]");
425  } else if (Rm == 13) {
426  Print("]!");
427  } else {
428  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
429  "], r%d", Rm);
430  }
431 }
432 
433 
434 // Print the movw or movt instruction.
435 void Decoder::PrintMovwMovt(Instruction* instr) {
436  int imm = instr->ImmedMovwMovtValue();
437  int rd = instr->RdValue();
438  PrintRegister(rd);
439  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm);
440 }
441 
442 
443 // FormatOption takes a formatting string and interprets it based on
444 // the current instructions. The format string points to the first
445 // character of the option string (the option escape has already been
446 // consumed by the caller.) FormatOption returns the number of
447 // characters that were consumed from the formatting string.
448 int Decoder::FormatOption(Instruction* instr, const char* format) {
449  switch (format[0]) {
450  case 'a': { // 'a: accumulate multiplies
451  if (instr->Bit(21) == 0) {
452  Print("ul");
453  } else {
454  Print("la");
455  }
456  return 1;
457  }
458  case 'b': { // 'b: byte loads or stores
459  if (instr->HasB()) {
460  Print("b");
461  }
462  return 1;
463  }
464  case 'c': { // 'cond: conditional execution
465  DCHECK(STRING_STARTS_WITH(format, "cond"));
466  PrintCondition(instr);
467  return 4;
468  }
469  case 'd': { // 'd: vmov double immediate.
470  double d = instr->DoubleImmedVmov();
471  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d);
472  return 1;
473  }
474  case 'f': { // 'f: bitfield instructions - v7 and above.
475  uint32_t lsbit = instr->Bits(11, 7);
476  uint32_t width = instr->Bits(20, 16) + 1;
477  if (instr->Bit(21) == 0) {
478  // BFC/BFI:
479  // Bits 20-16 represent most-significant bit. Covert to width.
480  width -= lsbit;
481  DCHECK(width > 0);
482  }
483  DCHECK((width + lsbit) <= 32);
484  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
485  "#%d, #%d", lsbit, width);
486  return 1;
487  }
488  case 'h': { // 'h: halfword operation for extra loads and stores
489  if (instr->HasH()) {
490  Print("h");
491  } else {
492  Print("b");
493  }
494  return 1;
495  }
496  case 'i': { // 'i: immediate value from adjacent bits.
497  // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16
498  int width = (format[3] - '0') * 10 + (format[4] - '0');
499  int lsb = (format[6] - '0') * 10 + (format[7] - '0');
500 
501  DCHECK((width >= 1) && (width <= 32));
502  DCHECK((lsb >= 0) && (lsb <= 31));
503  DCHECK((width + lsb) <= 32);
504 
505  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
506  "%d",
507  instr->Bits(width + lsb - 1, lsb));
508  return 8;
509  }
510  case 'l': { // 'l: branch and link
511  if (instr->HasLink()) {
512  Print("l");
513  }
514  return 1;
515  }
516  case 'm': {
517  if (format[1] == 'w') {
518  // 'mw: movt/movw instructions.
519  PrintMovwMovt(instr);
520  return 2;
521  }
522  if (format[1] == 'e') { // 'memop: load/store instructions.
523  DCHECK(STRING_STARTS_WITH(format, "memop"));
524  if (instr->HasL()) {
525  Print("ldr");
526  } else {
527  if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) &&
528  (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) {
529  if (instr->Bit(5) == 1) {
530  Print("strd");
531  } else {
532  Print("ldrd");
533  }
534  return 5;
535  }
536  Print("str");
537  }
538  return 5;
539  }
540  // 'msg: for simulator break instructions
541  DCHECK(STRING_STARTS_WITH(format, "msg"));
542  byte* str =
543  reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
544  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
545  "%s", converter_.NameInCode(str));
546  return 3;
547  }
548  case 'o': {
549  if ((format[3] == '1') && (format[4] == '2')) {
550  // 'off12: 12-bit offset for load and store instructions
551  DCHECK(STRING_STARTS_WITH(format, "off12"));
552  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
553  "%d", instr->Offset12Value());
554  return 5;
555  } else if (format[3] == '0') {
556  // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
557  DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19"));
558  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
559  "%d",
560  (instr->Bits(19, 8) << 4) +
561  instr->Bits(3, 0));
562  return 15;
563  }
564  // 'off8: 8-bit offset for extra load and store instructions
565  DCHECK(STRING_STARTS_WITH(format, "off8"));
566  int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
567  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8);
568  return 4;
569  }
570  case 'p': { // 'pu: P and U bits for load and store instructions
571  DCHECK(STRING_STARTS_WITH(format, "pu"));
572  PrintPU(instr);
573  return 2;
574  }
575  case 'r': {
576  return FormatRegister(instr, format);
577  }
578  case 's': {
579  if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat.
580  if (format[6] == 'o') { // 'shift_op
581  DCHECK(STRING_STARTS_WITH(format, "shift_op"));
582  if (instr->TypeValue() == 0) {
583  PrintShiftRm(instr);
584  } else {
585  DCHECK(instr->TypeValue() == 1);
586  PrintShiftImm(instr);
587  }
588  return 8;
589  } else if (format[6] == 's') { // 'shift_sat.
590  DCHECK(STRING_STARTS_WITH(format, "shift_sat"));
591  PrintShiftSat(instr);
592  return 9;
593  } else { // 'shift_rm
594  DCHECK(STRING_STARTS_WITH(format, "shift_rm"));
595  PrintShiftRm(instr);
596  return 8;
597  }
598  } else if (format[1] == 'v') { // 'svc
599  DCHECK(STRING_STARTS_WITH(format, "svc"));
600  PrintSoftwareInterrupt(instr->SvcValue());
601  return 3;
602  } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
603  DCHECK(STRING_STARTS_WITH(format, "sign"));
604  if (instr->HasSign()) {
605  Print("s");
606  }
607  return 4;
608  }
609  // 's: S field of data processing instructions
610  if (instr->HasS()) {
611  Print("s");
612  }
613  return 1;
614  }
615  case 't': { // 'target: target of branch instructions
616  DCHECK(STRING_STARTS_WITH(format, "target"));
617  int off = (instr->SImmed24Value() << 2) + 8;
618  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
619  "%+d -> %s",
620  off,
621  converter_.NameOfAddress(
622  reinterpret_cast<byte*>(instr) + off));
623  return 6;
624  }
625  case 'u': { // 'u: signed or unsigned multiplies
626  // The manual gets the meaning of bit 22 backwards in the multiply
627  // instruction overview on page A3.16.2. The instructions that
628  // exist in u and s variants are the following:
629  // smull A4.1.87
630  // umull A4.1.129
631  // umlal A4.1.128
632  // smlal A4.1.76
633  // For these 0 means u and 1 means s. As can be seen on their individual
634  // pages. The other 18 mul instructions have the bit set or unset in
635  // arbitrary ways that are unrelated to the signedness of the instruction.
636  // None of these 18 instructions exist in both a 'u' and an 's' variant.
637 
638  if (instr->Bit(22) == 0) {
639  Print("u");
640  } else {
641  Print("s");
642  }
643  return 1;
644  }
645  case 'v': {
646  return FormatVFPinstruction(instr, format);
647  }
648  case 'S':
649  case 'D': {
650  return FormatVFPRegister(instr, format);
651  }
652  case 'w': { // 'w: W field of load and store instructions
653  if (instr->HasW()) {
654  Print("!");
655  }
656  return 1;
657  }
658  default: {
659  UNREACHABLE();
660  break;
661  }
662  }
663  UNREACHABLE();
664  return -1;
665 }
666 
667 
668 // Format takes a formatting string for a whole instruction and prints it into
669 // the output buffer. All escaped options are handed to FormatOption to be
670 // parsed further.
671 void Decoder::Format(Instruction* instr, const char* format) {
672  char cur = *format++;
673  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
674  if (cur == '\'') { // Single quote is used as the formatting escape.
675  format += FormatOption(instr, format);
676  } else {
677  out_buffer_[out_buffer_pos_++] = cur;
678  }
679  cur = *format++;
680  }
681  out_buffer_[out_buffer_pos_] = '\0';
682 }
683 
684 
685 // The disassembler may end up decoding data inlined in the code. We do not want
686 // it to crash if the data does not ressemble any known instruction.
687 #define VERIFY(condition) \
688 if(!(condition)) { \
689  Unknown(instr); \
690  return; \
691 }
692 
693 
694 // For currently unimplemented decodings the disassembler calls Unknown(instr)
695 // which will just print "unknown" of the instruction bits.
696 void Decoder::Unknown(Instruction* instr) {
697  Format(instr, "unknown");
698 }
699 
700 
701 void Decoder::DecodeType01(Instruction* instr) {
702  int type = instr->TypeValue();
703  if ((type == 0) && instr->IsSpecialType0()) {
704  // multiply instruction or extra loads and stores
705  if (instr->Bits(7, 4) == 9) {
706  if (instr->Bit(24) == 0) {
707  // multiply instructions
708  if (instr->Bit(23) == 0) {
709  if (instr->Bit(21) == 0) {
710  // The MUL instruction description (A 4.1.33) refers to Rd as being
711  // the destination for the operation, but it confusingly uses the
712  // Rn field to encode it.
713  Format(instr, "mul'cond's 'rn, 'rm, 'rs");
714  } else {
715  if (instr->Bit(22) == 0) {
716  // The MLA instruction description (A 4.1.28) refers to the order
717  // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
718  // Rn field to encode the Rd register and the Rd field to encode
719  // the Rn register.
720  Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
721  } else {
722  // The MLS instruction description (A 4.1.29) refers to the order
723  // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
724  // Rn field to encode the Rd register and the Rd field to encode
725  // the Rn register.
726  Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
727  }
728  }
729  } else {
730  // The signed/long multiply instructions use the terms RdHi and RdLo
731  // when referring to the target registers. They are mapped to the Rn
732  // and Rd fields as follows:
733  // RdLo == Rd field
734  // RdHi == Rn field
735  // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
736  Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
737  }
738  } else {
739  Unknown(instr); // not used by V8
740  }
741  } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
742  // ldrd, strd
743  switch (instr->PUField()) {
744  case da_x: {
745  if (instr->Bit(22) == 0) {
746  Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
747  } else {
748  Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
749  }
750  break;
751  }
752  case ia_x: {
753  if (instr->Bit(22) == 0) {
754  Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
755  } else {
756  Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
757  }
758  break;
759  }
760  case db_x: {
761  if (instr->Bit(22) == 0) {
762  Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
763  } else {
764  Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
765  }
766  break;
767  }
768  case ib_x: {
769  if (instr->Bit(22) == 0) {
770  Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
771  } else {
772  Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
773  }
774  break;
775  }
776  default: {
777  // The PU field is a 2-bit field.
778  UNREACHABLE();
779  break;
780  }
781  }
782  } else {
783  // extra load/store instructions
784  switch (instr->PUField()) {
785  case da_x: {
786  if (instr->Bit(22) == 0) {
787  Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
788  } else {
789  Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
790  }
791  break;
792  }
793  case ia_x: {
794  if (instr->Bit(22) == 0) {
795  Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
796  } else {
797  Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
798  }
799  break;
800  }
801  case db_x: {
802  if (instr->Bit(22) == 0) {
803  Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
804  } else {
805  Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
806  }
807  break;
808  }
809  case ib_x: {
810  if (instr->Bit(22) == 0) {
811  Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
812  } else {
813  Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
814  }
815  break;
816  }
817  default: {
818  // The PU field is a 2-bit field.
819  UNREACHABLE();
820  break;
821  }
822  }
823  return;
824  }
825  } else if ((type == 0) && instr->IsMiscType0()) {
826  if (instr->Bits(22, 21) == 1) {
827  switch (instr->BitField(7, 4)) {
828  case BX:
829  Format(instr, "bx'cond 'rm");
830  break;
831  case BLX:
832  Format(instr, "blx'cond 'rm");
833  break;
834  case BKPT:
835  Format(instr, "bkpt 'off0to3and8to19");
836  break;
837  default:
838  Unknown(instr); // not used by V8
839  break;
840  }
841  } else if (instr->Bits(22, 21) == 3) {
842  switch (instr->BitField(7, 4)) {
843  case CLZ:
844  Format(instr, "clz'cond 'rd, 'rm");
845  break;
846  default:
847  Unknown(instr); // not used by V8
848  break;
849  }
850  } else {
851  Unknown(instr); // not used by V8
852  }
853  } else if ((type == 1) && instr->IsNopType1()) {
854  Format(instr, "nop'cond");
855  } else {
856  switch (instr->OpcodeField()) {
857  case AND: {
858  Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
859  break;
860  }
861  case EOR: {
862  Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
863  break;
864  }
865  case SUB: {
866  Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
867  break;
868  }
869  case RSB: {
870  Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
871  break;
872  }
873  case ADD: {
874  Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
875  break;
876  }
877  case ADC: {
878  Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
879  break;
880  }
881  case SBC: {
882  Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
883  break;
884  }
885  case RSC: {
886  Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
887  break;
888  }
889  case TST: {
890  if (instr->HasS()) {
891  Format(instr, "tst'cond 'rn, 'shift_op");
892  } else {
893  Format(instr, "movw'cond 'mw");
894  }
895  break;
896  }
897  case TEQ: {
898  if (instr->HasS()) {
899  Format(instr, "teq'cond 'rn, 'shift_op");
900  } else {
901  // Other instructions matching this pattern are handled in the
902  // miscellaneous instructions part above.
903  UNREACHABLE();
904  }
905  break;
906  }
907  case CMP: {
908  if (instr->HasS()) {
909  Format(instr, "cmp'cond 'rn, 'shift_op");
910  } else {
911  Format(instr, "movt'cond 'mw");
912  }
913  break;
914  }
915  case CMN: {
916  if (instr->HasS()) {
917  Format(instr, "cmn'cond 'rn, 'shift_op");
918  } else {
919  // Other instructions matching this pattern are handled in the
920  // miscellaneous instructions part above.
921  UNREACHABLE();
922  }
923  break;
924  }
925  case ORR: {
926  Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
927  break;
928  }
929  case MOV: {
930  Format(instr, "mov'cond's 'rd, 'shift_op");
931  break;
932  }
933  case BIC: {
934  Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
935  break;
936  }
937  case MVN: {
938  Format(instr, "mvn'cond's 'rd, 'shift_op");
939  break;
940  }
941  default: {
942  // The Opcode field is a 4-bit field.
943  UNREACHABLE();
944  break;
945  }
946  }
947  }
948 }
949 
950 
951 void Decoder::DecodeType2(Instruction* instr) {
952  switch (instr->PUField()) {
953  case da_x: {
954  if (instr->HasW()) {
955  Unknown(instr); // not used in V8
956  return;
957  }
958  Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
959  break;
960  }
961  case ia_x: {
962  if (instr->HasW()) {
963  Unknown(instr); // not used in V8
964  return;
965  }
966  Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
967  break;
968  }
969  case db_x: {
970  Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
971  break;
972  }
973  case ib_x: {
974  Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
975  break;
976  }
977  default: {
978  // The PU field is a 2-bit field.
979  UNREACHABLE();
980  break;
981  }
982  }
983 }
984 
985 
986 void Decoder::DecodeType3(Instruction* instr) {
987  switch (instr->PUField()) {
988  case da_x: {
989  VERIFY(!instr->HasW());
990  Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
991  break;
992  }
993  case ia_x: {
994  if (instr->Bit(4) == 0) {
995  Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
996  } else {
997  if (instr->Bit(5) == 0) {
998  switch (instr->Bits(22, 21)) {
999  case 0:
1000  if (instr->Bit(20) == 0) {
1001  if (instr->Bit(6) == 0) {
1002  Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
1003  } else {
1004  if (instr->Bits(11, 7) == 0) {
1005  Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
1006  } else {
1007  Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
1008  }
1009  }
1010  } else {
1011  UNREACHABLE();
1012  }
1013  break;
1014  case 1:
1015  UNREACHABLE();
1016  break;
1017  case 2:
1018  UNREACHABLE();
1019  break;
1020  case 3:
1021  Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
1022  break;
1023  }
1024  } else {
1025  switch (instr->Bits(22, 21)) {
1026  case 0:
1027  UNREACHABLE();
1028  break;
1029  case 1:
1030  UNREACHABLE();
1031  break;
1032  case 2:
1033  if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
1034  if (instr->Bits(19, 16) == 0xF) {
1035  switch (instr->Bits(11, 10)) {
1036  case 0:
1037  Format(instr, "uxtb16'cond 'rd, 'rm");
1038  break;
1039  case 1:
1040  Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
1041  break;
1042  case 2:
1043  Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
1044  break;
1045  case 3:
1046  Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
1047  break;
1048  }
1049  } else {
1050  UNREACHABLE();
1051  }
1052  } else {
1053  UNREACHABLE();
1054  }
1055  break;
1056  case 3:
1057  if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
1058  if (instr->Bits(19, 16) == 0xF) {
1059  switch (instr->Bits(11, 10)) {
1060  case 0:
1061  Format(instr, "uxtb'cond 'rd, 'rm");
1062  break;
1063  case 1:
1064  Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
1065  break;
1066  case 2:
1067  Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
1068  break;
1069  case 3:
1070  Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
1071  break;
1072  }
1073  } else {
1074  switch (instr->Bits(11, 10)) {
1075  case 0:
1076  Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
1077  break;
1078  case 1:
1079  Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
1080  break;
1081  case 2:
1082  Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
1083  break;
1084  case 3:
1085  Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
1086  break;
1087  }
1088  }
1089  } else {
1090  UNREACHABLE();
1091  }
1092  break;
1093  }
1094  }
1095  }
1096  break;
1097  }
1098  case db_x: {
1099  if (FLAG_enable_sudiv) {
1100  if (instr->Bits(5, 4) == 0x1) {
1101  if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
1102  if (instr->Bit(21) == 0x1) {
1103  // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1104  Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
1105  } else {
1106  // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1107  Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
1108  }
1109  break;
1110  }
1111  }
1112  }
1113  Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1114  break;
1115  }
1116  case ib_x: {
1117  if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1118  uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1119  uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1120  uint32_t msbit = widthminus1 + lsbit;
1121  if (msbit <= 31) {
1122  if (instr->Bit(22)) {
1123  Format(instr, "ubfx'cond 'rd, 'rm, 'f");
1124  } else {
1125  Format(instr, "sbfx'cond 'rd, 'rm, 'f");
1126  }
1127  } else {
1128  UNREACHABLE();
1129  }
1130  } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
1131  uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1132  uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
1133  if (msbit >= lsbit) {
1134  if (instr->RmValue() == 15) {
1135  Format(instr, "bfc'cond 'rd, 'f");
1136  } else {
1137  Format(instr, "bfi'cond 'rd, 'rm, 'f");
1138  }
1139  } else {
1140  UNREACHABLE();
1141  }
1142  } else {
1143  Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1144  }
1145  break;
1146  }
1147  default: {
1148  // The PU field is a 2-bit field.
1149  UNREACHABLE();
1150  break;
1151  }
1152  }
1153 }
1154 
1155 
1156 void Decoder::DecodeType4(Instruction* instr) {
1157  if (instr->Bit(22) != 0) {
1158  // Privileged mode currently not supported.
1159  Unknown(instr);
1160  } else {
1161  if (instr->HasL()) {
1162  Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1163  } else {
1164  Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1165  }
1166  }
1167 }
1168 
1169 
1170 void Decoder::DecodeType5(Instruction* instr) {
1171  Format(instr, "b'l'cond 'target");
1172 }
1173 
1174 
1175 void Decoder::DecodeType6(Instruction* instr) {
1176  DecodeType6CoprocessorIns(instr);
1177 }
1178 
1179 
1180 int Decoder::DecodeType7(Instruction* instr) {
1181  if (instr->Bit(24) == 1) {
1182  if (instr->SvcValue() >= kStopCode) {
1183  Format(instr, "stop'cond 'svc");
1184  // Also print the stop message. Its address is encoded
1185  // in the following 4 bytes.
1186  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1187  "\n %p %08x stop message: %s",
1188  reinterpret_cast<void*>(instr
1190  *reinterpret_cast<uint32_t*>(instr
1192  *reinterpret_cast<char**>(instr
1194  // We have decoded 2 * Instruction::kInstrSize bytes.
1195  return 2 * Instruction::kInstrSize;
1196  } else {
1197  Format(instr, "svc'cond 'svc");
1198  }
1199  } else {
1200  DecodeTypeVFP(instr);
1201  }
1202  return Instruction::kInstrSize;
1203 }
1204 
1205 
1206 // void Decoder::DecodeTypeVFP(Instruction* instr)
1207 // vmov: Sn = Rt
1208 // vmov: Rt = Sn
1209 // vcvt: Dd = Sm
1210 // vcvt: Sd = Dm
1211 // vcvt.f64.s32 Dd, Dd, #<fbits>
1212 // Dd = vabs(Dm)
1213 // Dd = vneg(Dm)
1214 // Dd = vadd(Dn, Dm)
1215 // Dd = vsub(Dn, Dm)
1216 // Dd = vmul(Dn, Dm)
1217 // Dd = vmla(Dn, Dm)
1218 // Dd = vmls(Dn, Dm)
1219 // Dd = vdiv(Dn, Dm)
1220 // vcmp(Dd, Dm)
1221 // vmrs
1222 // vmsr
1223 // Dd = vsqrt(Dm)
1224 void Decoder::DecodeTypeVFP(Instruction* instr) {
1225  VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
1226  VERIFY(instr->Bits(11, 9) == 0x5);
1227 
1228  if (instr->Bit(4) == 0) {
1229  if (instr->Opc1Value() == 0x7) {
1230  // Other data processing instructions
1231  if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
1232  // vmov register to register.
1233  if (instr->SzValue() == 0x1) {
1234  Format(instr, "vmov'cond.f64 'Dd, 'Dm");
1235  } else {
1236  Format(instr, "vmov'cond.f32 'Sd, 'Sm");
1237  }
1238  } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
1239  // vabs
1240  Format(instr, "vabs'cond.f64 'Dd, 'Dm");
1241  } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
1242  // vneg
1243  Format(instr, "vneg'cond.f64 'Dd, 'Dm");
1244  } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
1245  DecodeVCVTBetweenDoubleAndSingle(instr);
1246  } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
1247  DecodeVCVTBetweenFloatingPointAndInteger(instr);
1248  } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
1249  (instr->Bit(8) == 1)) {
1250  // vcvt.f64.s32 Dd, Dd, #<fbits>
1251  int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
1252  Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
1253  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1254  ", #%d", fraction_bits);
1255  } else if (((instr->Opc2Value() >> 1) == 0x6) &&
1256  (instr->Opc3Value() & 0x1)) {
1257  DecodeVCVTBetweenFloatingPointAndInteger(instr);
1258  } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1259  (instr->Opc3Value() & 0x1)) {
1260  DecodeVCMP(instr);
1261  } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
1262  Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
1263  } else if (instr->Opc3Value() == 0x0) {
1264  if (instr->SzValue() == 0x1) {
1265  Format(instr, "vmov'cond.f64 'Dd, 'd");
1266  } else {
1267  Unknown(instr); // Not used by V8.
1268  }
1269  } else {
1270  Unknown(instr); // Not used by V8.
1271  }
1272  } else if (instr->Opc1Value() == 0x3) {
1273  if (instr->SzValue() == 0x1) {
1274  if (instr->Opc3Value() & 0x1) {
1275  Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
1276  } else {
1277  Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
1278  }
1279  } else {
1280  Unknown(instr); // Not used by V8.
1281  }
1282  } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
1283  if (instr->SzValue() == 0x1) {
1284  Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
1285  } else {
1286  Unknown(instr); // Not used by V8.
1287  }
1288  } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
1289  if (instr->SzValue() == 0x1) {
1290  Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
1291  } else {
1292  Unknown(instr); // Not used by V8.
1293  }
1294  } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
1295  if (instr->SzValue() == 0x1) {
1296  Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
1297  } else {
1298  Unknown(instr); // Not used by V8.
1299  }
1300  } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
1301  if (instr->SzValue() == 0x1) {
1302  Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
1303  } else {
1304  Unknown(instr); // Not used by V8.
1305  }
1306  } else {
1307  Unknown(instr); // Not used by V8.
1308  }
1309  } else {
1310  if ((instr->VCValue() == 0x0) &&
1311  (instr->VAValue() == 0x0)) {
1312  DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1313  } else if ((instr->VLValue() == 0x0) &&
1314  (instr->VCValue() == 0x1) &&
1315  (instr->Bit(23) == 0x0)) {
1316  if (instr->Bit(21) == 0x0) {
1317  Format(instr, "vmov'cond.32 'Dd[0], 'rt");
1318  } else {
1319  Format(instr, "vmov'cond.32 'Dd[1], 'rt");
1320  }
1321  } else if ((instr->VLValue() == 0x1) &&
1322  (instr->VCValue() == 0x1) &&
1323  (instr->Bit(23) == 0x0)) {
1324  if (instr->Bit(21) == 0x0) {
1325  Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
1326  } else {
1327  Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
1328  }
1329  } else if ((instr->VCValue() == 0x0) &&
1330  (instr->VAValue() == 0x7) &&
1331  (instr->Bits(19, 16) == 0x1)) {
1332  if (instr->VLValue() == 0) {
1333  if (instr->Bits(15, 12) == 0xF) {
1334  Format(instr, "vmsr'cond FPSCR, APSR");
1335  } else {
1336  Format(instr, "vmsr'cond FPSCR, 'rt");
1337  }
1338  } else {
1339  if (instr->Bits(15, 12) == 0xF) {
1340  Format(instr, "vmrs'cond APSR, FPSCR");
1341  } else {
1342  Format(instr, "vmrs'cond 'rt, FPSCR");
1343  }
1344  }
1345  }
1346  }
1347 }
1348 
1349 
1350 void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
1351  Instruction* instr) {
1352  VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
1353  (instr->VAValue() == 0x0));
1354 
1355  bool to_arm_register = (instr->VLValue() == 0x1);
1356 
1357  if (to_arm_register) {
1358  Format(instr, "vmov'cond 'rt, 'Sn");
1359  } else {
1360  Format(instr, "vmov'cond 'Sn, 'rt");
1361  }
1362 }
1363 
1364 
1365 void Decoder::DecodeVCMP(Instruction* instr) {
1366  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1367  VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1368  (instr->Opc3Value() & 0x1));
1369 
1370  // Comparison.
1371  bool dp_operation = (instr->SzValue() == 1);
1372  bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1373 
1374  if (dp_operation && !raise_exception_for_qnan) {
1375  if (instr->Opc2Value() == 0x4) {
1376  Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
1377  } else if (instr->Opc2Value() == 0x5) {
1378  Format(instr, "vcmp'cond.f64 'Dd, #0.0");
1379  } else {
1380  Unknown(instr); // invalid
1381  }
1382  } else {
1383  Unknown(instr); // Not used by V8.
1384  }
1385 }
1386 
1387 
1388 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
1389  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1390  VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
1391 
1392  bool double_to_single = (instr->SzValue() == 1);
1393 
1394  if (double_to_single) {
1395  Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
1396  } else {
1397  Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
1398  }
1399 }
1400 
1401 
1402 void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
1403  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1404  VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
1405  (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
1406 
1407  bool to_integer = (instr->Bit(18) == 1);
1408  bool dp_operation = (instr->SzValue() == 1);
1409  if (to_integer) {
1410  bool unsigned_integer = (instr->Bit(16) == 0);
1411 
1412  if (dp_operation) {
1413  if (unsigned_integer) {
1414  Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
1415  } else {
1416  Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
1417  }
1418  } else {
1419  if (unsigned_integer) {
1420  Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
1421  } else {
1422  Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
1423  }
1424  }
1425  } else {
1426  bool unsigned_integer = (instr->Bit(7) == 0);
1427 
1428  if (dp_operation) {
1429  if (unsigned_integer) {
1430  Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
1431  } else {
1432  Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
1433  }
1434  } else {
1435  if (unsigned_integer) {
1436  Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
1437  } else {
1438  Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
1439  }
1440  }
1441  }
1442 }
1443 
1444 
1445 // Decode Type 6 coprocessor instructions.
1446 // Dm = vmov(Rt, Rt2)
1447 // <Rt, Rt2> = vmov(Dm)
1448 // Ddst = MEM(Rbase + 4*offset).
1449 // MEM(Rbase + 4*offset) = Dsrc.
1450 void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
1451  VERIFY(instr->TypeValue() == 6);
1452 
1453  if (instr->CoprocessorValue() == 0xA) {
1454  switch (instr->OpcodeValue()) {
1455  case 0x8:
1456  case 0xA:
1457  if (instr->HasL()) {
1458  Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1459  } else {
1460  Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1461  }
1462  break;
1463  case 0xC:
1464  case 0xE:
1465  if (instr->HasL()) {
1466  Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1467  } else {
1468  Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1469  }
1470  break;
1471  case 0x4:
1472  case 0x5:
1473  case 0x6:
1474  case 0x7:
1475  case 0x9:
1476  case 0xB: {
1477  bool to_vfp_register = (instr->VLValue() == 0x1);
1478  if (to_vfp_register) {
1479  Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
1480  } else {
1481  Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
1482  }
1483  break;
1484  }
1485  default:
1486  Unknown(instr); // Not used by V8.
1487  }
1488  } else if (instr->CoprocessorValue() == 0xB) {
1489  switch (instr->OpcodeValue()) {
1490  case 0x2:
1491  // Load and store double to two GP registers
1492  if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
1493  Unknown(instr); // Not used by V8.
1494  } else if (instr->HasL()) {
1495  Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1496  } else {
1497  Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1498  }
1499  break;
1500  case 0x8:
1501  case 0xA:
1502  if (instr->HasL()) {
1503  Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1504  } else {
1505  Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1506  }
1507  break;
1508  case 0xC:
1509  case 0xE:
1510  if (instr->HasL()) {
1511  Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1512  } else {
1513  Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1514  }
1515  break;
1516  case 0x4:
1517  case 0x5:
1518  case 0x6:
1519  case 0x7:
1520  case 0x9:
1521  case 0xB: {
1522  bool to_vfp_register = (instr->VLValue() == 0x1);
1523  if (to_vfp_register) {
1524  Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
1525  } else {
1526  Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
1527  }
1528  break;
1529  }
1530  default:
1531  Unknown(instr); // Not used by V8.
1532  }
1533  } else {
1534  Unknown(instr); // Not used by V8.
1535  }
1536 }
1537 
1538 
1539 void Decoder::DecodeSpecialCondition(Instruction* instr) {
1540  switch (instr->SpecialValue()) {
1541  case 5:
1542  if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
1543  (instr->Bit(4) == 1)) {
1544  // vmovl signed
1545  if ((instr->VdValue() & 1) != 0) Unknown(instr);
1546  int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
1547  int Vm = (instr->Bit(5) << 4) | instr->VmValue();
1548  int imm3 = instr->Bits(21, 19);
1549  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1550  "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm);
1551  } else {
1552  Unknown(instr);
1553  }
1554  break;
1555  case 7:
1556  if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
1557  (instr->Bit(4) == 1)) {
1558  // vmovl unsigned
1559  if ((instr->VdValue() & 1) != 0) Unknown(instr);
1560  int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
1561  int Vm = (instr->Bit(5) << 4) | instr->VmValue();
1562  int imm3 = instr->Bits(21, 19);
1563  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1564  "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm);
1565  } else {
1566  Unknown(instr);
1567  }
1568  break;
1569  case 8:
1570  if (instr->Bits(21, 20) == 0) {
1571  // vst1
1572  int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1573  int Rn = instr->VnValue();
1574  int type = instr->Bits(11, 8);
1575  int size = instr->Bits(7, 6);
1576  int align = instr->Bits(5, 4);
1577  int Rm = instr->VmValue();
1578  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1579  "vst1.%d ", (1 << size) << 3);
1580  FormatNeonList(Vd, type);
1581  Print(", ");
1582  FormatNeonMemory(Rn, align, Rm);
1583  } else if (instr->Bits(21, 20) == 2) {
1584  // vld1
1585  int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1586  int Rn = instr->VnValue();
1587  int type = instr->Bits(11, 8);
1588  int size = instr->Bits(7, 6);
1589  int align = instr->Bits(5, 4);
1590  int Rm = instr->VmValue();
1591  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1592  "vld1.%d ", (1 << size) << 3);
1593  FormatNeonList(Vd, type);
1594  Print(", ");
1595  FormatNeonMemory(Rn, align, Rm);
1596  } else {
1597  Unknown(instr);
1598  }
1599  break;
1600  case 0xA:
1601  case 0xB:
1602  if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
1603  int Rn = instr->Bits(19, 16);
1604  int offset = instr->Bits(11, 0);
1605  if (offset == 0) {
1606  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1607  "pld [r%d]", Rn);
1608  } else if (instr->Bit(23) == 0) {
1609  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1610  "pld [r%d, #-%d]", Rn, offset);
1611  } else {
1612  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1613  "pld [r%d, #+%d]", Rn, offset);
1614  }
1615  } else {
1616  Unknown(instr);
1617  }
1618  break;
1619  default:
1620  Unknown(instr);
1621  break;
1622  }
1623 }
1624 
1625 #undef VERIFIY
1626 
1627 bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
1628  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1629  return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
1630 }
1631 
1632 
1633 int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
1634  if (IsConstantPoolAt(instr_ptr)) {
1635  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1636  return DecodeConstantPoolLength(instruction_bits);
1637  } else {
1638  return -1;
1639  }
1640 }
1641 
1642 
1643 // Disassemble the instruction at *instr_ptr into the output buffer.
1644 int Decoder::InstructionDecode(byte* instr_ptr) {
1645  Instruction* instr = Instruction::At(instr_ptr);
1646  // Print raw instruction bytes.
1647  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1648  "%08x ",
1649  instr->InstructionBits());
1650  if (instr->ConditionField() == kSpecialCondition) {
1651  DecodeSpecialCondition(instr);
1652  return Instruction::kInstrSize;
1653  }
1654  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1655  if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
1656  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1657  "constant pool begin (length %d)",
1658  DecodeConstantPoolLength(instruction_bits));
1659  return Instruction::kInstrSize;
1660  } else if (instruction_bits == kCodeAgeJumpInstruction) {
1661  // The code age prologue has a constant immediatly following the jump
1662  // instruction.
1663  Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize);
1664  DecodeType2(instr);
1665  SNPrintF(out_buffer_ + out_buffer_pos_,
1666  " (0x%08x)", target->InstructionBits());
1667  return 2 * Instruction::kInstrSize;
1668  }
1669  switch (instr->TypeValue()) {
1670  case 0:
1671  case 1: {
1672  DecodeType01(instr);
1673  break;
1674  }
1675  case 2: {
1676  DecodeType2(instr);
1677  break;
1678  }
1679  case 3: {
1680  DecodeType3(instr);
1681  break;
1682  }
1683  case 4: {
1684  DecodeType4(instr);
1685  break;
1686  }
1687  case 5: {
1688  DecodeType5(instr);
1689  break;
1690  }
1691  case 6: {
1692  DecodeType6(instr);
1693  break;
1694  }
1695  case 7: {
1696  return DecodeType7(instr);
1697  }
1698  default: {
1699  // The type field is 3-bits in the ARM encoding.
1700  UNREACHABLE();
1701  break;
1702  }
1703  }
1704  return Instruction::kInstrSize;
1705 }
1706 
1707 
1708 } } // namespace v8::internal
1709 
1710 
1711 
1712 //------------------------------------------------------------------------------
1713 
1714 namespace disasm {
1715 
1716 
1717 const char* NameConverter::NameOfAddress(byte* addr) const {
1718  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1719  return tmp_buffer_.start();
1720 }
1721 
1722 
1723 const char* NameConverter::NameOfConstant(byte* addr) const {
1724  return NameOfAddress(addr);
1725 }
1726 
1727 
1728 const char* NameConverter::NameOfCPURegister(int reg) const {
1729  return v8::internal::Registers::Name(reg);
1730 }
1731 
1732 
1733 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1734  UNREACHABLE(); // ARM does not have the concept of a byte register
1735  return "nobytereg";
1736 }
1737 
1738 
1739 const char* NameConverter::NameOfXMMRegister(int reg) const {
1740  UNREACHABLE(); // ARM does not have any XMM registers
1741  return "noxmmreg";
1742 }
1743 
1744 
1745 const char* NameConverter::NameInCode(byte* addr) const {
1746  // The default name converter is called for unknown code. So we will not try
1747  // to access any memory.
1748  return "";
1749 }
1750 
1751 
1752 //------------------------------------------------------------------------------
1753 
1754 Disassembler::Disassembler(const NameConverter& converter)
1755  : converter_(converter) {}
1756 
1757 
1758 Disassembler::~Disassembler() {}
1759 
1760 
1761 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1762  byte* instruction) {
1763  v8::internal::Decoder d(converter_, buffer);
1764  return d.InstructionDecode(instruction);
1765 }
1766 
1767 
1768 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1769  return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
1770 }
1771 
1772 
1773 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1774  NameConverter converter;
1775  Disassembler d(converter);
1776  for (byte* pc = begin; pc < end;) {
1778  buffer[0] = '\0';
1779  byte* prev_pc = pc;
1780  pc += d.InstructionDecode(buffer, pc);
1782  f, "%p %08x %s\n",
1783  prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1784  }
1785 }
1786 
1787 
1788 } // namespace disasm
1789 
1790 #endif // V8_TARGET_ARCH_ARM
Disassembler(const NameConverter &converter)
v8::internal::EmbeddedVector< char, 128 > tmp_buffer_
Definition: disasm.h:26
virtual const char * NameInCode(byte *addr) const
virtual const char * NameOfByteCPURegister(int reg) const
virtual const char * NameOfXMMRegister(int reg) const
virtual const char * NameOfAddress(byte *addr) const
virtual const char * NameOfCPURegister(int reg) const
virtual const char * NameOfConstant(byte *addr) const
static Instruction * At(byte *pc)
static const char * Name(int reg)
static const char * Name(int reg, bool is_double)
T * start() const
Definition: vector.h:47
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array shift
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:244
Definition: disasm.h:8
int int32_t
Definition: unicode.cc:24
int DecodeConstantPoolLength(int instr)
Definition: constants-arm.h:25
int SNPrintF(Vector< char > str, const char *format,...)
Definition: utils.cc:105
const int kCodeAgeJumpInstruction
Definition: constants-arm.h:31
const Register pc
const int kConstantPoolMarkerMask
Definition: constants-arm.h:18
void PrintF(const char *format,...)
Definition: utils.cc:80
const int kConstantPoolMarker
Definition: constants-arm.h:19
const uint32_t kStopCodeMask
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20