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