• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // A Disassembler object is used to disassemble a block of code instruction by
6 // instruction. The default implementation of the NameConverter object can be
7 // overriden to modify register names or to do symbol lookup on addresses.
8 //
9 // The example below will disassemble a block of code and print it to stdout.
10 //
11 //   NameConverter converter;
12 //   Disassembler d(converter);
13 //   for (byte* pc = begin; pc < end;) {
14 //     v8::internal::EmbeddedVector<char, 256> buffer;
15 //     byte* prev_pc = pc;
16 //     pc += d.InstructionDecode(buffer, pc);
17 //     printf("%p    %08x      %s\n",
18 //            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
19 //   }
20 //
21 // The Disassembler class also has a convenience method to disassemble a block
22 // of code into a FILE*, meaning that the above functionality could also be
23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
24 
25 
26 #include <assert.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #if V8_TARGET_ARCH_ARM
32 
33 #include "src/arm/constants-arm.h"
34 #include "src/base/bits.h"
35 #include "src/base/platform/platform.h"
36 #include "src/disasm.h"
37 #include "src/macro-assembler.h"
38 
39 
40 namespace v8 {
41 namespace internal {
42 
43 const auto GetRegConfig = RegisterConfiguration::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::kPcLoadDelta;
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 1:
790                 Format(instr, "ldrexd'cond 'rt, ['rn]");
791                 break;
792               case 2:
793                 Format(instr, "ldrexb'cond 'rt, ['rn]");
794                 break;
795               case 3:
796                 Format(instr, "ldrexh'cond 'rt, ['rn]");
797                 break;
798               default:
799                 UNREACHABLE();
800                 break;
801             }
802           } else {
803             // strex
804             // The instruction is documented as strex rd, rt, [rn], but the
805             // "rt" register is using the rm bits.
806             switch (instr->Bits(22, 21)) {
807               case 0:
808                 Format(instr, "strex'cond 'rd, 'rm, ['rn]");
809                 break;
810               case 1:
811                 Format(instr, "strexd'cond 'rd, 'rm, ['rn]");
812                 break;
813               case 2:
814                 Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
815                 break;
816               case 3:
817                 Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
818                 break;
819               default:
820                 UNREACHABLE();
821                 break;
822             }
823           }
824         } else {
825           Unknown(instr);  // not used by V8
826         }
827       }
828     } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xD) == 0xD)) {
829       // ldrd, strd
830       switch (instr->PUField()) {
831         case da_x: {
832           if (instr->Bit(22) == 0) {
833             Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
834           } else {
835             Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
836           }
837           break;
838         }
839         case ia_x: {
840           if (instr->Bit(22) == 0) {
841             Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
842           } else {
843             Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
844           }
845           break;
846         }
847         case db_x: {
848           if (instr->Bit(22) == 0) {
849             Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
850           } else {
851             Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
852           }
853           break;
854         }
855         case ib_x: {
856           if (instr->Bit(22) == 0) {
857             Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
858           } else {
859             Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
860           }
861           break;
862         }
863         default: {
864           // The PU field is a 2-bit field.
865           UNREACHABLE();
866           break;
867         }
868       }
869     } else {
870       // extra load/store instructions
871       switch (instr->PUField()) {
872         case da_x: {
873           if (instr->Bit(22) == 0) {
874             Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
875           } else {
876             Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
877           }
878           break;
879         }
880         case ia_x: {
881           if (instr->Bit(22) == 0) {
882             Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
883           } else {
884             Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
885           }
886           break;
887         }
888         case db_x: {
889           if (instr->Bit(22) == 0) {
890             Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
891           } else {
892             Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
893           }
894           break;
895         }
896         case ib_x: {
897           if (instr->Bit(22) == 0) {
898             Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
899           } else {
900             Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
901           }
902           break;
903         }
904         default: {
905           // The PU field is a 2-bit field.
906           UNREACHABLE();
907           break;
908         }
909       }
910       return;
911     }
912   } else if ((type == 0) && instr->IsMiscType0()) {
913     if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
914         (instr->Bits(15, 4) == 0xF00)) {
915       Format(instr, "msr'cond 'spec_reg'spec_reg_fields, 'rm");
916     } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
917                (instr->Bits(11, 0) == 0)) {
918       Format(instr, "mrs'cond 'rd, 'spec_reg");
919     } else if (instr->Bits(22, 21) == 1) {
920       switch (instr->BitField(7, 4)) {
921         case BX:
922           Format(instr, "bx'cond 'rm");
923           break;
924         case BLX:
925           Format(instr, "blx'cond 'rm");
926           break;
927         case BKPT:
928           Format(instr, "bkpt 'off0to3and8to19");
929           break;
930         default:
931           Unknown(instr);  // not used by V8
932           break;
933       }
934     } else if (instr->Bits(22, 21) == 3) {
935       switch (instr->BitField(7, 4)) {
936         case CLZ:
937           Format(instr, "clz'cond 'rd, 'rm");
938           break;
939         default:
940           Unknown(instr);  // not used by V8
941           break;
942       }
943     } else {
944       Unknown(instr);  // not used by V8
945     }
946   } else if ((type == 1) && instr->IsNopLikeType1()) {
947     if (instr->BitField(7, 0) == 0) {
948       Format(instr, "nop'cond");
949     } else if (instr->BitField(7, 0) == 20) {
950       Format(instr, "csdb");
951     } else {
952       Unknown(instr);  // Not used in V8.
953     }
954   } else {
955     switch (instr->OpcodeField()) {
956       case AND: {
957         Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
958         break;
959       }
960       case EOR: {
961         Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
962         break;
963       }
964       case SUB: {
965         Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
966         break;
967       }
968       case RSB: {
969         Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
970         break;
971       }
972       case ADD: {
973         Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
974         break;
975       }
976       case ADC: {
977         Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
978         break;
979       }
980       case SBC: {
981         Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
982         break;
983       }
984       case RSC: {
985         Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
986         break;
987       }
988       case TST: {
989         if (instr->HasS()) {
990           Format(instr, "tst'cond 'rn, 'shift_op");
991         } else {
992           Format(instr, "movw'cond 'mw");
993         }
994         break;
995       }
996       case TEQ: {
997         if (instr->HasS()) {
998           Format(instr, "teq'cond 'rn, 'shift_op");
999         } else {
1000           // Other instructions matching this pattern are handled in the
1001           // miscellaneous instructions part above.
1002           UNREACHABLE();
1003         }
1004         break;
1005       }
1006       case CMP: {
1007         if (instr->HasS()) {
1008           Format(instr, "cmp'cond 'rn, 'shift_op");
1009         } else {
1010           Format(instr, "movt'cond 'mw");
1011         }
1012         break;
1013       }
1014       case CMN: {
1015         if (instr->HasS()) {
1016           Format(instr, "cmn'cond 'rn, 'shift_op");
1017         } else {
1018           // Other instructions matching this pattern are handled in the
1019           // miscellaneous instructions part above.
1020           UNREACHABLE();
1021         }
1022         break;
1023       }
1024       case ORR: {
1025         Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
1026         break;
1027       }
1028       case MOV: {
1029         Format(instr, "mov'cond's 'rd, 'shift_op");
1030         break;
1031       }
1032       case BIC: {
1033         Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
1034         break;
1035       }
1036       case MVN: {
1037         Format(instr, "mvn'cond's 'rd, 'shift_op");
1038         break;
1039       }
1040       default: {
1041         // The Opcode field is a 4-bit field.
1042         UNREACHABLE();
1043         break;
1044       }
1045     }
1046   }
1047 }
1048 
1049 
DecodeType2(Instruction * instr)1050 void Decoder::DecodeType2(Instruction* instr) {
1051   switch (instr->PUField()) {
1052     case da_x: {
1053       if (instr->HasW()) {
1054         Unknown(instr);  // not used in V8
1055         return;
1056       }
1057       Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
1058       break;
1059     }
1060     case ia_x: {
1061       if (instr->HasW()) {
1062         Unknown(instr);  // not used in V8
1063         return;
1064       }
1065       Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
1066       break;
1067     }
1068     case db_x: {
1069       if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
1070         Format(instr, "'memop'cond'b 'rd, [pc, #-'off12]'w (addr 'A)");
1071       } else {
1072         Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
1073       }
1074       break;
1075     }
1076     case ib_x: {
1077       if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
1078         Format(instr, "'memop'cond'b 'rd, [pc, #+'off12]'w (addr 'A)");
1079       } else {
1080         Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
1081       }
1082       break;
1083     }
1084     default: {
1085       // The PU field is a 2-bit field.
1086       UNREACHABLE();
1087       break;
1088     }
1089   }
1090 }
1091 
1092 
DecodeType3(Instruction * instr)1093 void Decoder::DecodeType3(Instruction* instr) {
1094   switch (instr->PUField()) {
1095     case da_x: {
1096       VERIFY(!instr->HasW());
1097       Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
1098       break;
1099     }
1100     case ia_x: {
1101       if (instr->Bit(4) == 0) {
1102         Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
1103       } else {
1104         if (instr->Bit(5) == 0) {
1105           switch (instr->Bits(22, 21)) {
1106             case 0:
1107               if (instr->Bit(20) == 0) {
1108                 if (instr->Bit(6) == 0) {
1109                   Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
1110                 } else {
1111                   if (instr->Bits(11, 7) == 0) {
1112                     Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
1113                   } else {
1114                     Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
1115                   }
1116                 }
1117               } else {
1118                 UNREACHABLE();
1119               }
1120               break;
1121             case 1:
1122               UNREACHABLE();
1123               break;
1124             case 2:
1125               UNREACHABLE();
1126               break;
1127             case 3:
1128               Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
1129               break;
1130           }
1131         } else {
1132           switch (instr->Bits(22, 21)) {
1133             case 0:
1134               UNREACHABLE();
1135               break;
1136             case 1:
1137               if (instr->Bits(9, 6) == 1) {
1138                 if (instr->Bit(20) == 0) {
1139                   if (instr->Bits(19, 16) == 0xF) {
1140                     switch (instr->Bits(11, 10)) {
1141                       case 0:
1142                         Format(instr, "sxtb'cond 'rd, 'rm");
1143                         break;
1144                       case 1:
1145                         Format(instr, "sxtb'cond 'rd, 'rm, ror #8");
1146                         break;
1147                       case 2:
1148                         Format(instr, "sxtb'cond 'rd, 'rm, ror #16");
1149                         break;
1150                       case 3:
1151                         Format(instr, "sxtb'cond 'rd, 'rm, ror #24");
1152                         break;
1153                     }
1154                   } else {
1155                     switch (instr->Bits(11, 10)) {
1156                       case 0:
1157                         Format(instr, "sxtab'cond 'rd, 'rn, 'rm");
1158                         break;
1159                       case 1:
1160                         Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8");
1161                         break;
1162                       case 2:
1163                         Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16");
1164                         break;
1165                       case 3:
1166                         Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24");
1167                         break;
1168                     }
1169                   }
1170                 } else {
1171                   if (instr->Bits(19, 16) == 0xF) {
1172                     switch (instr->Bits(11, 10)) {
1173                       case 0:
1174                         Format(instr, "sxth'cond 'rd, 'rm");
1175                         break;
1176                       case 1:
1177                         Format(instr, "sxth'cond 'rd, 'rm, ror #8");
1178                         break;
1179                       case 2:
1180                         Format(instr, "sxth'cond 'rd, 'rm, ror #16");
1181                         break;
1182                       case 3:
1183                         Format(instr, "sxth'cond 'rd, 'rm, ror #24");
1184                         break;
1185                     }
1186                   } else {
1187                     switch (instr->Bits(11, 10)) {
1188                       case 0:
1189                         Format(instr, "sxtah'cond 'rd, 'rn, 'rm");
1190                         break;
1191                       case 1:
1192                         Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8");
1193                         break;
1194                       case 2:
1195                         Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16");
1196                         break;
1197                       case 3:
1198                         Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24");
1199                         break;
1200                     }
1201                   }
1202                 }
1203               } else if (instr->Bits(27, 16) == 0x6BF &&
1204                          instr->Bits(11, 4) == 0xF3) {
1205                 Format(instr, "rev'cond 'rd, 'rm");
1206               } else {
1207                 UNREACHABLE();
1208               }
1209               break;
1210             case 2:
1211               if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
1212                 if (instr->Bits(19, 16) == 0xF) {
1213                   switch (instr->Bits(11, 10)) {
1214                     case 0:
1215                       Format(instr, "uxtb16'cond 'rd, 'rm");
1216                       break;
1217                     case 1:
1218                       Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
1219                       break;
1220                     case 2:
1221                       Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
1222                       break;
1223                     case 3:
1224                       Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
1225                       break;
1226                   }
1227                 } else {
1228                   UNREACHABLE();
1229                 }
1230               } else {
1231                 UNREACHABLE();
1232               }
1233               break;
1234             case 3:
1235               if ((instr->Bits(9, 6) == 1)) {
1236                 if ((instr->Bit(20) == 0)) {
1237                   if (instr->Bits(19, 16) == 0xF) {
1238                     switch (instr->Bits(11, 10)) {
1239                       case 0:
1240                         Format(instr, "uxtb'cond 'rd, 'rm");
1241                         break;
1242                       case 1:
1243                         Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
1244                         break;
1245                       case 2:
1246                         Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
1247                         break;
1248                       case 3:
1249                         Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
1250                         break;
1251                     }
1252                   } else {
1253                     switch (instr->Bits(11, 10)) {
1254                       case 0:
1255                         Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
1256                         break;
1257                       case 1:
1258                         Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
1259                         break;
1260                       case 2:
1261                         Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
1262                         break;
1263                       case 3:
1264                         Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
1265                         break;
1266                     }
1267                   }
1268                 } else {
1269                   if (instr->Bits(19, 16) == 0xF) {
1270                     switch (instr->Bits(11, 10)) {
1271                       case 0:
1272                         Format(instr, "uxth'cond 'rd, 'rm");
1273                         break;
1274                       case 1:
1275                         Format(instr, "uxth'cond 'rd, 'rm, ror #8");
1276                         break;
1277                       case 2:
1278                         Format(instr, "uxth'cond 'rd, 'rm, ror #16");
1279                         break;
1280                       case 3:
1281                         Format(instr, "uxth'cond 'rd, 'rm, ror #24");
1282                         break;
1283                     }
1284                   } else {
1285                     switch (instr->Bits(11, 10)) {
1286                       case 0:
1287                         Format(instr, "uxtah'cond 'rd, 'rn, 'rm");
1288                         break;
1289                       case 1:
1290                         Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8");
1291                         break;
1292                       case 2:
1293                         Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16");
1294                         break;
1295                       case 3:
1296                         Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24");
1297                         break;
1298                     }
1299                   }
1300                 }
1301               } else {
1302                 // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001
1303                 if ((instr->Bits(20, 16) == 0x1F) &&
1304                     (instr->Bits(11, 4) == 0xF3)) {
1305                   Format(instr, "rbit'cond 'rd, 'rm");
1306                 } else {
1307                   UNREACHABLE();
1308                 }
1309               }
1310               break;
1311           }
1312         }
1313       }
1314       break;
1315     }
1316     case db_x: {
1317       if (instr->Bits(22, 20) == 0x5) {
1318         if (instr->Bits(7, 4) == 0x1) {
1319           if (instr->Bits(15, 12) == 0xF) {
1320             Format(instr, "smmul'cond 'rn, 'rm, 'rs");
1321           } else {
1322             // SMMLA (in V8 notation matching ARM ISA format)
1323             Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
1324           }
1325           break;
1326         }
1327       }
1328       if (instr->Bits(5, 4) == 0x1) {
1329         if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
1330           if (instr->Bit(21) == 0x1) {
1331             // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1332             Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
1333           } else {
1334             // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1335             Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
1336           }
1337           break;
1338         }
1339       }
1340       Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1341       break;
1342     }
1343     case ib_x: {
1344       if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1345         uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1346         uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1347         uint32_t msbit = widthminus1 + lsbit;
1348         if (msbit <= 31) {
1349           if (instr->Bit(22)) {
1350             Format(instr, "ubfx'cond 'rd, 'rm, 'f");
1351           } else {
1352             Format(instr, "sbfx'cond 'rd, 'rm, 'f");
1353           }
1354         } else {
1355           UNREACHABLE();
1356         }
1357       } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
1358         uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1359         uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
1360         if (msbit >= lsbit) {
1361           if (instr->RmValue() == 15) {
1362             Format(instr, "bfc'cond 'rd, 'f");
1363           } else {
1364             Format(instr, "bfi'cond 'rd, 'rm, 'f");
1365           }
1366         } else {
1367           UNREACHABLE();
1368         }
1369       } else {
1370         Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1371       }
1372       break;
1373     }
1374     default: {
1375       // The PU field is a 2-bit field.
1376       UNREACHABLE();
1377       break;
1378     }
1379   }
1380 }
1381 
1382 
DecodeType4(Instruction * instr)1383 void Decoder::DecodeType4(Instruction* instr) {
1384   if (instr->Bit(22) != 0) {
1385     // Privileged mode currently not supported.
1386     Unknown(instr);
1387   } else {
1388     if (instr->HasL()) {
1389       Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1390     } else {
1391       Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1392     }
1393   }
1394 }
1395 
1396 
DecodeType5(Instruction * instr)1397 void Decoder::DecodeType5(Instruction* instr) {
1398   Format(instr, "b'l'cond 'target");
1399 }
1400 
1401 
DecodeType6(Instruction * instr)1402 void Decoder::DecodeType6(Instruction* instr) {
1403   DecodeType6CoprocessorIns(instr);
1404 }
1405 
1406 
DecodeType7(Instruction * instr)1407 int Decoder::DecodeType7(Instruction* instr) {
1408   if (instr->Bit(24) == 1) {
1409     if (instr->SvcValue() >= kStopCode) {
1410       Format(instr, "stop'cond 'svc");
1411     } else {
1412       Format(instr, "svc'cond 'svc");
1413     }
1414   } else {
1415     switch (instr->CoprocessorValue()) {
1416       case 10:  // Fall through.
1417       case 11:
1418         DecodeTypeVFP(instr);
1419         break;
1420       case 15:
1421         DecodeTypeCP15(instr);
1422         break;
1423       default:
1424         Unknown(instr);
1425         break;
1426     }
1427   }
1428   return kInstrSize;
1429 }
1430 
1431 
1432 // void Decoder::DecodeTypeVFP(Instruction* instr)
1433 // vmov: Sn = Rt
1434 // vmov: Rt = Sn
1435 // vcvt: Dd = Sm
1436 // vcvt: Sd = Dm
1437 // vcvt.f64.s32 Dd, Dd, #<fbits>
1438 // Dd = vabs(Dm)
1439 // Sd = vabs(Sm)
1440 // Dd = vneg(Dm)
1441 // Sd = vneg(Sm)
1442 // Dd = vadd(Dn, Dm)
1443 // Sd = vadd(Sn, Sm)
1444 // Dd = vsub(Dn, Dm)
1445 // Sd = vsub(Sn, Sm)
1446 // Dd = vmul(Dn, Dm)
1447 // Sd = vmul(Sn, Sm)
1448 // Dd = vmla(Dn, Dm)
1449 // Sd = vmla(Sn, Sm)
1450 // Dd = vmls(Dn, Dm)
1451 // Sd = vmls(Sn, Sm)
1452 // Dd = vdiv(Dn, Dm)
1453 // Sd = vdiv(Sn, Sm)
1454 // vcmp(Dd, Dm)
1455 // vcmp(Sd, Sm)
1456 // Dd = vsqrt(Dm)
1457 // Sd = vsqrt(Sm)
1458 // vmrs
1459 // vmsr
1460 // Qd = vdup.size(Qd, Rt)
1461 // vmov.size: Dd[i] = Rt
1462 // vmov.sign.size: Rt = Dn[i]
DecodeTypeVFP(Instruction * instr)1463 void Decoder::DecodeTypeVFP(Instruction* instr) {
1464   VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
1465   VERIFY(instr->Bits(11, 9) == 0x5);
1466 
1467   if (instr->Bit(4) == 0) {
1468     if (instr->Opc1Value() == 0x7) {
1469       // Other data processing instructions
1470       if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
1471         // vmov register to register.
1472         if (instr->SzValue() == 0x1) {
1473           Format(instr, "vmov'cond.f64 'Dd, 'Dm");
1474         } else {
1475           Format(instr, "vmov'cond.f32 'Sd, 'Sm");
1476         }
1477       } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
1478         // vabs
1479         if (instr->SzValue() == 0x1) {
1480           Format(instr, "vabs'cond.f64 'Dd, 'Dm");
1481         } else {
1482           Format(instr, "vabs'cond.f32 'Sd, 'Sm");
1483         }
1484       } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
1485         // vneg
1486         if (instr->SzValue() == 0x1) {
1487           Format(instr, "vneg'cond.f64 'Dd, 'Dm");
1488         } else {
1489           Format(instr, "vneg'cond.f32 'Sd, 'Sm");
1490         }
1491       } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
1492         DecodeVCVTBetweenDoubleAndSingle(instr);
1493       } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
1494         DecodeVCVTBetweenFloatingPointAndInteger(instr);
1495       } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
1496                  (instr->Bit(8) == 1)) {
1497         // vcvt.f64.s32 Dd, Dd, #<fbits>
1498         int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
1499         Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
1500         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1501                                     ", #%d", fraction_bits);
1502       } else if (((instr->Opc2Value() >> 1) == 0x6) &&
1503                  (instr->Opc3Value() & 0x1)) {
1504         DecodeVCVTBetweenFloatingPointAndInteger(instr);
1505       } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1506                  (instr->Opc3Value() & 0x1)) {
1507         DecodeVCMP(instr);
1508       } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
1509         if (instr->SzValue() == 0x1) {
1510           Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
1511         } else {
1512           Format(instr, "vsqrt'cond.f32 'Sd, 'Sm");
1513         }
1514       } else if (instr->Opc3Value() == 0x0) {
1515         if (instr->SzValue() == 0x1) {
1516           Format(instr, "vmov'cond.f64 'Dd, 'd");
1517         } else {
1518           Format(instr, "vmov'cond.f32 'Sd, 'd");
1519         }
1520       } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) {
1521         // vrintz - round towards zero (truncate)
1522         if (instr->SzValue() == 0x1) {
1523           Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm");
1524         } else {
1525           Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm");
1526         }
1527       } else {
1528         Unknown(instr);  // Not used by V8.
1529       }
1530     } else if (instr->Opc1Value() == 0x3) {
1531       if (instr->SzValue() == 0x1) {
1532         if (instr->Opc3Value() & 0x1) {
1533           Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
1534         } else {
1535           Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
1536         }
1537       } else {
1538         if (instr->Opc3Value() & 0x1) {
1539           Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm");
1540         } else {
1541           Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm");
1542         }
1543       }
1544     } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
1545       if (instr->SzValue() == 0x1) {
1546         Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
1547       } else {
1548         Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm");
1549       }
1550     } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
1551       if (instr->SzValue() == 0x1) {
1552         Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
1553       } else {
1554         Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm");
1555       }
1556     } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
1557       if (instr->SzValue() == 0x1) {
1558         Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
1559       } else {
1560         Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm");
1561       }
1562     } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
1563       if (instr->SzValue() == 0x1) {
1564         Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
1565       } else {
1566         Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm");
1567       }
1568     } else {
1569       Unknown(instr);  // Not used by V8.
1570     }
1571   } else {
1572     if ((instr->VCValue() == 0x0) &&
1573         (instr->VAValue() == 0x0)) {
1574       DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1575     } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
1576       const char* rt_name = converter_.NameOfCPURegister(instr->RtValue());
1577       if (instr->Bit(23) == 0) {
1578         int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
1579         if ((opc1_opc2 & 0xB) == 0) {
1580           // NeonS32/NeonU32
1581           if (instr->Bit(21) == 0x0) {
1582             Format(instr, "vmov'cond.32 'Dd[0], 'rt");
1583           } else {
1584             Format(instr, "vmov'cond.32 'Dd[1], 'rt");
1585           }
1586         } else {
1587           int vd = instr->VFPNRegValue(kDoublePrecision);
1588           if ((opc1_opc2 & 0x8) != 0) {
1589             // NeonS8 / NeonU8
1590             int i = opc1_opc2 & 0x7;
1591             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1592                                         "vmov.8 d%d[%d], %s", vd, i, rt_name);
1593           } else if ((opc1_opc2 & 0x1) != 0) {
1594             // NeonS16 / NeonU16
1595             int i = (opc1_opc2 >> 1) & 0x3;
1596             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1597                                         "vmov.16 d%d[%d], %s", vd, i, rt_name);
1598           } else {
1599             Unknown(instr);
1600           }
1601         }
1602       } else {
1603         int size = 32;
1604         if (instr->Bit(5) != 0) {
1605           size = 16;
1606         } else if (instr->Bit(22) != 0) {
1607           size = 8;
1608         }
1609         int Vd = instr->VFPNRegValue(kSimd128Precision);
1610         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1611                                     "vdup.%i q%d, %s", size, Vd, rt_name);
1612       }
1613     } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
1614       int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
1615       if ((opc1_opc2 & 0xB) == 0) {
1616         // NeonS32 / NeonU32
1617         if (instr->Bit(21) == 0x0) {
1618           Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
1619         } else {
1620           Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
1621         }
1622       } else {
1623         char sign = instr->Bit(23) != 0 ? 'u' : 's';
1624         const char* rt_name = converter_.NameOfCPURegister(instr->RtValue());
1625         int vn = instr->VFPNRegValue(kDoublePrecision);
1626         if ((opc1_opc2 & 0x8) != 0) {
1627           // NeonS8 / NeonU8
1628           int i = opc1_opc2 & 0x7;
1629           out_buffer_pos_ +=
1630               SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%c8 %s, d%d[%d]",
1631                        sign, rt_name, vn, i);
1632         } else if ((opc1_opc2 & 0x1) != 0) {
1633           // NeonS16 / NeonU16
1634           int i = (opc1_opc2 >> 1) & 0x3;
1635           out_buffer_pos_ +=
1636               SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%c16 %s, d%d[%d]",
1637                        sign, rt_name, vn, i);
1638         } else {
1639           Unknown(instr);
1640         }
1641       }
1642     } else if ((instr->VCValue() == 0x0) &&
1643                (instr->VAValue() == 0x7) &&
1644                (instr->Bits(19, 16) == 0x1)) {
1645       if (instr->VLValue() == 0) {
1646         if (instr->Bits(15, 12) == 0xF) {
1647           Format(instr, "vmsr'cond FPSCR, APSR");
1648         } else {
1649           Format(instr, "vmsr'cond FPSCR, 'rt");
1650         }
1651       } else {
1652         if (instr->Bits(15, 12) == 0xF) {
1653           Format(instr, "vmrs'cond APSR, FPSCR");
1654         } else {
1655           Format(instr, "vmrs'cond 'rt, FPSCR");
1656         }
1657       }
1658     } else {
1659       Unknown(instr);  // Not used by V8.
1660     }
1661   }
1662 }
1663 
DecodeTypeCP15(Instruction * instr)1664 void Decoder::DecodeTypeCP15(Instruction* instr) {
1665   VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
1666   VERIFY(instr->CoprocessorValue() == 15);
1667 
1668   if (instr->Bit(4) == 1) {
1669     int crn = instr->Bits(19, 16);
1670     int crm = instr->Bits(3, 0);
1671     int opc1 = instr->Bits(23, 21);
1672     int opc2 = instr->Bits(7, 5);
1673     if ((opc1 == 0) && (crn == 7)) {
1674       // ARMv6 memory barrier operations.
1675       // Details available in ARM DDI 0406C.b, B3-1750.
1676       if ((crm == 10) && (opc2 == 5)) {
1677         Format(instr, "mcr'cond (CP15DMB)");
1678       } else if ((crm == 10) && (opc2 == 4)) {
1679         Format(instr, "mcr'cond (CP15DSB)");
1680       } else if ((crm == 5) && (opc2 == 4)) {
1681         Format(instr, "mcr'cond (CP15ISB)");
1682       } else {
1683         Unknown(instr);
1684       }
1685     } else {
1686       Unknown(instr);
1687     }
1688   } else {
1689     Unknown(instr);
1690   }
1691 }
1692 
DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction * instr)1693 void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
1694     Instruction* instr) {
1695   VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
1696          (instr->VAValue() == 0x0));
1697 
1698   bool to_arm_register = (instr->VLValue() == 0x1);
1699 
1700   if (to_arm_register) {
1701     Format(instr, "vmov'cond 'rt, 'Sn");
1702   } else {
1703     Format(instr, "vmov'cond 'Sn, 'rt");
1704   }
1705 }
1706 
1707 
DecodeVCMP(Instruction * instr)1708 void Decoder::DecodeVCMP(Instruction* instr) {
1709   VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1710   VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1711          (instr->Opc3Value() & 0x1));
1712 
1713   // Comparison.
1714   bool dp_operation = (instr->SzValue() == 1);
1715   bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1716 
1717   if (dp_operation && !raise_exception_for_qnan) {
1718     if (instr->Opc2Value() == 0x4) {
1719       Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
1720     } else if (instr->Opc2Value() == 0x5) {
1721       Format(instr, "vcmp'cond.f64 'Dd, #0.0");
1722     } else {
1723       Unknown(instr);  // invalid
1724     }
1725   } else if (!raise_exception_for_qnan) {
1726     if (instr->Opc2Value() == 0x4) {
1727       Format(instr, "vcmp'cond.f32 'Sd, 'Sm");
1728     } else if (instr->Opc2Value() == 0x5) {
1729       Format(instr, "vcmp'cond.f32 'Sd, #0.0");
1730     } else {
1731       Unknown(instr);  // invalid
1732     }
1733   } else {
1734     Unknown(instr);  // Not used by V8.
1735   }
1736 }
1737 
1738 
DecodeVCVTBetweenDoubleAndSingle(Instruction * instr)1739 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
1740   VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1741   VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
1742 
1743   bool double_to_single = (instr->SzValue() == 1);
1744 
1745   if (double_to_single) {
1746     Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
1747   } else {
1748     Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
1749   }
1750 }
1751 
1752 
DecodeVCVTBetweenFloatingPointAndInteger(Instruction * instr)1753 void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
1754   VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1755   VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
1756          (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
1757 
1758   bool to_integer = (instr->Bit(18) == 1);
1759   bool dp_operation = (instr->SzValue() == 1);
1760   if (to_integer) {
1761     bool unsigned_integer = (instr->Bit(16) == 0);
1762 
1763     if (dp_operation) {
1764       if (unsigned_integer) {
1765         Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
1766       } else {
1767         Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
1768       }
1769     } else {
1770       if (unsigned_integer) {
1771         Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
1772       } else {
1773         Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
1774       }
1775     }
1776   } else {
1777     bool unsigned_integer = (instr->Bit(7) == 0);
1778 
1779     if (dp_operation) {
1780       if (unsigned_integer) {
1781         Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
1782       } else {
1783         Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
1784       }
1785     } else {
1786       if (unsigned_integer) {
1787         Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
1788       } else {
1789         Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
1790       }
1791     }
1792   }
1793 }
1794 
1795 
1796 // Decode Type 6 coprocessor instructions.
1797 // Dm = vmov(Rt, Rt2)
1798 // <Rt, Rt2> = vmov(Dm)
1799 // Ddst = MEM(Rbase + 4*offset).
1800 // MEM(Rbase + 4*offset) = Dsrc.
DecodeType6CoprocessorIns(Instruction * instr)1801 void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
1802   VERIFY(instr->TypeValue() == 6);
1803 
1804   if (instr->CoprocessorValue() == 0xA) {
1805     switch (instr->OpcodeValue()) {
1806       case 0x8:
1807       case 0xA:
1808         if (instr->HasL()) {
1809           Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1810         } else {
1811           Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1812         }
1813         break;
1814       case 0xC:
1815       case 0xE:
1816         if (instr->HasL()) {
1817           Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1818         } else {
1819           Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1820         }
1821         break;
1822       case 0x4:
1823       case 0x5:
1824       case 0x6:
1825       case 0x7:
1826       case 0x9:
1827       case 0xB: {
1828         bool to_vfp_register = (instr->VLValue() == 0x1);
1829         if (to_vfp_register) {
1830           Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
1831         } else {
1832           Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
1833         }
1834         break;
1835       }
1836       default:
1837         Unknown(instr);  // Not used by V8.
1838     }
1839   } else if (instr->CoprocessorValue() == 0xB) {
1840     switch (instr->OpcodeValue()) {
1841       case 0x2:
1842         // Load and store double to two GP registers
1843         if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
1844           Unknown(instr);  // Not used by V8.
1845         } else if (instr->HasL()) {
1846           Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1847         } else {
1848           Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1849         }
1850         break;
1851       case 0x8:
1852       case 0xA:
1853         if (instr->HasL()) {
1854           Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1855         } else {
1856           Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1857         }
1858         break;
1859       case 0xC:
1860       case 0xE:
1861         if (instr->HasL()) {
1862           Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1863         } else {
1864           Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1865         }
1866         break;
1867       case 0x4:
1868       case 0x5:
1869       case 0x6:
1870       case 0x7:
1871       case 0x9:
1872       case 0xB: {
1873         bool to_vfp_register = (instr->VLValue() == 0x1);
1874         if (to_vfp_register) {
1875           Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
1876         } else {
1877           Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
1878         }
1879         break;
1880       }
1881       default:
1882         Unknown(instr);  // Not used by V8.
1883     }
1884   } else {
1885     Unknown(instr);  // Not used by V8.
1886   }
1887 }
1888 
1889 
1890 static const char* const barrier_option_names[] = {
1891     "invalid", "oshld", "oshst", "osh", "invalid", "nshld", "nshst", "nsh",
1892     "invalid", "ishld", "ishst", "ish", "invalid", "ld",    "st",    "sy",
1893 };
1894 
1895 
DecodeSpecialCondition(Instruction * instr)1896 void Decoder::DecodeSpecialCondition(Instruction* instr) {
1897   switch (instr->SpecialValue()) {
1898     case 4: {
1899       int Vd, Vm, Vn;
1900       if (instr->Bit(6) == 0) {
1901         Vd = instr->VFPDRegValue(kDoublePrecision);
1902         Vm = instr->VFPMRegValue(kDoublePrecision);
1903         Vn = instr->VFPNRegValue(kDoublePrecision);
1904       } else {
1905         Vd = instr->VFPDRegValue(kSimd128Precision);
1906         Vm = instr->VFPMRegValue(kSimd128Precision);
1907         Vn = instr->VFPNRegValue(kSimd128Precision);
1908       }
1909       int size = kBitsPerByte * (1 << instr->Bits(21, 20));
1910       switch (instr->Bits(11, 8)) {
1911         case 0x0: {
1912           if (instr->Bit(4) == 1) {
1913             // vqadd.s<size> Qd, Qm, Qn.
1914             out_buffer_pos_ +=
1915                 SNPrintF(out_buffer_ + out_buffer_pos_,
1916                          "vqadd.s%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1917           } else {
1918             Unknown(instr);
1919           }
1920           break;
1921         }
1922         case 0x1: {
1923           if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 &&
1924               instr->Bit(4) == 1) {
1925             if (Vm == Vn) {
1926               // vmov Qd, Qm
1927               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1928                                           "vmov q%d, q%d", Vd, Vm);
1929             } else {
1930               // vorr Qd, Qm, Qn.
1931               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1932                                           "vorr q%d, q%d, q%d", Vd, Vn, Vm);
1933             }
1934           } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
1935                      instr->Bit(4) == 1) {
1936             // vand Qd, Qm, Qn.
1937             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1938                                         "vand q%d, q%d, q%d", Vd, Vn, Vm);
1939           } else {
1940             Unknown(instr);
1941           }
1942           break;
1943         }
1944         case 0x2: {
1945           if (instr->Bit(4) == 1) {
1946             // vqsub.s<size> Qd, Qm, Qn.
1947             out_buffer_pos_ +=
1948                 SNPrintF(out_buffer_ + out_buffer_pos_,
1949                          "vqsub.s%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1950           } else {
1951             Unknown(instr);
1952           }
1953           break;
1954         }
1955         case 0x3: {
1956           const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt";
1957           // vcge/vcgt.s<size> Qd, Qm, Qn.
1958           out_buffer_pos_ +=
1959               SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d",
1960                        op, size, Vd, Vn, Vm);
1961           break;
1962         }
1963         case 0x6: {
1964           // vmin/vmax.s<size> Qd, Qm, Qn.
1965           const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax";
1966           out_buffer_pos_ +=
1967               SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d",
1968                        op, size, Vd, Vn, Vm);
1969           break;
1970         }
1971         case 0x8: {
1972           const char* op = (instr->Bit(4) == 0) ? "vadd" : "vtst";
1973           // vadd/vtst.i<size> Qd, Qm, Qn.
1974           out_buffer_pos_ +=
1975               SNPrintF(out_buffer_ + out_buffer_pos_, "%s.i%d q%d, q%d, q%d",
1976                        op, size, Vd, Vn, Vm);
1977           break;
1978         }
1979         case 0x9: {
1980           if (instr->Bit(6) == 1 && instr->Bit(4) == 1) {
1981             // vmul.i<size> Qd, Qm, Qn.
1982             out_buffer_pos_ +=
1983                 SNPrintF(out_buffer_ + out_buffer_pos_,
1984                          "vmul.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1985           } else {
1986             Unknown(instr);
1987           }
1988           break;
1989         }
1990         case 0xA: {
1991           // vpmin/vpmax.s<size> Dd, Dm, Dn.
1992           const char* op = instr->Bit(4) == 1 ? "vpmin" : "vpmax";
1993           out_buffer_pos_ +=
1994               SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d d%d, d%d, d%d",
1995                        op, size, Vd, Vn, Vm);
1996           break;
1997         }
1998         case 0xB: {
1999           // vpadd.i<size> Dd, Dm, Dn.
2000           out_buffer_pos_ +=
2001               SNPrintF(out_buffer_ + out_buffer_pos_, "vpadd.i%d d%d, d%d, d%d",
2002                        size, Vd, Vn, Vm);
2003           break;
2004         }
2005         case 0xD: {
2006           if (instr->Bit(4) == 0) {
2007             const char* op = (instr->Bits(21, 20) == 0) ? "vadd" : "vsub";
2008             // vadd/vsub.f32 Qd, Qm, Qn.
2009             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2010                                         "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2011           } else {
2012             Unknown(instr);
2013           }
2014           break;
2015         }
2016         case 0xE: {
2017           if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) {
2018             // vceq.f32 Qd, Qm, Qn.
2019             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2020                                         "vceq.f32 q%d, q%d, q%d", Vd, Vn, Vm);
2021           } else {
2022             Unknown(instr);
2023           }
2024           break;
2025         }
2026         case 0xF: {
2027           if (instr->Bit(20) == 0 && instr->Bit(6) == 1) {
2028             if (instr->Bit(4) == 1) {
2029               // vrecps/vrsqrts.f32 Qd, Qm, Qn.
2030               const char* op = instr->Bit(21) == 0 ? "vrecps" : "vrsqrts";
2031               out_buffer_pos_ +=
2032                   SNPrintF(out_buffer_ + out_buffer_pos_,
2033                            "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2034             } else {
2035               // vmin/max.f32 Qd, Qm, Qn.
2036               const char* op = instr->Bit(21) == 1 ? "vmin" : "vmax";
2037               out_buffer_pos_ +=
2038                   SNPrintF(out_buffer_ + out_buffer_pos_,
2039                            "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2040             }
2041           } else {
2042             Unknown(instr);
2043           }
2044           break;
2045         }
2046         default:
2047           Unknown(instr);
2048           break;
2049       }
2050       break;
2051     }
2052     case 5:
2053       if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
2054           (instr->Bit(4) == 1)) {
2055         // vmovl signed
2056         if ((instr->VdValue() & 1) != 0) Unknown(instr);
2057         int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
2058         int Vm = (instr->Bit(5) << 4) | instr->VmValue();
2059         int imm3 = instr->Bits(21, 19);
2060         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2061                                     "vmovl.s%d q%d, d%d", imm3 * 8, Vd, Vm);
2062       } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) {
2063         // vext.8 Qd, Qm, Qn, imm4
2064         int imm4 = instr->Bits(11, 8);
2065         int Vd = instr->VFPDRegValue(kSimd128Precision);
2066         int Vm = instr->VFPMRegValue(kSimd128Precision);
2067         int Vn = instr->VFPNRegValue(kSimd128Precision);
2068         out_buffer_pos_ +=
2069             SNPrintF(out_buffer_ + out_buffer_pos_, "vext.8 q%d, q%d, q%d, #%d",
2070                      Vd, Vn, Vm, imm4);
2071       } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) {
2072         // vshl.i<size> Qd, Qm, shift
2073         int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2074         int shift = instr->Bits(21, 16) - size;
2075         int Vd = instr->VFPDRegValue(kSimd128Precision);
2076         int Vm = instr->VFPMRegValue(kSimd128Precision);
2077         out_buffer_pos_ +=
2078             SNPrintF(out_buffer_ + out_buffer_pos_, "vshl.i%d q%d, q%d, #%d",
2079                      size, Vd, Vm, shift);
2080       } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
2081         // vshr.s<size> Qd, Qm, shift
2082         int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2083         int shift = 2 * size - instr->Bits(21, 16);
2084         int Vd = instr->VFPDRegValue(kSimd128Precision);
2085         int Vm = instr->VFPMRegValue(kSimd128Precision);
2086         out_buffer_pos_ +=
2087             SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.s%d q%d, q%d, #%d",
2088                      size, Vd, Vm, shift);
2089       } else {
2090         Unknown(instr);
2091       }
2092       break;
2093     case 6: {
2094       int Vd, Vm, Vn;
2095       if (instr->Bit(6) == 0) {
2096         Vd = instr->VFPDRegValue(kDoublePrecision);
2097         Vm = instr->VFPMRegValue(kDoublePrecision);
2098         Vn = instr->VFPNRegValue(kDoublePrecision);
2099       } else {
2100         Vd = instr->VFPDRegValue(kSimd128Precision);
2101         Vm = instr->VFPMRegValue(kSimd128Precision);
2102         Vn = instr->VFPNRegValue(kSimd128Precision);
2103       }
2104       int size = kBitsPerByte * (1 << instr->Bits(21, 20));
2105       switch (instr->Bits(11, 8)) {
2106         case 0x0: {
2107           if (instr->Bit(4) == 1) {
2108             // vqadd.u<size> Qd, Qm, Qn.
2109             out_buffer_pos_ +=
2110                 SNPrintF(out_buffer_ + out_buffer_pos_,
2111                          "vqadd.u%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2112           } else {
2113             Unknown(instr);
2114           }
2115           break;
2116         }
2117         case 0x1: {
2118           if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) {
2119             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2120                                         "vbsl q%d, q%d, q%d", Vd, Vn, Vm);
2121           } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) {
2122             if (instr->Bit(6) == 0) {
2123               // veor Dd, Dn, Dm
2124               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2125                                           "veor d%d, d%d, d%d", Vd, Vn, Vm);
2126 
2127             } else {
2128               // veor Qd, Qn, Qm
2129               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2130                                           "veor q%d, q%d, q%d", Vd, Vn, Vm);
2131             }
2132           } else {
2133             Unknown(instr);
2134           }
2135           break;
2136         }
2137         case 0x2: {
2138           if (instr->Bit(4) == 1) {
2139             // vqsub.u<size> Qd, Qm, Qn.
2140             out_buffer_pos_ +=
2141                 SNPrintF(out_buffer_ + out_buffer_pos_,
2142                          "vqsub.u%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2143           } else {
2144             Unknown(instr);
2145           }
2146           break;
2147         }
2148         case 0x3: {
2149           const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt";
2150           // vcge/vcgt.u<size> Qd, Qm, Qn.
2151           out_buffer_pos_ +=
2152               SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d",
2153                        op, size, Vd, Vn, Vm);
2154           break;
2155         }
2156         case 0x6: {
2157           // vmin/vmax.u<size> Qd, Qm, Qn.
2158           const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax";
2159           out_buffer_pos_ +=
2160               SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d",
2161                        op, size, Vd, Vn, Vm);
2162           break;
2163         }
2164         case 0x8: {
2165           if (instr->Bit(4) == 0) {
2166             out_buffer_pos_ +=
2167                 SNPrintF(out_buffer_ + out_buffer_pos_,
2168                          "vsub.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2169           } else {
2170             out_buffer_pos_ +=
2171                 SNPrintF(out_buffer_ + out_buffer_pos_,
2172                          "vceq.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2173           }
2174           break;
2175         }
2176         case 0xA: {
2177           // vpmin/vpmax.u<size> Dd, Dm, Dn.
2178           const char* op = instr->Bit(4) == 1 ? "vpmin" : "vpmax";
2179           out_buffer_pos_ +=
2180               SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d d%d, d%d, d%d",
2181                        op, size, Vd, Vn, Vm);
2182           break;
2183         }
2184         case 0xD: {
2185           if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
2186               instr->Bit(4) == 1) {
2187             // vmul.f32 Qd, Qm, Qn
2188             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2189                                         "vmul.f32 q%d, q%d, q%d", Vd, Vn, Vm);
2190           } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 0 &&
2191                      instr->Bit(4) == 0) {
2192             // vpadd.f32 Dd, Dm, Dn.
2193             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2194                                         "vpadd.f32 d%d, d%d, d%d", Vd, Vn, Vm);
2195           } else {
2196             Unknown(instr);
2197           }
2198           break;
2199         }
2200         case 0xE: {
2201           if (instr->Bit(20) == 0 && instr->Bit(4) == 0) {
2202             const char* op = (instr->Bit(21) == 0) ? "vcge" : "vcgt";
2203             // vcge/vcgt.f32 Qd, Qm, Qn.
2204             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2205                                         "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2206           } else {
2207             Unknown(instr);
2208           }
2209           break;
2210         }
2211         default:
2212           Unknown(instr);
2213           break;
2214       }
2215       break;
2216     }
2217     case 7:
2218       if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
2219           (instr->Bit(4) == 1)) {
2220         // vmovl unsigned
2221         if ((instr->VdValue() & 1) != 0) Unknown(instr);
2222         int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
2223         int Vm = (instr->Bit(5) << 4) | instr->VmValue();
2224         int imm3 = instr->Bits(21, 19);
2225         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2226                                     "vmovl.u%d q%d, d%d", imm3 * 8, Vd, Vm);
2227       } else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) {
2228         if (instr->Bits(11, 7) == 0x18) {
2229           int Vm = instr->VFPMRegValue(kDoublePrecision);
2230           int imm4 = instr->Bits(19, 16);
2231           int size = 0, index = 0;
2232           if ((imm4 & 0x1) != 0) {
2233             size = 8;
2234             index = imm4 >> 1;
2235           } else if ((imm4 & 0x2) != 0) {
2236             size = 16;
2237             index = imm4 >> 2;
2238           } else {
2239             size = 32;
2240             index = imm4 >> 3;
2241           }
2242           if (instr->Bit(6) == 0) {
2243             int Vd = instr->VFPDRegValue(kDoublePrecision);
2244             out_buffer_pos_ +=
2245                 SNPrintF(out_buffer_ + out_buffer_pos_, "vdup.%i d%d, d%d[%d]",
2246                          size, Vd, Vm, index);
2247           } else {
2248             int Vd = instr->VFPDRegValue(kSimd128Precision);
2249             out_buffer_pos_ +=
2250                 SNPrintF(out_buffer_ + out_buffer_pos_, "vdup.%i q%d, d%d[%d]",
2251                          size, Vd, Vm, index);
2252           }
2253         } else if (instr->Bits(11, 10) == 0x2) {
2254           int Vd = instr->VFPDRegValue(kDoublePrecision);
2255           int Vn = instr->VFPNRegValue(kDoublePrecision);
2256           int Vm = instr->VFPMRegValue(kDoublePrecision);
2257           int len = instr->Bits(9, 8);
2258           NeonListOperand list(DwVfpRegister::from_code(Vn), len + 1);
2259           out_buffer_pos_ +=
2260               SNPrintF(out_buffer_ + out_buffer_pos_, "%s d%d, ",
2261                        instr->Bit(6) == 0 ? "vtbl.8" : "vtbx.8", Vd);
2262           FormatNeonList(Vn, list.type());
2263           Print(", ");
2264           PrintDRegister(Vm);
2265         } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x2 &&
2266                    instr->Bits(7, 6) != 0) {
2267           // vqmovn.<type><size> Dd, Qm.
2268           int Vd = instr->VFPDRegValue(kDoublePrecision);
2269           int Vm = instr->VFPMRegValue(kSimd128Precision);
2270           char type = instr->Bit(6) != 0 ? 'u' : 's';
2271           int size = 2 * kBitsPerByte * (1 << instr->Bits(19, 18));
2272           out_buffer_pos_ +=
2273               SNPrintF(out_buffer_ + out_buffer_pos_, "vqmovn.%c%i d%d, q%d",
2274                        type, size, Vd, Vm);
2275         } else {
2276           int Vd, Vm;
2277           if (instr->Bit(6) == 0) {
2278             Vd = instr->VFPDRegValue(kDoublePrecision);
2279             Vm = instr->VFPMRegValue(kDoublePrecision);
2280           } else {
2281             Vd = instr->VFPDRegValue(kSimd128Precision);
2282             Vm = instr->VFPMRegValue(kSimd128Precision);
2283           }
2284           if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) {
2285             if (instr->Bit(6) == 0) {
2286               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2287                                           "vswp d%d, d%d", Vd, Vm);
2288             } else {
2289               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2290                                           "vswp q%d, q%d", Vd, Vm);
2291             }
2292           } else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) {
2293             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2294                                         "vmvn q%d, q%d", Vd, Vm);
2295           } else if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 &&
2296                      instr->Bit(6) == 1) {
2297             const char* suffix = nullptr;
2298             int op = instr->Bits(8, 7);
2299             switch (op) {
2300               case 0:
2301                 suffix = "f32.s32";
2302                 break;
2303               case 1:
2304                 suffix = "f32.u32";
2305                 break;
2306               case 2:
2307                 suffix = "s32.f32";
2308                 break;
2309               case 3:
2310                 suffix = "u32.f32";
2311                 break;
2312             }
2313             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2314                                         "vcvt.%s q%d, q%d", suffix, Vd, Vm);
2315           } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x1) {
2316             int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2317             const char* op = instr->Bit(7) != 0 ? "vzip" : "vuzp";
2318             if (instr->Bit(6) == 0) {
2319               // vzip/vuzp.<size> Dd, Dm.
2320               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2321                                           "%s.%d d%d, d%d", op, size, Vd, Vm);
2322             } else {
2323               // vzip/vuzp.<size> Qd, Qm.
2324               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2325                                           "%s.%d q%d, q%d", op, size, Vd, Vm);
2326             }
2327           } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0 &&
2328                      instr->Bit(6) == 1) {
2329             int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2330             int op = kBitsPerByte
2331                      << (static_cast<int>(Neon64) - instr->Bits(8, 7));
2332             // vrev<op>.<size> Qd, Qm.
2333             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2334                                         "vrev%d.%d q%d, q%d", op, size, Vd, Vm);
2335           } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0x1) {
2336             int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2337             if (instr->Bit(6) == 0) {
2338               // vtrn.<size> Dd, Dm.
2339               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2340                                           "vtrn.%d d%d, d%d", size, Vd, Vm);
2341             } else {
2342               // vtrn.<size> Qd, Qm.
2343               out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2344                                           "vtrn.%d q%d, q%d", size, Vd, Vm);
2345             }
2346           } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0 &&
2347                      instr->Bit(6) == 1) {
2348             int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2349             char type = instr->Bit(10) != 0 ? 'f' : 's';
2350             if (instr->Bits(9, 6) == 0xD) {
2351               // vabs<type>.<size> Qd, Qm.
2352               out_buffer_pos_ +=
2353                   SNPrintF(out_buffer_ + out_buffer_pos_, "vabs.%c%d q%d, q%d",
2354                            type, size, Vd, Vm);
2355             } else if (instr->Bits(9, 6) == 0xF) {
2356               // vneg<type>.<size> Qd, Qm.
2357               out_buffer_pos_ +=
2358                   SNPrintF(out_buffer_ + out_buffer_pos_, "vneg.%c%d q%d, q%d",
2359                            type, size, Vd, Vm);
2360             } else {
2361               Unknown(instr);
2362             }
2363           } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5 &&
2364                      instr->Bit(6) == 1) {
2365             // vrecpe/vrsqrte.f32 Qd, Qm.
2366             const char* op = instr->Bit(7) == 0 ? "vrecpe" : "vrsqrte";
2367             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2368                                         "%s.f32 q%d, q%d", op, Vd, Vm);
2369           } else {
2370             Unknown(instr);
2371           }
2372         }
2373       } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1 &&
2374                  instr->Bit(6) == 1) {
2375         // vshr.u<size> Qd, Qm, shift
2376         int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2377         int shift = 2 * size - instr->Bits(21, 16);
2378         int Vd = instr->VFPDRegValue(kSimd128Precision);
2379         int Vm = instr->VFPMRegValue(kSimd128Precision);
2380         out_buffer_pos_ +=
2381             SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.u%d q%d, q%d, #%d",
2382                      size, Vd, Vm, shift);
2383       } else if (instr->Bit(10) == 1 && instr->Bit(6) == 0 &&
2384                  instr->Bit(4) == 1) {
2385         // vsli.<size> Dd, Dm, shift
2386         // vsri.<size> Dd, Dm, shift
2387         int imm7 = instr->Bits(21, 16);
2388         if (instr->Bit(7) != 0) imm7 += 64;
2389         int size = base::bits::RoundDownToPowerOfTwo32(imm7);
2390         int shift;
2391         char direction;
2392         if (instr->Bit(8) == 1) {
2393           shift = imm7 - size;
2394           direction = 'l';  // vsli
2395         } else {
2396           shift = 2 * size - imm7;
2397           direction = 'r';  // vsri
2398         }
2399         int Vd = instr->VFPDRegValue(kDoublePrecision);
2400         int Vm = instr->VFPMRegValue(kDoublePrecision);
2401         out_buffer_pos_ +=
2402             SNPrintF(out_buffer_ + out_buffer_pos_, "vs%ci.%d d%d, d%d, #%d",
2403                      direction, size, Vd, Vm, shift);
2404       } else {
2405         Unknown(instr);
2406       }
2407       break;
2408     case 8:
2409       if (instr->Bits(21, 20) == 0) {
2410         // vst1
2411         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
2412         int Rn = instr->VnValue();
2413         int type = instr->Bits(11, 8);
2414         int size = instr->Bits(7, 6);
2415         int align = instr->Bits(5, 4);
2416         int Rm = instr->VmValue();
2417         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vst1.%d ",
2418                                     (1 << size) << 3);
2419         FormatNeonList(Vd, type);
2420         Print(", ");
2421         FormatNeonMemory(Rn, align, Rm);
2422       } else if (instr->Bits(21, 20) == 2) {
2423         // vld1
2424         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
2425         int Rn = instr->VnValue();
2426         int type = instr->Bits(11, 8);
2427         int size = instr->Bits(7, 6);
2428         int align = instr->Bits(5, 4);
2429         int Rm = instr->VmValue();
2430         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vld1.%d ",
2431                                     (1 << size) << 3);
2432         FormatNeonList(Vd, type);
2433         Print(", ");
2434         FormatNeonMemory(Rn, align, Rm);
2435       } else {
2436         Unknown(instr);
2437       }
2438       break;
2439     case 0xA:
2440     case 0xB:
2441       if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xF)) {
2442         const char* rn_name = converter_.NameOfCPURegister(instr->Bits(19, 16));
2443         int offset = instr->Bits(11, 0);
2444         if (offset == 0) {
2445           out_buffer_pos_ +=
2446               SNPrintF(out_buffer_ + out_buffer_pos_, "pld [%s]", rn_name);
2447         } else if (instr->Bit(23) == 0) {
2448           out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2449                                       "pld [%s, #-%d]", rn_name, offset);
2450         } else {
2451           out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2452                                       "pld [%s, #+%d]", rn_name, offset);
2453         }
2454       } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) {
2455         int option = instr->Bits(3, 0);
2456         switch (instr->Bits(7, 4)) {
2457           case 4:
2458             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "dsb %s",
2459                                         barrier_option_names[option]);
2460             break;
2461           case 5:
2462             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "dmb %s",
2463                                         barrier_option_names[option]);
2464             break;
2465           case 6:
2466             out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "isb %s",
2467                                         barrier_option_names[option]);
2468             break;
2469           default:
2470             Unknown(instr);
2471         }
2472       } else {
2473         Unknown(instr);
2474       }
2475       break;
2476     case 0x1D:
2477       if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 &&
2478           instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 &&
2479           instr->Bit(4) == 0x0) {
2480         // VRINTA, VRINTN, VRINTP, VRINTM (floating-point)
2481         bool dp_operation = (instr->SzValue() == 1);
2482         int rounding_mode = instr->Bits(17, 16);
2483         switch (rounding_mode) {
2484           case 0x0:
2485             if (dp_operation) {
2486               Format(instr, "vrinta.f64.f64 'Dd, 'Dm");
2487             } else {
2488               Format(instr, "vrinta.f32.f32 'Sd, 'Sm");
2489             }
2490             break;
2491           case 0x1:
2492             if (dp_operation) {
2493               Format(instr, "vrintn.f64.f64 'Dd, 'Dm");
2494             } else {
2495               Format(instr, "vrintn.f32.f32 'Sd, 'Sm");
2496             }
2497             break;
2498           case 0x2:
2499             if (dp_operation) {
2500               Format(instr, "vrintp.f64.f64 'Dd, 'Dm");
2501             } else {
2502               Format(instr, "vrintp.f32.f32 'Sd, 'Sm");
2503             }
2504             break;
2505           case 0x3:
2506             if (dp_operation) {
2507               Format(instr, "vrintm.f64.f64 'Dd, 'Dm");
2508             } else {
2509               Format(instr, "vrintm.f32.f32 'Sd, 'Sm");
2510             }
2511             break;
2512           default:
2513             UNREACHABLE();  // Case analysis is exhaustive.
2514             break;
2515         }
2516       } else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) &&
2517                  (instr->Bit(4) == 0x0)) {
2518         // VMAXNM, VMINNM (floating-point)
2519         if (instr->SzValue() == 0x1) {
2520           if (instr->Bit(6) == 0x1) {
2521             Format(instr, "vminnm.f64 'Dd, 'Dn, 'Dm");
2522           } else {
2523             Format(instr, "vmaxnm.f64 'Dd, 'Dn, 'Dm");
2524           }
2525         } else {
2526           if (instr->Bit(6) == 0x1) {
2527             Format(instr, "vminnm.f32 'Sd, 'Sn, 'Sm");
2528           } else {
2529             Format(instr, "vmaxnm.f32 'Sd, 'Sn, 'Sm");
2530           }
2531         }
2532       } else {
2533         Unknown(instr);
2534       }
2535       break;
2536     case 0x1C:
2537       if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
2538           (instr->Bit(4) == 0)) {
2539         // VSEL* (floating-point)
2540         bool dp_operation = (instr->SzValue() == 1);
2541         switch (instr->Bits(21, 20)) {
2542           case 0x0:
2543             if (dp_operation) {
2544               Format(instr, "vseleq.f64 'Dd, 'Dn, 'Dm");
2545             } else {
2546               Format(instr, "vseleq.f32 'Sd, 'Sn, 'Sm");
2547             }
2548             break;
2549           case 0x1:
2550             if (dp_operation) {
2551               Format(instr, "vselvs.f64 'Dd, 'Dn, 'Dm");
2552             } else {
2553               Format(instr, "vselvs.f32 'Sd, 'Sn, 'Sm");
2554             }
2555             break;
2556           case 0x2:
2557             if (dp_operation) {
2558               Format(instr, "vselge.f64 'Dd, 'Dn, 'Dm");
2559             } else {
2560               Format(instr, "vselge.f32 'Sd, 'Sn, 'Sm");
2561             }
2562             break;
2563           case 0x3:
2564             if (dp_operation) {
2565               Format(instr, "vselgt.f64 'Dd, 'Dn, 'Dm");
2566             } else {
2567               Format(instr, "vselgt.f32 'Sd, 'Sn, 'Sm");
2568             }
2569             break;
2570           default:
2571             UNREACHABLE();  // Case analysis is exhaustive.
2572             break;
2573         }
2574       } else {
2575         Unknown(instr);
2576       }
2577       break;
2578     default:
2579       Unknown(instr);
2580       break;
2581   }
2582 }
2583 
2584 #undef VERIFIY
2585 
IsConstantPoolAt(byte * instr_ptr)2586 bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
2587   int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2588   return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
2589 }
2590 
2591 
ConstantPoolSizeAt(byte * instr_ptr)2592 int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
2593   if (IsConstantPoolAt(instr_ptr)) {
2594     int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2595     return DecodeConstantPoolLength(instruction_bits);
2596   } else {
2597     return -1;
2598   }
2599 }
2600 
2601 
2602 // Disassemble the instruction at *instr_ptr into the output buffer.
InstructionDecode(byte * instr_ptr)2603 int Decoder::InstructionDecode(byte* instr_ptr) {
2604   Instruction* instr = Instruction::At(reinterpret_cast<Address>(instr_ptr));
2605   // Print raw instruction bytes.
2606   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2607                               "%08x       ",
2608                               instr->InstructionBits());
2609   if (instr->ConditionField() == kSpecialCondition) {
2610     DecodeSpecialCondition(instr);
2611     return kInstrSize;
2612   }
2613   int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2614   if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
2615     out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2616                                 "constant pool begin (length %d)",
2617                                 DecodeConstantPoolLength(instruction_bits));
2618     return kInstrSize;
2619   }
2620   switch (instr->TypeValue()) {
2621     case 0:
2622     case 1: {
2623       DecodeType01(instr);
2624       break;
2625     }
2626     case 2: {
2627       DecodeType2(instr);
2628       break;
2629     }
2630     case 3: {
2631       DecodeType3(instr);
2632       break;
2633     }
2634     case 4: {
2635       DecodeType4(instr);
2636       break;
2637     }
2638     case 5: {
2639       DecodeType5(instr);
2640       break;
2641     }
2642     case 6: {
2643       DecodeType6(instr);
2644       break;
2645     }
2646     case 7: {
2647       return DecodeType7(instr);
2648     }
2649     default: {
2650       // The type field is 3-bits in the ARM encoding.
2651       UNREACHABLE();
2652       break;
2653     }
2654   }
2655   return kInstrSize;
2656 }
2657 
2658 
2659 }  // namespace internal
2660 }  // namespace v8
2661 
2662 
2663 //------------------------------------------------------------------------------
2664 
2665 namespace disasm {
2666 
2667 
NameOfAddress(byte * addr) const2668 const char* NameConverter::NameOfAddress(byte* addr) const {
2669   v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
2670   return tmp_buffer_.start();
2671 }
2672 
2673 
NameOfConstant(byte * addr) const2674 const char* NameConverter::NameOfConstant(byte* addr) const {
2675   return NameOfAddress(addr);
2676 }
2677 
2678 
NameOfCPURegister(int reg) const2679 const char* NameConverter::NameOfCPURegister(int reg) const {
2680   return v8::internal::GetRegConfig()->GetGeneralRegisterName(reg);
2681 }
2682 
2683 
NameOfByteCPURegister(int reg) const2684 const char* NameConverter::NameOfByteCPURegister(int reg) const {
2685   UNREACHABLE();  // ARM does not have the concept of a byte register
2686   return "nobytereg";
2687 }
2688 
2689 
NameOfXMMRegister(int reg) const2690 const char* NameConverter::NameOfXMMRegister(int reg) const {
2691   UNREACHABLE();  // ARM does not have any XMM registers
2692   return "noxmmreg";
2693 }
2694 
2695 
NameInCode(byte * addr) const2696 const char* NameConverter::NameInCode(byte* addr) const {
2697   // The default name converter is called for unknown code. So we will not try
2698   // to access any memory.
2699   return "";
2700 }
2701 
2702 
2703 //------------------------------------------------------------------------------
2704 
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)2705 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
2706                                     byte* instruction) {
2707   v8::internal::Decoder d(converter_, buffer);
2708   return d.InstructionDecode(instruction);
2709 }
2710 
2711 
ConstantPoolSizeAt(byte * instruction)2712 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2713   return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
2714 }
2715 
Disassemble(FILE * f,byte * begin,byte * end,UnimplementedOpcodeAction unimplemented_action)2716 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
2717                                UnimplementedOpcodeAction unimplemented_action) {
2718   NameConverter converter;
2719   Disassembler d(converter, unimplemented_action);
2720   for (byte* pc = begin; pc < end;) {
2721     v8::internal::EmbeddedVector<char, 128> buffer;
2722     buffer[0] = '\0';
2723     byte* prev_pc = pc;
2724     pc += d.InstructionDecode(buffer, pc);
2725     v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
2726                          *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
2727   }
2728 }
2729 
2730 }  // namespace disasm
2731 
2732 #endif  // V8_TARGET_ARCH_ARM
2733