1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  */
4 // Copyright 2011 the V8 project authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style license that can be
6 // found in the LICENSE file.
7 
8 // A Disassembler object is used to disassemble a block of code instruction by
9 // instruction. The default implementation of the NameConverter object can be
10 // overriden to modify register names or to do symbol lookup on addresses.
11 //
12 // The example below will disassemble a block of code and print it to stdout.
13 //
14 //   disasm::NameConverter converter;
15 //   disasm::Disassembler d(converter);
16 //   for (uint8_t* pc = begin; pc < end;) {
17 //     disasm::EmbeddedVector<char, disasm::ReasonableBufferSize> buffer;
18 //     uint8_t* prev_pc = pc;
19 //     pc += d.InstructionDecode(buffer, pc);
20 //     printf("%p    %08x      %s\n",
21 //            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
22 //   }
23 //
24 // The Disassembler class also has a convenience method to disassemble a block
25 // of code into a FILE*, meaning that the above functionality could also be
26 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
27 
28 #include "jit/arm/disasm/Disasm-arm.h"
29 
30 #ifdef JS_DISASM_ARM
31 
32 #  include <stdarg.h>
33 #  include <stdio.h>
34 #  include <string.h>
35 
36 #  include "jit/arm/disasm/Constants-arm.h"
37 
38 namespace js {
39 namespace jit {
40 namespace disasm {
41 
42 // Helper function for printing to a Vector.
43 static int MOZ_FORMAT_PRINTF(2, 3)
SNPrintF(V8Vector<char> str,const char * format,...)44     SNPrintF(V8Vector<char> str, const char* format, ...) {
45   va_list args;
46   va_start(args, format);
47   int result = vsnprintf(str.start(), str.length(), format, args);
48   va_end(args);
49   return result;
50 }
51 
52 //------------------------------------------------------------------------------
53 
54 // Decoder decodes and disassembles instructions into an output buffer.
55 // It uses the converter to convert register names and call destinations into
56 // more informative description.
57 class Decoder {
58  public:
Decoder(const disasm::NameConverter & converter,V8Vector<char> out_buffer)59   Decoder(const disasm::NameConverter& converter, V8Vector<char> out_buffer)
60       : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) {
61     out_buffer_[out_buffer_pos_] = '\0';
62   }
63 
~Decoder()64   ~Decoder() {}
65 
66   // Writes one disassembled instruction into 'buffer' (0-terminated).
67   // Returns the length of the disassembled machine instruction in bytes.
68   int InstructionDecode(uint8_t* instruction);
69 
70   static bool IsConstantPoolAt(uint8_t* instr_ptr);
71   static int ConstantPoolSizeAt(uint8_t* instr_ptr);
72 
73  private:
74   // Bottleneck functions to print into the out_buffer.
75   void PrintChar(const char ch);
76   void Print(const char* str);
77 
78   // Printing of common values.
79   void PrintRegister(int reg);
80   void PrintSRegister(int reg);
81   void PrintDRegister(int reg);
82   int FormatVFPRegister(Instruction* instr, const char* format);
83   void PrintMovwMovt(Instruction* instr);
84   int FormatVFPinstruction(Instruction* instr, const char* format);
85   void PrintCondition(Instruction* instr);
86   void PrintShiftRm(Instruction* instr);
87   void PrintShiftImm(Instruction* instr);
88   void PrintShiftSat(Instruction* instr);
89   void PrintPU(Instruction* instr);
90   void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
91 
92   // Handle formatting of instructions and their options.
93   int FormatRegister(Instruction* instr, const char* option);
94   void FormatNeonList(int Vd, int type);
95   void FormatNeonMemory(int Rn, int align, int Rm);
96   int FormatOption(Instruction* instr, const char* option);
97   void Format(Instruction* instr, const char* format);
98   void Unknown(Instruction* instr);
99 
100   // Each of these functions decodes one particular instruction type, a 3-bit
101   // field in the instruction encoding.
102   // Types 0 and 1 are combined as they are largely the same except for the way
103   // they interpret the shifter operand.
104   void DecodeType01(Instruction* instr);
105   void DecodeType2(Instruction* instr);
106   void DecodeType3(Instruction* instr);
107   void DecodeType4(Instruction* instr);
108   void DecodeType5(Instruction* instr);
109   void DecodeType6(Instruction* instr);
110   // Type 7 includes special Debugger instructions.
111   int DecodeType7(Instruction* instr);
112   // For VFP support.
113   void DecodeTypeVFP(Instruction* instr);
114   void DecodeType6CoprocessorIns(Instruction* instr);
115 
116   void DecodeSpecialCondition(Instruction* instr);
117 
118   void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
119   void DecodeVCMP(Instruction* instr);
120   void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
121   void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
122 
123   const disasm::NameConverter& converter_;
124   V8Vector<char> out_buffer_;
125   int out_buffer_pos_;
126 
127   // Disallow copy and assign.
128   Decoder(const Decoder&) = delete;
129   void operator=(const Decoder&) = delete;
130 };
131 
132 // Support for assertions in the Decoder formatting functions.
133 #  define STRING_STARTS_WITH(string, compare_string) \
134     (strncmp(string, compare_string, strlen(compare_string)) == 0)
135 
136 // Append the ch to the output buffer.
PrintChar(const char ch)137 void Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; }
138 
139 // Append the str to the output buffer.
Print(const char * str)140 void Decoder::Print(const char* str) {
141   char cur = *str++;
142   while (cur != '\0' && (out_buffer_pos_ < int(out_buffer_.length() - 1))) {
143     PrintChar(cur);
144     cur = *str++;
145   }
146   out_buffer_[out_buffer_pos_] = 0;
147 }
148 
149 // These condition names are defined in a way to match the native disassembler
150 // formatting. See for example the command "objdump -d <binary file>".
151 static const char* const cond_names[kNumberOfConditions] = {
152     "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
153     "hi", "ls", "ge", "lt", "gt", "le", "",   "invalid",
154 };
155 
156 // Print the condition guarding the instruction.
PrintCondition(Instruction * instr)157 void Decoder::PrintCondition(Instruction* instr) {
158   Print(cond_names[instr->ConditionValue()]);
159 }
160 
161 // Print the register name according to the active name converter.
PrintRegister(int reg)162 void Decoder::PrintRegister(int reg) {
163   Print(converter_.NameOfCPURegister(reg));
164 }
165 
166 // Print the VFP S register name according to the active name converter.
PrintSRegister(int reg)167 void Decoder::PrintSRegister(int reg) { Print(VFPRegisters::Name(reg, false)); }
168 
169 // Print the VFP D register name according to the active name converter.
PrintDRegister(int reg)170 void Decoder::PrintDRegister(int reg) { Print(VFPRegisters::Name(reg, true)); }
171 
172 // These shift names are defined in a way to match the native disassembler
173 // formatting. See for example the command "objdump -d <binary file>".
174 static const char* const shift_names[kNumberOfShifts] = {"lsl", "lsr", "asr",
175                                                          "ror"};
176 
177 // Print the register shift operands for the instruction. Generally used for
178 // data processing instructions.
PrintShiftRm(Instruction * instr)179 void Decoder::PrintShiftRm(Instruction* instr) {
180   ShiftOp shift = instr->ShiftField();
181   int shift_index = instr->ShiftValue();
182   int shift_amount = instr->ShiftAmountValue();
183   int rm = instr->RmValue();
184 
185   PrintRegister(rm);
186 
187   if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) {
188     // Special case for using rm only.
189     return;
190   }
191   if (instr->RegShiftValue() == 0) {
192     // by immediate
193     if ((shift == ROR) && (shift_amount == 0)) {
194       Print(", RRX");
195       return;
196     } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
197       shift_amount = 32;
198     }
199     out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", %s #%d",
200                                 shift_names[shift_index], shift_amount);
201   } else {
202     // by register
203     int rs = instr->RsValue();
204     out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", %s ",
205                                 shift_names[shift_index]);
206     PrintRegister(rs);
207   }
208 }
209 
RotateRight32(uint32_t value,uint32_t shift)210 static inline uint32_t RotateRight32(uint32_t value, uint32_t shift) {
211   if (shift == 0) return value;
212   return (value >> shift) | (value << (32 - shift));
213 }
214 
215 // Print the immediate operand for the instruction. Generally used for data
216 // processing instructions.
PrintShiftImm(Instruction * instr)217 void Decoder::PrintShiftImm(Instruction* instr) {
218   int rotate = instr->RotateValue() * 2;
219   int immed8 = instr->Immed8Value();
220   int imm = RotateRight32(immed8, rotate);
221   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm);
222 }
223 
224 // Print the optional shift and immediate used by saturating instructions.
PrintShiftSat(Instruction * instr)225 void Decoder::PrintShiftSat(Instruction* instr) {
226   int shift = instr->Bits(11, 7);
227   if (shift > 0) {
228     out_buffer_pos_ +=
229         SNPrintF(out_buffer_ + out_buffer_pos_, ", %s #%d",
230                  shift_names[instr->Bit(6) * 2], instr->Bits(11, 7));
231   }
232 }
233 
234 // Print PU formatting to reduce complexity of FormatOption.
PrintPU(Instruction * instr)235 void Decoder::PrintPU(Instruction* instr) {
236   switch (instr->PUField()) {
237     case da_x: {
238       Print("da");
239       break;
240     }
241     case ia_x: {
242       Print("ia");
243       break;
244     }
245     case db_x: {
246       Print("db");
247       break;
248     }
249     case ib_x: {
250       Print("ib");
251       break;
252     }
253     default: {
254       MOZ_CRASH();
255       break;
256     }
257   }
258 }
259 
260 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
261 // the FormatOption method.
PrintSoftwareInterrupt(SoftwareInterruptCodes svc)262 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
263   switch (svc) {
264     case kCallRtRedirected:
265       Print("call rt redirected");
266       return;
267     case kBreakpoint:
268       Print("breakpoint");
269       return;
270     default:
271       if (svc >= kStopCode) {
272         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d - 0x%x",
273                                     svc & kStopCodeMask, svc & kStopCodeMask);
274       } else {
275         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", svc);
276       }
277       return;
278   }
279 }
280 
281 // Handle all register based formatting in this function to reduce the
282 // complexity of FormatOption.
FormatRegister(Instruction * instr,const char * format)283 int Decoder::FormatRegister(Instruction* instr, const char* format) {
284   MOZ_ASSERT(format[0] == 'r');
285   if (format[1] == 'n') {  // 'rn: Rn register
286     int reg = instr->RnValue();
287     PrintRegister(reg);
288     return 2;
289   } else if (format[1] == 'd') {  // 'rd: Rd register
290     int reg = instr->RdValue();
291     PrintRegister(reg);
292     return 2;
293   } else if (format[1] == 's') {  // 'rs: Rs register
294     int reg = instr->RsValue();
295     PrintRegister(reg);
296     return 2;
297   } else if (format[1] == 'm') {  // 'rm: Rm register
298     int reg = instr->RmValue();
299     PrintRegister(reg);
300     return 2;
301   } else if (format[1] == 't') {  // 'rt: Rt register
302     int reg = instr->RtValue();
303     PrintRegister(reg);
304     return 2;
305   } else if (format[1] == 'l') {
306     // 'rlist: register list for load and store multiple instructions
307     MOZ_ASSERT(STRING_STARTS_WITH(format, "rlist"));
308     int rlist = instr->RlistValue();
309     int reg = 0;
310     Print("{");
311     // Print register list in ascending order, by scanning the bit mask.
312     while (rlist != 0) {
313       if ((rlist & 1) != 0) {
314         PrintRegister(reg);
315         if ((rlist >> 1) != 0) {
316           Print(", ");
317         }
318       }
319       reg++;
320       rlist >>= 1;
321     }
322     Print("}");
323     return 5;
324   }
325   MOZ_CRASH();
326   return -1;
327 }
328 
329 // Handle all VFP register based formatting in this function to reduce the
330 // complexity of FormatOption.
FormatVFPRegister(Instruction * instr,const char * format)331 int Decoder::FormatVFPRegister(Instruction* instr, const char* format) {
332   MOZ_ASSERT((format[0] == 'S') || (format[0] == 'D'));
333 
334   VFPRegPrecision precision =
335       format[0] == 'D' ? kDoublePrecision : kSinglePrecision;
336 
337   int retval = 2;
338   int reg = -1;
339   if (format[1] == 'n') {
340     reg = instr->VFPNRegValue(precision);
341   } else if (format[1] == 'm') {
342     reg = instr->VFPMRegValue(precision);
343   } else if (format[1] == 'd') {
344     if ((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) &&
345         (instr->Bits(11, 9) == 0x5) && (instr->Bit(4) == 0x1)) {
346       // vmov.32 has Vd in a different place.
347       reg = instr->Bits(19, 16) | (instr->Bit(7) << 4);
348     } else {
349       reg = instr->VFPDRegValue(precision);
350     }
351 
352     if (format[2] == '+') {
353       int immed8 = instr->Immed8Value();
354       if (format[0] == 'S') reg += immed8 - 1;
355       if (format[0] == 'D') reg += (immed8 / 2 - 1);
356     }
357     if (format[2] == '+') retval = 3;
358   } else {
359     MOZ_CRASH();
360   }
361 
362   if (precision == kSinglePrecision) {
363     PrintSRegister(reg);
364   } else {
365     PrintDRegister(reg);
366   }
367 
368   return retval;
369 }
370 
FormatVFPinstruction(Instruction * instr,const char * format)371 int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) {
372   Print(format);
373   return 0;
374 }
375 
FormatNeonList(int Vd,int type)376 void Decoder::FormatNeonList(int Vd, int type) {
377   if (type == nlt_1) {
378     out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "{d%d}", Vd);
379   } else if (type == nlt_2) {
380     out_buffer_pos_ +=
381         SNPrintF(out_buffer_ + out_buffer_pos_, "{d%d, d%d}", Vd, Vd + 1);
382   } else if (type == nlt_3) {
383     out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
384                                 "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2);
385   } else if (type == nlt_4) {
386     out_buffer_pos_ +=
387         SNPrintF(out_buffer_ + out_buffer_pos_, "{d%d, d%d, d%d, d%d}", Vd,
388                  Vd + 1, Vd + 2, Vd + 3);
389   }
390 }
391 
FormatNeonMemory(int Rn,int align,int Rm)392 void Decoder::FormatNeonMemory(int Rn, int align, int Rm) {
393   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "[r%d", Rn);
394   if (align != 0) {
395     out_buffer_pos_ +=
396         SNPrintF(out_buffer_ + out_buffer_pos_, ":%d", (1 << align) << 6);
397   }
398   if (Rm == 15) {
399     Print("]");
400   } else if (Rm == 13) {
401     Print("]!");
402   } else {
403     out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "], r%d", Rm);
404   }
405 }
406 
407 // Print the movw or movt instruction.
PrintMovwMovt(Instruction * instr)408 void Decoder::PrintMovwMovt(Instruction* instr) {
409   int imm = instr->ImmedMovwMovtValue();
410   int rd = instr->RdValue();
411   PrintRegister(rd);
412   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm);
413 }
414 
415 // FormatOption takes a formatting string and interprets it based on
416 // the current instructions. The format string points to the first
417 // character of the option string (the option escape has already been
418 // consumed by the caller.)  FormatOption returns the number of
419 // characters that were consumed from the formatting string.
FormatOption(Instruction * instr,const char * format)420 int Decoder::FormatOption(Instruction* instr, const char* format) {
421   switch (format[0]) {
422     case 'a': {  // 'a: accumulate multiplies
423       if (instr->Bit(21) == 0) {
424         Print("ul");
425       } else {
426         Print("la");
427       }
428       return 1;
429     }
430     case 'b': {  // 'b: byte loads or stores
431       if (instr->HasB()) {
432         Print("b");
433       }
434       return 1;
435     }
436     case 'c': {  // 'cond: conditional execution
437       MOZ_ASSERT(STRING_STARTS_WITH(format, "cond"));
438       PrintCondition(instr);
439       return 4;
440     }
441     case 'd': {  // 'd: vmov double immediate.
442       double d = instr->DoubleImmedVmov();
443       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d);
444       return 1;
445     }
446     case 'f': {  // 'f: bitfield instructions - v7 and above.
447       uint32_t lsbit = instr->Bits(11, 7);
448       uint32_t width = instr->Bits(20, 16) + 1;
449       if (instr->Bit(21) == 0) {
450         // BFC/BFI:
451         // Bits 20-16 represent most-significant bit. Covert to width.
452         width -= lsbit;
453         MOZ_ASSERT(width > 0);
454       }
455       MOZ_ASSERT((width + lsbit) <= 32);
456       out_buffer_pos_ +=
457           SNPrintF(out_buffer_ + out_buffer_pos_, "#%d, #%d", lsbit, width);
458       return 1;
459     }
460     case 'h': {  // 'h: halfword operation for extra loads and stores
461       if (instr->HasH()) {
462         Print("h");
463       } else {
464         Print("b");
465       }
466       return 1;
467     }
468     case 'i': {  // 'i: immediate value from adjacent bits.
469       // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16
470       int width = (format[3] - '0') * 10 + (format[4] - '0');
471       int lsb = (format[6] - '0') * 10 + (format[7] - '0');
472 
473       MOZ_ASSERT((width >= 1) && (width <= 32));
474       MOZ_ASSERT((lsb >= 0) && (lsb <= 31));
475       MOZ_ASSERT((width + lsb) <= 32);
476 
477       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d",
478                                   instr->Bits(width + lsb - 1, lsb));
479       return 8;
480     }
481     case 'l': {  // 'l: branch and link
482       if (instr->HasLink()) {
483         Print("l");
484       }
485       return 1;
486     }
487     case 'm': {
488       if (format[1] == 'w') {
489         // 'mw: movt/movw instructions.
490         PrintMovwMovt(instr);
491         return 2;
492       }
493       if (format[1] == 'e') {  // 'memop: load/store instructions.
494         MOZ_ASSERT(STRING_STARTS_WITH(format, "memop"));
495         if (instr->HasL()) {
496           Print("ldr");
497         } else {
498           if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) &&
499               (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) {
500             if (instr->Bit(5) == 1) {
501               Print("strd");
502             } else {
503               Print("ldrd");
504             }
505             return 5;
506           }
507           Print("str");
508         }
509         return 5;
510       }
511       // 'msg: for simulator break instructions
512       MOZ_ASSERT(STRING_STARTS_WITH(format, "msg"));
513       uint8_t* str =
514           reinterpret_cast<uint8_t*>(instr->InstructionBits() & 0x0fffffff);
515       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
516                                   converter_.NameInCode(str));
517       return 3;
518     }
519     case 'o': {
520       if ((format[3] == '1') && (format[4] == '2')) {
521         // 'off12: 12-bit offset for load and store instructions
522         MOZ_ASSERT(STRING_STARTS_WITH(format, "off12"));
523         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d",
524                                     instr->Offset12Value());
525         return 5;
526       } else if (format[3] == '0') {
527         // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
528         MOZ_ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19"));
529         out_buffer_pos_ +=
530             SNPrintF(out_buffer_ + out_buffer_pos_, "%d",
531                      (instr->Bits(19, 8) << 4) + instr->Bits(3, 0));
532         return 15;
533       }
534       // 'off8: 8-bit offset for extra load and store instructions
535       MOZ_ASSERT(STRING_STARTS_WITH(format, "off8"));
536       int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
537       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8);
538       return 4;
539     }
540     case 'p': {  // 'pu: P and U bits for load and store instructions
541       MOZ_ASSERT(STRING_STARTS_WITH(format, "pu"));
542       PrintPU(instr);
543       return 2;
544     }
545     case 'r': {
546       return FormatRegister(instr, format);
547     }
548     case 's': {
549       if (format[1] == 'h') {    // 'shift_op or 'shift_rm or 'shift_sat.
550         if (format[6] == 'o') {  // 'shift_op
551           MOZ_ASSERT(STRING_STARTS_WITH(format, "shift_op"));
552           if (instr->TypeValue() == 0) {
553             PrintShiftRm(instr);
554           } else {
555             MOZ_ASSERT(instr->TypeValue() == 1);
556             PrintShiftImm(instr);
557           }
558           return 8;
559         } else if (format[6] == 's') {  // 'shift_sat.
560           MOZ_ASSERT(STRING_STARTS_WITH(format, "shift_sat"));
561           PrintShiftSat(instr);
562           return 9;
563         } else {  // 'shift_rm
564           MOZ_ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
565           PrintShiftRm(instr);
566           return 8;
567         }
568       } else if (format[1] == 'v') {  // 'svc
569         MOZ_ASSERT(STRING_STARTS_WITH(format, "svc"));
570         PrintSoftwareInterrupt(instr->SvcValue());
571         return 3;
572       } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
573         MOZ_ASSERT(STRING_STARTS_WITH(format, "sign"));
574         if (instr->HasSign()) {
575           Print("s");
576         }
577         return 4;
578       }
579       // 's: S field of data processing instructions
580       if (instr->HasS()) {
581         Print("s");
582       }
583       return 1;
584     }
585     case 't': {  // 'target: target of branch instructions
586       MOZ_ASSERT(STRING_STARTS_WITH(format, "target"));
587       int off = (instr->SImmed24Value() << 2) + 8;
588       out_buffer_pos_ += SNPrintF(
589           out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
590           converter_.NameOfAddress(reinterpret_cast<uint8_t*>(instr) + off));
591       return 6;
592     }
593     case 'u': {  // 'u: signed or unsigned multiplies
594       // The manual gets the meaning of bit 22 backwards in the multiply
595       // instruction overview on page A3.16.2.  The instructions that
596       // exist in u and s variants are the following:
597       // smull A4.1.87
598       // umull A4.1.129
599       // umlal A4.1.128
600       // smlal A4.1.76
601       // For these 0 means u and 1 means s.  As can be seen on their individual
602       // pages.  The other 18 mul instructions have the bit set or unset in
603       // arbitrary ways that are unrelated to the signedness of the instruction.
604       // None of these 18 instructions exist in both a 'u' and an 's' variant.
605 
606       if (instr->Bit(22) == 0) {
607         Print("u");
608       } else {
609         Print("s");
610       }
611       return 1;
612     }
613     case 'v': {
614       return FormatVFPinstruction(instr, format);
615     }
616     case 'S':
617     case 'D': {
618       return FormatVFPRegister(instr, format);
619     }
620     case 'w': {  // 'w: W field of load and store instructions
621       if (instr->HasW()) {
622         Print("!");
623       }
624       return 1;
625     }
626     default: {
627       MOZ_CRASH();
628       break;
629     }
630   }
631   MOZ_CRASH();
632   return -1;
633 }
634 
635 // Format takes a formatting string for a whole instruction and prints it into
636 // the output buffer. All escaped options are handed to FormatOption to be
637 // parsed further.
Format(Instruction * instr,const char * format)638 void Decoder::Format(Instruction* instr, const char* format) {
639   char cur = *format++;
640   while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
641     if (cur == '\'') {  // Single quote is used as the formatting escape.
642       format += FormatOption(instr, format);
643     } else {
644       out_buffer_[out_buffer_pos_++] = cur;
645     }
646     cur = *format++;
647   }
648   out_buffer_[out_buffer_pos_] = '\0';
649 }
650 
651 // The disassembler may end up decoding data inlined in the code. We do not want
652 // it to crash if the data does not ressemble any known instruction.
653 #  define VERIFY(condition) \
654     if (!(condition)) {     \
655       Unknown(instr);       \
656       return;               \
657     }
658 
659 // For currently unimplemented decodings the disassembler calls Unknown(instr)
660 // which will just print "unknown" of the instruction bits.
Unknown(Instruction * instr)661 void Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); }
662 
DecodeType01(Instruction * instr)663 void Decoder::DecodeType01(Instruction* instr) {
664   int type = instr->TypeValue();
665   if ((type == 0) && instr->IsSpecialType0()) {
666     // multiply instruction or extra loads and stores
667     if (instr->Bits(7, 4) == 9) {
668       if (instr->Bit(24) == 0) {
669         // multiply instructions
670         if (instr->Bit(23) == 0) {
671           if (instr->Bit(21) == 0) {
672             // The MUL instruction description (A 4.1.33) refers to Rd as being
673             // the destination for the operation, but it confusingly uses the
674             // Rn field to encode it.
675             Format(instr, "mul'cond's 'rn, 'rm, 'rs");
676           } else {
677             if (instr->Bit(22) == 0) {
678               // The MLA instruction description (A 4.1.28) refers to the order
679               // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
680               // Rn field to encode the Rd register and the Rd field to encode
681               // the Rn register.
682               Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
683             } else {
684               // The MLS instruction description (A 4.1.29) refers to the order
685               // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
686               // Rn field to encode the Rd register and the Rd field to encode
687               // the Rn register.
688               Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
689             }
690           }
691         } else {
692           // The signed/long multiply instructions use the terms RdHi and RdLo
693           // when referring to the target registers. They are mapped to the Rn
694           // and Rd fields as follows:
695           // RdLo == Rd field
696           // RdHi == Rn field
697           // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
698           Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
699         }
700       } else {
701         if (instr->Bits(ExclusiveOpHi, ExclusiveOpLo) == ExclusiveOpcode) {
702           if (instr->Bit(ExclusiveLoad) == 1) {
703             switch (instr->Bits(ExclusiveSizeHi, ExclusiveSizeLo)) {
704               case ExclusiveWord:
705                 Format(instr, "ldrex'cond 'rt, ['rn]");
706                 break;
707               case ExclusiveDouble:
708                 Format(instr, "ldrexd'cond 'rt, ['rn]");
709                 break;
710               case ExclusiveByte:
711                 Format(instr, "ldrexb'cond 'rt, ['rn]");
712                 break;
713               case ExclusiveHalf:
714                 Format(instr, "ldrexh'cond 'rt, ['rn]");
715                 break;
716             }
717           } else {
718             // The documentation names the low four bits of the
719             // store-exclusive instructions "Rt" but canonically
720             // for disassembly they are really "Rm".
721             switch (instr->Bits(ExclusiveSizeHi, ExclusiveSizeLo)) {
722               case ExclusiveWord:
723                 Format(instr, "strex'cond 'rd, 'rm, ['rn]");
724                 break;
725               case ExclusiveDouble:
726                 Format(instr, "strexd'cond 'rd, 'rm, ['rn]");
727                 break;
728               case ExclusiveByte:
729                 Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
730                 break;
731               case ExclusiveHalf:
732                 Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
733                 break;
734             }
735           }
736         } else {
737           Unknown(instr);
738         }
739       }
740     } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
741       // ldrd, strd
742       switch (instr->PUField()) {
743         case da_x: {
744           if (instr->Bit(22) == 0) {
745             Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
746           } else {
747             Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
748           }
749           break;
750         }
751         case ia_x: {
752           if (instr->Bit(22) == 0) {
753             Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
754           } else {
755             Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
756           }
757           break;
758         }
759         case db_x: {
760           if (instr->Bit(22) == 0) {
761             Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
762           } else {
763             Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
764           }
765           break;
766         }
767         case ib_x: {
768           if (instr->Bit(22) == 0) {
769             Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
770           } else {
771             Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
772           }
773           break;
774         }
775         default: {
776           // The PU field is a 2-bit field.
777           MOZ_CRASH();
778           break;
779         }
780       }
781     } else {
782       // extra load/store instructions
783       switch (instr->PUField()) {
784         case da_x: {
785           if (instr->Bit(22) == 0) {
786             Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
787           } else {
788             Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
789           }
790           break;
791         }
792         case ia_x: {
793           if (instr->Bit(22) == 0) {
794             Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
795           } else {
796             Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
797           }
798           break;
799         }
800         case db_x: {
801           if (instr->Bit(22) == 0) {
802             Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
803           } else {
804             Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
805           }
806           break;
807         }
808         case ib_x: {
809           if (instr->Bit(22) == 0) {
810             Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
811           } else {
812             Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
813           }
814           break;
815         }
816         default: {
817           // The PU field is a 2-bit field.
818           MOZ_CRASH();
819           break;
820         }
821       }
822       return;
823     }
824   } else if ((type == 0) && instr->IsMiscType0()) {
825     if (instr->Bits(22, 21) == 1) {
826       switch (instr->BitField(7, 4)) {
827         case BX:
828           Format(instr, "bx'cond 'rm");
829           break;
830         case BLX:
831           Format(instr, "blx'cond 'rm");
832           break;
833         case BKPT:
834           Format(instr, "bkpt 'off0to3and8to19");
835           break;
836         default:
837           Unknown(instr);  // not used by V8
838           break;
839       }
840     } else if (instr->Bits(22, 21) == 3) {
841       switch (instr->BitField(7, 4)) {
842         case CLZ:
843           Format(instr, "clz'cond 'rd, 'rm");
844           break;
845         default:
846           Unknown(instr);  // not used by V8
847           break;
848       }
849     } else {
850       Unknown(instr);  // not used by V8
851     }
852   } else if ((type == 1) && instr->IsNopType1()) {
853     Format(instr, "nop'cond");
854   } else if ((type == 1) && instr->IsCsdbType1()) {
855     Format(instr, "csdb'cond");
856   } else {
857     switch (instr->OpcodeField()) {
858       case AND: {
859         Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
860         break;
861       }
862       case EOR: {
863         Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
864         break;
865       }
866       case SUB: {
867         Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
868         break;
869       }
870       case RSB: {
871         Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
872         break;
873       }
874       case ADD: {
875         Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
876         break;
877       }
878       case ADC: {
879         Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
880         break;
881       }
882       case SBC: {
883         Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
884         break;
885       }
886       case RSC: {
887         Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
888         break;
889       }
890       case TST: {
891         if (instr->HasS()) {
892           Format(instr, "tst'cond 'rn, 'shift_op");
893         } else {
894           Format(instr, "movw'cond 'mw");
895         }
896         break;
897       }
898       case TEQ: {
899         if (instr->HasS()) {
900           Format(instr, "teq'cond 'rn, 'shift_op");
901         } else {
902           // Other instructions matching this pattern are handled in the
903           // miscellaneous instructions part above.
904           MOZ_CRASH();
905         }
906         break;
907       }
908       case CMP: {
909         if (instr->HasS()) {
910           Format(instr, "cmp'cond 'rn, 'shift_op");
911         } else {
912           Format(instr, "movt'cond 'mw");
913         }
914         break;
915       }
916       case CMN: {
917         if (instr->HasS()) {
918           Format(instr, "cmn'cond 'rn, 'shift_op");
919         } else {
920           // Other instructions matching this pattern are handled in the
921           // miscellaneous instructions part above.
922           MOZ_CRASH();
923         }
924         break;
925       }
926       case ORR: {
927         Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
928         break;
929       }
930       case MOV: {
931         Format(instr, "mov'cond's 'rd, 'shift_op");
932         break;
933       }
934       case BIC: {
935         Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
936         break;
937       }
938       case MVN: {
939         Format(instr, "mvn'cond's 'rd, 'shift_op");
940         break;
941       }
942       default: {
943         // The Opcode field is a 4-bit field.
944         MOZ_CRASH();
945         break;
946       }
947     }
948   }
949 }
950 
DecodeType2(Instruction * instr)951 void Decoder::DecodeType2(Instruction* instr) {
952   switch (instr->PUField()) {
953     case da_x: {
954       if (instr->HasW()) {
955         Unknown(instr);  // not used in V8
956         return;
957       }
958       Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
959       break;
960     }
961     case ia_x: {
962       if (instr->HasW()) {
963         Unknown(instr);  // not used in V8
964         return;
965       }
966       Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
967       break;
968     }
969     case db_x: {
970       Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
971       break;
972     }
973     case ib_x: {
974       Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
975       break;
976     }
977     default: {
978       // The PU field is a 2-bit field.
979       MOZ_CRASH();
980       break;
981     }
982   }
983 }
984 
DecodeType3(Instruction * instr)985 void Decoder::DecodeType3(Instruction* instr) {
986   switch (instr->PUField()) {
987     case da_x: {
988       VERIFY(!instr->HasW());
989       Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
990       break;
991     }
992     case ia_x: {
993       if (instr->Bit(4) == 0) {
994         Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
995       } else {
996         if (instr->Bit(5) == 0) {
997           switch (instr->Bits(22, 21)) {
998             case 0:
999               if (instr->Bit(20) == 0) {
1000                 if (instr->Bit(6) == 0) {
1001                   Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
1002                 } else {
1003                   if (instr->Bits(11, 7) == 0) {
1004                     Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
1005                   } else {
1006                     Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
1007                   }
1008                 }
1009               } else {
1010                 MOZ_CRASH();
1011               }
1012               break;
1013             case 1:
1014               MOZ_CRASH();
1015               break;
1016             case 2:
1017               MOZ_CRASH();
1018               break;
1019             case 3:
1020               Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
1021               break;
1022           }
1023         } else {
1024           switch (instr->Bits(22, 21)) {
1025             case 0:
1026               MOZ_CRASH();
1027               break;
1028             case 1:
1029               if (instr->Bits(9, 6) == 1) {
1030                 if (instr->Bit(20) == 0) {
1031                   if (instr->Bits(19, 16) == 0xF) {
1032                     switch (instr->Bits(11, 10)) {
1033                       case 0:
1034                         Format(instr, "sxtb'cond 'rd, 'rm");
1035                         break;
1036                       case 1:
1037                         Format(instr, "sxtb'cond 'rd, 'rm, ror #8");
1038                         break;
1039                       case 2:
1040                         Format(instr, "sxtb'cond 'rd, 'rm, ror #16");
1041                         break;
1042                       case 3:
1043                         Format(instr, "sxtb'cond 'rd, 'rm, ror #24");
1044                         break;
1045                     }
1046                   } else {
1047                     switch (instr->Bits(11, 10)) {
1048                       case 0:
1049                         Format(instr, "sxtab'cond 'rd, 'rn, 'rm");
1050                         break;
1051                       case 1:
1052                         Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8");
1053                         break;
1054                       case 2:
1055                         Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16");
1056                         break;
1057                       case 3:
1058                         Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24");
1059                         break;
1060                     }
1061                   }
1062                 } else {
1063                   if (instr->Bits(19, 16) == 0xF) {
1064                     switch (instr->Bits(11, 10)) {
1065                       case 0:
1066                         Format(instr, "sxth'cond 'rd, 'rm");
1067                         break;
1068                       case 1:
1069                         Format(instr, "sxth'cond 'rd, 'rm, ror #8");
1070                         break;
1071                       case 2:
1072                         Format(instr, "sxth'cond 'rd, 'rm, ror #16");
1073                         break;
1074                       case 3:
1075                         Format(instr, "sxth'cond 'rd, 'rm, ror #24");
1076                         break;
1077                     }
1078                   } else {
1079                     switch (instr->Bits(11, 10)) {
1080                       case 0:
1081                         Format(instr, "sxtah'cond 'rd, 'rn, 'rm");
1082                         break;
1083                       case 1:
1084                         Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8");
1085                         break;
1086                       case 2:
1087                         Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16");
1088                         break;
1089                       case 3:
1090                         Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24");
1091                         break;
1092                     }
1093                   }
1094                 }
1095               } else {
1096                 MOZ_CRASH();
1097               }
1098               break;
1099             case 2:
1100               if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
1101                 if (instr->Bits(19, 16) == 0xF) {
1102                   switch (instr->Bits(11, 10)) {
1103                     case 0:
1104                       Format(instr, "uxtb16'cond 'rd, 'rm");
1105                       break;
1106                     case 1:
1107                       Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
1108                       break;
1109                     case 2:
1110                       Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
1111                       break;
1112                     case 3:
1113                       Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
1114                       break;
1115                   }
1116                 } else {
1117                   MOZ_CRASH();
1118                 }
1119               } else {
1120                 MOZ_CRASH();
1121               }
1122               break;
1123             case 3:
1124               if ((instr->Bits(9, 6) == 1)) {
1125                 if ((instr->Bit(20) == 0)) {
1126                   if (instr->Bits(19, 16) == 0xF) {
1127                     switch (instr->Bits(11, 10)) {
1128                       case 0:
1129                         Format(instr, "uxtb'cond 'rd, 'rm");
1130                         break;
1131                       case 1:
1132                         Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
1133                         break;
1134                       case 2:
1135                         Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
1136                         break;
1137                       case 3:
1138                         Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
1139                         break;
1140                     }
1141                   } else {
1142                     switch (instr->Bits(11, 10)) {
1143                       case 0:
1144                         Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
1145                         break;
1146                       case 1:
1147                         Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
1148                         break;
1149                       case 2:
1150                         Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
1151                         break;
1152                       case 3:
1153                         Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
1154                         break;
1155                     }
1156                   }
1157                 } else {
1158                   if (instr->Bits(19, 16) == 0xF) {
1159                     switch (instr->Bits(11, 10)) {
1160                       case 0:
1161                         Format(instr, "uxth'cond 'rd, 'rm");
1162                         break;
1163                       case 1:
1164                         Format(instr, "uxth'cond 'rd, 'rm, ror #8");
1165                         break;
1166                       case 2:
1167                         Format(instr, "uxth'cond 'rd, 'rm, ror #16");
1168                         break;
1169                       case 3:
1170                         Format(instr, "uxth'cond 'rd, 'rm, ror #24");
1171                         break;
1172                     }
1173                   } else {
1174                     switch (instr->Bits(11, 10)) {
1175                       case 0:
1176                         Format(instr, "uxtah'cond 'rd, 'rn, 'rm");
1177                         break;
1178                       case 1:
1179                         Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8");
1180                         break;
1181                       case 2:
1182                         Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16");
1183                         break;
1184                       case 3:
1185                         Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24");
1186                         break;
1187                     }
1188                   }
1189                 }
1190               } else {
1191                 MOZ_CRASH();
1192               }
1193               break;
1194           }
1195         }
1196       }
1197       break;
1198     }
1199     case db_x: {
1200       if (instr->Bits(22, 20) == 0x5) {
1201         if (instr->Bits(7, 4) == 0x1) {
1202           if (instr->Bits(15, 12) == 0xF) {
1203             Format(instr, "smmul'cond 'rn, 'rm, 'rs");
1204           } else {
1205             // SMMLA (in V8 notation matching ARM ISA format)
1206             Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
1207           }
1208           break;
1209         }
1210       }
1211       bool FLAG_enable_sudiv = true;  // Flag doesn't exist in our engine.
1212       if (FLAG_enable_sudiv) {
1213         if (instr->Bits(5, 4) == 0x1) {
1214           if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
1215             if (instr->Bit(21) == 0x1) {
1216               // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1217               Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
1218             } else {
1219               // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1220               Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
1221             }
1222             break;
1223           }
1224         }
1225       }
1226       Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1227       break;
1228     }
1229     case ib_x: {
1230       if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1231         uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1232         uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1233         uint32_t msbit = widthminus1 + lsbit;
1234         if (msbit <= 31) {
1235           if (instr->Bit(22)) {
1236             Format(instr, "ubfx'cond 'rd, 'rm, 'f");
1237           } else {
1238             Format(instr, "sbfx'cond 'rd, 'rm, 'f");
1239           }
1240         } else {
1241           MOZ_CRASH();
1242         }
1243       } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
1244         uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1245         uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
1246         if (msbit >= lsbit) {
1247           if (instr->RmValue() == 15) {
1248             Format(instr, "bfc'cond 'rd, 'f");
1249           } else {
1250             Format(instr, "bfi'cond 'rd, 'rm, 'f");
1251           }
1252         } else {
1253           MOZ_CRASH();
1254         }
1255       } else {
1256         Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1257       }
1258       break;
1259     }
1260     default: {
1261       // The PU field is a 2-bit field.
1262       MOZ_CRASH();
1263       break;
1264     }
1265   }
1266 }
1267 
DecodeType4(Instruction * instr)1268 void Decoder::DecodeType4(Instruction* instr) {
1269   if (instr->Bit(22) != 0) {
1270     // Privileged mode currently not supported.
1271     Unknown(instr);
1272   } else {
1273     if (instr->HasL()) {
1274       Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1275     } else {
1276       Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1277     }
1278   }
1279 }
1280 
DecodeType5(Instruction * instr)1281 void Decoder::DecodeType5(Instruction* instr) {
1282   Format(instr, "b'l'cond 'target");
1283 }
1284 
DecodeType6(Instruction * instr)1285 void Decoder::DecodeType6(Instruction* instr) {
1286   DecodeType6CoprocessorIns(instr);
1287 }
1288 
DecodeType7(Instruction * instr)1289 int Decoder::DecodeType7(Instruction* instr) {
1290   if (instr->Bit(24) == 1) {
1291     if (instr->SvcValue() >= kStopCode) {
1292       Format(instr, "stop'cond 'svc");
1293       // Also print the stop message. Its address is encoded
1294       // in the following 4 bytes.
1295       out_buffer_pos_ += SNPrintF(
1296           out_buffer_ + out_buffer_pos_, "\n  %p  %08x       stop message: %s",
1297           reinterpret_cast<void*>(instr + Instruction::kInstrSize),
1298           *reinterpret_cast<uint32_t*>(instr + Instruction::kInstrSize),
1299           *reinterpret_cast<char**>(instr + Instruction::kInstrSize));
1300       // We have decoded 2 * Instruction::kInstrSize bytes.
1301       return 2 * Instruction::kInstrSize;
1302     } else {
1303       Format(instr, "svc'cond 'svc");
1304     }
1305   } else {
1306     DecodeTypeVFP(instr);
1307   }
1308   return Instruction::kInstrSize;
1309 }
1310 
1311 // void Decoder::DecodeTypeVFP(Instruction* instr)
1312 // vmov: Sn = Rt
1313 // vmov: Rt = Sn
1314 // vcvt: Dd = Sm
1315 // vcvt: Sd = Dm
1316 // vcvt.f64.s32 Dd, Dd, #<fbits>
1317 // Dd = vabs(Dm)
1318 // Sd = vabs(Sm)
1319 // Dd = vneg(Dm)
1320 // Sd = vneg(Sm)
1321 // Dd = vadd(Dn, Dm)
1322 // Sd = vadd(Sn, Sm)
1323 // Dd = vsub(Dn, Dm)
1324 // Sd = vsub(Sn, Sm)
1325 // Dd = vmul(Dn, Dm)
1326 // Sd = vmul(Sn, Sm)
1327 // Dd = vmla(Dn, Dm)
1328 // Sd = vmla(Sn, Sm)
1329 // Dd = vmls(Dn, Dm)
1330 // Sd = vmls(Sn, Sm)
1331 // Dd = vdiv(Dn, Dm)
1332 // Sd = vdiv(Sn, Sm)
1333 // vcmp(Dd, Dm)
1334 // vcmp(Sd, Sm)
1335 // Dd = vsqrt(Dm)
1336 // Sd = vsqrt(Sm)
1337 // vmrs
1338 // vmsr
DecodeTypeVFP(Instruction * instr)1339 void Decoder::DecodeTypeVFP(Instruction* instr) {
1340   VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
1341   VERIFY(instr->Bits(11, 9) == 0x5);
1342 
1343   if (instr->Bit(4) == 0) {
1344     if (instr->Opc1Value() == 0x7) {
1345       // Other data processing instructions
1346       if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
1347         // vmov register to register.
1348         if (instr->SzValue() == 0x1) {
1349           Format(instr, "vmov'cond.f64 'Dd, 'Dm");
1350         } else {
1351           Format(instr, "vmov'cond.f32 'Sd, 'Sm");
1352         }
1353       } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
1354         // vabs
1355         if (instr->SzValue() == 0x1) {
1356           Format(instr, "vabs'cond.f64 'Dd, 'Dm");
1357         } else {
1358           Format(instr, "vabs'cond.f32 'Sd, 'Sm");
1359         }
1360       } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
1361         // vneg
1362         if (instr->SzValue() == 0x1) {
1363           Format(instr, "vneg'cond.f64 'Dd, 'Dm");
1364         } else {
1365           Format(instr, "vneg'cond.f32 'Sd, 'Sm");
1366         }
1367       } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
1368         DecodeVCVTBetweenDoubleAndSingle(instr);
1369       } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
1370         DecodeVCVTBetweenFloatingPointAndInteger(instr);
1371       } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
1372                  (instr->Bit(8) == 1)) {
1373         // vcvt.f64.s32 Dd, Dd, #<fbits>
1374         int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
1375         Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
1376         out_buffer_pos_ +=
1377             SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", fraction_bits);
1378       } else if (((instr->Opc2Value() >> 1) == 0x6) &&
1379                  (instr->Opc3Value() & 0x1)) {
1380         DecodeVCVTBetweenFloatingPointAndInteger(instr);
1381       } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1382                  (instr->Opc3Value() & 0x1)) {
1383         DecodeVCMP(instr);
1384       } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
1385         if (instr->SzValue() == 0x1) {
1386           Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
1387         } else {
1388           Format(instr, "vsqrt'cond.f32 'Sd, 'Sm");
1389         }
1390       } else if (instr->Opc3Value() == 0x0) {
1391         if (instr->SzValue() == 0x1) {
1392           Format(instr, "vmov'cond.f64 'Dd, 'd");
1393         } else {
1394           Unknown(instr);  // Not used by V8.
1395         }
1396       } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) {
1397         // vrintz - round towards zero (truncate)
1398         if (instr->SzValue() == 0x1) {
1399           Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm");
1400         } else {
1401           Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm");
1402         }
1403       } else {
1404         Unknown(instr);  // Not used by V8.
1405       }
1406     } else if (instr->Opc1Value() == 0x3) {
1407       if (instr->SzValue() == 0x1) {
1408         if (instr->Opc3Value() & 0x1) {
1409           Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
1410         } else {
1411           Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
1412         }
1413       } else {
1414         if (instr->Opc3Value() & 0x1) {
1415           Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm");
1416         } else {
1417           Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm");
1418         }
1419       }
1420     } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
1421       if (instr->SzValue() == 0x1) {
1422         Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
1423       } else {
1424         Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm");
1425       }
1426     } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
1427       if (instr->SzValue() == 0x1) {
1428         Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
1429       } else {
1430         Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm");
1431       }
1432     } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
1433       if (instr->SzValue() == 0x1) {
1434         Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
1435       } else {
1436         Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm");
1437       }
1438     } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
1439       if (instr->SzValue() == 0x1) {
1440         Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
1441       } else {
1442         Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm");
1443       }
1444     } else {
1445       Unknown(instr);  // Not used by V8.
1446     }
1447   } else {
1448     if ((instr->VCValue() == 0x0) && (instr->VAValue() == 0x0)) {
1449       DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1450     } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1) &&
1451                (instr->Bit(23) == 0x0)) {
1452       if (instr->Bit(21) == 0x0) {
1453         Format(instr, "vmov'cond.32 'Dd[0], 'rt");
1454       } else {
1455         Format(instr, "vmov'cond.32 'Dd[1], 'rt");
1456       }
1457     } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1) &&
1458                (instr->Bit(23) == 0x0)) {
1459       if (instr->Bit(21) == 0x0) {
1460         Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
1461       } else {
1462         Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
1463       }
1464     } else if ((instr->VCValue() == 0x0) && (instr->VAValue() == 0x7) &&
1465                (instr->Bits(19, 16) == 0x1)) {
1466       if (instr->VLValue() == 0) {
1467         if (instr->Bits(15, 12) == 0xF) {
1468           Format(instr, "vmsr'cond FPSCR, APSR");
1469         } else {
1470           Format(instr, "vmsr'cond FPSCR, 'rt");
1471         }
1472       } else {
1473         if (instr->Bits(15, 12) == 0xF) {
1474           Format(instr, "vmrs'cond APSR, FPSCR");
1475         } else {
1476           Format(instr, "vmrs'cond 'rt, FPSCR");
1477         }
1478       }
1479     }
1480   }
1481 }
1482 
DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction * instr)1483 void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
1484     Instruction* instr) {
1485   VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
1486          (instr->VAValue() == 0x0));
1487 
1488   bool to_arm_register = (instr->VLValue() == 0x1);
1489 
1490   if (to_arm_register) {
1491     Format(instr, "vmov'cond 'rt, 'Sn");
1492   } else {
1493     Format(instr, "vmov'cond 'Sn, 'rt");
1494   }
1495 }
1496 
DecodeVCMP(Instruction * instr)1497 void Decoder::DecodeVCMP(Instruction* instr) {
1498   VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1499   VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1500          (instr->Opc3Value() & 0x1));
1501 
1502   // Comparison.
1503   bool dp_operation = (instr->SzValue() == 1);
1504   bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1505 
1506   if (dp_operation && !raise_exception_for_qnan) {
1507     if (instr->Opc2Value() == 0x4) {
1508       Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
1509     } else if (instr->Opc2Value() == 0x5) {
1510       Format(instr, "vcmp'cond.f64 'Dd, #0.0");
1511     } else {
1512       Unknown(instr);  // invalid
1513     }
1514   } else if (!raise_exception_for_qnan) {
1515     if (instr->Opc2Value() == 0x4) {
1516       Format(instr, "vcmp'cond.f32 'Sd, 'Sm");
1517     } else if (instr->Opc2Value() == 0x5) {
1518       Format(instr, "vcmp'cond.f32 'Sd, #0.0");
1519     } else {
1520       Unknown(instr);  // invalid
1521     }
1522   } else {
1523     Unknown(instr);  // Not used by V8.
1524   }
1525 }
1526 
DecodeVCVTBetweenDoubleAndSingle(Instruction * instr)1527 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
1528   VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1529   VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
1530 
1531   bool double_to_single = (instr->SzValue() == 1);
1532 
1533   if (double_to_single) {
1534     Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
1535   } else {
1536     Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
1537   }
1538 }
1539 
DecodeVCVTBetweenFloatingPointAndInteger(Instruction * instr)1540 void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
1541   VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1542   VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
1543          (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
1544 
1545   bool to_integer = (instr->Bit(18) == 1);
1546   bool dp_operation = (instr->SzValue() == 1);
1547   if (to_integer) {
1548     bool unsigned_integer = (instr->Bit(16) == 0);
1549 
1550     if (dp_operation) {
1551       if (unsigned_integer) {
1552         Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
1553       } else {
1554         Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
1555       }
1556     } else {
1557       if (unsigned_integer) {
1558         Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
1559       } else {
1560         Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
1561       }
1562     }
1563   } else {
1564     bool unsigned_integer = (instr->Bit(7) == 0);
1565 
1566     if (dp_operation) {
1567       if (unsigned_integer) {
1568         Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
1569       } else {
1570         Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
1571       }
1572     } else {
1573       if (unsigned_integer) {
1574         Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
1575       } else {
1576         Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
1577       }
1578     }
1579   }
1580 }
1581 
1582 // Decode Type 6 coprocessor instructions.
1583 // Dm = vmov(Rt, Rt2)
1584 // <Rt, Rt2> = vmov(Dm)
1585 // Ddst = MEM(Rbase + 4*offset).
1586 // MEM(Rbase + 4*offset) = Dsrc.
DecodeType6CoprocessorIns(Instruction * instr)1587 void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
1588   VERIFY(instr->TypeValue() == 6);
1589 
1590   if (instr->CoprocessorValue() == 0xA) {
1591     switch (instr->OpcodeValue()) {
1592       case 0x8:
1593       case 0xA:
1594         if (instr->HasL()) {
1595           Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1596         } else {
1597           Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1598         }
1599         break;
1600       case 0xC:
1601       case 0xE:
1602         if (instr->HasL()) {
1603           Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1604         } else {
1605           Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1606         }
1607         break;
1608       case 0x4:
1609       case 0x5:
1610       case 0x6:
1611       case 0x7:
1612       case 0x9:
1613       case 0xB: {
1614         bool to_vfp_register = (instr->VLValue() == 0x1);
1615         if (to_vfp_register) {
1616           Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
1617         } else {
1618           Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
1619         }
1620         break;
1621       }
1622       default:
1623         Unknown(instr);  // Not used by V8.
1624     }
1625   } else if (instr->CoprocessorValue() == 0xB) {
1626     switch (instr->OpcodeValue()) {
1627       case 0x2:
1628         // Load and store double to two GP registers
1629         if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
1630           Unknown(instr);  // Not used by V8.
1631         } else if (instr->HasL()) {
1632           Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1633         } else {
1634           Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1635         }
1636         break;
1637       case 0x8:
1638       case 0xA:
1639         if (instr->HasL()) {
1640           Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1641         } else {
1642           Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1643         }
1644         break;
1645       case 0xC:
1646       case 0xE:
1647         if (instr->HasL()) {
1648           Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1649         } else {
1650           Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1651         }
1652         break;
1653       case 0x4:
1654       case 0x5:
1655       case 0x6:
1656       case 0x7:
1657       case 0x9:
1658       case 0xB: {
1659         bool to_vfp_register = (instr->VLValue() == 0x1);
1660         if (to_vfp_register) {
1661           Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
1662         } else {
1663           Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
1664         }
1665         break;
1666       }
1667       default:
1668         Unknown(instr);  // Not used by V8.
1669     }
1670   } else {
1671     Unknown(instr);  // Not used by V8.
1672   }
1673 }
1674 
DecodeSpecialCondition(Instruction * instr)1675 void Decoder::DecodeSpecialCondition(Instruction* instr) {
1676   switch (instr->SpecialValue()) {
1677     case 5:
1678       if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
1679           (instr->Bit(4) == 1)) {
1680         // vmovl signed
1681         if ((instr->VdValue() & 1) != 0) Unknown(instr);
1682         int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
1683         int Vm = (instr->Bit(5) << 4) | instr->VmValue();
1684         int imm3 = instr->Bits(21, 19);
1685         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1686                                     "vmovl.s%d q%d, d%d", imm3 * 8, Vd, Vm);
1687       } else {
1688         Unknown(instr);
1689       }
1690       break;
1691     case 7:
1692       if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
1693           (instr->Bit(4) == 1)) {
1694         // vmovl unsigned
1695         if ((instr->VdValue() & 1) != 0) Unknown(instr);
1696         int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
1697         int Vm = (instr->Bit(5) << 4) | instr->VmValue();
1698         int imm3 = instr->Bits(21, 19);
1699         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1700                                     "vmovl.u%d q%d, d%d", imm3 * 8, Vd, Vm);
1701       } else {
1702         Unknown(instr);
1703       }
1704       break;
1705     case 8:
1706       if (instr->Bits(21, 20) == 0) {
1707         // vst1
1708         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1709         int Rn = instr->VnValue();
1710         int type = instr->Bits(11, 8);
1711         int size = instr->Bits(7, 6);
1712         int align = instr->Bits(5, 4);
1713         int Rm = instr->VmValue();
1714         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vst1.%d ",
1715                                     (1 << size) << 3);
1716         FormatNeonList(Vd, type);
1717         Print(", ");
1718         FormatNeonMemory(Rn, align, Rm);
1719       } else if (instr->Bits(21, 20) == 2) {
1720         // vld1
1721         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1722         int Rn = instr->VnValue();
1723         int type = instr->Bits(11, 8);
1724         int size = instr->Bits(7, 6);
1725         int align = instr->Bits(5, 4);
1726         int Rm = instr->VmValue();
1727         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vld1.%d ",
1728                                     (1 << size) << 3);
1729         FormatNeonList(Vd, type);
1730         Print(", ");
1731         FormatNeonMemory(Rn, align, Rm);
1732       } else {
1733         Unknown(instr);
1734       }
1735       break;
1736     case 9:
1737       if (instr->Bits(21, 20) == 0 && instr->Bits(9, 8) == 0) {
1738         // vst1
1739         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1740         int Rn = instr->VnValue();
1741         int size = instr->Bits(11, 10);
1742         int index = instr->Bits(7, 5);
1743         int align = instr->Bit(4);
1744         int Rm = instr->VmValue();
1745         out_buffer_pos_ +=
1746             SNPrintF(out_buffer_ + out_buffer_pos_, "vst1.%d {d%d[%d]}, ",
1747                      (1 << size) << 3, Vd, index);
1748         FormatNeonMemory(Rn, align, Rm);
1749       } else if (instr->Bits(21, 20) == 2 && instr->Bits(9, 8) == 0) {
1750         // vld1
1751         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1752         int Rn = instr->VnValue();
1753         int size = instr->Bits(11, 10);
1754         int index = instr->Bits(7, 5);
1755         int align = instr->Bit(4);
1756         int Rm = instr->VmValue();
1757         out_buffer_pos_ +=
1758             SNPrintF(out_buffer_ + out_buffer_pos_, "vld1.%d {d%d[%d]}, ",
1759                      (1 << size) << 3, Vd, index);
1760         FormatNeonMemory(Rn, align, Rm);
1761       } else {
1762         Unknown(instr);
1763       }
1764       break;
1765     case 0xA:
1766       if (instr->Bits(22, 20) == 7) {
1767         const char* option = "?";
1768         switch (instr->Bits(3, 0)) {
1769           case 2:
1770             option = "oshst";
1771             break;
1772           case 3:
1773             option = "osh";
1774             break;
1775           case 6:
1776             option = "nshst";
1777             break;
1778           case 7:
1779             option = "nsh";
1780             break;
1781           case 10:
1782             option = "ishst";
1783             break;
1784           case 11:
1785             option = "ish";
1786             break;
1787           case 14:
1788             option = "st";
1789             break;
1790           case 15:
1791             option = "sy";
1792             break;
1793         }
1794         switch (instr->Bits(7, 4)) {
1795           case 1:
1796             Print("clrex");
1797             break;
1798           case 4:
1799             out_buffer_pos_ +=
1800                 SNPrintF(out_buffer_ + out_buffer_pos_, "dsb %s", option);
1801             break;
1802           case 5:
1803             out_buffer_pos_ +=
1804                 SNPrintF(out_buffer_ + out_buffer_pos_, "dmb %s", option);
1805             break;
1806           default:
1807             Unknown(instr);
1808         }
1809         break;
1810       }
1811       [[fallthrough]];
1812     case 0xB:
1813       if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
1814         int Rn = instr->Bits(19, 16);
1815         int offset = instr->Bits(11, 0);
1816         if (offset == 0) {
1817           out_buffer_pos_ +=
1818               SNPrintF(out_buffer_ + out_buffer_pos_, "pld [r%d]", Rn);
1819         } else if (instr->Bit(23) == 0) {
1820           out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1821                                       "pld [r%d, #-%d]", Rn, offset);
1822         } else {
1823           out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1824                                       "pld [r%d, #+%d]", Rn, offset);
1825         }
1826       } else {
1827         Unknown(instr);
1828       }
1829       break;
1830     case 0x1D:
1831       if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 &&
1832           instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 &&
1833           instr->Bit(4) == 0x0) {
1834         // VRINTA, VRINTN, VRINTP, VRINTM (floating-point)
1835         bool dp_operation = (instr->SzValue() == 1);
1836         int rounding_mode = instr->Bits(17, 16);
1837         switch (rounding_mode) {
1838           case 0x0:
1839             if (dp_operation) {
1840               Format(instr, "vrinta.f64.f64 'Dd, 'Dm");
1841             } else {
1842               Unknown(instr);
1843             }
1844             break;
1845           case 0x1:
1846             if (dp_operation) {
1847               Format(instr, "vrintn.f64.f64 'Dd, 'Dm");
1848             } else {
1849               Unknown(instr);
1850             }
1851             break;
1852           case 0x2:
1853             if (dp_operation) {
1854               Format(instr, "vrintp.f64.f64 'Dd, 'Dm");
1855             } else {
1856               Unknown(instr);
1857             }
1858             break;
1859           case 0x3:
1860             if (dp_operation) {
1861               Format(instr, "vrintm.f64.f64 'Dd, 'Dm");
1862             } else {
1863               Unknown(instr);
1864             }
1865             break;
1866           default:
1867             MOZ_CRASH();  // Case analysis is exhaustive.
1868             break;
1869         }
1870       } else {
1871         Unknown(instr);
1872       }
1873       break;
1874     default:
1875       Unknown(instr);
1876       break;
1877   }
1878 }
1879 
1880 #  undef VERIFIY
1881 
IsConstantPoolAt(uint8_t * instr_ptr)1882 bool Decoder::IsConstantPoolAt(uint8_t* instr_ptr) {
1883   int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1884   return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
1885 }
1886 
ConstantPoolSizeAt(uint8_t * instr_ptr)1887 int Decoder::ConstantPoolSizeAt(uint8_t* instr_ptr) {
1888   if (IsConstantPoolAt(instr_ptr)) {
1889     int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1890     return DecodeConstantPoolLength(instruction_bits);
1891   } else {
1892     return -1;
1893   }
1894 }
1895 
1896 // Disassemble the instruction at *instr_ptr into the output buffer.
InstructionDecode(uint8_t * instr_ptr)1897 int Decoder::InstructionDecode(uint8_t* instr_ptr) {
1898   Instruction* instr = Instruction::At(instr_ptr);
1899   // Print raw instruction bytes.
1900   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x       ",
1901                               instr->InstructionBits());
1902   if (instr->ConditionField() == kSpecialCondition) {
1903     DecodeSpecialCondition(instr);
1904     return Instruction::kInstrSize;
1905   }
1906   int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1907   if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
1908     out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1909                                 "constant pool begin (length %d)",
1910                                 DecodeConstantPoolLength(instruction_bits));
1911     return Instruction::kInstrSize;
1912   } else if (instruction_bits == kCodeAgeJumpInstruction) {
1913     // The code age prologue has a constant immediatly following the jump
1914     // instruction.
1915     Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize);
1916     DecodeType2(instr);
1917     SNPrintF(out_buffer_ + out_buffer_pos_, " (0x%08x)",
1918              target->InstructionBits());
1919     return 2 * Instruction::kInstrSize;
1920   }
1921   switch (instr->TypeValue()) {
1922     case 0:
1923     case 1: {
1924       DecodeType01(instr);
1925       break;
1926     }
1927     case 2: {
1928       DecodeType2(instr);
1929       break;
1930     }
1931     case 3: {
1932       DecodeType3(instr);
1933       break;
1934     }
1935     case 4: {
1936       DecodeType4(instr);
1937       break;
1938     }
1939     case 5: {
1940       DecodeType5(instr);
1941       break;
1942     }
1943     case 6: {
1944       DecodeType6(instr);
1945       break;
1946     }
1947     case 7: {
1948       return DecodeType7(instr);
1949     }
1950     default: {
1951       // The type field is 3-bits in the ARM encoding.
1952       MOZ_CRASH();
1953       break;
1954     }
1955   }
1956   return Instruction::kInstrSize;
1957 }
1958 
1959 }  // namespace disasm
1960 
1961 #  undef STRING_STARTS_WITH
1962 #  undef VERIFY
1963 
1964 //------------------------------------------------------------------------------
1965 
1966 namespace disasm {
1967 
NameOfAddress(uint8_t * addr) const1968 const char* NameConverter::NameOfAddress(uint8_t* addr) const {
1969   SNPrintF(tmp_buffer_, "%p", addr);
1970   return tmp_buffer_.start();
1971 }
1972 
NameOfConstant(uint8_t * addr) const1973 const char* NameConverter::NameOfConstant(uint8_t* addr) const {
1974   return NameOfAddress(addr);
1975 }
1976 
NameOfCPURegister(int reg) const1977 const char* NameConverter::NameOfCPURegister(int reg) const {
1978   return disasm::Registers::Name(reg);
1979 }
1980 
NameOfByteCPURegister(int reg) const1981 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1982   MOZ_CRASH();  // ARM does not have the concept of a byte register
1983   return "nobytereg";
1984 }
1985 
NameOfXMMRegister(int reg) const1986 const char* NameConverter::NameOfXMMRegister(int reg) const {
1987   MOZ_CRASH();  // ARM does not have any XMM registers
1988   return "noxmmreg";
1989 }
1990 
NameInCode(uint8_t * addr) const1991 const char* NameConverter::NameInCode(uint8_t* addr) const {
1992   // The default name converter is called for unknown code. So we will not try
1993   // to access any memory.
1994   return "";
1995 }
1996 
1997 //------------------------------------------------------------------------------
1998 
Disassembler(const NameConverter & converter)1999 Disassembler::Disassembler(const NameConverter& converter)
2000     : converter_(converter) {}
2001 
~Disassembler()2002 Disassembler::~Disassembler() {}
2003 
InstructionDecode(V8Vector<char> buffer,uint8_t * instruction)2004 int Disassembler::InstructionDecode(V8Vector<char> buffer,
2005                                     uint8_t* instruction) {
2006   Decoder d(converter_, buffer);
2007   return d.InstructionDecode(instruction);
2008 }
2009 
ConstantPoolSizeAt(uint8_t * instruction)2010 int Disassembler::ConstantPoolSizeAt(uint8_t* instruction) {
2011   return Decoder::ConstantPoolSizeAt(instruction);
2012 }
2013 
Disassemble(FILE * f,uint8_t * begin,uint8_t * end)2014 void Disassembler::Disassemble(FILE* f, uint8_t* begin, uint8_t* end) {
2015   NameConverter converter;
2016   Disassembler d(converter);
2017   for (uint8_t* pc = begin; pc < end;) {
2018     EmbeddedVector<char, ReasonableBufferSize> buffer;
2019     buffer[0] = '\0';
2020     uint8_t* prev_pc = pc;
2021     pc += d.InstructionDecode(buffer, pc);
2022     fprintf(f, "%p    %08x      %s\n", prev_pc,
2023             *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
2024   }
2025 }
2026 
2027 }  // namespace disasm
2028 }  // namespace jit
2029 }  // namespace js
2030 
2031 #endif  // JS_DISASM_ARM
2032