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