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