V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
disasm-arm.cc
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 #if V8_TARGET_ARCH_ARM
32 
33 #include "src/arm/constants-arm.h"
34 #include "src/base/bits.h"
35 #include "src/base/platform/platform.h"
36 #include "src/disasm.h"
37 #include "src/macro-assembler.h"
38 
39 namespace v8 {
40 namespace internal {
41 
42 //------------------------------------------------------------------------------
43 
44 // Decoder decodes and disassembles instructions into an output buffer.
45 // It uses the converter to convert register names and call destinations into
46 // more informative description.
47 class Decoder {
48  public:
49  Decoder(const disasm::NameConverter& converter,
50  Vector<char> out_buffer)
51  : converter_(converter),
52  out_buffer_(out_buffer),
53  out_buffer_pos_(0) {
54  out_buffer_[out_buffer_pos_] = '\0';
55  }
56 
57  ~Decoder() {}
58 
59  // Writes one disassembled instruction into 'buffer' (0-terminated).
60  // Returns the length of the disassembled machine instruction in bytes.
61  int InstructionDecode(byte* instruction);
62 
63  static bool IsConstantPoolAt(byte* instr_ptr);
64  static int ConstantPoolSizeAt(byte* instr_ptr);
65 
66  private:
67  // Bottleneck functions to print into the out_buffer.
68  void PrintChar(const char ch);
69  void Print(const char* str);
70 
71  // Printing of common values.
72  void PrintRegister(int reg);
73  void PrintSRegister(int reg);
74  void PrintDRegister(int reg);
75  int FormatVFPRegister(Instruction* instr, const char* format);
76  void PrintMovwMovt(Instruction* instr);
77  int FormatVFPinstruction(Instruction* instr, const char* format);
78  void PrintCondition(Instruction* instr);
79  void PrintShiftRm(Instruction* instr);
80  void PrintShiftImm(Instruction* instr);
81  void PrintShiftSat(Instruction* instr);
82  void PrintPU(Instruction* instr);
83  void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
84 
85  // Handle formatting of instructions and their options.
86  int FormatRegister(Instruction* instr, const char* option);
87  void FormatNeonList(int Vd, int type);
88  void FormatNeonMemory(int Rn, int align, int Rm);
89  int FormatOption(Instruction* instr, const char* option);
90  void Format(Instruction* instr, const char* format);
91  void Unknown(Instruction* instr);
92 
93  // Each of these functions decodes one particular instruction type, a 3-bit
94  // field in the instruction encoding.
95  // Types 0 and 1 are combined as they are largely the same except for the way
96  // they interpret the shifter operand.
97  void DecodeType01(Instruction* instr);
98  void DecodeType2(Instruction* instr);
99  void DecodeType3(Instruction* instr);
100  void DecodeType4(Instruction* instr);
101  void DecodeType5(Instruction* instr);
102  void DecodeType6(Instruction* instr);
103  // Type 7 includes special Debugger instructions.
104  int DecodeType7(Instruction* instr);
105  // CP15 coprocessor instructions.
106  void DecodeTypeCP15(Instruction* instr);
107  // For VFP support.
108  void DecodeTypeVFP(Instruction* instr);
109  void DecodeType6CoprocessorIns(Instruction* instr);
110 
111  void DecodeSpecialCondition(Instruction* instr);
112 
113  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
114  void DecodeVCMP(Instruction* instr);
115  void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
116  void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
117 
118  const disasm::NameConverter& converter_;
119  Vector<char> out_buffer_;
120  int out_buffer_pos_;
121 
122  DISALLOW_COPY_AND_ASSIGN(Decoder);
123 };
124 
125 
126 // Support for assertions in the Decoder formatting functions.
127 #define STRING_STARTS_WITH(string, compare_string) \
128  (strncmp(string, compare_string, strlen(compare_string)) == 0)
129 
130 
131 // Append the ch to the output buffer.
132 void Decoder::PrintChar(const char ch) {
133  out_buffer_[out_buffer_pos_++] = ch;
134 }
135 
136 
137 // Append the str to the output buffer.
138 void Decoder::Print(const char* str) {
139  char cur = *str++;
140  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
141  PrintChar(cur);
142  cur = *str++;
143  }
144  out_buffer_[out_buffer_pos_] = 0;
145 }
146 
147 
148 // These condition names are defined in a way to match the native disassembler
149 // formatting. See for example the command "objdump -d <binary file>".
150 static const char* const cond_names[kNumberOfConditions] = {
151  "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
152  "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
153 };
154 
155 
156 // Print the condition guarding the instruction.
157 void Decoder::PrintCondition(Instruction* instr) {
158  Print(cond_names[instr->ConditionValue()]);
159 }
160 
161 
162 // Print the register name according to the active name converter.
163 void Decoder::PrintRegister(int reg) {
164  Print(converter_.NameOfCPURegister(reg));
165 }
166 
167 
168 // Print the VFP S register name according to the active name converter.
169 void Decoder::PrintSRegister(int reg) {
170  Print(VFPRegisters::Name(reg, false));
171 }
172 
173 
174 // Print the VFP D register name according to the active name converter.
175 void Decoder::PrintDRegister(int reg) {
176  Print(VFPRegisters::Name(reg, true));
177 }
178 
179 
180 // These shift names are defined in a way to match the native disassembler
181 // formatting. See for example the command "objdump -d <binary file>".
182 static const char* const shift_names[kNumberOfShifts] = {
183  "lsl", "lsr", "asr", "ror"
184 };
185 
186 
187 // Print the register shift operands for the instruction. Generally used for
188 // data processing instructions.
189 void Decoder::PrintShiftRm(Instruction* instr) {
190  ShiftOp shift = instr->ShiftField();
191  int shift_index = instr->ShiftValue();
192  int shift_amount = instr->ShiftAmountValue();
193  int rm = instr->RmValue();
194 
195  PrintRegister(rm);
196 
197  if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) {
198  // Special case for using rm only.
199  return;
200  }
201  if (instr->RegShiftValue() == 0) {
202  // by immediate
203  if ((shift == ROR) && (shift_amount == 0)) {
204  Print(", RRX");
205  return;
206  } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
207  shift_amount = 32;
208  }
209  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
210  ", %s #%d",
211  shift_names[shift_index],
212  shift_amount);
213  } else {
214  // by register
215  int rs = instr->RsValue();
216  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
217  ", %s ", shift_names[shift_index]);
218  PrintRegister(rs);
219  }
220 }
221 
222 
223 // Print the immediate operand for the instruction. Generally used for data
224 // processing instructions.
225 void Decoder::PrintShiftImm(Instruction* instr) {
226  int rotate = instr->RotateValue() * 2;
227  int immed8 = instr->Immed8Value();
228  int imm = base::bits::RotateRight32(immed8, rotate);
229  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm);
230 }
231 
232 
233 // Print the optional shift and immediate used by saturating instructions.
234 void Decoder::PrintShiftSat(Instruction* instr) {
235  int shift = instr->Bits(11, 7);
236  if (shift > 0) {
237  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
238  ", %s #%d",
239  shift_names[instr->Bit(6) * 2],
240  instr->Bits(11, 7));
241  }
242 }
243 
244 
245 // Print PU formatting to reduce complexity of FormatOption.
246 void Decoder::PrintPU(Instruction* instr) {
247  switch (instr->PUField()) {
248  case da_x: {
249  Print("da");
250  break;
251  }
252  case ia_x: {
253  Print("ia");
254  break;
255  }
256  case db_x: {
257  Print("db");
258  break;
259  }
260  case ib_x: {
261  Print("ib");
262  break;
263  }
264  default: {
265  UNREACHABLE();
266  break;
267  }
268  }
269 }
270 
271 
272 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
273 // the FormatOption method.
274 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
275  switch (svc) {
276  case kCallRtRedirected:
277  Print("call rt redirected");
278  return;
279  case kBreakpoint:
280  Print("breakpoint");
281  return;
282  default:
283  if (svc >= kStopCode) {
284  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
285  "%d - 0x%x",
286  svc & kStopCodeMask,
287  svc & kStopCodeMask);
288  } else {
289  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
290  "%d",
291  svc);
292  }
293  return;
294  }
295 }
296 
297 
298 // Handle all register based formatting in this function to reduce the
299 // complexity of FormatOption.
300 int Decoder::FormatRegister(Instruction* instr, const char* format) {
301  DCHECK_EQ(format[0], 'r');
302  if (format[1] == 'n') { // 'rn: Rn register
303  int reg = instr->RnValue();
304  PrintRegister(reg);
305  return 2;
306  } else if (format[1] == 'd') { // 'rd: Rd register
307  int reg = instr->RdValue();
308  PrintRegister(reg);
309  return 2;
310  } else if (format[1] == 's') { // 'rs: Rs register
311  int reg = instr->RsValue();
312  PrintRegister(reg);
313  return 2;
314  } else if (format[1] == 'm') { // 'rm: Rm register
315  int reg = instr->RmValue();
316  PrintRegister(reg);
317  return 2;
318  } else if (format[1] == 't') { // 'rt: Rt register
319  int reg = instr->RtValue();
320  PrintRegister(reg);
321  return 2;
322  } else if (format[1] == 'l') {
323  // 'rlist: register list for load and store multiple instructions
324  DCHECK(STRING_STARTS_WITH(format, "rlist"));
325  int rlist = instr->RlistValue();
326  int reg = 0;
327  Print("{");
328  // Print register list in ascending order, by scanning the bit mask.
329  while (rlist != 0) {
330  if ((rlist & 1) != 0) {
331  PrintRegister(reg);
332  if ((rlist >> 1) != 0) {
333  Print(", ");
334  }
335  }
336  reg++;
337  rlist >>= 1;
338  }
339  Print("}");
340  return 5;
341  }
342  UNREACHABLE();
343 }
344 
345 
346 // Handle all VFP register based formatting in this function to reduce the
347 // complexity of FormatOption.
348 int Decoder::FormatVFPRegister(Instruction* instr, const char* format) {
349  DCHECK((format[0] == 'S') || (format[0] == 'D'));
350 
351  VFPRegPrecision precision =
352  format[0] == 'D' ? kDoublePrecision : kSinglePrecision;
353 
354  int retval = 2;
355  int reg = -1;
356  if (format[1] == 'n') {
357  reg = instr->VFPNRegValue(precision);
358  } else if (format[1] == 'm') {
359  reg = instr->VFPMRegValue(precision);
360  } else if (format[1] == 'd') {
361  if ((instr->TypeValue() == 7) &&
362  (instr->Bit(24) == 0x0) &&
363  (instr->Bits(11, 9) == 0x5) &&
364  (instr->Bit(4) == 0x1)) {
365  // vmov.32 has Vd in a different place.
366  reg = instr->Bits(19, 16) | (instr->Bit(7) << 4);
367  } else {
368  reg = instr->VFPDRegValue(precision);
369  }
370 
371  if (format[2] == '+') {
372  int immed8 = instr->Immed8Value();
373  if (format[0] == 'S') reg += immed8 - 1;
374  if (format[0] == 'D') reg += (immed8 / 2 - 1);
375  }
376  if (format[2] == '+') retval = 3;
377  } else {
378  UNREACHABLE();
379  }
380 
381  if (precision == kSinglePrecision) {
382  PrintSRegister(reg);
383  } else {
384  PrintDRegister(reg);
385  }
386 
387  return retval;
388 }
389 
390 
391 int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) {
392  Print(format);
393  return 0;
394 }
395 
396 
397 void Decoder::FormatNeonList(int Vd, int type) {
398  if (type == nlt_1) {
399  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
400  "{d%d}", Vd);
401  } else if (type == nlt_2) {
402  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
403  "{d%d, d%d}", Vd, Vd + 1);
404  } else if (type == nlt_3) {
405  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
406  "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2);
407  } else if (type == nlt_4) {
408  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
409  "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3);
410  }
411 }
412 
413 
414 void Decoder::FormatNeonMemory(int Rn, int align, int Rm) {
415  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "[%s",
416  converter_.NameOfCPURegister(Rn));
417  if (align != 0) {
418  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
419  ":%d", (1 << align) << 6);
420  }
421  if (Rm == 15) {
422  Print("]");
423  } else if (Rm == 13) {
424  Print("]!");
425  } else {
426  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "], %s",
427  converter_.NameOfCPURegister(Rm));
428  }
429 }
430 
431 
432 // Print the movw or movt instruction.
433 void Decoder::PrintMovwMovt(Instruction* instr) {
434  int imm = instr->ImmedMovwMovtValue();
435  int rd = instr->RdValue();
436  PrintRegister(rd);
437  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm);
438 }
439 
440 
441 // FormatOption takes a formatting string and interprets it based on
442 // the current instructions. The format string points to the first
443 // character of the option string (the option escape has already been
444 // consumed by the caller.) FormatOption returns the number of
445 // characters that were consumed from the formatting string.
446 int Decoder::FormatOption(Instruction* instr, const char* format) {
447  switch (format[0]) {
448  case 'a': { // 'a: accumulate multiplies
449  if (instr->Bit(21) == 0) {
450  Print("ul");
451  } else {
452  Print("la");
453  }
454  return 1;
455  }
456  case 'b': { // 'b: byte loads or stores
457  if (instr->HasB()) {
458  Print("b");
459  }
460  return 1;
461  }
462  case 'c': { // 'cond: conditional execution
463  DCHECK(STRING_STARTS_WITH(format, "cond"));
464  PrintCondition(instr);
465  return 4;
466  }
467  case 'd': { // 'd: vmov double immediate.
468  double d = instr->DoubleImmedVmov().get_scalar();
469  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d);
470  return 1;
471  }
472  case 'f': { // 'f: bitfield instructions - v7 and above.
473  uint32_t lsbit = instr->Bits(11, 7);
474  uint32_t width = instr->Bits(20, 16) + 1;
475  if (instr->Bit(21) == 0) {
476  // BFC/BFI:
477  // Bits 20-16 represent most-significant bit. Covert to width.
478  width -= lsbit;
479  DCHECK_GT(width, 0);
480  }
481  DCHECK_LE(width + lsbit, 32);
482  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
483  "#%d, #%d", lsbit, width);
484  return 1;
485  }
486  case 'h': { // 'h: halfword operation for extra loads and stores
487  if (instr->HasH()) {
488  Print("h");
489  } else {
490  Print("b");
491  }
492  return 1;
493  }
494  case 'i': { // 'i: immediate value from adjacent bits.
495  // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16
496  int width = (format[3] - '0') * 10 + (format[4] - '0');
497  int lsb = (format[6] - '0') * 10 + (format[7] - '0');
498 
499  DCHECK((width >= 1) && (width <= 32));
500  DCHECK((lsb >= 0) && (lsb <= 31));
501  DCHECK_LE(width + lsb, 32);
502 
503  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
504  "%d",
505  instr->Bits(width + lsb - 1, lsb));
506  return 8;
507  }
508  case 'l': { // 'l: branch and link
509  if (instr->HasLink()) {
510  Print("l");
511  }
512  return 1;
513  }
514  case 'm': {
515  if (format[1] == 'w') {
516  // 'mw: movt/movw instructions.
517  PrintMovwMovt(instr);
518  return 2;
519  }
520  if (format[1] == 'e') { // 'memop: load/store instructions.
521  DCHECK(STRING_STARTS_WITH(format, "memop"));
522  if (instr->HasL()) {
523  Print("ldr");
524  } else {
525  if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) &&
526  (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) {
527  if (instr->Bit(5) == 1) {
528  Print("strd");
529  } else {
530  Print("ldrd");
531  }
532  return 5;
533  }
534  Print("str");
535  }
536  return 5;
537  }
538  // 'msg: for simulator break instructions
539  DCHECK(STRING_STARTS_WITH(format, "msg"));
540  byte* str =
541  reinterpret_cast<byte*>(instr->InstructionBits() & 0x0FFFFFFF);
542  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
543  "%s", converter_.NameInCode(str));
544  return 3;
545  }
546  case 'o': {
547  if ((format[3] == '1') && (format[4] == '2')) {
548  // 'off12: 12-bit offset for load and store instructions
549  DCHECK(STRING_STARTS_WITH(format, "off12"));
550  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
551  "%d", instr->Offset12Value());
552  return 5;
553  } else if (format[3] == '0') {
554  // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
555  DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19"));
556  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
557  "%d",
558  (instr->Bits(19, 8) << 4) +
559  instr->Bits(3, 0));
560  return 15;
561  }
562  // 'off8: 8-bit offset for extra load and store instructions
563  DCHECK(STRING_STARTS_WITH(format, "off8"));
564  int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
565  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8);
566  return 4;
567  }
568  case 'p': { // 'pu: P and U bits for load and store instructions
569  DCHECK(STRING_STARTS_WITH(format, "pu"));
570  PrintPU(instr);
571  return 2;
572  }
573  case 'r': {
574  return FormatRegister(instr, format);
575  }
576  case 's': {
577  if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat.
578  if (format[6] == 'o') { // 'shift_op
579  DCHECK(STRING_STARTS_WITH(format, "shift_op"));
580  if (instr->TypeValue() == 0) {
581  PrintShiftRm(instr);
582  } else {
583  DCHECK_EQ(instr->TypeValue(), 1);
584  PrintShiftImm(instr);
585  }
586  return 8;
587  } else if (format[6] == 's') { // 'shift_sat.
588  DCHECK(STRING_STARTS_WITH(format, "shift_sat"));
589  PrintShiftSat(instr);
590  return 9;
591  } else { // 'shift_rm
592  DCHECK(STRING_STARTS_WITH(format, "shift_rm"));
593  PrintShiftRm(instr);
594  return 8;
595  }
596  } else if (format[1] == 'v') { // 'svc
597  DCHECK(STRING_STARTS_WITH(format, "svc"));
598  PrintSoftwareInterrupt(instr->SvcValue());
599  return 3;
600  } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
601  DCHECK(STRING_STARTS_WITH(format, "sign"));
602  if (instr->HasSign()) {
603  Print("s");
604  }
605  return 4;
606  } else if (format[1] == 'p') {
607  if (format[8] == '_') { // 'spec_reg_fields
608  DCHECK(STRING_STARTS_WITH(format, "spec_reg_fields"));
609  Print("_");
610  int mask = instr->Bits(19, 16);
611  if (mask == 0) Print("(none)");
612  if ((mask & 0x8) != 0) Print("f");
613  if ((mask & 0x4) != 0) Print("s");
614  if ((mask & 0x2) != 0) Print("x");
615  if ((mask & 0x1) != 0) Print("c");
616  return 15;
617  } else { // 'spec_reg
618  DCHECK(STRING_STARTS_WITH(format, "spec_reg"));
619  if (instr->Bit(22) == 0) {
620  Print("CPSR");
621  } else {
622  Print("SPSR");
623  }
624  return 8;
625  }
626  }
627  // 's: S field of data processing instructions
628  if (instr->HasS()) {
629  Print("s");
630  }
631  return 1;
632  }
633  case 't': { // 'target: target of branch instructions
634  DCHECK(STRING_STARTS_WITH(format, "target"));
635  int off = (instr->SImmed24Value() << 2) + 8;
636  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
637  "%+d -> %s",
638  off,
639  converter_.NameOfAddress(
640  reinterpret_cast<byte*>(instr) + off));
641  return 6;
642  }
643  case 'u': { // 'u: signed or unsigned multiplies
644  // The manual gets the meaning of bit 22 backwards in the multiply
645  // instruction overview on page A3.16.2. The instructions that
646  // exist in u and s variants are the following:
647  // smull A4.1.87
648  // umull A4.1.129
649  // umlal A4.1.128
650  // smlal A4.1.76
651  // For these 0 means u and 1 means s. As can be seen on their individual
652  // pages. The other 18 mul instructions have the bit set or unset in
653  // arbitrary ways that are unrelated to the signedness of the instruction.
654  // None of these 18 instructions exist in both a 'u' and an 's' variant.
655 
656  if (instr->Bit(22) == 0) {
657  Print("u");
658  } else {
659  Print("s");
660  }
661  return 1;
662  }
663  case 'v': {
664  return FormatVFPinstruction(instr, format);
665  }
666  case 'A': {
667  // Print pc-relative address.
668  int offset = instr->Offset12Value();
669  byte* pc = reinterpret_cast<byte*>(instr) + Instruction::kPcLoadDelta;
670  byte* addr;
671  switch (instr->PUField()) {
672  case db_x: {
673  addr = pc - offset;
674  break;
675  }
676  case ib_x: {
677  addr = pc + offset;
678  break;
679  }
680  default: {
681  UNREACHABLE();
682  return -1;
683  }
684  }
685  out_buffer_pos_ +=
686  SNPrintF(out_buffer_ + out_buffer_pos_, "0x%08" PRIxPTR,
687  reinterpret_cast<uintptr_t>(addr));
688  return 1;
689  }
690  case 'S':
691  case 'D': {
692  return FormatVFPRegister(instr, format);
693  }
694  case 'w': { // 'w: W field of load and store instructions
695  if (instr->HasW()) {
696  Print("!");
697  }
698  return 1;
699  }
700  default: {
701  UNREACHABLE();
702  break;
703  }
704  }
705  UNREACHABLE();
706 }
707 
708 
709 // Format takes a formatting string for a whole instruction and prints it into
710 // the output buffer. All escaped options are handed to FormatOption to be
711 // parsed further.
712 void Decoder::Format(Instruction* instr, const char* format) {
713  char cur = *format++;
714  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
715  if (cur == '\'') { // Single quote is used as the formatting escape.
716  format += FormatOption(instr, format);
717  } else {
718  out_buffer_[out_buffer_pos_++] = cur;
719  }
720  cur = *format++;
721  }
722  out_buffer_[out_buffer_pos_] = '\0';
723 }
724 
725 
726 // The disassembler may end up decoding data inlined in the code. We do not want
727 // it to crash if the data does not resemble any known instruction.
728 #define VERIFY(condition) \
729 if(!(condition)) { \
730  Unknown(instr); \
731  return; \
732 }
733 
734 
735 // For currently unimplemented decodings the disassembler calls Unknown(instr)
736 // which will just print "unknown" of the instruction bits.
737 void Decoder::Unknown(Instruction* instr) {
738  Format(instr, "unknown");
739 }
740 
741 
742 void Decoder::DecodeType01(Instruction* instr) {
743  int type = instr->TypeValue();
744  if ((type == 0) && instr->IsSpecialType0()) {
745  // multiply instruction or extra loads and stores
746  if (instr->Bits(7, 4) == 9) {
747  if (instr->Bit(24) == 0) {
748  // multiply instructions
749  if (instr->Bit(23) == 0) {
750  if (instr->Bit(21) == 0) {
751  // The MUL instruction description (A 4.1.33) refers to Rd as being
752  // the destination for the operation, but it confusingly uses the
753  // Rn field to encode it.
754  Format(instr, "mul'cond's 'rn, 'rm, 'rs");
755  } else {
756  if (instr->Bit(22) == 0) {
757  // The MLA instruction description (A 4.1.28) refers to the order
758  // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
759  // Rn field to encode the Rd register and the Rd field to encode
760  // the Rn register.
761  Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
762  } else {
763  // The MLS instruction description (A 4.1.29) refers to the order
764  // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
765  // Rn field to encode the Rd register and the Rd field to encode
766  // the Rn register.
767  Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
768  }
769  }
770  } else {
771  // The signed/long multiply instructions use the terms RdHi and RdLo
772  // when referring to the target registers. They are mapped to the Rn
773  // and Rd fields as follows:
774  // RdLo == Rd field
775  // RdHi == Rn field
776  // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
777  Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
778  }
779  } else {
780  if (instr->Bits(24, 23) == 3) {
781  if (instr->Bit(20) == 1) {
782  // ldrex
783  switch (instr->Bits(22, 21)) {
784  case 0:
785  Format(instr, "ldrex'cond 'rt, ['rn]");
786  break;
787  case 1:
788  Format(instr, "ldrexd'cond 'rt, ['rn]");
789  break;
790  case 2:
791  Format(instr, "ldrexb'cond 'rt, ['rn]");
792  break;
793  case 3:
794  Format(instr, "ldrexh'cond 'rt, ['rn]");
795  break;
796  default:
797  UNREACHABLE();
798  break;
799  }
800  } else {
801  // strex
802  // The instruction is documented as strex rd, rt, [rn], but the
803  // "rt" register is using the rm bits.
804  switch (instr->Bits(22, 21)) {
805  case 0:
806  Format(instr, "strex'cond 'rd, 'rm, ['rn]");
807  break;
808  case 1:
809  Format(instr, "strexd'cond 'rd, 'rm, ['rn]");
810  break;
811  case 2:
812  Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
813  break;
814  case 3:
815  Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
816  break;
817  default:
818  UNREACHABLE();
819  break;
820  }
821  }
822  } else {
823  Unknown(instr); // not used by V8
824  }
825  }
826  } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xD) == 0xD)) {
827  // ldrd, strd
828  switch (instr->PUField()) {
829  case da_x: {
830  if (instr->Bit(22) == 0) {
831  Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
832  } else {
833  Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
834  }
835  break;
836  }
837  case ia_x: {
838  if (instr->Bit(22) == 0) {
839  Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
840  } else {
841  Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
842  }
843  break;
844  }
845  case db_x: {
846  if (instr->Bit(22) == 0) {
847  Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
848  } else {
849  Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
850  }
851  break;
852  }
853  case ib_x: {
854  if (instr->Bit(22) == 0) {
855  Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
856  } else {
857  Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
858  }
859  break;
860  }
861  default: {
862  // The PU field is a 2-bit field.
863  UNREACHABLE();
864  break;
865  }
866  }
867  } else {
868  // extra load/store instructions
869  switch (instr->PUField()) {
870  case da_x: {
871  if (instr->Bit(22) == 0) {
872  Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
873  } else {
874  Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
875  }
876  break;
877  }
878  case ia_x: {
879  if (instr->Bit(22) == 0) {
880  Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
881  } else {
882  Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
883  }
884  break;
885  }
886  case db_x: {
887  if (instr->Bit(22) == 0) {
888  Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
889  } else {
890  Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
891  }
892  break;
893  }
894  case ib_x: {
895  if (instr->Bit(22) == 0) {
896  Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
897  } else {
898  Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
899  }
900  break;
901  }
902  default: {
903  // The PU field is a 2-bit field.
904  UNREACHABLE();
905  break;
906  }
907  }
908  return;
909  }
910  } else if ((type == 0) && instr->IsMiscType0()) {
911  if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
912  (instr->Bits(15, 4) == 0xF00)) {
913  Format(instr, "msr'cond 'spec_reg'spec_reg_fields, 'rm");
914  } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
915  (instr->Bits(11, 0) == 0)) {
916  Format(instr, "mrs'cond 'rd, 'spec_reg");
917  } else if (instr->Bits(22, 21) == 1) {
918  switch (instr->BitField(7, 4)) {
919  case BX:
920  Format(instr, "bx'cond 'rm");
921  break;
922  case BLX:
923  Format(instr, "blx'cond 'rm");
924  break;
925  case BKPT:
926  Format(instr, "bkpt 'off0to3and8to19");
927  break;
928  default:
929  Unknown(instr); // not used by V8
930  break;
931  }
932  } else if (instr->Bits(22, 21) == 3) {
933  switch (instr->BitField(7, 4)) {
934  case CLZ:
935  Format(instr, "clz'cond 'rd, 'rm");
936  break;
937  default:
938  Unknown(instr); // not used by V8
939  break;
940  }
941  } else {
942  Unknown(instr); // not used by V8
943  }
944  } else if ((type == 1) && instr->IsNopLikeType1()) {
945  if (instr->BitField(7, 0) == 0) {
946  Format(instr, "nop'cond");
947  } else if (instr->BitField(7, 0) == 20) {
948  Format(instr, "csdb");
949  } else {
950  Unknown(instr); // Not used in V8.
951  }
952  } else {
953  switch (instr->OpcodeField()) {
954  case AND: {
955  Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
956  break;
957  }
958  case EOR: {
959  Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
960  break;
961  }
962  case SUB: {
963  Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
964  break;
965  }
966  case RSB: {
967  Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
968  break;
969  }
970  case ADD: {
971  Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
972  break;
973  }
974  case ADC: {
975  Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
976  break;
977  }
978  case SBC: {
979  Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
980  break;
981  }
982  case RSC: {
983  Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
984  break;
985  }
986  case TST: {
987  if (instr->HasS()) {
988  Format(instr, "tst'cond 'rn, 'shift_op");
989  } else {
990  Format(instr, "movw'cond 'mw");
991  }
992  break;
993  }
994  case TEQ: {
995  if (instr->HasS()) {
996  Format(instr, "teq'cond 'rn, 'shift_op");
997  } else {
998  // Other instructions matching this pattern are handled in the
999  // miscellaneous instructions part above.
1000  UNREACHABLE();
1001  }
1002  break;
1003  }
1004  case CMP: {
1005  if (instr->HasS()) {
1006  Format(instr, "cmp'cond 'rn, 'shift_op");
1007  } else {
1008  Format(instr, "movt'cond 'mw");
1009  }
1010  break;
1011  }
1012  case CMN: {
1013  if (instr->HasS()) {
1014  Format(instr, "cmn'cond 'rn, 'shift_op");
1015  } else {
1016  // Other instructions matching this pattern are handled in the
1017  // miscellaneous instructions part above.
1018  UNREACHABLE();
1019  }
1020  break;
1021  }
1022  case ORR: {
1023  Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
1024  break;
1025  }
1026  case MOV: {
1027  Format(instr, "mov'cond's 'rd, 'shift_op");
1028  break;
1029  }
1030  case BIC: {
1031  Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
1032  break;
1033  }
1034  case MVN: {
1035  Format(instr, "mvn'cond's 'rd, 'shift_op");
1036  break;
1037  }
1038  default: {
1039  // The Opcode field is a 4-bit field.
1040  UNREACHABLE();
1041  break;
1042  }
1043  }
1044  }
1045 }
1046 
1047 
1048 void Decoder::DecodeType2(Instruction* instr) {
1049  switch (instr->PUField()) {
1050  case da_x: {
1051  if (instr->HasW()) {
1052  Unknown(instr); // not used in V8
1053  return;
1054  }
1055  Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
1056  break;
1057  }
1058  case ia_x: {
1059  if (instr->HasW()) {
1060  Unknown(instr); // not used in V8
1061  return;
1062  }
1063  Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
1064  break;
1065  }
1066  case db_x: {
1067  if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
1068  Format(instr, "'memop'cond'b 'rd, [pc, #-'off12]'w (addr 'A)");
1069  } else {
1070  Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
1071  }
1072  break;
1073  }
1074  case ib_x: {
1075  if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
1076  Format(instr, "'memop'cond'b 'rd, [pc, #+'off12]'w (addr 'A)");
1077  } else {
1078  Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
1079  }
1080  break;
1081  }
1082  default: {
1083  // The PU field is a 2-bit field.
1084  UNREACHABLE();
1085  break;
1086  }
1087  }
1088 }
1089 
1090 
1091 void Decoder::DecodeType3(Instruction* instr) {
1092  switch (instr->PUField()) {
1093  case da_x: {
1094  VERIFY(!instr->HasW());
1095  Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
1096  break;
1097  }
1098  case ia_x: {
1099  if (instr->Bit(4) == 0) {
1100  Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
1101  } else {
1102  if (instr->Bit(5) == 0) {
1103  switch (instr->Bits(22, 21)) {
1104  case 0:
1105  if (instr->Bit(20) == 0) {
1106  if (instr->Bit(6) == 0) {
1107  Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
1108  } else {
1109  if (instr->Bits(11, 7) == 0) {
1110  Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
1111  } else {
1112  Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
1113  }
1114  }
1115  } else {
1116  UNREACHABLE();
1117  }
1118  break;
1119  case 1:
1120  UNREACHABLE();
1121  break;
1122  case 2:
1123  UNREACHABLE();
1124  break;
1125  case 3:
1126  Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
1127  break;
1128  }
1129  } else {
1130  switch (instr->Bits(22, 21)) {
1131  case 0:
1132  UNREACHABLE();
1133  break;
1134  case 1:
1135  if (instr->Bits(9, 6) == 1) {
1136  if (instr->Bit(20) == 0) {
1137  if (instr->Bits(19, 16) == 0xF) {
1138  switch (instr->Bits(11, 10)) {
1139  case 0:
1140  Format(instr, "sxtb'cond 'rd, 'rm");
1141  break;
1142  case 1:
1143  Format(instr, "sxtb'cond 'rd, 'rm, ror #8");
1144  break;
1145  case 2:
1146  Format(instr, "sxtb'cond 'rd, 'rm, ror #16");
1147  break;
1148  case 3:
1149  Format(instr, "sxtb'cond 'rd, 'rm, ror #24");
1150  break;
1151  }
1152  } else {
1153  switch (instr->Bits(11, 10)) {
1154  case 0:
1155  Format(instr, "sxtab'cond 'rd, 'rn, 'rm");
1156  break;
1157  case 1:
1158  Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8");
1159  break;
1160  case 2:
1161  Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16");
1162  break;
1163  case 3:
1164  Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24");
1165  break;
1166  }
1167  }
1168  } else {
1169  if (instr->Bits(19, 16) == 0xF) {
1170  switch (instr->Bits(11, 10)) {
1171  case 0:
1172  Format(instr, "sxth'cond 'rd, 'rm");
1173  break;
1174  case 1:
1175  Format(instr, "sxth'cond 'rd, 'rm, ror #8");
1176  break;
1177  case 2:
1178  Format(instr, "sxth'cond 'rd, 'rm, ror #16");
1179  break;
1180  case 3:
1181  Format(instr, "sxth'cond 'rd, 'rm, ror #24");
1182  break;
1183  }
1184  } else {
1185  switch (instr->Bits(11, 10)) {
1186  case 0:
1187  Format(instr, "sxtah'cond 'rd, 'rn, 'rm");
1188  break;
1189  case 1:
1190  Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8");
1191  break;
1192  case 2:
1193  Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16");
1194  break;
1195  case 3:
1196  Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24");
1197  break;
1198  }
1199  }
1200  }
1201  } else if (instr->Bits(27, 16) == 0x6BF &&
1202  instr->Bits(11, 4) == 0xF3) {
1203  Format(instr, "rev'cond 'rd, 'rm");
1204  } else {
1205  UNREACHABLE();
1206  }
1207  break;
1208  case 2:
1209  if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
1210  if (instr->Bits(19, 16) == 0xF) {
1211  switch (instr->Bits(11, 10)) {
1212  case 0:
1213  Format(instr, "uxtb16'cond 'rd, 'rm");
1214  break;
1215  case 1:
1216  Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
1217  break;
1218  case 2:
1219  Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
1220  break;
1221  case 3:
1222  Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
1223  break;
1224  }
1225  } else {
1226  UNREACHABLE();
1227  }
1228  } else {
1229  UNREACHABLE();
1230  }
1231  break;
1232  case 3:
1233  if ((instr->Bits(9, 6) == 1)) {
1234  if ((instr->Bit(20) == 0)) {
1235  if (instr->Bits(19, 16) == 0xF) {
1236  switch (instr->Bits(11, 10)) {
1237  case 0:
1238  Format(instr, "uxtb'cond 'rd, 'rm");
1239  break;
1240  case 1:
1241  Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
1242  break;
1243  case 2:
1244  Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
1245  break;
1246  case 3:
1247  Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
1248  break;
1249  }
1250  } else {
1251  switch (instr->Bits(11, 10)) {
1252  case 0:
1253  Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
1254  break;
1255  case 1:
1256  Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
1257  break;
1258  case 2:
1259  Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
1260  break;
1261  case 3:
1262  Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
1263  break;
1264  }
1265  }
1266  } else {
1267  if (instr->Bits(19, 16) == 0xF) {
1268  switch (instr->Bits(11, 10)) {
1269  case 0:
1270  Format(instr, "uxth'cond 'rd, 'rm");
1271  break;
1272  case 1:
1273  Format(instr, "uxth'cond 'rd, 'rm, ror #8");
1274  break;
1275  case 2:
1276  Format(instr, "uxth'cond 'rd, 'rm, ror #16");
1277  break;
1278  case 3:
1279  Format(instr, "uxth'cond 'rd, 'rm, ror #24");
1280  break;
1281  }
1282  } else {
1283  switch (instr->Bits(11, 10)) {
1284  case 0:
1285  Format(instr, "uxtah'cond 'rd, 'rn, 'rm");
1286  break;
1287  case 1:
1288  Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8");
1289  break;
1290  case 2:
1291  Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16");
1292  break;
1293  case 3:
1294  Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24");
1295  break;
1296  }
1297  }
1298  }
1299  } else {
1300  // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001
1301  if ((instr->Bits(20, 16) == 0x1F) &&
1302  (instr->Bits(11, 4) == 0xF3)) {
1303  Format(instr, "rbit'cond 'rd, 'rm");
1304  } else {
1305  UNREACHABLE();
1306  }
1307  }
1308  break;
1309  }
1310  }
1311  }
1312  break;
1313  }
1314  case db_x: {
1315  if (instr->Bits(22, 20) == 0x5) {
1316  if (instr->Bits(7, 4) == 0x1) {
1317  if (instr->Bits(15, 12) == 0xF) {
1318  Format(instr, "smmul'cond 'rn, 'rm, 'rs");
1319  } else {
1320  // SMMLA (in V8 notation matching ARM ISA format)
1321  Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
1322  }
1323  break;
1324  }
1325  }
1326  if (instr->Bits(5, 4) == 0x1) {
1327  if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
1328  if (instr->Bit(21) == 0x1) {
1329  // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1330  Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
1331  } else {
1332  // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1333  Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
1334  }
1335  break;
1336  }
1337  }
1338  Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1339  break;
1340  }
1341  case ib_x: {
1342  if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1343  uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1344  uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1345  uint32_t msbit = widthminus1 + lsbit;
1346  if (msbit <= 31) {
1347  if (instr->Bit(22)) {
1348  Format(instr, "ubfx'cond 'rd, 'rm, 'f");
1349  } else {
1350  Format(instr, "sbfx'cond 'rd, 'rm, 'f");
1351  }
1352  } else {
1353  UNREACHABLE();
1354  }
1355  } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
1356  uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1357  uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
1358  if (msbit >= lsbit) {
1359  if (instr->RmValue() == 15) {
1360  Format(instr, "bfc'cond 'rd, 'f");
1361  } else {
1362  Format(instr, "bfi'cond 'rd, 'rm, 'f");
1363  }
1364  } else {
1365  UNREACHABLE();
1366  }
1367  } else {
1368  Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1369  }
1370  break;
1371  }
1372  default: {
1373  // The PU field is a 2-bit field.
1374  UNREACHABLE();
1375  break;
1376  }
1377  }
1378 }
1379 
1380 
1381 void Decoder::DecodeType4(Instruction* instr) {
1382  if (instr->Bit(22) != 0) {
1383  // Privileged mode currently not supported.
1384  Unknown(instr);
1385  } else {
1386  if (instr->HasL()) {
1387  Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1388  } else {
1389  Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1390  }
1391  }
1392 }
1393 
1394 
1395 void Decoder::DecodeType5(Instruction* instr) {
1396  Format(instr, "b'l'cond 'target");
1397 }
1398 
1399 
1400 void Decoder::DecodeType6(Instruction* instr) {
1401  DecodeType6CoprocessorIns(instr);
1402 }
1403 
1404 
1405 int Decoder::DecodeType7(Instruction* instr) {
1406  if (instr->Bit(24) == 1) {
1407  if (instr->SvcValue() >= kStopCode) {
1408  Format(instr, "stop'cond 'svc");
1409  } else {
1410  Format(instr, "svc'cond 'svc");
1411  }
1412  } else {
1413  switch (instr->CoprocessorValue()) {
1414  case 10: // Fall through.
1415  case 11:
1416  DecodeTypeVFP(instr);
1417  break;
1418  case 15:
1419  DecodeTypeCP15(instr);
1420  break;
1421  default:
1422  Unknown(instr);
1423  break;
1424  }
1425  }
1426  return kInstrSize;
1427 }
1428 
1429 
1430 // void Decoder::DecodeTypeVFP(Instruction* instr)
1431 // vmov: Sn = Rt
1432 // vmov: Rt = Sn
1433 // vcvt: Dd = Sm
1434 // vcvt: Sd = Dm
1435 // vcvt.f64.s32 Dd, Dd, #<fbits>
1436 // Dd = vabs(Dm)
1437 // Sd = vabs(Sm)
1438 // Dd = vneg(Dm)
1439 // Sd = vneg(Sm)
1440 // Dd = vadd(Dn, Dm)
1441 // Sd = vadd(Sn, Sm)
1442 // Dd = vsub(Dn, Dm)
1443 // Sd = vsub(Sn, Sm)
1444 // Dd = vmul(Dn, Dm)
1445 // Sd = vmul(Sn, Sm)
1446 // Dd = vmla(Dn, Dm)
1447 // Sd = vmla(Sn, Sm)
1448 // Dd = vmls(Dn, Dm)
1449 // Sd = vmls(Sn, Sm)
1450 // Dd = vdiv(Dn, Dm)
1451 // Sd = vdiv(Sn, Sm)
1452 // vcmp(Dd, Dm)
1453 // vcmp(Sd, Sm)
1454 // Dd = vsqrt(Dm)
1455 // Sd = vsqrt(Sm)
1456 // vmrs
1457 // vmsr
1458 // Qd = vdup.size(Qd, Rt)
1459 // vmov.size: Dd[i] = Rt
1460 // vmov.sign.size: Rt = Dn[i]
1461 void Decoder::DecodeTypeVFP(Instruction* instr) {
1462  VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
1463  VERIFY(instr->Bits(11, 9) == 0x5);
1464 
1465  if (instr->Bit(4) == 0) {
1466  if (instr->Opc1Value() == 0x7) {
1467  // Other data processing instructions
1468  if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
1469  // vmov register to register.
1470  if (instr->SzValue() == 0x1) {
1471  Format(instr, "vmov'cond.f64 'Dd, 'Dm");
1472  } else {
1473  Format(instr, "vmov'cond.f32 'Sd, 'Sm");
1474  }
1475  } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
1476  // vabs
1477  if (instr->SzValue() == 0x1) {
1478  Format(instr, "vabs'cond.f64 'Dd, 'Dm");
1479  } else {
1480  Format(instr, "vabs'cond.f32 'Sd, 'Sm");
1481  }
1482  } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
1483  // vneg
1484  if (instr->SzValue() == 0x1) {
1485  Format(instr, "vneg'cond.f64 'Dd, 'Dm");
1486  } else {
1487  Format(instr, "vneg'cond.f32 'Sd, 'Sm");
1488  }
1489  } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
1490  DecodeVCVTBetweenDoubleAndSingle(instr);
1491  } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
1492  DecodeVCVTBetweenFloatingPointAndInteger(instr);
1493  } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
1494  (instr->Bit(8) == 1)) {
1495  // vcvt.f64.s32 Dd, Dd, #<fbits>
1496  int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
1497  Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
1498  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1499  ", #%d", fraction_bits);
1500  } else if (((instr->Opc2Value() >> 1) == 0x6) &&
1501  (instr->Opc3Value() & 0x1)) {
1502  DecodeVCVTBetweenFloatingPointAndInteger(instr);
1503  } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1504  (instr->Opc3Value() & 0x1)) {
1505  DecodeVCMP(instr);
1506  } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
1507  if (instr->SzValue() == 0x1) {
1508  Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
1509  } else {
1510  Format(instr, "vsqrt'cond.f32 'Sd, 'Sm");
1511  }
1512  } else if (instr->Opc3Value() == 0x0) {
1513  if (instr->SzValue() == 0x1) {
1514  Format(instr, "vmov'cond.f64 'Dd, 'd");
1515  } else {
1516  Format(instr, "vmov'cond.f32 'Sd, 'd");
1517  }
1518  } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) {
1519  // vrintz - round towards zero (truncate)
1520  if (instr->SzValue() == 0x1) {
1521  Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm");
1522  } else {
1523  Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm");
1524  }
1525  } else {
1526  Unknown(instr); // Not used by V8.
1527  }
1528  } else if (instr->Opc1Value() == 0x3) {
1529  if (instr->SzValue() == 0x1) {
1530  if (instr->Opc3Value() & 0x1) {
1531  Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
1532  } else {
1533  Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
1534  }
1535  } else {
1536  if (instr->Opc3Value() & 0x1) {
1537  Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm");
1538  } else {
1539  Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm");
1540  }
1541  }
1542  } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
1543  if (instr->SzValue() == 0x1) {
1544  Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
1545  } else {
1546  Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm");
1547  }
1548  } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
1549  if (instr->SzValue() == 0x1) {
1550  Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
1551  } else {
1552  Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm");
1553  }
1554  } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
1555  if (instr->SzValue() == 0x1) {
1556  Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
1557  } else {
1558  Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm");
1559  }
1560  } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
1561  if (instr->SzValue() == 0x1) {
1562  Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
1563  } else {
1564  Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm");
1565  }
1566  } else {
1567  Unknown(instr); // Not used by V8.
1568  }
1569  } else {
1570  if ((instr->VCValue() == 0x0) &&
1571  (instr->VAValue() == 0x0)) {
1572  DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1573  } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
1574  const char* rt_name = converter_.NameOfCPURegister(instr->RtValue());
1575  if (instr->Bit(23) == 0) {
1576  int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
1577  if ((opc1_opc2 & 0xB) == 0) {
1578  // NeonS32/NeonU32
1579  if (instr->Bit(21) == 0x0) {
1580  Format(instr, "vmov'cond.32 'Dd[0], 'rt");
1581  } else {
1582  Format(instr, "vmov'cond.32 'Dd[1], 'rt");
1583  }
1584  } else {
1585  int vd = instr->VFPNRegValue(kDoublePrecision);
1586  if ((opc1_opc2 & 0x8) != 0) {
1587  // NeonS8 / NeonU8
1588  int i = opc1_opc2 & 0x7;
1589  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1590  "vmov.8 d%d[%d], %s", vd, i, rt_name);
1591  } else if ((opc1_opc2 & 0x1) != 0) {
1592  // NeonS16 / NeonU16
1593  int i = (opc1_opc2 >> 1) & 0x3;
1594  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1595  "vmov.16 d%d[%d], %s", vd, i, rt_name);
1596  } else {
1597  Unknown(instr);
1598  }
1599  }
1600  } else {
1601  int size = 32;
1602  if (instr->Bit(5) != 0) {
1603  size = 16;
1604  } else if (instr->Bit(22) != 0) {
1605  size = 8;
1606  }
1607  int Vd = instr->VFPNRegValue(kSimd128Precision);
1608  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1609  "vdup.%i q%d, %s", size, Vd, rt_name);
1610  }
1611  } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
1612  int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
1613  if ((opc1_opc2 & 0xB) == 0) {
1614  // NeonS32 / NeonU32
1615  if (instr->Bit(21) == 0x0) {
1616  Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
1617  } else {
1618  Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
1619  }
1620  } else {
1621  char sign = instr->Bit(23) != 0 ? 'u' : 's';
1622  const char* rt_name = converter_.NameOfCPURegister(instr->RtValue());
1623  int vn = instr->VFPNRegValue(kDoublePrecision);
1624  if ((opc1_opc2 & 0x8) != 0) {
1625  // NeonS8 / NeonU8
1626  int i = opc1_opc2 & 0x7;
1627  out_buffer_pos_ +=
1628  SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%c8 %s, d%d[%d]",
1629  sign, rt_name, vn, i);
1630  } else if ((opc1_opc2 & 0x1) != 0) {
1631  // NeonS16 / NeonU16
1632  int i = (opc1_opc2 >> 1) & 0x3;
1633  out_buffer_pos_ +=
1634  SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%c16 %s, d%d[%d]",
1635  sign, rt_name, vn, i);
1636  } else {
1637  Unknown(instr);
1638  }
1639  }
1640  } else if ((instr->VCValue() == 0x0) &&
1641  (instr->VAValue() == 0x7) &&
1642  (instr->Bits(19, 16) == 0x1)) {
1643  if (instr->VLValue() == 0) {
1644  if (instr->Bits(15, 12) == 0xF) {
1645  Format(instr, "vmsr'cond FPSCR, APSR");
1646  } else {
1647  Format(instr, "vmsr'cond FPSCR, 'rt");
1648  }
1649  } else {
1650  if (instr->Bits(15, 12) == 0xF) {
1651  Format(instr, "vmrs'cond APSR, FPSCR");
1652  } else {
1653  Format(instr, "vmrs'cond 'rt, FPSCR");
1654  }
1655  }
1656  } else {
1657  Unknown(instr); // Not used by V8.
1658  }
1659  }
1660 }
1661 
1662 void Decoder::DecodeTypeCP15(Instruction* instr) {
1663  VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
1664  VERIFY(instr->CoprocessorValue() == 15);
1665 
1666  if (instr->Bit(4) == 1) {
1667  int crn = instr->Bits(19, 16);
1668  int crm = instr->Bits(3, 0);
1669  int opc1 = instr->Bits(23, 21);
1670  int opc2 = instr->Bits(7, 5);
1671  if ((opc1 == 0) && (crn == 7)) {
1672  // ARMv6 memory barrier operations.
1673  // Details available in ARM DDI 0406C.b, B3-1750.
1674  if ((crm == 10) && (opc2 == 5)) {
1675  Format(instr, "mcr'cond (CP15DMB)");
1676  } else if ((crm == 10) && (opc2 == 4)) {
1677  Format(instr, "mcr'cond (CP15DSB)");
1678  } else if ((crm == 5) && (opc2 == 4)) {
1679  Format(instr, "mcr'cond (CP15ISB)");
1680  } else {
1681  Unknown(instr);
1682  }
1683  } else {
1684  Unknown(instr);
1685  }
1686  } else {
1687  Unknown(instr);
1688  }
1689 }
1690 
1691 void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
1692  Instruction* instr) {
1693  VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
1694  (instr->VAValue() == 0x0));
1695 
1696  bool to_arm_register = (instr->VLValue() == 0x1);
1697 
1698  if (to_arm_register) {
1699  Format(instr, "vmov'cond 'rt, 'Sn");
1700  } else {
1701  Format(instr, "vmov'cond 'Sn, 'rt");
1702  }
1703 }
1704 
1705 
1706 void Decoder::DecodeVCMP(Instruction* instr) {
1707  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1708  VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1709  (instr->Opc3Value() & 0x1));
1710 
1711  // Comparison.
1712  bool dp_operation = (instr->SzValue() == 1);
1713  bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1714 
1715  if (dp_operation && !raise_exception_for_qnan) {
1716  if (instr->Opc2Value() == 0x4) {
1717  Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
1718  } else if (instr->Opc2Value() == 0x5) {
1719  Format(instr, "vcmp'cond.f64 'Dd, #0.0");
1720  } else {
1721  Unknown(instr); // invalid
1722  }
1723  } else if (!raise_exception_for_qnan) {
1724  if (instr->Opc2Value() == 0x4) {
1725  Format(instr, "vcmp'cond.f32 'Sd, 'Sm");
1726  } else if (instr->Opc2Value() == 0x5) {
1727  Format(instr, "vcmp'cond.f32 'Sd, #0.0");
1728  } else {
1729  Unknown(instr); // invalid
1730  }
1731  } else {
1732  Unknown(instr); // Not used by V8.
1733  }
1734 }
1735 
1736 
1737 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
1738  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1739  VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
1740 
1741  bool double_to_single = (instr->SzValue() == 1);
1742 
1743  if (double_to_single) {
1744  Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
1745  } else {
1746  Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
1747  }
1748 }
1749 
1750 
1751 void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
1752  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1753  VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
1754  (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
1755 
1756  bool to_integer = (instr->Bit(18) == 1);
1757  bool dp_operation = (instr->SzValue() == 1);
1758  if (to_integer) {
1759  bool unsigned_integer = (instr->Bit(16) == 0);
1760 
1761  if (dp_operation) {
1762  if (unsigned_integer) {
1763  Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
1764  } else {
1765  Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
1766  }
1767  } else {
1768  if (unsigned_integer) {
1769  Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
1770  } else {
1771  Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
1772  }
1773  }
1774  } else {
1775  bool unsigned_integer = (instr->Bit(7) == 0);
1776 
1777  if (dp_operation) {
1778  if (unsigned_integer) {
1779  Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
1780  } else {
1781  Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
1782  }
1783  } else {
1784  if (unsigned_integer) {
1785  Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
1786  } else {
1787  Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
1788  }
1789  }
1790  }
1791 }
1792 
1793 
1794 // Decode Type 6 coprocessor instructions.
1795 // Dm = vmov(Rt, Rt2)
1796 // <Rt, Rt2> = vmov(Dm)
1797 // Ddst = MEM(Rbase + 4*offset).
1798 // MEM(Rbase + 4*offset) = Dsrc.
1799 void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
1800  VERIFY(instr->TypeValue() == 6);
1801 
1802  if (instr->CoprocessorValue() == 0xA) {
1803  switch (instr->OpcodeValue()) {
1804  case 0x8:
1805  case 0xA:
1806  if (instr->HasL()) {
1807  Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1808  } else {
1809  Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1810  }
1811  break;
1812  case 0xC:
1813  case 0xE:
1814  if (instr->HasL()) {
1815  Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1816  } else {
1817  Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1818  }
1819  break;
1820  case 0x4:
1821  case 0x5:
1822  case 0x6:
1823  case 0x7:
1824  case 0x9:
1825  case 0xB: {
1826  bool to_vfp_register = (instr->VLValue() == 0x1);
1827  if (to_vfp_register) {
1828  Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
1829  } else {
1830  Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
1831  }
1832  break;
1833  }
1834  default:
1835  Unknown(instr); // Not used by V8.
1836  }
1837  } else if (instr->CoprocessorValue() == 0xB) {
1838  switch (instr->OpcodeValue()) {
1839  case 0x2:
1840  // Load and store double to two GP registers
1841  if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
1842  Unknown(instr); // Not used by V8.
1843  } else if (instr->HasL()) {
1844  Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1845  } else {
1846  Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1847  }
1848  break;
1849  case 0x8:
1850  case 0xA:
1851  if (instr->HasL()) {
1852  Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1853  } else {
1854  Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1855  }
1856  break;
1857  case 0xC:
1858  case 0xE:
1859  if (instr->HasL()) {
1860  Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1861  } else {
1862  Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1863  }
1864  break;
1865  case 0x4:
1866  case 0x5:
1867  case 0x6:
1868  case 0x7:
1869  case 0x9:
1870  case 0xB: {
1871  bool to_vfp_register = (instr->VLValue() == 0x1);
1872  if (to_vfp_register) {
1873  Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
1874  } else {
1875  Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
1876  }
1877  break;
1878  }
1879  default:
1880  Unknown(instr); // Not used by V8.
1881  }
1882  } else {
1883  Unknown(instr); // Not used by V8.
1884  }
1885 }
1886 
1887 
1888 static const char* const barrier_option_names[] = {
1889  "invalid", "oshld", "oshst", "osh", "invalid", "nshld", "nshst", "nsh",
1890  "invalid", "ishld", "ishst", "ish", "invalid", "ld", "st", "sy",
1891 };
1892 
1893 
1894 void Decoder::DecodeSpecialCondition(Instruction* instr) {
1895  switch (instr->SpecialValue()) {
1896  case 4: {
1897  int Vd, Vm, Vn;
1898  if (instr->Bit(6) == 0) {
1899  Vd = instr->VFPDRegValue(kDoublePrecision);
1900  Vm = instr->VFPMRegValue(kDoublePrecision);
1901  Vn = instr->VFPNRegValue(kDoublePrecision);
1902  } else {
1903  Vd = instr->VFPDRegValue(kSimd128Precision);
1904  Vm = instr->VFPMRegValue(kSimd128Precision);
1905  Vn = instr->VFPNRegValue(kSimd128Precision);
1906  }
1907  int size = kBitsPerByte * (1 << instr->Bits(21, 20));
1908  switch (instr->Bits(11, 8)) {
1909  case 0x0: {
1910  if (instr->Bit(4) == 1) {
1911  // vqadd.s<size> Qd, Qm, Qn.
1912  out_buffer_pos_ +=
1913  SNPrintF(out_buffer_ + out_buffer_pos_,
1914  "vqadd.s%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1915  } else {
1916  Unknown(instr);
1917  }
1918  break;
1919  }
1920  case 0x1: {
1921  if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 &&
1922  instr->Bit(4) == 1) {
1923  if (Vm == Vn) {
1924  // vmov Qd, Qm
1925  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1926  "vmov q%d, q%d", Vd, Vm);
1927  } else {
1928  // vorr Qd, Qm, Qn.
1929  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1930  "vorr q%d, q%d, q%d", Vd, Vn, Vm);
1931  }
1932  } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
1933  instr->Bit(4) == 1) {
1934  // vand Qd, Qm, Qn.
1935  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1936  "vand q%d, q%d, q%d", Vd, Vn, Vm);
1937  } else {
1938  Unknown(instr);
1939  }
1940  break;
1941  }
1942  case 0x2: {
1943  if (instr->Bit(4) == 1) {
1944  // vqsub.s<size> Qd, Qm, Qn.
1945  out_buffer_pos_ +=
1946  SNPrintF(out_buffer_ + out_buffer_pos_,
1947  "vqsub.s%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1948  } else {
1949  Unknown(instr);
1950  }
1951  break;
1952  }
1953  case 0x3: {
1954  const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt";
1955  // vcge/vcgt.s<size> Qd, Qm, Qn.
1956  out_buffer_pos_ +=
1957  SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d",
1958  op, size, Vd, Vn, Vm);
1959  break;
1960  }
1961  case 0x6: {
1962  // vmin/vmax.s<size> Qd, Qm, Qn.
1963  const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax";
1964  out_buffer_pos_ +=
1965  SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d",
1966  op, size, Vd, Vn, Vm);
1967  break;
1968  }
1969  case 0x8: {
1970  const char* op = (instr->Bit(4) == 0) ? "vadd" : "vtst";
1971  // vadd/vtst.i<size> Qd, Qm, Qn.
1972  out_buffer_pos_ +=
1973  SNPrintF(out_buffer_ + out_buffer_pos_, "%s.i%d q%d, q%d, q%d",
1974  op, size, Vd, Vn, Vm);
1975  break;
1976  }
1977  case 0x9: {
1978  if (instr->Bit(6) == 1 && instr->Bit(4) == 1) {
1979  // vmul.i<size> Qd, Qm, Qn.
1980  out_buffer_pos_ +=
1981  SNPrintF(out_buffer_ + out_buffer_pos_,
1982  "vmul.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1983  } else {
1984  Unknown(instr);
1985  }
1986  break;
1987  }
1988  case 0xA: {
1989  // vpmin/vpmax.s<size> Dd, Dm, Dn.
1990  const char* op = instr->Bit(4) == 1 ? "vpmin" : "vpmax";
1991  out_buffer_pos_ +=
1992  SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d d%d, d%d, d%d",
1993  op, size, Vd, Vn, Vm);
1994  break;
1995  }
1996  case 0xB: {
1997  // vpadd.i<size> Dd, Dm, Dn.
1998  out_buffer_pos_ +=
1999  SNPrintF(out_buffer_ + out_buffer_pos_, "vpadd.i%d d%d, d%d, d%d",
2000  size, Vd, Vn, Vm);
2001  break;
2002  }
2003  case 0xD: {
2004  if (instr->Bit(4) == 0) {
2005  const char* op = (instr->Bits(21, 20) == 0) ? "vadd" : "vsub";
2006  // vadd/vsub.f32 Qd, Qm, Qn.
2007  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2008  "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2009  } else {
2010  Unknown(instr);
2011  }
2012  break;
2013  }
2014  case 0xE: {
2015  if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) {
2016  // vceq.f32 Qd, Qm, Qn.
2017  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2018  "vceq.f32 q%d, q%d, q%d", Vd, Vn, Vm);
2019  } else {
2020  Unknown(instr);
2021  }
2022  break;
2023  }
2024  case 0xF: {
2025  if (instr->Bit(20) == 0 && instr->Bit(6) == 1) {
2026  if (instr->Bit(4) == 1) {
2027  // vrecps/vrsqrts.f32 Qd, Qm, Qn.
2028  const char* op = instr->Bit(21) == 0 ? "vrecps" : "vrsqrts";
2029  out_buffer_pos_ +=
2030  SNPrintF(out_buffer_ + out_buffer_pos_,
2031  "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2032  } else {
2033  // vmin/max.f32 Qd, Qm, Qn.
2034  const char* op = instr->Bit(21) == 1 ? "vmin" : "vmax";
2035  out_buffer_pos_ +=
2036  SNPrintF(out_buffer_ + out_buffer_pos_,
2037  "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2038  }
2039  } else {
2040  Unknown(instr);
2041  }
2042  break;
2043  }
2044  default:
2045  Unknown(instr);
2046  break;
2047  }
2048  break;
2049  }
2050  case 5:
2051  if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
2052  (instr->Bit(4) == 1)) {
2053  // vmovl signed
2054  if ((instr->VdValue() & 1) != 0) Unknown(instr);
2055  int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
2056  int Vm = (instr->Bit(5) << 4) | instr->VmValue();
2057  int imm3 = instr->Bits(21, 19);
2058  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2059  "vmovl.s%d q%d, d%d", imm3 * 8, Vd, Vm);
2060  } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) {
2061  // vext.8 Qd, Qm, Qn, imm4
2062  int imm4 = instr->Bits(11, 8);
2063  int Vd = instr->VFPDRegValue(kSimd128Precision);
2064  int Vm = instr->VFPMRegValue(kSimd128Precision);
2065  int Vn = instr->VFPNRegValue(kSimd128Precision);
2066  out_buffer_pos_ +=
2067  SNPrintF(out_buffer_ + out_buffer_pos_, "vext.8 q%d, q%d, q%d, #%d",
2068  Vd, Vn, Vm, imm4);
2069  } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) {
2070  // vshl.i<size> Qd, Qm, shift
2071  int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2072  int shift = instr->Bits(21, 16) - size;
2073  int Vd = instr->VFPDRegValue(kSimd128Precision);
2074  int Vm = instr->VFPMRegValue(kSimd128Precision);
2075  out_buffer_pos_ +=
2076  SNPrintF(out_buffer_ + out_buffer_pos_, "vshl.i%d q%d, q%d, #%d",
2077  size, Vd, Vm, shift);
2078  } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
2079  // vshr.s<size> Qd, Qm, shift
2080  int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2081  int shift = 2 * size - instr->Bits(21, 16);
2082  int Vd = instr->VFPDRegValue(kSimd128Precision);
2083  int Vm = instr->VFPMRegValue(kSimd128Precision);
2084  out_buffer_pos_ +=
2085  SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.s%d q%d, q%d, #%d",
2086  size, Vd, Vm, shift);
2087  } else {
2088  Unknown(instr);
2089  }
2090  break;
2091  case 6: {
2092  int Vd, Vm, Vn;
2093  if (instr->Bit(6) == 0) {
2094  Vd = instr->VFPDRegValue(kDoublePrecision);
2095  Vm = instr->VFPMRegValue(kDoublePrecision);
2096  Vn = instr->VFPNRegValue(kDoublePrecision);
2097  } else {
2098  Vd = instr->VFPDRegValue(kSimd128Precision);
2099  Vm = instr->VFPMRegValue(kSimd128Precision);
2100  Vn = instr->VFPNRegValue(kSimd128Precision);
2101  }
2102  int size = kBitsPerByte * (1 << instr->Bits(21, 20));
2103  switch (instr->Bits(11, 8)) {
2104  case 0x0: {
2105  if (instr->Bit(4) == 1) {
2106  // vqadd.u<size> Qd, Qm, Qn.
2107  out_buffer_pos_ +=
2108  SNPrintF(out_buffer_ + out_buffer_pos_,
2109  "vqadd.u%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2110  } else {
2111  Unknown(instr);
2112  }
2113  break;
2114  }
2115  case 0x1: {
2116  if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) {
2117  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2118  "vbsl q%d, q%d, q%d", Vd, Vn, Vm);
2119  } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) {
2120  if (instr->Bit(6) == 0) {
2121  // veor Dd, Dn, Dm
2122  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2123  "veor d%d, d%d, d%d", Vd, Vn, Vm);
2124 
2125  } else {
2126  // veor Qd, Qn, Qm
2127  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2128  "veor q%d, q%d, q%d", Vd, Vn, Vm);
2129  }
2130  } else {
2131  Unknown(instr);
2132  }
2133  break;
2134  }
2135  case 0x2: {
2136  if (instr->Bit(4) == 1) {
2137  // vqsub.u<size> Qd, Qm, Qn.
2138  out_buffer_pos_ +=
2139  SNPrintF(out_buffer_ + out_buffer_pos_,
2140  "vqsub.u%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2141  } else {
2142  Unknown(instr);
2143  }
2144  break;
2145  }
2146  case 0x3: {
2147  const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt";
2148  // vcge/vcgt.u<size> Qd, Qm, Qn.
2149  out_buffer_pos_ +=
2150  SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d",
2151  op, size, Vd, Vn, Vm);
2152  break;
2153  }
2154  case 0x6: {
2155  // vmin/vmax.u<size> Qd, Qm, Qn.
2156  const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax";
2157  out_buffer_pos_ +=
2158  SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d",
2159  op, size, Vd, Vn, Vm);
2160  break;
2161  }
2162  case 0x8: {
2163  if (instr->Bit(4) == 0) {
2164  out_buffer_pos_ +=
2165  SNPrintF(out_buffer_ + out_buffer_pos_,
2166  "vsub.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2167  } else {
2168  out_buffer_pos_ +=
2169  SNPrintF(out_buffer_ + out_buffer_pos_,
2170  "vceq.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2171  }
2172  break;
2173  }
2174  case 0xA: {
2175  // vpmin/vpmax.u<size> Dd, Dm, Dn.
2176  const char* op = instr->Bit(4) == 1 ? "vpmin" : "vpmax";
2177  out_buffer_pos_ +=
2178  SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d d%d, d%d, d%d",
2179  op, size, Vd, Vn, Vm);
2180  break;
2181  }
2182  case 0xD: {
2183  if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
2184  instr->Bit(4) == 1) {
2185  // vmul.f32 Qd, Qm, Qn
2186  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2187  "vmul.f32 q%d, q%d, q%d", Vd, Vn, Vm);
2188  } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 0 &&
2189  instr->Bit(4) == 0) {
2190  // vpadd.f32 Dd, Dm, Dn.
2191  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2192  "vpadd.f32 d%d, d%d, d%d", Vd, Vn, Vm);
2193  } else {
2194  Unknown(instr);
2195  }
2196  break;
2197  }
2198  case 0xE: {
2199  if (instr->Bit(20) == 0 && instr->Bit(4) == 0) {
2200  const char* op = (instr->Bit(21) == 0) ? "vcge" : "vcgt";
2201  // vcge/vcgt.f32 Qd, Qm, Qn.
2202  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2203  "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2204  } else {
2205  Unknown(instr);
2206  }
2207  break;
2208  }
2209  default:
2210  Unknown(instr);
2211  break;
2212  }
2213  break;
2214  }
2215  case 7:
2216  if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
2217  (instr->Bit(4) == 1)) {
2218  // vmovl unsigned
2219  if ((instr->VdValue() & 1) != 0) Unknown(instr);
2220  int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
2221  int Vm = (instr->Bit(5) << 4) | instr->VmValue();
2222  int imm3 = instr->Bits(21, 19);
2223  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2224  "vmovl.u%d q%d, d%d", imm3 * 8, Vd, Vm);
2225  } else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) {
2226  if (instr->Bits(11, 7) == 0x18) {
2227  int Vm = instr->VFPMRegValue(kDoublePrecision);
2228  int imm4 = instr->Bits(19, 16);
2229  int size = 0, index = 0;
2230  if ((imm4 & 0x1) != 0) {
2231  size = 8;
2232  index = imm4 >> 1;
2233  } else if ((imm4 & 0x2) != 0) {
2234  size = 16;
2235  index = imm4 >> 2;
2236  } else {
2237  size = 32;
2238  index = imm4 >> 3;
2239  }
2240  if (instr->Bit(6) == 0) {
2241  int Vd = instr->VFPDRegValue(kDoublePrecision);
2242  out_buffer_pos_ +=
2243  SNPrintF(out_buffer_ + out_buffer_pos_, "vdup.%i d%d, d%d[%d]",
2244  size, Vd, Vm, index);
2245  } else {
2246  int Vd = instr->VFPDRegValue(kSimd128Precision);
2247  out_buffer_pos_ +=
2248  SNPrintF(out_buffer_ + out_buffer_pos_, "vdup.%i q%d, d%d[%d]",
2249  size, Vd, Vm, index);
2250  }
2251  } else if (instr->Bits(11, 10) == 0x2) {
2252  int Vd = instr->VFPDRegValue(kDoublePrecision);
2253  int Vn = instr->VFPNRegValue(kDoublePrecision);
2254  int Vm = instr->VFPMRegValue(kDoublePrecision);
2255  int len = instr->Bits(9, 8);
2256  NeonListOperand list(DwVfpRegister::from_code(Vn), len + 1);
2257  out_buffer_pos_ +=
2258  SNPrintF(out_buffer_ + out_buffer_pos_, "%s d%d, ",
2259  instr->Bit(6) == 0 ? "vtbl.8" : "vtbx.8", Vd);
2260  FormatNeonList(Vn, list.type());
2261  Print(", ");
2262  PrintDRegister(Vm);
2263  } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x2 &&
2264  instr->Bits(7, 6) != 0) {
2265  // vqmovn.<type><size> Dd, Qm.
2266  int Vd = instr->VFPDRegValue(kDoublePrecision);
2267  int Vm = instr->VFPMRegValue(kSimd128Precision);
2268  char type = instr->Bit(6) != 0 ? 'u' : 's';
2269  int size = 2 * kBitsPerByte * (1 << instr->Bits(19, 18));
2270  out_buffer_pos_ +=
2271  SNPrintF(out_buffer_ + out_buffer_pos_, "vqmovn.%c%i d%d, q%d",
2272  type, size, Vd, Vm);
2273  } else {
2274  int Vd, Vm;
2275  if (instr->Bit(6) == 0) {
2276  Vd = instr->VFPDRegValue(kDoublePrecision);
2277  Vm = instr->VFPMRegValue(kDoublePrecision);
2278  } else {
2279  Vd = instr->VFPDRegValue(kSimd128Precision);
2280  Vm = instr->VFPMRegValue(kSimd128Precision);
2281  }
2282  if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) {
2283  if (instr->Bit(6) == 0) {
2284  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2285  "vswp d%d, d%d", Vd, Vm);
2286  } else {
2287  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2288  "vswp q%d, q%d", Vd, Vm);
2289  }
2290  } else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) {
2291  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2292  "vmvn q%d, q%d", Vd, Vm);
2293  } else if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 &&
2294  instr->Bit(6) == 1) {
2295  const char* suffix = nullptr;
2296  int op = instr->Bits(8, 7);
2297  switch (op) {
2298  case 0:
2299  suffix = "f32.s32";
2300  break;
2301  case 1:
2302  suffix = "f32.u32";
2303  break;
2304  case 2:
2305  suffix = "s32.f32";
2306  break;
2307  case 3:
2308  suffix = "u32.f32";
2309  break;
2310  }
2311  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2312  "vcvt.%s q%d, q%d", suffix, Vd, Vm);
2313  } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x1) {
2314  int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2315  const char* op = instr->Bit(7) != 0 ? "vzip" : "vuzp";
2316  if (instr->Bit(6) == 0) {
2317  // vzip/vuzp.<size> Dd, Dm.
2318  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2319  "%s.%d d%d, d%d", op, size, Vd, Vm);
2320  } else {
2321  // vzip/vuzp.<size> Qd, Qm.
2322  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2323  "%s.%d q%d, q%d", op, size, Vd, Vm);
2324  }
2325  } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0 &&
2326  instr->Bit(6) == 1) {
2327  int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2328  int op = kBitsPerByte
2329  << (static_cast<int>(Neon64) - instr->Bits(8, 7));
2330  // vrev<op>.<size> Qd, Qm.
2331  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2332  "vrev%d.%d q%d, q%d", op, size, Vd, Vm);
2333  } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0x1) {
2334  int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2335  if (instr->Bit(6) == 0) {
2336  // vtrn.<size> Dd, Dm.
2337  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2338  "vtrn.%d d%d, d%d", size, Vd, Vm);
2339  } else {
2340  // vtrn.<size> Qd, Qm.
2341  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2342  "vtrn.%d q%d, q%d", size, Vd, Vm);
2343  }
2344  } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0 &&
2345  instr->Bit(6) == 1) {
2346  int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2347  char type = instr->Bit(10) != 0 ? 'f' : 's';
2348  if (instr->Bits(9, 6) == 0xD) {
2349  // vabs<type>.<size> Qd, Qm.
2350  out_buffer_pos_ +=
2351  SNPrintF(out_buffer_ + out_buffer_pos_, "vabs.%c%d q%d, q%d",
2352  type, size, Vd, Vm);
2353  } else if (instr->Bits(9, 6) == 0xF) {
2354  // vneg<type>.<size> Qd, Qm.
2355  out_buffer_pos_ +=
2356  SNPrintF(out_buffer_ + out_buffer_pos_, "vneg.%c%d q%d, q%d",
2357  type, size, Vd, Vm);
2358  } else {
2359  Unknown(instr);
2360  }
2361  } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5 &&
2362  instr->Bit(6) == 1) {
2363  // vrecpe/vrsqrte.f32 Qd, Qm.
2364  const char* op = instr->Bit(7) == 0 ? "vrecpe" : "vrsqrte";
2365  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2366  "%s.f32 q%d, q%d", op, Vd, Vm);
2367  } else {
2368  Unknown(instr);
2369  }
2370  }
2371  } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1 &&
2372  instr->Bit(6) == 1) {
2373  // vshr.u<size> Qd, Qm, shift
2374  int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2375  int shift = 2 * size - instr->Bits(21, 16);
2376  int Vd = instr->VFPDRegValue(kSimd128Precision);
2377  int Vm = instr->VFPMRegValue(kSimd128Precision);
2378  out_buffer_pos_ +=
2379  SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.u%d q%d, q%d, #%d",
2380  size, Vd, Vm, shift);
2381  } else if (instr->Bit(10) == 1 && instr->Bit(6) == 0 &&
2382  instr->Bit(4) == 1) {
2383  // vsli.<size> Dd, Dm, shift
2384  // vsri.<size> Dd, Dm, shift
2385  int imm7 = instr->Bits(21, 16);
2386  if (instr->Bit(7) != 0) imm7 += 64;
2387  int size = base::bits::RoundDownToPowerOfTwo32(imm7);
2388  int shift;
2389  char direction;
2390  if (instr->Bit(8) == 1) {
2391  shift = imm7 - size;
2392  direction = 'l'; // vsli
2393  } else {
2394  shift = 2 * size - imm7;
2395  direction = 'r'; // vsri
2396  }
2397  int Vd = instr->VFPDRegValue(kDoublePrecision);
2398  int Vm = instr->VFPMRegValue(kDoublePrecision);
2399  out_buffer_pos_ +=
2400  SNPrintF(out_buffer_ + out_buffer_pos_, "vs%ci.%d d%d, d%d, #%d",
2401  direction, size, Vd, Vm, shift);
2402  } else {
2403  Unknown(instr);
2404  }
2405  break;
2406  case 8:
2407  if (instr->Bits(21, 20) == 0) {
2408  // vst1
2409  int Vd = (instr->Bit(22) << 4) | instr->VdValue();
2410  int Rn = instr->VnValue();
2411  int type = instr->Bits(11, 8);
2412  int size = instr->Bits(7, 6);
2413  int align = instr->Bits(5, 4);
2414  int Rm = instr->VmValue();
2415  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vst1.%d ",
2416  (1 << size) << 3);
2417  FormatNeonList(Vd, type);
2418  Print(", ");
2419  FormatNeonMemory(Rn, align, Rm);
2420  } else if (instr->Bits(21, 20) == 2) {
2421  // vld1
2422  int Vd = (instr->Bit(22) << 4) | instr->VdValue();
2423  int Rn = instr->VnValue();
2424  int type = instr->Bits(11, 8);
2425  int size = instr->Bits(7, 6);
2426  int align = instr->Bits(5, 4);
2427  int Rm = instr->VmValue();
2428  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vld1.%d ",
2429  (1 << size) << 3);
2430  FormatNeonList(Vd, type);
2431  Print(", ");
2432  FormatNeonMemory(Rn, align, Rm);
2433  } else {
2434  Unknown(instr);
2435  }
2436  break;
2437  case 0xA:
2438  case 0xB:
2439  if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xF)) {
2440  const char* rn_name = converter_.NameOfCPURegister(instr->Bits(19, 16));
2441  int offset = instr->Bits(11, 0);
2442  if (offset == 0) {
2443  out_buffer_pos_ +=
2444  SNPrintF(out_buffer_ + out_buffer_pos_, "pld [%s]", rn_name);
2445  } else if (instr->Bit(23) == 0) {
2446  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2447  "pld [%s, #-%d]", rn_name, offset);
2448  } else {
2449  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2450  "pld [%s, #+%d]", rn_name, offset);
2451  }
2452  } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) {
2453  int option = instr->Bits(3, 0);
2454  switch (instr->Bits(7, 4)) {
2455  case 4:
2456  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "dsb %s",
2457  barrier_option_names[option]);
2458  break;
2459  case 5:
2460  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "dmb %s",
2461  barrier_option_names[option]);
2462  break;
2463  case 6:
2464  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "isb %s",
2465  barrier_option_names[option]);
2466  break;
2467  default:
2468  Unknown(instr);
2469  }
2470  } else {
2471  Unknown(instr);
2472  }
2473  break;
2474  case 0x1D:
2475  if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 &&
2476  instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 &&
2477  instr->Bit(4) == 0x0) {
2478  // VRINTA, VRINTN, VRINTP, VRINTM (floating-point)
2479  bool dp_operation = (instr->SzValue() == 1);
2480  int rounding_mode = instr->Bits(17, 16);
2481  switch (rounding_mode) {
2482  case 0x0:
2483  if (dp_operation) {
2484  Format(instr, "vrinta.f64.f64 'Dd, 'Dm");
2485  } else {
2486  Format(instr, "vrinta.f32.f32 'Sd, 'Sm");
2487  }
2488  break;
2489  case 0x1:
2490  if (dp_operation) {
2491  Format(instr, "vrintn.f64.f64 'Dd, 'Dm");
2492  } else {
2493  Format(instr, "vrintn.f32.f32 'Sd, 'Sm");
2494  }
2495  break;
2496  case 0x2:
2497  if (dp_operation) {
2498  Format(instr, "vrintp.f64.f64 'Dd, 'Dm");
2499  } else {
2500  Format(instr, "vrintp.f32.f32 'Sd, 'Sm");
2501  }
2502  break;
2503  case 0x3:
2504  if (dp_operation) {
2505  Format(instr, "vrintm.f64.f64 'Dd, 'Dm");
2506  } else {
2507  Format(instr, "vrintm.f32.f32 'Sd, 'Sm");
2508  }
2509  break;
2510  default:
2511  UNREACHABLE(); // Case analysis is exhaustive.
2512  break;
2513  }
2514  } else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) &&
2515  (instr->Bit(4) == 0x0)) {
2516  // VMAXNM, VMINNM (floating-point)
2517  if (instr->SzValue() == 0x1) {
2518  if (instr->Bit(6) == 0x1) {
2519  Format(instr, "vminnm.f64 'Dd, 'Dn, 'Dm");
2520  } else {
2521  Format(instr, "vmaxnm.f64 'Dd, 'Dn, 'Dm");
2522  }
2523  } else {
2524  if (instr->Bit(6) == 0x1) {
2525  Format(instr, "vminnm.f32 'Sd, 'Sn, 'Sm");
2526  } else {
2527  Format(instr, "vmaxnm.f32 'Sd, 'Sn, 'Sm");
2528  }
2529  }
2530  } else {
2531  Unknown(instr);
2532  }
2533  break;
2534  case 0x1C:
2535  if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
2536  (instr->Bit(4) == 0)) {
2537  // VSEL* (floating-point)
2538  bool dp_operation = (instr->SzValue() == 1);
2539  switch (instr->Bits(21, 20)) {
2540  case 0x0:
2541  if (dp_operation) {
2542  Format(instr, "vseleq.f64 'Dd, 'Dn, 'Dm");
2543  } else {
2544  Format(instr, "vseleq.f32 'Sd, 'Sn, 'Sm");
2545  }
2546  break;
2547  case 0x1:
2548  if (dp_operation) {
2549  Format(instr, "vselvs.f64 'Dd, 'Dn, 'Dm");
2550  } else {
2551  Format(instr, "vselvs.f32 'Sd, 'Sn, 'Sm");
2552  }
2553  break;
2554  case 0x2:
2555  if (dp_operation) {
2556  Format(instr, "vselge.f64 'Dd, 'Dn, 'Dm");
2557  } else {
2558  Format(instr, "vselge.f32 'Sd, 'Sn, 'Sm");
2559  }
2560  break;
2561  case 0x3:
2562  if (dp_operation) {
2563  Format(instr, "vselgt.f64 'Dd, 'Dn, 'Dm");
2564  } else {
2565  Format(instr, "vselgt.f32 'Sd, 'Sn, 'Sm");
2566  }
2567  break;
2568  default:
2569  UNREACHABLE(); // Case analysis is exhaustive.
2570  break;
2571  }
2572  } else {
2573  Unknown(instr);
2574  }
2575  break;
2576  default:
2577  Unknown(instr);
2578  break;
2579  }
2580 }
2581 
2582 #undef VERIFIY
2583 
2584 bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
2585  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2586  return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
2587 }
2588 
2589 
2590 int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
2591  if (IsConstantPoolAt(instr_ptr)) {
2592  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2593  return DecodeConstantPoolLength(instruction_bits);
2594  } else {
2595  return -1;
2596  }
2597 }
2598 
2599 
2600 // Disassemble the instruction at *instr_ptr into the output buffer.
2601 int Decoder::InstructionDecode(byte* instr_ptr) {
2602  Instruction* instr = Instruction::At(reinterpret_cast<Address>(instr_ptr));
2603  // Print raw instruction bytes.
2604  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2605  "%08x ",
2606  instr->InstructionBits());
2607  if (instr->ConditionField() == kSpecialCondition) {
2608  DecodeSpecialCondition(instr);
2609  return kInstrSize;
2610  }
2611  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2612  if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
2613  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2614  "constant pool begin (length %d)",
2615  DecodeConstantPoolLength(instruction_bits));
2616  return kInstrSize;
2617  }
2618  switch (instr->TypeValue()) {
2619  case 0:
2620  case 1: {
2621  DecodeType01(instr);
2622  break;
2623  }
2624  case 2: {
2625  DecodeType2(instr);
2626  break;
2627  }
2628  case 3: {
2629  DecodeType3(instr);
2630  break;
2631  }
2632  case 4: {
2633  DecodeType4(instr);
2634  break;
2635  }
2636  case 5: {
2637  DecodeType5(instr);
2638  break;
2639  }
2640  case 6: {
2641  DecodeType6(instr);
2642  break;
2643  }
2644  case 7: {
2645  return DecodeType7(instr);
2646  }
2647  default: {
2648  // The type field is 3-bits in the ARM encoding.
2649  UNREACHABLE();
2650  break;
2651  }
2652  }
2653  return kInstrSize;
2654 }
2655 
2656 
2657 } // namespace internal
2658 } // namespace v8
2659 
2660 
2661 //------------------------------------------------------------------------------
2662 
2663 namespace disasm {
2664 
2665 
2666 const char* NameConverter::NameOfAddress(byte* addr) const {
2667  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
2668  return tmp_buffer_.start();
2669 }
2670 
2671 
2672 const char* NameConverter::NameOfConstant(byte* addr) const {
2673  return NameOfAddress(addr);
2674 }
2675 
2676 
2677 const char* NameConverter::NameOfCPURegister(int reg) const {
2678  return RegisterName(i::Register::from_code(reg));
2679 }
2680 
2681 
2682 const char* NameConverter::NameOfByteCPURegister(int reg) const {
2683  UNREACHABLE(); // ARM does not have the concept of a byte register
2684  return "nobytereg";
2685 }
2686 
2687 
2688 const char* NameConverter::NameOfXMMRegister(int reg) const {
2689  UNREACHABLE(); // ARM does not have any XMM registers
2690  return "noxmmreg";
2691 }
2692 
2693 
2694 const char* NameConverter::NameInCode(byte* addr) const {
2695  // The default name converter is called for unknown code. So we will not try
2696  // to access any memory.
2697  return "";
2698 }
2699 
2700 
2701 //------------------------------------------------------------------------------
2702 
2703 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
2704  byte* instruction) {
2705  v8::internal::Decoder d(converter_, buffer);
2706  return d.InstructionDecode(instruction);
2707 }
2708 
2709 
2710 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2711  return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
2712 }
2713 
2714 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
2715  UnimplementedOpcodeAction unimplemented_action) {
2716  NameConverter converter;
2717  Disassembler d(converter, unimplemented_action);
2718  for (byte* pc = begin; pc < end;) {
2720  buffer[0] = '\0';
2721  byte* prev_pc = pc;
2722  pc += d.InstructionDecode(buffer, pc);
2723  v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc),
2724  *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
2725  }
2726 }
2727 
2728 } // namespace disasm
2729 
2730 #endif // V8_TARGET_ARCH_ARM
Definition: libplatform.h:13
Definition: disasm.h:10