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