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